1、什么是反锯齿(Antialiasing)

反锯齿是指*滑图像的边缘减少锯齿(阶梯状线条)的技术。

反锯齿通常通过多重采样(multisampling)实现,你使用超过一个像素(“采样”)决定最终图像中一个像素的颜色。

每个像素的采样点越多,最终图像越*滑。 PC和Xbox 360*台都支持全屏反锯齿(FSAA) 模式,额外的数据会渲染到一个渲染目标并用来作为创建最终图像的采样器。4x FSAA通过将场景渲染到一个长宽都为后备缓冲两倍的渲染目标,实现每个像素使用4个采样点,使用渲染目标中的额外采样点创建最终的反锯齿的图像。PC上2x FSAA也很常见并被Xbox 360*台支持。

使用CheckDeviceMultiSampleType方法可以罗列你的游戏设备的antialiasing支持、也可以使用PresentationParameters的MultiSampleQuality和MultiSampleType属性为后备缓冲选择一个antialiasing模式。更多的信息可见How To: Enable Antialiasing (Multisampling)。你可以将GraphicsDeviceManager的PreferMultiSampling设置为true让GraphicsDeviceManager选择antialiasing模式。

你可以使用RenderState 属性实时启用/禁用multisampling。

 

2、什么是颜色混合(Color Blending)

颜色混合是指将两个颜色混合在一起产生第三个颜色的处理过程。

第一个颜色叫做源颜色(source color)。第二个颜色叫做目标颜色(destination color),这个颜色已经存在(例如在后备缓冲中)。每个颜色都一个单独的的混合因子确定每种颜色在最终图像中的多少。当源颜色和目标颜色乘以各自的混合因子后,最终结果根据指定的混合函数进行合成。通常混合函数只是简单的相加。

完整公式如下所示:

(source × source blend factor) (blend function) (destination × destination blend factor)

源颜色的混合因子是由SourceBlend属性指定的,目标颜色的混合因子是由DestinationBlend属性指定的。BlendFunction属性指定使用的混合函数,通常是BlendFunction.Add,这种情况公式如下表示:

(source × SourceBlend) + (destination × DestinationBlend)

当AlphaBlendEnable属性为false时,在绘制时不进行混合。这种情况中,源像素会覆盖目标像素。当AlphaBlendEnable属性为true时,你可以使用SourceBlend和DestinationBlend属性创建很多特定的效果:

Blend Type

Blend Settings

Alpha Blending

(source × Blend.SourceAlpha) + (destination × Blend.InvSourceAlpha)

Additive Blending

(source × Blend.One) + (destination × Blend.One)

Multiplicative Blending

(source × Blend.Zero) + (destination × Blend.SouceColor)

2X Multiplicative Blending

(source × Blend.DestinationColor) + (destination × Blend.SourceColor)

RangeSeekBar 锯齿 锯齿模式_深度测试

图1 这张图片显示了四种常见的混合模式。从左至右分别是:Alpha blending,Additive blending,Multiplicative blending和2X Multiplicative blending。每列上面的图像是源图像,下面是添加了目标图像后的最终效果。

Alpha blending使用源颜色的alpha通道创建一个透明效果。例如,你将后备缓冲清除为 Color.Gray,颜色为(0.5,0.5,0.5,1)。如果你指定带有特定alpha值的Color.White颜色(1,1,1,0.4),将会使用60%的目标颜色和40%的源颜色:(0.5 x 0.6) + (1 x 0.4),结果颜色会是(0.7,0.7,0.7, 1)。alpha值也会相乘- (.6 x 1) + .4结果alpha 值为1。

在某些情况中,alpha blending是自动的。当使用SpriteBatch类绘制精灵时,选择SpriteBlendMode.AlphaBlend会开启alpha blending。

默认情况中,alpha通道会使用SourceBlend和DestinationBlend属性和红、绿、蓝通道进行混合。你也可以使用AlphaSourceBlend和AlphaDestinationBlend只对alpha通道进行混合。当计算alpha通道时,如果SeparateAlphaBlendEnabled为true,这些属性会做为混合因子。

 

