《OpenGL编程指南(原书第9版)》——2.7 独立的着色器对象

简介: 本节书摘来自华章计算机《OpenGL编程指南(原书第9版)》一书中的第2章,第2.7节,作者:(美)约翰·克赛尼希(John Kessenich)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.7 独立的着色器对象

高级技巧
在OpenGL 4.1版本之前(不考虑扩展功能),在应用程序中,同一时间只能绑定一个着色器程序。如果你的程序需要使用多个片元着色器来处理来自同一个顶点着色器的几何体变换数据,那么这样会变得很不方便。此时只能将同一个顶点着色器复制多份,并且多次绑定到不同的着色器程序,从而造成了资源的浪费和代码的重复。
独立的着色器对象可以将不同程序的着色阶段(例如顶点着色)合并到同一个程序管线中。
第一步,我们需要创建用于着色器管线的着色器程序。我们可以调用glProgramParameteri()函数并且设置参数为GL_PROGRAM_SEPARABLE,然后再链接着色器程序。这样该程序就被标识为在程序管线中使用。如果想要简化这个过程,还可以直接使用新增的glCreateShaderProgramv()来封装着色器编译过程,并且将程序标识为可共享(如上文所述),然后链接到最终的对象。
将着色器程序集合合并之后,就需要用这个新的着色器管线结构来合并多个程序中的着色阶段。对于OpenGL中的大部分对象来说,都有一个生成-绑定-删除的过程,以及对应可用的函数。着色器管线的创建可以调用glCreateProgramPipelines(),即创建一个未使用的程序管线标识符,然后将它传入glBindProgramPipeline(),使得该程序可以自由编辑(例如,添加或者替换着色阶段)和使用。与其他生成的对象相似,程序管线可以通过glDeleteProgramPipelines()来删除。
当绑定了一个程序管线之后,可以调用glUseProgramStages()将之前标记为独立的程序对象关联到管线上,它通过位域的方式来描述该管线处理几何体和着色片元时,给定程序所处的着色阶段。而之前的glUseProgram()只能直接调用一个程序并且替换当前绑定的程序管线。
为了确保管线可以使用,着色器阶段之间的接口—in和out变量—也必须是匹配的。非独立的着色器对象在程序链接时就可以检查这些接口的匹配情况,与之相比,使用独立程序对象的着色器管线只能在绘制–调用过程中进行检查。如果接口没有正确匹配,那么所有的可变变量(out变量)都未定义。
内置的gl_PerVertex块必须重新声明,以便显式地指定固定管线接口中的哪些部分可以使用。如果管线用到了多个程序,那么这一步是必需的。
例如:
image

这样我们就建立了着色器的输出接口,它将用于后继的管线阶段当中。这里必须使用gl_PerVertex自己的内置成员。如果不同的着色器程序都用到了同一个内置的块接口,那么所有的着色器都必须使用相同的方式重新声明这个内置的块。
因为独立的着色器对象可以有各自独立的程序uniform集合,所以我们可以使用两种方法来设置uniform变量的值。第一种方法是通过glActiveShaderProgram()来选择一个活动的着色器程序,然后调用glUniform()和glUniformMatrix()来设置某个着色器程序的uniform变量的值。另一种推荐的方法是调用glProgramUniform()和glProgramUniformMatrix()函数,它们有一个显式的program对象参数,这样可以独立地设置某个程序的uniform变量的值。
void glProgramUniform{1234}{fdi ui}(GLuint program, GLint location, TYPE value);
void glProgramUniform{1234}{fdi ui}v(GLuint program, GLint location, GLsizei count, const TYPE* values);
void glProgramUniformMatrix{234}{fd}v(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLf?loat* values);
void glProgramUniformMatrix{2x3,2x4,3x2,3x4,4x2,4x3}{fd}v( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLf?loat* values);
glProgramUniform()和glProgramUniformMatrix()函数的使用与glUniform()和glUniformMatrix()的使用是一样的,唯一的区别是使用一个program参数来设置准备更新uniform变量的着色器程序。这些函数的主要优点是,program可以不是当前绑定的程序(即最后一个使用glUseProgram()指定的着色器程序)。

相关文章
|
6月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
124 0
|
数据可视化
QT+OpenGL几何着色器
输入布局限定符可以从顶点着色器接收下列任何一个图元值: ● points:绘制GL_POINTS图元时 ● lines:绘制GL_LINES或GL_LINE_STRIP时 ● lines_adjacency:GL_ADJACENCY或GL_LINESTRIP_ADJACENCY ● triangles:GL_TRIANGLES、GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN ● triangles_adjacency:GL_TRIANGLES_ADJACENCY或GL_TRIANGLE_STRIP_ADJACENCY
117 0
|
缓存 图形学
《OpenGL编程指南(原书第9版)》——导读
OpenGL图形系统是图形硬件的一种软件接口(GL表示Graphics Library,即图形库)。它使得用户可以创建交互式的程序以产生运动的三维对象的颜色图像。通过OpenGL,我们可以使用计算机图形学技术产生逼真的图像,或者通过一些虚构的方式产生虚拟的图像。
3003 0
|
缓存 索引
OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结
OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结
OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结
|
编译器 C语言 C++
OpenGL学习笔记(十一):封装自己的着色器类
OpenGL学习笔记(十一):封装自己的着色器类
OpenGL学习笔记(十一):封装自己的着色器类
|
存储 缓存 API
三、OpenGL ES GLSL语言 & 自定义着色器常用API
OpenGL ES GLSL语言 & 自定义着色器常用API
314 0
三、OpenGL ES GLSL语言 & 自定义着色器常用API
|
存储
了解OpenGL中的投影方式、存储着色器分类、常见图元连接方式
了解OpenGL中的投影方式、存储着色器分类、常见图元连接方式
238 0
了解OpenGL中的投影方式、存储着色器分类、常见图元连接方式
|
存储 芯片 异构计算