OpenGL Auto Texture Coordinates Generation
OpenGL自动纹理坐标生成 (OpenGL Auto Texture Coordinates Generation)
OpenGL中有两种方法为顶点(Vertex)指定纹理坐标:
由人工给每个顶点分配坐标。可以通过函数glTexCord*()来完成。 .
由OpenGL自动为每个顶点分配坐标。这个任务由函数glTexGen*()来完成。 .
一开始,我对glTexGen*()这个函数并不是十分的理解,不知道OpenGL到底是怎样自动生成纹理坐标的。查阅了相关的资料,才开始有一点明白:要完成自动纹理坐标的生成,首先要指定以什么样的模式(既什么样的算法)来生成纹理坐标。 在OpenGL1.1中,可以指定三种纹理坐标生成模式:GL_OBJECT_LINEAR, GL_EYE_LINEAR, GL_SPHERE_MAP,在OpenGL1.3中,又添加了两种生成模式:GL_REFLECTION_MAP,GL_NORMAL_MAP.对这些模式的理解是使用glTexGen*()的关键,也决定了纹理贴图后的效果。下面就分析这些模式的具体含义:
GL_OBJECT_LINEAR . 在这个模式下,其纹理生成函数是顶点坐标(x0,y0,z0,w0)的线性组合: 生成的坐标=p0*x0+p1*y0+p2*z0+p3*w0; . 假如我们以(p0,p1,p2,p3)为参数构造一个平面:p0*X+p1*Y+p2*Z+p3=0; . 若(p0,p1,p2)已经被归一化,则任何一点到这个平面的距离为: (p0*x+p1*y+p2*z+p3)/sqrt(p0*p0+p1*p1+p2*p2)=p0*x+p1*y+p2*z+p3; 可以看出:此模式下生成的坐标相当于顶点坐标到特定平面的距离。
2. GL_EYE_LINEAR . 在这个模式下,其纹理生成函数也是顶点的人眼坐标(xe,ye,ze,we)的线性组合: 生成的坐标=p0′*xe+p1′*ye+p2′*ze+p3′*we; . 其中:(p0′,p1′,p2′,p3′)=(p0,p1,p2,p3)*inverse(M) . 可以看出:GL_EYE_LINEAR和GL_OBJECT_LINEAR模式具有类似的纹理生成函数,唯一的差别在于GL_OBJECT_LINEAR 是物体空间内,在视发生变化的情况下,纹理坐标不会随着视的改变而改变;而GL_EYE_LINEAR是在视空间内,在视发生变化的情况下,纹理坐标会随着视的改变而改变,用而改变贴图后的效果。
GL_S, X plan
GL_OBJECT_LINEAR GL_S, Oblique plane
GL_EYE_LINEAR GL_S, Oblique plane
3. GL_SPHERE_MAP . 在这个模式下,其纹理坐标生成算法如下: . 以u标识在视坐标系下原点到顶点的一个单位向量; . 以n’标识在视坐标系下顶点的法向量; . 以r=trans(rx,ry,rz)标识顶点的反射向量,则t可以由以下公式计算得到: r=u-2*trans(n’)(n’u); . 另m=2*sqrt(rx*rx+ry*ry+(rz+1)*(rz+1)),则生成的坐标: (S,T)=( rx/m+0.5, [...]
如何投影一个纹理
如何投影一个纹理 原文出处:SGI OpenGL 教程 翻译:心蓝 潘李亮。 Email: Xheartblue@etang.com 译者前言: 影子有两种经典的实现方法:一是Shadow Volume 。二是Shadow Mapping。如何用Light Mapping来实现投影影子呢?这就要用到Project Texture.直接翻译的意思就是投影纹理—-把一个纹理像放幻灯片一样投影到场景中去,假想有一个电影机在放电影,沿着镜头方向,电影将被投在墙上,而投影纹理就类似于这种情况,我们想要使用的纹理就是电影机里Film。 以下是我在SGI的教程中找到的文章。奉献给大家。 How to Project a Texture http://www.sgi.com/software/opengl/advanced98/notes/node49.html 投影一个纹理图象到你自己合成的环境里在许多步骤上和投影渲染场景到显示器上的步骤是一样的。投影纹理的关键是纹理变换矩阵的内容。该变换矩阵由以下三个变换串联起来: 1.视图/模型变换 — 朝着需要投影到场景的方向。 2.投影变换(透视或者正交) 3.缩放和偏移(bias 是叫偏移吗?),它将近裁剪面到纹理坐标。 Projecting a texture image into your synthetic environment requires many of the same steps that are used to project the rendered scene onto the display. The [...]
Projective Texture的原理与实现
Projective Texture是比较常见的一种技术,实现起来代码也就区区的不过百行,了解其原理及技术细节是我们的重点,知其然,知其所以然。 粗略的说就是想象场景中有台投影仪(Projector),texture 们投影的内容,把纹理放在近裁剪面(near clip plane)上,沿着投影仪的方向把纹理投影到场景中。Xheartblue兄翻译了一篇文章,很好的给投影纹理的原理进行的阐述[1],有兴趣阅读原文的可以访问这里[2],这本书可以是好东东啊!! 在这里有几个概念不能混淆了:Camera–人眼坐标;Projector–投影仪坐标。在纹理坐标自动生成过程中,关键的就是如何把人眼坐标系中的vertex转换到Projector Space,进而转换到Projector clip plane,最后规范化为纹理坐标[0,1]。在我的实现中是把Projector定义为一个Camera(注意:不同于显示场景的Camera),所以 Projector有Camera的各项属性,我们可以通过gluPerspective,gluLookAt对其进行设置。如何为Projective texture自动生成纹理坐标是重点,这个过程和物体顶点变换为窗口坐标是类似的。在NV Developer Document[3]中有篇文档说的很详细,截图如下:
对上图可以这么理解,Camera用于物体顶点坐标到规范化设备的生成,Projector用于物体顶点纹理坐标的生成。而在不同模式下纹理坐标的生成方式是不同。 根据glTexGen的不同参数GL_OBJECT_LINEAR,GL_EYE_LINEAR来确定纹理生成的函数。在Projective texture mapping一文中给出的纹理坐标生成公式是:
注意:此处Vo是基于物体坐标系的,无论物体在人眼坐标系中如何变换,其物体坐标是不变的,根据公式其纹理坐标也是不变的。所以在 GL_OBJECT_LINEAR模式下看到的纹理是紧贴在物体表面的。而Ve是基于人眼坐标系的,在Projector设置好位置后是基于人眼坐标不变的。 我们来看Object Linear模式下纹理坐标是如何生成的:
此处的M(Model Matrix)是模型变换矩阵,不同于OPENGL的MODELVIEW MATRIX(这在模型变换的基础上还进行了视图变换)。顶点坐标左乘M后变换到World Space,为什么要变换到World Space呢??这是因为Camera和Projector都是通过gluLookAt而定义在世界坐标中,这就像座桥梁,唯有通过它才能使得人眼视图体中的顶点转换到Projector定义的视图体内,才能进一步求出相应的纹理坐标。Vp是projector的view matrix(由gluLookAt定义),累加左乘得到projector space中的坐标。Pp是projector的projection matrix(由gluPerspective定义),累加左乘得到projector clip space中的坐标。最后累加偏移矩阵,使纹理坐标的s、t、 映射到[0,1]内。 本文关注的是Eye Linear模式下纹理坐标的生成,有了以上对Object Linear的理解就好办了,公式如下:
Eye Linear模式是把人眼坐标下的顶点左乘OPENGL的MODELVIEW 转换到world space中。Eye Linear和Object Linear的最后一项略有不同,Ve-1是Camera视图矩阵的逆矩阵,目的是把人眼坐标下的顶点转换到世界坐标系中(还记得为什么一定要转换到世界坐标中吗?桥梁的作用,前面已经讲过了^_^)。总之,无论何种模式下使用何种方法都需要把物体顶点转换到世界坐标系中,这样才能通过累加 Vp(Projector的view matrix)、Pp(Projector的projection matrix)、偏移矩阵得到纹理坐标。 Pointer在其BLOG中对上述问题也有详细的描述[4],有很好的启发作用。值得拜读! 纹理坐标的自动生成大致就如此了,看点代码或许能更好的理解吧! //—————————————-ProjTexture.h———————————— /******************************************************** Usage Instruction: //in init() glGenTextures(1, &id); [...]
