Nehe OpenGL lesson 8

lesson8 Blending: http://nehe.gamedev.net/tutorial/lessons_06__10/17010/ (或许需要特殊手段访问)

There was a reason for the wait. A fellow programmer from the totally cool site Hypercosm, had asked if he could write a trial on blending. Lesson eight was going to be a blending tutorial anyways. So the timing was perfect! This tutorial expands on lesson
seven. lending is a very cool effect.. I hope you all enjoy the tutorial. the author of this tutorial is Tom Stanis. He‘s put a lot of error into the tutorial, so let him know what you think. Blending is not an easy topic to cover.

Most special effects in OpenGL rely on some type of blending. Blending is used to combine the colour of a given pixel that is about to be drawn with the pixel that is already on the screen. How the colours are combined is based on the alpha value of the
colours, and/or the blending function that is being used. Alpha is a 4th colour component usually specified at the end. In the past you have used GL_RGB to specify colour with 3 components. GL_RGBA can be used to specify alpha as well. In addition, we can
use glColor4f() instead of glColor3f().

Most people think of Alpha as how opaque a material is. An alpha value of 0.0 would mean that he material is completely transparent. A value of 1.0 would be totally opaque.

The Blending Equation: (Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)

OpenGL will calculate the result of blending two pixels based on the above equation. The s and subscripts specify the source and destination pixels. The S and D components are the blend factors. The values indicate how you would like to blend the pixels.
The most common values for S and D are (As, As, As, As) (AKA source alpha) for S and (1, 1, 1, 1)-(As, As, As, As) (AKA one minus src alpha) for D. This will yield a blending equation that looks like this:

(Rs As + Rd (1 - As), Gs As + Gd(1 - As), Bs As + Bd (1 - As), As As + Ad(1 - As))

This equation will yield transparent / translucent style effects.

We enable blending just like everything else. Then we set the equation, and turn off depth buffer writing when drawing transparent objects, since we still want objects behind the translucent
shapes to be drawn. This isn‘t the proper way to blend, but most the time in simple projects it will work fine. Rui Martins Adds: The
correct way is to draw all the transparent (with alpha < 1.0) polys after you have drawn the entire scene, and to draw them in reverse depth order (farthest first). This is due to the fact that blending two polygons (1 and 2) in different order gives different
results, i.e. (assuming poly 1 is nearest to the viewer, the correct way would be to draw poly 2 first and then poly 1. If you look at it, like in reality, all the light comming from behind these two polys (which are transparent) has to pass poly 2 first and
then poly 1 before it reaches the eye of the viewer. You should SORT THE TRANSPARENT POLYGONS BY DEPTH and draw them AFTER THE ENTIRE SCENE HAS BEEN DRAWN, with the DEPTH BUFFER ENABLED, or you will get incorrect results. I know this sometimes is a pain, but
this is the correct way to do it.

We‘ll be using the code from the last tutorial. We start off by adding two new variables to the top of the code. I‘ll rewrite the entire
section of code for clarity.

接下来是代码:(已经编译通过: 对于MacBook来说,没有page键盘,所以使用了字母键盘A &#8;、S两个按键替代

// lesson 8 Blending
//
// The S and D components are the blend factors.
// (Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
//
// The  most common values for S and D are (As, As, As, As) (AKA source alpha)
// for S and (1, 1, 1, 1) - (As, As, As, As) (AKA one minus src alpha) for D. This will
// yield a blending equation that looks like this:
// (Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bd (1 - As), As As + Ad (1 - As))
// This equation will yield transparent/translucent style effects.
//
// Linux
// #include <GL/glut.h>
// #include <GL/gl.h>
// #include <GL/glu.h>

// Mac OS X
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

/* ascii codes for various special keys */
#define ESCAPE 				27
#define PAGE_UP 			73
#define PAGE_DOWN			81
#define UP_ARROW      72
#define DOWN_ARROW    80
#define LEFT_ARROW		75
#define RIGHT_ARROW 	77
#define KEY_A        	97
#define KEY_S       	115

/* The number of our GLUT window */
int window;

/* lighting on/off (1 = on, 0 = off) */
int light;

/* L pressed (1 = yes, 0 = no) */
int lp;

/* F pressed (1 = yes, 0 = no) */
int fp;

GLfloat xrot;			 	// x rotation
GLfloat yrot; 			// y rotation
GLfloat xspeed; 		// x rotation speed
GLfloat yspeed; 		// y rotation speed

GLfloat z = -5.0f; 	// depth into the screen.

/* white ambient light at half intensity (rgba) */
GLfloat lightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };

/* supper bright, full intensity diffuse light. */
GLfloat lightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };

