该模式下,仅对模板缓冲区的模板值和用户指定的相等的区域进行Alpha透明混合绘制。
void BasicEffect::SetRenderAlphaBlendWithStencil(ID3D11DeviceContext * deviceContext, UINT stencilRef) { deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->IASetInputLayout(pImpl->m_pVertexLayout3D.Get()); deviceContext->VSSetShader(pImpl->m_pVertexShader3D.Get(), nullptr, 0); deviceContext->RSSetState(RenderStates::RSNoCull.Get()); deviceContext->PSSetShader(pImpl->m_pPixelShader3D.Get(), nullptr, 0); deviceContext->PSSetSamplers(0, 1, RenderStates::SSLinearWrap.GetAddressOf()); deviceContext->OMSetDepthStencilState(RenderStates::DSSDrawWithStencil.Get(), stencilRef); deviceContext->OMSetBlendState(RenderStates::BSTransparent.Get(), nullptr, 0xFFFFFFFF); } BasicEffect::Set2DRenderDefault方法--2D默认绘制该模式使用的是2D顶点着色器和像素着色器,并修改为2D输入布局。
void BasicEffect::Set2DRenderDefault(ID3D11DeviceContext * deviceContext) { deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->IASetInputLayout(pImpl->m_pVertexLayout2D.Get()); deviceContext->VSSetShader(pImpl->m_pVertexShader2D.Get(), nullptr, 0); deviceContext->RSSetState(nullptr); deviceContext->PSSetShader(pImpl->m_pPixelShader2D.Get(), nullptr, 0); deviceContext->PSSetSamplers(0, 1, RenderStates::SSLinearWrap.GetAddressOf()); deviceContext->OMSetDepthStencilState(nullptr, 0); deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); } BasicEffect::Set2DRenderAlphaBlend方法--2D透明混合绘制相比上面,多了透明混合状态。
void BasicEffect::Set2DRenderAlphaBlend(ID3D11DeviceContext * deviceContext) { deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContext->IASetInputLayout(pImpl->m_pVertexLayout2D.Get()); deviceContext->VSSetShader(pImpl->m_pVertexShader2D.Get(), nullptr, 0); deviceContext->RSSetState(RenderStates::RSNoCull.Get()); deviceContext->PSSetShader(pImpl->m_pPixelShader2D.Get(), nullptr, 0); deviceContext->PSSetSamplers(0, 1, RenderStates::SSLinearWrap.GetAddressOf()); deviceContext->OMSetDepthStencilState(nullptr, 0); deviceContext->OMSetBlendState(RenderStates::BSTransparent.Get(), nullptr, 0xFFFFFFFF); } 更新常量缓冲区下面这些所有的方法会更新CBufferObject中的临时数据,数据脏标记被设为true:
void XM_CALLCONV BasicEffect::SetWorldMatrix(DirectX::FXMMATRIX W) { auto& cBuffer = pImpl->m_CBDrawing; cBuffer.data.world = XMMatrixTranspose(W); cBuffer.data.worldInvTranspose = XMMatrixTranspose(InverseTranspose(W)); pImpl->m_IsDirty = cBuffer.isDirty = true; } void XM_CALLCONV BasicEffect::SetViewMatrix(FXMMATRIX V) { auto& cBuffer = pImpl->m_CBFrame; cBuffer.data.view = XMMatrixTranspose(V); pImpl->m_IsDirty = cBuffer.isDirty = true; } void XM_CALLCONV BasicEffect::SetProjMatrix(FXMMATRIX P) { auto& cBuffer = pImpl->m_CBOnResize; cBuffer.data.proj = XMMatrixTranspose(P); pImpl->m_IsDirty = cBuffer.isDirty = true; } void XM_CALLCONV BasicEffect::SetReflectionMatrix(FXMMATRIX R) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.reflection = XMMatrixTranspose(R); pImpl->m_IsDirty = cBuffer.isDirty = true; } void XM_CALLCONV BasicEffect::SetShadowMatrix(FXMMATRIX S) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.shadow = XMMatrixTranspose(S); pImpl->m_IsDirty = cBuffer.isDirty = true; } void XM_CALLCONV BasicEffect::SetRefShadowMatrix(DirectX::FXMMATRIX RefS) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.refShadow = XMMatrixTranspose(RefS); pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetDirLight(size_t pos, const DirectionalLight & dirLight) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.dirLight[pos] = dirLight; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetPointLight(size_t pos, const PointLight & pointLight) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.pointLight[pos] = pointLight; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetSpotLight(size_t pos, const SpotLight & spotLight) { auto& cBuffer = pImpl->m_CBRarely; cBuffer.data.spotLight[pos] = spotLight; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetMaterial(const Material & material) { auto& cBuffer = pImpl->m_CBDrawing; cBuffer.data.material = material; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetTexture(ID3D11ShaderResourceView * m_pTexture) { pImpl->m_pTexture = m_pTexture; } void BasicEffect::SetEyePos(const XMFLOAT3& eyePos) { auto& cBuffer = pImpl->m_CBFrame; cBuffer.data.eyePos = eyePos; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetReflectionState(bool isOn) { auto& cBuffer = pImpl->m_CBStates; cBuffer.data.isReflection = isOn; pImpl->m_IsDirty = cBuffer.isDirty = true; } void BasicEffect::SetShadowState(bool isOn) { auto& cBuffer = pImpl->m_CBStates; cBuffer.data.isShadow = isOn; pImpl->m_IsDirty = cBuffer.isDirty = true; } BasicEffect::Apply方法--应用缓冲区、纹理资源并进行更新BasicEffect::Apply首先将所需要用到的缓冲区绑定到渲染管线上,并设置纹理,然后才是视情况更新常量缓冲区。
下面的缓冲区数组索引值同时也对应了之前编译期指定的startSlot值。