Thursday, September 26, 2013

Changing and Animating Colors

After all the movement coding that we just did, how about we take a step back and do something a little different - color using Three.js.  Remember the rgb (red, green, and blue) line of code that made the cube a bright green?  Just in case, here it is again: 
var material = new THREE.MeshBasicMaterial({ color: 'rgb(0,255,0)' });
The three numbers inside the rgb code parentheses, (0,255,0) represent the intensity of each component of the overall final color.  We have 0 for red, 255 for green,and 0 for blue.  Remember that 255 is the maximum value for a color code.  Since we have 0 for both red and blue, they will not be mixed into the final color.  And since we have the maximum 255 for green, our cube turns out to be the brightest green possible.  Let's have a little fun with the color values.  First, try replacing the number 255 with a lower number, like 50.   Since this is a lower intensity, it will still be green, but it will now be a darker green.  Here's what the updated line of code should like like:
var material = new THREE.MeshBasicMaterial({ color: 'rgb(0,50,0)' });

Once you have gone in and changed that one little number, Save the whole file as tempGame.js, overwriting the old one.  Indeed, we now have a dark green cube.  Pretty easy!
If you would like to experiment with different color codes, here is a helpful website that gives you the exact rgb code for all the popular web colors in use today:
RGB color code charts

That's great, but wouldn't it be neat if we could animate the numbers and change the cube color over time?  Well, now that we have explored the 'oscillation' technique in the last couple of posts, we can apply our new knowledge to color as well! 
Here's the plan - we want to have a glowing red cube that pulsates (oscillates) from dark to light to dark to light, etc.  This could be used as an emergency light in a future game project.   Since rgb stands for red, green, and blue, we will set green and blue to 0 and leave those numbers alone.  For the first number, the r-value, we have it be a variable that represents a constantly changing number somewhere between 0 and 255.  When it is closer to 0, the cube will appear to be a dark red, almost black-red.  And when it approaches 255, it will glow the brightest red possible.
First, we need to create a color object that will hold the rgb information of our changing red color.  Using the Three.js library, a new color object is declared like this:
var redColor = new THREE.Color( 'rgb(0,0,0)' );
I chose the name 'redColor' because that is descriptive of what information it holds.  We fill this object by typing ' = new ' and then we access the Three.js library by typing 'THREE.something()' , where 'something' is the object that we want.  In this case it's a color object, so we type THREE.Color().  As an option, when declaring a new THREE.Color, we can specify what color it starts out as.  Even though it will be shades of red throughout the program, I initially set it to black which is rgb(0,0,0).  This takes care of the green and blue components which have to be set to 0 anyway.  And with the first number, the red component, we will ramp it up and down very soon in the program, so it really doesn't matter what this number is set to.
Next, let's declare a red intensity variable and call it something meaningful.  'redIntensity' sounds appropriate.  Here's how that looks in JavaScript code: 
var redIntensity = 0;
In the above code, we again use our trusty 'var' keyword then our 'redIntensity' name representing the amount of red color.  Then we fill it with the value of 0 by typing:  = 0;  It's always a good idea to initialize your variables to something, 0 being the most often used choice.  This is because you are telling JavaScript that this variable will hold some kind of number in the future, and then you can use it right away in your program.  You don't have to even know what it's going to be right away, but you can always change that later in the program.  
Next we need a flag, just like we had for the camera motion, but this time for color motion.  Remember, a flag is just a switch, on or off, true or false.  When the color motion flag is equal to 'true', we will add brightness to the red color by adding to its value every animation frame.  Likewise if the flag is switched to 'false', we will darken the red color by subtracting from its value every frame.  Let's declare this new flag:
var colorBrightenFlag = true;

Notice I used camelCase to capitalize the beginning of all words that are mashed together (except the first word) in 'colorBrightenFlag'.  This makes variable names easier to read.
I set this flag equal to true because I want the cube to start brightening right away when the program starts.  You could have set it to 'false' to - it doesn't really matter.
Moving on, we need an oscillation block of code (like we used for our camera a while ago) that repeatedly goes back and forth between a low value and a high value.  Let's copy the code we already made for the oscillating camera and replace the variable names with our new names so it works with colors:
if(colorBrightenFlag == true){
   redIntensity = redIntensity + 8;
}
if(colorBrightenFlag == false){
   redIntensity = redIntensity - 8;
} 
      
if(redIntensity > 255){
   redIntensity = 255;
   colorBrightenFlag = false;
}
       
if(redIntensity < 0){
   redIntensity = 0;
   colorBrightenFlag = true;
}

