当前位置: 首页 > news >正文

东莞网站推广及优化平台营销策略

东莞网站推广及优化,平台营销策略,培训公司,大连微信网站制作目录OpenGL工作原理设置OpenGL和在C中创建一个窗口在C中使用现代OpenGL顶点缓冲区和在现代OpenGL中画一个三角形在OpenGL中顶点的属性和布局着色器在OpenGL中着色器的原理在OpenGL中写一个着色器在OpenGL中我是如何处理着色器的在OpenGL中的索引缓冲区在OpenGL中处理错误OpenGL…

目录

  • OpenGL工作原理
  • 设置OpenGL和在C++中创建一个窗口
  • 在C++中使用现代OpenGL
  • 顶点缓冲区和在现代OpenGL中画一个三角形
  • 在OpenGL中顶点的属性和布局
  • 着色器
    • 在OpenGL中着色器的原理
    • 在OpenGL中写一个着色器
    • 在OpenGL中我是如何处理着色器的
  • 在OpenGL中的索引缓冲区
  • 在OpenGL中处理错误
  • OpenGL中的统一变量(uniforms)
  • OpenGL中的顶点数组
  • 抽象顶点索引缓冲区成类
  • OpenGL中的缓冲区和布局的抽象
  • 在OpenGL中抽象着色器
  • 在OpenGL中写一个基础的渲染器类
  • 在OpenGL中的纹理
  • 在OpenGL中的混合

OpenGL工作原理

  • OpenGL工作原理:我们为显卡提供数据,在显卡上存储一些内存,它包含了我们想要绘制的所有数据。然后使用一个着色器,一个在显卡上执行的程序来读取数据,并且完全显示在屏幕上。
  • 通常我们画几何图形的方式就是使用一个顶点缓冲区,这基本上是存储在显卡上的内存缓冲区。所以,当对着着色器编程时,实际上是从读取顶点缓冲区开始的,它需要知道缓冲区的布局。这个缓冲区实际上包含的就是一堆浮点数,它们指定了每个顶点的位置,也有纹理坐标,法线等。所以我们需要告诉GPU,内存中是什么,是如何布局的。
  • 从着色器的角度来说,你也需要匹配你在CPU端的布局。

设置OpenGL和在C++中创建一个窗口

网站 :docs.GL

#include <GLFW/glfw3.h>int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);glBegin(GL_TRIANGLES);glVertex2f(-0.5f, -0.5f);glVertex2f(0.0f, 0.5f);glVertex2f(0.5f, -0.5f);glEnd();/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

在这里插入图片描述

在C++中使用现代OpenGL

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);glBegin(GL_TRIANGLES);glVertex2f(-0.5f, -0.5f);glVertex2f(0.0f, 0.5f);glVertex2f(0.5f, -0.5f);glEnd();/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

顶点缓冲区和在现代OpenGL中画一个三角形

  • 顶点缓冲区 : OpenGL中的内存缓冲区,它实际上是在显卡上,在VRAM(显存)中,Video RAM。
  • 顶点缓冲区的家在显存(VRAM) 中。但它是由CPU在系统内存(RAM) 中“生”出来,然后通过“快递”(PCIe总线)送过去的。而CPU/GPU缓存就像是“临时工作台”,数据在被处理时才会放在上面。
  • 着色器 : 着色器是一个运行在显卡上的程序,是我们可以编写的可以在显卡上运行的代码,它可以在显存上以一种非常特殊又非常强大的方式运行。
  • 状态机(state machine): OpenGL的本质是状态机,不同于函数调用,它已经知道了状态的所有可能。
  • OpenGL工作原理:创建顶点缓冲区(包含顶点数据,放入一个缓冲区,传到OpenGL的VRAM),然后发出一个 DrawCall 指令,让GPU根据缓冲区画出图形。
  • 唯一标识符 : 在OpenGL中生成的所有东西都会被分配一个唯一标识符——整数,不管是顶点缓冲区,顶点数组,纹理,着色器或其他。0通常是一种无效状态,但不都是。
  • glBufferData usage属性:
    • STREAM:它被修改一次,并且只能使用几次
    • STATIC:数据存储内容将被修改一次,并且可以使用多次
    • DYNAMIC: 数据存储的内容会被反复修改,并且多次使用
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}float positions[6] = {-0.5f, -0.5f,0.0f,  0.5f,0.5f, -0.5f};// create vertex bufferunsigned int buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions),positions,GL_STATIC_DRAW);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);glDrawArrays(GL_TRIANGLES, 0, 3);/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

