opengl算法学习---纹理映射
纹理映射
纹理映射(Texture Mapping),又称纹理贴图,是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程。简单来说,就是把一幅图像贴到三维物体的表面上来增强真实感,可以和光照计算、图像混合等技术结合起来形成许多非常漂亮的效果。
纹理
纹理可看成是一个或多个变量的函数,因此根据纹理定义域的不同,纹理可分为一维纹理、二维纹理、三维纹理和高维纹理。
基于纹理的表现形式,纹理又可分为颜色纹理、几何纹理两大类。
颜色纹理指的是呈现在物体表面上的各种花纹、图案和文字等,即通过颜色色彩或明暗度的变化体现出来的细节。如大理石墙面、墙上贴的字画器皿上的图案等。
几何纹理(也可称为凹凸纹理)是指基于景物表面微观几何形状的表面纹理,如桔子、树干、岩石、山脉等表面呈现的凸凹不平的纹理细节。
生成颜色纹理的一般方法是在一个平面区域(即纹理空间)上预先定义纹理图案,然后建立物体表面的点与纹理空间的点之间的对应—即映射。
以纹理空间的对应点的值乘以亮度值,就可把纹理图案附到物体表面上
用类似的方法给物体表面产生凹凸不平的外观或称凹凸纹理。
普通纹理映射
常见的2D纹理映射实际上是从纹理平面到三维物体表面的一个映射。
凹凸纹理映射
前述各种纹理映射技术只能在光滑表面上描述各种事先定义的花纹图案,但不能表现由于表面的微观几何形状凹凸不平而呈现出来的粗糙质感,如布纹,植物和水果的表皮等
1978年Blinn提出了一种无需修改表面几何模型,即能模拟表面凹凸不平效果的有效方法一几何(凹凸)纹理映射(bump mapping)技术
一个好的扰动方法应使得扰动后的法向量与表面的几何变换无关,不论表面如何运动或观察者从哪一方向观察表面,扰动后的表面法向量保持不变。
Blinn表面法矢扰动法
在表面任一点处沿其法向附加一微小增量,从而生成一张新的表面,计算新生成表面的法矢量以取代原表面上相应点的法矢量。
透明效果与混合
光学原理:透射,折射,反射
颜色调和法
设a为透明体的不透明度,\(0\leq a\leq 1\),则
a=1,完全不透明
a=0,完全透明
alpha融合技术Blending
RGBA(a)
不透明度a表示穿透该表面光线的数量
a=1,完全不透明;a=0,完全透明
gl.blendFunc(src_ factor,dst factor)
混合后颜色=源颜色src_factor+目标颜色dst_factor
源颜色:当前对象
目标颜色:帧缓存像素
透明与Z-Buffer消隐
当对象A是透明的,即B透过A是部分可见时
先画B再画A,可以处理
先画A再画B,深度缓冲会从B取一个像素,同时注意到己经绘制了一个更近的像素(A),然
后它的选择是不绘制B
Z-Buffer消隐不能很好处理透明的物体,需要修正才行
开启深度测试gl.enable(gl.DEPTH_TEST);
绘制所有不透明物体(a=1.0)
锁定深度缓冲区gl.depthMask(false);
按从后向前次序绘制所有半透明物体
释放深度缓冲区gl.depthMask(true);
光线跟踪
光线跟踪算法[WH1T80]是生成高度真实感图形的主要算法之一。利用光线跟踪技术能生成传统图形学算法很难模拟的整体光照明效果,生成各种逼真的视觉图形。由于其算法简单,易于实现,因而在CAD及图形学等许多领域得到了广泛应用,受到人们广泛的重视。
整体光照明模型
简单光照明模型中,我们假定所考虑的物体表面是不透明的,实际上并非所有的物体都是不透明的,例如玻璃、花瓶、车窗等。
简单光照模型不考虑周围环境对当前景物表面的光照明影响,忽略了光在环境景物之间的传递,很难表现自然界复杂场景的高质量真实感图形。为了增加图形的真实感,必须考虑环境的漫反射、镜面反射和规则投射对景物表面产生的整体照明效果。
物体表面入射光的构成
(1)光源直接照射(2)其它物体的反射光(3)透射光
局部光照明模型仅考虑了(1)
Whitted光照模型
Whitted光照模型基于如下假设:
物体表面向视点方向V辐射的光亮度\(I_{\lambda}\)由三部分组成:
(1)光源直接照射引起的反射光亮度\(I_{l\lambda}\)
(2)来自V的镜面反射方向R的其它物体反射或折射来的光的亮度\(I_{s\lambda}\)
(3)来自V的透射方向T的其它物体反射或折射来的光的亮度\(I_{t\lambda}\)
光线跟踪算法的基本原理
自然界中光线的传播过程
光源->物体表面->物体表面->人眼
光线跟踪是自然界光照明物理过程的近似逆过程,即逆向跟踪从光源发出的光经环境景物间的多次反射、折射后投射到景物表面,最终进入人眼的过程。
光线传播的逆过程
从视点向每个象素发出一条光线,它与场景中的一些物体表面相交,最近的交点即为可见点,记为P,像素的亮度即由P点的亮度确定。由Whitted光照模型可知,P点的亮度由三部分组成:其中\(I_{l\lambda}\)可以直接由局部光照模型计算得到。
为了求\(I_{s\lambda}\) ,和\(I_{t\lambda}\),从P点发出反射光线和透射光线,它分别交场景中的物体表面于Ps和Pt,Ps和Pt点的亮度即分别为\(I_{s\lambda}\) ,和\(I_{t\lambda}\),,将它们求出代入Whitted模型即可。但是,\(I_{s\lambda}\) 和\(I_{t\lambda}\),同样由Whitted模型确定,即Whitted模型是一个递归式,从而计算\(I_{s\lambda}\) ,和\(I_{t\lambda}\),需要重复以上的计算过程:计算局部光亮度、发出反射光线与透射光线可以用一棵光线树来表示
递归终止条件:
1.光线不与场景中的任何物体相交
2.被跟踪的光线达到了给定的层次
3.由于Ks和Kt都小于1,当光线经过反射和折射后,其亮度会衰减。因此可以预先设置一个阈值,在进行光线跟踪时,若被跟踪光线对像素亮度的贡献小于这个阈值,便停止跟踪。
算法描述
设置视点,投影平面以及窗口的参数;
For(窗口内的每一条扫描线)
for(扫描线上的每一个像素)
{确定从视点指向像素中心的光线ray;
像素的颜色=RayTracing(ray,1) ;
}
Color RayTracing(Ray ray, int depth)
{求ray与物体表面最近的交点P;
if(有交点)
{用局部光照明模型计算P点的Ic;
color=Ic;
if (depth<给定的最大跟踪层次)
{计算ray的反射光线;
Is=RayTracing(反射光线,depth+ 1);
if(物体是透明的)
{计算ray的透射光线;
It=RayTracing(透射光线,depth+ 1);
}
color=Ic+ Is+It;
}
}else color=black;
return color;
}
光线跟踪算法
根据光线跟踪基本原理,假设在显示分辨率为NM的屏幕上生成图形,必须从视点出发通过屏幕向景物发射NM条光线
设每根光线在场景中经过反射和折射平均派生出d根光线,并设每一景物交点朝光源发射m条阴影探测光线,则总的光线数增加至(m+ 1) dNM。当m为2, d为5, N为800, M为600时,其光线数目是720万条
这意味着需进行720万次直线与景物的求交计算才能完成图形的绘制。庞大的求交量使图形绘制耗费大大增加。生成一幅中等复杂程度的真实感图形需要数分钟至数小时
优点
不仅考虑到光源的光照,而且考虑到场景中各物体之间的反射的影响,因此显示效果十分逼真。
用光线跟踪方法,在显示的同时,自然完成消隐功能,不用事先消隐。
光线跟踪能产生阴影的效果。
每条光线的处理过程相同,结果彼此独立,因此可以在并行处理的硬件上快速实现光线跟踪。
缺点
计算量大。
算法忽略了穿过象素内其他各点投向眼睛的光线,所以它所绘制的画面可能出现严重的走样现象。
加速光线跟踪技术
包围盒技术
包围盒技术是用几何形状相对简单的封闭表面(如长方体、球、圆柱等)将一复杂景物包裹起来
如图中的虚线为最简单的椭球形包围盒。
优点:
场景分层次表示法和包围盒技术用光线与少量形状简单的包围盒的求交测试取代与大量景物表面的求交计算,提高了算法效率。
缺点:
这种方法的问题在于许多情况下简单的包围盒不能紧密地包裹其中所含的景物,因此降低了包围盒测试的可靠性。而复杂的包围盒又将导致光线和包围盒的求交计算变得困难。
空间剖分技术
这一方法利用相邻网格单元的空间连贯性,使光线能跨越一个个空的网格单元,直到求得它与景物的第一个交点时为止。
第一种方法:
将空间均匀地分割成大小相同的小立方体网格单元。该方法可以简化光线穿越空间网格的计算,且便于硬件实现,但缺点是需占用较大的存储区域,当景物在空间分布稀疏时,被跟踪的光线可能需穿越大量的空网格才能到达目标。
第二种方法:
非均匀网格剖分,即根据景物的形状把空间分成大小不同的子空间,典型的方法是采用八叉树和二叉树的空间分割,这种剖分可减少每条被跟踪的光线所需穿越的空网格单元数目,所需要的内存耗费较小
这两种方式主要的不同点在于它们所选取的辅助数据结构不同。