Looking at the above code, if 'colorBrightenFlag' is equal to 'true', then our 'redIntensity' variable gets added 8 units to itself and it grows every animation frame.  Likewise, if 'colorBrightenFlag' is equal to 'false', then our 'redIntensity' variable gets subtracted 8 from itself and it shrinks every frame.  I arbitrarily chose the number 8 because this produced a faster glowing effect.  Try different values and see how it affects the glow speed.  Remember, the higher the number, the faster it will oscillate between light and dark. 
To keep our program from adding and subtracting too far out of range, we next 'clamp' the 'redIntensity' value to a range between 0 and 255, which is the required range for rgb codes.  When the intensity wanders out of range and it is time to be clamped, we also flip the 'colorBrightenFlag' switch, so that the intensity starts to go in the opposite direction (just as we did for our camera oscillation before). 

Now we must update our 'redColor' Three.js color object that we declared earlier.  This actually holds all the color information, including the intensities of the r, g, and b components.  Since we used Three.js to declare this color, it now has handy properties and built-in functions that come with it.  One of these properties is the 'r' intensity of red, which is indeed what we want to change every animation frame.  We access it like this:
redColor.r = redIntensity;
We access the redColor's 'r' property by simply typing 'redColor' then ' . '(dot) then 'r'.  We then fill this value with whatever 'redIntensity' happens to be at the moment (which is constantly rising and falling).  There's one catch though - Three.js color properties such as '.r' must be presented in a range from 0 to 1.  0 would be dark and 1 would be bright.  0.5 would be somewhere in the middle.  I wanted to work in 0-255 rgb ranges which I find easier to read and work with, but now we must convert the intensity and scale it down to a range between 0 and 1.  Don't worry though, this is easily done with a couple of keystrokes:
redColor.r = redIntensity / 255;
The above code reads out loud "redColor.r equals redIntensity divided by ( / ) 255".  All we had to do is divide our 255-range intensity by its highest possible value, which is 255.  This will clamp it down to a range somewhere between 0 and 1.  For example, if 'redIntensity' is 255, then 255 / 255 = 1 which is the brightest value.  If 'redIntensity' is 0, then 0 / 255 = 0, which is darkest.  If 'redIntensity' is 175, then 175 / 255 = 0.68627... which is a little over half-bright.  
One more thing to do; we have to attach this updated 'redColor' to our cube so that the cube will indeed turn to whatever shade of red that we want it to.  This requires more ' . ' (dots) to access all the different properties of the cube.  It might not seem intuitive right now, but the more you use Three.js, the more you will realize why they designed the library this way, and it actually will make sense as we keep doing it in the future.  Here's how we access the color of the cube:
cube.material.color.set(redColor);
I know, that's a lot of dots ( . ) to look at, but Three.js mesh objects necessarily have a lot of different properties that can be optionally set (which makes the library so robust).  Going down the list, we start by typing 'cube' which is our mesh object, followed by '.material', which is the cube's skin, followed by '.color', which is the skin's color, followed by '.set', which is an action that changes the skin color, followed lastly by '(redColor)' which is the name of our color-info variable that holds the actual r, g, and b intensities of the final color.
Thus, if 'redColor' has a low '.r' (red-component) inside of it, our cube will turn dark-red.  If 'redColor' has a higher '.r' inside of it, our cube will glow bright-red.  

Since we added color-changing code to our .js file, I have listed the new updated tempGame.js in its entirety below. Copy and paste the following code and then Save it as tempGame.js, overwriting the old one:   


var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({ color: 'rgb(0,255,0)' });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);


var redIntensity = 0;
var redColor = new THREE.Color( 'rgb(0,0,0)' );
var colorBrightenFlag = true;

camera.position.z = 5;
var forwardFlag = false;
animate();

function animate(){
   
   requestAnimationFrame(animate);

   cube.rotation.x = cube.rotation.x + 0.02;
   cube.rotation.y = cube.rotation.y + 0.03;

   if(forwardFlag == false){
      camera.position.z = camera.position.z + 0.1;
   }
   if(forwardFlag == true){
      camera.position.z = camera.position.z - 0.1;
   } 
      
   if(camera.position.z > 10){
      camera.position.z = 10;
      forwardFlag = true;
   }
       
   if(camera.position.z < 1){
      camera.position.z = 1;
      forwardFlag = false;
   }

   if(colorBrightenFlag == true){
      redIntensity = redIntensity + 8;
   }
   if(colorBrightenFlag == false){
      redIntensity = redIntensity - 8;
   } 
      
   if(redIntensity > 255){
      redIntensity = 255;
      colorBrightenFlag = false;
   }
       
   if(redIntensity < 0){
      redIntensity = 0;
      colorBrightenFlag = true;
   }
   
   redColor.r = redIntensity / 255;
   cube.material.color.set(redColor);
      
   renderer.render( scene, camera );

}

Once you have saved it, go back to your example01.html file and open with your Chrome browser.  If you saved everything correctly, you should see our cube now glowing red, going back and forth between light and dark. Pretty cool!

In the next post we will learn how to add lighting to our scene.  We will explore the Three.js library's different kinds of lights for different situations.  Most importantly, we will be able to see the edges and shaded sides of our cube, making it look even more 3D!