/* position of light (x, y, z (position of light)) */
GLfloat lightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f };

GLuint filter; 	   /* which filter to use (nearest/linear/mipmapped) */
GLuint texture[3]; /* storage for 3 textures. */
GLuint blend; 		 /* turn blending on/off */

/* Image type - contains height, width, and data */
struct Image {
	unsigned long sizeX;
	unsigned long sizeY;
	char *data;
};
typedef struct Image Image;

/*
 * getint and getshort are help functions to load bitmap byte by byte on
 * SPARC platform.
 * I've got them from xv bitmap load routine because the original bmp loader didn't work
 * I've tried to change as less code as possible.
 */

static unsigned int getint(FILE *fp) {
  int c, c1, c2, c3;

  // get 4 bytes
  c   = getc(fp);
  c1  = getc(fp);
  c2  = getc(fp);
  c3  = getc(fp);

  return ((unsigned int) c) +
    (((unsigned int) c1) << 8) +
    (((unsigned int) c2) << 16) +
    (((unsigned int) c3) << 24);
}

static unsigned int getshort(FILE *fp) {
  int c, c1;

  // get 2 bytes
  c   = getc(fp);
  c1  = getc(fp);

  return ((unsigned int) c) + (((unsigned int) c1) << 8);
}

int imageLoad(char *filename, Image *image) {
  FILE *file;
  unsigned long size; 				// size of the image in bytes.
  unsigned long i; 						// standard counter.
  unsigned short int planes; 	// number of planes in image (must be 1)
  unsigned short int bpp; 		// number of bits per pixel (must be 24)
  char temp; 									// used to convert bgr to rgb color.

  // make sure the file is there.
  if ((file = fopen(filename, "rb")) == NULL) {
    printf("File Not Fond: %s\n", filename);
		return 0;
	}

  // seek through the bmp header, up to the width/height;
  fseek(file, 18, SEEK_CUR);

  // NO 100% errorchecking anymore!!!
  // read the width
  image->sizeX = getint(file);
  printf("Width of %s: %lu\n", filename, image->sizeX);

  // read the height
  image->sizeY = getint(file);
  printf("Height of %s: %lu\n", filename, image->sizeY);

  // calcualte the size (assuming 24 bits or 3 bytes per pixel).
  size = image->sizeX * image->sizeY * 3;

  // read the planes
  planes = getshort(file);
  if (planes != 1) {
    printf("Planes from %s is not 1: %u\n", filename, planes);
    return 0;
  } 

  // read the bpp
  bpp = getshort(file);
  if (bpp != 24) {
    printf("Bpp from %s is not 24: %u\n", filename, bpp);
    return 0;
  }

  // seek past the rest of the bitmap header.
  fseek(file, 24, SEEK_CUR);

  // read the data.
  image->data = (char *) malloc(size);
  if (image->data == NULL) {
    printf("Error allocating memory for color-corrected image data");
    return 0;
  }

  if ((i = fread(image->data, size, 1, file)) != 1) {
    printf("Error reading image data from %s.\n", filename);
    return 0;
  }  

  for (i = 0; i < size; i += 3) {
    temp = image->data[i];
    image->data[i] = image->data[i+2];
    image->data[i+2] = temp;
  }

  return 1; // we're done.
}

