• 实验2.1——彩色三角形的显示


    序 

    查这段代码的时候:

    无意中看到了一个这个链接:

    (31条消息) 现代OpenGL学习笔记三:深入理解着色器_不想不努力的菜菜的博客-CSDN博客

    里面讲了如何绘制一个彩色的三角形,还演示了index=0,1两种情况下,VBO与shader怎么呼应的,绘制有颜色的图形,很常用,值得学习。

    链接的学习

    这部分内容,来自上面那个链接。

    1. float vertices[] = {
    2. // 位置 // 颜色
    3. 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下
    4. -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下
    5. 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部
    6. };
    1. #version 330 core
    2. layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为 0
    3. layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
    4. out vec3 ourColor; // 向片段着色器输出一个颜色
    5. void main()
    6. {
    7. gl_Position = vec4(aPos, 1.0);
    8. ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
    9. }

    1. #version 330 core
    2. out vec4 FragColor;
    3. in vec3 ourColor;
    4. void main()
    5. {
    6. FragColor = vec4(ourColor, 1.0);
    7. }

     图画的挺漂亮的:

    1. // 位置属性
    2. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
    3. glEnableVertexAttribArray(0);
    4. // 颜色属性
    5. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
    6. glEnableVertexAttribArray(1);

    明白了,去尝试自己写吧。 

    尝试

    作为一个小白,报错是常态,所以,不要有心理负担。

    之前做到了这样:

    第一次运行,是这样:

     

     改,在这一行里,少了个vec3,少了个;

     

    坏消息是依旧报错,好消息是错少了

     这个const float,和这个有关系吗?

     实测,没关系……

    经过重写对比,发现少了个“,”

    这可能不是调试代码,这是比谁的眼更敏感……对我这种小白来说,太难搞了。。

    正常了,这个就已经开始有点实用价值了

    能正常运行出结果的完整代码

    1. /***
    2. * 例程 绘制三角形 (MAKE后运行时可删除ALL_BUILD,也可以将Task-triangle设为默认启动工程)
    3. * 步骤:
    4. * 1-初始化: GLFW窗口,GLAD。
    5. * 2-数据处理: 给定顶点数据,生成并绑定VAO&VBO(准备在GPU中进行处理),设置顶点属性指针(本质上就是告诉OpenGL如何处理数据)。
    6. * 3-着色器: 给出顶点和片段着色器,然后链接为着色器程序,渲染时使用着色器程序。
    7. * 4-渲染: 清空缓冲,绑定纹理,使用着色器程序,绘制三角形,交换缓冲区检查触发事件后释放资源
    8. */
    9. #include <iostream>
    10. #include "glad/glad.h"
    11. #include "GLFW/glfw3.h"
    12. // 三角形的顶点数据
    13. //const float triangle[] = {
    14. // // ---- 位置 ----
    15. // -0.5f, -0.5f, 0.0f, // 左下
    16. // 0.5f, -0.5f, 0.0f, // 右下
    17. // 0.0f, 0.5f, 0.0f // 正上
    18. //};
    19. //
    20. //const float triangle2[] = {
    21. // // ---- 位置 ----
    22. // 0.6f, -0.5f, 0.0f, // 左下
    23. // 0.8f, -0.5f, 0.0f, // 右下
    24. // 0.7f, 0.5f, 0.0f // 正上
    25. //};
    26. const float triangle[] = {
    27. // 位置 // 颜色
    28. 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下
    29. -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下
    30. 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部
    31. };
    32. const float triangle2[] = {
    33. // 位置 // 颜色
    34. 0.6f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下
    35. 0.8f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下
    36. 0.7f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部
    37. };
    38. // 屏幕宽,高
    39. int screen_width = 1280;
    40. int screen_height = 720;
    41. int main() {
    42. // 第一部分,初始化GLFW和GLAD,分为4个步骤进行/
    43. // 初始化GLFW
    44. glfwInit(); // 初始化GLFW
    45. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL版本为3.3,主次版本号均设为3
    46. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    47. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式(无需向后兼容性)
    48. //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 如果使用的是Mac OS X系统,需加上这行
    49. glfwWindowHint(GLFW_RESIZABLE, false); // 不可改变窗口大小
    50. // 创建窗口(宽、高、窗口名称)
    51. auto window = glfwCreateWindow(screen_width, screen_height, "Triangle", nullptr, nullptr);
    52. if (window == nullptr) { // 如果窗口创建失败,输出Failed to Create OpenGL Context
    53. std::cout << "Failed to Create OpenGL Context" << std::endl;
    54. glfwTerminate();
    55. return -1;
    56. }
    57. glfwMakeContextCurrent(window); // 将窗口的上下文设置为当前线程的主上下文
    58. // 初始化GLAD,加载OpenGL函数指针地址的函数
    59. // 在调用任何OpenGL函数之前
    60. if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    61. {
    62. std::cout << "Failed to initialize GLAD" << std::endl;
    63. return -1;
    64. }
    65. // 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
    66. glViewport(0, 0, screen_width, screen_height);
    67. // 第二部分,数据处理,通过VAO,VBO,把顶点数据发送到显卡GPU上,并设置属性指针,告诉GPU如何解释这些数据/
    68. // 生成并绑定VAO和VBO
    69. GLuint vertex_array_object; // == VAO 核心模式要求必须使用VAO
    70. glGenVertexArrays(1, &vertex_array_object);//先生成
    71. glBindVertexArray(vertex_array_object);//再绑定
    72. GLuint vertex_buffer_object[2]; // == VBO
    73. glGenBuffers(2, &vertex_buffer_object[0]);//先生成,相当于C里声明的指针
    74. glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);//绑定, 相当于声明指针指向的变量类型,同时设置一下状态机的状态(火车轨道变轨,变完了后面的车都得按变了的轨道走)
    75. glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW); // 将顶点数据绑定至当前默认的缓冲中
    76. //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 设置顶点属性指针——告知OpenGL,如何解释这些数据
    77. //glEnableVertexAttribArray(0);
    78. glBindBuffer(GL_ARRAY_BUFFER, 0);//解绑
    79. glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);//再绑定
    80. glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2), triangle2, GL_STATIC_DRAW); // 将顶点数据绑定至当前默认的缓冲中,可能是传数据到GPU吧
    81. //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); // 设置顶点属性指针——告知OpenGL,如何解释这些数据
    82. //glEnableVertexAttribArray(0);
    83. glBindBuffer(GL_ARRAY_BUFFER, 0);//再绑定
    84. // 解绑VAO和VBO 为了代码更规范
    85. glBindVertexArray(0);
    86. // 第三部分,着色器,用来处理GPU里的数据//
    87. // 顶点着色器和片段着色器源码【GLSL】
    88. const char* vertex_shader_source =
    89. "#version 330 core\n"
    90. "layout (location = 0) in vec3 aPos;\n" // 位置变量的属性位置值为0
    91. "layout (location = 1) in vec3 aColor; \n " 颜色变量的属性位置值为 1
    92. "out vec3 ourColor; \n"// 向片段着色器输出一个颜色
    93. "void main()\n"
    94. "{\n"
    95. "gl_Position = vec4(aPos, 1.0);\n" //内建变量
    96. "ourColor=aColor;\n"
    97. "}\n\0";
    98. const char* fragment_shader_source =
    99. "#version 330 core\n"
    100. "in vec3 ourColor;\n"
    101. "out vec4 FragColor;\n" // 输出的颜色向量
    102. "void main()\n"
    103. "{\n"
    104. "FragColor = vec4(ourColor, 1.0f);\n"
    105. "}\n\0";
    106. // 生成并编译着色器
    107. // 顶点着色器
    108. int vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    109. glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
    110. glCompileShader(vertex_shader);
    111. int success;
    112. char info_log[512];
    113. // 检查着色器是否成功编译,如果编译失败,打印错误信息
    114. glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
    115. if (!success)
    116. {
    117. glGetShaderInfoLog(vertex_shader, 512, NULL, info_log);
    118. std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << info_log << std::endl;
    119. }
    120. // 片段着色器
    121. int fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    122. glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
    123. glCompileShader(fragment_shader);
    124. // 检查着色器是否成功编译,如果编译失败,打印错误信息
    125. glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
    126. if (!success)
    127. {
    128. glGetShaderInfoLog(fragment_shader, 512, NULL, info_log);
    129. std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << info_log << std::endl;
    130. }
    131. // 链接顶点和片段着色器至一个着色器程序
    132. int shader_program = glCreateProgram();
    133. glAttachShader(shader_program, vertex_shader);
    134. glAttachShader(shader_program, fragment_shader);
    135. glLinkProgram(shader_program);
    136. // 检查着色器是否成功链接,如果链接失败,打印错误信息
    137. glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
    138. if (!success) {
    139. glGetProgramInfoLog(shader_program, 512, NULL, info_log);
    140. std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << info_log << std::endl;
    141. }
    142. // 删除着色器 需要的着色器程序已经拿到了,这个没用了,就删除了
    143. glDeleteShader(vertex_shader);
    144. glDeleteShader(fragment_shader);
    145. // 线框模式
    146. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    147. // 第4部分,渲染//
    148. // 渲染循环
    149. while (!glfwWindowShouldClose(window)) {
    150. // 清空颜色缓冲
    151. glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
    152. glClear(GL_COLOR_BUFFER_BIT);
    153. // 使用着色器程序 【之前链接好的那个】
    154. glUseProgram(shader_program);
    155. // 绘制三角形
    156. glBindVertexArray(vertex_array_object); // 绑定VAO
    157. glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[0]);
    158. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // 设置指针位置,以便后续从此处读取数据进行渲染
    159. glEnableVertexAttribArray(0);
    160. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3*sizeof(float))); // 设置指针位置,以便后续从此处读取数据进行渲染
    161. glEnableVertexAttribArray(1);
    162. glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制三角形
    163. glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_object[1]);
    164. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); // 【渲染时告诉OpenGL如何解释这些数据】
    165. glEnableVertexAttribArray(0);
    166. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); // 【渲染时告诉OpenGL如何解释这些数据】
    167. glEnableVertexAttribArray(1);
    168. glDrawArrays(GL_TRIANGLES, 0, 3); // 绘制三角形
    169. glBindVertexArray(0); // 解除绑定
    170. // 交换缓冲并且检查是否有触发事件(比如键盘输入、鼠标移动等)
    171. glfwSwapBuffers(window);//双缓冲
    172. glfwPollEvents();
    173. }
    174. // 第五部分,善后工作
    175. // 删除VAO和VBO
    176. glDeleteVertexArrays(1, &vertex_array_object);
    177. glDeleteBuffers(1, &vertex_buffer_object[0]);
    178. // 清理所有的资源并正确退出程序
    179. glfwTerminate();
    180. return 0;
    181. }

    后记

    那末,如果这个顶点数据,是可变的,应该咋写?

    和STATIC_DRAW有关吗?

    有关,但是没有想象里的关联那么大

     引用:

    (31条消息) STATIC_DRAW, DYNAMIC_DRAW, STREAM_DRAW的区别_me_badman的博客-CSDN博客

     

    以后再说吧,暂时用不到。

    小白而已,不能一次要求的太多…… 

  • 相关阅读:
    WebGL正射投影
    lwIP 细节之四:ARP 相关知识
    Cesium 问题:鼠标移出地球,但移动中生成的内容还在球上
    后端程序员实现一个IP归属地的小程序
    k8s学习-持久化存储(Volumes、hostPath、emptyDir、PV、PVC)详解与实战
    ICCV 2023|小红书 4 篇入选论文亮点解读,「开集视频目标分割」获得 Oral
    Observability:使用 Elastic Agent 来收集定制的 TCP 日志
    基于闪电搜索优化的BP神经网络(分类应用) - 附代码
    python加载图片无法显示原因探究/python内存回收机制作祟
    SegNeXt Rethinking Convolutional Attention Design for Semantic Segmentation
  • 原文地址:https://blog.csdn.net/averagePerson/article/details/125628600