经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 软件/图像 » OpenGL » 查看文章
OpenGL(3)-三角形
来源:cnblogs  作者:年少无知的Jack  时间:2018/9/25 19:31:20  对本文有异议

写在前面

从这节开始,会接触到很多基本概念,原书我也是读了很多遍,一遍一遍去理解其中的意思,以及他们之间的关系。

概念

顶点数组对象:VAO

顶点缓冲对象:VBO

索引缓冲对象:EBO|IBO

OpenGL是一个3D空间,而屏幕和窗口是2D的,所以OpenGL的大部分工作是将3D坐标转换为2D像素

转换的过程就是由图形渲染管线管理的。

图像渲染管线分为两部分:1.把3D坐标转换为2D坐标。2.把2D坐标转变为有颜色的像素

渲染的几个阶段:

顶点数据->顶点着色器->图元装配->几何着色器->光栅化->片段着色器->测试与混合

渲染的每一个阶段都有自己的程序,该程序是使用OpenGL着色器语言进行编写的,这些小程序叫做着色器(shader)

顶点着色器:把3D坐标转换为另一种3d坐标,同时对顶点属性进行一些基本处理

图元装配:将所有的点装配成指定的图元形状

几何着色器:通过产生新的点和新的图元来生成形状

光栅化:将图元映射为最终屏幕上相应的像素,生成片段着色器使用的片段,并裁切吊超过视图以外的像素

片段着色器:计算一个像素的最终颜色

测试与混合:检测片段对应的深度值,用来判断这个像素是其它物体的前面还是后面,决定是否丢弃

代码创建

首先,我们声明出来下面需要使用的着色器源码。

通过上述概念我们知道着色器,是运行在图像渲染管线上的小程序,代码风格类似c语言

  1. 1 // 顶点着色器源码
  2. 2 const char *vertexShaderSource =
  3. 3 "#version 330 core\n"
  4. 4 "layout (location = 0) in vec3 aPos;\n"
  5. 5 "void main(){\n"
  6. 6 "gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);\n"
  7. 7 "}\n\0";
  8. 8
  9. 9 //片段着色器源码
  10. 10 const char *fragmentShaderSource =
  11. 11 "#version 330 core\n"
  12. 12 "out vec4 FragColor;\n"
  13. 13 "void main(){\n"
  14. 14 "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
  15. 15 "}\n\0";

下边我们使用上述两个着色器,构建一个可以渲染的渲染管线

  1. //创建顶点着色器
  2. int vertexShader = glCreateShader(GL_VERTEX_SHADER);
  3. // 第一个参数着色器对象,第二个参数传递的源码字符串,第三个参数顶点着色器的源码
  4. glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
  5. glCompileShader(vertexShader);
  6. // 判断编译是否成功
  7. int sucess;
  8. char infoLog[512];
  9. glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &sucess);
  10. if(!sucess){
  11. glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
  12. std::cout<< "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n"<< infoLog << std::endl;
  13. }
  1. // 片段着色器,创建并编译
  2. int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  3. glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  4. glCompileShader(fragmentShader);
  5. glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, & sucess);
  6. if(!sucess){
  7. glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
  8. std::cout<<"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n"<< infoLog<<std::endl;
  9. }

两个着色器创建,且编译之后,需要进行连接

  1. //链接两个着色器对象到用来渲染的着色器程序中
  2. // 创建着色器程序
  3. int shaderProgram = glCreateProgram();
  4. //链接
  5. glAttachShader(shaderProgram, vertexShader);
  6. glAttachShader(shaderProgram, fragmentShader);
  7. glLinkProgram(shaderProgram);
  8. glGetShaderiv(shaderProgram, GL_COMPILE_STATUS, & sucess);
  9. if(!sucess){
  10. glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
  11. std::cout<<"ERROR::SHADER::PROGRAM::COMPILATION_FAILED\n"<< infoLog<<std::endl;
  12. }

链接两个着色器到我们刚创建的着色器程序中,且进行了编译,这个时候,我们上面的两个着色器,已经在shaderProgram中了。

  1. 1 //删除无用的顶点着色器以及片段着色器
  2. 2 glDeleteShader(vertexShader);
  3. 3 glDeleteShader(fragmentShader);

 

我们知道,渲染的几个阶段,那么现在我们只需要创建顶点数据,然后使用上述着色器程序进行渲染

  1. 1 // 定义三个顶点
  2. 2 float vertices[] = {
  3. 3 -0.5f, -0.5f, 0.0f,
  4. 4 0.5f, -0.5f, 0.0f,
  5. 5 0.0f, 0.5f, 0.0f
  6. 6 };

 

 

对于顶点的管理,我们使用顶点缓冲对象以及顶点数组对象进行管理。文章开头已经讲解了基本的概念

  1. // 使用顶点缓冲对象进行缓存
  2. unsigned int VBO, VAO;
  3. glGenVertexArrays(1, &VAO);
  4. glGenBuffers(1, &VBO);
  5. // 缓冲对象进行绑定
  6. glBindVertexArray(VAO);
  7. glBindBuffer(GL_ARRAY_BUFFER, VBO);

 

缓冲对象的使用

  1. 1 // 将定义的顶点数据复制到缓冲内存中
  2. 2 // 第一个参数,缓冲类型,第二个参数数据大小,第三个参数发送的数据,第四个参数,显卡如何管理给定的数据
  3. 3 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  4. 4
  5. 5 // 解析顶点数据
  6. 6 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  7. 7 // 启动顶点数据
  8. 8 glEnableVertexAttribArray(0);
  9. 9
  10. 10 glBindBuffer(GL_ARRAY_BUFFER, 0);
  11. 11 glBindVertexArray(0);
  12. 12
  13. 13 glDrawArrays(GL_TRIANGLES,0,3);

 

现在我们的顶点数组对象已经在内存中了

下面就是调用着色器程序进行启动

  1. 1 //启用三角形
  2. 2 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
  3. 3 glClear(GL_COLOR_BUFFER_BIT);
  4. 4 // 激活程序
  5. 5 glUseProgram(shaderProgram);
  6. 6 glBindVertexArray(VAO);
  7. 7 glDrawArrays(GL_TRIANGLES, 0, 3);
  8. 8 glfwSwapBuffers(window);

 

最后,不要忘了清楚我们使用的vao以及vbo对象

  1. //清除对象
  2. glDeleteVertexArrays(1, &VAO);
  3. glDeleteBuffers(1, &VBO);

 

总结

通过上述的流程,应该是可以跑起来一个三角形的。OpenGL之路漫漫长,我们继续加油

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号