天行健 君子当自强而不息

高级纹理映射技术(3)

黑暗贴图动画

可以通过黑暗贴图三种调制操作的切换来创建一个动画示例,代码如下所示:

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 黑暗贴图"


posted on 2008-05-20 13:59 lovedday 阅读(1832) 评论(1)  编辑 收藏 引用

评论

# re: 高级纹理映射技术(3)[未登录] 2013-03-16 16:10 kid

源码在哪里?
  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论