(t)
| 9774 | |
| 9775 | const postOn=()=>FX.post||FX.bloom||FX.outline; |
| 9776 | function drawFrame(t){ |
| 9777 | if(!postOn()){ renderer.render(scene,view); return; } |
| 9778 | outlinePass.enabled=!!FX.outline; |
| 9779 | bloomAdd.enabled=!!FX.bloom; |
| 9780 | gradePass.material.uniforms.uOn.value=FX.post?1:0; |
| 9781 | gradePass.material.uniforms.uT.value=t*11.3; |
| 9782 | |
| 9783 | if(FX.outline){ |
| 9784 | const bg=scene.background, ov=scene.overrideMaterial, air=airRoot.visible; |
| 9785 | scene.background=null; scene.overrideMaterial=normalMat; |
| 9786 | /* The air layer sits out of the normal buffer. An override material is |
| 9787 | opaque by definition, so the falls ribbons and the mist — which are |
| 9788 | almost entirely transparent — would punch full-strength silhouettes into |
| 9789 | the depth buffer and come back as hard rectangles ruled across the sky. */ |
| 9790 | airRoot.visible=false; |
| 9791 | view.layers.set(0); // sprites live off layer 0 — see markBloom |
| 9792 | renderer.setRenderTarget(normalRT); |
| 9793 | renderer.clear(); |
| 9794 | renderer.render(scene,view); |
| 9795 | renderer.setRenderTarget(null); |
| 9796 | view.layers.enableAll(); |
| 9797 | scene.background=bg; scene.overrideMaterial=ov; airRoot.visible=air; |
| 9798 | const u=outlinePass.material.uniforms; |
| 9799 | u.tNormal.value=normalRT.texture; u.tDepth.value=normalRT.depthTexture; |
| 9800 | u.uNear.value=view.near; u.uFar.value=view.far; |
| 9801 | } |
| 9802 | if(FX.bloom){ |
| 9803 | const bg=scene.background; |
| 9804 | scene.background=null; // or the sky blooms as one flat sheet |
| 9805 | /* The whole scene, with everything that does not glow painted black — |
| 9806 | NOT just the emissive layer on its own. Rendering the layer alone leaves |
| 9807 | the bloom buffer with no occluders in it at all, so a lamp behind a wall |
| 9808 | is drawn as if the wall were not there, and `bloomAdd` then adds that |
| 9809 | glow over the finished frame with no depth test. The lamp shines through |
| 9810 | the wall. |
| 9811 | |
| 9812 | Under the isometric camera you are looking down on a shallow town and |
| 9813 | almost nothing is behind anything else, so this never showed. Ride a bird |
| 9814 | through the same town at roof height and half the district is suddenly |
| 9815 | behind something — which is where a scatter of pale blobs sitting on top |
| 9816 | of rooftops, hillside and sky came from. |
| 9817 | |
| 9818 | Black geometry costs nothing in the bloom (it is under any threshold) but |
| 9819 | it writes depth and paints over what is behind it, which is the entire |
| 9820 | point. colorWrite stays ON for exactly that reason: three sorts opaque |
| 9821 | front-to-back but does not guarantee it, and a depth-only occluder cannot |
| 9822 | erase a glow that was already drawn. */ |
| 9823 | bloomMask(true); |
| 9824 | bloomComposer.render(); |
| 9825 | bloomMask(false); |
| 9826 | scene.background=bg; |
| 9827 | bloomAdd.material.uniforms.tBloom.value=bloomComposer.renderTarget2.texture; |
| 9828 | } |
| 9829 | composer.render(); |
| 9830 | } |
| 9831 | |
| 9832 | /* =================================================================== the hand |
| 9833 | Dungeon Keeper's hand, at the scale this world actually runs at: the smallest |
no test coverage detected