如何使用DirectX9为网格应用Bump Map凹凸贴图效果
你目前使用的是DirectX9固定功能管线实现渲染,要在现有基础上添加Bump Map(凹凸贴图,采用常规切线空间法线贴图方案),按以下步骤操作即可:
前置准备
- 首先为你的网格生成切线空间数据(切线Tangent、副切线Binormal),并更新顶点声明包含这两个分量,固定管线需要这组数据将光照向量转换到切线空间,和法线贴图采样结果做计算。
- 你用到的Bump Map需要是标准切线空间法线贴图,导入时建议指定格式为
D3DFMT_Q8W8V8U8或者D3DFMT_V8U8,适配固定管线的DOTPRODUCT3计算操作。
代码修改步骤
在现有漫反射纹理绑定逻辑之后、高光纹理绑定逻辑之前,插入Bump Map的处理逻辑,完整修改后的代码如下:
std::vector<std::string> tex_keys = { mesh + "_Diffuse", mesh + "_Ambient", mesh + "_Specular", mesh + "_Dissolve", mesh + "_Bump", mesh + "_Sharpness" }; auto device = GetDevice(); // Diffuse Map _ Base Texture if (TextureMap[tex_keys[0]]) { device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_COLOROP, D3DTOP_MODULATE); device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_COLORARG2, D3DTA_DIFFUSE); device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_ALPHAOP, D3DTOP_MODULATE); device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); device->SetTextureStageState(TextureMap[tex_keys[0]]->GetSlot(), D3DTSS_ALPHAARG2, D3DTA_TEXTURE); TextureMap[tex_keys[0]]->Bind(); } // ========== 新增Bump Map处理逻辑 开始 ========== if (TextureMap[tex_keys[4]]) { UINT bumpSlot = TextureMap[tex_keys[4]]->GetSlot(); // 第一步:用法线贴图采样值和切线空间光照向量做点积,得到凹凸光照系数 device->SetTextureStageState(bumpSlot, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3); device->SetTextureStageState(bumpSlot, D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(bumpSlot, D3DTSS_COLORARG2, D3DTA_DIFFUSE); // 第二步:将凹凸光照系数和前一阶段的漫反射结果相乘,得到带凹凸效果的漫反射颜色 device->SetTextureStageState(bumpSlot, D3DTSS_COLORARG0, D3DTA_CURRENT); device->SetTextureStageState(bumpSlot, D3DTSS_COLOROP, D3DTOP_MODULATE); device->SetTextureStageState(bumpSlot, D3DTSS_COLORARG1, D3DTA_ARG0); device->SetTextureStageState(bumpSlot, D3DTSS_COLORARG2, D3DTA_ARG1); // 绑定Bump纹理 TextureMap[tex_keys[4]]->Bind(); } // ========== 新增Bump Map处理逻辑 结束 ========== // Specular Map if (TextureMap[tex_keys[2]]) { device->SetTextureStageState(TextureMap[tex_keys[2]]->GetSlot(), D3DTSS_COLOROP, D3DTOP_ADD); device->SetTextureStageState(TextureMap[tex_keys[2]]->GetSlot(), D3DTSS_COLORARG1, D3DTA_TEXTURE); device->SetTextureStageState(TextureMap[tex_keys[2]]->GetSlot(), D3DTSS_COLORARG2, D3DTA_CURRENT); TextureMap[tex_keys[2]]->Bind(); }
额外配置说明
- 需要提前开启设备的光照渲染状态:
device->SetRenderState(D3DRS_LIGHTING, TRUE);,同时保证场景中配置了至少一盏可用的平行光。 - 如果凹凸效果不明显,可以调整法线贴图的对比度,或者在纹理阶段配置时添加额外的缩放参数放大凹凸系数。
- 后续如果改用可编程管线(HLSL着色器)实现,逻辑会更灵活,不需要依赖固定管线的DOTPRODUCT3操作,可以直接在像素着色器中完成切线空间光照计算,实现更多自定义效果。
内容的提问来源于stack exchange,提问作者sparkskapil
相关产品推荐
相关产品推荐

