高级纹理映射技术(2)
纹理阶段混合操作
纹理映射本质上就是从纹理中获取颜色值,然后应用到物体的表面,多层纹理映射本质上就是混合多层纹理的颜色,然后应用到物体表面。为了处理上的方便,Direct3D将颜色的RGB通道和alpha通道分别进行处理,具体的操作方法通过纹理阶段状态进行设置。
设置纹理颜色混合操作的代码大致如下:
// i表示纹理阶段序号
pd3dDevice->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
pd3dDevice->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
pd3dDevice->SetTextureStageState(i, D3DTSS_COLOROP, op);
一般的,用D3DTSS_COLORARG1指定当前纹理层的颜色,用D3DTSS_COLORARG2指定已经过颜色混合处理后的前面所有纹理层的颜色,用D3DTSS_COLOROP指定混合方式。Direct3D使用下面的方式进行纹理混合:
Colorstage = D3DTSS_COLOROP(D3DTSS_COLORARG1, D3DTSS_COLORARG2)
渲染状态D3DTSS_COLOROP用来指定纹理RGB通道混合方式,它们是属于枚举类型D3DTEXTUREOP的常量,D3DTEXTUREOP定义如下:
Defines per-stage texture-blending operations.
typedef enum D3DTEXTUREOP
{
D3DTOP_DISABLE = 1,
D3DTOP_SELECTARG1 = 2,
D3DTOP_SELECTARG2 = 3,
D3DTOP_MODULATE = 4,
D3DTOP_MODULATE2X = 5,
D3DTOP_MODULATE4X = 6,
D3DTOP_ADD = 7,
D3DTOP_ADDSIGNED = 8,
D3DTOP_ADDSIGNED2X = 9,
D3DTOP_SUBTRACT = 10,
D3DTOP_ADDSMOOTH = 11,
D3DTOP_BLENDDIFFUSEALPHA = 12,
D3DTOP_BLENDTEXTUREALPHA = 13,
D3DTOP_BLENDFACTORALPHA = 14,
D3DTOP_BLENDTEXTUREALPHAPM = 15,
D3DTOP_BLENDCURRENTALPHA = 16,
D3DTOP_PREMODULATE = 17,
D3DTOP_MODULATEALPHA_ADDCOLOR = 18,
D3DTOP_MODULATECOLOR_ADDALPHA = 19,
D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20,
D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21,
D3DTOP_BUMPENVMAP = 22,
D3DTOP_BUMPENVMAPLUMINANCE = 23,
D3DTOP_DOTPRODUCT3 = 24,
D3DTOP_MULTIPLYADD = 25,
D3DTOP_LERP = 26,
D3DTOP_FORCE_DWORD = 0x7fffffff,
} D3DTEXTUREOP, *LPD3DTEXTUREOP;
Constants
- D3DTOP_DISABLE
-
Disables output from this texture stage and all stages with a higher index. To disable texture mapping, set this as the color operation for the first texture stage (stage 0). Alpha operations cannot be disabled when color operations are enabled. Setting the alpha operation to D3DTOP_DISABLE when color blending is enabled causes undefined behavior.
- D3DTOP_SELECTARG1
-
Use this texture stage's first color or alpha argument, unmodified, as the output. This operation affects the color argument when used with the D3DTSS_COLOROP texture-stage state, and the alpha argument when used with D3DTSS_ALPHAOP.
SRGBA = Arg1
- D3DTOP_SELECTARG2
-
Use this texture stage's second color or alpha argument, unmodified, as the output. This operation affects the color argument when used with the D3DTSS_COLOROP texture stage state, and the alpha argument when used with D3DTSS_ALPHAOP.
SRGBA = Arg2
- D3DTOP_MODULATE
-
Multiply the components of the arguments.
SRGBA = Arg1 x Arg2
- D3DTOP_MODULATE2X
-
Multiply the components of the arguments, and shift the products to the left 1 bit (effectively multiplying them by 2) for brightening.
SRGBA = (Arg1 x Arg2) << 1
- D3DTOP_MODULATE4X
-
Multiply the components of the arguments, and shift the products to the left 2 bits (effectively multiplying them by 4) for brightening.
SRGBA = (Arg1 x Arg2) << 2
- D3DTOP_ADD
-
Add the components of the arguments.
SRGBA = Arg1 + Arg2
- D3DTOP_ADDSIGNED
-
Add the components of the arguments with a - 0.5 bias, making the effective range of values from - 0.5 through 0.5.
SRGBA = Arg1 + Arg2 - 0.5
- D3DTOP_ADDSIGNED2X
-
Add the components of the arguments with a - 0.5 bias, and shift the products to the left 1 bit.
SRGBA = (Arg1 + Arg2 - 0.5) << 1
- D3DTOP_SUBTRACT
-
Subtract the components of the second argument from those of the first argument.
SRGBA = Arg1 - Arg2
- D3DTOP_ADDSMOOTH
-
Add the first and second arguments; then subtract their product from the sum.
SRGBA = Arg1 + Arg2 - Arg1 x Arg2 = Arg1 + Arg2 x (1 - Arg1)
D3DTA
Texture argument constants are used as values for the following members of the D3DTEXTURESTAGESTATETYPE enumerated type:
- D3DTSS_ALPHAARG0
- D3DTSS_ALPHAARG1
- D3DTSS_ALPHAARG2
- D3DTSS_COLORARG0
- D3DTSS_COLORARG1
- D3DTSS_COLORARG2
- D3DTSS_RESULTARG
Set and retrieve texture arguments by calling the IDirect3DDevice9::SetTextureStageState and IDirect3DDevice9::GetTextureStageState methods.
Argument flags
You can combine an argument flag with a modifier, but two argument flags cannot be combined.
#define | Description |
---|---|
D3DTA_CONSTANT | Select a constant from a texture stage. The default value is 0xffffffff. |
D3DTA_CURRENT | The texture argument is the result of the previous blending stage. In the first texture stage (stage 0), this argument is equivalent to D3DTA_DIFFUSE. If the previous blending stage uses a bump-map texture (the D3DTOP_BUMPENVMAP operation), the system chooses the texture from the stage before the bump-map texture. If s represents the current texture stage and s - 1 contains a bump-map texture, this argument becomes the result output by texture stage s - 2. Permissions are read/write. |
D3DTA_DIFFUSE | The texture argument is the diffuse color interpolated from vertex components during Gouraud shading. If the vertex does not contain a diffuse color, the default color is 0xffffffff. Permissions are read-only. |
D3DTA_SELECTMASK | Mask value for all arguments; not used when setting texture arguments. |
D3DTA_SPECULAR | The texture argument is the specular color interpolated from vertex components during Gouraud shading. If the vertex does not contain a specular color, the default color is 0xffffffff. Permissions are read-only. |
D3DTA_TEMP | The texture argument is a temporary register color for read or write. D3DTA_TEMP is supported if the D3DPMISCCAPS_TSSARGTEMP device capability is present. The default value for the register is (0.0, 0.0, 0.0, 0.0). Permissions are read/write. |
D3DTA_TEXTURE | The texture argument is the texture color for this texture stage. Permissions are read-only. |
D3DTA_TFACTOR | The texture argument is the texture factor set in a previous call to the IDirect3DDevice9::SetRenderState with the D3DRS_TEXTUREFACTOR render-state value. Permissions are read-only. |
Modifier flags
An argument flag may be combined with one of the following modifier flags.
#define | Description |
---|---|
D3DTA_ALPHAREPLICATE | Replicate the alpha information to all color channels before the operation completes. This is a read modifier. |
D3DTA_COMPLEMENT | Take the complement of the argument x, (1.0 - x). This is a read modifier. |
黑暗映射
在Direct3D的坐标变换和光照流水线中,光照效果是基于所谓的"逐顶点(per-vertex)"方式计算的,也就是说,参与实际数计算的是三角形的每个顶点,而不是针对每个像素进行。有时这会造成一些较为明显的视觉错误,例如,有一个很大的三角形,其表面近处有一个光源,当光源靠近该三角形的一个顶点时,就会看到这个三角形的受光效果;当光源向三角形的重心靠近时,三角形的受光效果便会逐渐消失。最坏的情况是,当光源位于三角形的中央时,整个三角形只受非常少的光照,而在三角形的中央会有一个亮点。由此可见,如果顶点未受光照,则无法计算出正确的三角形面的颜色。为了解决这个问题,可以采用基于像素的光照计算,但是基于像素的光照计算其计算量比较大,通常采用纹理贴图的方式模拟基于逐像素光照效果,其中纹理贴图的内容正式所期望的类型光源照射在一张漆黑表面上的结果。
通过纹理映射来模拟逐像素光照效果,通常是将第一层纹理设置为物体原来的表面纹理,将第二层纹理设置为光照纹理,然后将两张纹理的颜色相乘,所以有时将两张纹理的颜色相乘称为光照映射(light mapping)。由于这种技术经常被用于使一张纹理变暗,有时也称为黑暗映射(dark mapping)。示例代码如下:
pd3dDevice->SetTexture(0, g_base_texture);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
pd3dDevice->SetTexture(1, g_dark_texture);
pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
物体纹理 |
光照纹理 |
黑暗映射的效果:
这种类型的多层纹理之所以称为"黑暗映射",是因为最终结果中未受到"光照"的纹理元素比原图中的纹理元素更暗。
黑暗映射通常有三种调制操作:D3DTOP_MODULATE,D3DTOP_MODULATE2X,D3DTOP_MODULATE4X。
当应用程序选择了一张纹理作为当前纹理,也就是指示Direct3D将该纹理应用于此后所有将要渲染的图元,直到再次改变当前纹理为止。如果一个三维场景中的每个图元都有各自不同的纹理,则必须在渲染每个图元之前先设置相应的纹理。