1. 程式人生 > >用OpenGL快速給圖形新增紋理含圓柱圓錐

用OpenGL快速給圖形新增紋理含圓柱圓錐

這裡討論的是二維紋理

1.圖取影象資料

void readimage(char* filename, BYTE* imagedata)//所讀圖片均為24位bmp,且寬度補齊至四位元組邊界
{
	BITMAPFILEHEADER bf;  //檔案頭
	BITMAPINFOHEADER bi;  //資訊頭
	int     m_ImageWidth;   //圖象寬度
	int     m_ImageHeight;  //圖象高度
	FILE  *fp1; //檔案指標,fp1為原始檔
	//開啟檔案,到檔案指標
	if ((fp1 = fopen(filename, "rb")) == NULL)
	{
		MessageBox(NULL, "檔案開啟錯誤", "warning", MB_OK);
	}

	fread((LPSTR)&bf, sizeof(BITMAPFILEHEADER), 1, fp1);  //讀取檔案頭,讀取以後檔案指標在檔案頭末尾(即資訊頭)
	fread((LPSTR)&bi, sizeof(BITMAPINFOHEADER), 1, fp1);  //讀取資訊頭
	m_ImageWidth = bi.biWidth;             //給圖象寬度賦值
	m_ImageHeight = bi.biHeight;           //給圖象高度賦值
	fread(imagedata, m_ImageHeight*m_ImageWidth * 3, 1, fp1);  //讀取圖象資料
	fclose(fp1);
}


注意:讀進來的影象為BGR,要調整為RGB

void adjustimage(BYTE* imagedata, int w, int h)
{
	BYTE temp;
	for (int i = 0; i<w*h; i++)
	{<pre name="code" class="cpp">glEnable(GL_TEXTURE_2D);

temp = imagedata[i * 3];imagedata[i * 3] = imagedata[i * 3 + 2];imagedata[i * 3 + 2] = temp;}} 2.設定紋理(因為一般要用到的紋理比較多,先將所有圖片讀入,要用到那張時候就使用glBindTexture函式來指定當前所使用的紋理物件)

注意:影象的畫素要與陣列對應,下面的是256*256

//------------------------設定紋理----------------------------------
void loadtexture()
{           
	glGenTextures(2, &texName);//2表示有兩個紋理
	glBindTexture(GL_TEXTURE_2D, texName);
	{
		BYTE imagemoon[256][256][3];			//牆壁2的紋理
		readimage("D:\\wall2.bmp", &imagemoon[0][0][0]);
		adjustimage(&imagemoon[0][0][0], 256, 256);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imagemoon);
	}
	{
		BYTE imagesky[256][256][3];
		readimage("D:\\wall1.bmp", &imagesky[0][0][0]);//牆壁1的紋理
		adjustimage(&imagesky[0][0][0], 256, 256);
		glBindTexture(GL_TEXTURE_2D, texName + 1);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imagesky);
	}
}

3.啟用紋理
glEnable(GL_TEXTURE_2D);
4.紋理座標

例子:座標要對應,紋理用單位表示,(0.0,0.0)表示左下角(1.0,1.0)表示右上角

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//printf("At:%.2f %.2f %.2f\n",r*cos(c*du),h,r*sin(c*du)); //這就是視點的座標
	glLoadIdentity();
	gluLookAt(r*cos(c*du), h, r*sin(c*du), 0, 0, 0, 0, 1, 0); //從視點看遠點,y軸方向(0,1,0)是上方向

	glColor3f(1.0f, 0.0f, 0.0f);

	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

	//地面
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, texName + 2);
	glColor3f(0.0, 1.0, 1.0);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0, 0.0); glVertex3f(5.0f,-2.0f,3.0f);
	glTexCoord2f(1.0, 0.0); glVertex3f(-5.0f, -2.0f, 3.0f);
	glTexCoord2f(1.0, 1.0); glVertex3f(-5.0f, -2.0f, -3.0f);
	glTexCoord2f(0.0, 1.0); glVertex3f(5.0f, -2.0f, -3.0f);
	glEnd();

	//左牆
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, texName + 1);
	glBegin(GL_POLYGON);
	glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, 0.0, 1.5);
	glTexCoord2f(0.0, 0.66); glVertex3f(-2.0, 2.0, 1.5);
	glTexCoord2f(0.5, 1.0); glVertex3f(-2.0, 3.0, 0.0);
	glTexCoord2f(1.0, 0.66); glVertex3f(-2.0, 2.0, -1.5);
	glTexCoord2f(1.0, 0.0); glVertex3f(-2.0, 0.0, -1.5);
	glEnd();
	glPopMatrix();

	glFlush();
	glutSwapBuffers();

	glDisable(GL_TEXTURE_2D);
}


5.對於圓柱和圓錐

將圓柱和圓錐看做是由很多線組成的,使用三角函式和一個迴圈就可以畫出

        //圓柱
	glTranslatef(-3.0, -2.0, 2.0);
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, texName );
    glBegin( GL_QUAD_STRIP);
    double t = 0.0;double dt = 2*PI/nslice;
    for (int j = 0; j <= nslice; ++j) 
	{
       glTexCoord2f( t/(2*PI), 1.0); glVertex3f( cos( t), 2.0, -sin( t));
       glTexCoord2f( t/(2*PI), 0.0); glVertex3f( cos( t), 0.0, -sin( t));
       t = t + dt;
     }
    glEnd();
	glPopMatrix();

	//圓錐
	glPushMatrix();
	glBindTexture(GL_TEXTURE_2D, texName + 4 );
	glBegin( GL_QUAD_STRIP);
    double tt = 0.0;double dtt = 2*PI/nslice;
    for (int j = 0; j <= nslice; ++j) 
	{
       glTexCoord2f( tt/(2*PI), 1.0); glVertex3f( 0.0, 2.0, 0.0);
       glTexCoord2f( tt/(2*PI), 0.0); glVertex3f( cos( tt), 0.0, -sin( tt));
       tt = tt + dtt;
     }
    glEnd();
	glPopMatrix();