赞
踩
观察图9.1 我们开始渲染帧,首先绘制地形,然后是木箱,以便地形和箱子像素位于后台缓冲区。然后,我们使用混合将水面绘制到后部缓冲区,使得水像素与地形混合,并在后部缓冲区中创建像素,以便地形和箱子通过水面显示。在本章中,我们将研究混合技术,它们允许我们将当前正在栅格化的像素(所谓的源像素)与之前栅格化的像素混合(组合)到后台缓冲区(所谓的目标像素)。除此之外,这种技术使我们能够渲染诸如水和玻璃之类的半透明物体。
NOTE:为了讨论,我们特别提到了后台缓冲区作为渲染目标。不过,我们稍后会显示,我们也可以渲染“屏幕外”渲染目标。混合适用于这些渲染目标相同,目标像素是以前栅格化到这些屏幕渲染目标的像素值。
学习目标:
1.了解混合是如何工作的以及其D3D实现。
2.了解Direct3D支持的不同混合模式。
3.了解如何使用alpha组件来控制基元的透明度。
4.学习如何通过使用HLSL剪辑函数来防止像素被完全绘制到后台缓冲区。
设Csrc为当前正在栅格化的第ij个像素(源像素)的像素着色器的颜色输出,
前面的混合等式仅适用于颜色的RGB分量。alpha分量实际上是由一个单独的类似的方程来处理的:
NOTE:混合alpha组件比混合RGB组件要少得多。 这主要是因为我们不关心后台缓冲区的alpha值。 如果您有一些算法需要目标Alpha值,则后台缓冲区Alpha值才是重要的。
混合等式中使用的二元运算符⊞可以是下列之一:
typedef enum D3D11_BLEND_OP
{
D3D11_BLEND_OP_ADD = 1,
D3D11_BLEND_OP_SUBTRACT = 2,
D3D11_BLEND_OP_REV_SUBTRACT = 3,
D3D11_BLEND_OP_MIN = 4,
D3D11_BLEND_OP_MAX = 5,
} D3D11_BLEND_OP;
NOTE:在最小/最大操作中忽略混合因子。
这些相同的算子也适用于α混合方程。 另外,可以为RGB和alpha指定不同的运算符。例如,可以添加两个RGB项,但是可以减去两个alpha项:
通过为源和目标混合因子以及不同的混合算子设置不同的组合,可以实现数十种不同的混合效果。我们将在第9.5节中举例说明一些组合,但是你需要尝试与其他人一起来了解他们所做的事情。以下列表描述了适用于
D3D11_BLEND_ZERO: F = (0,0,0) and F = 0
D3D11_BLEND_ONE: F = (1,1,1) and F = 1
D3D11_BLEND_SRC_COLOR:
D3D11_BLEND_INV_SRC_COLOR:
D3D11_BLEND_SRC_ALPHA:
D3D11_BLEND_INV_SRC_ALPHA:
D3D11_BLEND_DEST_ALPHA:
D3D11_BLEND_INV_DEST_ALPHA:
D3D11_BLEND_DEST_COLOR:
D3D11_BLEND_INV_DEST_COLOR:
D3D11_BLEND_SRC_ALPHA_SAT:
D3D11_BLEND_BLEND_FACTOR:
D3D11_BLEND_INV_BLEND_FACTOR:
NOTE:钳位功能定义如下:
已经谈到了混合算子和混合因子,但是我们在哪里使用Direct3D来设置这些值? 这些混合设置由ID3D11BlendState接口控制。通过填充D3D11_BLEND_DESC结构,然后调用ID3D11Device :: CreateBlendState,可以找到这样一个接口:
HRESULT ID3D11Device::CreateBlendState(
const D3D11_BLEND_DESC *pBlendStateDesc,
ID3D11BlendState **ppBlendState);
1 . pBlendStateDesc:指向填充D3D11_BLEND_DESC结构的指针,用于描述要创建的混合状态。
2 . ppBlendState:返回一个指向创建的混合状态接口的指针。
D3D11_BLEND_DESC:Structure定义如下:
typedef struct D3D11_BLEND_DESC {
BOOL AlphaToCoverageEnable; // Default: False
BOOL IndependentBlendEnable; // Default: False
D3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8];
} D3D11_BLEND_DESC;
1 . AlphaToCoverageEnable:指定true以启用alpha-to-coverage,这是渲染树叶或门纹理时有用的多重采样技术。指定false以禁用alpha-to-coverage。 Alpha覆盖需要启用多重采样(即,使用多重采样创建背景和深度缓冲区)。我们将在第11章中展示一个使用alpha-to-coverage的示例。
2 . IndependentBlendEnable:Direct3D 11支持同时渲染多达8个渲染目标。如果此标志设置为true,则表示可以对每个渲染目标进行不同的混合(不同的混合因子,不同的混合操作,混合禁用/启用等)。如果此标志设置为false,则意味着所有渲染目标将按照D3D11_BLEND_DESC :: RenderTarget数组中第一个元素所描述的方式进行混合。多个渲染目标用于高级算法;现在假设我们一次只渲染一个渲染目标。
3 . RenderTarget:具有8个D3D11_RENDER_TARGET_BLEND_DESC元素的数组,其中第i个元素描述了如何对第i个同时渲染目标进行混合。如果IndependentBlendEnable设置为false,则所有渲染目标都使用RenderTarget [0]进行混合。
D3D11_RENDER_TARGET_BLEND_DESC结构定义如下:
typedef struct D3D11_RENDER_TARGET_BLEND_DESC {
BOOL BlendEnable; // Default: False
D3D11_BLEND SrcBlend; // Default: D3D11_BLEND_ONE
D3D11_BLEND DestBlend; // Default: D3D11_BLEND_ZERO
D3D11_BLEND_OP BlendOp; // Default: D3D11_BLEND_OP_ADD
D3D11_BLEND SrcBlendAlpha; // Default: D3D11_BLEND_ONE
D3D11_BLEND DestBlendAlpha; // Default: D3D11_BLEND_ZERO
D3D11_BLEND_OP BlendOpAlpha; // Default: D3D11_BLEND_OP_ADD
UINT8 RenderTargetWriteMask; // Default: D3D11_COLOR_WRITE_ENABLE_ALL
} D3D11_RENDER_TARGET_BLEND_DESC;
1 . BlendEnable:指定true以启用混合,false指定将其禁用。
2 . SrcBlend:D3D11_BLEND枚举类型的成员,它指定RGB混合的源混合因子Fsrc。
3 . DestBlend:D3D11_BLEND枚举类型的成员,用于指定RGB混合的目标混合因子Fdst。
4 . BlendOp:指定RGB混合运算符的D3D11_BLEND_OP枚举类型的成员。
5 . SrcBlendAlpha:D3D11_BLEND枚举类型的成员,指定alpha的目标混合因子
6 . DestBlendAlpha:D3D11_BLEND枚举类型的成员,它指定alpha的目标混合因子$F_{dst}混合。
7 . BlendOpAlpha:指定alpha混合运算符的D3D11_BLEND_OP枚举类型的成员。
8 . RenderTargetWriteMask:一个或多个以下标志的组合:
typedef enum D3D11_COLOR_WRITE_ENABLE {
D3D11_COLOR_WRITE_ENABLE_RED = 1,
D3D11_COLOR_WRITE_ENABLE_GREEN = 2,
D3D11_COLOR_WRITE_ENABLE_BLUE = 4,
D3D11_COLOR_WRITE_ENABLE_ALPHA = 8,
D3D11_COLOR_WRITE_ENABLE_ALL =
(D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN |
D3D11_COLOR_WRITE_ENABLE_BLUE | D3D11_COLOR_WRITE_ENABLE_ALPHA)
} D3D11_COLOR_WRITE_ENABLE;
这些标志控制混合后写入后缓冲区中的哪些颜色通道。例如,可以通过指定D3D11_COLOR_WRITE_ENABLE_ALPHA来禁止写入RGB通道,并仅写入Alpha通道。这种灵活性对于高级技术是有用的。当禁用混合时,使用从像素着色器返回的颜色而不应用写入蒙版。
为了将混合状态对象绑定到管道的输出合并阶段,我们调用:
void ID3D11DeviceContext::OMSetBlendState(
ID3D11BlendState *pBlendState,
const FLOAT BlendFactor,
UINT SampleMask);
1 . pBlendState:一个指向混合状态对象的指针,用于使能设备。
2 . BlendFactor:一个由四个浮点数组成的数组,定义一个RGBA颜色矢量。 当指定了D3D11_BLEND_BLEND_FACTOR或D3D11_BLEND_INV_BLEND_FACTOR时,使用此颜色矢量作为混合因子。
3 . SampleMask:多重采样可能需要多达32个采样。 这个32位整数值用于启用/禁用采样。 例如,如果您关闭第五位,那么第五个采样将不会被采用。 当然,如果实际上使用至少5个采样的多重采样,则禁用第五个采样只会有任何结果。 如果应用程序使用单个采样,则只有该参数的第一位很重要(请参阅练习1)。 通常使用默认值0xffffffff,这不会禁用应用程序可能采取的任何示例。
与其他状态块一样,有一个默认的混合状态(禁用混合)。如果您使用null调用OMSetBlendState,则会恢复默认混合状态。我们注意到混合确实需要额外的每像素工作,所以只有在需要的时候启用它,并在完成后关闭它。
以下代码显示了创建和设置混合状态的示例:
D3D11_BLEND_DESC transparentDesc = {0};
transparentDesc.AlphaToCoverageEnable = false;
transparentDesc.IndependentBlendEnable = false;
transparentDesc.RenderTarget[0].BlendEnable = true;
transparentDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
transparentDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
transparentDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
transparentDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
transparentDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
transparentDesc.RenderTarget[0].RenderTargetWriteMask =
D3D11_COLOR_WRITE_ENABLE_ALL;
ID3D11BlendState* TransparentBS;
HR(device->CreateBlendState(&transparentDesc, &TransparentBS));
…
float blendFactors[] = {0.0f, 0.0f, 0.0f, 0.0f};
md3dImmediateContext->OMSetBlendState(
TransparentBS, blendFactor, 0xffffffff);
As with other state block interfaces, you should create them all at application initialization time, and then just switch
between the state interfaces as needed.
A blend state object can also be set and defined in an effect file:
BlendState blend
{
// Blending state for first render target.
BlendEnable[0] = TRUE;
SrcBlend[0] = SRC_COLOR;
DestBlend[0] = INV_SRC_ALPHA;
BlendOp[0] = ADD;
SrcBlendAlpha[0] = ZERO;
DestBlendAlpha[0] = ZERO;
BlendOpAlpha[0] = ADD;
RenderTargetWriteMask[0] = 0x0F;
// Blending state for second simultaneous render target.
BlendEnable[1] = True;
SrcBlend[1] = One;
DestBlend[1] = Zero;
BlendOp[1] = Add;
SrcBlendAlpha[1] = Zero;
DestBlendAlpha[1] = Zero;
BlendOpAlpha[1] = Add;
RenderTargetWriteMask[1] = 0x0F;
};
technique11 Tech
{
pass P0
{
…
// Use "blend" for this pass.
SetBlendState(blend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xffffffff);
}
}
除非没有前缀,否则分配给混合状态对象的值与您分配给C ++结构的值相同。 例如,我们不是指定D3D11_BLEND_SRC_COLOR,而是在效果代码中指定SRC_COLOR。还要注意,状态属性的赋值不区分大小写。
在下面的小节中,我们看看用于获得特定效果的一些混合因子组合。在这些例子中,我们只看RGB混合。阿尔法混合是类似的处理。
假设我们想保持原来的目标像素是完全不变的,而不是覆盖它,或者将它与当前被光栅化的源像素混合。 例如,如果您只是要写入深度/模板缓冲区而不是后缓冲区,则此功能非常有用。为此,请将源像素混合因子设置为D3D11_BLEND_ZERO,将目标混合因子设置为D3D11_BLEND_ONE,并将混合 运算符D3D11_BLEND_OP_ADD。 通过这种设置,混合等式可以简化为:
假设我们要添加具有目标像素的源像素(见图9.2)。 为此,请将源混合因子设置为D3D11_BLEND_ONE,将目标混合因子设置为D3D11_BLEND_ONE,将混合运算符设置为D3D11_BLEND_OP_ADD。 通过这种设置,混合等式可以简化为:
假设我们想将一个源像素与其相应的目标像素相乘(见图9.4)。 为此,我们将源混合因子设置为D3D11_BLEND_ZERO,将目标混合因子设置为D3D11_BLEND_SRC_COLOR,将混合运算符设置为D3D11_BLEND_OP_ADD。 通过这种设置,混合等式可以简化为:
让源alpha分量被认为是控制源像素的不透明度的百分比(例如,0α表示0%不透明,0.4表示40%不透明,1.0表示100%不透明)。 不透明度和透明度之间的关系简单地是T = 1 -A,其中A是不透明度,T是透明度。 例如,如果0.4是不透明的,则透明度是1-0.4 = 0.6。 现在假设我们想要根据源像素的不透明度来混合源像素和目标像素。 为此,请将源混合因子设置为D3D11_BLEND_SRC_ALPHA,将目标混合因子设置为D3D11_BLEND_INV_SRC_ALPHA,将混合运算符设置为D3D11_BLEND_OP_ADD。 通过这种设置,混合等式可以简化为:
背对背绘制顺序的原因是,物体与空间背后的物体混合在一起。因为如果一个物体是透明的,我们可以透过它看到它背后的景象。所以透明物体后面的所有像素都必须写入后台缓冲区,所以我们可以将透明源像素与其后面的场景的目标像素混合。
对于第9.5.1节中的混合方法,绘制顺序并不重要,因为它可以防止源像素写入后台缓冲区。对于第9.5.2节和第9.5.3节讨论的混合方法,我们仍然先绘制非混合对象 最后混合物体; 这是因为我们希望在开始混合之前先将所有非混合几何图形放置在后台缓冲区中。 但是,我们不需要对使用混合的对象进行排序。 这是因为这些操作是可交换的。 也就是说,如果您从后缓冲区像素颜色B开始,然后对该像素执行n个加法/减法/乘法混合,则顺序无关紧要:
当混合加法/减法/乘法混合时,深度测试会出现问题。为了举例,我们将只用加法混合来解释,但是减法/乘法混合也是一样的。如果我们用叠加混合来渲染一组对象S,那么这个想法就是S中的对象不会互相混淆;相反,它们的颜色只是简单的积累(见图9.5)。因此,我们不想在S中的对象之间进行深度测试;因为如果我们这样做了,没有后端的绘制顺序,S中的一个对象会隐藏S中的另一个对象,从而导致像素片段由于深度测试而被拒绝,这意味着对象的像素颜色不会被累积进入混合总和。我们可以禁用S中的对象之间的深度测试,通过在S中渲染对象时禁止对深度缓冲区的写入。因为深度写入被禁用,所以使用加法混合绘制的S中的对象的深度不会写入深度缓冲区;因此,由于深度测试,这个对象不会隐藏在其后的S中的任何后来绘制的对象。请注意,我们只在绘制S中的对象(用添加混合绘制的对象集)时禁用深度写入。深度读取和深度测试仍然启用。这是因为非混合几何体(在混合几何体之前绘制)仍将隐藏其后面的混合几何体。例如,如果在墙后面有一组添加混合的对象,则不会看到混合的对象,因为实心墙遮挡了它们。如何禁用深度写入,更一般的配置深度测试设置将在下一章中介绍。
§9.5.4中的例子显示,源代码alpha组件可以用于RGB混合来控制透明度。 混合方程中使用的源颜色来自像素着色器。 正如我们在上一章中看到的,我们将漫反射材质的alpha值作为像素着色器的alpha输出返回。因此漫反射贴图的alpha通道用于控制透明度。
float4 PS(VertexOut pin) : SV_Target
{
…
// Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a;
return litColor;
}
您通常可以在任何流行的图像编辑软件(如Adobe Photoshop)中添加Alpha通道,然后将图像保存为支持Alpha通道(例如,32位.bmp格式或.dds格式)的格式。 然而,在这里我们展示了一个使用上一章讨论过的DXTex实用程序插入一个alpha通道的替代方法。
我们首先假定我们有两个图像 - 一个彩色的RGB图像和一个灰度图像,将被插入到alpha通道(见图9.6)。
现在,打开DXTex工具,打开位于本章的示例文件夹中的fire_rgb.bmp文件。 火纹理以24位RGB纹理(即,D3DFMT_R8G8B8)自动加载,每个像素具有8位红色,8位绿色和8位蓝色。 我们需要将格式更改为支持Alpha通道的格式,例如32位ARGB纹理格式D3DFMT_A8R8G8B8,或者使用支持alpha D3DFMT_DXT5等格式的压缩格式。 从菜单中选择格式并选择Change_Surface格式。 弹出如图9.7所示的对话框,选择DXT5格式,然后按OK。
这将创建一个带有alpha通道的压缩纹理。 我们的下一个任务是将数据加载到alpha通道。 我们将把图9.6所示的8位灰度图加载到alpha通道中。 从菜单中选择“文件”,然后选择“打开此纹理的Alpha通道”,然后选择“格式” - >“生成Mip贴图”。 会弹出一个对话框,要求您找到包含要加载到Alpha通道的数据的图像文件。 选择位于本章演示文件夹中的fire_a.bmp文件。插入Alpha通道数据之后,程序如图9.8所示,纹理透明地与背景颜色混合。 可以通过从菜单栏选择视图,然后更改背景颜色…来更改背景颜色。 您也可以选择View-> Alpha Channel Only来查看Alpha通道。
有时我们想要完全拒绝源像素被进一步处理。这可以通过内在的HLSL clip(x)函数来完成。该函数只能在像素着色器中调用,并且如果x <0,则丢弃当前像素以进行进一步处理。例如,如图9.9所示,此函数对渲染钢丝网纹理非常有用。也就是说,对像素完全不透明或完全透明的像素进行渲染是非常有用的。
在像素着色器中,我们抓取纹理的alpha分量。如果它是一个接近于0的小值,这表示像素是完全透明的,那么我们将该像素从进一步处理中剪裁掉。
float4 PS(VertexOut pin, uniform int gLightCount, uniform bool gUseTexure,uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW);
// The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW;
// Cache the distance to the eye from this surface point.
float distToEye = length(toEye);
// Normalize.
toEye /= distToEye;
// Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
if(gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample(samAnisotropic, pin.Tex);
if(gAlphaClip)
{
// Discard pixel if texture alpha < 0.1. Note that
// we do this test as soon as possible so that we can
// potentially exit the shader early, thereby skipping the
// rest of the shader code.
clip(texColor.a - 0.1f);
}
}
…
注意只在参数gAlphaClip为true时才统一剪辑; 这是因为我们可能不想为一些几何体调用剪辑,所以我们需要通过使用专门的着色器来打开/关闭它。
请注意,使用混合可以获得相同的结果,但这样更有效。首先,不需要进行混合计算(可以禁用混合)。另外,绘制顺序并不重要。此外,通过从像素着色器中提前丢弃像素,可以跳过剩余的像素着色器指令(对丢弃的像素进行计算没有意义)。
NOTE:由于过滤,alpha通道可能会模糊一点,所以在剪裁像素时应该留出一些缓冲空间。 例如,剪裁alpha值接近于0的像素,但不一定完全为零。
图9.10显示了“混合”演示的屏幕截图。它使用透明度混合渲染半透明的水,并使用剪辑测试呈现围栏的线框。另一个值得一提的变化是,因为我们现在可以看到带有栅栏纹理的盒子,所以我们要禁用背面剔除:
ZeroMemory(&noCullDesc, sizeof(D3D11_RASTERIZER_DESC));
noCullDesc.FillMode = D3D11_FILL_SOLID;
noCullDesc.CullMode = D3D11_CULL_NONE;
noCullDesc.FrontCounterClockwise = false;
noCullDesc.DepthClipEnable = true;
ID3D11RasterizerState* NoCullRS;
HR(device->CreateRasterizerState(&noCullDesc, &NoCullRS));
…
// Since the fence texture has transparent regions, we can
// see through it, and thus see the backsides of the triangles.
// Therefore, we don't want to backface culling in this case.
md3dImmediateContext->RSSetState(NoCullRS);
boxTech->GetPassByIndex(p)->Apply(0, md3dImmediateContext);
md3dImmediateContext->DrawIndexed(36, 0, 0);
// Restore default render state.
md3dImmediateContext->RSSetState(0);
为了在我们的游戏中模拟某些类型的天气条件,我们需要能够实现雾效果; 见图9.11。除了雾的明显目的之外,雾提供了一些附带的好处。例如,它可以屏蔽远处的渲染伪像并防止弹出。 弹出是指由于相机移动,突然之前在远平面后面的物体出现在平截头体的前面,从而变得可见; 所以它似乎突然“弹出”到现场。通过在远处有一层雾,弹出隐藏。请注意,如果您的场景发生在一个晴朗的日子,您可能希望仍然在远处包含微量的雾,因为即使在晴朗的日子,远处的物体(如山脉)也会变得更加朦胧,并因深度而失去对比度, 我们可以用雾来模拟这种大气透视现象。
float3 toEye = gEyePosW - pin.PosW;
// Cache the distance to the eye from this surface point.
float distToEye = length(toEye);
// Normalize.
toEye /= distToEye;
// Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
if(gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample(samAnisotropic, pin.Tex);
if(gAlphaClip)
{
// Discard pixel if texture alpha < 0.1. Note that
// we do this test as soon as possible so that we can
// potentially exit the shader early, thereby
// skipping the rest of the shader code.
clip(texColor.a - 0.1f);
}
}
//
// Lighting.
//
float4 litColor = texColor;
if(gLightCount > 0)
{
// Start with a sum of zero.
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
// Sum the light contribution from each light source.
[unroll]
for(int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i],
pin.NormalW, toEye,
A, D, S);
ambient += A;
diffuse += D;
spec += S;
}
// Modulate with late add.
litColor = texColor*(ambient + diffuse) + spec;
} //
// Fogging
//
if( gFogEnabled )
{
float fogLerp = saturate((distToEye - gFogStart) / gFogRange);
// Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
}
// Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a;
return litColor;
}
Note:观察雾计算中,我们使用distToEye值,我们也计算了toEye矢量的归一化。 不太理想的实现应该是写:
float3 toEye = normalize(gEyePosW - pin.PosW);
float distToEye = distance(gEyePosW, pin.PosW);
这基本上计算了toEye矢量的长度,一次在归一化函数中,一次在距离函数中计算。
Note:“混合”演示支持三种渲染模式,可以通过按“1”,“2”和“3”键进行切换。第一种模式仅使用光照渲染场景(见图9.14)。照明是一个过去的话题,但看看没有纹理的场景是什么样的。 第二种模式渲染场景的照明和纹理(图9.10)。第三种模式渲染场景的照明,纹理和雾(图9.11)。这些渲染模式开关演示了我们如何使用效果框架中的统一参数来生成功能性开启和关闭的专用着色器。 读者可能希望重新检查Basic.fx中的一些汇编语言输出。比较照明,照明和纹理,照明,纹理和雾的帧速率也是有趣的。
1.混合是一种技术,它允许我们将当前正在栅格化的像素(所谓的源像素)与先前栅格化到后端缓冲区的像素(所谓的目标像素)混合(组合)。 除此之外,这种技术使我们能够渲染诸如水和玻璃之类的半透明物体。
2.混合方程是:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。