Adding a light source

Notes:

We modify the last exercise to add a light source

Source:

// Light.cpp
// Create a light source

#include <GLTools.h>
#include <GLShaderManager.h>
#include <GLFrustum.h>
#include <GLBatch.h>
#include <GLFrame.h>
#include <GLMatrixStack.h>
#include <GLGeometryTransform.h>
#include <StopWatch.h>

#include <math.h>
#include <stdio.h>

#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

#define NUM_SPHERES 50

GLShaderManager		shaderManager;			// Shader Manager
GLMatrixStack		modelViewMatrix;		// Modelview Matrix
GLMatrixStack		projectionMatrix;		// Projection Matrix
GLFrustum		viewFrustum;			// View Frustum
GLGeometryTransform	transformPipeline;		// Geometry Transform Pipeline

//GLTriangleBatch		torusBatch;
GLTriangleBatch     cylinderBatch;			// cylinder
GLBatch		    floorBatch;
GLTriangleBatch     sphereBatch;
GLFrame             cameraFrame;
GLFrame             spheres[NUM_SPHERES];
        
// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    // Initialze Shader Manager
    shaderManager.InitializeStockShaders();
	
    glEnable(GL_DEPTH_TEST);
    
    // Background color
    glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
	
    // This makes a torus
    //gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);
	
    // This generates a cylinder
    gltMakeCylinder(cylinderBatch,
                    0.5,    // base radius
                    0.5,    // top radius
                    1.0,    // length
                    16,     // slices
                    1);     // stacks

    // This make a sphere
    gltMakeSphere(sphereBatch, 0.1f, 26, 13);
    	
    floorBatch.Begin(GL_LINES, 324);
    for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5)
    {
        floorBatch.Vertex3f(x, -0.55f, 20.0f);
        floorBatch.Vertex3f(x, -0.55f, -20.0f);
        
        floorBatch.Vertex3f(20.0f, -0.55f, x);
        floorBatch.Vertex3f(-20.0f, -0.55f, x);
    }
    floorBatch.End();    

    // Randomly place the spheres
    for(int i = 0; i < NUM_SPHERES; i++)
    {
        GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
        GLfloat y = ((GLfloat)(rand() % 40) * 0.1f);
        GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
        spheres[i].SetOrigin(x, y, z);
    }
}

// Screen changes size or is initialized
void ChangeSize(int nWidth, int nHeight)
{
    // Prevent a divide by zero
    if(nHeight == 0)
    {
        nHeight = 1;
    }
    
    glViewport(0, 0, nWidth, nHeight);
	
    // Create the projection matrix, and load it on the projection matrix stack
    viewFrustum.SetPerspective(35.0f, float(nWidth)/float(nHeight), 1.0f, 100.0f);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    // Set the transformation pipeline to use the two matrix stacks 
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

// Called to draw scene
void RenderScene(void)
{
    // colors
    GLfloat vRed[]      =   { 1.0f, 0.0f, 0.0f, 1.0f };
    GLfloat vMaroon[]   =   { 0.5f, 0.0f, 0.0f, 1.0f };
    GLfloat vBlue[]     =   { 0.0f, 0.0f, 1.0f, 1.0f };
    GLfloat vDBlue[]    =   { 0.0f, 0.0f, 0.5f, 1.0f };
    GLfloat vLGrey[]    =   { 0.3f, 0.3f, 0.3f, 1.0f };
    GLfloat vGrey[]     =   { 0.8f, 0.8f, 0.8f, 1.0f };

    // Time Based animation
    static CStopWatch	rotTimer;
    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
	
    // Clear the color and depth buffers
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
    // Save the current modelview matrix (the identity matrix)
    modelViewMatrix.PushMatrix();	
    
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.PushMatrix(mCamera);

    // Transform the light position into eye coordinates
    M3DVector4f vLightPos = { 0.0f, 10.0f, 5.0f, 1.0f };
    M3DVector4f vLightEyePos;
    m3dTransformVector4(vLightEyePos, vLightPos, mCamera);
		
    // Draw the ground
    shaderManager.UseStockShader(GLT_SHADER_FLAT,
				 transformPipeline.GetModelViewProjectionMatrix(),
				 vGrey);	
    floorBatch.Draw();   
    
    for(int i = 0; i < NUM_SPHERES; i++) 
    {
        modelViewMatrix.PushMatrix();
        modelViewMatrix.MultMatrix(spheres[i]);
        shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(), 
                                transformPipeline.GetProjectionMatrix(), vLightEyePos, vBlue);
        sphereBatch.Draw();
        modelViewMatrix.PopMatrix();
    }

    // Move our objects into the screen and up, above the floor
    modelViewMatrix.Translate(0.0f, 0.5f, -4.5f);
    // and save
    modelViewMatrix.PushMatrix();
    
    // Apply a rotation and draw the cylinder
    modelViewMatrix.Rotate(90, 1.0f, 0.0, 0.0f);    // make the cylinder stand up
    modelViewMatrix.Rotate(yRot, 0.0f, 0.0f, 1.0f); // spin it
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, 
                                 transformPipeline.GetModelViewMatrix(), 
                                 transformPipeline.GetProjectionMatrix(), 
                                 vLightEyePos, 
                                 vRed);
    cylinderBatch.Draw();
    modelViewMatrix.PopMatrix(); // "Erase" the Rotation from before

    // Apply another rotation, followed by a translation, then draw the sphere
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0f, 0.0f);
    modelViewMatrix.Translate(0.8f,-0.5f, 0.0f);
    shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, 
                                 transformPipeline.GetModelViewMatrix(), 
                                 transformPipeline.GetProjectionMatrix(), 
                                 vLightEyePos, 
                                 vBlue);
    sphereBatch.Draw();

    // Restore the previous modleview matrix (the identity matrix)
    modelViewMatrix.PopMatrix();
    modelViewMatrix.PopMatrix();    
    // Do the buffer Swap
    glutSwapBuffers();
        
    // Tell GLUT to do it again
    glutPostRedisplay();
}

// Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key, int x, int y)
{
    float linear = 0.1f;
    float angular = float(m3dDegToRad(5.0f));
	
    if(key == GLUT_KEY_UP)
    {
        cameraFrame.MoveForward(linear);
    }
    if(key == GLUT_KEY_DOWN)
    {
        cameraFrame.MoveForward(-linear);
    }
    if(key == GLUT_KEY_LEFT)
    {
        cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    }	
    if(key == GLUT_KEY_RIGHT)
    {
        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);		
    }
}

int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
		
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(480,480);
  
    glutCreateWindow("Light");
 
    glutSpecialFunc(SpecialKeys);
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();
    glutMainLoop();    
    return 0;
}

Answer:



Back to index