Program 7

Program 7: Fragment Shader: Textures

Due: Thursday, November 18th, 2010 (before class begins)

In this programming assignment, you will create a fragment shader that allows you to use textures in GLSL. Being able to use textures in GLSL opens the door to a number of really fancy screen-space post-processing techniques with multipass rendering, such as bloom effects, motion blur, volumetric lighting, and more.

Your base code for this assignment consists of a single quad and a simple brick texture. You can press 't' to cycle through 3 different rendering modes: no textures, texturing with OpenGL, and texturing with GLSL. Currently, there are no shaders attached, so texturing with GLSL does nothing. Your task is to write and appropriately setup two shaders: a vertex shader, which transforms the vertices as usual and passes along texture coordinates, and a fragment shader, which uses those texture coordinates to obtain the final fragment color from a texture sampler in GLSL.

NOTE: GLSL can be very touchy, and the best way to save time debugging is to avoid mistakes in the first place. Some big stumbling blocks:

The base code can be found at pgm_07.tar.gz.

You are expected to place your name in the main.cpp source file and comment any code you add or modify.

Getting Started

As with the lab assignment, your first step should be to get and attach simple dummy vertex and fragment shaders. For starters, just render the wall as a solid red color, or pass gl_Color through to the fragment shader. Verify that you have the dummy shader programs attached and working properly before you continue.

Textures in GLSL

Textures in GLSL work almost the same as textures in straight OpenGL: you have to initialize your textures in the same way, get a handle to your texture data, pass the texture image to the GPU with glTexImage2D, give your object texture coordinates, etc. You don't even need to pass the texture handle to the GPU as a uniform -- by default, any texture samplers you make will refer to whatever texture is bound to the first texture unit. (The only time that this is not the case is with multitexturing.)

In your fragment shader, you will need to declare your texture sampler:

uniform sampler 2D tex;

And you can access the value of the texture at the current texture coordinates with:

vec4 textureColor = texture2D(tex, gl_TexCoord[0].xy);

However, since texture coordinates are interpolated across vertices, they must be set in the vertex shader (since we replaced the part of the pipeline that normally does this for us):

gl_TexCoord[0] = gl_MultiTexCoord0;

At this point, you should be able to set the fragment color and get texturing through GLSL. When you toggle through texturing modes with 't,' you should see no difference between OpenGL texturing and GLSL texturing.

Controlled Texture Modulation

With OpenGL textures, you've done about as much as you can do; you can modulate the texture color with the object's color after lighting, but that's about it. Since you have control over the final color of a fragment in the shader, you can do much more with it. The last step of this assignment is to control the modulation based on time, such that the texture fades in and out, leaving the color of the object when it is not visible.

To achieve this, add a uniform to your fragment shader that will hold the elapsed time, as in lab 7. Query the uniform's location after the shaders have been compiled, pass in the time with GLUT_ELAPSED_TIME, and use sin(time) to blend between the original gl_Color and the texture color. (Hint: use linear interpolation. Don't just use sin(time) -- that varies from [-1 to 1]. Scale that value to the range of [0, 1] and then use it as your linear interpolant.)

When GLSL texturing is enabled, your texture should pulse in and out of visibility:

pgm_07/texture_visible.png pgm_07/texture_pseudovisible.png

Submission

Place the source code, a Makefile, and a README, all with your name, in your course dropbox:

/afs/nd.edu/coursefa.10/cse/cse40166.01/dropbox/<afsid>/pgm7