6.1 纹理管线(The Texturing Pipeline)
在空间中的位置是纹理化过程的起点。
该位置可以在世界空间中,但通常位于模型的参照系中,因此随着模型的移动,纹理也随之移动。
在空间上,通过该点应用一个投影函数以获取一组数据——纹理坐标(texture coordinates),这种操作被称为映射(mapping)
单个纹理的广义纹理管线
坐标转换
6.1.1 投影函数(The Projector Function)
根本目的:获取表面的位置并将其投影到纹理坐标空间中,通常是二维(u,v)空间
*uv坐标可以用编辑顶点位置的相同方式来编辑
其他输入可用于投影函数。 例如,可以使用表面法线来选择用于表面的六个平面投影方向中的哪一个。
其他投影函数根本不是投影,而是表面创建(surface creation)和细分tessellation的隐含部分。 例如,参数化曲面具有自然的(u,v)值集作为其定义的一部分。纹理坐标也可以根据各种不同的参数生成,例如视图方向,表面温度或其他任何可想象的参数。 投影函数的目标是生成纹理坐标。 根据位置推论得出这些只是实现此目的的一种方法。
- 球形投影将点投射到以某个点为中心的虚拟球体上。 圆柱投影计算的等高线坐标与球面投影相同,而v纹理坐标计算为沿圆柱轴的距离。
- 此投影对于具有自然轴的对象(例如旋转表面)很有用。 当表面垂直于圆柱轴垂直时会发生变形。
- 平面投影就像X射线束一样,沿着一个方向平行投影,并将纹理应用于所有表面。 它使用正交投影。这种类型的投影可用于贴花。
非交互式渲染器(Non-interactive renderer)通常将这些投影函数称为渲染过程本身的一部分。 单个投影函数可能足以满足整个模型的需要,但美术师通常必须使用工具来细分模型并分别应用各种投影函数。如下图
纹理坐标空间并不总是二维平面。 有时是三维空间。 在这种情况下,纹理坐标表示为三元素矢量(u,v,w),沿投影方向具有一定深度。
6.1.2 映射函数(The Corresponder Function)
映射函数将纹理坐标转换为纹理空间位置。 即
它们提供了将纹理应用于表面的灵活性。 映射函数的一个示例是使用API选择现有纹理的一部分进行显示。 仅此子图片将在后续操作中使用。
wrap(DirectX), repeat(OpenGL), or tile,图像在整个表面上重复。
mirror,图像在整个表面上重复,但在其他每一次重复中都被镜像(翻转)。
clamp(DirectX) or clamp to edge(OpenGL),超出[0,1]范围的值将被夹紧到该范围。
border(DirectX) or clamp to border(OpenGL),[0,1]外部的纹理坐标以单独定义的边框颜色渲染
*可以为每个纹理轴分配不同的映射函数,例如,纹理可以沿u轴repeat并在v轴上clamp。
6.1.3 纹理值(Texture Values)
最直接的纹理值是RGB三元组,用于替换或修改表面颜色。 同样,可以返回一个灰度值。另一种要返回的数据是RGBα,α值通常是颜色的不透明度,它确定颜色可能影响像素的程度。
6.2 图片纹理(Image Texturing)
我们已经完成了计算纹理空间位置的过程。 现在,我们将解决在给定位置的情况下从图像纹理获取纹理值的问题和算法。 在本章的其余部分中,图像纹理将简称为纹理。 另外,当我们在此处引用像素单元(cell)时,是指围绕该像素的屏幕网格单元。 如第5.4.1节所述,像素实际上是显示的颜色值,该颜色值可能(并且应该具有更好的质量)受到与其关联的网格单元外部的样本的影响。
像素着色器通过将纹理坐标值传递给诸如texture2D之类的调用来访问纹理。 这些值位于(u,v)纹理坐标中,通过对应函数将其映射到[0.0,1.0]范围。 GPU负责将此值转换为texel坐标。 不同API中的纹理坐标系之间有两个主要区别。 在DirectX中,纹理的左上角为(0,0),而OpenGL中左下角为(0,0)。
像素具有整数坐标,但是我们经常要访问像素之间的位置并在它们之间融合。 这就提出了一个问题,即像素中心的浮点坐标是什么。通常使用floor(向下取整)计算。
6.2.1 放大(Magnification)
缩小(Minification)
当纹理缩小时,几个纹理像素可能会同时覆盖像素的单元。 为了获得每个像素的正确颜色值,应该整合影响像素的纹理像素的效果。 然而,难以确定特定像素附近所有纹理像素的精确影响,并且实际上不可能实时地完美地做到这一点。
mipmapping
通过在金字塔的底部获取原始图像(级别0)并在下一级向上将每个2×2区域平均为texel值来形成mipmap。
区域求和表(Summed-Area Table)
避免过度模糊的另一种方法是求和面积表(SAT)。 要使用此方法,首先要创建一个数组,该数组的大小等于纹理的大小,但包含更多的颜色精度
参考文档
无约束各向异性过滤(Unconstrained Anisotropic Filtering)
Mipmap与各向异性过滤。 左侧进行了三线性mipmapping,右侧进行了16:1各向异性过滤。 展望未来,各向异性过滤可提供更清晰的结果,并具有最小的混叠。
6.2.3 体纹理(Volume Textures)
图像纹理的直接扩展是通过(u,v,w)(或(s,t,r)值)访问的三维图像数据。 例如,医学成像数据可以生成为三维网格; 通过在该网格中移动多边形,可以查看这些数据的二维切片。 一个相关的想法是用这种形式表示体积照明。 通过找到其在该体积内的位置值以及光的方向,可以找到表面上某个点的照明。
优点:
- 可以将三维位置直接用作纹理坐标,因此能够跳过为三维网格找到良好的二维参数化的复杂过程。 这避免了二维参数化中常见的变形和接缝问题。
- 可以用于表示诸如木材或大理石的材料的体积结构。 带有这种纹理的模型看上去效果相当逼真
缺点:
- 具有更高的存储要求,并且过滤成本更高
- 使用体纹理作为表面纹理会非常低效,因为三维纹理中的绝大多数样本都没起到作用。
6.2.4 立方体贴图(Cube Maps)
主要用于环境映射。
6.2.5 纹理表示(Texture Representation)
为了能够为GPU分配尽可能多的工作,通常建议更改状态尽可能少。 为此,可以将多个图像放入一个较大的纹理中,称为纹理图集(texture atlas)
6.2.6 纹理压缩(Texture Compression)
直接解决内存和带宽问题以及缓存问题的一种解决方案是固定速率纹理压缩。 通过让GPU动态地解码压缩纹理,纹理可以需要更少的纹理内存,因此可以增加有效的缓存大小。
参考文档
6.3 程序化纹理(procedural texture)
也可译作“过程纹理”
尽管过程纹理通常在脱机渲染应用程序中使用,但是图像纹理在实时渲染中更为常见。 这是由于现代GPU中图像纹理化硬件的极高效率,它在一秒钟内可以执行数十亿次纹理访问。 但是,GPU架构正在朝着更便宜的计算和(相对)更昂贵的内存访问发展。 这些趋势已使过程纹理在实时应用程序中得到更多使用。
通常用于一些大自然的事物,能够用噪波模拟的事物。
6.4 纹理动画(Texture Animation)
纹理坐标也不必是静态的。 应用程序设计人员可以在网格的数据本身中,也可以通过在顶点或像素着色器中应用的函数,在帧之间逐帧更改纹理坐标。
通过将矩阵应用于纹理坐标可以创建更精细的效果。 除平移外,这还允许进行线性变换,例如缩放,旋转和剪切,图像变形和变形变换和广义投影。
6.5 材质贴图(Material Mapping)
纹理的常见用途是修改影响着色方程的材料属性。
6.6 Alpha贴图(Alpha Mapping)
使用alpha混合或alpha测试可以将alpha值用于许多效果,例如有效地渲染树叶,爆炸和远处的物体等。
Alpha测试(Alpha Testing)
当某个片元的alpha值满足某个要求(如小于某一阈值),便将其舍弃。
Alpha测试与mipmap一同使用时,会使物体看上去更加透明
关于AlphaTest、AlphaBlend、Alpha to coverage,参考文档
6.7 凹凸映射(Bump Mapping)
6.7.1 Blinn的方法(Blinn’s Methods)
提出用bu和bv两个值来记录法线的偏移量,这种贴图通常被称作offset vector bump map或offset map。
6.7.2 法线贴图(Normal Mapping)
将法线的xyz数值存储为rgb
6.8 视差纹理映射(Parallax Mapping)
凹凸映射的局限在于物体无法发生自遮挡,比如一堵砖墙,一个砖头无法挡住另一个砖头。而视差贴图可以做到,视差贴图的关键思想是通过检查被发现的可见物体的高度来对像素中应该看到的物体进行合理的猜测
相关文档
*视差贴图的开销较大
6.8.1 视差遮挡贴图(Parallax Occlusion Mapping)
视差遮挡贴图,也被称为浮雕贴图,
6.9 贴图光(Textured Lights)
纹理还可以用于增加光源的视觉丰富度,并允许复杂的强度分布或聚光灯功能。 对于所有照明都限于圆锥形或截头圆锥形的灯光,可以使用投射纹理来调制光强度。 这样就可以形成聚光灯,图案灯甚至“幻灯机”效果(如图)