阅读:1500回复:0
OpenGL系列讲座(17)
2.4 映射方式
在本章的第一个例程中,纹理图像是直接作为画到多边形上的颜色。实际上,可以用纹 理中的值来调整多边形(曲面)原来的颜色,或用纹理图像中的颜色与多边形(曲面)原来 的颜色进行混合。因此,OpenGL提供了三种纹理映射的方式,这个函数是: void glTexEnv{if}[v](GLenum target,GLenum pname,TYPE param); 设置纹理映射方式。参数target必须是GL_TEXTURE_ENV;若参数pname是 GL_TEXTURE_ENV_MODE,则参数param可以是GL_DECAL、GL_MODULATE或GL_BLEND,以说明 纹理值怎样与原来表面颜色的处理方式;若参数pname是GL_TEXTURE_ENV_COLOR,则参数 param是包含四个浮点数(分别是R、G、B、a分量)的数组,这些值只在采用GL_BLEND纹 理函数时才有用。 2.5 纹理坐标 2.5.1 坐标定义 在绘制纹理映射场景时,不仅要给每个顶点定义几何坐标,而且也要定义纹理坐标。经 过多种变换后,几何坐标决定顶点在屏幕上绘制的位置,而纹理坐标决定纹理图像中的哪一 个纹素赋予该顶点。并且顶点之间的纹理坐标插值与基础篇中所讲的平滑着色插值方法相同。 纹理图像是方形数组,纹理坐标通常可定义成一、二、三或四维形式,称为s,t,r和q 坐标,以区别于物体坐标(x,y,z,w)和其他坐标。一维纹理常用s坐标表示,二维纹理常用(s,t) 坐标表示,目前忽略r坐标,q坐标象w一样,一半值为1,主要用于建立齐次坐标。OpenGL 坐标定义的函数是: void gltexCoord{1234}{sifd}[v](TYPE coords); 设置当前纹理坐标,此后调用glVertex*()所产生的顶点都赋予当前的纹理坐标。对于 gltexCoord1*(),s坐标被设置成给定值,t和r设置为0,q设置为1;用gltexCoord2*() 可以设置s和t坐标值,r设置为0,q设置为1;对于gltexCoord3*(),q设置为1,其它坐 标按给定值设置;用gltexCoord4*()可以给定所有的坐标。使用适当的后缀(s,i,f或d)和 TYPE的相应值(GLshort、GLint、glfloat或GLdouble)来说明坐标的类型。注意,整型纹 理坐标可以直接应用,而不是象普通坐标那样被映射到[-1,1]之间。 2.5.2 坐标自动产生 在某些场合(环境映射等)下,为获得特殊效果需要自动产生纹理坐标,并不要求为用 函数gltexCoord*()为每个物体顶点赋予纹理坐标值。OpenGL提供了自动产生纹理坐标的函 数,其如下: void glTexGen{if}[v](GLenum coord,GLenum pname,TYPE param); 自动产生纹理坐标。第一个参数必须是GL_S、GL_T、GL_R或GL_Q,它指出纹理坐标s,t,r,q 中的哪一个要自动产生;第二个参数值为GL_TEXTURE_GEN_MODE、GL_OBJECT_PLANE或 GL_EYE_PLANE;第三个参数param是一个定义纹理产生参数的指针,其值取决于第二个参数 pname的设置,当pname为GL_TEXTURE_GEN_MODE时,param是一个常量,即GL_OBJECT_LINEAR、 GL_EYE_LINEAR或GL_SPHERE_MAP,它们决定用哪一个函数来产生纹理坐标。对于pname的其 它可能值,param是一个指向参数数组的指针。 下面是一个运用自动产生纹理坐标函数的实例texpot.c: 例 3-4 纹理坐标自动产生例程 texpot.c #include "glos.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void myinit(void); void makeStripeImage(void); void CALLBACK display(void); void CALLBACK myReshape(GLsizei w, GLsizei h); #define stripeImageWidth 64 GLubyte stripeImage[3*stripeImageWidth]; void makeStripeImage(void) { int j; for (j = 0; j < stripeImageWidth; j++) { stripeImage[3*j] = 255; stripeImage[3*j+1] =255-2*j; stripeImage[3*j+2] =255; } } /* 参数设置 */ GLfloat sgenparams[] = {1.0, 1.0, 1.0, 0.0}; void myinit(void) { glClearColor (0.0, 0.0, 0.0, 0.0); makeStripeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage1D(GL_TEXTURE_1D, 0, 3, stripeImageWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, stripeImage); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, sgenparams); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_1D); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glFrontFace(GL_CW); glCullFace(GL_BACK); glMaterialf (GL_FRONT, GL_SHININESS, 64.0); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); glRotatef(25.0, 1.0, 0.0, 0.0); auxSolidTeapot(1.5); glPopMatrix (); glFlush(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { float a=3.5; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-a, a, -a*(GLfloat)h/(GLfloat)w, a*(GLfloat)h/(GLfloat)w, -a, a); else glOrtho (-a*(GLfloat)w/(GLfloat)h, a*(GLfloat)w/(GLfloat)h, -a, a, -a, a); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA); auxInitPosition (0, 0, 500, 500); auxInitWindow (" Teapot TextureMapping"); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); } 以上程序运行结果是在屏幕上显示一个带条状纹理的茶壶。其中用到了前面所讲的一维 纹理映射定义,以及本节的纹理坐标自动产生。 图 3-2-2 贴纹理的茶壶 |
|
|