3、什么是深度缓冲(Depth Buffer)                       

深度缓冲是一个与你的渲染目标(render target)相同大小的缓冲,这个缓冲记录每个像素的深度。

当一个像素第二次被绘制时– 例如当一个物体在另一个物体之后被绘制- 深度缓冲要么保留前面的深度值,要么使用第二个像素的深度值替换当前深度值。那个深度保留哪个深度抛弃取决于你选择的深度函数。例如,如果当前深度函数是CompareFunction.LessEqual时,只有小于等于当前深度值的值才会被保留,而大于当前深度值的值会被抛弃。这叫做深度测试,每次绘制像素时都会进行深度测试。当对一个像素进行深度测试时,它的颜色会被写入渲染目标,而深度被写入深度缓冲。

像素的深度值是由视矩阵和投影矩阵决定的。在*裁*面上的像素深度值为0,在远裁*面上的像素的深度值为1。场景中的每个对象都需进行绘制,通常最靠*相机的像素会被保留,这些对象阻挡了在它们后面的对象的可见性。

深度缓冲通常还包含stencil bits – 所以深度缓冲又被叫做depth-stencil缓冲。深度格式(depth format)表示深度缓冲的构造。深度缓冲总是32 bits,但可以用不同的方式组合,类似于纹理格式。常用的深度格式是Depth32,这种格式中32 bits都用来存储深度信息。另一个常用格式是DepthFormat.Depth24Stencil8,这种格式中24 bits用于深度计算而8 bits用于模版缓冲(stencil buffer)。DepthFormat.Depth24Stencil8Single不常用,这种格式使用24 bits以浮点数计算深度缓冲。在PresentationParameters中使用AutoDepthStencilFormat属性可以设置默认深度格式。

使用RenderState.DepthBufferEnable可以打开或关闭深度缓冲。使用 RenderState.DepthBufferFunction可以改变用于深度测试的比较函数。将ClearOptions.DepthBuffer传递给GraphicsDevice.Clear方法可以清楚深度缓冲。使用 DepthStencilBuffer类可以创建自己的深度缓冲。可见示例How To: Create a Depth Texture 学习如何创建一个自定义DepthStencilBuffer。

 

4、什么是深度纹理(Depth Texture)                       

深度纹理是一张包含特定场景的深度缓冲中的数据的纹理。纹理中的每个像素的颜色代表对应这个像素的多边形的深度值,这个深度值来自于深度缓冲。你可以使用深度缓冲通过一个叫做shadow mapping的技术绘制一个精确的阴影,所以深度纹理又被称为阴影贴图(shadow maps)。

有两个方法可以将深度信息保存到一张纹理中。第一个方法是使用一个标准的RGBA表面(surface)格式并将四个颜色作为一个32-bit缓冲,将深度复制到这个缓冲(深度数据通常是24或32 bits)。第二个方法是对纹理使用一个浮点(floating-point)表面格式,这个格式与一个浮点深度缓冲组合在一起。深度缓冲通常是定点(fixed-point)的,当使用第二种方法时,在存储前从1减去深度值的结果更加精确,这是因为此时浮点数是encoded。

以上两种方法都需要一个自定义顶点和像素shader。

 

5、什么是模型Bone                       

模型bone是一个表示3D模型中一个mesh相对于其他bone的位置的矩阵。

RangeSeekBar 锯齿 锯齿模式_RangeSeekBar 锯齿_02

在XNA Framework中,Model类表示整个模型。而Model中每个独立的mesh都对应一个ModelMesh。每个ModelMesh包含一个ParentBone,这个ParentBone控制相对于模型的位置和朝向。Model有一个Root bone,它决定了模型的位置和朝向。

