使用Subroutine在shader中封装不同的函数,在CPU端选择调用那个函数
效果如下图所示
左侧:环境光
中间:环境光 + 漫反射
右侧:环境光 + 漫反射 + 高光
1、Subroutine 在shader中的内容
subroutine vec4 SurfaceColor(); subroutine uniform SurfaceColor U_SurfaceColor;
定义SurfaceColor()函数类型
环境光函数
// Ambient subroutine (SurfaceColor) vec4 Ambient() { // Ambient vec4 M_AmbientLightColor = vec4(0.2, 0.2, 0.2, 1.0); vec4 M_AmbientMaterial = vec4(0.2, 0.2, 0.2, 1.0); vec4 ambientColor = M_AmbientLightColor * M_AmbientMaterial; return ambientColor; }
环境光+漫反射函数
subroutine (SurfaceColor) vec4 Diffuse() { // Ambient vec4 M_AmbientLightColor = vec4(0.2, 0.2, 0.2, 1.0); vec4 M_AmbientMaterial = vec4(0.2, 0.2, 0.2, 1.0); vec4 ambientColor = M_AmbientLightColor * M_AmbientMaterial; // Diffuse vec3 M_LightPos = vec3(10.0, 10.0, 0.0); vec3 LightNormal = normalize(M_LightPos); // 指向光源的单位向量 vec3 NormalNormal = normalize(M_normal); // 法线的单位向量 // 点乘获取光照强度 vec4 M_DiffuseLightColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 M_DiffuseMaterial = vec4(0.8, 0.8, 0.8, 1.0); vec4 diffuseColor = M_DiffuseLightColor * M_DiffuseMaterial * max(0.0, dot(NormalNormal, LightNormal)); return ambientColor + texture2D(U_MainTexture, M_coord) * diffuseColor; }
镜面反射函数
subroutine (SurfaceColor) vec4 Specular() { // Ambient vec4 M_AmbientLightColor = vec4(0.2, 0.2, 0.2, 1.0); vec4 M_AmbientMaterial = vec4(0.2, 0.2, 0.2, 1.0); vec4 ambientColor = M_AmbientLightColor * M_AmbientMaterial; // Diffuse vec3 M_LightPos = vec3(10.0, 10.0, 0.0); vec3 LightNormal = normalize(M_LightPos); // 指向光源的单位向量 vec3 NormalNormal = normalize(M_normal); // 法线的单位向量 // 点乘获取光照强度 vec4 M_DiffuseLightColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 M_DiffuseMaterial = vec4(0.8, 0.8, 0.8, 1.0); vec4 diffuseColor = M_DiffuseLightColor * M_DiffuseMaterial * max(0.0, dot(NormalNormal, LightNormal)); // 镜面反射 vec4 specularLightColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 specularMaterial = vec4(0.4, 0.4, 0.4, 1.0); vec3 reflerDir = normalize(reflect(-LightNormal, NormalNormal)); vec3 eyeDir = normalize(vec3(0.0) - M_WordPos.xyz); vec4 specularColor = specularLightColor * specularMaterial * pow(max(0.0, dot(reflerDir, eyeDir)), 180); return ambientColor + texture2D(U_MainTexture, M_coord) * diffuseColor + specularColor; }
main函数
void main() { gl_FragColor = U_SurfaceColor(); }
2、CPU端设置调用subrountine
获取subrountine的Location
m_SubRoutineLocation = OpenGLCore->glGetSubroutineUniformLocation(programId, \ GL_FRAGMENT_SHADER, "U_SurfaceColor"); // 获取 SubRoutine Index m_AmbientIndex=OpenGLCore->glGetSubroutineIndex(programId,GL_FRAGMENT_SHADER,"Ambient"); m_DiffuseIndex=OpenGLCore->glGetSubroutineIndex(programId,GL_FRAGMENT_SHADER,"Diffuse"); m_SpecularIndex=OpenGLCore->glGetSubroutineIndex(programId,GL_FRAGMENT_SHADER,"Specular");
为U_SurfaceColor设置值
OpenGLCore->glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &m_AmbientIndex); OpenGLCore->glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &m_DiffuseIndex); OpenGLCore->glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &m_SpecularIndex);