CS 457/557 -- Winter Quarter 2024

Project #4

Cube Mapping Reflective and Refractive Bump-mapped Surfaces

100 Points

Due: February 14


This page was last updated: January 11, 2024


Reflection Refraction

Requirements:

  1. The goal of this project is to use cube-mapping to create a reflective and refractive display of a bump-mapped math function.

  2. Use the same math function you used in Project #3.

  3. You need to show the effect of the parameters for the math function (uA, uB, uD).

  4. You niied to show the effect of the uMix parameter to blend the reflective and refractive versions of the scene as we did with the cube-mapping example in class.

  5. Create an index of refraction parameter, uEta, but it can be hard-coded. A good range for uEta is 1. - 2.5

  6. Don't do any lighting. Just use the output from the cube map.

  7. You can use the NVIDIA cube map, the Kelley cube map, or any other cube maps you find.

  8. You can have as many other uniform variables as you wish.

ParameterWhat It DoesHas To Be Varied?
uARipple amplitudeYes
uBRipple frequencyYes
uDRipple decayNo
uNoiseAmpNoise AmplitudeYes
uNoiseFreqNoise FrequencyYes
uEtaIndex of refractionNo
uMixMixing of reflection and refractionYes
uWhiteMixMixing of WHITE with the refractionNo

A Template Glib File

##OpenGL GLIB
Perspective 70
LookAt 0 0 3  0 0 0  0 1 0

CubeMap 6 nvposx.bmp nvnegx.bmp  nvposy.bmp nvnegy.bmp   nvposz.bmp nvnegz.bmp

CubeMap 7 nvposx.bmp nvnegx.bmp  nvposy.bmp nvnegy.bmp   nvposz.bmp nvnegz.bmp

Vertex		ripplecube.vert
Fragment	ripplecube.frag
Program    	RippleCube			\
           	uReflectUnit 6             	\
           	uRefractUnit 7             	\
		uA < ? ? ?>			\
		uB < ? ? ?>			\
		uD 0.5				\
        	uNoiseAmp <0. 0. 5.>		\
        	uNoiseFreq <0.0 0.1 0.5>	\
		uEta 1.2			\
		uMix <0. 0. 1.>			\
		uWhiteMix 0.3

PushMatrix
Rotate -15   1 0 0
QuadXY  -0.2  2.  300 300
PopMatrix

A Template for a C/C++ Program using the API

GLSLProgram Pattern;
GLuint CubeName;
char * FaceFiles[6] =
{
	"kec.posx.bmp",
	"kec.negx.bmp",
	"kec.posy.bmp",
	"kec.negy.bmp",
	"kec.posz.bmp",
	"kec.negz.bmp"
};

. . .

