OpenGL實例:紋理映射

OpenGL實例:紋理映射

做者:凱魯嘎吉 - 博客園 http://www.cnblogs.com/kailugaji/算法

更多請查看:計算機圖形學函數

1. 介紹

    用於指定一維、二維和三維紋理的函數分別爲:oop

Void glTexImage1D(GLenum target, Glint level, Glint components, GLsizei width, Glint border, GLenum format, GLenum type, const GLvoid *texels);
Void glTexImage2D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels);
Void glTexImage3D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLsizei depth, Glint border, GLenum format, GLenum type, const GLvoid *texels);

    其中,參數target取值通常爲GL_TEXTURE_1D, GL_TEXTURE_2D和GL_TEXTURE_3D,分別與一維、二維和三維的紋理相對應。參數Level表示紋理多分辨率層數,一般取值爲0,表示只有一種分辨率。參數components的可能取值爲1~4的整數以及多種符號常量(如GL_RGBA),表示紋理元素中存儲的哪些份量(RGBA顏色、深度等)在紋理映射中被使用,1表示使用R顏色份量,2表示使用R和A顏色份量,3表示使用RGB顏色份量,4表示使用RGBA顏色份量。參數width,height,depth分別指定紋理的寬度、高度、深度。參數format和type表示給出的圖像數據的數據格式和數據類型,這兩個參數的取值都是符號常量(好比format指定爲GL_RGBA,type指定爲GL_UNSIGNED_BYTE,參數texels指向內存中指定的紋理圖像數據。spa

    在定義了紋理以後,須要啓用紋理的函數:component

glEnable(GL_TEXTURE_1D);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_3D);

    在啓用紋理以後,須要創建物體表面上點與紋理空間的對應關係,即在繪製基本圖元時,在glVertex函數調用以前調用glTexCoord函數,明確指定當前頂點所對應的紋理座標,例如:orm

glBegin(GL_TRIANGLES);
   glTexCoord2f(0.0,  0.0); glVertex2f(0.0,  0.0);
   glTexCoord2f(1.0,  1.0); glVertex2f(15.0,  15.0);
glTexCoord2f(1.0,  0.0); glVertex2f(30.0,  0.0);
glEnd();

    其圖元內部點的紋理座標利用頂點處的紋理座標採用線性插值的方法計算出來。blog

    在OpenGL中,紋理座標的範圍被指定在[0,1]之間,而在使用映射函數進行紋理座標計算時,有可能獲得不在[0,1]之間的座標。此時OpenGL有兩種處理方式,一種是截斷,另外一種是重複,它們被稱爲環繞模式。在截斷模式(GL_CLAMP)中,將大於1.0的紋理座標設置爲1.0,將小於0.0的紋理座標設置爲0.0。在重複模式(GL_REPEAT)中,若是紋理座標不在[0,1]之間,則將紋理座標值的整數部分捨棄,只使用小數部分,這樣使紋理圖像在物體表面重復出現。例如,使用下面的函數:ip

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

分別指定二維紋理中s座標採用截斷或重複處理方式。內存

    另外,在變換和紋理映射後,屏幕上的一個像素可能對應紋理元素的一小部分(放大),也可能對應大量的處理元素(縮小)。在OpenGL中,容許指定多種方式來決定如何完成像素與紋理元素對應的計算方法(濾波)。好比,下面的函數能夠指定放大和縮小的濾波方法:get

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    其中,glTexParameteri函數的第一個參數指定使用的是一維、二維或三維紋理;第二個參數爲GL_TEXTURE_MAG_FILTER或GL_TEXTURE_MIN_FILTER,指出要指定縮小仍是放大濾波算法;最後一個參數指定濾波的方法。

補充:透視投影函數

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);

    它也建立一個對稱透視視景體,但它的參數定義於前面的不一樣。其操做是建立一個對稱的透視投影矩陣,而且用這個矩陣乘以當前矩陣。參數fovy定義視野在X-Z平面的角度,範圍是[0.0,180.0];參數aspect是投影平面寬度與高度的比率;參數zNear和Far分別是遠近裁剪面沿Z負軸到視點的距離,它們總爲正值。

2. 實例一

#include <GL/glut.h>  
#include <cstdlib>  
#include <cstdio>  
#include <cmath>  
#define stripeImageWidth 32

GLubyte stripeImage[4 * stripeImageWidth];

// create 2D texture
void makeStripeImage(void)
{
	int j;
	for (j = 0; j < stripeImageWidth; j++)
	{
		stripeImage[4 * j + 0] = (GLubyte)((j <= 4) ? 255 : 0);
		stripeImage[4 * j + 1] = (GLubyte)((j > 4) ? 255 : 0);
		stripeImage[4 * j + 2] = (GLubyte)0;
		stripeImage[4 * j + 3] = (GLubyte)255;
	}
}