每个ModelBone都有一个parent和许多children。模型对象的root bone是最终的parent。它的children是ModelMesh对象的bone-而这个ModelMesh对象可能还有其他ModelMesh bones作为它的children。对于给定的一族bone,旋转parent bone也会导致旋转它的children和这个children的children。每个bone都有一个变换矩阵(叫做Transform)定义相对于parent bone的位置和旋转。这个位置和旋转作用于ModelMesh 中的所有顶点(例如,连接到这个bone的所有顶点)。要对一个bone施加动画,你需要将默认bone变换乘以一个新矩阵。当绘制ModelMesh时,世界矩阵就是基于这个bone变换的。

在绘制过程中加入变换的bone的最简单方法是使用CopyAbsoluteBoneTransformsTo方法。这个方法提取相对的bone变换,并将这个变换最终变为相对于模型Root bone的变换(译者注:即绝对bone变换)。然后返回这些变换的拷贝。当你绘制每个ModelMesh时,你可以使用绝对bone变换作为世界矩阵的第一个部分。通过这种方式,你无需考虑parent bone和它们之间的联系。

 

6、什么是渲染目标(render target)

渲染目标是一个缓冲,显卡通过这个缓冲使用一个Effect类绘制场景的像素。

默认的渲染目标叫做后备缓冲- 物理上就是包含下一帧要绘制的信息的一块显存。你可以使用RenderTarget2D类创建另一个渲染目标,在显存中保留一块新区域用于绘制。大多数游戏在后备缓冲之外将大量的内容绘制到其他渲染目标内("offscreen"),然后编译这些不同的图像元素,将它们组合起来构成最终的后备缓冲。

一个渲染目标具有高和宽。后备缓冲的高和宽就是游戏的最终分辨率(而在Xbox 360中最终结果要进行缩放匹配用户的屏幕)。而一个offscreen渲染目标无需和后背缓冲有相同大小的高和宽,最终图像的小部分可以绘制到一个小渲染目标中,然后将它复制到另一个渲染目标。渲染目标还有一个surface格式,表明每个像素分配到多少bits和它们如何分割成红,绿,蓝,alpha通道。例如,SurfaceFormat.Bgr32给每个像素分配32 bits:每个颜色通道8 bits ,alpha通道8 bits。渲染目标还可以对所有绘制在其中的图像施加反锯齿(antialiasing)。

要使用渲染目标,需要创建一个指定高、宽或其他选项的RenderTarget2D对象。然后调用GraphicsDevice.SetRenderTarget将这个渲染目标作为当前渲染目标。从这一步开始,任何对Draw的调用会绘制到这个渲染目标。当结束渲染目标后,调用 GraphicsDevice.SetRenderTarget切换到一个新的渲染目标(或设置为null切换到后备缓冲)。 然后你就可以在任何时候调用RenderTarget2D.GetTexture获取渲染目标的内容进行后继处理。

;渲染目标可以和depth-stencil缓冲结合起来使用。如果你设置一个新的渲染目标,这个渲染目标会使用一个已存在的depth-stencil缓冲。如果新渲染目标有一个不同于depth-stencil缓冲的multisampling设置,或更大的宽和高,你就需要一个新的depth-stencil缓冲匹配这种情况。你还需要在depth-stencil缓冲中使用一个匹配渲染目标表面格式的深度格式。有时你可以同时渲染超过一个以上的渲染目标。你的图形设备支持的渲染目标的数量可以从MaxSimultaneousRenderTargets属性获得。使用多个渲染目标有很多变量,更多的信息可见Render Targets

 

7、什么是模板缓冲(Stencil Buffer)                       

模板缓冲类似于深度缓冲。事实上,它使用深度缓冲的一部分(因此,深度缓冲常常被称做depth-stencil缓冲)。深度缓冲让程序员可以设置一个模板函数测试"reference(参考)"模板值-一个全局值 – 每次当这个值仍然在模板缓冲时像素才会被绘制。

模板测试的结果决定了像素的颜色值是否要被写入到渲染目标,像素的深度值是否要被写入深度缓冲。

