码迷,mamicode.com
首页 > 其他好文 > 详细

OpenGL超级宝典笔记三 - 基础纹理1

时间:2015-05-07 16:42:29      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:

纹理对象的使用:纹理图像数据的类型,图像数据的导入导出方式,纹理的使用过程:图像数据的加载,纹理参数的设置,纹理的绑定。


一、图像数据的分类:位图图像和像素图像


二、像素图像数据的包装:
在OpenGL中:使用4字节的行对齐方式,每一行补全到4的倍数,使用glPixelStorei(pname,param)可以改变或者恢复像素的存储方式
介绍常用的两组:内存<->缓冲区的压缩和解包
glPixcelStorei(GL_UNPACK_ALIGNMENT) ----图像数据从内存到缓冲区的解包设置
glPixcelStorei(GL_PACK_ALIGNMENT) ---- 图像数据从缓冲区到内存的封包设置


三、像素图的存储过程(从颜色缓冲区中获取图像保存为图片)
1、从颜色缓冲区读取像素数据到内存中:glReadPixcels(x,y,width,height,format,type,*pixcels)
pixcels:必须有足够的存储空间
format:指定颜色布局,类似GL_RGB,GL_RBGA之类
type:颜色分量的数据类型,类似GL_UNSIGHED_BYTE,GL_BYTE之类
2、从内存到硬盘的图像文件保存


四、像素图数据的获取过程(从硬盘到内存)
gltReadTGABits(szFileName,iWidth,iHeight,iComponents,eFormat)
获取:图片位图数据,宽高,iComponents:颜色成分的存储大小和压缩状况,eFormat:颜色布局
这些数据是位图数据从内存加载到缓冲区的时候,OpenGL需要的数据


五、纹理载入方式一(图像数据从内存到纹理缓冲区):
glTexImage1D/glTexImage2D/glTexImage3D
glTexImage2D(target,level,internalformat,width,height,border,format,type,*data)
target:GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
level:指定mip贴图的层次
internalformat:就是上述获取到的iComponents的数据
border:为纹理贴图指定一个边界宽度
format,type,data:和用于把图像数据放入颜色缓冲区的glDrawPixcels函数对应的参数一致


六、纹理载入方式二(图像数据从颜色缓冲区读取到纹理缓冲区):
glCopyTexImage2D(target,level,internalformat,x,y,width,height,border)
源缓冲区是通过glReadBuffer(mode)函数设置的。 mode为GL_FRONT,GL_LEFT 等参数


七、纹理更新操纵:更新替换原纹理的一部分数据
glTexSubImage2D(target,level,xOffset,yOffset,width,height,format,type,*data)


从颜色缓冲区中提取纹理作为数据去更新:
glCopyTexSubImage2D(target,level,xOffset,yOffset,width,height)


八、纹理对象的使用:由于使用glTexImage和glTexSubImage这样的函数加载和更新纹理太耗费内存,所以引用纹理对象
特点:纹理对象是允许我们一次加载一个以上的纹理状态(包括纹理图像)以及可以在它们之间快速切换的。
纹理对象的创建:glGenTextures(GLsizei n,GLuint* textures)
n:纹理对象数量
textures:不同纹理状态的句柄数组


纹理状态的绑定:glBindTexture(GLenum target,Gluint texture)
target:GL_TEXTURE_2D.....
texture:需要绑定的特定纹理状态


纹理对象的销毁:glDeleteTextures(n,textures)
纹理状态的确认:glIsTexure(GLuint texture)


九、纹理应用:
1、加载纹理数据
2、提供纹理坐标
s,t,r相当于x,y,z
3、设置纹理坐标的环绕模式(相对每个纹理坐标轴的)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT)
环绕模式:
GL_REPEAT:超出1.0的对纹理进行重复
GL_CLAMP:使用纹理边界或者既定设置的边界颜色
GL_CLAMP_EDGE:使用纹理单元的最后一行或者一列数据
GL_CLAMP_BORDER:使用边界纹理单元
4、设置纹理的过滤(相对于拉伸和缩小的)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
过滤模式:
GL_NEAREST:最邻近过滤,快速,但是如果纹理被拉伸过大会出现大片的斑驳像素
GL_LINEAR:线性过滤,开销大,但是效果比较好

十、综合运用的例子:可以旋转带光照纹理的金字塔

// Pyramid.cpp
// OpenGL SuperBible, Chapter 5
// Demonstrates Texture mapping a pyramid
// Program by Richard S. Wright Jr.

#include <GLTools.h>	// OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLBatch.h>
#include <GLGeometryTransform.h>

#include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

/////////////////////////////////////////////////////////////////////////////////
// An assortment of needed classes
GLShaderManager		shaderManager;
GLMatrixStack		modelViewMatrix;
GLMatrixStack		projectionMatrix;
GLFrame				cameraFrame;
GLFrame             objectFrame;
GLFrustum			viewFrustum;

GLBatch             pyramidBatch;

GLuint              textureID;

GLGeometryTransform	transformPipeline;
M3DMatrix44f		shadowMatrix;


