黑暗贴图动画
可以通过黑暗贴图三种调制操作的切换来创建一个动画示例,代码如下所示:
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);
static double last_time = 0.0f;
double interval = fTime - last_time;
if(interval < 0.5f)
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
else if(interval > 0.5f && interval < 1.0f)
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE2X);
else if(interval > 1.0f && interval < 1.5f)
pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE4X);
else if(interval > 1.5f)
last_time = fTime;
效果如下:
混合纹理与顶点漫反射颜色
当很强的阳光照射在物体表面上时,会使它表面的颜色变得更加明亮,这可以通过将纹理与顶点的漫反射颜色相混合来模拟这种效果。当一个白色材质反射一个方向光时,反射量越多,就意味着纹理颜色在最终显示结果中所占的成分越少。因此,那些被光直接照射到表面会呈现出白色。示例代码如下:
// 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);
运行效果:
这个效果只需一次渲染,因此这里没有多重纹理的代码,对这段代码的简单描述就是"基础贴图 + 漫反射插值"。
在固定函数流水线中有三种获取漫反射颜色的途径(在可编程流水线中则有更多的途径):材质、漫反射顶点颜色、镜面反射顶点颜色。从何处获取漫反射颜色取决于渲染状态D3DRS_DIFFUSEMATERIALSOURCE的设定。例如,如果调用:
pd3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
- D3DRS_DIFFUSEMATERIALSOURCE
- Diffuse color source for lighting calculations.
Valid values are members of the D3DMATERIALCOLORSOURCE enumerated type. The
default value is D3DMCS_COLOR1. The value for this render state is used only
if the D3DRS_COLORVERTEX render state is set to TRUE.
D3DMATERIALCOLORSOURCE
Defines the location at which a color or color
component must be accessed for lighting calculations.
typedef enum D3DMATERIALCOLORSOURCE
{
D3DMCS_MATERIAL = 0,
D3DMCS_COLOR1 = 1,
D3DMCS_COLOR2 = 2,
D3DMCS_FORCE_DWORD = 0x7fffffff,
} D3DMATERIALCOLORSOURCE, *LPD3DMATERIALCOLORSOURCE;
Constants
- D3DMCS_MATERIAL
- Use the color from the current material.
- D3DMCS_COLOR1
- Use the diffuse vertex color.
- D3DMCS_COLOR2
- Use the specular vertex color.
- D3DMCS_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
These flags are used to set the value of the following
render states in the D3DRENDERSTATETYPE enumerated type.
- D3DRS_AMBIENTMATERIALSOURCE
- D3DRS_DIFFUSEMATERIALSOURCE
- D3DRS_EMISSIVEMATERIALSOURCE
- D3DRS_SPECULARMATERIALSOURCE
混合黑暗贴图与顶点漫反射颜色
试想,当你站在一间伸手不见五指的房间内,无法看清周围的任何颜色。于是你打开灯光,突然之间物体的颜色便呈现了出来,就好像是被火焰点燃了一样。对于这种效果,可以通过黑暗贴图和顶点漫反射颜色的混合来模拟。
先将一张纹理与一个顶点的漫反射颜色相混合,再将这个结果与黑暗贴图相混合:
pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x0080FFFF);
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_MODULATE);
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);
运行效果:
如果没有光照,则纹理颜色会乘以0,因此就看不到墙壁纹理了,在这种情况下将只能看到第二张纹理。如果第一张纹理是不可见的,则第一阶段的颜色值0与第二阶段的颜色相乘的结果仍将为0(黑色)。当没有光照在物体的某个表面上时,该面的第一张纹理颜色会减弱为黑色。当你身处一个真正漆黑的地方时,由于光照微弱,你是无法看到周围物体的颜色的,因此上面这段代码对于模拟这种情况非常有效。
这个过程可以描述为"(基础贴图 x 顶点的漫反射颜色)
x 黑暗贴图"