例如,当参考模板值为0时将一些物体绘制到场景中,而此时模板缓冲已经清除为1,那么当绘制这些物体时模板缓冲就会为0。如果接着将参考值设置为1,而且StencilFunction设置为 CompareFunction.LessEqual,那么只有那些模板值不为0的对应区域的像素会被绘制。这是使用模板缓冲创建一个限制当前绘制区域的基本用法。

模板缓冲还有许多更高级的用法。指定StencilOperations除了可以进行替换或抛弃操作,还可以在每次模板测试后减少或增加模板缓冲,这可以和StencilMask值组合起来保证模板测试只作用在模板缓冲的一部分区域上。

要使用模板缓冲,DepthFormat必须保留一些字节用于模板缓冲。DepthFormat.Depth24Stencil8深度格式使用了8位用于一个模板缓冲。当你将这个格式与RenderState.StencilMask属性组合起来时,它可以提供8个不同的模板缓冲。Depth24Stencil4 深度格式使用4位用于模板缓冲,而DepthFormat.Depth15Stencil1格式只允许1位。可以将ClearOptions.StencilBuffer传递到GraphicsDevice.Clear方法单独清除模板缓冲。

你可以使用DepthStencilBuffer类创建自己的depth-stencil缓冲。当创建一个自定义渲染目标时你需要创建自己的depth-stencil缓冲。

 

8、什么是纹理映射(Texture Mapping)                       

纹理映射是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程。

一张纹理是由一系列的像素组成的(所以叫做texel,翻译为“纹理像素”或“纹理元素”),每个像素基于纹理的宽和高对应一个纹理坐标。这些纹理坐标沿着uv坐标(u为宽,v为高)被映射到[0,1]范围内。这个过程叫做UV映射,坐标被称为UV坐标。

当你绘制一个多边形时,会计算三角形中每个顶点的UV坐标。这三个UV坐标决定在pixal shader中如何将一张纹理应用到多边形上。当u或v值小于0或大于1时,会根据设置的纹理寻址模式(texture address mode)决定应用的方式。当设置为TextureAddressMode.Border时,任何UV映射超出[0,1]范围的像素的颜色会被设置成纹理边界的颜色。当设置成 TextureAddressMode.Clamp时,会使用最*像素的颜色。设置为TextureAddressMode.Wrap 表示重复纹理。当设置为TextureAddressMode.Mirror时,纹理会重复,但在UV边界上会反向。每根轴的纹理寻址模式可以不同,所以你可以在u轴上设置wrap同时在v轴上设置clamp。

如果对于多边形来说纹理太大或太小,那么纹理需要被过滤以匹配空间。有两种过滤方式:放大和缩小。放大过滤器将纹理放大,缩小过滤器将纹理缩小。纹理放大通常很简单,会获得一张模糊的图像,而纹理缩小比较复杂,不正确的缩小会导致锯齿。

最常用的缩小方法是为每个纹理创建一个mipmap。mipmap是一张预先缩小的纹理,尺寸通常是原始纹理大小的一半。对这个mipmap再进行mipmap操作,最终创建一个大小为1x1的纹理,这就是纹理的最终mipmap。你可以将mipmap想象成一个链表,从原始纹理开始,然后变得越来越小,直到变为一个纹理像素。当需要缩小时,首先选择适当大小的mipmap纹理,然后将这个纹理施加到对象上,如果需要还要进行实时纹理过滤。内容管道中的默认纹理处理器有一个自动生成mipmap的选项。

XNA支持5种过滤器。TextureFilter.Point(点过滤)使用纹理上的最*点,没有过滤。TextureFilter.Linear(线性过滤)对邻*的4个纹理像素的采样进行线性插值并生成一个*均值。TextureFilter.PyramidalQuad也使用4个采样点,这些采样点用的是靠*结果像素中心的纹理像素计算出最终结果。TextureFilter.GaussianQuad工作方式相同,但使用了不同的算法权重- 类似于一个钟型曲线,此曲线的顶部就是结果像素的中心。TextureFilter.Anisotropic(各向异性过滤)被设计用来过滤那些不是面对相机的表面(例如靠*水*面的地面)。