在GLSL中,subroutine是这样一种机制:它根据某个变量的值把一个函数调用和一个函数定义集合中的某一个函数定义绑定起来。在很多方面它和C语言中的函数指针类似。一个全局变量充当指针,用来调用函数。可以在OpenGL中设置这个变量的值,这样可以把它和多个函数定义中的一个绑定起来。subroutine中的函数定义不一定要同名,但是必须要有同等数量和相同类型的参数以及相同的返回类型
Subroutines提供了在运行时刻不用切换着色器或者是重新编译或者是使用if判断就能选择不同实现功能的方法。例如,一个着色器里面可以实现多种算法用来在场景中渲染不同的对象。当渲染场景的时候,我们可以通过改变subroutines的全局变量的值来选择合适的渲染算法而不是去通过切换着色器或者是使用条件判断来实现。
注意:由于性能在着色器中越来越重要,所以避免条件判断或着色器切换是很有必要的。有了subroutines,我们就能够在不增加计算负载的情况下实现条件判断和着色器切换的功能。
下面用一个例子来进行说明。在这个例子中,采用subroutine渲染了两次茶壶。分别采用不同的光照模型。第一次用ADS(ambient,diffuse,specular)模型进行渲染,第二次只用diffuse模型渲染。一个subroutine全局变量用来选择渲染算法。下面两幅图可以看出效果的对比。
左边是ADS模型渲染效果,右边是diffuse模型渲染效果。
下面介绍使用subroutines的步骤。
我们在vertex shader中进行subroutines的定义。
(1)首先是定义subroutine类型:
subroutine vec3 shadeModelType( vec4 position, vec3 normal);
上面的代码定义了一个新的subroutine类型,其名字是shadeModelType。其语意和函数原型很类似。它定义了一个名字,一个参数列表和返回类型,参数名不是必须的。
(2)紧接着我们定义一个上述类型的uniform变量shadeModel:
subroutine uniform shadeModelType shadeModel;
这个变量充当了函数指针的作用,它在OpenGL应用程序中将会被赋值为两个可能的函数之一。
(3)定义两个函数,作为subroutine的一部分。
它们都有一个前缀是:
subroutine( shadeModelType )
其意味着函数和subroutine类型匹配。我们使用这个前缀定义了两个函数:
(4)函数调用
在vertex shader的main函数中,我们使用subroutine的uniform变量shadeModel来调用定义的两个函数。
LightIntensity = shadeModel( eyePosition, eyeNorm );
这样,根据uniform变量shadeModel的值,这个调用会被绑定到上述我们定义的两个函数之一。
(5)给subroutine uniform变量赋值。
分两步进行。
1、使用glGetSubroutineIndex函数查询每个subroutine函数的索引。
第一个参数是程序的句柄。第二个是着色器。第三个是subroutine的名字。查询到的索引存储在两个GLuint型的值中。
2、为了选择合适的subroutine函数,我们需要给subroutine uniform变量shadeModel赋值。采用如下函数调用实现:
glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &adsIndex);
这个函数可以一次设置多个uniform变量值。第一个参数指定着色阶段。第二个是要设定的uniform变量的数量。这里只需要设置一个uniform变量的值。
如果要设置多个,那么第三个参数应该是个数组,通常数组中的第i个元素赋值给subroutine uniform变量中索引为i的那个。
这里只需要设置一个值,我们设置的是索引为0 的那么subroutine uniform变量。
注意:OpenGL中,uniform 变量的索引默认就是从0开始的。如果有多个变量需要设置,可以用glGetSubroutineUniformLocation()查询。
接下来进行渲染就可以得出相应的效果了。
要进行另外一种效果的渲染只需调用下面函数:
glUniformSubroutinesuiv( GL_VERTEX_SHADER, 1, &diffuseIndex);
再进来渲染过程即可。
分享到:
相关推荐
内容包含了glm glut 等库,用vs2008 基于OpenGL 4.0 ,可以直接运行,包含所有源码,里面含有很多使用性技巧
opengl编程入门,glsl语言的hello world,着色器,glsl语言简介
opengl_learning--C-GLSL-C++.cmake-2020m6
opengl编程入门,glsl语言的hello world,着色器,glsl语言简介
:gem_stone: vscode-glsl-canvas 通过提供Show glslCanvas命令,该扩展程序可在VSCode中打开GLSL着色器的实时WebGL预览。 它使用的改进和改进版本,版本来自 javascript库和由制造的 。 现在支持WebGL2。 只需在文件...
If you are an OpenGL programmer looking to use the modern features of GLSL 4.0 to create real-time, three-dimensional graphics, then this book is for you. Familiarity with OpenGL programming, along ...
非常不好找的 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 opengl 4.0 shading language cookbook 源码 GLSL COOKBOOK 源码 ...
前端开源库-glsl-transitionsglsl transitions,在glsl.io上创建的glsl transitions集合。
opengl编程入门,glsl语言的hello world,你好三角形,绘制一个三角形
GLSL小巧的调试工具,可以代替glDebugger。我自己编译好的,免去自己编译的麻烦
这是一个简单的GLSL着色程序的完整代码,GLSL需要显卡支持OpenGL版本2.0以上
前端开源库-glsl-transition-fadeglsl transition fade,简单的fade glsl transition对象
glsl-atmosphere, 使用瑞利和散射渲染天空颜色 glsl大气使用瑞利和散射渲染天空颜色。 演示工具安装npm install glsl-atmosphere示例 Javascriptvar quad = Geometry(gl). attr('a
npm install --save-dev webpack-glsl-loader 用法 与require 注意:如中所述,您应避免使用此方法,而应在下一部分中使用配置方法。 require ( 'webpack-glsl!./my-lovely-shader.glsl' ) ; 在配置中 { module :...
glsl-沙盒 服务器开发 设置 Fork 仓库 下载存储库并创建新的开发分支: $ git clone git@github.com:<your>/glsl-sandbox $ cd glsl-sandbox $ git checkout -b <feature> go 下载并解压测试数据: $ curl -O ...
glsl-face-正常 在片段着色器中近似面法线,用于从相机空间中的位置进行平面着色。 注意:您需要启用GL_OES_standard_derivatives 。 分段: #extension GL_OES_standard_derivatives : enable varying vec3 ...
GLSL-Debugger 对GLSL语言的调试工具
这是有关使用SDL2作为OpenGL Helper的GLSL着色器的入门系列,以及有关C-Coders的一些着色器语言。 0-初始化一个简单的OpenGL窗口1-绘制和旋转矩形texture_SOIL texture_SDL2-渲染纹理2-使用着色器3-加载着色器3a1-...