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

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

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

二、像素图像数据的包装:

在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;
	}
时间: 2024-10-12 15:45:16

OpenGL超级宝典笔记三 - 基础纹理1的相关文章

OpenGL超级宝典笔记四 - 基础纹理2

一.使用MipMap贴图(主要是应用在纹理缩小过滤中) 优点: 防止当纹理缩小太大的时候,出现闪烁的问题 提高性能,需要缩小的时候就不加载大内存的纹理 缺点: 需要额外的内存作为代价 组成:由一系列缩小的纹理图像组成,子层是父层的1/4 过滤类型:NEAREST快速,LINEAR效果好 GL_NEAREST_MINMAP_NEAREST选择最邻近Mip层并执行邻近过滤 GL_NEAREST_MINMAP_LINEAR选择最Mip层线性插补并执行邻近过滤 GL_LINEAR_MINMAP_NEAR

OpenGL超级宝典笔记一 - 基础渲染

1.渲染中的双缓冲: 使用但缓冲的时候,在渲染每一帧的绘图时,会对画板进行擦除然后在慢慢填充绘制,如果绘制时间过长的时候,就会出现闪烁的现象.为解决这个问题,所以引入双缓冲 双缓冲相当于,在显示的画板中重新创建另外一个画板,绘制的过程在另外的画板进行,绘制完成之后,将显示的画板的内容直接替换成另外一个画板的内容.这样呈现的过程中就不会出现闪烁的问题,即使是绘制的过程比较慢,最多就是出现顿的现象 在例子中渲染的RenderScene()函数中,每次渲染结束之后都会调用glutSwapBuffers

OpenGL超级宝典笔记五 - 基础Shader

1.基本着色器的架构 顶点着色器:接收客户端输入的Attribute属性数据,有些计算后自己用于顶点变换,有些传给片段着色器.除此之外,顶点着色器还接受uniform数据,一般是变换矩阵.最后输出顶点的位置变换值. 片段着色器:接收来自顶点着色器输出的纹理坐标和纹理等属性,另外也接收用于计算光照的光照颜色的uniform值,最后输出像素的颜色值. 2.Shader的变量和数据类型 数据类型:整数(有符号和无符号),浮点数和布尔值..没有指针和字符类型 复合数据类型:向量类型(vec3,ivec3

OpenGL超级宝典笔记二 - 基础变换

1.向量: 点乘:float m3dDotProduce3(u,v):返回两个单位向量的余弦值 叉乘:float m3dCrossProduct3(result,u,v):返回垂直于两个向量定义的平面的向量 2.矩阵: OpenGL使用的是列优先排序的矩阵 单位矩阵(对角线为1,其他为0):任何向量乘以一个单位矩阵都不会发生任何改变 3.变换:最终获得的变换矩阵会应用到每个顶点 视图矩阵x模型矩阵x投影矩阵->投影摄像机的位置变换,物体对象的位置变换,投影裁剪变换 若顶点向量为Vert,则变换公

OpenGL超级宝典笔记——深度纹理和阴影 【转】

目录[-] 光源视角 新型的纹理 深度纹理的大小 首先绘制阴影 然后是光照 投影阴影贴图 阴影比较 之前我们介绍过简单的把物体压平到投影平面来制造阴影.但这种阴影方式有其局限性(如投影平面须是平面).在OpenGL1.4引入了一种新的方法阴影贴图来产生阴影. 阴影贴图背后的原理是简单的.我们先把光源的位置当作照相机的位置,我们从这个位置观察物体,我们就知道哪些物体的表面是被照射到(被光源看到) 的,哪些是没有被照射到(被遮挡住)的(在某个方向上离光源最近的表面是被照射的,后面的表面则没有被照射到

【转载】OpenGL超级宝典笔记——GLSL语言基础

变量 GLSL的变量命名方式与C语言类似.变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量.当然还有一些GLSL保留的名称是不能够作为变量的名称的. 基本类型 除了布尔型,整型,浮点型基本类型外,GLSL还引入了一些在着色器中经常用到的类型作为基本类型.这些基本类型都可以作为结构体内部的类型.如下表: 类型 描述 void 跟C语言的void类似,表示空类型.作为函数的返回类型,表示这个函数不返回值.

OpenGL超级宝典笔记——贝塞尔曲线和曲面(转)

http://my.oschina.net/sweetdark/blog/183721 参数方程表现形式 在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标).类似地,我们也可以用一个参数方程来表示一条曲线.1962年,法国工程师贝塞尔发明了贝塞尔曲线方程.关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔).这里只介绍OpenGL实现贝塞尔的函数. OpenGl定义一条曲线时,也把它定义为一个曲线方程.我们把这条曲线的参数成为u,它的值域就

OpenGL超级宝典笔记——遮挡查询 [转]

目录[-] 遮挡查询之前 包围体 遮挡查询 在一个场景中,如果有有些物体被其他物体遮住了不可见.那么我们就不需要绘制它.在复杂的场景中,这可以减少大量的顶点和像素的处理,大幅度的提高帧率.遮挡查询就是允许我们判断一组图形在进行了深度测试之后是否可见. 遮挡查询之前 为了显示遮挡查询对性能的提升,我们需要一个对照组(不使用遮挡查询来渲染场景). 首先我们先绘制“主遮挡物”.这个主遮挡物不需要太多的细节,一般是墙,天花板,地板之类的物体.在下面的例子中我们,使用6面墙来组成这个主遮挡物. void 

OpenGL超级宝典笔记——画三角形(转)

http://my.oschina.net/sweetdark/blog/161002 学习了画线的知识,我们可以使用GL_LINE_LOOP来画闭合的多边形.但是使用这种方式画出来的只有线框,多边形没有填充颜色.OpenGL支持绘制实心的多边形,并使用当前的颜色进行填充. 三角形 简单的三角形,需要指定三个顶点. 1: glBegin(GL_TRIANGLES); 2: glVertex2f(0.0f, 0.0f); // V0 3: glVertex2f(25.0f, 25.0f); //