我想用普通的地图在GLSL中渲染一些曲面,有些则没有

我有正常的映射在我的游戏中工作,但我只想使用正常的映射一些表面,而不是其他人。

现在,就我所知,我的着色器将正切空间中的(0,0,0)不正确的法线应用于我的非法线贴图表面,因为没有纹理绑定到采样器。

是否有一种合适的方法来检测GLSL中的采样器没有任何约束,然后使用平坦法线? 我也发现在networking上的旧post建议如下:

  1. 使用虚拟1×1纹理与颜色(128,128,255) – 这将失去Phong插值。
  2. 切换正常映射表面和非正常映射表面的着色器程序 – 我感觉最终会以这种方式复制大量的代码,特别是当我开始实现高光贴图,视差位移贴图等时。

这些仍然是推荐的还是有一个新的function来查询采样器,我可以利用? 出于性能方面的原因,我是否应该这样做?

这是我的片段着色器:

#version 330 core in vec2 UV; in vec3 tangentSpaceLightDir; out vec4 outColor; uniform sampler2D diffuseMap, normalMap; void main (void) { vec4 texel = texture(diffuseMap, UV); vec4 ntexel = texture(normalMap, UV); // I want to use vertex normal here, if nothing is bound. vec3 N = normalize(ntexel.xyz * 2.0 - 1.0); vec3 L = normalize(tangentSpaceLightDir); float lambertTerm = dot(N, -L); vec4 finalColor = vec4(0.0); if (lambertTerm > 0.0) { finalColor += vec4(lambertTerm, 1.0); } outColor = finalColor * texel; } 

你已经知道你要做什么了,我只是总结一下。 有三种方法可以解决您的问题:

  • 继续前进,像你说的那样做一个有条件的事情,要么通过抽样纹理,要么为此创建一个单独的uniform 。 正如你可能知道的那样,在着色器上添加​​分支几乎不是一个好主意,在片段着色器中更是如此: 你通常不想这样做

  • 添加一个uniform float ,决定你是否使用法线。 将其设置为0以禁用,并将其设置为1以启用。 计algorithm线后,将结果乘以该值。 如果将其设置为0,结果将为0.但是,如果要禁用法线,程序将不会更快。 你通常会喜欢这种方法

  • 但是,如果你可以负担切换着色器,我真的建议你这样做。 当法线被禁用时,着色器会快一点。 如果您担心重复的代码,您可以通过汇编不同的部分来程序化地生成着色器,并根据您的不同需要创建不同的着色器集合。 拥有大量的着色器,甚至数百种不同的着色器在现代游戏中并不罕见。 如果可能的话,你可能要这样做