DirectX11 With Windows SDK--13 动手实现一个简易Effects框架、阴影效果绘制 (3)

然后是派生类CBufferObject,startSlot指定了HLSL对应cbuffer的索引,T则是C++对应的结构体,存储临时数据:

template<UINT startSlot, class T> struct CBufferObject : CBufferBase { T data; CBufferObject() : CBufferBase(), data() {} HRESULT CreateBuffer(ID3D11Device * device) override { if (cBuffer != nullptr) return S_OK; D3D11_BUFFER_DESC cbd; ZeroMemory(&cbd, sizeof(cbd)); cbd.Usage = D3D11_USAGE_DYNAMIC; cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbd.ByteWidth = sizeof(T); return device->CreateBuffer(&cbd, nullptr, cBuffer.GetAddressOf()); } void UpdateBuffer(ID3D11DeviceContext * deviceContext) override { if (isDirty) { isDirty = false; D3D11_MAPPED_SUBRESOURCE mappedData; deviceContext->Map(cBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData); memcpy_s(mappedData.pData, sizeof(T), &data, sizeof(T)); deviceContext->Unmap(cBuffer.Get(), 0); } } void BindVS(ID3D11DeviceContext * deviceContext) override { deviceContext->VSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } void BindHS(ID3D11DeviceContext * deviceContext) override { deviceContext->HSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } void BindDS(ID3D11DeviceContext * deviceContext) override { deviceContext->DSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } void BindGS(ID3D11DeviceContext * deviceContext) override { deviceContext->GSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } void BindCS(ID3D11DeviceContext * deviceContext) override { deviceContext->CSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } void BindPS(ID3D11DeviceContext * deviceContext) override { deviceContext->PSSetConstantBuffers(startSlot, 1, cBuffer.GetAddressOf()); } };

关于常量缓冲区临时变量的修改则在后续的内容。

BasicEffect类--管理对象绘制的资源

首先是抽象基类IEffects,它仅允许被移动,并且仅包含Apply方法。

class IEffect { public: // 使用模板别名(C++11)简化类型名 template <class T> using ComPtr = Microsoft::WRL::ComPtr<T>; IEffect() = default; // 不支持复制构造 IEffect(const IEffect&) = delete; IEffect& operator=(const IEffect&) = delete; // 允许转移 IEffect(IEffect&& moveFrom) = default; IEffect& operator=(IEffect&& moveFrom) = default; virtual ~IEffect() = default; // 更新并绑定常量缓冲区 virtual void Apply(ID3D11DeviceContext * deviceContext) = 0; };

原来的ID3DX11EffectPass包含的方法Apply用于在各个着色器阶段绑定所需要的常量缓冲区、纹理等资源,并更新之前有所修改的常量缓冲区。现在我们实现Effects框架中的Apply方法也是这么做的。

然后是派生类BasicEffect,从它的方法来看,包含了单例获取、渲染状态的切换、修改常量缓冲区某一成员的值、应用变更四个大块:

class BasicEffect : public IEffect { public: BasicEffect(); virtual ~BasicEffect() override; BasicEffect(BasicEffect&& moveFrom) noexcept; BasicEffect& operator=(BasicEffect&& moveFrom) noexcept; // 获取单例 static BasicEffect& Get(); // 初始化Basic.hlsli所需资源并初始化渲染状态 bool InitAll(ID3D11Device * device); // // 渲染模式的变更 // // 默认状态来绘制 void SetRenderDefault(ID3D11DeviceContext * deviceContext); // Alpha混合绘制 void SetRenderAlphaBlend(ID3D11DeviceContext * deviceContext); // 无二次混合 void SetRenderNoDoubleBlend(ID3D11DeviceContext * deviceContext, UINT stencilRef); // 仅写入模板值 void SetWriteStencilOnly(ID3D11DeviceContext * deviceContext, UINT stencilRef); // 对指定模板值的区域进行绘制,采用默认状态 void SetRenderDefaultWithStencil(ID3D11DeviceContext * deviceContext, UINT stencilRef); // 对指定模板值的区域进行绘制,采用Alpha混合 void SetRenderAlphaBlendWithStencil(ID3D11DeviceContext * deviceContext, UINT stencilRef); // 2D默认状态绘制 void Set2DRenderDefault(ID3D11DeviceContext * deviceContext); // 2D混合绘制 void Set2DRenderAlphaBlend(ID3D11DeviceContext * deviceContext); // // 矩阵设置 // void XM_CALLCONV SetWorldMatrix(DirectX::FXMMATRIX W); void XM_CALLCONV SetViewMatrix(DirectX::FXMMATRIX V); void XM_CALLCONV SetProjMatrix(DirectX::FXMMATRIX P); void XM_CALLCONV SetReflectionMatrix(DirectX::FXMMATRIX R); void XM_CALLCONV SetShadowMatrix(DirectX::FXMMATRIX S); void XM_CALLCONV SetRefShadowMatrix(DirectX::FXMMATRIX RefS); // // 光照、材质和纹理相关设置 // // 各种类型灯光允许的最大数目 static const int maxLights = 5; void SetDirLight(size_t pos, const DirectionalLight& dirLight); void SetPointLight(size_t pos, const PointLight& pointLight); void SetSpotLight(size_t pos, const SpotLight& spotLight); void SetMaterial(const Material& material); void SetTexture(ID3D11ShaderResourceView * texture); void SetEyePos(const DirectX::XMFLOAT3& eyePos); // // 状态开关设置 // void SetReflectionState(bool isOn); void SetShadowState(bool isOn); // 应用常量缓冲区和纹理资源的变更 void Apply(ID3D11DeviceContext * deviceContext); private: class Impl; std::unique_ptr<Impl> pImpl; };

XM_CALLCONV即在第五章之前提到的__vectorcall或__fastcall约定。

BasicEffect::Impl类

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzjgjd.html