查这段代码的时候:
无意中看到了一个这个链接:
(31条消息) 现代OpenGL学习笔记三:深入理解着色器_不想不努力的菜菜的博客-CSDN博客
里面讲了如何绘制一个彩色的三角形,还演示了index=0,1两种情况下,VBO与shader怎么呼应的,绘制有颜色的图形,很常用,值得学习。
这部分内容,来自上面那个链接。
- 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 // 顶部
- };
- #version 330 core
- layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为 0
- layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
-
- out vec3 ourColor; // 向片段着色器输出一个颜色
-
- void main()
- {
- gl_Position = vec4(aPos, 1.0);
- ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
- }
- #version 330 core
- out vec4 FragColor;
- in vec3 ourColor;
-
- void main()
- {
- FragColor = vec4(ourColor, 1.0);
- }
图画的挺漂亮的:
- // 位置属性
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
- glEnableVertexAttribArray(0);
- // 颜色属性
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
- glEnableVertexAttribArray(1);
明白了,去尝试自己写吧。
作为一个小白,报错是常态,所以,不要有心理负担。
之前做到了这样:
第一次运行,是这样:
改,在这一行里,少了个vec3,少了个;
坏消息是依旧报错,好消息是错少了
这个const float,和这个有关系吗?
实测,没关系……
经过重写对比,发现少了个“,”
这可能不是调试代码,这是比谁的眼更敏感……对我这种小白来说,太难搞了。。
正常了,这个就已经开始有点实用价值了
- /***
- * 例程 绘制三角形 (MAKE后运行时可删除ALL_BUILD,也可以将Task-triangle设为默认启动工程)
- * 步骤:
- * 1-初始化: GLFW窗口,GLAD。
- * 2-数据处理: 给定顶点数据,生成并绑定VAO&VBO(准备在GPU中进行处理),设置顶点属性指针(本质上就是告诉OpenGL如何处理数据)。
- * 3-着色器: 给出顶点和片段着色器,然后链接为着色器程序,渲染时使用着色器程序。
- * 4-渲染: 清空缓冲,绑定纹理,使用着色器程序,绘制三角形,交换缓冲区检查触发事件后释放资源
- */
-
- #include <iostream>
- #include "glad/glad.h"
- #include "GLFW/glfw3.h"
-
- // 三角形的顶点数据
- //const float triangle[] = {
- // // ---- 位置 ----
- // -0.5f, -0.5f, 0.0f, // 左下
- // 0.5f, -0.5f, 0.0f, // 右下
- // 0.0f, 0.5f, 0.0f // 正上
- //};
- //
- //const float triangle2[] = {
- // // ---- 位置 ----
- // 0.6f, -0.5f, 0.0f, // 左下
- // 0.8f, -0.5f, 0.0f, // 右下
- // 0.7f, 0.5f, 0.0f // 正上
- //};
-
- const float triangle[] = {
- // 位置 // 颜色
- 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 // 顶部
- };
-
- const float triangle2[] = {
- // 位置 // 颜色
- 0.6f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下
- 0.8f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下
- 0.7f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部
- };
-
- // 屏幕宽,高
- int screen_width = 1280;
- int screen_height = 720;
-
- int main() {
- // 第一部分,初始化GLFW和GLAD,分为4个步骤进行/
-
- // 初始化GLFW
- glfwInit(); // 初始化GLFW
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL版本为3.3,主次版本号均设为3
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式(无需向后兼容性)
- //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 如果使用的是Mac OS X系统,需加上这行
- glfwWindowHint(GLFW_RESIZABLE, false); // 不可改变窗口大小
-
- // 创建窗口(宽、高、窗口名称)
- auto window = glfwCreateWindow(screen_width, screen_height, "Triangle", nullptr, nullptr);
- if (window == nullptr) { // 如果窗口创建失败,输出Failed to Create OpenGL Context
- std::cout << "Failed to Create OpenGL Context" << std::endl;
- glfwTerminate();
- return -1;
- }
- glfwMakeContextCurrent(window); // 将窗口的上下文设置为当前线程的主上下文
-
- // 初始化GLAD,加载OpenGL函数指针地址的函数
- // 在调用任何OpenGL函数之前
- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
- {
- std::cout << "Failed to initialize GLAD" << std::endl;
- return -1;
- }
-
- // 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
- glViewport(0, 0, screen_width, screen_height);
-
-
-
- // 第二部分,数据处理,通过VAO,VBO,把顶点数据发送到显卡GPU上,并设置属性指针,告诉GPU如何解释这些数据/
-
- // 生成并绑定VAO和VBO
- GLuint vertex_array_object; // == VAO 核心模式要求必须使用VAO
- glGenVertexArrays(1, &vertex_array_object);//先生成
- glBindVertexArray(vertex_array_object);//再绑定
-
- GLuint vertex_buffer_object[2]; // == VBO
- glGenBuffers(2, &vertex_buffer_object[0]);//先生成,相当于C里声明的指针
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);//绑定, 相当于声明指针指向的变量类型,同时设置一下状态机的状态(火车轨道变轨,变完了后面的车都得按变了的轨道走)
- glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW); // 将顶点数据绑定至当前默认的缓冲中
- //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 设置顶点属性指针——告知OpenGL,如何解释这些数据
- //glEnableVertexAttribArray(0);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);//再绑定
- glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2), triangle2, GL_STATIC_DRAW); // 将顶点数据绑定至当前默认的缓冲中,可能是传数据到GPU吧
- //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 设置顶点属性指针——告知OpenGL,如何解释这些数据
- //glEnableVertexAttribArray(0);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);//再绑定
-
- // 解绑VAO和VBO 为了代码更规范
- glBindVertexArray(0);
-
-
- // 第三部分,着色器,用来处理GPU里的数据//
-
- // 顶点着色器和片段着色器源码【GLSL】
- const char* vertex_shader_source =
- "#version 330 core\n"
- "layout (location = 0) in vec3 aPos;\n" // 位置变量的属性位置值为0
- "layout (location = 1) in vec3 aColor; \n " 颜色变量的属性位置值为 1
- "out vec3 ourColor; \n"// 向片段着色器输出一个颜色
- "void main()\n"
- "{\n"
- "gl_Position = vec4(aPos, 1.0);\n" //内建变量
- "ourColor=aColor;\n"
- "}\n\0";
- const char* fragment_shader_source =
- "#version 330 core\n"
- "in vec3 ourColor;\n"
- "out vec4 FragColor;\n" // 输出的颜色向量
- "void main()\n"
- "{\n"
- "FragColor = vec4(ourColor, 1.0f);\n"
- "}\n\0";
-
- // 生成并编译着色器
- // 顶点着色器
- int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
- glCompileShader(vertex_shader);
- int success;
- char info_log[512];
- // 检查着色器是否成功编译,如果编译失败,打印错误信息
- glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
- if (!success)
- {
- glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
- std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
- }
- // 片段着色器
- int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
- glCompileShader(fragment_shader);
- // 检查着色器是否成功编译,如果编译失败,打印错误信息
- glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
- if (!success)
- {
- glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
- std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
- }
-
- // 链接顶点和片段着色器至一个着色器程序
- int shader_program = glCreateProgram();
- glAttachShader(shader_program, vertex_shader);
- glAttachShader(shader_program, fragment_shader);
- glLinkProgram(shader_program);
- // 检查着色器是否成功链接,如果链接失败,打印错误信息
- glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
- if (!success) {
- glGetProgramInfoLog(shader_program, 512, NULL, info_log);
- std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
- }
-
- // 删除着色器 需要的着色器程序已经拿到了,这个没用了,就删除了
- glDeleteShader(vertex_shader);
- glDeleteShader(fragment_shader);
-
- // 线框模式
- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- // 第4部分,渲染//
-
- // 渲染循环
- while (!glfwWindowShouldClose(window)) {
-
- // 清空颜色缓冲
- glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- // 使用着色器程序 【之前链接好的那个】
- glUseProgram(shader_program);
-
- // 绘制三角形
- glBindVertexArray(vertex_array_object); // 绑定VAO
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // 设置指针位置,以便后续从此处读取数据进行渲染
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float))); // 设置指针位置,以便后续从此处读取数据进行渲染
- glEnableVertexAttribArray(1);
- glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制三角形
-
- glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // 【渲染时告诉OpenGL如何解释这些数据】
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); // 【渲染时告诉OpenGL如何解释这些数据】
- glEnableVertexAttribArray(1);
- glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制三角形
-
-
- glBindVertexArray(0); // 解除绑定
-
- // 交换缓冲并且检查是否有触发事件(比如键盘输入、鼠标移动等)
- glfwSwapBuffers(window);//双缓冲
- glfwPollEvents();
- }
-
- // 第五部分,善后工作
-
- // 删除VAO和VBO
- glDeleteVertexArrays(1, &vertex_array_object);
- glDeleteBuffers(1, &vertex_buffer_object[0]);
-
- // 清理所有的资源并正确退出程序
- glfwTerminate();
- return 0;
- }
那末,如果这个顶点数据,是可变的,应该咋写?
和STATIC_DRAW有关吗?
有关,但是没有想象里的关联那么大
引用:
(31条消息) STATIC_DRAW, DYNAMIC_DRAW, STREAM_DRAW的区别_me_badman的博客-CSDN博客
以后再说吧,暂时用不到。
小白而已,不能一次要求的太多……