Интуитивно понятно, что можно было бы реализовать несколько источников света, делая что-то вроде этого:
uniform int NUM_LIGHTS;
uniform vec3 uLa[NUM_LIGHTS];
Но WebGL выдает такую ошибку:
ERROR: 0:12: ":constant expression required
ERROR: 0:12: ":array size must be a constant integer expression"
Тем не менее, вы на самом деле можете передавать единообразные массивы в шейдер фрагментов для представления нескольких источников света. Единственное предостережение в том, что вам нужно заранее знать размер этих массивов. Например:
const int NUM_LIGHTS = 5;
uniform vec3 uLa[NUM_LIGHTS]; //ambient
uniform vec3 uLd[NUM_LIGHTS]; //diffuse
uniform vec3 uLs[NUM_LIGHTS]; //specular
Это правильно. Также вам необходимо убедиться, что вы отображаете плоский массив на стороне JavaScript. Поэтому вместо этого:
var ambientLightArray = [[0.1,0.1,0.1][0.1,0.1,0.1],...]
сделать это:
var ambientLightArray = [0.1,0.1,0.1,0.1,0.1,0.1,..]
Тогда вы делаете:
var location = gl.getUniformLocation(prg,"uLa");
gl.uniform3fv(location, ambientLightArray);
После того, как вы настроили массивы с заранее заданным размером, вы можете делать такие вещи:
//Example: Calculate diffuse contribution from all lights to the current fragment
//vLightRay[] and vNormal are varyings calculated in the Vertex Shader
//uKa and uKd are material properties (ambient and diffuse)
vec3 COLOR = vec3(0.0,0.0,0.0);
vec3 N = normalize(vNormal);
for(int i = 0; i < NUM_LIGHTS; i++){
L = normalize(vLightRay[i]);
COLOR += (uLa[i] * uKa) + (uLd[i] * uKd * clamp(dot(N, -L),0.0,1.0));
}
gl_FragColor = vec4(COLOR,1.0);
Я надеюсь, что это может быть полезно