## Project #6

### Introduction:

The goal of this project is to create an animated ellipse pattern by using an OpenGL fragment shader. The center of the ellipse will be animated using the KeyTime method you already know. The S-radius and T-radius will be animated using the Time variable and some functions that you invent. Light the object using per-fragment lighting.

Note: the reason this pattern looks more teardrop-shaped than ellipse-shaped is that the nature of spheres is to distort patterns near the poles. That Mercator-projection map you always had in the front of the classroom in middle and high school showed this effect in how greatly it distorted the size of Greenland.

The circle equation is explained here:

The ellipse equation is explained here:

### Learning Objective:

When you are done with this assignment, you will understand how to create a GPU-program, known as a shader. Your shader will let you dynamically alter a color pattern on an arbitrary object. Today's games and movies employ hundreds of shader programs to get the variety of special effects they need. This assignment will also set you up to succeed in CS 457/557, our shaders course which you will be able to take in the Winter Quarter.

### Hints:

• The Head Start code in this handout is a complete implementation of the gold-sphere-red-square example from the shader notes. Nothing left out, no question marks. I recommend you start with this. Compile it. It should run. Then make the ellipse changes.
• You don't need to compile pattern.vert and pattern.frag yourself. Don't try including them in your Makefile or in your Visual Studio solution! The line of sample.cpp code: Pattern.Create( ... ) does the compile for you.
• In the gold-sphere-red-square example code, there are 3 uniform variables that get passed to your shaders each time Display is called. They are there to tell the fragment shader how and where to draw the square.
• For the ellipse, you will need 4 uniform variables, a different 4 than any from the sample code. The 3 uniform variables from the sample code won't help you draw an ellipse.

If you are getting undefined reference messages on GLEW:
• Install the 'glew' package using the command "sudo apt-get install libglew-dev"
• Remove #ifdef WIN32 in InitGraphics()
• g++ -o sample sample.cpp -g -I. -lGL -lGLU -lglut -lGLEW -lm

• For Apple Mac shader users:
• In all .cpp files, be sure all #include <GL/anything> have been changed to #include <OpenGL/anything>
• In all .cpp and .h files, be sure all #include "glew.h" lines have been eliminated
• In the pattern.* shader files, comment out the #version line at the top
• In the pattern.* shader files, change all out declarations to varying
• In the pattern.* shader files, change all in declarations to varying

### Instructions:

1. Draw a 3D object (your choice). Be sure that it has (s,t) texture coordinates in it. All of the osu* geometry functions do.

2. Use the GLSLProgram C++ class to create a shader from the pattern.vert and pattern.frag files.

3. Write a pattern.vert vertex shader that transforms the vertex and passes, to the fragment shader, the vST texture coordinates, the vN normal vector, the vE eye vector, and the vL light vector.

4. Write a fragment shader that accepts, from the vertex shader, the vST texture coordinates, the vN normal vector, the vE eye vector, and the vL light vector.

5. The fragment shader also needs to read in, from the uniform variables, the per-fragment lighting information, uKa, uKd, uKs, uColor, uSpecularColor, and uShininess. These can be set once after the shader has been created and left alone after that. InitGraphics( ) is a good place to do this.

6. The fragment shader also needs to read in, from the uniform variables, the ellipse center uSc and uTc, and the ellipse radii uRs and uRt. These will be set every time Display( ) is called.

7. The first half of the fragment shader needs to look at that fragment's vST texture coordinates and decide, from the ellipse equation, if that fragment gets the ellipse color or the rest-of-the-object color.

8. The second half of the fragment shader applies per-fragment lighting to that chosen color.

9. Use the SetUniformVariable( ) method to set the uniform variables.

10. Use the in and out keywords to pass 4 variabes from the vertex shader to the fragment shader. Those 4 variables will be interpolated in the rasterizer so that each fragment gets its own copy of them.

11. The choice of colors is up to you.

12. For the keytime-varying ellipse center, pick at least 4 keytime positions for Sc and Tc. Remember that they need to be between 0. and 1.

13. For the Time-varying ellipse center, some equations that will cause the Rs and Rt variables to stretch and shrink. Sine functions work well here, but you can choose anything that works. Remember that these need to be between 0. and 1.

