| 114 | } |
| 115 | |
| 116 | void PlanarReflectionEffect::Draw(std::shared_ptr<GraphicsEngine> const& engine, |
| 117 | PVWUpdater& pvwMatrices) |
| 118 | { |
| 119 | // Save the global state, to be restored later. |
| 120 | std::shared_ptr<BlendState> saveBState = engine->GetBlendState(); |
| 121 | std::shared_ptr<DepthStencilState> saveDSState = engine->GetDepthStencilState(); |
| 122 | std::shared_ptr<RasterizerState> saveRState = engine->GetRasterizerState(); |
| 123 | |
| 124 | // The depth range will be modified during drawing, so save the current |
| 125 | // depth range for restoration later. |
| 126 | float minDepth{}, maxDepth{}; |
| 127 | engine->GetDepthRange(minDepth, maxDepth); |
| 128 | |
| 129 | // Get the camera to store post-world transformations. |
| 130 | std::shared_ptr<Camera> camera = pvwMatrices.GetCamera(); |
| 131 | |
| 132 | // Get the current cull mode and reverse it. Allow for models that are |
| 133 | // not necessarily set up with front or back face culling. |
| 134 | if (saveRState->cull == RasterizerState::Cull::BACK) |
| 135 | { |
| 136 | mCullReverse->cull = RasterizerState::Cull::FRONT; |
| 137 | } |
| 138 | else if (saveRState->cull == RasterizerState::Cull::FRONT) |
| 139 | { |
| 140 | mCullReverse->cull = RasterizerState::Cull::BACK; |
| 141 | } |
| 142 | else |
| 143 | { |
| 144 | mCullReverse->cull = RasterizerState::Cull::NONE; |
| 145 | } |
| 146 | engine->Bind(mCullReverse); |
| 147 | |
| 148 | uint32_t const numPlanes = static_cast<uint32_t>(mPlaneVisuals.size()); |
| 149 | for (uint32_t i = 0, reference = 1; i < numPlanes; ++i, ++reference) |
| 150 | { |
| 151 | auto const& plane = mPlaneVisuals[i]; |
| 152 | |
| 153 | // Render the plane to the stencil buffer only; that is, there are no |
| 154 | // color writes or depth writes. The depth buffer is read so that |
| 155 | // plane pixels occluded by other already drawn geometry are not |
| 156 | // drawn. The stencil buffer value for pixels from plane i is (i+1). |
| 157 | // The stencil buffer is updated at a pixel only when the depth test |
| 158 | // passes at that pixel (the plane pixel is visible): |
| 159 | // face.fail is always false, so value KEEP is irrelevant |
| 160 | // face.depthFail = true, KEEP current stencil value |
| 161 | // face.pass = false, REPLACE current stencil value with (i+1) |
| 162 | // for each face in { frontFace, backFace . |
| 163 | mDSPass0->reference = reference; |
| 164 | engine->SetDepthStencilState(mDSPass0); |
| 165 | engine->SetBlendState(mNoColorWrites); |
| 166 | engine->Draw(plane); |
| 167 | |
| 168 | // Render the plane again. The stencil buffer comparison is EQUAL, so |
| 169 | // the color and depth are updated only at pixels generated by the |
| 170 | // plane; the stencil values for such pixels is necessarily (i+1). The |
| 171 | // depth buffer comparison is ALWAYS and the depth range settings |
| 172 | // cause the depth to be updated to maximum depth at all pixels where |
| 173 | // where the stencil values are (i+1). This allows us to draw the |
nothing calls this directly
no test coverage detected