在OpenGL中顶点的属性和布局

  • glVertexAttribPointer
parametermeaningaddition
index需要再次修改的共享信息顶点属性(位置、颜色、纹理坐标、法线等)的索引着色器读取所有这些的方式就是通过索引, 它是缓冲区中实际属性的索引
size计数只能是1,2,3,4,它是提供的浮点数的数量
type数据类型
normalized标准化假设我们要指定一个字节在0255之间,它需要被规范化到0-1之间,在我们实际着色器中作为浮点数
stride连续通用顶点属性之间的字节偏移量每个顶点之间的字节数
pointer指向实际属性的指针int类型
  • glEnableVertexAttribArray(int pointer):启动pointer号指针
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}float positions[6] = {-0.5f, -0.5f,0.0f,  0.5f,0.5f, -0.5f};// create vertex bufferunsigned int buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions),positions,GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);glBindBuffer(GL_ARRAY_BUFFER, 0);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);glDrawArrays(GL_TRIANGLES, 0, 3);/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

着色器

在OpenGL中着色器的原理

  • 着色器:它是我们可以在计算机上以文本/字符串形式编写的代码,然后给OpenGL,就可以把它发送到显卡上,像编译链接运行其他程序一样编译、链接和运行。
  • 着色器的本质:对GPU编程,告诉GPU如何处理我们发送的数据。
  • 分类:顶点着色器(vertex shaders)和片段着色器(fragment shaders,像素着色器pixel shaders)等
  • 着色器运行过程:顶点着色器和片段着色器是顺着管道的两种不同的着色器类型。当我们真正发出DrawCall指令时,顶点着色器会被调用,然后片段着色器会被调用,然后我们会在屏幕上看到结果。
  • 顶点着色器:尝试渲染每个顶点调用,每个顶点会调用一次顶点着色器。顶点着色器主要决定顶点在什么位置。
  • 片段着色器:会为每个需要光栅化的像素运行一次。光栅化实际上是画在屏幕上的,类似于给区域填色。它会对需要填充的每个像素调用一次,主要决定这个像素是什么颜色。

在OpenGL中写一个着色器

#version 330 core
//means we’re going to use GLSL

在OpenGL中我是如何处理着色器的

  • "Basic.shader“