// Load Bitmaps and convert to texture
GLvoid loadGLTextures(GLvoid) {
  Image *image1; // Load Texture

  // allocate space for texture.
  image1 = (Image *) malloc(sizeof(Image));
  if (image1 == NULL) {
    printf("Error allocating space for image");
    exit(0);
  }

  if (!imageLoad("Data/lesson8/glass.bmp", image1)) {
    exit(1);
  }

  // Create Textures
  glGenTextures(3, &texture[0]);

  // texture 1 (poor quality scaling)
  glBindTexture(GL_TEXTURE_2D, texture[0]);  // 2d texture (x and y size)

  // cheap scaling when image bigger than texture.
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  // cheap scaling when image samlled than texture
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

  // 2d texture level of detail 0 (normal), 3 components (red, green, blue), x size from
  // image, y size from image, border 0 (normal) rgb color data, unsigned byte data,
  // and finally the data itself.
  glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0,
     GL_RGB, GL_UNSIGNED_BYTE, image1->data);

  // texture 2 (linear scaling)
  glBindTexture(GL_TEXTURE_2D, texture[1]); // 2d texture (x and y size)
  // scale linearly when image bigger than texture.
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  // scale linearly when image smaller than texture.
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0,
    GL_RGB, GL_UNSIGNED_BYTE, image1->data);

  // texture 3 (mipmapped scaling)
  glBindTexture(GL_TEXTURE_2D, texture[2]); // 2d textuer (x and y size)
  // scale linearly when image bigger than texture.
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  // scale linearly + mipmap when image smalled than texture.
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0,
    GL_RGB, GL_UNSIGNED_BYTE, image1->data);

  // 2d texture 3 colors, width, height, RGB in that order, byte data, and the data.
  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB,
    GL_UNSIGNED_BYTE, image1->data);
}

/* A general OpenGL initialization function. Sets all of the initial parameters. */
GLvoid initGL(GLsizei width, GLsizei height) {
  loadGLTextures();
  glEnable(GL_TEXTURE_2D); 

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear the background Color to black.
  glClearDepth(1.0);		// Enables clearing of the depth buffer.
  glDepthFunc(GL_LESS); // The type of depth test to do.
  glEnable(GL_DEPTH_TEST); // Enables depth testing.
  glShadeModel(GL_SMOOTH); // Enables smooth color shading.

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();  // Reset the projection matrix.

  // Calculate the aspect ratio of the window.
  gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); 

  glMatrixMode(GL_MODELVIEW);

  // set up light number 1.
  glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbient); // add lighting. (ambient)
  glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse); // add lighting. (diffuse)
  glLightfv(GL_LIGHT1, GL_POSITION, lightPosition); // set light position.
  glEnable(GL_LIGHT1);

  /* setup blending */
  glBlendFunc(GL_SRC_ALPHA, GL_ONE); 	// Set the blending function for translucency.
  glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}

/* The function called when our window is resized (which
   shouldn't happend, because we're fullscreen) */
GLvoid resizeGLScene(GLsizei width, GLsizei height) {
  if (height == 0)
    height = 1;

  // Reset the current viewport and perspective transformation
  glViewport(0, 0, width, height);  

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
  glMatrixMode(GL_MODELVIEW);
}

