使用Subroutine在shader中封装不同的函数,在CPU端选择调用那个函数

效果如下图所示

左侧:环境光

中间:环境光 + 漫反射

右侧:环境光 + 漫反射 + 高光


1、Subroutine 在shader中的内容

subroutinevec4SurfaceColor();subroutineuniformSurfaceColorU_SurfaceColor;

定义SurfaceColor()函数类型


环境光函数

//Ambientsubroutine(SurfaceColor)vec4Ambient(){//Ambientvec4M_AmbientLightColor=vec4(0.2,0.2,0.2,1.0);vec4M_AmbientMaterial=vec4(0.2,0.2,0.2,1.0);vec4ambientColor=M_AmbientLightColor*M_AmbientMaterial;returnambientColor;}


环境光+漫反射函数

subroutine(SurfaceColor)vec4Diffuse(){//Ambientvec4M_AmbientLightColor=vec4(0.2,0.2,0.2,1.0);vec4M_AmbientMaterial=vec4(0.2,0.2,0.2,1.0);vec4ambientColor=M_AmbientLightColor*M_AmbientMaterial;//Diffusevec3M_LightPos=vec3(10.0,10.0,0.0);vec3LightNormal=normalize(M_LightPos);//指向光源的单位向量vec3NormalNormal=normalize(M_normal);//法线的单位向量//点乘获取光照强度vec4M_DiffuseLightColor=vec4(1.0,1.0,1.0,1.0);vec4M_DiffuseMaterial=vec4(0.8,0.8,0.8,1.0);vec4diffuseColor=M_DiffuseLightColor*M_DiffuseMaterial*max(0.0,dot(NormalNormal,LightNormal));returnambientColor+texture2D(U_MainTexture,M_coord)*diffuseColor;}


镜面反射函数

subroutine(SurfaceColor)vec4Specular(){//Ambientvec4M_AmbientLightColor=vec4(0.2,0.2,0.2,1.0);vec4M_AmbientMaterial=vec4(0.2,0.2,0.2,1.0);vec4ambientColor=M_AmbientLightColor*M_AmbientMaterial;//Diffusevec3M_LightPos=vec3(10.0,10.0,0.0);vec3LightNormal=normalize(M_LightPos);//指向光源的单位向量vec3NormalNormal=normalize(M_normal);//法线的单位向量//点乘获取光照强度vec4M_DiffuseLightColor=vec4(1.0,1.0,1.0,1.0);vec4M_DiffuseMaterial=vec4(0.8,0.8,0.8,1.0);vec4diffuseColor=M_DiffuseLightColor*M_DiffuseMaterial*max(0.0,dot(NormalNormal,LightNormal));//镜面反射vec4specularLightColor=vec4(1.0,1.0,1.0,1.0);vec4specularMaterial=vec4(0.4,0.4,0.4,1.0);vec3reflerDir=normalize(reflect(-LightNormal,NormalNormal));vec3eyeDir=normalize(vec3(0.0)-M_WordPos.xyz);vec4specularColor=specularLightColor*specularMaterial*pow(max(0.0,dot(reflerDir,eyeDir)),180);returnambientColor+texture2D(U_MainTexture,M_coord)*diffuseColor+specularColor;}


main函数

voidmain(){gl_FragColor=U_SurfaceColor();}


2、CPU端设置调用subrountine

获取subrountine的Location

m_SubRoutineLocation=OpenGLCore->glGetSubroutineUniformLocation(programId,\GL_FRAGMENT_SHADER,"U_SurfaceColor");//获取SubRoutineIndexm_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);