Выбрать главу

  delete Image;

  Image=NULL;

 }

 // Load The "Extension Enabled"-Logo

 if (Image=auxDIBImageLoad("Data/multi_on_alpha.bmp")) {

  alpha=new char[4*Image->sizeX*Image->sizeY]; // Create Memory For RGBA8-Texture

  >…<

  glGenTextures(1, &multiLogo); // Create One Textures

  // Create Linear Filtered RGBA8-Texture

  >…<

  delete alpha;

 } else status=false;

 if (Image) { // If Texture Exists

  if (Image->data) delete Image->data; // If Texture Image Exists

  delete Image;

  Image=NULL;

 }

 return status; // Return The Status

}

Next comes nearly the only unmodified function ReSizeGLScene(). I've omitted it here. It is followed by a function doCube() that draws a cube, complete with normalized normals. Note that this version only feeds texture-unit #0, since glTexCoord2f(s,t) is the same thing as glMultiTexCoord2f(GL_TEXTURE0_ARB,s,t). Note also that the cube could be done using interleaved arrays, but this is definitely another issue. Note also that this cube CAN NOT be done using a display list, since display-lists seem to use an internal floating point accuracy different from GLfloat. Since this leads to several nasty effects, generally referred to as "decaling"-problems, I kicked display lists. I assume that a general rule for multipass algorithms is to do the entire geometry with or without display lists. So never dare mixing even if it seems to run on your hardware, since it won't run on any hardware!

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window

>…<

void doCube (void) {

 int i;

 glBegin(GL_QUADS);

  // Front Face

  glNormal3f( 0.0f, 0.0f, +1.0f);

  for (i=0; i<4; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

  // Back Face

  glNormal3f( 0.0f, 0.0f,-1.0f);

  for (i=4; i<8; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

  // Top Face

  glNormal3f( 0.0f, 1.0f, 0.0f);

  for (i=8; i<12; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

  // Bottom Face

  glNormal3f( 0.0f,-1.0f, 0.0f);

  for (i=12; i<16; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

  // Right Face

  glNormal3f( 1.0f, 0.0f, 0.0f);

  for (i=16; i<20; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

  // Left Face

  glNormal3f(-1.0f, 0.0f, 0.0f);

  for (i=20; i<24; i++) {

   glTexCoord2f(data[5*i],data[5*i+1]);

   glVertex3f(data[5*i+2],data[5*i+3],data[5*i+4]);

  }

 glEnd();

}

Time to initialize OpenGL. All as in Lesson 06, except that I call initLights() instead of setting them here. Oh, and of course I'm calling Multitexture-setup, here!

int InitGL(GLvoid) // All Setup For OpenGL Goes Here

{

 multitextureSupported=initMultitexture();

 if (!LoadGLTextures()) return false; // Jump To Texture Loading Routine

 glEnable(GL_TEXTURE_2D); // Enable Texture Mapping

 glShadeModel(GL_SMOOTH); // Enable Smooth Shading

 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background

 glClearDepth(1.0f); // Depth Buffer Setup

 glEnable(GL_DEPTH_TEST); // Enables Depth Testing

 glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do

 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations

 initLights(); // Initialize OpenGL Light

 return true // Initialization Went OK

}

Here comes about 95% of the work. All references like "for reasons discussed later" will be solved in the following block of theory.

Begin Theory (Emboss Bump Mapping)

If you have a Powerpoint-viewer installed, it is highly recommended that you download the following presentation:

"Emboss Bump Mapping" by Michael I. Gold, nVidia Corp. [.ppt, 309K]

For those without Powerpoint-viewer, I've tried to convert the information contained in the document to .html-format. Here it comes:

Emboss Bump Mapping

Michael I. Gold

NVidia Corporation

Bump Mapping

Real Bump Mapping Uses Per-Pixel Lighting.

• Lighting calculation at each pixel based on perturbed normal vectors.

• Computationally expensive.

• For more information see: Blinn, J. : Simulation of Wrinkled Surfaces, Computer Graphics. 12,3 (August 1978) 286-292.

• For information on the web go to: http://www.objectecture.com/ to see Cass Everitt's Orthogonal Illumination Thesis. (rem.: Jens)

Emboss Bump Mapping

Emboss Bump Mapping Is A Hack

• Diffuse lighting only, no specular component

• Under-sampling artefacts (may result in blurry motion, rem.: Jens)

• Possible on today's consumer hardware (as shown, rem.: Jens)

• If it looks good, do it!

Diffuse Lighting Calculation

C=(L*N) × Dl × Dm

• L is light vector

• N is normal vector

• Dl is light diffuse color

• Dm is material diffuse color

• Bump Mapping changes N per pixel

• Emboss Bump Mapping approximates (L*N)

Approximate Diffuse Factor L*N

Texture Map Represents Heightfield

• [0,1] represents range of bump function

• First derivate represents slope m (Note that m is only 1D. Imagine m to be the inf.-norm of grad(s,t) to a given set of coordinates (s,t)!, rem.: Jens)

• m increases / decreases base diffuse factor Fd

• (Fd+m) approximates (L*N) per pixel

Approximate Derivative

Embossing Approximates Derivative

• Lookup height H0 at point (s,t)

• Lookup height H1 at point slightly perturbed toward light source (s+ds,t+dt)

• Subtract original height H0 from perturbed height H1

• Difference represents instantaneous slope m=H1-H0

Compute The Bump

1) Original bump (H0).

2) Original bump (H0) overlaid with second bump (H1) slightly perturbed toward light source.