void MakePyramid(GLBatch& pyramidBatch)
    {
	pyramidBatch.Begin(GL_TRIANGLES, 18, 1);
    <span style="white-space:pre">	</span>//手动设置金字塔的顶点数据,包括位置,纹理坐标和光照法线向量
	// Bottom of pyramid
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
	pyramidBatch.Vertex3f(1.0f, -1.0f, -1.0f);
    
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
	pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);
    
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
	pyramidBatch.Vertex3f(-1.0f, -1.0f, 1.0f);
    
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);
    
	pyramidBatch.Normal3f(0.0f, -1.0f, 0.0f);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
	pyramidBatch.Vertex3f(1.0f, -1.0f, 1.0f);
    
	
	M3DVector3f vApex = { 0.0f, 1.0f, 0.0f };
	M3DVector3f vFrontLeft = { -1.0f, -1.0f, 1.0f };
	M3DVector3f vFrontRight = { 1.0f, -1.0f, 1.0f };
	M3DVector3f vBackLeft = { -1.0f, -1.0f, -1.0f };
	M3DVector3f vBackRight = { 1.0f, -1.0f, -1.0f };
	M3DVector3f n;
	
	// 根据三个点计算法线向量
	m3dFindNormal(n, vApex, vFrontLeft, vFrontRight);
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
	pyramidBatch.Vertex3fv(vApex);		// Apex
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3fv(vFrontLeft);		// Front left corner
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
	pyramidBatch.Vertex3fv(vFrontRight);		// Front right corner
    
    
	m3dFindNormal(n, vApex, vBackLeft, vFrontLeft);
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
	pyramidBatch.Vertex3fv(vApex);		// Apex
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
	pyramidBatch.Vertex3fv(vBackLeft);		// Back left corner
	
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3fv(vFrontLeft);		// Front left corner
    
	m3dFindNormal(n, vApex, vFrontRight, vBackRight);
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
	pyramidBatch.Vertex3fv(vApex);				// Apex
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
	pyramidBatch.Vertex3fv(vFrontRight);		// Front right corner
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3fv(vBackRight);			// Back right cornder
    
    
	m3dFindNormal(n, vApex, vBackRight, vBackLeft);
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
	pyramidBatch.Vertex3fv(vApex);		// Apex
    
	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
	pyramidBatch.Vertex3fv(vBackRight);		// Back right cornder

	pyramidBatch.Normal3fv(n);
	pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
	pyramidBatch.Vertex3fv(vBackLeft);		// Back left corner

	pyramidBatch.End();
	}
//获取纹理图像数据,并且设置纹理参数并得到一个纹理状态放入纹理对象中
bool loadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
	GLbyte *pBits;
	int nWidth,nHeight,nComponents;
	GLenum eFormat;

	pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
	if(pBits == NULL)
		return false;
<span style="white-space:pre">	</span>//S,T轴上的纹理环绕模式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
<span style="white-space:pre">	</span>//放大和缩小的过滤
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,minFilter);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,magFilter);

	glPixelStorei(GL_UNPACK_ALIGNMENT,1);		//图像数据解包,从内存区到缓存区
	glTexImage2D(GL_TEXTURE_2D,0,nComponents,nWidth,nHeight,0,eFormat,GL_UNSIGNED_BYTE,pBits);

	free(pBits);

	if(minFilter == GL_LINEAR_MIPMAP_LINEAR || 
       minFilter == GL_LINEAR_MIPMAP_NEAREST ||
       minFilter == GL_NEAREST_MIPMAP_LINEAR ||
       minFilter == GL_NEAREST_MIPMAP_NEAREST)
        glGenerateMipmap(GL_TEXTURE_2D);
    
	return true;
}

void SetupRC(){
	glClearColor(0.7f,0.7f,0.7f,1.0f);

	shaderManager.InitializeStockShaders();

	glEnable(GL_DEPTH_TEST);

	glGenTextures(1,&textureID);
	glBindTexture(GL_TEXTURE_2D,textureID);
	loadTGATexture("stone.tga",GL_LINEAR,GL_LINEAR,GL_CLAMP_TO_EDGE);

	MakePyramid(pyramidBatch);
<span style="white-space:pre">	</span>//场景的照相机
	cameraFrame.MoveForward(-7.0f);

}

void ShutdownRC(){
	glDeleteTextures(1,&textureID);
}

void RenderScene(){
	static GLfloat vLightPos[] = {1.0f,1.0f,0.0f};
	static GLfloat vWhite[] = {1.0f,1.0f,1.0f,1.0f};

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	modelViewMatrix.PushMatrix();
	M3DMatrix44f mCamera;
	cameraFrame.GetCameraMatrix(mCamera);
	modelViewMatrix.MultMatrix(mCamera);

	M3DMatrix44f mObjectFrame;
	objectFrame.GetCameraMatrix(mObjectFrame);
	modelViewMatrix.MultMatrix(mObjectFrame);
<span style="white-space:pre">	</span>//在提交批绘制的时候,绑定我们需要使用的纹理
	glBindTexture(GL_TEXTURE_2D,textureID);
	shaderManager.UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),
		transformPipeline.GetProjectionMatrix(),vLightPos,vWhite,0);

	pyramidBatch.Draw();

	modelViewMatrix.PopMatrix();

	glutSwapBuffers();
}

void SpecialKeys(int key,int x,int y){
	if(key == GLUT_KEY_UP)
		objectFrame.RotateWorld(m3dDegToRad(-5.0f),1.0f,0.0f,0.0f);
	if(key == GLUT_KEY_DOWN)
		objectFrame.RotateWorld(m3dDegToRad(5.0f),1.0f,0.0f,0.0f);
	if(key == GLUT_KEY_LEFT)
		objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
    
	if(key == GLUT_KEY_RIGHT)
		objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
    
	glutPostRedisplay();
}

void ChangeSize(int w,int h){
	glViewport(0,0,w,h);
	viewFrustum.SetPerspective(35.0f,float(w)/float(h),1.0f,500.0f);
	projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
	transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);
}

int main(int argc, char* argv[])
	{
	gltSetWorkingDirectory(argv[0]);
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Pyramid");
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
        
	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
		}
	

	SetupRC();

	glutMainLoop();
    
    ShutdownRC();
    
	return 0;
	}




OpenGL超级宝典笔记三 - 基础纹理1

标签:

原文地址:http://blog.csdn.net/zh13544539220/article/details/45562083

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!