Direct3D融合技术
一、概要
二、融合方程
三、融合因子
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA ,
D3DBLEND_INVDESTALPHA,
D3DBLEND_DESTCOLOR ,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHASAT,
D3DBLEND_BOTHSRCALPHA,
D3DBLEND_BOTHINVSRCALPHA,
D3DBLEND_BLENDFACTOR,
D3DBLEND_INVBLENDFACTOR
四、透明度
1、Alpha通道
2、指定 Alpha 来源
//compute Alpha from diffuse colors during shading Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); //take Alpha from Alpha channel Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
五、示例代码

#include <Windows.h> #include <mmsystem.h> #include <d3dx9.h> #pragma warning( disable : 4996 ) // disable deprecated warning #include <strsafe.h> #pragma warning( default : 4996 ) #include <d3dx9math.h> LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; LPDIRECT3DTEXTURE9 g_pTexture = NULL; struct CUSTOMVERTEX { FLOAT x, y, z; FLOAT tu,tv; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1) HRESULT InitD3D(HWND hWnd) { // Create the D3D object. if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return E_FAIL; // Set up the structure used to create the D3DDevice 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; // Create the D3DDevice if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) { return E_FAIL; } return S_OK; } HRESULT InitGeometry() { if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,L"cratealpha.dds",&g_pTexture))) { return E_FAIL; } CUSTOMVERTEX vertices[] = { { -10.0f, -10.0f, 0.0f, 0,1}, { -10.0f, 10.0f, 0.0f, 0,0 }, { 10.0f, 10.0f, 0.0f, 1,0}, { 10.0f, -10.0f, 0.0f,1,1 }, }; // Create the vertex buffer. if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(vertices)/sizeof(vertices[0]) * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL))) { return E_FAIL; } // Fill the vertex buffer. VOID* pVertices; if (FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0))) return E_FAIL; memcpy(pVertices, (void*)vertices, sizeof(vertices)); g_pVB->Unlock(); WORD indices[] = {0,1,2,0,2,3}; if( FAILED( g_pd3dDevice->CreateIndexBuffer( sizeof(indices)/sizeof(indices[0]) * sizeof( WORD ), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIB, NULL ) ) ) { return E_FAIL; } VOID* pIndices = NULL; if(FAILED(g_pIB->Lock(0, sizeof(indices), (void**)&pIndices,0))) return E_FAIL; memcpy(pIndices,(VOID*)indices, sizeof(indices)); g_pIB->Unlock(); return S_OK; } VOID SetupMatrices() { D3DXVECTOR3 vEyePt(0.0f, 0.0f, -30); D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f); D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec); g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //D3DXMatrixPerspectiveFovLH()函数中的最远、最近距离为相对于视点的距离(即vEyePt中的距离) D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 200.0f); g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); } VOID Cleanup() { if( g_pTexture != NULL ) g_pTexture->Release(); if (g_pVB != NULL) g_pVB->Release(); if (g_pIB != NULL) g_pIB->Release(); if (g_pd3dDevice != NULL) g_pd3dDevice->Release(); if (g_pD3D != NULL) g_pD3D->Release(); } VOID Render() { g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0); // Begin the scene if (SUCCEEDED(g_pd3dDevice->BeginScene())) { SetupMatrices(); g_pd3dDevice->SetTexture( 0, g_pTexture ); g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX)); g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); g_pd3dDevice->SetIndices(g_pIB); g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present(NULL, NULL, NULL, NULL); } //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: The window’s message handler //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: Cleanup(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, msg, wParam, lParam); } //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application’s entry point //----------------------------------------------------------------------------- INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT) { UNREFERENCED_PARAMETER(hInst); // Register the window class WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"D3D Tutorial", NULL }; RegisterClassEx(&wc); // Create the application's window HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 03: CreateAlpha", WS_OVERLAPPEDWINDOW, 100, 100, 700, 700, NULL, NULL, wc.hInstance, NULL); // Initialize Direct3D if (SUCCEEDED(InitD3D(hWnd))) { // Create the scene geometry if (SUCCEEDED(InitGeometry())) { // Show the window ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); // Enter the message loop MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else Render(); } } } UnregisterClass(L"D3D Tutorial", wc.hInstance); return 0; }
alpha通道与混合技术
Alpha其作用是要实现一种半透明效果。
假设一种不透明的东西颜色是A,另一种透明的东西颜色是B,那么透过B去看A,看上去的颜色C就是B与A的混合颜色。设置B的透明度为alpha(取值为0-1,0为完全透明,1为不透明)
R(C)=alpha*R(B)+(1-alpha)*R(A)
G(C)=alpha*G(B)+(1-alpha)*G(A)
B(C)=alpha*B(B)+(1-alpha)*B(A)
融合因子
首先,Direct3D中依然是用Alpha通道来实现多个像素颜色值的融合。每个像素都包含四个分量:Alpha分量、红色分量、绿色分量和蓝色分量(即ARGB四分量)。其中,Alpha分量用于指定像素的透明度,在0~255之间取值,0表示完全透明,255表示完全不透明。另外,根据使用的不同的颜色宏的区别,还可能是在0.0~1.0之间取值。
在Direct3D中,融合这一领域有一个权威,那便是Alpha融合公式。Alpha融合公式如下:
其中RGB_src 和RGB_dst分别表示源像素和目标像素的颜色值,为包含四个颜色分量的颜色值。
K_src 和K_dst分别表示源融合因子和目标融合因子。他们指定了源像素和目标像素的颜色值在融合过程中所占的比例,在[0,1]之间取值。通过原融合因子和目标融合因子,我们能够以多种方式来修改源像素和目标像素的颜色值,从而获得我们满意的最终的融合后的颜色值。稍后会讲解融合因子的具体取法,这里我们先把这个融合公式解析完。
在融合公式中,OP表示源和目标的融合运算方式,由D3DBLENDOP枚举体来指定,需要注意的是它的默认值是源计算结果和目标计算结果相加。
上面我们刚提到过,融合运算方式由D3DBLENDOP枚举体来指定。
我们指的是SetRenderState中的第二个参数在D3DBLENDOP枚举体中取值,而第一个参数,取D3DRS_BLENDOP。
这一节就来看一下这个D3DBLENDOP枚举体的定义:
typedef enum D3DBLENDOP {
D3DBLENDOP_ADD = 1,
D3DBLENDOP_SUBTRACT = 2,
D3DBLENDOP_REVSUBTRACT = 3,
D3DBLENDOP_MIN = 4,
D3DBLENDOP_MAX = 5, D3DBLENDOP_FORCE_DWORD = 0x7fffffff } D3DBLENDOP, *LPD3DBLENDOP;
我们用一个列表来进行讲解吧:
D3DBLENDOP操作符 |
精析 |
D3DBLENDOP_ADD |
源像素计算结果与目标像素的计算结果相加,即【最终结果】=【源】+【目标】 |
D3DBLENDOP_SUBTRACT |
源像素计算结果与目标像素的计算结果相减,即【最终结果】=【源】-【目标】 |
D3DBLENDOP_REVSUBTRACT |
目标像素的计算结果减去源像素计算结果,即【最终结果】=【目标】-【源】 |
D3DBLENDOP_MIN |
在源像素计算结果和目标像素计算结果之间取小者。即【最终结果】= MIN(【目标】,【源】) |
D3DBLENDOP_MAX |
在源像素计算结果和目标像素计算结果之间取大者。即【最终结果】= MAX(【目标】,【源】) |
源融合因子和目标融合因子可以在SetRenderState方法中第一个参数取D3DRS_SRCBLEND和D3DRS_DESTBLEND分别进行设置,而第二个参数都是在一个D3DBLEND枚举体中进行的取值,我们在MSDN中查到它的原型如下:
typedef enum D3DBLEND { D3DBLEND_ZERO = 1, D3DBLEND_ONE = 2, D3DBLEND_SRCCOLOR = 3, D3DBLEND_INVSRCCOLOR = 4, D3DBLEND_SRCALPHA = 5, D3DBLEND_INVSRCALPHA = 6, D3DBLEND_DESTALPHA = 7, D3DBLEND_INVDESTALPHA = 8, D3DBLEND_DESTCOLOR = 9, D3DBLEND_INVDESTCOLOR = 10, D3DBLEND_SRCALPHASAT = 11, D3DBLEND_BOTHSRCALPHA = 12, D3DBLEND_BOTHINVSRCALPHA = 13, D3DBLEND_BLENDFACTOR = 14, D3DBLEND_INVBLENDFACTOR = 15, D3DBLEND_SRCCOLOR2 = 16, D3DBLEND_INVSRCCOLOR2 = 17, D3DBLEND_FORCE_DWORD = 0x7fffffff } D3DBLEND, *LPD3DBLEND;
依旧是通过一个表格来对其中常用的参数进行讲解,:
D3DBLEND融合类型 |
精析 |
D3DBLEND_ZERO |
融合因子=(0,0,0,0) |
D3DBLEND_ONE |
融合因子=(1,1,1,1) |
D3DBLEND_SRCCOLOR |
融合因子=(R_src,G_src,B_src,A_src) |
D3DBLEND_INVSRCCOLOR |
融合因子=(1- R_src,1-G_src,1-B_src,1-A_src ) |
D3DBLEND_SRCALPHA |
融合因子=(1- A_src , A_src , A_src , A_src ) |
D3DBLEND_INVSRCALPHA |
融合因子=( 1- A_src , 1- A_src , 1- A_src , 1- A_src ) |
D3DBLEND_DESTALPHA |
融合因子=( A_dst , A_dst, A_dst , A_dst) |
D3DBLEND_INVDESTALPHA |
融合因子= (1- A_dst , 1- A_dst , 1- A_dst , 1- A_dst ). |
D3DBLEND_DESTCOLOR |
融合因子=( R_dst , G_dst, B_dst , A_dst). |
D3DBLEND_INVDESTCOLOR |
融合因子= ( 1 - R_dst, 1 - G_dst, 1 - B_dst, 1 - A_dst). |
D3DBLEND_SRCALPHASAT |
融合因子= (f, f, f, 1),其中f = min(A_src,1 - A_dst) |
在上表中, R_src , G_src , B_src , A_src 分别表示源(即source)像素的红、绿、蓝、透明四个分量值,而 R_dst , G_dst, B_dst , A_dst 表示目标(即destination)像素的红、绿、蓝、透明四个分量值。
大家需要什么类型的融合因子,在上表中进行查阅就行了。
Alpha的三处来源
我们在使用Alpha融合之前,还需要明确源像素和目标像素颜色值的Alpha分量来自何方。像素的Alpha值一般有三处来源,分别是顶点颜色的Alpha值、材质的Alpha值、纹理的Alpha值。我们通常在这三处来源中取一处就可以了。它们的优先级是这样的,纹理>材质>顶点颜色。
1.顶点Alpha分量
首先我们要知道,顶点Alpha分量只是备胎的备胎而已,它在没有使用光照和材质的情况下才有上场的机会。
如果在程序中直接指定每个顶点的颜色,那么可以直接给出每个顶点颜色的Alpha值,并且这些顶点的Alpha值是可以在程序运行过程中动态修改的。
我们可以通过IDirect3DDevice9::SetTextureStageState方法指定Alpha值的来源,把第三个参数指定为D3DTA_DIFFUSE,来指定Alpha值来自顶点颜色。
在MSDN中查到这个函数原型如下:
HRESULT SetTextureStageState( [in] DWORD Stage, [in]D3DTEXTURESTAGESTATETYPE Type, [in] DWORD Value );
■第一个参数,DWORD类型的Stage,指定当前设置的纹理层为第几层(有效值0~7)
■第二个参数,D3DTEXTURESTAGESTATETYPE类型的Type,填将要设置的纹理渲染状态,在枚举类型D3DTEXTURESTAGESTATETYPE中任意取值。
■第三个参数,DWORD类型的Value,表示所设置的状态值,它是根据第二个参数来决定具体取什么值的。
对于顶点Alpha分量,我们就这样来两句:
//计算漫反射颜色的alpha值 g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); g_pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
2.材质的Alpha分量
之前部分我们讲的材质的Alpha分量,充其量也只是个备胎而已,在场景内的物体没有指定纹理的时候,才有用武之地。在这种情况下,顶点的Alpha值取决于材质属性中漫反射颜色的Alpha系数以及灯光颜色中的Alpha系数,通过材质和光照中的Alpha系数相互作用,计算得到。我们知道,顶点的光照计算过程是分别针对红、绿、蓝、Alpha这四个颜色分量分开独立计算的。而我们关注的顶点的Alpha值就决定于光照计算结果的Alpha分量,和其他的红、绿、蓝三个分量毫无瓜葛。
比如我们可以这样来设定某材质的Alpha分量值,这句代码中我们把这种材质的漫反射颜色值的Alpha分量设为了0.2(范围为0.0~1.0)
g_pMaterial].Diffuse.a= 0.2f;
3.纹理的Alpha分量
作为不可一世的“高富帅”——纹理,既然它在物体表面上使用了,就必须首先满足它的要求,那么,像素的Alpha值就是纹理Alpha混合之后的值了。
所以这时候混合后的像素就取决于纹理的Alpha混合方式。而纹理Alpha混合方式决定了纹理Alpha混合之后的Alpha值是取自材质,还是取自纹理,抑或是取自这两者的某种运算。
若是取自纹理,我们就这样写:
m_pd3dDevice->SetTextureStageState( 0,D3DTSS_ALPHAARG1, D3DTA_TEXTURE );// Alpha值是取自材质 m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); //将纹理颜色混合的第一个参数的ALPHA值用于输出
我是旁白:可以使用DirectX SDK中提供的DirectX Texture Tool来为我们的素材纹理图片创建Alpha通道
Alpha融合使用三步曲
1. 三步曲之一:启用Alpha融合
在Direct3D中,混合默认是被关闭着的,要启用Alpha融合的话,我们就通过设置D3DRS_ALPHABLENDENABLE渲染状态为true,即写上这句代码:
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
2. 三步曲之二:设置融合因子
启用了Alpha融合,第二步便是设置源融合因子和目标融合因子。前面我们已经详细讲解过源融合因子和目标融合因子的取值。源融合因子和目标融合因子分别可以在SetRenderState方法中第一个参数取D3DRS_SRCBLEND和D3DRS_DESTBLEND分别进行设置,第二个参数都是在一个D3DBLEND枚举体中进行的取值。
比如这样写,就是源融合因子=( A_src , A_src , A_src , A_src),目标融合因子=(1- A_src , 1-A_src , 1-A_src , 1-A_src ),这是我们最常用的Alpha混合因子取法:
//设置融合因子 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
3. 三步曲之三:设置Alpha融合运算方式
因为Direct3D中有默认的融合运算方式D3DBLENDOP_ADD,即源像素计算结果与目标像素的计算结果相加。所以这一步其实可以省略,但是如果不想用这种融合运算方式,我们可以加上这一步,用SetRenderState方法来改成我们需要的运算方式,比如如下的代码,便将融合运算方式改成了D3DBLENDOP_SUBTRACT,即源像素计算结果与目标像素的计算结果相减:
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
4. 以代码为载体理解
依旧是把这三步曲整合一下,在Direct3D中运用Alpha混合技术,其实最少只用写3句代码,第三步通常可以省略,即如下的代码:
// 三步曲之一,开启Alpha融合 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //三步曲之二,设置融合因子 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); //三步曲之三,设置融合运算方式 g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); //这句设置运算方式为D3DBLENDOP_ADD的代码Direct3D默认为我们写了,所以注释掉这句也没大碍
SetTextureStageState
先说明几个概念:
1, Multipass(多通道)
将一个任务划分成几个阶段,由多个pass处理不同阶段,后续pass总是处理前一个pass的结果。例如复杂的光照方程可以分成几个pass来计算。
用不同的纹理通过多个pass来多次渲染一个图元,这样可以实现许多很酷的特效。例如LightMap,它就是用不同的纹理来表示复杂的光、影效果。
2, Multitexture(多纹理)
很显然,pass越多,效率越低。为了降低pass的数量,有些硬件加速卡支持在一个pass中渲染两个或更多的纹理,这种技术就叫做multitexture。D3D在一个pass中最多支持8个纹理的混合。
3, Pipeline(管道)
可以将管道想像成一条流水线,它完成某项任务。
4, Stage
一个管道可以由多个stage组成,这些stage同时运行,所以管道的速度取决于最慢的stage。
5, Texture blending cascade
Texture blending cascade是一个pipeline,它完成在一个pass中混合多个纹理这个任务。
6, Texture Stage(也叫做texture unit)
Texture blending cascade由许多Texture Stage构成,每个Texture Stage混合两个纹理(或经过计算的顶点集),通常是RGB和Alpha值,并将结果(经过计算的顶点集)传递给下一个Texture Stage。
理解了上面的那些概念,理解SetTextureStageState函数就很容易了。
HRESULT SetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD Value
);
1, Stage参数,D3D支持8个Texture Unit,索引值由0~7,通过此参数你可以指定是哪一个Texture Unit。
2, Type参数,用来选择Texture Stage不同的状态,如D3DTSS_COLOROP代表颜色混合操作,D3DTSS_ALPHAOP代表ALPHA值混合操作。
3, Value参数,根据不同的Type,来设置其状态值。如:SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_ADD ),就是指在第一个Texture Unit中,将两个颜色值的混合操作设定为累加。
D3DTSS_COLORARG1等其余的参数在D3D Document里写的很详细,就不多说了。
/
/
/
HRESULT SetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD Value
);
stage这个参数是指第几层纹理,1.2.3...9,,这个版本的dx最多支持9层纹理。
Type:Defines the type of operation that atexture stage will perform.//定义对该纹理的哪个属进行设置,值很多。。。
Value: 指的是前面所选属性的值
type:
D3DTSS_ALPHAOP = 4, //alpha通道的运算,
D3DTSS_COLOROP = 1, //颜色的运算
//这里的op 是operations,指对前面设置的颜色进行运算
//既后面的2个type:D3DTSS_COLORARG1,D3DTSS_COLORARG2
//或D3DTSS_ALPHAARG1,D3DTSS_ALPHAARG2 = 6
value:
D3DTOP_DISABLE =1, //该纹理无效,既不显示
D3DTOP_SELECTARG1 =2, //Arg1
D3DTOP_SELECTARG2 =3, //Arg2
D3DTOP_MODULATE =4, //Arg1 * Arg2
D3DTOP_MODULATE2X =5, //Arg1 * Arg2 * 2
D3DTOP_MODULATE4X =6, //Arg1 * Arg2 * 4
D3DTOP_ADD =7, // Arg1 + Arg2
D3DTOP_ADDSIGNED =8, //(Arg1 + Arg2 - 0.5)
D3DTOP_ADDSIGNED2X = 9, //(Arg1 + Arg2 -0.5)*2
D3DTOP_SUBTRACT = 10, //Arg1 - Arg2
D3DTOP_ADDSMOOTH = 11, //Arg1 + Arg2 – Arg1* Arg2
D3DTOP_BLENDDIFFUSEALPHA = 12, //将Arg1与Arg2使用Alpha值进行线性插值。这是标准的Alpha混合效果。纹理参数常数 TextureArgumentConstants同样可以设置到Value里
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, //SRGBA = Arg1 +Arg2 * Arg3
D3DTOP_LERP = 26,
D3DTOP_FORCE_DWORD = 0x7fffffff,
type:
D3DTSS_COLORARG1 = 2,
D3DTSS_COLORARG2 = 3,
D3DTSS_ALPHAARG1 = 5,
D3DTSS_ALPHAARG2 = 6,
D3DTSS_COLORARG0 = 26,
D3DTSS_ALPHAARG0 = 27,
D3DTSS_RESULTARG = 28,
value:
这里的TA指的是texture arguments ,
D3DTA_CURRENT 表示上一个Stage混合的结果。Stage=0时,这个值表示的是D3DTA_DIFFUSE
D3DTA_CONSTANT //给当前纹理一个固定的值;
D3DTA_DIFFUSE; //diffuse的值作为参数 diffuse 可能有多个来源。。比如材质,vertex
D3DTA_SELECTMASK //Mask valuefor all arguments; not used when setting texture arguments 这句话不理解啊,为什么要伪装呢
D3DTA_SPECULAR //取spercular 的值作为参数 来源同diffuse
D3DTA_TEMP //待定。。
D3DTA_TEXTURE //用纹理的颜色值作为参数
D3DTA_TFACTOR //待定。。
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_CONSTANT = 32,
D3DTSS_FORCE_DWORD = 0x7fffffff,
m_pD3DDevice->SetTexture( 0,m_pTexture0 ); // 土地材質
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
// TextureStage 0 (不做任何改變)
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//------------
m_pD3DDevice->SetTexture( 1,m_pTexture1 ); // 草地材質
m_pD3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
// TextureStage 1 (使用頂點alpha值計算混合)
m_pD3DDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
m_pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pD3DDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
m_pD3DDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//------------
// TextureStage 2 (使用光影遮罩圖)// 光影材質
m_pD3DDevice->SetTexture( 2, m_pTexture2 );
m_pD3DDevice->SetTextureStageState( 2, D3DTSS_TEXCOORDINDEX, 1 );
m_pD3DDevice->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
m_pD3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pD3DDevice->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_CURRENT );
m_pD3DDevice->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
//------------
// TextureStage 3 (使用頂點值計算陰影)
m_pD3DDevice->SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pD3DDevice->SetTextureStageState( 3, D3DTSS_COLORARG1, D3DTA_DIFFUSE );
m_pD3DDevice->SetTextureStageState( 3, D3DTSS_COLORARG2, D3DTA_CURRENT );
m_pD3DDevice->SetTextureStageState( 3, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
黑暗纹理
通过纹理映射来模拟逐像素光照效果,通常是将第一层纹理设置为物体原来的表面纹理,将第二层纹理设置为光照纹理,然后将两张纹理的颜色相乘,所以有时将两张纹理的颜色相乘称为光照映射(light mapping)。由于这种技术经常被用于使一张纹理变暗,有时也称为黑暗映射(dark mapping)。
混合纹理与顶点漫反射颜色
当很强的阳光照射在物体表面上时,会使它表面的颜色变得更加明亮,这可以通过将纹理与顶点的漫反射颜色相混合来模拟这种效果。当一个白色材质反射一个方向光时,反射量越多,就意味着纹理颜色在最终显示结果中所占的成分越少。因此,那些被光直接照射到表面会呈现出白色。示例代码如下:
// setup light
ZeroMemory(&g_light,sizeof(D3DLIGHT9));
g_light.Type = D3DLIGHT_DIRECTIONAL;
g_light.Diffuse.r = 0.5f;
g_light.Diffuse.g = 0.5f;
g_light.Diffuse.b = 0.5f;
D3DXVECTOR3 light_dir(0, 0, 10);
D3DXVec3Normalize((D3DXVECTOR3*) &g_light.Direction, &light_dir);
// setup material
ZeroMemory(&g_material,sizeof(D3DMATERIAL9));
g_material.Ambient.r = 1.0f;
g_material.Ambient.g = 1.0f;
g_material.Ambient.b = 1.0f;
g_material.Ambient.a = 1.0f;
g_material.Diffuse.r = 0.7f;
g_material.Diffuse.g = 0.7f;
g_material.Diffuse.b = 0.7f;
g_material.Diffuse.a = 0.5f;
pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00808080);
pd3dDevice->SetLight(0, &g_light);
pd3dDevice->LightEnable(0, TRUE);
pd3dDevice->SetMaterial(&g_material);
pd3dDevice->SetTexture(0,g_base_texture);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
发光映射
发光映射(glowing 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_ADD);
细节映射
如果要模拟一块粗糙的石灰泥墙壁,可以通过细节映射(detail mapping)来实现。实现过程是:将基础贴图(也就是第一张纹理)的颜色未经修改便作为第二个纹理操作阶段中的第二个参数,然后通过D3DTOP_ADDSIGNED将灰色的细节纹理与基础贴图相加。这个操作本质上是做了一个加法,只是使用了有符号的颜色值来代替平时使用的无符号值。在对两张纹理的像素颜色进行D3DTOP_ADDSIGNED操作时,它将参数的每个成分相加后再减去偏移量0.5,从而使有效值域变为-0.5 ~ 0.5。对一些比较旧的显卡,当其不能支持D3DTOP_ADDSIGNED操作时,可以使用D3DTOP_MODULATE2X代替D3DTOP_ADDSIGNED操作进行模拟。
在细节贴图中较亮的灰色纹理元素会使基础贴图变得更亮,而较暗的灰色纹理元素会使基础贴图变得更暗。由此可使物体呈现出粗糙的表面,从而使之看上去更为真实。示例代码如下:
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_detail_texture);
pd3dDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
pd3dDevice->SetTextureStageState(1,D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
hr = pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED);
if(FAILED(hr))
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
ALPHA混合操作
Direct3D在渲染一个场景时,它可以结合几种来源的颜色信息:顶点、当前材质、纹理贴图、先前写入渲染目标的颜色信息,然后将其中的一些颜色混合起来。同时也可以使用Alpha来指定Direct3D该以怎样的权重混合这些颜色,Alpha信息可以存储在顶点中、材质中、纹理贴图中。Alpha值为0表示完全透明,Alpha值为1表示不透明,其余0~1之间的值表示不同程度的透明。
如果要从一张纹理中获取Alpha值,应将D3DTA_TEXTURE作为Alpha参数。
如果要使用来自顶点中的Alpha值,应将D3DTA_DIFFUSE作为Alpha参数,并确保渲染状态D3DRS_DIFFUSEMATERIALSOURCE被设置为D3DMCS_COLOR1(这也是默认状态)。
如果要使用来自材质中的Alpha值,应将D3DTA_DIFFUSE作为Alpha参数,并确保渲染状态D3DRS_DIFFUSEMATERIALSOURCE被设置为D3DMCS_MATERIAL。
如果未用SetRenderState()设置D3DRS_DIFFUSEMATERIALSOURCE参数,则从默认来源(即顶点)获取漫反射颜色。
pd3dDevice->SetTexture(0, g_texture);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
纹理坐标自动生成
在Direct3D程序中,不仅可以在模型载入阶段或渲染阶段指定物体的纹理坐标,还可以通过Direct3D渲染引擎自动生成纹理坐标,用于诸如环境映射等特殊的视觉效果。与手动设置纹理坐标相比,纹理坐标自动生成在Direct3D坐标变换和光照流水线中完成,执行速度更快。
Direct3D系统可以使用经过变换的摄像机空间顶点位置坐标、法线信息来生成纹理坐标。如果使用纹理坐标自动生成,那么在顶点中就可以不用包含纹理坐标数据,从而可以降低图形渲染时的数据传输量。纹理坐标自动生成主要用于产生一些特殊效果,在大多数情况下还是手工为每个顶点指定纹理坐标。
通过调用SetTextureStageState()并将第二个参数设置为D3DTSS_TEXCOORDINDEX来控制Direct3D系统如何自动生成纹理坐标。
D3DTSS_TEXCOORDINDEX用于指定特定纹理层使用顶点中的第几组纹理坐标,但如果指定了上表中的成员值,Direct3D将忽略顶点中的纹理坐标,转而使用自动生成的纹理坐标。
D3DTSS_TEXTURETRANSFORMFLAGS用来控制生成的纹理坐标的输出,在大多数情况下纹理坐标是二维的,即将D3DTSS_TEXTURETRANSFORMFLAGS设置为D3DTTFF_COUNT2。但当绘制线段或三维纹理时,纹理坐标可能是一维或三维的。
纹理坐标变换
Direct3D提供了对生成的纹理坐标进行坐标变换的功能,与顶点坐标变换相类似,可以指定一个4x4的纹理坐标变换矩阵,把它与生成的纹理坐标相乘,然后将变换之后的纹理坐标输出至Direct3D渲染流水线。使用纹理坐标变换可以对纹理坐标进行诸如平移、旋转和缩放等三维变换。纹理坐标变换对于生成一些特殊效果是非常有用的,它不用直接修改顶点的纹理坐标。例如可以通过一个简单的平移矩阵对纹理坐标进行变换,从而使物体表面上的纹理不断变换位置,产生动画效果。纹理坐标自动生成在三维图形程序中最广泛的应用是环境映射。
可通过函数IDirect3DDevice9::SetTransform()来设置4x4的纹理坐标变换矩阵,它以D3DTS_TEXTURE0~ D3DTS_TEXTURE7作为第一个参数,表示设置纹理层0~7的纹理矩阵。下列代码对纹理层0设置了一个将纹理坐标u、v缩小到原来一半的纹理矩阵:
D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
mat._11 = 0.5f;
mat._22 = 0.5f;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat);
下面的代码将原来的纹理坐标平移(1.0, 1.0, 0)个单位。
D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
mat._41 = 1.0f;
mat._42 = 1.0f;
mat._43 = 0.0f;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat);
示例程序通过下列代码对自动生成的纹理坐标进行变换:
// texture coordinate transform
D3DXMATRIX mat_texture, mat_scale,mat_trans;
D3DXMatrixIdentity(&mat_texture);
D3DXMatrixScaling(&mat_scale, 0.5f, -0.5f, 1.0f);
D3DXMatrixTranslation(&mat_trans, 0.5f, 0.5f, 1.0f);
mat_texture = mat_texture * mat_scale *mat_trans;
pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat_texture);
立方体环境映射
立方体环境映射图有时又称为立方体映射图,是一组包含物体周围环境图像的纹理贴图,好像物体在立方体的中心。立方体环境图的每个面覆盖水平和垂直方向上各90度视角区域,一共6个面.
球形环境映射
球形环境映射图(或称为球形映射图)和立方体环境映射图类似,也是一幅包含周围场景图像的特殊纹理。和立方体环境映射图不同的是,球形环境映射图不直接代表物体周围的环境。球形映射图就好像通过鱼眼(fish-eye)凸透镜观察到的景象一样,是一个物体周围环境360度全方位视域的三维表现。
首先使用一张球形的背景图作为环境映射纹理,接着在回调函数OnCreateDevice()中加载纹理和网格模型,接着在回调函数OnResetDevice()中自动生成纹理坐标,并设置纹理阶段颜色混合方法,最后在回调函数OnFrameRender()中渲染茶壶:
V_RETURN(D3DXCreateTextureFromFile(pd3dDevice,L"spheremap.bmp", &g_env_texture));
ID3DXBuffer* material_buffer;
V_RETURN(D3DXLoadMeshFromXW(L"teapot.x", D3DXMESH_MANAGED, pd3dDevice,NULL, &material_buffer, NULL, &g_num_materials, &g_mesh));
D3DXMATERIAL* xmaterials = (D3DXMATERIAL*)material_buffer->GetBufferPointer();g_mesh_materials = newD3DMATERIAL9[g_num_materials];
for(DWORD i = 0; i < g_num_materials; i++){ g_mesh_materials[i] =xmaterials[i].MatD3D;
// .x file do not save ambient data, so set ithere. g_mesh_materials[i].Ambient = g_mesh_materials[i].Diffuse; }
material_buffer->Release();
pd3dDevice->SetTexture(0,g_env_texture);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
pd3dDevice->SetTextureStageState(0,D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_SPHEREMAP);
pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_COUNT2);
// Clear the render target and thezbuffer V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0) );
// Render the scene
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{ for(DWORD i = 0; i < g_num_materials; i++)
{
pd3dDevice->SetMaterial(&g_mesh_materials[i]);
g_mesh->DrawSubset(i);
}
RenderText();
V(g_button_dlg.OnRender(fElapsedTime));
V( pd3dDevice->EndScene() );
}
D3D中的texture应用示例
示例代码使用Beginning direct3D game programming中的框架,省去不少事情,可以专注纹理话题。代码: 点此下载
下面来看代码与效果:
正常的纹理贴图效果:
正常的纹理贴图代码:

2

3



4

5

6

7

8

9

10

11

12

黑暗纹理贴图效果:
黑暗纹理贴图代码:

2

3



4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

漫反射映射贴图效果:夜光镜效果
漫反射映射贴图代码:

2

3



4

5

6

7

8

9

10

11

12

13

14

15

16

发光映射纹理贴图效果:
发光映射纹理贴图代码:

2

3



4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

细节映射纹理贴图:实现粗糙的凹凸效果
细节映射纹理贴图代码:

2

3



4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

alpha纹理混合效果:多次渲染实现
alph纹理混合代码:

2

3



4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

</div>
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 上周热点回顾(2.17-2.23)
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)