纹理阶段混合状态用于指定当前纹理颜色值和alpha值的混合方法。
纹理阶段混合状态设置
纹理阶段混合状态由IDirect3DDevice9::SetTextureStageState()设置,该函数的声明如下:
Sets the state value for the currently assigned
texture.
HRESULT SetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD Value
);
Parameters
- Stage
- [in] Stage identifier of the texture for which the
state value is set. Stage identifiers are zero-based. Devices can have up to
eight set textures, so the maximum value allowed for Stage is 7.
- Type
- [in] Texture state to set. This parameter can be
any member of the D3DTEXTURESTAGESTATETYPE enumerated type.
- Value
- [in] State value to set. The meaning of this value
is determined by the Type parameter.
Return Values
If the method succeeds, the return value is D3D_OK. If
the method fails, the return value can be D3DERR_INVALIDCALL.
枚举类型D3DTEXTURESTAGESTATETYPE的定义为:
Texture stage states define multi-blender texture
operations. Some sampler states set up vertex processing, and some set up pixel
processing. Texture stage states can be saved and restored using stateblocks
(see State Blocks Save and Restore State (Direct3D 9)).
typedef enum D3DTEXTURESTAGESTATETYPE
{
D3DTSS_COLOROP = 1,
D3DTSS_COLORARG1 = 2,
D3DTSS_COLORARG2 = 3,
D3DTSS_ALPHAOP = 4,
D3DTSS_ALPHAARG1 = 5,
D3DTSS_ALPHAARG2 = 6,
D3DTSS_BUMPENVMAT00 = 7,
D3DTSS_BUMPENVMAT01 = 8,
D3DTSS_BUMPENVMAT10 = 9,
D3DTSS_BUMPENVMAT11 = 10,
D3DTSS_TEXCOORDINDEX = 11,
D3DTSS_BUMPENVLSCALE = 22,
D3DTSS_BUMPENVLOFFSET = 23,
D3DTSS_TEXTURETRANSFORMFLAGS = 24,
D3DTSS_COLORARG0 = 26,
D3DTSS_ALPHAARG0 = 27,
D3DTSS_RESULTARG = 28,
D3DTSS_CONSTANT = 32,
D3DTSS_FORCE_DWORD = 0x7fffffff,
} D3DTEXTURESTAGESTATETYPE, *LPD3DTEXTURESTAGESTATETYPE;
Constants
- D3DTSS_COLOROP
- Texture-stage state is a texture color blending
operation identified by one member of the D3DTEXTUREOP enumerated type. The
default value for the first texture stage (stage 0) is D3DTOP_MODULATE; for
all other stages the default is D3DTOP_DISABLE.
- D3DTSS_COLORARG1
- Texture-stage state is the first color argument
for the stage, identified by one of the D3DTA. The default argument is
D3DTA_TEXTURE.
Specify D3DTA_TEMP to select 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).
- D3DTSS_COLORARG2
- Texture-stage state is the second color argument
for the stage, identified by D3DTA. The default argument is
D3DTA_CURRENT. Specify D3DTA_TEMP to select 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)
- D3DTSS_ALPHAOP
- Texture-stage state is a texture alpha blending
operation identified by one member of the D3DTEXTUREOP enumerated
type. The default value for the first texture stage (stage 0) is
D3DTOP_SELECTARG1, and for all other stages the default is D3DTOP_DISABLE.
- D3DTSS_ALPHAARG1
- Texture-stage state is the first alpha argument
for the stage, identified by by D3DTA. The default argument is
D3DTA_TEXTURE. If no texture is set for this stage, the default argument is
D3DTA_DIFFUSE. Specify D3DTA_TEMP to select 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).
- D3DTSS_ALPHAARG2
- Texture-stage state is the second alpha argument
for the stage, identified by by D3DTA. The default argument is
D3DTA_CURRENT. Specify D3DTA_TEMP to select 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).
- D3DTSS_BUMPENVMAT00
- Texture-stage state is a floating-point value for
the [0][0] coefficient in a bump-mapping matrix. The default value is 0.0.
- D3DTSS_BUMPENVMAT01
- Texture-stage state is a floating-point value for
the [0][1] coefficient in a bump-mapping matrix. The default value is 0.0.
- D3DTSS_BUMPENVMAT10
- Texture-stage state is a floating-point value for
the [1][0] coefficient in a bump-mapping matrix. The default value is 0.0.
- D3DTSS_BUMPENVMAT11
- Texture-stage state is a floating-point value for
the [1][1] coefficient in a bump-mapping matrix. The default value is 0.0.
- D3DTSS_TEXCOORDINDEX
- Index of the texture coordinate set to use with
this texture stage. You can specify up to eight sets of texture coordinates
per vertex. If a vertex does not include a set of texture coordinates at the
specified index, the system defaults to the u and v coordinates (0,0).
When rendering using vertex shaders, each stage's
texture coordinate index must be set to its default value. The default index
for each stage is equal to the stage index. Set this state to the zero-based
index of the coordinate set for each vertex that this texture stage uses.
Additionally, applications can include, as logical
OR with the index being set, one of the constants to request that Direct3D
automatically generate the input texture coordinates for a texture
transformation. For a list of all the constants, see D3DTSS_TCI.
With the exception of D3DTSS_TCI_PASSTHRU, which
resolves to zero, if any of the following values is included with the index
being set, the system uses the index strictly to determine texture wrapping
mode. These flags are most useful when performing environment mapping.
- D3DTSS_BUMPENVLSCALE
- Floating-point scale value for bump-map luminance.
The default value is 0.0.
- D3DTSS_BUMPENVLOFFSET
- Floating-point offset value for bump-map
luminance. The default value is 0.0.
- D3DTSS_TEXTURETRANSFORMFLAGS
- Member of the D3DTEXTURETRANSFORMFLAGS enumerated
type that controls the transformation of texture coordinates for this
texture stage. The default value is D3DTTFF_DISABLE.
- D3DTSS_COLORARG0
- Settings for the third color operand for triadic
operations (multiply, add, and linearly interpolate), identified by D3DTA.
This setting is supported if the D3DTEXOPCAPS_MULTIPLYADD or
D3DTEXOPCAPS_LERP device capabilities are present. The default argument is
D3DTA_CURRENT. Specify D3DTA_TEMP to select 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).
- D3DTSS_ALPHAARG0
- Settings for the alpha channel selector operand
for triadic operations (multiply, add, and linearly interpolate), identified
by D3DTA. This setting is supported if the D3DTEXOPCAPS_MULTIPLYADD
or D3DTEXOPCAPS_LERP device capabilities are present. The default argument
is D3DTA_CURRENT. Specify D3DTA_TEMP to select a temporary register color
for read or write. D3DTA_TEMP is supported if the D3DPMISCCAPS_TSSARGTEMP
device capability is present. The default argument is (0.0, 0.0, 0.0, 0.0).
- D3DTSS_RESULTARG
- Setting to select destination register for the
result of this stage, identified by D3DTA. This value can be set to
D3DTA_CURRENT (the default value) or to D3DTA_TEMP, which is a single
temporary register that can be read into subsequent stages as an input
argument. The final color passed to the fog blender and frame buffer is
taken from D3DTA_CURRENT, so the last active texture stage state must be set
to write to current. This setting is supported if the
D3DPMISCCAPS_TSSARGTEMP device capability is present.
- D3DTSS_CONSTANT
- Per-stage constant color. To see if a device
supports a per-stage constant color, see the D3DPMISCCAPS_PERSTAGECONSTANT
constant in D3DPMISCCAPS. D3DTSS_CONSTANT is used by D3DTA_CONSTANT. See
D3DTA.
- D3DTSS_FORCE_DWORD
- Forces this enumeration to compile to 32 bits in
size. Without this value, some compilers would allow this enumeration to
compile to a size other than 32 bits. This value is not used.
Remarks
Members of this enumerated type are used with the
IDirect3DDevice9::GetTextureStageState and
IDirect3DDevice9::SetTextureStageState methods to retrieve and set texture state
values.
The valid range of values for the D3DTSS_BUMPENVMAT00,
D3DTSS_BUMPENVMAT01, D3DTSS_BUMPENVMAT10, and D3DTSS_BUMPENVMAT11 bump-mapping
matrix coefficients is greater than or equal to -8.0 and less than 8.0. This
range, expressed in mathematical notation is (-8.0,8.0).
D3DTSS_COLOROP:指定纹理颜色的混合方法,Value值属于D3DTEXTUREOP枚举类型。Value等于D3DTOP_DISABLE,表示禁用当前纹理层颜色输出;Value等于D3DTOP_SELECTARG1或者D3DTOP_SELECTARG2,表示将颜色混合的第一个或第二个参数颜色输出;Value等于D3DTOP_MODULATE,表示将颜色混合的第一个和第二个参数颜色相乘输出。纹理层的颜色混合方法多种多样。
D3DTSS_BUMPENVMAT00、D3DTSS_BUMPENVMAT01、D3DTSS_BUMPENVMAT10、D3DTSS_BUMPENVMAT11:在绘制具有凹凸花纹表面的物体时使用,表示将要设置的凹凸映射矩阵的m[0][0]、m[0][1]、m[1][0]、m[1][1]参数值。
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. |
纹理阶段混合状态示例程序
示例程序演示了纹理阶段混合状态的使用极其效果,纹理阶段混合状态在纹理中具有非常重要的作用,示例代码中设置纹理阶段混合状态的代码如下:
g_device->SetTextureStageState(0, D3DTSS_COLOROP,
D3DTOP_MODULATE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
上面的代码指定将纹理颜色和顶点漫反射颜色相乘输出到第一个纹理层,由于示例程序指定了只使用单层纹理贴图,因此,第一个纹理层的颜色输出就是最终颜色输出,其中顶点漫反射颜色值是由漫反射光照计算得到的。
运行效果图:
如果将设置纹理阶段混合状态的代码改为如下,则采用纹理颜色作为最终的颜色结果,此时光照效果被取消:
g_device->SetTextureStageState(0, D3DTSS_COLOROP,
D3DTOP_SELECTARG1);
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
运行效果图:
如果将设置纹理阶段混合状态的代码改为如下,则采用顶点光照漫反射颜色作为最终的颜色结果,此时纹理贴图效果被取消:
g_device->SetTextureStageState(0, D3DTSS_COLOROP,
D3DTOP_SELECTARG2);
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
运行效果图:
源程序:
#include <d3dx9.h>
#pragma warning(disable : 4127)
#define CLASS_NAME "GameApp"
#define release_com(p) do { if(p) { (p)->Release(); (p) = NULL; } } while(0)
IDirect3D9* g_d3d;
IDirect3DDevice9* g_device;
IDirect3DVertexBuffer9* g_vertex_buffer;
IDirect3DTexture9* g_texture;
struct sCustomVertex
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
float u, v;
};
#define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
void setup_matrices()
{
// build world matrix
D3DXMATRIX mat_world;
D3DXMatrixIdentity(&mat_world);
g_device->SetTransform(D3DTS_WORLD, &mat_world);
// setup view matrix
D3DXVECTOR3 eye(0.0f, 3.0f, -5.0f);
D3DXVECTOR3 at(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX mat_view;
D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
g_device->SetTransform(D3DTS_VIEW, &mat_view);
// setup projection matrix
D3DXMATRIX mat_proj;
D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
}
void setup_material_light()
{
// setup material
D3DMATERIAL9 material;
ZeroMemory(&material, sizeof(material));
material.Diffuse.r = material.Ambient.r = 1.0f;
material.Diffuse.g = material.Ambient.g = 1.0f;
material.Diffuse.b = material.Ambient.b = 1.0f;
material.Diffuse.a = material.Ambient.a = 0.5f;
g_device->SetMaterial(&material);
// setup light
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
light.Diffuse.a = 1.0f;
light.Range = 1000.0f;
float time = timeGetTime() / 350.0f;
light.Direction= D3DXVECTOR3(cosf(time), 1.0f, sinf(time));
g_device->SetLight(0, &light);
g_device->LightEnable(0, TRUE);
g_device->SetRenderState(D3DRS_AMBIENT, 0x00FF5050);
}
bool init_graphics()
{
if(FAILED(D3DXCreateTextureFromFile(g_device, "texture.jpg", &g_texture)))
{
MessageBox(NULL, "Create texture failed!", "ERROR", MB_OK);
return false;
}
g_device->CreateVertexBuffer(50 * 2 * sizeof(sCustomVertex), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT,
&g_vertex_buffer, NULL);
sCustomVertex* vertices;
g_vertex_buffer->Lock(0, 0, (void**)&vertices, 0);
for(int i = 0; i < 50; i++)
{
float theta = (2 * D3DX_PI * i) / (50 - 1);
vertices[2 * i + 0].position = D3DXVECTOR3(sin(theta), -1.0f, cos(theta));
vertices[2 * i + 0].normal = D3DXVECTOR3(sin(theta), 0.0f, cos(theta));
vertices[2 * i + 0].u = ((float)i) / (50-1);
vertices[2 * i + 0].v = 1.0f;
vertices[2 * i + 1].position = D3DXVECTOR3(sin(theta), 1.0f, cos(theta));
vertices[2 * i + 1].normal = D3DXVECTOR3(sin(theta), 0.0f, cos(theta));
vertices[2 * i + 1].u = ((float)i) / (50-1);
vertices[2 * i + 1].v = 0.0f;
}
g_vertex_buffer->Unlock();
return true;
}
bool init_d3d(HWND hwnd)
{
g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if(g_d3d == NULL)
return false;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_device)))
{
return false;
}
if(! init_graphics())
return false;
setup_matrices();
g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
//g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
//g_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
g_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
//g_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
//g_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
//g_device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
return true;
}
void cleanup()
{
release_com(g_texture);
release_com(g_vertex_buffer);
release_com(g_device);
release_com(g_d3d);
}
void render()
{
g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);
g_device->BeginScene();
setup_material_light();
g_device->SetTexture(0, g_texture);
g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);
g_device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 * 50 - 2);
g_device->EndScene();
g_device->Present(NULL, NULL, NULL, NULL);
}
LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_KEYDOWN:
switch(wParam)
{
case VK_ESCAPE:
DestroyWindow(hwnd);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_CLASSDC;
wc.lpfnWndProc = WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = inst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = CLASS_NAME;
wc.hIconSm = NULL;
if(! RegisterClassEx(&wc))
return -1;
HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 480, 480,
NULL, NULL, wc.hInstance, NULL);
if(hwnd == NULL)
return -1;
if(init_d3d(hwnd))
{
ShowWindow(hwnd, SW_SHOWDEFAULT);
UpdateWindow(hwnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
render();
Sleep(10);
}
}
cleanup();
UnregisterClass(CLASS_NAME, wc.hInstance);
return 0;
}
在该示例程序中,每个像素的最终颜色是由光照颜色和纹理颜色共同确定的。
可以说对于三维图形程序设计其所有的操作最后都是为了得到每个像素的颜色,即像素最终显示颜色。
目前为止有三种基本情况:
(1)不使用灯光、材质和纹理。图元顶点的颜色直接取顶点数据中设置的顶点颜色,如果在图元顶点不包含顶点颜色,则默认为黑色。有了图元顶点的颜色,根据着色模式渲染状态,通过插值可得到每个像素的颜色。
(2)使用灯光和材质,但不使用纹理映射。在这种情况下,图元顶点颜色取决于光照计算,由光照计算得到顶点颜色后,根据着色模式渲染状态,通过插值得到每个像素的颜色。
(3)使用纹理映射。在这种情况下,像素的最后颜色取决于纹理阶段混合状态,具体说取决于每个纹理阶段颜色操作和两个颜色参数的来源。