Subroutine 功能是在OpenGL 4.0 版本号里才添加的。因此对于各种Android手机。这个功能基本跪了。假设你发现你的程序报错:ARB_shader_subroutine。那就说明当前显卡不支持。只是大体思路能够了解一下。由于思路相似的功能有其它的实现方式。
原理
在shader中声明一个函数变量,然后定义它的指针,并将其作为一个uniform变量公开出去。最后定义非常多复写函数就可以。
实现
由于版本号限制。使用 subroutine 要注意在shader中添加版本号的编译宏:
#version 400 core
在shader中编写:
subroutine vec4 SurfaceColor(); subroutine uniform SurfaceColor U_SurfaceColor; subroutine (SurfaceColor) vec4 Ambient() { //... } subroutine (SurfaceColor) vec4 Diffuse() { //... } subroutine (SurfaceColor) vec4 Specular() { //... } void main() { gl_FragColor = U_SurfaceColor(); }
在shader中,每个函数中的代码段代表一种处理函数。
还有一方面在GL指令中,绑定这个函数指针,并为其指定实现函数的索引值,就可以实现效果的控制。
surfaceColorLocation = glGetSubroutineUniformLocation(program,GL_FRAGMENT_SHADER,"U_SurfaceColor"); GLuint ambientLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Ambient"); GLuint diffuseLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Diffuse"); GLuint specularLightIndex = glGetSubroutineIndex(program,GL_FRAGMENT_SHADER,"Specular"); //draw glUniformMatrix4fv(MLocation, 1, GL_FALSE, glm::value_ptr(model)); glUniformSubroutinesuiv(GL_FRAGMENT_SHADER,1,&ambientLightIndex); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo); glDrawElements(GL_TRIANGLES,indexCount,GL_UNSIGNED_INT,0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
总结
本文介绍了OpenGL中的 subroutine 机制,通过它能够切换shader的内容。在Unity3d中使用Shader.maximumLOD
技术能够达到相似的效果,相关内容能够參考官方文档
关注我的微信公众号,获取很多其它优质内容
时间: 2024-10-27 05:03:13