781 Lab4

 


CSE 781 Lab4 (11 Points)


Environment Mapping using OpenGL fixed pipeline (6pts)  and GLSL (5pts)

Due: March 14, Sunday 11:59pm


In this lab, you will implement environment mapping using OpenGL’s Environment Cube Map texture.  You will implement the same algorithm using two different methods: One is to use OpenGL fixed rendering pipeline (6 points), and the other is to use GLSL (5 points). Very similar results will be generated by the two implementations.


The environment cube map algorithm is fairly straightforward. First, you will define an environment cube map, which consists of 6 images that represent the 6 faces of the environment. To render the scene, for each fragment, from the view vector and the normal, the reflection vector is computed and used to look up the environment cube map texture. The color from the cube map is then assigned to the fragment.


Implementation Details


Setup


To set up an environment cube map, you first create a GL_TEXTURE_CUBE_MAP texture, and then load 6 images into the 6 faces of the cube map:


GL_TEXTURE_CUBE_MAP_POSITIVE_X,

GL_TEXTURE_CUBE_MAP_NEGATIVE_X,

GL_TEXTURE_CUBE_MAP_POSITIVE_Y,

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,

GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z


The following code segment is an example to set up the environment cube map:


  glEnable(GL_TEXTURE_CUBE_MAP);

  glGenTextures(1, &cubemap_texture);

  glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap_texture);

  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_REPEAT);

  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_REPEAT);

  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_REPEAT);

  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,

  GL_LINEAR);

  glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,

  GL_LINEAR);

  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE, GL_REPLACE);

  for (int i=0; i<6; i++) {

    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, 0, GL_RGBA, 256,

256,0, GL_RGBA, GL_UNSIGNED_BYTE,

cubeMap[i]);

  }


  where cubeMap[i], i=0..5, are the 6 images that have already been input from files.



Using Fixed OpenGL Pipeline


To render the environment cube map, OpenGL fixed pipeline can be used. This is done by using OpenGL to generate texture coordinates for each fragment. Previously, you have used OpenGL’s glTexGeni() function to implement shadow maps. For this lab, you will use GL_REFLECTION_MAP_ARB as the texture generation mode. The following code segment is to set up the generation of texture coordinates:


  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);

  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);

  glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);

  glEnable(GL_TEXTURE_GEN_S);

  glEnable(GL_TEXTURE_GEN_T);

  glEnable(GL_TEXTURE_GEN_R);


With this setup, OpenGL will automatically generate the reflection vector for each fragment in eye space as the texture coordinates. You need to convert the eye space reflection vector to world space to create the correct environment reflection in case you will rotate the scene. You can achieve the transformation of the texture coordinates using the GL_TEXTURE matrix. The texture matrix should contain the inverse view matrix.


To enable and disable environment cubemap mapping, you do:


glEnable(GL_TEXTURE_CUBE_MAP);  

glDisable(GL_TEXTURE_CUBE_MAP);


Using GLSL


To implement environment cube map in GLSL, first of all you need to pass the cube map texture to your fragment shader. In GLSL, a cube map texture is called “samplerCube”. For example, you can declare a cube map in your fragment shader as:


  uniform samplerCube cubeMap;


Where the cubeMap is a uniform variable representing the cube map texture.

The way you pass the cubemap texture to your GLSL shader is pretty much the same as you pass a regular texture. For example, assuming you have the code above in the setup section to create a cube map texture, you just need to add:


  GLint loc;

  loc = glGetUniformLocation(programObject, "cubeMap");

  glUniform1i(loc, 0);


where “cubeMap” is the name of the uniform variable in your fragment shader, and you associate it to your texture unit 0.


When you use GLSL, the cube map lookup should be done in your fragment shader. You need to calculate the reflection vector by yourself, instead of using the generated texture coordinates. GLSL provides a function ‘reflect(L1, L2)’ to compute the reflection vector, where L1 is a view vector from the camera to the fragment,  and L2 is the fragment normal. With the reflection vector, you can perform a cube map texture lookup as:


  vec4 color = textureCube(cubeMap, reflection);


where cubeMap is the cubemap texture, and reflection is the reflection vector. Note that if the reflection vector is calculated in eye space, you need to transform it to the world space like what you need to do in the fixed opengl pipeline. You can do this by multiplying the reflection vector with the opengl texture matrix. You can set up the texture matrix the same way as in the fixed OpenGL pipeline. In GLSL, the texture matrix can be accessed through gl_TextureMatrix[i] (for texture 0, it is gl_TextureMatrix[0], for example)


Lab Requirements


Do the following in your lab4


(1)Draw 6 walls to represent your environment, and map the 6 face textures of the cube map to the walls. This is done through the regular GL_TEXTURE_2D texture mapping, not the environment cube map. You should only use the fixed OpenGL pipeline to do this. Make sure that the images are correctly mapped to the wall so that they match on the wall boundaries.

(2)Draw some geometric objects with at least one sphere, one cube, and one ply model in the scene, and perform environment mapping on those objects. When drawing the walls and the objects, you need to make sure that the reflections on the objects and the images on the walls are consistent. By this, I mean if a point is facing to the positive x direction, for example, it should reflect the image from the positive X wall.

(3)Be able to rotate the scene globally. You need to make sure that the reflections are correct as the scene is rotated. For example, since you are rotating the environment globally, how the objects reflect the environment should remain the same.

(4)Use key stroke ‘s’ to toggle between your OpenGL fixed pipeline implementation and   the GLSL implementation. The results should be almost the same.



Where to find the environment cubemaps?


You can also find many on line. For example, this link:


http://www.codemonsters.de/home/content.php?show=cubemaps


have some good ones.



Submit


You need to remember to submit your environment cubemap with your source code so that we can run your program.