/* The main drawing function. */
GLvoid drawGLScene(GLvoid)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity(); 

  glTranslatef(0.0f, 0.0f, z);    		// move z units out from the screen.

  glRotatef(xrot, 1.0f, 0.0f, 0.0f);  // Rotate on the X axis
  glRotatef(yrot, 0.0f, 1.0f, 0.0f);  // Rotate on the y axis.

  glBindTexture(GL_TEXTURE_2D, texture[filter]); // choose the texture to use.

  glBegin(GL_QUADS); // begin drawing a cube

    // Front Face (note that the texture's corner's have to match the quad's corners)
    glNormal3f(0.0f, 0.0f, 1.0f); // front face points out of the screen on z.
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // bottom left
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // bottom right
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // top right
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // top left.

    // Back face
    glNormal3f(0.0f, 0.0f, -1.0f);  // back face points into the screen on z
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // bottom right
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); // top right
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); // top left
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // bottom left.

    // Top Face
    glNormal3f(0.0f, 1.0f, 0.0f); // top face points up on y
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // top left
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f,  1.0f); // bottom left
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f,  1.0f); // bottom right
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // top right

    // bottom face
    glNormal3f(0.0f, -1.0f, 0.0f); // bottom face points down on y
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // top right
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // top left.
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // bottom left.
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // bottom right

	  // right face
    glNormal3f(1.0f, 0.0f, 0.0f); // right face points right on x.
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // bottom right
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f); // top right
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f); // top left.
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f); // bottom left.

		// left face
    glNormal3f(-1.0f, 0.0f, 0.0f); // left face points left on x.
    glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // bottom left
    glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f); // bottom right
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f); // top right
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f); // top left.

  glEnd();

  xrot += xspeed;
  yrot += yspeed;

  // since this is double buffered, swap the buffers to display what just got drawn.
  glutSwapBuffers();
}

/* The function called wheever a normal key is pressed. */
void keyPressed(unsigned char key, int x, int y) {
  /* avoid thrashing this procedure */
  usleep(100);

  printf("keypressed: %c, %d\n", key, key);   

  switch (key) {
    case ESCAPE:  // kill everything.
      glutDestroyWindow(window); // exit the program...normal termination.
      exit(1);
      break;
    case 76:
    case 108:
      printf("L/l pressed is : %d\n", light);
      light = light ? 0 : 1; // switch the current value of light, between 0 and 1.
      printf("Light is now: %d\n", light);
      if (!light) {
  		  glDisable(GL_LIGHTING);
      } else {
   	    glEnable(GL_LIGHTING);
      }
      break;

    case 70:
    case 102: // switch the filter.
      printf("F/f pressed; filter is: %d\n", filter);
      filter += 1;
      if (filter > 2) {
     	  filter = 0;
      }
      printf("Filter is now: %d\n", filter);
      break;

    case 98:
    case 66: // switch the blending.
      printf("B/b pressed; blending is: %d\n", blend);
      blend = blend ? 0 : 1;
      printf("Blend is now: %d\n", blend);
      if (!blend) {
			  glDisable(GL_BLEND);    // Turn Blending Off
        glEnable(GL_DEPTH_TEST); // Turn Depth Testing On
      } else {
			  glEnable(GL_BLEND);       // Turn Blending On
        glDisable(GL_DEPTH_TEST); // Turn Depth Testing Off
      }
      break; 

    case KEY_A:								// Move the cube into the distance.
      z -= 0.02f;
      break;

    case KEY_S:								// Move te cube closer.
      z += 0.02f;
      break;

  }
}

/* The function called whenver a normal key is pressed. */
void specialKeyPressed(int key, int x, int y) {
  /* avoid thrashing this procedure */
  usleep(100);

  printf("specialKeyPressed: %c, %d\n", key, key);

  switch (key) {
    case GLUT_KEY_UP: 			// decrease x rotation speed;
      xspeed -= 0.01f;
      break;
    case GLUT_KEY_DOWN:     // increase x rotation speed;
      xspeed += 0.01f;
      break;

    case GLUT_KEY_LEFT:     // increase y rotation speed;
      yspeed -= 0.01f;
      break;
    case GLUT_KEY_RIGHT:    // decrease y rotation speed;
      yspeed += 0.01f;
      break;

    default:
      break;
  }
}

