OpenGL使用 subroutine 切换可编程管线

Posted gccbuaa

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL使用 subroutine 切换可编程管线相关的知识,希望对你有一定的参考价值。

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技术能够达到相似的效果,相关内容能够參考官方文档


技术分享

关注我的微信公众号,获取很多其它优质内容

以上是关于OpenGL使用 subroutine 切换可编程管线的主要内容,如果未能解决你的问题,请参考以下文章

从 OpenGL 切换到 GDI

opengl 的窗口处理程序

Perl编程-4子程序+引用

OpenGL:切换和反转轴

opengl 渲染纹理并在是不是使用 mipmap 之间切换

NVIDIA Optimus 卡在 OpenGL 下不切换