5. GLSL Per Pixel Lighting

Jump To:

main.cpp Source
shader.vert Source
shader.frag Source
Download

This tutorial is going to be quite simple. To achieve the effect of per pixel lighting, we simply need to move one calculation from our vertex shader to our fragment shader.

So lets go to it!

Main.CPP File:

Just for the sake of it, I have switched to a glutSolidTeapot for this tutorial. It will come on handy when testing different effects.

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
    #if ( (defined(__MACH__)) && (defined(__APPLE__)) )   
#include <stdlib.h>
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#include <OpenGL/glext.h>
#else
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glext.h>
#endif

#include “shader.h”

Shader shader;

GLfloat angle = 0.0; //set the angle of rotation

//diffuse light color variables
GLfloat dlr = 1.0;
GLfloat dlg = 1.0;
GLfloat dlb = 1.0;

//ambient light color variables
GLfloat alr = 0.0;
GLfloat alg = 0.0;
GLfloat alb = 0.0;

//light position variables
GLfloat lx = 0.0;
GLfloat ly = 1.0;
GLfloat lz = 1.0;
GLfloat lw = 0.0;

void init(void) {
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    
    shader.init(“shader.vert”, “shader.frag”);
}

void cube (void) {
    glRotatef(angle, 1.0, 0.0, 0.0); //rotate on the x axis
    glRotatef(angle, 0.0, 1.0, 0.0); //rotate on the y axis
    glRotatef(angle, 0.0, 0.0, 1.0); //rotate on the z axis
    glColor4f(1.0, 0.0, 0.0, 1.0);
    glutSolidTeapot(2);
}

void setLighting(void) {
    GLfloat DiffuseLight[] = {dlr, dlg, dlb}; //set DiffuseLight[] to the 
specified values

    GLfloat AmbientLight[] = {alr, alg, alb}; //set AmbientLight[] to the 
specified values

    
    glLightfv (GL_LIGHT0, GL_DIFFUSE, DiffuseLight); //change the light
 accordingly

    glLightfv (GL_LIGHT0, GL_AMBIENT, AmbientLight); //change the light
 accordingly

    
    GLfloat LightPosition[] = {lx, ly, lz, lw}; //set the LightPosition to 
the specified values

    
    glLightfv (GL_LIGHT0, GL_POSITION, LightPosition); //change the 
light accordingly

}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();  
    gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    
    setLighting();
    
    shader.bind();
    cube();
    shader.unbind();
    
    glutSwapBuffers();
    angle += 0.01f;
}

void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}

int main (int argc, char **argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); //set up
 the double buffering

    glutInitWindowSize(500, 500);
    glutInitWindowPosition(100, 100);
    glutCreateWindow(“A basic OpenGL Window);
    
    glewInit();

    glutDisplayFunc(display);
    glutIdleFunc(display);
    
    glutReshapeFunc(reshape);
    
    init();
    
    glutMainLoop();
    
    return 0;
}

Vertex Shader Source:

In the last tutorial, to achieve lighting, we had one varying variable called diffuse_value. In this tutorial, we are going to remove this varying, and create two others. One of them is going to contain the vertex_light_position, and the other is going to contain the vertex_normal:

varying vec3 vertex_light_position;
varying vec3 vertex_normal;

Now we need to store some values in here. This is collected the exact same way as last time:

    vertex_normal = normalize(gl_NormalMatrix * gl_Normal);

    vertex_light_position = normalize(gl_LightSource[0].position.xyz);

And that’s all their is in the vertex shader. Note that I have removed the diffuse_value variable.

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
    varying vec3 vertex_light_position;
varying vec3 vertex_normal;

void main() {            
    // Calculate the normal value for this vertex, in world coordinates (
multiply by gl_NormalMatrix)

    vertex_normal = normalize(gl_NormalMatrix * gl_Normal);
    // Calculate the light position for this vertex
    vertex_light_position = normalize(gl_LightSource[0].position.xyz);

    // Set the front color to the color passed through with glColor*f
    gl_FrontColor = gl_Color;
    // Set the position of the current vertex 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

 

Fragment Shader Source:

Since I changed the varying variables in the Vertex Shader, I also need to update them in the fragment shader:

varying vec3 vertex_light_position;
varying vec3 vertex_normal;

Now, if you remember the diffuse_value calculation from the previous tutorial, it has been pretty much copied and pasted into this tutorial, only now it resides inside the fragment shader:

    float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);

And that is all their is to it. We now have per pixel lighting. That wasn’t too hard 🙂

If you have any questions, please email me at swiftless@gmail.com

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

    varying vec3 vertex_light_position;
varying vec3 vertex_normal;

void main() {
    // Set the diffuse value (darkness). This is done with a dot product between
 the normal and the light

    // and the maths behind it is explained in the maths section of the site.
    float diffuse_value = max(dot(vertex_normal, vertex_light_position), 0.0);

    // Set the output color of our current pixel
    gl_FragColor = gl_Color * diffuse_value;
}

 

Download:

Download shader.h Source Code for this Tutorial

Download shader.cpp Source Code for this Tutorial

Download main.cpp Source Code for this Tutorial

Download shader.vert Source Code for this Tutorial

Download shader.frag Source Code for this Tutorial

  • March 25, 2010
  • 10