目录
操作非常灵活

vertexShader.glsl
- #version 330 core
- layout (location = 0) in vec3 aPos;//由C++代码中VBO绑定的锚定点输入。
-
- out vec4 vertexColor;
-
- void main()
- {
- gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
- vertexColor=vec4(0.5,0.0,0.0,1.0);
- };
fragmentShader.glsl
- #version 330 core
- out vec4 FragColor;
-
- in vec4 vertexColor;
-
- void main()
- {
- //FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
- FragColor = vertexColor;
- };
vertexShader中的aPos,由
- //对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
进行读入;
随后vertexShader输出一个vertexColor传入下一个阶段,也就是fragmentShader。
fragmentShader接受vertexShader的输入(vertexColor),同时再输出一个FragColor。
直接上代码,注意需要把glUserProgram放在前面,启用shaderProblem这个状态
- //渲染
- void render() {
- glUseProgram(shaderProgram);
- float _time = glfwGetTime();
- float _green = sin(_time) * 0.5f + 0.5f;
- int _location = glGetUniformLocation(shaderProgram, "ourColor");
- glUniform4f(_location, 0.0f, _green, 0.0f, 1.0f);
-
- glBindVertexArray(VAO);
- //以三角形模式绘制,从第0个顶点开始,起作用的有3个点
- glDrawArrays(GL_TRIANGLES, 0, 3);
- glUseProgram(0);
- }
渲染结果:

创建一个新的Shader类,抽象出一些重合度比较高的代码:
Shader.h
- #pragma once
-
- #include "Base.h"
-
- class Shader
- {
- private:
- unsigned int m_shaderProgram;
- public:
- Shader() {
- m_shaderProgram = 0;
- }
- ~Shader() {}
- public:
- void initShader(const char* _vertexPath, const char* _fragPath);
- void start() { glUseProgram(m_shaderProgram); }
- void end() { glUseProgram(0); }
- };
-
然后把之前的代码copy进initShader即可。
另外将一些常用的头文件集成到Base.h中:
- //Base.h
- #pragma once
- #include
- #include
- #include
- #include
- #include
- #include
我们在vertices中为三个顶点新添加颜色信息:
- float vertices[] = {
- //顶点信息 颜色信息
- -0.5f, -0.5f, 0.0f, 1.0f,0.0f,0.0f,
- 0.5f, -0.5f, 0.0f, 0.0f,1.0f,0.0f,
- 0.0f, 0.5f, 0.0f, 0.0f,0.0f,1.0f
- };
同时,添加了这些信息之后,我们就需要为它们新分配一个layout,并且激活这个layout:
这里注意步长变更为6个float,同时颜色的开始地址为第三个float处。
- //对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float)*3));
-
- //打开锚点:激活
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
之后,我们既然已经分配了layout=1的GPU空间,并令他为颜色的信息,那么在shader中也应该有所体现,需要读取layout=1处的颜色信息:
- //vertexShader.glsl
- #version 330 core
- layout (location = 0) in vec3 aPos;
- layout (location = 1) in vec3 aColor;
-
- out vec4 outColor;
-
- void main()
- {
- gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
- outColor = vec4(aColor, 1.0f);
- };
并将颜色信息传入到fragmentShader中:
- //fragmentShader.glsl
- #version 330 core
- out vec4 FragColor;
-
- in vec4 outColor;
-
- void main()
- {
- FragColor = outColor;
- };
渲染结果如下:



EBO就是用来存储顶点索引的一块区域。
EBO的创建与绑定
与VAO和VBO一样的流程:
- glGenBuffers(1, &EBO);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
另外需要注意的是render中需要更换绘制函数:
- void render() {
- _shader.start();
- glBindVertexArray(VAO);
- //以三角形模式绘制,从第0个顶点开始,起作用的有3个点
- //glDrawArrays(GL_TRIANGLES, 0, 3);
-
- //以三角形模式绘制,用顶点索引
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
-
- _shader.end();
- }
- #include "Base.h"
- #include "Shader.h"
-
-
- void framebuffer_size_callback(GLFWwindow* window, int width, int height);
- void processInput(GLFWwindow* window);
- void initModel();
- void initShader(const char* _vertexPath, const char* _fragPath);
- void render();
-
- unsigned int VBO = 0;
- unsigned int VAO = 0;
- unsigned int EBO = 0;
-
- Shader _shader;
-
- int main() {
- //初始化OpenGL上下文环境,OpenGL是一个状态机,会保存当前状态下的渲染状态以及管线的状态
- glfwInit();
- //,3版本以上
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- //用OpenGL核心开发模式
- glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
-
- //创建窗体
- GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGl Core", nullptr, nullptr);
- if (window == nullptr) {
- std::cout << "Failed to create GLFW window" << std::endl;
- glfwTerminate();
- return -1;
- }
- //把当前上下文绑定至当前窗口
- glfwMakeContextCurrent(window);
-
- //通过glad绑定各种函数指针
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
- std::cout << "Failed to initialize GLAD" << std::endl;
- return -1;
- }
-
- //视口:需要渲染的东西在哪里
- glViewport(0, 0, 800, 600);
- //当Frame大小变动,调用回调函数调整视口大小
- glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
-
- initModel();
- initShader("vertexShader.glsl", "fragmentShader.glsl");
-
- //防止窗口结束退出
- while (!glfwWindowShouldClose(window)) {
- processInput(window);
-
- //擦除画布,用定义的颜色填充
- glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- render();
-
- //双缓冲
- glfwSwapBuffers(window);
- glfwPollEvents();
- }
-
- //结束,释放资源
- glfwTerminate();
- return 0;
-
- }
-
- void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
- glViewport(0, 0, width, height);
- }
-
- void processInput(GLFWwindow* window) {
- if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
- glfwSetWindowShouldClose(window, true);
- }
- }
-
- //渲染
- void render() {
- _shader.start();
- glBindVertexArray(VAO);
- //以三角形模式绘制,从第0个顶点开始,起作用的有3个点
- //glDrawArrays(GL_TRIANGLES, 0, 3);
-
- //以三角形模式绘制,用顶点索引
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
-
- _shader.end();
- }
-
- //构建模型数据:VBO,VAO
- void initModel() {
- float vertices[] = {
- //顶点信息 颜色信息
- 0.5f, 0.5f, 0.0f, 1.0f,0.0f,0.0f,
- 0.5f, -0.5f, 0.0f, 0.0f,1.0f,0.0f,
- -0.5f, -0.5f, 0.0f, 0.0f,0.0f,1.0f,
- -0.5f, 0.5f, 0.0f, 0.0f,1.0f,0.0f
- };
-
- unsigned int indices[] = {
- 0,1,3,
- 1,2,3
- };
-
- glGenVertexArrays(1, &VAO);
- glBindVertexArray(VAO);
-
- //EBO同样要位于VAO的管理之下
- glGenBuffers(1, &EBO);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
-
- //之后的VBO便属于了VAO的管理范围
- glGenBuffers(1, &VBO);
- //绑定哪一种buffer,
- glBindBuffer(GL_ARRAY_BUFFER, VBO);
- //分配显存:分配哪种buffer,分配显存大小,分配地址,使用数据的方式
- glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
-
- //对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(sizeof(float)*3));
-
- //打开锚点:激活
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- //解绑
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- }
-
- //
- void initShader(const char* _vertexPath, const char* _fragPath) {
-
- _shader.initShader(_vertexPath, _fragPath);
- }
渲染结果
