Pythonstuff GLSL in English Pythonstuff GLSL auf Deutsch Pythonstuff GLSL Pythonstuff
PythonStuff Home
 

 

Environmental Bump Mapping with GLSL Cube Mapping

The program

The textures used in this demo are here:

  • textures4.zip File (unpack the directory “textures” in the directory where you keep the “env_bump_map.py” file)

The Museum environment texture is taken from http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/stereographics/stereopanoramic/, curtesy by Peter Murphy.

The result looks like this:

Environmental Cube Mapped Ball Environmental Cube Mapped Ball - with bumps and texture Environmental Cube Mapped Torus

Program description

To create a reflecting sphere (optionally with a rough surface), we display a cube map on the surface of the sphere. Which point in the six square textures of the cube is displayed on a certain spot on the sphere determined by the reflected eye vector. This reflection calculation is controlled by the surface normal vector - and therefore can be easily manipulated by a bumpmap shown in a previous example.

We define the key “Z” for switching the Bumpmap on and off, and the keys “N” and “B” (conviniently located next to each other on the keyboard) to control the intensity of the effect:

elif symbol == key.Z:
    togglebump = not togglebump
    print 'Toggle Bump ', togglebump
elif symbol == key.N:
    normalweight += 0.05
    print 'Normal Weight = ', normalweight
elif symbol == key.B:
    normalweight -= 0.05
    print 'Normal Weight = ', normalweight

The mirrored image can optionally made “dirty” or “scratched” by a classic texture map, toggled by the “T”-key:

elif symbol == key.T:
    print 'Texture toggle'
    textureon = not textureon

Finally we want to zoom in and out (”+” and ”-” keys):

elif symbol == key.PLUS:
    dist += 0.5
    print 'Distance now ', dist
elif symbol == key.MINUS:
    dist -= 0.5
    print 'Distance now ', dist

The Cube Map

The cube map occupies 6 consecutive texture indices we reserve in one step (after the “texturecnt” maps we used up to now).

We tell the shader program the index of the reservation:

glActiveTexture(GL_TEXTURE0+texturecnt)
glEnable(GL_TEXTURE_CUBE_MAP)
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap)
shader.uniformi('my_cube_texture', texturecnt)

and load the images:

glEnable(GL_TEXTURE_CUBE_MAP)
cubemap = GLuint()
glGenTextures( 1, byref(cubemap))
cubemap = cubemap.value
print "CubeTexture is bound to", cubemap
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR ) #  GL_NEAREST)
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR ) #  GL_NEAREST)
cubename = ['cube_map_positive_x.jpg', 'cube_map_negative_x.jpg',
            'cube_map_negative_y.jpg', 'cube_map_positive_y.jpg',
            'cube_map_negative_z.jpg', 'cube_map_positive_z.jpg']
for i in range (6):
    cubefile = cubename[i]
    print "Loading Cube Texture", cubefile
    cube = resource.texture(cubefile) # instance of class AbstractImage
    data = cube.get_image_data().get_data('RGBA', cube.width * 4)
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
             GL_RGBA8, # texture.format, # 0,   # format
             cube.width,
             cube.height,
             0,
             GL_RGBA, GL_UNSIGNED_BYTE,
             data)
glDisable(GL_TEXTURE_CUBE_MAP)

The Shader Program

We declare the cube map in the shader program by:

uniform samplerCube my_cube_texture;

and access it (again we use the Tangent Space Coordinate System - this makes the calculations surprisingly easy):

vec3 refl = reflect(norm, eye);  // in tangent space !
vec3 reflw = vec3( 1.0, -1.0, 1.0) * (TBNMatrix * refl);
reflex = textureCube(my_cube_texture, reflw);
if ( textureon > 0 )
  gl_FragColor = mix( reflex, vec4(color, 1.0), smoothstep( 0.7, 1.5, length(color)) );
else
  gl_FragColor = reflex;

The brighter the “color” value is, the more it overrides the “reflex” color. So a black Texture Image would represent a perfect mirror, while a white image would hide the reflections completely (see the “pythonstuff”-Label on the screenshot).

Now let's go crazy: Example 9 - adding realtime video !

(have you seen Example 7 - Anisotropic Specular Highlights ?)


Deutschsprachige Version, Start
Impressum & Disclaimer