Basic_VS_2D.hlsl变化如下:
#include "Basic.hlsli" // 顶点着色器(2D) VertexPosHTex VS_2D(VertexPosTex vIn) { VertexPosHTex vOut; vOut.PosH = float4(vIn.PosL, 1.0f); vOut.Tex = vIn.Tex; return vOut; }Basic_VS_3D.hlsl变化如下:
#include "Basic.hlsli" // 顶点着色器(3D) VertexPosHWNormalTex VS_3D(VertexPosNormalTex vIn) { VertexPosHWNormalTex vOut; matrix viewProj = mul(g_View, g_Proj); float4 posW = mul(float4(vIn.PosL, 1.0f), g_World); float3 normalW = mul(vIn.NormalL, (float3x3) g_WorldInvTranspose); // 若当前在绘制反射物体,先进行反射操作 [flatten] if (g_IsReflection) { posW = mul(posW, g_Reflection); normalW = mul(normalW, (float3x3) g_Reflection); } // 若当前在绘制阴影,先进行投影操作 [flatten] if (g_IsShadow) { posW = (g_IsReflection ? mul(posW, g_RefShadow) : mul(posW, g_Shadow)); } vOut.PosH = mul(posW, viewProj); vOut.PosW = posW.xyz; vOut.NormalW = normalW; vOut.Tex = vIn.Tex; return vOut; } GameObject类与BasicEffect类的对接由于GameObject类也承担了绘制方法,那么最后的Apply也需要交给游戏对象来调用。因此GameObject::Draw方法变更如下:
void GameObject::Draw(ID3D11DeviceContext * deviceContext, BasicEffect& effect) { // 设置顶点/索引缓冲区 UINT strides = m_VertexStride; UINT offsets = 0; deviceContext->IASetVertexBuffers(0, 1, m_pVertexBuffer.GetAddressOf(), &strides, &offsets); deviceContext->IASetIndexBuffer(m_pIndexBuffer.Get(), DXGI_FORMAT_R32_UINT, 0); // 更新数据并应用 effect.SetWorldMatrix(m_Transform.GetLocalToWorldMatrixXM()); effect.SetTexture(m_pTexture.Get()); effect.SetMaterial(m_Material); effect.Apply(deviceContext); deviceContext->DrawIndexed(m_IndexCount, 0, 0); } 场景绘制现在场景只有墙体、地板、木箱和镜面。
第1步: 镜面区域写入模板缓冲区 // ********************* // 1. 给镜面反射区域写入值1到模板缓冲区 // m_BasicEffect.SetWriteStencilOnly(m_pd3dImmediateContext.Get(), 1); m_Mirror.Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); 第2步: 绘制不透明的反射物体 // *********************** // 2. 绘制不透明的反射物体 // // 开启反射绘制 m_BasicEffect.SetReflectionState(true); m_BasicEffect.SetRenderDefaultWithStencil(m_pd3dImmediateContext.Get(), 1); m_Walls[2].Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); m_Walls[3].Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); m_Walls[4].Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); m_Floor.Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); m_WoodCrate.Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); 第3步: 绘制不透明反射物体的阴影 // *********************** // 3. 绘制不透明反射物体的阴影 // m_WoodCrate.SetMaterial(m_ShadowMat); m_BasicEffect.SetShadowState(true); // 反射开启,阴影开启 m_BasicEffect.SetRenderNoDoubleBlend(m_pd3dImmediateContext.Get(), 1); m_WoodCrate.Draw(m_pd3dImmediateContext.Get(), m_BasicEffect); // 恢复到原来的状态 m_BasicEffect.SetShadowState(false); m_WoodCrate.SetMaterial(m_WoodCrateMat); 第4步: 绘制透明镜面 // *********************** // 4. 绘制透明镜面 // // 关闭反射绘制 m_BasicEffect.SetReflectionState(false); m_BasicEffect.SetRenderAlphaBlendWithStencil(m_pd3dImmediateContext.Get(), 1); m_Mirror.Draw(m_pd3dImmediateContext.Get(), m_BasicEffect);