之前在BasicEffect中声明了Impl类,主要目的是为了将类的成员和方法定义都转移到源文件中,并且还包含了HLSL五个cbuffer的C++结构体。不仅可以减少BasicEffect类的压力,还可以避免暴露上面的五个结构体:
class BasicEffect::Impl : public AlignedType<BasicEffect::Impl> { public: // // 这些结构体对应HLSL的结构体。需要按16字节对齐 // struct CBChangesEveryDrawing { DirectX::XMMATRIX world; DirectX::XMMATRIX worldInvTranspose; Material material; }; struct CBDrawingStates { int isReflection; int isShadow; DirectX::XMINT2 pad; }; struct CBChangesEveryFrame { DirectX::XMMATRIX view; DirectX::XMFLOAT3 eyePos; float pad; }; struct CBChangesOnResize { DirectX::XMMATRIX proj; }; struct CBChangesRarely { DirectX::XMMATRIX reflection; DirectX::XMMATRIX shadow; DirectX::XMMATRIX refShadow; DirectionalLight dirLight[BasicEffect::maxLights]; PointLight pointLight[BasicEffect::maxLights]; SpotLight spotLight[BasicEffect::maxLights]; }; public: // 必须显式指定 Impl() : m_IsDirty() {} ~Impl() = default; public: // 需要16字节对齐的优先放在前面 CBufferObject<0, CBChangesEveryDrawing> m_CBDrawing; // 每次对象绘制的常量缓冲区 CBufferObject<1, CBDrawingStates> m_CBStates; // 每次绘制状态变更的常量缓冲区 CBufferObject<2, CBChangesEveryFrame> m_CBFrame; // 每帧绘制的常量缓冲区 CBufferObject<3, CBChangesOnResize> m_CBOnResize; // 每次窗口大小变更的常量缓冲区 CBufferObject<4, CBChangesRarely> m_CBRarely; // 几乎不会变更的常量缓冲区 BOOL m_IsDirty; // 是否有值变更 std::vector<CBufferBase*> m_pCBuffers; // 统一管理上面所有的常量缓冲区 ComPtr<ID3D11VertexShader> m_pVertexShader3D; // 用于3D的顶点着色器 ComPtr<ID3D11PixelShader> m_pPixelShader3D; // 用于3D的像素着色器 ComPtr<ID3D11VertexShader> m_pVertexShader2D; // 用于2D的顶点着色器 ComPtr<ID3D11PixelShader> m_pPixelShader2D; // 用于2D的像素着色器 ComPtr<ID3D11InputLayout> m_pVertexLayout2D; // 用于2D的顶点输入布局 ComPtr<ID3D11InputLayout> m_pVertexLayout3D; // 用于3D的顶点输入布局 ComPtr<ID3D11ShaderResourceView> m_pTexture; // 用于绘制的纹理 }; 构造/析构/单例这里用一个匿名空间保管单例对象的指针。当有一个实例被构造出来的时候就会给其赋值。后续就不允许再被实例化了,可以使用Get方法获取该单例。
namespace { // BasicEffect单例 static BasicEffect * g_pInstance = nullptr; } BasicEffect::BasicEffect() { if (g_pInstance) throw std::exception("BasicEffect is a singleton!"); g_pInstance = this; pImpl = std::make_unique<BasicEffect::Impl>(); } BasicEffect::~BasicEffect() { } BasicEffect::BasicEffect(BasicEffect && moveFrom) noexcept { pImpl.swap(moveFrom.pImpl); } BasicEffect & BasicEffect::operator=(BasicEffect && moveFrom) noexcept { pImpl.swap(moveFrom.pImpl); return *this; } BasicEffect & BasicEffect::Get() { if (!g_pInstance) throw std::exception("BasicEffect needs an instance!"); return *g_pInstance; } BasicEffect::InitAll方法BasicEffect::InitAll方法负责创建出所有的着色器和常量缓冲区,以及所有的渲染状态:
bool BasicEffect::InitAll(ID3D11Device * device) { if (!device) return false; if (!pImpl->m_pCBuffers.empty()) return true; if (!RenderStates::IsInit()) throw std::exception("RenderStates need to be initialized first!"); ComPtr<ID3DBlob> blob; // 创建顶点着色器(2D) HR(CreateShaderFromFile(L"HLSL\\Basic_VS_2D.cso", L"HLSL\\Basic_VS_2D.hlsl", "VS_2D", "vs_5_0", blob.GetAddressOf())); HR(device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pVertexShader2D.GetAddressOf())); // 创建顶点布局(2D) HR(device->CreateInputLayout(VertexPosTex::inputLayout, ARRAYSIZE(VertexPosTex::inputLayout), blob->GetBufferPointer(), blob->GetBufferSize(), pImpl->m_pVertexLayout2D.GetAddressOf())); // 创建像素着色器(2D) HR(CreateShaderFromFile(L"HLSL\\Basic_PS_2D.cso", L"HLSL\\Basic_PS_2D.hlsl", "PS_2D", "ps_5_0", blob.ReleaseAndGetAddressOf())); HR(device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pPixelShader2D.GetAddressOf())); // 创建顶点着色器(3D) HR(CreateShaderFromFile(L"HLSL\\Basic_VS_3D.cso", L"HLSL\\Basic_VS_3D.hlsl", "VS_3D", "vs_5_0", blob.ReleaseAndGetAddressOf())); HR(device->CreateVertexShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pVertexShader3D.GetAddressOf())); // 创建顶点布局(3D) HR(device->CreateInputLayout(VertexPosNormalTex::inputLayout, ARRAYSIZE(VertexPosNormalTex::inputLayout), blob->GetBufferPointer(), blob->GetBufferSize(), pImpl->m_pVertexLayout3D.GetAddressOf())); // 创建像素着色器(3D) HR(CreateShaderFromFile(L"HLSL\\Basic_PS_3D.cso", L"HLSL\\Basic_PS_3D.hlsl", "PS_3D", "ps_5_0", blob.ReleaseAndGetAddressOf())); HR(device->CreatePixelShader(blob->GetBufferPointer(), blob->GetBufferSize(), nullptr, pImpl->m_pPixelShader3D.GetAddressOf())); pImpl->m_pCBuffers.assign({ &pImpl->m_CBDrawing, &pImpl->m_CBFrame, &pImpl->m_CBStates, &pImpl->m_CBOnResize, &pImpl->m_CBRarely}); // 创建常量缓冲区 for (auto& pBuffer : pImpl->m_pCBuffers) { HR(pBuffer->CreateBuffer(device)); } return true; } 各种渲染状态的切换下面所有的渲染模式使用的是线性Wrap采样器。
BasicEffect::SetRenderDefault方法--默认渲染