1. 程式人生 > >OpenGL(八)使用 subroutine 切換可編程管線

OpenGL(八)使用 subroutine 切換可編程管線

rgb false pro 編程 其它 () con 函數指針 shader

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 切換可編程管線