static GLfloat xequalzero[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat slanted[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat *currentCoeff;
static GLenum currentPlane;
static GLint currentGenMode;
static float roangles;
void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	makeStripeImage();
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage1D(GL_TEXTURE_1D, 0, 4, stripeImageWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	currentCoeff = xequalzero;
	currentGenMode = GL_OBJECT_LINEAR;
	currentPlane = GL_OBJECT_PLANE;
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode);
	glTexGenfv(GL_S, currentPlane, currentCoeff);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_1D);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_AUTO_NORMAL);
	glEnable(GL_NORMALIZE);
	glMaterialf(GL_FRONT, GL_SHININESS, 64.0);
	roangles = 45.0f;
}

void display(void) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
	glRotatef(roangles, 0.0, 0.0, 1.0);
	glutSolidSphere(2.0, 32, 32);
	glPopMatrix();
	glFlush();
};

void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-3.5, 3.5, -3.5*(GLfloat)h / (GLfloat)w, 3.5*(GLfloat)h / (GLfloat)w, -3.5, 3.5);
	else
		glOrtho(-3.5*(GLfloat)w / (GLfloat)h, 3.5*(GLfloat)w / (GLfloat)h, -3.5, 3.5, -3.5, 3.5);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void idle()
{
	roangles += 0.05f;
	glutPostRedisplay();
}

int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(256, 256);
	glutInitWindowPosition(100, 100);
	glutCreateWindow(argv[0]);
	glutIdleFunc(idle);
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMainLoop();
	return 0;
}

結果:

3. 實例二

#include <GL/glut.h>  
#include <cstdlib>  
#include <cstdio>  
#include <cmath>  
#define stripeImageWidth 32
#define stripeImageHeight 32
GLubyte stripeImage[stripeImageWidth][stripeImageHeight][4];
void makeStripeImage(void)
{
	int i, j;
	for (i = 0; i < stripeImageWidth; i++)
	{
		for (j = 0; j < stripeImageHeight; j++)
		{
			stripeImage[i][j][0] = (GLubyte)(i * 7 - 1);
			stripeImage[i][j][1] = (GLubyte)(j * 4 - 1);
			stripeImage[i][j][2] = (GLubyte)50;
			stripeImage[i][j][3] = (GLubyte)255;
		}
	}
}
static GLfloat xequalzero[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat slanted[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat *currentCoeff;
static GLenum currentPlane;
static GLint currentGenMode;
static float roangles;
void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	makeStripeImage();
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, 4, stripeImageWidth, stripeImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, stripeImage);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
	currentCoeff = xequalzero;
	currentGenMode = GL_OBJECT_LINEAR;
	currentPlane = GL_OBJECT_PLANE;
	glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, currentGenMode);
	glTexGenfv(GL_S, currentPlane, currentCoeff);
	glEnable(GL_TEXTURE_GEN_S);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_AUTO_NORMAL);
	glEnable(GL_NORMALIZE);
	glMaterialf(GL_FRONT, GL_SHININESS, 64.0);
	roangles = 60.0f;
	//光照
	GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
	GLfloat mat_shininess[] = { 50.0 };
	GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };    //光源位置
	GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };
	GLfloat Light_Model_Ambient[] = { 0.2, 0.2, 0.2, 1.0 };
	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);    //設置材料反射指數(純鏡面反射)
	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);  //設置材料反射指數(材料反射指數)
	glLightfv(GL_LIGHT0, GL_POSITION, light_position);   //創建光源 (光源位置)
	glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);       //創建光源 (漫反射光份量強度)
	glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);      //創建光源 (折射光份量強度)
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, Light_Model_Ambient);
}
void display(void) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPushMatrix();
	glRotatef(roangles, 0.0, 1.0, 0.0);
	glutSolidSphere(3.0, 32, 32);
	glPopMatrix();
	glFlush();
}
void reshape(int w, int h) {
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-3.5, 3.5, -3.5*(GLfloat)h / (GLfloat)w, 3.5*(GLfloat)h / (GLfloat)w, -3.5, 3.5);
	else
		glOrtho(-3.5*(GLfloat)w / (GLfloat)h, 3.5*(GLfloat)w / (GLfloat)h, -3.5, 3.5, -3.5, 3.5);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void idle()
{
	roangles += 0.05f;
	glutPostRedisplay();
}
int main(int argc, char** argv) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(256, 256);
	glutInitWindowPosition(100, 100);
	glutCreateWindow("balloon");
	glutIdleFunc(idle);
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutMainLoop();
	return 0;
}

結果:

相關文章
相關標籤/搜索