Browse Source

Examples: Fix godrays shader.

Mugen87 5 years ago
parent
commit
9627ebb703

+ 15 - 18
examples/js/shaders/GodRaysShader.js

@@ -85,7 +85,7 @@ THREE.GodRaysGenerateShader = {
 			value: 1.0
 		},
 		vSunPositionScreenSpace: {
-			value: new THREE.Vector2( 0.5, 0.5 )
+			value: new THREE.Vector3()
 		}
 
 	},
@@ -111,14 +111,14 @@ THREE.GodRaysGenerateShader = {
 
 		"uniform sampler2D tInput;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
+		"uniform vec3 vSunPositionScreenSpace;",
 		"uniform float fStepSize;", // filter step size
 
 		"void main() {",
 
 		// delta from current pixel to "sun" position
 
-		"	vec2 delta = vSunPositionScreenSpace - vUv;",
+		"	vec2 delta = vSunPositionScreenSpace.xy - vUv;",
 		"	float dist = length( delta );",
 
 		// Step vector (uv space)
@@ -157,22 +157,24 @@ THREE.GodRaysGenerateShader = {
 
 		// Unrolling loop manually makes it work in ANGLE
 
-		"	if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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
@@ -210,10 +212,6 @@ THREE.GodRaysCombineShader = {
 
 		fGodRayIntensity: {
 			value: 0.69
-		},
-
-		vSunPositionScreenSpace: {
-			value: new THREE.Vector2( 0.5, 0.5 )
 		}
 
 	},
@@ -238,7 +236,6 @@ THREE.GodRaysCombineShader = {
 		"uniform sampler2D tColors;",
 		"uniform sampler2D tGodRays;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
 		"uniform float fGodRayIntensity;",
 
 		"void main() {",
@@ -267,7 +264,7 @@ THREE.GodRaysFakeSunShader = {
 	uniforms: {
 
 		vSunPositionScreenSpace: {
-			value: new THREE.Vector2( 0.5, 0.5 )
+			value: new THREE.Vector3()
 		},
 
 		fAspect: {
@@ -301,7 +298,7 @@ THREE.GodRaysFakeSunShader = {
 
 		"varying vec2 vUv;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
+		"uniform vec3 vSunPositionScreenSpace;",
 		"uniform float fAspect;",
 
 		"uniform vec3 sunColor;",
@@ -309,7 +306,7 @@ THREE.GodRaysFakeSunShader = {
 
 		"void main() {",
 
-		"	vec2 diff = vUv - vSunPositionScreenSpace;",
+		"	vec2 diff = vUv - vSunPositionScreenSpace.xy;",
 
 		// Correct for aspect ratio
 
@@ -318,7 +315,7 @@ THREE.GodRaysFakeSunShader = {
 		"	float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 );",
 		"	prop = 0.35 * pow( 1.0 - prop, 3.0 );",
 
-		"	gl_FragColor.xyz = mix( sunColor, bgColor, 1.0 - prop );",
+		"	gl_FragColor.xyz = ( vSunPositionScreenSpace.z > 0.0 ) ? mix( sunColor, bgColor, 1.0 - prop ) : bgColor;",
 		"	gl_FragColor.w = 1.0;",
 
 		"}"

+ 0 - 1
examples/jsm/shaders/GodRaysShader.d.ts

@@ -25,7 +25,6 @@ export const GodRaysCombineShader: {
 		tColors: Uniform;
 		tGodRays: Uniform;
 		fGodRayIntensity: Uniform;
-		vSunPositionScreenSpace: Uniform;
 	};
 	vertexShader: string;
 	fragmentShader: string;

+ 16 - 19
examples/jsm/shaders/GodRaysShader.js

@@ -20,7 +20,7 @@
 
 import {
 	Color,
-	Vector2
+	Vector3
 } from "../../../build/three.module.js";
 
 var GodRaysDepthMaskShader = {
@@ -90,7 +90,7 @@ var GodRaysGenerateShader = {
 			value: 1.0
 		},
 		vSunPositionScreenSpace: {
-			value: new Vector2( 0.5, 0.5 )
+			value: new Vector3()
 		}
 
 	},
@@ -116,14 +116,14 @@ var GodRaysGenerateShader = {
 
 		"uniform sampler2D tInput;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
+		"uniform vec3 vSunPositionScreenSpace;",
 		"uniform float fStepSize;", // filter step size
 
 		"void main() {",
 
 		// delta from current pixel to "sun" position
 
-		"	vec2 delta = vSunPositionScreenSpace - vUv;",
+		"	vec2 delta = vSunPositionScreenSpace.xy - vUv;",
 		"	float dist = length( delta );",
 
 		// Step vector (uv space)
@@ -162,22 +162,24 @@ var GodRaysGenerateShader = {
 
 		// Unrolling loop manually makes it work in ANGLE
 
-		"	if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+		"	float f = min( 1.0, max( vSunPositionScreenSpace.z / 1000.0, 0.0 ) );", // used to fade outgodrays
+
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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;",
+		"	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
@@ -215,10 +217,6 @@ var GodRaysCombineShader = {
 
 		fGodRayIntensity: {
 			value: 0.69
-		},
-
-		vSunPositionScreenSpace: {
-			value: new Vector2( 0.5, 0.5 )
 		}
 
 	},
@@ -243,7 +241,6 @@ var GodRaysCombineShader = {
 		"uniform sampler2D tColors;",
 		"uniform sampler2D tGodRays;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
 		"uniform float fGodRayIntensity;",
 
 		"void main() {",
@@ -272,7 +269,7 @@ var GodRaysFakeSunShader = {
 	uniforms: {
 
 		vSunPositionScreenSpace: {
-			value: new Vector2( 0.5, 0.5 )
+			value: new Vector3()
 		},
 
 		fAspect: {
@@ -306,7 +303,7 @@ var GodRaysFakeSunShader = {
 
 		"varying vec2 vUv;",
 
-		"uniform vec2 vSunPositionScreenSpace;",
+		"uniform vec3 vSunPositionScreenSpace;",
 		"uniform float fAspect;",
 
 		"uniform vec3 sunColor;",
@@ -314,7 +311,7 @@ var GodRaysFakeSunShader = {
 
 		"void main() {",
 
-		"	vec2 diff = vUv - vSunPositionScreenSpace;",
+		"	vec2 diff = vUv - vSunPositionScreenSpace.xy;",
 
 		// Correct for aspect ratio
 
@@ -323,7 +320,7 @@ var GodRaysFakeSunShader = {
 		"	float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 );",
 		"	prop = 0.35 * pow( 1.0 - prop, 3.0 );",
 
-		"	gl_FragColor.xyz = mix( sunColor, bgColor, 1.0 - prop );",
+		"	gl_FragColor.xyz = ( vSunPositionScreenSpace.z > 0.0 ) ? mix( sunColor, bgColor, 1.0 - prop ) : bgColor;",
 		"	gl_FragColor.w = 1.0;",
 
 		"}"

+ 20 - 54
examples/webgl_postprocessing_godrays.html

@@ -19,6 +19,7 @@
 			import Stats from './jsm/libs/stats.module.js';
 
 			import { OBJLoader } from './jsm/loaders/OBJLoader.js';
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
 			import { GodRaysFakeSunShader, GodRaysDepthMaskShader, GodRaysCombineShader, GodRaysGenerateShader } from './jsm/shaders/GodRaysShader.js';
 
 			var container, stats;
@@ -27,10 +28,9 @@
 			var sphereMesh;
 
 			var sunPosition = new THREE.Vector3( 0, 1000, - 1000 );
+			var clipPosition = new THREE.Vector4();
 			var screenSpacePosition = new THREE.Vector3();
 
-			var mouseX = 0, mouseY = 0;
-
 			var postprocessing = { enabled: true };
 
 			var orbitRadius = 200;
@@ -91,6 +91,10 @@
 
 				renderer.autoClear = false;
 
+				var controls = new OrbitControls( camera, renderer.domElement );
+				controls.minDistance = 50;
+				controls.maxDistance = 500;
+
 				//
 
 				stats = new Stats();
@@ -98,9 +102,6 @@
 
 				//
 
-				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
-				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
-				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 				//
@@ -111,41 +112,6 @@
 
 			//
 
-			function onDocumentMouseMove( event ) {
-
-				mouseX = event.clientX - window.innerWidth / 2;
-				mouseY = event.clientY - window.innerHeight / 2;
-
-			}
-
-			function onDocumentTouchStart( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - window.innerWidth / 2;
-					mouseY = event.touches[ 0 ].pageY - window.innerHeight / 2;
-
-				}
-
-			}
-
-			function onDocumentTouchMove( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - window.innerWidth / 2;
-					mouseY = event.touches[ 0 ].pageY - window.innerHeight / 2;
-
-				}
-
-			}
-
-			//
-
 			function onWindowResize() {
 
 				var renderTargetWidth = window.innerWidth;
@@ -287,28 +253,28 @@
 				sphereMesh.position.x = orbitRadius * Math.cos( time );
 				sphereMesh.position.z = orbitRadius * Math.sin( time ) - 100;
 
+				if ( postprocessing.enabled ) {
 
-				camera.position.x += ( mouseX - camera.position.x ) * 0.036;
-				camera.position.y += ( - ( mouseY ) - camera.position.y ) * 0.036;
-
-				camera.lookAt( scene.position );
+					clipPosition.x = sunPosition.x;
+					clipPosition.y = sunPosition.y;
+					clipPosition.z = sunPosition.z;
+					clipPosition.w = 1;
 
-				if ( postprocessing.enabled ) {
+					clipPosition.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
 
-					// Find the screenspace position of the sun
+					// perspective divide (produce NDC space)
 
-					screenSpacePosition.copy( sunPosition ).project( camera );
+					clipPosition.x /= clipPosition.w;
+					clipPosition.y /= clipPosition.w;
 
-					screenSpacePosition.x = ( screenSpacePosition.x + 1 ) / 2;
-					screenSpacePosition.y = ( screenSpacePosition.y + 1 ) / 2;
+					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 visibilty checks
 
 					// Give it to the god-ray and sun shaders
 
-					postprocessing.godrayGenUniforms[ "vSunPositionScreenSpace" ].value.x = screenSpacePosition.x;
-					postprocessing.godrayGenUniforms[ "vSunPositionScreenSpace" ].value.y = screenSpacePosition.y;
-
-					postprocessing.godraysFakeSunUniforms[ "vSunPositionScreenSpace" ].value.x = screenSpacePosition.x;
-					postprocessing.godraysFakeSunUniforms[ "vSunPositionScreenSpace" ].value.y = screenSpacePosition.y;
+					postprocessing.godrayGenUniforms[ "vSunPositionScreenSpace" ].value.copy( screenSpacePosition );
+					postprocessing.godraysFakeSunUniforms[ "vSunPositionScreenSpace" ].value.copy( screenSpacePosition );
 
 					// -- Draw sky and sun --