#shader vertex
#version 330 corelayout(location = 0) in vec4 position;    void main()
{gl_Position = position;
};#shader fragment
#version 330 core //means we're going to use GLSLlayout(location = 0) out vec4 color;    void main()
{color = vec4(1.0, 0.0, 0.0, 1.0);
};
  • “Application.cpp"
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>struct ShaderProgramSource {std::string VertexSource;std::string FragmentSource;
};static ShaderProgramSource ParseShader(const std::string& filepath) {std::ifstream stream(filepath);enum class ShaderType {NONE = -1,VERTEX = 0,FRAGMENT = 1};std::string line;std::stringstream ss[2];ShaderType type = ShaderType::NONE;while (getline(stream, line)) {if (line.find("# shader") != std::string::npos) {if (line.find("vertex") != std::string::npos) {// set mode to vertextype = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos) {// set mode to fragmenttype = ShaderType::FRAGMENT;}}else {ss[(int)type] << line << '\n';}}return { ss[0].str(), ss[1].str() };
}static unsigned int CompileShader(unsigned int type, const std::string& source) {unsigned int id = glCreateShader(type);// 因为OpenGL是C库,需要以NULL结尾的char数组const char* src = source.c_str(); //&source[0]glShaderSource(id, 1, &src, nullptr);glCompileShader(id);// TODO : Error handingint result;glGetShaderiv(id, GL_COMPILE_STATUS, &result);if (result == GL_FALSE) {int length;glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);char* message = (char*)alloca(length * sizeof(char)); // alloca allocate on stack dynamicallyglGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment")<< "shader !" << std::endl << message << std::endl;glDeleteShader(id);return 0;}return id;
}static int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {// create a programunsigned int program = glCreateProgram();// create vertex shader & fragment shaderunsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);// link the shaders to one program to useglAttachShader(program, vs);glAttachShader(program, fs);glLinkProgram(program);glValidateProgram(program);// delete the intermediates because the shaders have already been linked into a programglDeleteShader(vs);glDeleteShader(fs);return program;
}int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}float positions[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,  0.5f,-0.5f,  0.5f,};unsigned int indices[] = {0, 1, 2,2, 3, 0};// create vertex bufferunsigned int buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);// glBindBuffer(GL_ARRAY_BUFFER, 0);// create index bufferunsigned int ibo;   // index buffer objectglGenBuffers(1, &ibo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;unsigned int shader = CreateShader(vertexShader, fragmentShader);glUseProgram(shader);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);// glDrawArrays(GL_TRIANGLES, 0, 6);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

在OpenGL中的索引缓冲区

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>struct ShaderProgramSource {std::string VertexSource;std::string FragmentSource;
};static ShaderProgramSource ParseShader(const std::string& filepath) {std::ifstream stream(filepath);enum class ShaderType {NONE = -1,VERTEX = 0,FRAGMENT = 1};std::string line;std::stringstream ss[2];ShaderType type = ShaderType::NONE;while (getline(stream, line)) {if (line.find("# shader") != std::string::npos) {if (line.find("vertex") != std::string::npos) {// set mode to vertextype = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos) {// set mode to fragmenttype = ShaderType::FRAGMENT;}}else {ss[(int)type] << line << '\n';}}return { ss[0].str(), ss[1].str() };
}static unsigned int CompileShader(unsigned int type, const std::string& source) {unsigned int id = glCreateShader(type);// 因为OpenGL是C库,需要以NULL结尾的char数组const char* src = source.c_str(); //&source[0]glShaderSource(id, 1, &src, nullptr);glCompileShader(id);// TODO : Error handingint result;glGetShaderiv(id, GL_COMPILE_STATUS, &result);if (result == GL_FALSE) {int length;glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);char* message = (char*)alloca(length * sizeof(char)); // alloca allocate on stack dynamicallyglGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment")<< "shader !" << std::endl << message << std::endl;glDeleteShader(id);return 0;}return id;
}static int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {// create a programunsigned int program = glCreateProgram();// create vertex shader & fragment shaderunsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);// link the shaders to one program to useglAttachShader(program, vs);glAttachShader(program, fs);glLinkProgram(program);glValidateProgram(program);// delete the intermediates because the shaders have already been linked into a programglDeleteShader(vs);glDeleteShader(fs);return program;
}int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}float positions[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,  0.5f,-0.5f,  0.5f,};unsigned int indices[] = {0, 1, 2,2, 3, 0};// create vertex bufferunsigned int buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);// glBindBuffer(GL_ARRAY_BUFFER, 0);// create index bufferunsigned int ibo;   // index buffer objectglGenBuffers(1, &ibo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;unsigned int shader = CreateShader(vertexShader, fragmentShader);glUseProgram(shader);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);// glDrawArrays(GL_TRIANGLES, 0, 6);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

在OpenGL中处理错误

  • glGetError
  • glDebugMessageCallback
  • 步骤:先清除其他error,再在可能出bug的语句下面输出error。
static void GLClearError() {while (!glGetError());
}static void GLCheckError() {while (GLenum error = glGetError()) {std::cout << "[OpenGL Error](" << error << ")" << std::endl;}
}
    /* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);// glDrawArrays(GL_TRIANGLES, 0, 6);GLClearError();// glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);glDrawElements(GL_TRIANGLES, 6, GL_INT, nullptr); //errorGLCheckError();/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}
  • 使用 assert 和 宏
//__表示它是编译器本身的函数(MSVC特有的,在gcc等其他编译器上无效
#define ASSERT(x) if (!x) __debugbreak();   
// #表示将其转换为字符串
#define GLCall(x) GLClearError();\x;\ASSERT(GLLogCall(#x, __FILE__, __LINE__));static void GLClearError() {while (!glGetError());
}static bool GLLogCall(const char* function, const char* file, int line) {while (GLenum error = glGetError()) {std::cout << "[OpenGL Error](" << error << "): " <<function << " " << file << ":" << line << std::endl;return false;}return true;
}
GLCall(glDrawElements(GL_TRIANGLES, 6, GL_INT, nullptr));

OpenGL中的统一变量(uniforms)

  • 统一变量:一种实际上从CPU端获取数据到显存方式
  • 属性和统一变量是两种获取从CPU到显卡绘制的对象数据的两种主要方式
  • glUniformnm:n 表示几个数字,m 表示数字的类型。例如glUniform4f
  • 步骤:
    • 通过实际的着色器 id 编写 glUseProgram 来绑定着色器,获取这个实际颜色变量的位置。得到这个位置时,用这个位置整数和值调用 glUniform,这样就可以在着色器中设置我的数据。
    • 而在着色器中,所作的是通过输入 uniform 关键字以及类型和名称来创建统一变量,就像创建其他变量一样,只是实际我是用统一变量来写输出颜色。如果一切顺利,我应该将这个颜色值写入我的实际输出颜色。
  • “Basic.shader”
#shader vertex
#version 330 corelayout(location = 0) in vec4 position;    void main()
{gl_Position = position;
};#shader fragment
#version 330 core layout(location = 0) out vec4 color;    uniform vec4 u_Color;void main()
{color = u_Color;
};
  • “Application.cpp”
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>//__表示它是编译器本身的函数(MSVC特有的,在gcc等其他编译器上无效
#define ASSERT(x) if (!x) __debugbreak();
// #表示将其转换为字符串
#define GLCall(x) GLClearError();\x;\ASSERT(GLLogCall(#x, __FILE__, __LINE__))static void GLClearError() {while (!glGetError());
}static bool GLLogCall(const char* function, const char* file, int line) {while (GLenum error = glGetError()) {std::cout << "[OpenGL Error](" << error << "): " <<function << " " << file << ":" << line << std::endl;return false;}return true;
}struct ShaderProgramSource {std::string VertexSource;std::string FragmentSource;
};static ShaderProgramSource ParseShader(const std::string& filepath) {std::ifstream stream(filepath);enum class ShaderType {NONE = -1,VERTEX = 0,FRAGMENT = 1};std::string line;std::stringstream ss[2];ShaderType type = ShaderType::NONE;while (getline(stream, line)) {if (line.find("#shader") != std::string::npos) {if (line.find("vertex") != std::string::npos) {// set mode to vertextype = ShaderType::VERTEX;}else if (line.find("fragment") != std::string::npos) {// set mode to fragmenttype = ShaderType::FRAGMENT;}}else {ss[(int)type] << line << '\n';}}return { ss[0].str(), ss[1].str() };
}static unsigned int CompileShader(unsigned int type, const std::string& source) {unsigned int id = glCreateShader(type);// 因为OpenGL是C库,需要以NULL结尾的char数组const char* src = source.c_str(); //&source[0]glShaderSource(id, 1, &src, nullptr);glCompileShader(id);// TODO : Error handingint result;glGetShaderiv(id, GL_COMPILE_STATUS, &result);if (result == GL_FALSE) {int length;glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);char* message = (char*)alloca(length * sizeof(char)); // alloca allocate on stack dynamicallyglGetShaderInfoLog(id, length, &length, message);std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment")<< "shader !" << std::endl << message << std::endl;glDeleteShader(id);return 0;}return id;
}static int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {// create a programunsigned int program = glCreateProgram();// create vertex shader & fragment shaderunsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);// link the shaders to one program to useglAttachShader(program, vs);glAttachShader(program, fs);glLinkProgram(program);glValidateProgram(program);// delete the intermediates because the shaders have already been linked into a programglDeleteShader(vs);glDeleteShader(fs);return program;
}int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);glfwSwapInterval(1);if (glewInit() != GLEW_OK) {std::cout << "Error!" << std::endl;}float positions[] = {-0.5f, -0.5f,0.5f, -0.5f,0.5f,  0.5f,-0.5f,  0.5f,};unsigned int indices[] = {0, 1, 2,2, 3, 0};// create vertex bufferunsigned int buffer;glGenBuffers(1, &buffer);glBindBuffer(GL_ARRAY_BUFFER, buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);// glBindBuffer(GL_ARRAY_BUFFER, 0);// create index bufferunsigned int ibo;   // index buffer objectglGenBuffers(1, &ibo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");std::string vertexShader = source.VertexSource;std::string fragmentShader = source.FragmentSource;unsigned int shader = CreateShader(vertexShader, fragmentShader);glUseProgram(shader);   //在这一步必须有一个实际绑定的着色器int location = glGetUniformLocation(shader, "u_Color");ASSERT(location != -1);glUniform4f(location, 0.8f, 0.3f, 0.8f, 1.0f);  //将代码从着色器移到了C++中float r = 0.0f;float increment = 0.05f;/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){/* Render here */glClear(GL_COLOR_BUFFER_BIT);// glDrawArrays(GL_TRIANGLES, 0, 6);glUniform4f(location, r, 0.3f, 0.8f, 1.0f);GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));//GLCall(glDrawElements(GL_TRIANGLES, 6, GL_INT, nullptr));if (r > 1.0f) {increment = -0.05f;}else if (r < 0.0f){increment = 0.05f;}r += increment;/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}

OpenGL中的顶点数组

抽象顶点索引缓冲区成类

OpenGL中的缓冲区和布局的抽象

在OpenGL中抽象着色器

在OpenGL中写一个基础的渲染器类

在OpenGL中的纹理

在OpenGL中的混合

http://www.dtcms.com/a/495578.html

相关文章:

  • exp4j并发解决
  • 学习博弈本身过程脑是怎么看的?
  • 风险感知中枢:监测预警系统的架构与核心
  • 使用ROS2 + Qt编写一个简易计算器
  • 校园资料分享平台|基于SpringBoot和Vue的校园资料分享平台(源码+数据库+文档)
  • 企业花钱做的网站出现违禁词本地wordpress 手机浏览器
  • 网站建设最基础是什么广东网站建设服务商
  • 如何模仿一个网站云手机免费版无限挂机
  • Vue2 + Office Add-in关于用vue项目于加载项控制excel单元格内容(Demo版)
  • TS在Vue3中的使用实例集合
  • 储能技术适配绿电直连场景深度对比
  • React + Ant Design 日期选择器避免显示“Invalid Date“的解决方案
  • Vue 3 多实例 + 缓存复用:理念及实践
  • 手机网站自适应布局怎么做wordpress背景图片下载
  • Java基础——面向对象进阶复习知识点3
  • wordpress资讯站模板网站建设 智能建站
  • NoSQL介绍
  • 【实时Linux实战系列】FPGA 与实时 Linux 的协同设计
  • 可以做翻译兼职的网站wordpress icp链接
  • 【系统分析师】高分论文:数据库集群技术及应用
  • 西安知名高端网站建设服务企业郑州做系统集成的公司网站
  • 基于Matlab实现双目图计算深度图
  • sysctl -w net.ipv4.ip_forward=1 是一个Linux系统命令,用于开启IP转发功能
  • 信息检索4
  • 简述建设电子商务网站步骤苏州住房与城乡建设网站
  • 437路径总和III(dfs+前缀和)
  • 国内直连 Cursor:Remote SSH 无配置设置教程
  • Claude Code 使用手册
  • 网站开发需求书模板接软件开发项目的平台
  • 【源码深度 第1篇】LinkedList:双向链表的设计与实现