Time for Action: Adding a White Light to a Scene

Let's cover an example of how we'd add a new light to our scene:

  1. Open the ch06_04_wall-light-arrays.html file in your browser. This scene looks exactly like ch06_03_wall-final.html; however, the code is far less complex since we are now using uniform arrays. Let's see how using uniform arrays changes our code.
  2. Open the ch06_04_wall-light-arrays.html file in your code editor. Let's take a look at the vertex shader. Note the use of the constant integer expression const int, numLights = 3;, to declare the number of lights that the shader will handle.
  1. There, you can also see that a uniform array is being used to operate on light positions. Note that we are using a varying array to pass the light rays (for each light) to the fragment shader:
for(int i = 0; i < numLights; i++) {
vec4 lightPosition = uModelViewMatrix * vec4(uLightPosition[i],
1.0);
vLightRay[i] = vertex.xyz - lightPosition.xyz;
}
  1. This fragment of code calculates one varying light ray per light. Recall that the same code in the ch06_03_wall-final.html file looks like the following code:
vec4 redLightPosition = uModelViewMatrix * vec4(uPositionRedLight, 
1.0);
vec4 greenLightPosition = uModelViewMatrix *
vec4(uPositionGreenLight, 1.0);
vec4 blueLightPosition = uModelViewMatrix *
vec4(uPositionBlueLight, 1.0);

vRedRay = vertex.xyz - redLightPosition.xyz;
vGreenRay = vertex.xyz - greenLightPosition.xyz;
vBlueRay = vertex.xyz - blueLightPosition.xyz;
  1. Once you compare these two snippets, the advantage of using uniform arrays (and varying arrays) should be clear.
  2. The fragment shader also uses uniform arrays. In this case, the fragment shader iterates through the light diffuse properties to calculate the contribution of each one to the final color on the wall:
for(int i = 0; i < numLights; i++) {
L = normalize(vLightRay[i]);
lambertTerm = dot(N, -L);
if (lambertTerm > uCutOff) {
finalColor += uLightDiffuse[i] * uMaterialDiffuse * lambertTerm;
}
}
  1. For the sake of brevity, we won’t cover the verbose version from the ch06_03_wall-final.html exercise, but you should check it out for yourself and compare it with this one.
  1. In the configure function, the size of the JavaScript array containing the uniform names has decreased considerably by omitting the other unnecessary light attributes:
const uniforms = [
'uPerspectiveMatrix',
'uModelViewMatrix',
'uNormalMatrix',
'uMaterialDiffuse',
'uMaterialAmbient',
'uLightAmbient',
'uLightDiffuse',
'uLightPosition',
'uWireframe',
'uLightSource',
'uCutOff'
];
  1. The mapping between JavaScript lights and uniform arrays is now simpler because of the getArray method from the LightsManager class. As we described earlier, the getArray method concatenates the lights' data into one flat array.
  2. The load and render functions look exactly the same. If we want to add a new light, we still need to load a new sphere with the load function (to represent the light source in our scene), and we still need to translate the sphere to the appropriate location in the render function.
  3. Let's see how much effort we need to add a new light. Go to the configure function and create a new light object, as follows:
const whiteLight = new Light('whiteLight');
whiteLight.setPosition([0, 10, 2]);
whiteLight.setDiffuse([1.0, 1.0, 1.0, 1.0]);
  1. Add whiteLight to the lights instance:
lights.add(whiteLight);
  1. Move to the load function and append this line:
scene.load('/common/models/geometries/sphere3.json', 'whiteLight');
  1. Just like in the previous Time for Action section, add this to the render function:
if (object.alias === 'whiteLight') {
const whiteLight = lights.get(object.alias);
mat4.translate(modelViewMatrix, modelViewMatrix,
whiteLight.position);
object.diffuse = whiteLight.diffuse;
gl.uniform1i(program.uLightSource, true);
}
  1. Save the webpage with a different name and open it using your browser. We have also included the completed exercise in ch06_05_wall-light-arrays-final.html, including some minor improvements on keeping the light configuration more declarative. The following diagram shows the final result:

That’s all you need to do! If you want to control the white light properties with the controls widget, you would need to write the corresponding code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.200.211