真实感图形 授课教师: 单位:
主要内容 引言 光照明模型 多边形物体的明暗处理 光线跟踪算法 纹理映射 辐射度方法 实时绘制技术 非真实感图形绘制技术
纹理映射 纹理(texture)通常指物体的表面细节
纹理映射 纹理映射技术给出了定义表面上任意点属性的一种方式 漫反射率 镜面反射率 透明度 折射率 …
纹理映射 两类最常使用的纹理 颜色纹理 几何纹理
颜色纹理 确定表面上颜色纹理的两种方法 预先建立表面的纹理模型 纹理映射:建立表面上的每一点和一已知图像上的点的对应关系,取图像上相应点的颜色值作为表面上各点的颜色值
纹理映射 采用景物表面的参数化表示来确立表面的纹理映射坐标,即可实现纹理图像在景物表面的映射 景物表面的参数化表示为f(u,v) 纹理图像表示为T(s,t) 建立景物表面参数空间(u,v)和纹理图像参数空间(s,t)之间的一一对应关系
纹理映射 示例
几何纹理 凹凸映射(bump mapping) 法向映射(normal mapping) 在不改变物体宏观几何的前提下,模拟物体表面粗糙的、褶皱的、凹凸不平的光照效果 法向映射(normal mapping) 利用法向纹理保证高质量的表面细节复现 位移映射(displacement mapping) 利用纹理改变物体表面上点的几何位置,获得很强的深度感和细节
几何纹理 法向映射(Normal mapping) 借助低精度模型和一个法向纹理,获得高精度模型的绘制效果 先计算高精度模型的法向,将其保存在法向纹理中,再将法向纹理映射到低精度模型上进行光照计算
几何纹理 位移映射(displacement mapping) 依据与表面上点所对应的纹理值,沿表面法向偏移该点的几何位置 能产生很强的深度感 自遮挡 自阴影 轮廓 计算代价大 与凹凸映射、法向映射相比
凹凸映射 思想 方法 在应用光照明模型计算景物表面光亮度时,对景物表面法向进行微小的扰动 物体表面S由参数方程S=S(u,v) 表示 S上的任意一点(u,v)的法向n=Su×Sv 沿着表面S的法线方向叠加一个微小的扰动量P(u,v)定义了一张新的表面S’
凹凸映射 方法(cont.) 新表面的法向可用 n’=Su’×Sv’ 计算 在计算表面S的光亮度时,取新表面的法向量n’取代原光滑表面法向量n,生成物体表面的凹凸效果 扰动函数P(u,v)既可解析定义,也可通过二维图像定义
凹凸映射 示例
凹凸映射 示例
纹理反走样 纹理走样示例
纹理反走样 纹理走样原因
纹理反走样 常用纹理反走样方法 前置滤波方法 超采样方法 Mipmap方法
纹理反走样 前置滤波方法 确定屏幕像素P上可见的景物表面区域A 将区域A直接映射到纹理空间区域T 取区域T内的所有纹理像素颜色值的平均作为景物表面区域A的平均纹理颜色 代入光照明模型,计算出 像素P应显示的光亮度值 前置滤波
纹理反走样 前置滤波效果 走样 前置滤波
纹理反走样 超采样方法 将屏幕像素P的四个角点分别映射到纹理空间,得到四个纹理像素值
纹理反走样 超采样方法效果 走样 超采样
纹理反走样 Mipmap方法 MIP来源于 拉丁语“multum in parvo”,意为“many things in a small place” 目前应用最广的纹理反走样算法之一 通过预先计算并存贮原始 纹理图像的一组多分辨率 版本,能显著地节省纹理 反走样的计算量
Mipmap方法 预处理:生成一个由不同分辨率图像构成的纹理图像序列 从原始纹理图像出发,生成一个其分辨率为原始图像1/4的新的纹理图像版本 新版本中的每一个像素值取为原始图像中相对应的四个像素颜色值的平均 类似地基于所得到的新纹理图像版本生成一个更低分辨率的、尺寸更小的纹理图像版本 这一过程一直持续到最后生成的纹理图像仅包含一个像素为止
Mipmap方法 预处理
Mipmap方法 映射阶段 屏幕上的每一像素内的可见表面区域被映射到原始纹理图像上的一块区域 估计该区域所覆盖的原始纹理图像中像素的个数并以此作为选取适当分辨度的纹理图像版本的一种测度
Mipmap方法 映射阶段(cont.) 从预先构造的纹理图像序列中找出其压缩率最接近当前纹理像素与屏幕像素比率的两个纹理图像 在相邻分辨率的两纹理图像上计算当前屏幕像素映射点的纹理颜色值 根据两纹理图像对原始图像的压缩率在所得到的两个纹理颜色值间取加权平均,作为当前屏幕像素可见表面区域的颜色值
Mipmap方法 映射阶段(cont.)
Mipmap效果 无Mipmap 有Mipmap
纹理反走样效果对比
纹理映射实例程序 利用OpenGL实现纹理映射的三个主要步骤 生成纹理数据 将纹理数据载入纹理内存 将纹理数据映射到物体表面
纹理映射实例程序 讲解光盘中所附的程序 DEMO
纹理映射实例程序 Step1:生成纹理数据 void glInit (void) { … if (!loadTGA ("texture.tga", 13)) printf ("texture.tga not found!\n"); } int loadTGA (char *name, int id) unsigned char *imageData = NULL; …. imageData = (unsigned char*)getData (s, size, imageBits); /* no image data */ if (imageData == NULL) returnError (s, TGA_BAD_DATA);
纹理映射实例程序 Step2:将纹理数据载入纹理内存 int loadTGA (char *name, int id) { … glBindTexture (GL_TEXTURE_2D, id); glPixelStorei (GL_UNPACK_ALIGNMENT, 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_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glTexImage2D (GL_TEXTURE_2D, 0, texFormat, imageWidth, imageHeight, 0, texFormat, GL_UNSIGNED_BYTE, imageData); ... }
纹理映射实例程序 Step3:将纹理数据映射到物体表面 void drawFace (void) { glEnable (GL_TEXTURE_2D); /* enable texture mapping */ glBindTexture (GL_TEXTURE_2D, 13); /* bind to our texture, has id of 13 */ … glBegin (GL_QUADS); glTexCoord2f (0.2f,0.2f); /* lower left corner of image */ glVertex3f (-10.0f, -10.0f, 0.0f); glTexCoord2f (0.6f, 0.2f); /* lower right corner of image */ glVertex3f (10.0f, -10.0f, 0.0f); glTexCoord2f (0.6f, 0.6f); /* upper right corner of image */ glVertex3f (10.0f, 10.0f, 0.0f); glTexCoord2f (0.2f, 0.6f); /* upper left corner of image */ glVertex3f (-10.0f, 10.0f, 0.0f); glEnd (); glDisable (GL_TEXTURE_2D); /* disable texture mapping */ }
纹理映射实例程序 结果