14. You must have the ability to show the pattern animating and not animating. One way to control this is with keyboard keys:
 'k' Toggle the keytime-based animation on and off 't' Toggle the Time-based animation on and off

### The GLSLProgram C++ class

The glslprogram.h and glslprogram.cpp files are already in your Sample folder. You just need to un-comment their #include's.

See the class Shader notes for how to use them.

### Per-Fragment Lighting

You need to do per-fragment lighting.
Here is what needs to be added to the vertex shader code to enable per-fragment lighting:

```// make this 120 for the mac:
#version 330 compatability

// out variables to be interpolated in the rasterizer and sent to each fragment shader:

out  vec3  vN;		// normal vector
out  vec3  vL;		// vector from point to light
out  vec3  vE;		// vector from point to eye
out  vec2  vST;		// (s,t) texture coordinates

// where the light is:

const vec3 LightPosition = vec3(  0., 5., 5. );

void
main( )
{
vST = gl_MultiTexCoord0.st;
vec4 ECposition = gl_ModelViewMatrix * gl_Vertex;
vN = normalize( gl_NormalMatrix * gl_Normal );	// normal vector
vL = LightPosition - ECposition.xyz;		// vector from the point
// to the light position
vE = vec3( 0., 0., 0. ) - ECposition.xyz;	// vector from the point
// to the eye position
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
```

Here is what needs to be added to the fragment shader code to enable per-fragment lighting:

```// make this 120 for the mac:
#version 330 compatability

// lighting uniform variables -- these can be set once and left alone:
uniform float   uKa, uKd, uKs;		// coefficients of each type of lighting -- make sum to 1.0
uniform vec3    uColor;			// object color
uniform vec3    uSpecularColor;		// light color
uniform float   uShininess;		// specular exponent

// ellipse-equation uniform variables -- these should be set every time Display( ) is called:

uniform float	uSc, uTc;
uniform float	uRs, uRt;

// in variables from the vertex shader and interpolated in the rasterizer:

in  vec3  vN;			// normal vector
in  vec3  vL;			// vector from point to light
in  vec3  vE;			// vector from point to eye
in  vec2  vST;			// (s,t) texture coordinates

void
main( )
{
vec3 Normal = normalize(vN);
vec3 Light  = normalize(vL);
vec3 Eye    = normalize(vE);
float s = vST.s;
float t = vST.t;

// determine the color using the ellipse equation:

vec3 myColor = uColor;
if( ??? )
{
myColor = ???;
}

// apply the per-fragmewnt lighting to myColor:

vec3 ambient = uKa * myColor;

float d = max( dot(Normal,Light), 0. );       // only do diffuse if the light can see the point
vec3 diffuse = uKd * d * myColor;

float s = 0.;
if( dot(Normal,Light) > 0. )	          // only do specular if the light can see the point
{
vec3 ref = normalize(  reflect( -Light, Normal )  );
s = pow( max( dot(Eye,ref),0. ), uShininess );
}
vec3 specular = uKs * s * uSpecularColor;
gl_FragColor = vec4( ambient + diffuse + specular,  1. );
}
```

So, the first half of the fragment shader determines the color to use based on if that fragment is inside the pattern or not. The second half of the fragment shader code uses that color in the per-fragment lighting. The final value assigned to gl_FragColor will be an RGBA that has both the pattern color and the lighting intensity.

### Turning Animation Effects On and Off

I recommend that you pass in your pattern parameters as uniform variables and just control when you give them new values. Thus, in Display( ), you might say:

```
Pattern.Use( );
if( KeytimePatternOn )
{
float sc = Sc.GetValue( Time );
float tc = Tc.GetValue( Time );
}
if( TimePatternOn )
{
float rs = << some function of the Time variable >>
float rt = << some function of the Time variable >>
}
Pattern.SetUniformVariable( "uSc", sc );
Pattern.SetUniformVariable( "uTc", tc );
Pattern.SetUniformVariable( "uRs", rs );
Pattern.SetUniformVariable( "uRt", rt );

<< do the drawing >>

Pattern.UnUse( );	// Pattern.Use(0);  also works
```

### Turn-in:

Use the Teach system to turn in your:

1. .cpp file
2. .vert file
3. .frag file
4. A PDF report containing:
• Project number and title