From b48227fffdc535cc42ad4050c719912159090c47 Mon Sep 17 00:00:00 2001 From: Michael Herzog Date: Tue, 20 Jan 2026 17:59:32 +0100 Subject: [PATCH] Examples: Update Godrays demo. (#32801) --- examples/jsm/Addons.js | 1 - examples/jsm/shaders/GodRaysShader.js | 333 -------------- examples/models/gltf/godrays_demo.glb | Bin 0 -> 75824 bytes .../webgl_postprocessing_godrays.jpg | Bin 44198 -> 19438 bytes examples/tags.json | 2 +- examples/webgl_postprocessing_godrays.html | 407 ++++++------------ 6 files changed, 127 insertions(+), 616 deletions(-) delete mode 100644 examples/jsm/shaders/GodRaysShader.js create mode 100644 examples/models/gltf/godrays_demo.glb diff --git a/examples/jsm/Addons.js b/examples/jsm/Addons.js index d901f4de1746e5..58350ce6d9bed9 100644 --- a/examples/jsm/Addons.js +++ b/examples/jsm/Addons.js @@ -223,7 +223,6 @@ export * from './shaders/FilmShader.js'; export * from './shaders/FocusShader.js'; export * from './shaders/FreiChenShader.js'; export * from './shaders/GammaCorrectionShader.js'; -export * from './shaders/GodRaysShader.js'; export * from './shaders/GTAOShader.js'; export * from './shaders/HalftoneShader.js'; export * from './shaders/HorizontalBlurShader.js'; diff --git a/examples/jsm/shaders/GodRaysShader.js b/examples/jsm/shaders/GodRaysShader.js deleted file mode 100644 index 6fe9629adee004..00000000000000 --- a/examples/jsm/shaders/GodRaysShader.js +++ /dev/null @@ -1,333 +0,0 @@ -import { - Color, - Vector3 -} from 'three'; - -/** - * @module GodRaysShader - * @three_import import * as GodRaysShader from 'three/addons/shaders/GodRaysShader.js'; - */ - -/** - * God-rays (crepuscular rays) - * - * Similar implementation to the one used by Crytek for CryEngine 2 [Sousa2008]. - * Blurs a mask generated from the depth map along radial lines emanating from the light - * source. The blur repeatedly applies a blur filter of increasing support but constant - * sample count to produce a blur filter with large support. - * - * My implementation performs 3 passes, similar to the implementation from Sousa. I found - * just 6 samples per pass produced acceptable results. The blur is applied three times, - * with decreasing filter support. The result is equivalent to a single pass with - * 6*6*6 = 216 samples. - * - * References: - * - [Sousa2008, Crysis Next Gen Effects, GDC2008](http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt). - * - * @constant - * @type {ShaderMaterial~Shader} - */ -const GodRaysDepthMaskShader = { - - name: 'GodRaysDepthMaskShader', - - uniforms: { - - tInput: { - value: null - } - - }, - - vertexShader: /* glsl */` - - varying vec2 vUv; - - void main() { - - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - - }`, - - fragmentShader: /* glsl */` - - varying vec2 vUv; - - uniform sampler2D tInput; - - void main() { - - gl_FragColor = vec4( 1.0 ) - texture2D( tInput, vUv ); - - }` - -}; - - -/** - * The god-ray generation shader. - * - * First pass: - * - * The depth map is blurred along radial lines towards the "sun". The - * output is written to a temporary render target (I used a 1/4 sized - * target). - * - * Pass two & three: - * - * The results of the previous pass are re-blurred, each time with a - * decreased distance between samples. - * - * @constant - * @type {ShaderMaterial~Shader} - */ -const GodRaysGenerateShader = { - - name: 'GodRaysGenerateShader', - - uniforms: { - - tInput: { - value: null - }, - fStepSize: { - value: 1.0 - }, - vSunPositionScreenSpace: { - value: new Vector3() - } - - }, - - vertexShader: /* glsl */` - - varying vec2 vUv; - - void main() { - - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - - }`, - - fragmentShader: /* glsl */` - - #define TAPS_PER_PASS 6.0 - - varying vec2 vUv; - - uniform sampler2D tInput; - - uniform vec3 vSunPositionScreenSpace; - uniform float fStepSize; // filter step size - - void main() { - - // delta from current pixel to "sun" position - - vec2 delta = vSunPositionScreenSpace.xy - vUv; - float dist = length( delta ); - - // Step vector (uv space) - - vec2 stepv = fStepSize * delta / dist; - - // Number of iterations between pixel and sun - - float iters = dist/fStepSize; - - vec2 uv = vUv.xy; - float col = 0.0; - - // This breaks ANGLE in Chrome 22 - // - see http://code.google.com/p/chromium/issues/detail?id=153105 - - /* - // Unrolling didn't do much on my hardware (ATI Mobility Radeon 3450), - // so i've just left the loop - - "for ( float i = 0.0; i < TAPS_PER_PASS; i += 1.0 ) {", - - // Accumulate samples, making sure we don't walk past the light source. - - // The check for uv.y < 1 would not be necessary with "border" UV wrap - // mode, with a black border color. I don't think this is currently - // exposed by three.js. As a result there might be artifacts when the - // sun is to the left, right or bottom of screen as these cases are - // not specifically handled. - - " col += ( i <= iters && uv.y < 1.0 ? texture2D( tInput, uv ).r : 0.0 );", - " uv += stepv;", - - "}", - */ - - // Unrolling loop manually makes it work in ANGLE - - float f = min( 1.0, max( vSunPositionScreenSpace.z / 1000.0, 0.0 ) ); // used to fade out godrays - - if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r * f; - uv += stepv; - - // Should technically be dividing by 'iters but 'TAPS_PER_PASS' smooths out - // objectionable artifacts, in particular near the sun position. The side - // effect is that the result is darker than it should be around the sun, as - // TAPS_PER_PASS is greater than the number of samples actually accumulated. - // When the result is inverted (in the shader 'godrays_combine this produces - // a slight bright spot at the position of the sun, even when it is occluded. - - gl_FragColor = vec4( col/TAPS_PER_PASS ); - gl_FragColor.a = 1.0; - - }` - -}; - -/** - * Additively applies god rays from texture tGodRays to a background (tColors). - * fGodRayIntensity attenuates the god rays. - * - * @constant - * @type {ShaderMaterial~Shader} - */ -const GodRaysCombineShader = { - - name: 'GodRaysCombineShader', - - uniforms: { - - tColors: { - value: null - }, - - tGodRays: { - value: null - }, - - fGodRayIntensity: { - value: 0.69 - } - - }, - - vertexShader: /* glsl */` - - varying vec2 vUv; - - void main() { - - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - - }`, - - fragmentShader: /* glsl */` - - varying vec2 vUv; - - uniform sampler2D tColors; - uniform sampler2D tGodRays; - - uniform float fGodRayIntensity; - - void main() { - - // Since THREE.MeshDepthMaterial renders foreground objects white and background - // objects black, the god-rays will be white streaks. Therefore value is inverted - // before being combined with tColors - - gl_FragColor = texture2D( tColors, vUv ) + fGodRayIntensity * vec4( 1.0 - texture2D( tGodRays, vUv ).r ); - gl_FragColor.a = 1.0; - - }` - -}; - - -/** - * A dodgy sun/sky shader. Makes a bright spot at the sun location. Would be - * cheaper/faster/simpler to implement this as a simple sun sprite. - * - * @constant - * @type {Object} - */ -const GodRaysFakeSunShader = { - - name: 'GodRaysFakeSunShader', - - uniforms: { - - vSunPositionScreenSpace: { - value: new Vector3() - }, - - fAspect: { - value: 1.0 - }, - - sunColor: { - value: new Color( 0xffee00 ) - }, - - bgColor: { - value: new Color( 0x000000 ) - } - - }, - - vertexShader: /* glsl */` - - varying vec2 vUv; - - void main() { - - vUv = uv; - gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); - - }`, - - fragmentShader: /* glsl */` - - varying vec2 vUv; - - uniform vec3 vSunPositionScreenSpace; - uniform float fAspect; - - uniform vec3 sunColor; - uniform vec3 bgColor; - - void main() { - - vec2 diff = vUv - vSunPositionScreenSpace.xy; - - // Correct for aspect ratio - - diff.x *= fAspect; - - float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 ); - prop = 0.35 * pow( 1.0 - prop, 3.0 ); - - gl_FragColor.xyz = ( vSunPositionScreenSpace.z > 0.0 ) ? mix( sunColor, bgColor, 1.0 - prop ) : bgColor; - gl_FragColor.w = 1.0; - - }` - -}; - -export { GodRaysDepthMaskShader, GodRaysGenerateShader, GodRaysCombineShader, GodRaysFakeSunShader }; diff --git a/examples/models/gltf/godrays_demo.glb b/examples/models/gltf/godrays_demo.glb new file mode 100644 index 0000000000000000000000000000000000000000..4e63ff9131dfdbb7ebe79e6e7a40664ddc8bcc92 GIT binary patch literal 75824 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 literal 0 HcmV?d00001 diff --git a/examples/screenshots/webgl_postprocessing_godrays.jpg b/examples/screenshots/webgl_postprocessing_godrays.jpg index 60ddccdd51a9867b7eecae675e66859567e08fc2..0a8a358541c7bd61c9fcdb2ba1f20114d1c02e6b 100644 GIT binary patch delta 19123 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 literal 44198 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 USi$yPmoTmk1#1f4{#Ez?1C^5M?*IS* diff --git a/examples/tags.json b/examples/tags.json index 16dd0c5053e6c2..edee62010f7d63 100644 --- a/examples/tags.json +++ b/examples/tags.json @@ -102,7 +102,7 @@ "webgl_postprocessing_dof": [ "bokeh" ], "webgl_postprocessing_dof2": [ "bokeh" ], "webgl_postprocessing_fxaa": [ "msaa", "multisampled" ], - "webgl_postprocessing_godrays": [ "light scattering" ], + "webgl_postprocessing_godrays": [ "community" ], "webgl_postprocessing_gtao": [ "ambient occlusion" ], "webgl_shadowmap_progressive": [ "shadow", "soft", "lightmap", "onBeforeCompile" ], "webgl_postprocessing_ssaa": [ "msaa", "multisampled" ], diff --git a/examples/webgl_postprocessing_godrays.html b/examples/webgl_postprocessing_godrays.html index 605ffab5d308dd..e6efed53c1f35d 100644 --- a/examples/webgl_postprocessing_godrays.html +++ b/examples/webgl_postprocessing_godrays.html @@ -9,14 +9,16 @@ @@ -27,92 +29,130 @@ import Stats from 'three/addons/libs/stats.module.js'; - import { OBJLoader } from 'three/addons/loaders/OBJLoader.js'; + import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - import { GodRaysFakeSunShader, GodRaysDepthMaskShader, GodRaysCombineShader, GodRaysGenerateShader } from 'three/addons/shaders/GodRaysShader.js'; - let container, stats; - let camera, scene, renderer, materialDepth; + import { EffectComposer, RenderPass } from 'postprocessing'; + import { GodraysPass } from 'goodrays'; - let sphereMesh; + let camera, scene, renderer, composer; + let controls, stats; - const sunPosition = new THREE.Vector3( 0, 1000, - 1000 ); - const clipPosition = new THREE.Vector4(); - const screenSpacePosition = new THREE.Vector3(); + init(); - const postprocessing = { enabled: true }; + async function init() { - const orbitRadius = 200; + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 1000 ); + camera.position.set( - 175, 50, 0 ); - const bgColor = 0x000511; - const sunColor = 0xffee00; + scene = new THREE.Scene(); + scene.background = new THREE.Color( 0x000000 ); - // Use a smaller size for some of the god-ray render targets for better performance. - const godrayRenderTargetResolutionMultiplier = 1.0 / 4.0; + // asset - init(); + const loader = new GLTFLoader(); + const gltf = await loader.loadAsync( 'models/gltf/godrays_demo.glb' ); + scene.add( gltf.scene ); - function init() { + const pillars = gltf.scene.getObjectByName( 'concrete' ); + pillars.material = new THREE.MeshStandardMaterial( { + color: 0x333333, + } ); - container = document.createElement( 'div' ); - document.body.appendChild( container ); + const base = gltf.scene.getObjectByName( 'base' ); + base.material = new THREE.MeshStandardMaterial( { + color: 0x333333, + side: THREE.DoubleSide, + } ); - // + setupBackdrop(); - camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 ); - camera.position.z = 200; + // lights - scene = new THREE.Scene(); + const lightPos = new THREE.Vector3( 0, 50, 0 ); + const lightSphereMaterial = new THREE.MeshBasicMaterial( { + color: 0xffffff, + } ); + const lightSphere = new THREE.Mesh( new THREE.SphereGeometry( 0.5, 16, 16 ), lightSphereMaterial ); + lightSphere.position.copy( lightPos ); + scene.add( lightSphere ); - // + scene.add( new THREE.AmbientLight( 0xcccccc, 0.4 ) ); - materialDepth = new THREE.MeshDepthMaterial(); + const pointLight = new THREE.PointLight( 0xf6287d, 10000 ); + pointLight.castShadow = true; + pointLight.shadow.bias = - 0.001; + pointLight.shadow.mapSize.width = 1024; + pointLight.shadow.mapSize.height = 1024; + pointLight.position.copy( lightPos ); + scene.add( pointLight ); - // tree + // shadow setup - const loader = new OBJLoader(); - loader.load( 'models/obj/tree.obj', function ( object ) { + scene.traverse( obj => { - object.position.set( 0, - 150, - 150 ); - object.scale.multiplyScalar( 400 ); - scene.add( object ); + if ( obj.isMesh === true ) { - } ); + obj.castShadow = true; + obj.receiveShadow = true; - // sphere + } - const geo = new THREE.SphereGeometry( 1, 20, 10 ); - sphereMesh = new THREE.Mesh( geo, new THREE.MeshBasicMaterial( { color: 0x000000 } ) ); - sphereMesh.scale.multiplyScalar( 20 ); - scene.add( sphereMesh ); + } ); + + lightSphere.castShadow = false; + lightSphere.receiveShadow = false; // renderer = new THREE.WebGLRenderer(); - renderer.setClearColor( 0xffffff ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setAnimationLoop( animate ); - container.appendChild( renderer.domElement ); + renderer.shadowMap.enabled = true; + document.body.appendChild( renderer.domElement ); + + // - renderer.autoClear = false; + composer = new EffectComposer( renderer, { frameBufferType: THREE.HalfFloatType } ); - const controls = new OrbitControls( camera, renderer.domElement ); - controls.minDistance = 50; - controls.maxDistance = 500; + const renderPass = new RenderPass( scene, camera ); + composer.addPass( renderPass ); + + const params = { + density: 1 / 128, + maxDensity: 0.5, + edgeStrength: 2, + edgeRadius: 2, + distanceAttenuation: 2, + color: new THREE.Color( 0xf6287d ), + raymarchSteps: 60, + blur: true, + gammaCorrection: true, + }; + + + const godraysPass = new GodraysPass( pointLight, camera, params ); + godraysPass.renderToScreen = true; + composer.addPass( godraysPass ); // - stats = new Stats(); - container.appendChild( stats.dom ); + controls = new OrbitControls( camera, renderer.domElement ); + controls.target.set( 0, 0.5, 0 ); + controls.enableDamping = true; + controls.maxDistance = 200; + controls.update(); // - window.addEventListener( 'resize', onWindowResize ); + stats = new Stats(); + document.body.appendChild( stats.dom ); // - initPostprocessing( window.innerWidth, window.innerHeight ); + window.addEventListener( 'resize', onWindowResize ); + } @@ -120,254 +160,59 @@ function onWindowResize() { - const renderTargetWidth = window.innerWidth; - const renderTargetHeight = window.innerHeight; - - camera.aspect = renderTargetWidth / renderTargetHeight; + camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); - renderer.setSize( renderTargetWidth, renderTargetHeight ); - postprocessing.rtTextureColors.setSize( renderTargetWidth, renderTargetHeight ); - postprocessing.rtTextureDepth.setSize( renderTargetWidth, renderTargetHeight ); - postprocessing.rtTextureDepthMask.setSize( renderTargetWidth, renderTargetHeight ); - - const adjustedWidth = renderTargetWidth * godrayRenderTargetResolutionMultiplier; - const adjustedHeight = renderTargetHeight * godrayRenderTargetResolutionMultiplier; - postprocessing.rtTextureGodRays1.setSize( adjustedWidth, adjustedHeight ); - postprocessing.rtTextureGodRays2.setSize( adjustedWidth, adjustedHeight ); + renderer.setSize( window.innerWidth, window.innerHeight ); } - function initPostprocessing( renderTargetWidth, renderTargetHeight ) { - - postprocessing.scene = new THREE.Scene(); - - postprocessing.camera = new THREE.OrthographicCamera( - 0.5, 0.5, 0.5, - 0.5, - 10000, 10000 ); - postprocessing.camera.position.z = 100; - - postprocessing.scene.add( postprocessing.camera ); - - postprocessing.rtTextureColors = new THREE.WebGLRenderTarget( renderTargetWidth, renderTargetHeight, { type: THREE.HalfFloatType } ); - - // I would have this quarter size and use it as one of the ping-pong render - // targets but the aliasing causes some temporal flickering - - postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( renderTargetWidth, renderTargetHeight, { type: THREE.HalfFloatType } ); - postprocessing.rtTextureDepthMask = new THREE.WebGLRenderTarget( renderTargetWidth, renderTargetHeight, { type: THREE.HalfFloatType } ); - - // The ping-pong render targets can use an adjusted resolution to minimize cost - - const adjustedWidth = renderTargetWidth * godrayRenderTargetResolutionMultiplier; - const adjustedHeight = renderTargetHeight * godrayRenderTargetResolutionMultiplier; - postprocessing.rtTextureGodRays1 = new THREE.WebGLRenderTarget( adjustedWidth, adjustedHeight, { type: THREE.HalfFloatType } ); - postprocessing.rtTextureGodRays2 = new THREE.WebGLRenderTarget( adjustedWidth, adjustedHeight, { type: THREE.HalfFloatType } ); - - // god-ray shaders - - const godraysMaskShader = GodRaysDepthMaskShader; - postprocessing.godrayMaskUniforms = THREE.UniformsUtils.clone( godraysMaskShader.uniforms ); - postprocessing.materialGodraysDepthMask = new THREE.ShaderMaterial( { - - uniforms: postprocessing.godrayMaskUniforms, - vertexShader: godraysMaskShader.vertexShader, - fragmentShader: godraysMaskShader.fragmentShader + function setupBackdrop() { + const backdropDistance = 200; + // Add backdrop walls `backdropDistance` units away from the origin + const backdropGeometry = new THREE.PlaneGeometry( 400, 200 ); + const backdropMaterial = new THREE.MeshBasicMaterial( { + color: 0x200808, + side: THREE.DoubleSide, } ); - - const godraysGenShader = GodRaysGenerateShader; - postprocessing.godrayGenUniforms = THREE.UniformsUtils.clone( godraysGenShader.uniforms ); - postprocessing.materialGodraysGenerate = new THREE.ShaderMaterial( { - - uniforms: postprocessing.godrayGenUniforms, - vertexShader: godraysGenShader.vertexShader, - fragmentShader: godraysGenShader.fragmentShader - - } ); - - const godraysCombineShader = GodRaysCombineShader; - postprocessing.godrayCombineUniforms = THREE.UniformsUtils.clone( godraysCombineShader.uniforms ); - postprocessing.materialGodraysCombine = new THREE.ShaderMaterial( { - - uniforms: postprocessing.godrayCombineUniforms, - vertexShader: godraysCombineShader.vertexShader, - fragmentShader: godraysCombineShader.fragmentShader - - } ); - - const godraysFakeSunShader = GodRaysFakeSunShader; - postprocessing.godraysFakeSunUniforms = THREE.UniformsUtils.clone( godraysFakeSunShader.uniforms ); - postprocessing.materialGodraysFakeSun = new THREE.ShaderMaterial( { - - uniforms: postprocessing.godraysFakeSunUniforms, - vertexShader: godraysFakeSunShader.vertexShader, - fragmentShader: godraysFakeSunShader.fragmentShader - - } ); - - postprocessing.godraysFakeSunUniforms.bgColor.value.setHex( bgColor ); - postprocessing.godraysFakeSunUniforms.sunColor.value.setHex( sunColor ); - - postprocessing.godrayCombineUniforms.fGodRayIntensity.value = 0.75; - - postprocessing.quad = new THREE.Mesh( - new THREE.PlaneGeometry( 1.0, 1.0 ), - postprocessing.materialGodraysGenerate - ); - postprocessing.quad.position.z = - 9900; - postprocessing.scene.add( postprocessing.quad ); + const backdropLeft = new THREE.Mesh( backdropGeometry, backdropMaterial ); + backdropLeft.position.set( - backdropDistance, 100, 0 ); + backdropLeft.rotateY( Math.PI / 2 ); + scene.add( backdropLeft ); + + const backdropRight = new THREE.Mesh( backdropGeometry, backdropMaterial ); + backdropRight.position.set( backdropDistance, 100, 0 ); + backdropRight.rotateY( Math.PI / 2 ); + scene.add( backdropRight ); + + const backdropFront = new THREE.Mesh( backdropGeometry, backdropMaterial ); + backdropFront.position.set( 0, 100, - backdropDistance ); + scene.add( backdropFront ); + + const backdropBack = new THREE.Mesh( backdropGeometry, backdropMaterial ); + backdropBack.position.set( 0, 100, backdropDistance ); + scene.add( backdropBack ); + + const backdropTop = new THREE.Mesh( backdropGeometry, backdropMaterial ); + backdropTop.position.set( 0, 200, 0 ); + backdropTop.rotateX( Math.PI / 2 ); + backdropTop.scale.set( 3, 6, 1 ); + scene.add( backdropTop ); } function animate() { - stats.begin(); - render(); - stats.end(); - - } - - function getStepSize( filterLen, tapsPerPass, pass ) { - - return filterLen * Math.pow( tapsPerPass, - pass ); - - } - - function filterGodRays( inputTex, renderTarget, stepSize ) { - - postprocessing.scene.overrideMaterial = postprocessing.materialGodraysGenerate; - - postprocessing.godrayGenUniforms[ 'fStepSize' ].value = stepSize; - postprocessing.godrayGenUniforms[ 'tInput' ].value = inputTex; - - renderer.setRenderTarget( renderTarget ); - renderer.render( postprocessing.scene, postprocessing.camera ); - postprocessing.scene.overrideMaterial = null; - - } - - function render() { - - const time = Date.now() / 4000; - - sphereMesh.position.x = orbitRadius * Math.cos( time ); - sphereMesh.position.z = orbitRadius * Math.sin( time ) - 100; - - if ( postprocessing.enabled ) { - - clipPosition.x = sunPosition.x; - clipPosition.y = sunPosition.y; - clipPosition.z = sunPosition.z; - clipPosition.w = 1; - - clipPosition.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); - - // perspective divide (produce NDC space) - - clipPosition.x /= clipPosition.w; - clipPosition.y /= clipPosition.w; - - screenSpacePosition.x = ( clipPosition.x + 1 ) / 2; // transform from [-1,1] to [0,1] - screenSpacePosition.y = ( clipPosition.y + 1 ) / 2; // transform from [-1,1] to [0,1] - screenSpacePosition.z = clipPosition.z; // needs to stay in clip space for visibility checks - - // Give it to the god-ray and sun shaders - - postprocessing.godrayGenUniforms[ 'vSunPositionScreenSpace' ].value.copy( screenSpacePosition ); - postprocessing.godraysFakeSunUniforms[ 'vSunPositionScreenSpace' ].value.copy( screenSpacePosition ); - - // -- Draw sky and sun -- - - // Clear colors and depths, will clear to sky color - - renderer.setRenderTarget( postprocessing.rtTextureColors ); - renderer.clear( true, true, false ); - - // Sun render. Runs a shader that gives a brightness based on the screen - // space distance to the sun. Not very efficient, so i make a scissor - // rectangle around the suns position to avoid rendering surrounding pixels. - - const sunsqH = 0.74 * window.innerHeight; // 0.74 depends on extent of sun from shader - const sunsqW = 0.74 * window.innerHeight; // both depend on height because sun is aspect-corrected - - screenSpacePosition.x *= window.innerWidth; - screenSpacePosition.y *= window.innerHeight; - - renderer.setScissor( screenSpacePosition.x - sunsqW / 2, screenSpacePosition.y - sunsqH / 2, sunsqW, sunsqH ); - renderer.setScissorTest( true ); + controls.update(); - postprocessing.godraysFakeSunUniforms[ 'fAspect' ].value = window.innerWidth / window.innerHeight; - - postprocessing.scene.overrideMaterial = postprocessing.materialGodraysFakeSun; - renderer.setRenderTarget( postprocessing.rtTextureColors ); - renderer.render( postprocessing.scene, postprocessing.camera ); - - renderer.setScissorTest( false ); - - // -- Draw scene objects -- - - // Colors - - scene.overrideMaterial = null; - renderer.setRenderTarget( postprocessing.rtTextureColors ); - renderer.render( scene, camera ); - - // Depth - - scene.overrideMaterial = materialDepth; - renderer.setRenderTarget( postprocessing.rtTextureDepth ); - renderer.clear(); - renderer.render( scene, camera ); - - // - - postprocessing.godrayMaskUniforms[ 'tInput' ].value = postprocessing.rtTextureDepth.texture; - - postprocessing.scene.overrideMaterial = postprocessing.materialGodraysDepthMask; - renderer.setRenderTarget( postprocessing.rtTextureDepthMask ); - renderer.render( postprocessing.scene, postprocessing.camera ); - - // -- Render god-rays -- - - // Maximum length of god-rays (in texture space [0,1]X[0,1]) - - const filterLen = 1.0; - - // Samples taken by filter - - const TAPS_PER_PASS = 6.0; - - // Pass order could equivalently be 3,2,1 (instead of 1,2,3), which - // would start with a small filter support and grow to large. however - // the large-to-small order produces less objectionable aliasing artifacts that - // appear as a glimmer along the length of the beams - - // pass 1 - render into first ping-pong target - filterGodRays( postprocessing.rtTextureDepthMask.texture, postprocessing.rtTextureGodRays2, getStepSize( filterLen, TAPS_PER_PASS, 1.0 ) ); - - // pass 2 - render into second ping-pong target - filterGodRays( postprocessing.rtTextureGodRays2.texture, postprocessing.rtTextureGodRays1, getStepSize( filterLen, TAPS_PER_PASS, 2.0 ) ); - - // pass 3 - 1st RT - filterGodRays( postprocessing.rtTextureGodRays1.texture, postprocessing.rtTextureGodRays2, getStepSize( filterLen, TAPS_PER_PASS, 3.0 ) ); - - // final pass - composite god-rays onto colors - - postprocessing.godrayCombineUniforms[ 'tColors' ].value = postprocessing.rtTextureColors.texture; - postprocessing.godrayCombineUniforms[ 'tGodRays' ].value = postprocessing.rtTextureGodRays2.texture; - - postprocessing.scene.overrideMaterial = postprocessing.materialGodraysCombine; - - renderer.setRenderTarget( null ); - renderer.render( postprocessing.scene, postprocessing.camera ); - postprocessing.scene.overrideMaterial = null; - - } else { + stats.begin(); - renderer.setRenderTarget( null ); - renderer.clear(); - renderer.render( scene, camera ); + composer.render(); - } + //renderer.render( scene, camera ); + + stats.end(); }
- three.js - webgl god-rays example - tree by stanloshka + three.js - webgl god-rays example - three-good-godrays extension