OpenGL(一) OpenGL管线 与 可编程管线流程
来源:互联网 发布:卡密软件破解 编辑:程序博客网 时间:2024/06/06 00:07
由于OpenGL是一个纯渲染核心,要写OpenGL程序,得先搭建一个外壳程序。不同平台下外壳程序的实现各有不同,这个系列的文章都在win32的平台上进行。具体实现,网上能找到很多,所以这不是本文的重点。本篇主要构建探讨 OpenGL管线 本身,具体说来,就是构建可编程管线。
主体流程
大体流程是:
- 在main函数中拉起外壳程序,初始化一些默认参数。例如双缓冲,32位颜色等。
- 创建GL上下文(HGLRC)。
- 加载&设置OpenGL的相关参数
- 在帧循环中进行绘制
至于固定管线和可编程管线,主要区别在3、4部分。固定管线是将绘制的方法写死到代码中,而可编程管线可以理解为脚本化了渲染的逻辑。不过这两者渲染的数据部分仍由编译后的程序提供。
具体说来,通过一种语法定义,将一个文本文件实例化到内存中,并且在运行时动态编译,挂载,链接到GPU程序中,完成绘制算法的替换。对应的,由于所有数据都放在内存中,绘制时,需要将它传输到GPU上,这就是缓冲区(glBuffer)。缓冲区在CPU上,会将在某些时间段内缓冲区的数据一起提交给GPU。
实现
总的来看,可编程管线动态生成了一段绘制程序,在每个GPU核心通过绘制命令,绘制传给他数据。简单的看下两部分的代码片段:
首先是创建GPU绘制程序
GLuint CreateGPUProgram(const char* vsShaderPath,const char* fsShaderPath){ GLuint vsShader = glCreateShader(GL_VERTEX_SHADER); GLuint fsShader = glCreateShader(GL_FRAGMENT_SHADER); //Load const char* vsCode = LoadFileContent(vsShaderPath); const char* fsCode = LoadFileContent(fsShaderPath); //Compile glShaderSource(vsShader,1,&vsCode,nullptr); glShaderSource(fsShader,1,&fsCode,nullptr); glCompileShader(vsShader); glCompileShader(fsShader); //Attach GLuint program = glCreateProgram(); glAttachShader(program,vsShader); glAttachShader(program,fsShader); //Link glLinkProgram(program); //Clear glDetachShader(program,vsShader); glDetachShader(program,fsShader); glDeleteShader(vsShader); glDeleteShader(fsShader); return program;}
当GPU程序创建完成之后,就可以在主线程中写一个死循环,然后调用下面的绘制命令:
struct Vertex{ float pos[3]; float color[3];};void VFRender(){ glUseProgram(s_program); glUniformMatrix4fv(s_shaderData.MLocation,1,GL_FALSE,identify); glUniformMatrix4fv(s_shaderData.VLocation,1,GL_FALSE,identify); glUniformMatrix4fv(s_shaderData.PLocation,1,GL_FALSE,glm::value_ptr(s_shaderData.projection)); glBindBuffer(GL_ARRAY_BUFFER,s_shaderData.vbo); glEnableVertexAttribArray(s_shaderData.posLocation); glVertexAttribPointer(s_shaderData.posLocation,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),nullptr); glEnableVertexAttribArray(s_shaderData.colorLoacation); glVertexAttribPointer(s_shaderData.colorLoacation,3,GL_FLOAT,GL_FALSE,sizeof(Vertex),(void*)(sizeof(float)*3)); glDrawArrays(GL_TRIANGLES,0,3); glBindBuffer(GL_ARRAY_BUFFER,0); glUseProgram(0);}
其中,绘制的顶点数据是s_shaderData.vbo
,这些VBO(VertexBufferObject)数据通常在绘制之前就已准备好了。关于VBO的组成原理,我会在之后再写一篇文章详述。
GL2.0限制
由于目前市场上大多手机还是OpenGL2.0,总结了一下2.0需要注意的事项:
- 对于支持GL2.0最差的硬件,只支持输入8个Vector4。即
attribute
输入的vec4不应超过8。uniform
不受此限制。 - 矩阵会占用4个vec4,因此不应使用
attribute
修饰mat4,应使用uniform
。 - VertexShader与FragmentShader传递的变量使用
varying
进行标记。 - VS里面必须给
gl_Position
赋值,否则无法绘制。
GLSL 例子
最简单的shader可以写成这样:
VertexShader
attribute vec3 pos;attribute vec4 color;uniform mat4 M;uniform mat4 V;uniform mat4 P;varying vec4 V_Color;void main(){ V_Color = color; gl_Position = P*V*M*vec4(pos,1.0);}
FragmentShader
varying vec4 V_Color;void main(){ gl_FragColor = V_Color;}
简化看来,VertexShader处理3d的绘制信息,输出2d绘制信息。FragmentShader则是对2d信息进行色彩加工。
总结
以上就是构建 OpenGL管线 的流程。需要注意的是,一些变量需要从C++程序传入到OpenGL中。这是因为视口程序通常会提供一些动态更改这些值的方法。因此从外面传入shader会更灵活。如果在测试阶段,可以直接在shader中声明这些值,就省去了跨程序传值的烦恼。
关注我的微信公众号,获取更多优质内容
- OpenGL(一) OpenGL管线 与 可编程管线流程
- OpenGL固定管线与可编程管线对比
- OpenGL 可编程管线学习
- OpenGL ES1.1与OpenGL2.0函数集合,固定管线与可编程管线
- OpenGL(八)使用 subroutine 切换可编程管线
- OpenGL(十一) 可编程管线 基础光照 的实现
- opengl从固定渲染管线到可编程渲染管线
- opengl 管线
- OpenGL渲染管线---概述(一)
- GPU图形处理管线、图形硬件接口(OpenGL)与可编程图形渲染语言(CG)的关系
- GPU图形处理管线、图形硬件接口(OpenGL)与可编程图形渲染语言(CG)的关系
- opengl 渲染管线(转)
- 从OpenGL 1.x 到 2.x的迁移(即从固定管线到可编程管线的迁移)
- OpenGL-渲染管线的流程(有图有真相)
- OpenGL-渲染管线的流程(有图有真相)
- OpenGL-渲染管线的流程(有图有真相)
- OpenGL-渲染管线的流程(有图有真相)
- 基于Qt的OpenGL可编程管线学习(1)- 绘制一个三角形
- response.setContentType 与 request.setCharacterEncoding 区别
- BZOJ3223 文艺平衡树 题解
- ubuntu中卸载opencv2,安装opencv3.2.0和contrib组件,并使用python进行开发
- Django学习笔记
- Android 使用SharePerference实现判断是否为第一次登陆
- OpenGL(一) OpenGL管线 与 可编程管线流程
- 如何让存储到数据库的数据是完整的?
- VS使用技巧(快捷键)
- WIN32 下读取excel文档
- meta-http 属性详情
- ArcGIS Python API 与R语言混合编程实现分析及可视化
- 快速排序
- arcgis for android 和百度地图共同使用出现的问题
- Linux监控工具vmstat命令详解