我希望能够将多个光源附加到场景图的每个节点上,但是我不知道该怎么做!

learningwebgl.com的教程中,我学会了使用定向照明还是位置照明,但是找不到如何实现多个光源的很好的解释。

因此,目标应该是可以选择向每个节点附加任意数量的光源,该光源可以是定向照明或位置照明,并且如果可能和建议的话,应该仅使用一个着色器程序来实现(如果这不是唯一可行的方法),因为我会根据每个节点的特定需求自动为其创建程序(除非堆栈中已经存在具有相同设置的程序)。

根据learningwebgl.com上的教程,我的节点照明的片段着色器源使用照明而没有预设绑定到一种照明类型,看起来像这样...

precision highp float;

uniform bool uUsePositionLighting;
uniform bool uUseDirectionalLighting;

uniform vec3 uLightPosition;
uniform vec3 uLightDirection;

uniform vec3 uAmbientColor;
uniform vec3 uDirectionalColor;

uniform float uAlpha;

varying vec4 vPosition;
varying vec3 vTransformedNormal;
varying vec3 vColor;


void main (void) {

  float directionalLightWeighting;

  if (uUseDirectionalLighting) {

    directionalLightWeighting = max(dot(vTransformedNormal, uLightDirection), 0.0);

  else if (uUsePositionLighting) {

    vec3 lightDirection = normalize(uLightPosition, vPosition.xyz);

    directionalLightWeighting = max(dot(normalize(vTransformedNormal, lightDirection), 0.0);

  }

  vec3 lightWeighting = uAmbientColor + uDirectionalColor * directionalLightWeighting;

  gl_FragColor = vec4(vColor * lightWeighting, uAlpha);

}


...所以,这基本上是我对这个问题的较差知识。

我也问自己,添加更多的光源将如何影响照明颜色:

我的意思是,uAmbientColoruDirectionalColor是否必须加总为1.0?在这种情况下(尤其是当使用多个光源时),在将这些值传递给着色器之前预先计算这些值肯定会很好,不是吗?

最佳答案

将您的灯光排列成阵列,并为每个片段遍历它们。从固定的光源阵列开始,直到OpenGL 4.3才支持无边界阵列,并且使用起来更加复杂。

类似于以下内容:

uniform vec3 uLightPosition[16];
uniform vec3 uLightColor[16];
uniform vec3 uLightDirection[16];
uniform bool uLightIsDirectional[16];

 ....

 void main(void) {
   vec3 reflectedLightColor;

   // Calculate incoming light for all light sources
   for(int i = 0; i < 16; i++) {
     vec3 lightDirection = normalize(uLightPosition[i], vPosition.xyz);
     if (lightIsDirectional[i]) {
       reflectedLightColor += max(dot(vTransformedNormal, uLightDirection[i]), 0.0) * uLightColor[i];
     }
     else  {
       reflectedLightColor += max(dot(normalize(vTransformedNormal, lightDirection), 0.0) * uLightColor[i];
     }
   }

   glFragColor = vec4(uAmbientColor + reflectedLightColor * vColor, uAlpha);
 }


然后,可以通过将不使用的条目的uLightColor设置为(0,0,0)来启用/禁用光源。

环境和方向的总和不必为1,实际上光源的强度可以比1.0强得多,但是您需要进行色调映射以返回可以在屏幕上显示的一系列值,我建议您四处游玩以了解正在发生的事情(例如,当光源具有负色或颜色大于1.0时会发生什么情况)。

uAmbientColor只是一种模拟场景中多次反弹的光线的(差)方法。否则,阴影中的事物将完全变为黑色,这看起来是不现实的。

反射率通常应在0到1之间(在此示例中,这将是“最大”计算返回的部分),否则当通过材质查看时,光源会变得更强。

09-20 07:05