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

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

   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, data[5*i]+c[0], data[5*i+1]+c[1]);

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

  }

  // Left Face

  n[0]=-1.0f;

  n[1]=0.0f;

  n[2]=0.0f;

  s[0]=0.0f;

  s[1]=0.0f;

  s[2]=1.0f;

  t[0]=0.0f;

  t[1]=1.0f;

  t[2]=0.0f;

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

   c[0]=data[5*i+2];

   c[1]=data[5*i+3];

   c[2]=data[5*i+4];

   SetUpBumps(n,c,l,s,t);

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

   glMultiTexCoord2fARB(GL_TEXTURE1_ARB, data[5*i]+c[0], data[5*i+1]+c[1]);

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

  }

 glEnd();

Second Pass

• Use the base-texture

• Enable Lighting

• No offset texturre-coordinates → reset GL_TEXTURE-matrix

• Reset texture environment to GL_MODULATE in order to do OpenGLLighting (doesn't work otherwise!)

This will render our complete bump-mapped cube.

 glActiveTextureARB(GL_TEXTURE1_ARB);

 glDisable(GL_TEXTURE_2D);

 glActiveTextureARB(GL_TEXTURE0_ARB);

 if (!emboss) {

  glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  glBindTexture(GL_TEXTURE_2D,texture[filter]);

  glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);

  glEnable(GL_BLEND);

  glEnable(GL_LIGHTING);

  doCube();

 }

Last Pass

• Update Geometry (esp. rotations)

• Do The Logos

 xrot+=xspeed;

 yrot+=yspeed;

 if (xrot>360.0f) xrot-=360.0f;

 if (xrot<0.0f) xrot+=360.0f;

 if (yrot>360.0f) yrot-=360.0f;

 if (yrot<0.0f) yrot+=360.0f;

 /* LAST PASS: Do The Logos! */

 doLogo();

 return true; // Keep Going

}

Finally, a function to render the cube without bump mapping, so that you can see what difference this makes!

bool doMeshNoBumps(void) {

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer

 glLoadIdentity(); // Reset The View

 glTranslatef(0.0f,0.0f,z);

 glRotatef(xrot,1.0f,0.0f,0.0f);

 glRotatef(yrot,0.0f,1.0f,0.0f);

 if (useMultitexture) {

  glActiveTextureARB(GL_TEXTURE1_ARB);

  glDisable(GL_TEXTURE_2D);

  glActiveTextureARB(GL_TEXTURE0_ARB);

 }

 glDisable(GL_BLEND);

 glBindTexture(GL_TEXTURE_2D,texture[filter]);

 glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);

 glEnable(GL_LIGHTING);

 doCube();

 xrot+=xspeed;

 yrot+=yspeed;

 if (xrot>360.0f) xrot-=360.0f;

 if (xrot<0.0f) xrot+=360.0f;

 if (yrot>360.0f) yrot-=360.0f;

 if (yrot<0.0f) yrot+=360.0f;

 /* LAST PASS: Do The Logos! */

 doLogo();

 return true; // Keep Going

}

All the drawGLScene() function has to do is to determine which doMesh-function to calclass="underline"

bool DrawGLScene(GLvoid) // Here's Where We Do All The Drawing {

 if (bumps) {

  if (useMultitexture && maxTexelUnits>1) return doMesh2TexelUnits();

  else return doMesh1TexelUnits();

 } else return doMeshNoBumps();

}

Kills the GLWindow, not modified (thus omitted):

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window

>…<

Creates the GLWindow, not modified (thus omitted):

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)

>…<

Windows main-loop, not modified (thus omitted):

LRESULT CALLBACK WndProc(HWND hWnd, // Handle For This Window

 UINT uMsg, // Message For This Window

 WPARAM wParam, // Additional Message Information

 LPARAM lParam) // Additional Message Information

>…<

Windows main-function, added some keys:

• E: Toggle Emboss / Bumpmapped Mode

• M: Toggle Multitexturing

• B: Toggle Bumpmapping. This Is Mutually Exclusive With Emboss Mode

• F: Toggle Filters. You'll See Directly That GL_NEAREST Isn't For Bumpmapping

• CURSOR-KEYS: Rotate The Cube

int WINAPI WinMain(HINSTANCE hInstance, // Instance

 HINSTANCE hPrevInstance, // Previous Instance

 LPSTR lpCmdLine, // Command Line Parameters

 int nCmdShow) // Window Show State {

 >…<

   if (keys['E']) {

    keys['E']=false;

    emboss=!emboss;

   }

   if (keys['M']) {

     keys['M']=false;

     useMultitexture=((!useMultitexture) && multitextureSupported);

    }

    if (keys['B']) {

     keys['B']=false;

     bumps=!bumps;

    }

    if (keys['F']) {

     keys['F']=false;

     filter++;

     filter%=3;

    }

    if (keys[VK_PRIOR]) {

     z-=0.02f;

    }

    if (keys[VK_NEXT]) {

     z+=0.02f;

    }

    if (keys[VK_UP]) {

     xspeed-=0.01f;

    }

    if (keys[VK_DOWN]) {

     xspeed+=0.01f;

    }

    if (keys[VK_RIGHT]) {

     yspeed+=0.01f;

    }

    if (keys[VK_LEFT]) {

     yspeed-=0.01f;

    }

   }

  }

 }

 // Shutdown

 KillGLWindow(); // Kill The Window

 return (msg.wParam); // Exit The Program

}

Now that you managed this tutorial some words about generating textures and bumpmapped objects before you start to program mighty games and wonder why bumpomapping isn't that fast or doesn't look that good:

• You shouldn't use textures of 256×256 as done in this lesson. This slows things down a lot. Only do so if demonstrating visual capabilities (like in tutorials).

• A bumpmapped cube is not usual. A rotated cube far less. The reason for this is the viewing angle: The steeper it gets, the more visual distortion due to filtering you get. Nearly all multipass algorithms are very affected by this. To avoid the need for high-resolution textures, reduce the minimum viewing angle to a sensible value or reduce the bandwidth of viewing angles and pre-filter you texture to perfectly fit that bandwidth.