void
InitGraphics( )
{
	// open the window . . .
	// setup the callbacks . . .
	// initialize glew . . .
	// create and compile the shader . . .
	glGenTextures( 1, &CubeName );
	glBindTexture( GL_TEXTURE_CUBE_MAP, CubeName );
	glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT );
	glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT );
	glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameterf( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	for( int file = 0; file < 6; file++ )
	{
		int nums, numt;
		unsigned char * texture2d = BmpToTexture( FaceFiles[file], &nums, &numt );
		if( texture2d == NULL )
			fprintf( stderr, "Could not open BMP 2D texture '%s'", FaceFiles[file] );
		else
			fprintf( stderr, "BMP 2D texture '%s' read -- nums = %d, numt = %d\n", FaceFiles[file], nums, numt );
		glTexImage2D( GL_TEXTURE_CUBE_MAP_POSITIVE_X + file, 0, 3, nums, numt, 0,
			GL_RGB, GL_UNSIGNED_BYTE, texture2d );
		delete [ ] texture2d;
	}

. . .

void
Display( )
{
	. . .
	int ReflectUnit = 5;
	int RefractUnit = 6;
	float Ad = 0.1f;
	float Bd = 0.1f;
	float Eta = 1.4f;
	float Mix = 0.4f;

	Pattern.Use( );
	glActiveTexture( GL_TEXTURE0 + ReflectUnit );
	glBindTexture( GL_TEXTURE_CUBE_MAP, CubeName );
	glActiveTexture( GL_TEXTURE0 + RefractUnit );
	glBindTexture( GL_TEXTURE_CUBE_MAP, CubeName );
	Pattern.SetUniformVariable( "uReflectUnit", ReflectUnit );
	Pattern.SetUniformVariable( "uRefractUnit", RefractUnit );
	Pattern.SetUniformVariable( "uMix", Mix );
	Pattern.SetUniformVariable( "uEta", Eta )
	glCallList( GridOfQuadsList );
	Pattern.UnUse;
}

A Template Vertex Shader File

#version 330 compatibility

uniform float uA, uB, uD;

out vec3	vNs;
out vec3	vEs;
out vec3	vMC;


void
main( )
{    
	vMC = gl_Vertex.xyz;
	vec4 newVertex = gl_Vertex;
	float r = ?????
	newVertex.z = ?????

	vec4 ECposition = gl_ModelViewMatrix * newVertex;

	float dzdr = ?????
	float drdx = ?????
	float drdy = ?????
	float dzdx = ?????
	float dzdy = ?????
	vec3 xtangent = ?????
	vec3 ytangent = ?????

	vec3 newNormal = ?????
	vNs = newNormal;
	vEs = ECposition.xyz - vec3( 0., 0., 0. ) ; 
	       		// vector from the eye position to the point

	gl_Position = gl_ModelViewProjectionMatrix * newVertex;
}

A Template Fragment Shader

#version 330 compatibility

uniform sampler3D	Noise3;
uniform float 		uNoiseAmp;
uniform float 		uNoiseFreq;
uniform float		uEta;
uniform float 		uMix;
uniform float 		uWhiteMix;
uniform samplerCube uReflectUnit;
uniform samplerCube uRefractUnit;

in vec3	vMC;
in vec3	vNs;
in vec3	vEs;

const vec3  WHITE = vec3( 1.,1.,1. );

vec3
RotateNormal( float angx, float angy, vec3 n )
{
	float cx = cos( angx );
	float sx = sin( angx );
	float cy = cos( angy );
	float sy = sin( angy );
	
	// rotate about x:
	float yp =  n.y*cx - n.z*sx;	// y'
	n.z      =  n.y*sx + n.z*cx;	// z'
	n.y      =  yp;
	// n.x      =  n.x;

	// rotate about y:
	float xp =  n.x*cy + n.z*sy;	// x'
	n.z      = -n.x*sy + n.z*cy;	// z'
	n.x      =  xp;
	// n.y      =  n.y;

	return normalize( n );
}


void
main( )
{
	vec3 Normal = ?????	// remember to unitize this
	vec3 Eye =    ?????	// remember to unitize this

	vec4 nvx = texture( Noise3, uNoiseFreq*vMC );
	vec4 nvy = texture( Noise3, uNoiseFreq*vec3(vMC.xy,vMC.z+0.5) );

	float angx = nvx.r + nvx.g + nvx.b + nvx.a;	//  1. -> 3.
	angx = angx - 2.;				// -1. -> 1.
	angx *= uNoiseAmp;

	float angy = nvy.r + nvy.g + nvy.b + nvy.a;	//  1. -> 3.
	angy = angy - 2.;				// -1. -> 1.
	angy *= uNoiseAmp;

	Normal = RotateNormal( angx, angy, Normal );
	Normal = normalize( gl_NormalMatrix * Normal );

	vec3 reflectVector = ?????
	vec3 reflectColor = ?????.rgb

	vec3 refractVector = ?????

	vec3 refractColor;
	if( all( equal( refractVector, vec3(0.,0.,0.) ) ) )
	{
		refractColor = reflectColor;
	}
	else
	{
		refractColor = texture( uRefractUnit, refractVector ).rgb;
		refractColor = mix( refractColor, WHITE, uWhiteMix );
	}
	gl_FragColor = mix( ?????
}

texture.vert and texture.frag

These are only used for wall decorations. They don't actually participate in the cube mapping, but the cube mapping looks weird without them.

texture.vert:


#version 330 compatibility

out vec2	vST;

void
main( )
{
	vST = gl_MultiTexCoord0.st;
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

texture.frag:


#version 330 compatibility

uniform sampler2D TexUnit;

in vec2		vST;

void main( )
{
	vec3 newcolor = texture( TexUnit, vST ).rgb;
	gl_FragColor = vec4( newcolor, 1. );
}

The Turn-In Process:

The turnin for this project will be all of the source files and a PDF report containing:

This needs to be a PDF file turned into Teach with your other files. Be sure to keep your PDF outside your .zip file so I can gather up all the PDF files at once with a script.

Where to Get Cube Map Images

Want to use the Nvidia Lobby in a cube map? Here are the files:
nvposx.bmp
nvnegx.bmp
nvposy.bmp
nvnegy.bmp
nvposz.bmp
nvnegz.bmp

Want to use the Kelley Engineering Center Atrium in a cube map? Here are the files:
kec.posx.bmp
kec.negx.bmp
kec.posy.bmp
kec.negy.bmp
kec.posz.bmp
kec.negz.bmp

Grading:

FeaturePoints
Displaces correctly15
Bump-maps correctly15
Refracts correctly30
Reflects correctly30
Mixes the reflective and refractive correctly10
Potential Total100