OpenGL ES 2.0。 GLSL - 无法在片段着色器中同时使用两种采样颜色
我有一个片段着色器,可以进行视差映射和照明计算。我已经设法将问题追溯到纹理和/或照明计算的采样,因此我只会发布代码以使其简短:
// sample maps
vec3 albedo = texture2D(u_albedo_texture_1, p_texc).rgb;
vec3 ao = texture2D(u_ambientocclusion_texture, v_texcoord).rgb - 0.5; // ambient occlusion
vec3 normalT = texture2D(u_normalmap_texture, p_texc).rgb * 2.0 - 1.0; // tangent space normal
vec4 normalW = vec4(normalize(TBN * normalT).xyz, 1.0); // world space normal
vec3 color = vec3(0.0);
vec3 ambient = textureCube(u_cubemap_texture, -normalW.xyz).rgb; // get ambient lighting from cubemap
color += ambient * ao;
float d = length(light_vector);
float atten = 1.0 / dot(light_attenuation, vec3(1.0, d, d * d)); // compute attenuation of point light
// diffuse term
float ndotl = max(dot(normalW.xyz, light_vector), 0.0);
color += atten * ndotl * light_diffuse.rgb * albedo;
// specular term
float hdotn = max(0.0, dot(half_vector, normalW.xyz));
color += atten * ((shininess + 8.0) / 8.0 * 3.1416) * light_specular.rgb * p_ks * pow(hdotn, shininess);
gl_FragColor = vec4(color.rgb, 1.0);
我有此代码在其他着色器中工作,但在视差映射着色器中它只是丢弃像素,我不明白为什么。因此,它不是显示对象,而是简单地丢弃像素,并且对象根本不显示。没有错误或凌乱的颜色,什么都没有。
我设法将问题追溯到反照率和环境采样颜色。它们都被正确采样。如果我打印出来
gl_FragColor = vec4(ambient.rgb, 1.0);
或者
gl_FragColor = vec4(albedo.rgb, 1.0);
它们都正确显示,但如果我尝试用两种颜色做某事,像素就会被丢弃。以下均不起作用:
gl_FragColor = vec4(ambient + albedo, 1.0);
gl_FragColor = vec4(ambient * albedo, 1.0);
gl_FragColor = vec4(ambient.r, albedo.g, ambient.b, 1.0);
环境从立方体贴图采样,反照率从 2D 纹理采样。我还有其他用于环境光遮挡和法线贴图的采样器,这些采样器可以工作,并且它们还可以与环境或反照率结合使用。 所以环境光 + ao 可以工作,反照率 + ao 也可以工作。
所以,这是我的问题,我不知道是什么原因造成的。就像我说的,我在另一个着色器中有相同的代码并且该代码可以工作。
值得一提的是,它在 OpenGL ES 2.0 的 PowerVR 模拟器上运行。 GPU是nVidia GT220。 也请随意指出我的代码中的其他错误,例如效率低下的内容。如果有必要,我将发布完整的片段着色器代码。抱歉发了这么长的帖子:P
已解决
哇,不敢相信原因如此愚蠢,但我完全错过了。基本上,我忘记加载该特定模型的立方体贴图,并且它没有发送到着色器。不过,它到底是如何采样的呢?我的意思是,它是单独工作的,那么纹理单元采样了什么?先前处理后在缓存中留下的立方体贴图?
I have a fragment shader that does parallax mapping and lighting computations. I've managed to trace the problem to the sampling of textures and/or lighting computation so I'll only post code for that to keep it short:
// sample maps
vec3 albedo = texture2D(u_albedo_texture_1, p_texc).rgb;
vec3 ao = texture2D(u_ambientocclusion_texture, v_texcoord).rgb - 0.5; // ambient occlusion
vec3 normalT = texture2D(u_normalmap_texture, p_texc).rgb * 2.0 - 1.0; // tangent space normal
vec4 normalW = vec4(normalize(TBN * normalT).xyz, 1.0); // world space normal
vec3 color = vec3(0.0);
vec3 ambient = textureCube(u_cubemap_texture, -normalW.xyz).rgb; // get ambient lighting from cubemap
color += ambient * ao;
float d = length(light_vector);
float atten = 1.0 / dot(light_attenuation, vec3(1.0, d, d * d)); // compute attenuation of point light
// diffuse term
float ndotl = max(dot(normalW.xyz, light_vector), 0.0);
color += atten * ndotl * light_diffuse.rgb * albedo;
// specular term
float hdotn = max(0.0, dot(half_vector, normalW.xyz));
color += atten * ((shininess + 8.0) / 8.0 * 3.1416) * light_specular.rgb * p_ks * pow(hdotn, shininess);
gl_FragColor = vec4(color.rgb, 1.0);
I have this code working in other shaders, but here in the parallax mapping shader it just discards the pixels and I can't understand why. So instead of showing the object it simply discards the pixels and the object doesn't show up at all. No wrong or messy colors, nothing.
I managed to trace the problem to the albedo and ambient sampled colors. They're both sampled correctly. If I print out
gl_FragColor = vec4(ambient.rgb, 1.0);
or
gl_FragColor = vec4(albedo.rgb, 1.0);
they both get displayed correctly but if I try to do something with both colors, the pixels get discarded. None of the following work:
gl_FragColor = vec4(ambient + albedo, 1.0);
gl_FragColor = vec4(ambient * albedo, 1.0);
gl_FragColor = vec4(ambient.r, albedo.g, ambient.b, 1.0);
ambient is sampled from a cube map and albedo from a 2D texture. I have other samplers for ambient occlusion and normal mapping and those work and they also work in conjunction with ambient OR albedo.
So ambient + ao works and albedo + ao works.
So, this is my problem and I can't figure out what causes it. Like I said, I have the same code in another shader and that one works.
Worth mentioning, this runs on a PowerVR emulator for OpenGL ES 2.0. and the GPU is an nVidia GT220.
Also feel free to point out other mistakes in my code like inefficient stuff. And if necessary, I'll post the full fragment shader code. Sorry for the long post :P
SOLVED
Wow, can't believe the cause was so stupid, but I completely missed it. Basically, I forgot to load the cubemap for that particular model and it wasn't sent to the shader. Still, how the hell did it sample something in the first place? I mean, it was working separately, so what did the texture unit sample? A cubemap left in the cache from previous processing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通常,当我的着色器没有产生所需的结果但看起来令人烦恼的“正常”时,这是因为着色器编译丢弃了它(我在某处犯了错误)并决定使用“固定管道”着色器......
Usually when my shaders doesn't produce the desired result but are looking annoyingly 'normal' it is because the shader compilation discarded it (I made an error somewhere) and decided to use the 'fixed pipeline' shader instead...