| 10 | using namespace gte; |
| 11 | |
| 12 | PlanarShadowEffect::PlanarShadowEffect( |
| 13 | std::shared_ptr<ProgramFactory> const& factory, |
| 14 | std::shared_ptr<Node> const& shadowCaster, |
| 15 | std::shared_ptr<LightProjector> const& lightProjector, |
| 16 | std::vector<std::shared_ptr<Visual>> const& planeVisuals, |
| 17 | std::vector<Vector4<float>> const& shadowColors) |
| 18 | : |
| 19 | mShadowCaster(shadowCaster), |
| 20 | mLightProjector(lightProjector), |
| 21 | mPlaneVisuals(planeVisuals), |
| 22 | mShadowColors(shadowColors), |
| 23 | mCasterVisuals{}, |
| 24 | mCasterEffects{}, |
| 25 | mSaveVisualEffects{}, |
| 26 | mModelSpaceTriangles{planeVisuals.size()}, |
| 27 | mShadowBlend{}, |
| 28 | mDSPass0{}, |
| 29 | mDSPass1{}, |
| 30 | mAPI(factory->GetAPI()) |
| 31 | { |
| 32 | // Recursively traverse the shadow caster hierarchy and gather all the |
| 33 | // Visual objects. Each Visual requires a constant-color effect for |
| 34 | // drawing the shadow it casts. The model-space triangles are also |
| 35 | // computed during the traversal. |
| 36 | GatherVisuals(factory, mShadowCaster); |
| 37 | mSaveVisualEffects.resize(mCasterEffects.size()); |
| 38 | |
| 39 | // Verify the planeVisuals satisfy the constraints for the POSITION |
| 40 | // semantic. Package the first triangle of vertices into the model-space |
| 41 | // storage. |
| 42 | GetModelSpaceTriangles(); |
| 43 | |
| 44 | mShadowBlend = std::make_shared<BlendState>(); |
| 45 | mShadowBlend->target[0].enable = true; |
| 46 | mShadowBlend->target[0].srcColor = BlendState::Mode::SRC_ALPHA; |
| 47 | mShadowBlend->target[0].dstColor = BlendState::Mode::INV_SRC_ALPHA; |
| 48 | mShadowBlend->target[0].opColor = BlendState::Operation::ADD; |
| 49 | mShadowBlend->target[0].srcAlpha = BlendState::Mode::SRC_ALPHA; |
| 50 | mShadowBlend->target[0].dstAlpha = BlendState::Mode::INV_SRC_ALPHA; |
| 51 | mShadowBlend->target[0].opAlpha = BlendState::Operation::ADD; |
| 52 | mShadowBlend->target[0].mask = BlendState::ColorWrite::ENABLE_ALL; |
| 53 | |
| 54 | // Enable depth reads and writes. The stencil face.fail value is |
| 55 | // irrelevant. The face.depthFail value is KEEP so that invisible pixels |
| 56 | // have stencil value 0. The face.pass value is REPLACE so that visible |
| 57 | // pixels have stencil value i+1 for plane i. The stencil comparison value |
| 58 | // is ALWAYS to that stencil writes always occur. The stencil reference |
| 59 | // i+1 is set on demand for each plane. |
| 60 | mDSPass0 = std::make_shared<DepthStencilState>(); |
| 61 | mDSPass0->depthEnable = true; |
| 62 | mDSPass0->writeMask = DepthStencilState::WriteMask::ALL; |
| 63 | mDSPass0->comparison = DepthStencilState::Comparison::LESS_EQUAL; |
| 64 | mDSPass0->stencilEnable = true; |
| 65 | mDSPass0->stencilReadMask = 0xFF; |
| 66 | mDSPass0->stencilWriteMask = 0xFF; |
| 67 | mDSPass0->frontFace.fail = DepthStencilState::Operation::OP_KEEP; |
| 68 | mDSPass0->frontFace.depthFail = DepthStencilState::Operation::OP_KEEP; |
| 69 | mDSPass0->frontFace.pass = DepthStencilState::Operation::OP_REPLACE; |