int main(int argc, char **argv) {
  glutInit(&argc, argv);

  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);

  /* get a 640 x 480 window */
  glutInitWindowSize(640, 480);

  /* the window starts at the upper left corner of the screen. */
  glutInitWindowPosition(0, 0);

  /* Open a window */
  window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99");

  /* Register the function to do all our OpenGL drawing. */
  glutDisplayFunc(&drawGLScene);

  /* Go fullscreen. This is as soon as possible. */
 // glutFullScreen();

  /* Event if there are no events, redraw our gl scene. */
  glutIdleFunc(&drawGLScene);

  /* Register the function called when our window is resized. */
  glutReshapeFunc(&resizeGLScene);

  /* Register the funciton called when the keyboard is pressed. */
  glutKeyboardFunc(&keyPressed);

  /* Register the function called when special keys (arrows, page down, etc) a re pressed. */
  glutSpecialFunc(&specialKeyPressed);

  /* Initialize our window */
  initGL(640, 480);

  /* Start Event Processing Engine */
  glutMainLoop();

  return 0;
}
时间: 2024-11-06 16:47:08

Nehe OpenGL lesson 8的相关文章

NeHe OpenGL lesson 7

HeHe OpenGL 第七节,纹理部分,光照初步.由于Mac 上面没有Page键,所以用G . H键替换 // NeHe OpenGL lession 7 // Texture Filters, Lighting & keyboard Control // /** * Linux * #include <GL/glut.h> * #include <GL/gl.h> * #include <GL/glu.h> */ #include <GLUT/GLUT

NeHe OpenGL Lesson 9

// // This code was created by Jeff Molofee '99 (ported to Linux/GLUT by // Richard Campbell '99) // // If you've found this code useful, please let me know. // // Visit me at www.demonews.com/hosted/nehe // (email Richard Campbell at [email protecte

NeHe OpenGL教程 第三十八课:资源文件

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十八课:资源文件 从资源文件中载入图像: 如何把图像数据保存到*.exe程序中,使用Windows的资源文件吧,它既简单又实用. 欢迎来到NeHe教程第38课.离上节课的写作已经有些时日了,加上写了一整天的code,也许笔头已经

NeHe OpenGL教程 第四十七课:CG顶点脚本

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第四十七课:CG顶点脚本 CG 顶点脚本 nVidio的面向GPU的C语言,如果你相信它就好好学学吧,同样这里也只是个入门.记住,类似的语言还有微软的HLSL,OpenGL的GLSL,ATI的shaderMonker.不要选错哦:)

NeHe OpenGL教程 第二十三课:球面映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十三课:球面映射 球面映射: 这一个将教会你如何把环境纹理包裹在你的3D模型上,让它看起来象反射了周围的场景一样. 球体环境映射是一个创建快速金属反射效果的方法,但它并不像真实世界里那么精确!我们从18课的代码开始来创建这个教程

NeHe OpenGL教程 第三十五课:播放AVI

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十五课:播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢?利用Windows的API把每一帧作为纹理绑定到OpenGL中,虽然很慢,但它的效果不错.你可以试试. 首先我得说我非常喜欢这一章节.Jonat

NeHe OpenGL教程 第三十七课:卡通映射

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十七课:卡通映射 卡通映射: 什么是卡通了,一个轮廓加上少量的几种颜色.使用一维纹理映射,你也可以实现这种效果. 看到人们仍然e-mail我请求在文章中使用我方才在GameDev.net上写的源代码,还看到文章的第二版(在那每一

NeHe OpenGL教程 第四十四课:3D光晕

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第四十四课:3D光晕 3D 光晕 当镜头对准太阳的时候就会出现这种效果,模拟它非常的简单,一点数学和纹理贴图就够了.好好看看吧. 大家好,欢迎来到新的一课,在这一课中我们将扩展glCamera类,来实现镜头光晕的效果.在日常生活中,

NeHe OpenGL教程 第四十三课:FreeType库

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第四十三课:FreeType库 在OpenGL中使用FreeType库 使用FreeType库可以创建非常好看的反走样的字体,记住暴雪公司就是使用这个库的,就是那个做魔兽世界的.尝试一下吧,我只告诉你了基本的使用方式,你可以走的更远