伙计们,我终于为此目的编写了一个着色器!奇怪的是,我最终没有使用加法混合(只是在着色器中改变一条线来实现这一点),而是扩展了这个想法,使第二个纹理成为高光贴图 - 这样它的纹理只有在高光时才能看到光击中它!
大多数效果可以通过以下事实来实现:我自己的着色器可以简单地处理远高于 1 的镜面反射值- 邪恶的 OpenGL 会在不询问的情况下将其剪辑为 1 :-(
GLfloat mat_specular[] ={ 2, 2, 2, 1 }; glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular); //works here :-)
顶点着色器:
vs = const_cast<char *>(
"varying vec4 diffuse, ambient;"
"varying vec3 normal, lightDir, halfVector;"
"uniform float time;"
"void main(void){"
"normal = normalize(gl_NormalMatrix * gl_Normal);" //Transform Normal into Eye Space
"lightDir = normalize(vec3(gl_LightSource[0].position));"
"halfVector = normalize(gl_LightSource[0].halfVector.xyz);"
"diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;"
"ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient + gl_FrontMaterial.ambient * gl_LightModel.ambient;"
"gl_TexCoord[0] = gl_MultiTexCoord0;"
"gl_Position = ftransform();" //Apply Changes
"}") ;
和片段着色器:
fs =const_cast<char *>(
"uniform sampler2D tex1;"
"uniform sampler2D tex2;"
"varying vec4 diffuse,ambient;"
"varying vec3 normal, lightDir, halfVector;"
"void main() {"
"vec3 n,halfV,colortexel,colorfragment;"
"vec4 texel,specularmap;"
"float NdotL,NdotHV,alphatexel,alphafragment;\n"
"colorfragment = ambient.rgb;" //initialize color with ambient part
"alphafragment = gl_FrontMaterial.diffuse.a;"
"n = normalize(normal);" //copy to write
"NdotL = max(dot(normal, lightDir), -0.1);"
"specularmap = texture2D(tex2,gl_TexCoord[0].st);" //MUST Be started first!
"texel = texture2D(tex1,gl_TexCoord[0].st*2.0);"
"if (NdotL>=-0.1) {"
"colorfragment += diffuse.rgb * NdotL;"
"halfV = normalize(halfVector);"
"NdotHV = max (dot(n,halfV),0.0);"
"colorfragment += gl_FrontMaterial.specular.rgb * specularmap.rgb * gl_LightSource[0].specular.rgb * pow(NdotHV, gl_FrontMaterial.shininess);"
"}"
"colortexel = texel.rgb; alphatexel = texel.a;"
"gl_FragColor = vec4(colortexel * colorfragment, alphatexel * alphafragment);"
"}");
它根本没有优化,目前只是一个没有艺术技巧的概念验证,但结果如下:
在没有任何着色器的情况下渲染,但在“调制”上使用多纹理。您可以看到容器上有一些污垢,但镜面光很差:
使用着色器渲染 - 虽然在这张照片上看不清楚,但污垢在那里。重镜面光,甚至可以通过增加 glMaterialfv 中的镜面值来加强:
以夸张的 4 倍光泽度渲染。您现在可以在辉光中看到污垢纹理:
仍然存在一个问题 - 为什么我不能使用 gl_TexCoord(1) - 结果是没有纹理,而是像素渲染伪影,尽管多纹理在没有着色器的情况下可以正常工作。任何帮助表示赞赏。