首页 > 代码库 > Nehe OpenGL lesson 8

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 、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 = http://www.mamicode.com/(char *) malloc(size);>



Nehe OpenGL lesson 8