Browse Source

Get ray by decomposing the camera matrix

gam0022 7 years ago
parent
commit
29b1e20fa3
1 changed files with 40 additions and 33 deletions
  1. 40 33
      examples/webgl_raymarching_reflect.html

+ 40 - 33
examples/webgl_raymarching_reflect.html

@@ -46,8 +46,12 @@
 			precision highp float;
 
 			uniform vec2 resolution;
-			uniform vec3 cameraPos;
-			uniform vec3 cameraDir;
+
+			uniform mat4 viewMatrix;
+			uniform vec3 cameraPosition;
+
+			uniform mat4 cameraWorldMatrix;
+			uniform mat4 cameraProjectionMatrixInverse;
 
 			const float EPS = 0.01;
 			const float OFFSET = EPS * 100.0;
@@ -198,33 +202,32 @@
 			void main(void) {
 
 				// fragment position
-				vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / min( resolution.x, resolution.y );
+				vec2 screenPos = ( gl_FragCoord.xy * 2.0 - resolution ) / min( resolution.x, resolution.y );
+
+				// convert ray direction from screen coordinate to world coordinate
+				vec3 ray = (cameraWorldMatrix * cameraProjectionMatrixInverse * vec4( screenPos.xy, 1.0, 1.0 )).xyz;
+				ray = normalize( ray );
 
-				// camera and ray
-				vec3 cPos  = cameraPos;
-				vec3 cDir  = cameraDir;
-				vec3 cSide = normalize( cross( cDir, vec3( 0.0, 1.0 ,0.0 ) ) );
-				vec3 cUp   = normalize( cross( cSide, cDir ) );
-				float targetDepth = 1.3;
-				vec3 ray = normalize( cSide * p.x + cUp * p.y + cDir * targetDepth );
+				// camera position
+				vec3 cPos = cameraPosition;
 
 				vec3 color = vec3( 0.0 );
-				vec3 q, normal;
+				vec3 p, normal;
 				bool hit;
 				float alpha = 1.0;
 
 				for ( int i = 0; i < 3; i++ ) {
 
-					color += alpha * getRayColor( cPos, ray, q, normal, hit );
+					color += alpha * getRayColor( cPos, ray, p, normal, hit );
 					alpha *= 0.3;
 					ray = normalize( reflect( ray, normal ) );
-					cPos = q + normal * OFFSET;
+					cPos = p + normal * OFFSET;
 
 					if ( !hit ) break;
 
 				}
 
-				gl_FragColor = vec4(color, 1.0);
+				gl_FragColor = vec4( color, 1.0 );
 
 			}
 
@@ -250,7 +253,7 @@
 
 		<script>
 
-			var camera, dummyCamera, scene, controls, renderer;
+			var camera, scene, controls, renderer;
 			var geometry, material, mesh;
 			var mouse = new THREE.Vector2( 0.5, 0.5 );
 			var canvas;
@@ -261,7 +264,7 @@
 			var config = {
 				saveImage: function() {
 
-					renderer.render( scene, dummyCamera );
+					renderer.render( scene, camera );
 					window.open( canvas.toDataURL() );
 
 				},
@@ -274,40 +277,42 @@
 
 			function init() {
 
+				renderer = new THREE.WebGLRenderer();
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( 512, 512 );
+
+				canvas = renderer.domElement;
+				canvas.addEventListener( 'mousemove', onMouseMove );
+				window.addEventListener( 'resize', onWindowResize );
+				document.body.appendChild( canvas );
+
+				// Scene
 				scene = new THREE.Scene();
-				camera = new THREE.Camera();
-				dummyCamera = new THREE.Camera();
+				camera = new THREE.PerspectiveCamera( 60, canvas.width / canvas.height, 1, 2000 );
 				camera.lookAt( new THREE.Vector3( 0.0, -0.3, 1.0 ) );
 
 				geometry = new THREE.PlaneBufferGeometry( 2.0, 2.0 );
 				material = new THREE.RawShaderMaterial( {
 					uniforms: {
 						resolution: { value: new THREE.Vector2( 512, 512 ) },
-						cameraPos:  { value: camera.getWorldPosition() },
-						cameraDir:  { value: camera.getWorldDirection() }
+						cameraWorldMatrix: { value: camera.matrixWorld },
+						cameraProjectionMatrixInverse: { value: new THREE.Matrix4().getInverse( camera.projectionMatrix ) }
 					},
 					vertexShader: document.getElementById( 'vertex_shader' ).textContent,
 					fragmentShader: document.getElementById( 'fragment_shader' ).textContent
 				} );
 				mesh = new THREE.Mesh( geometry, material );
+				mesh.frustumCulled = false;
 				scene.add( mesh );
 
-				renderer = new THREE.WebGLRenderer();
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( 512, 512 );
-
-				canvas = renderer.domElement;
-				canvas.addEventListener( 'mousemove', onMouseMove );
-				window.addEventListener( 'resize', onWindowResize );
-				document.body.appendChild( canvas );
-
+				// Controls
 				controls = new THREE.FlyControls( camera, canvas );
-
 				controls.autoForward = true;
 				controls.dragToLook = false;
 				controls.rollSpeed = Math.PI / 12;
 				controls.movementSpeed = 0.5;
 
+				// GUI
 				var gui = new dat.GUI();
 				gui.add( config, 'saveImage' ).name( 'Save Image' );
 				gui.add( config, 'freeCamera' ).name( 'Free Camera' );
@@ -348,9 +353,11 @@
 				if ( camera.position.y < 0 ) camera.position.y = 0;
 
 				material.uniforms.resolution.value = new THREE.Vector2( canvas.width, canvas.height );
-				material.uniforms.cameraPos.value = camera.getWorldPosition();
-				material.uniforms.cameraDir.value = camera.getWorldDirection();
-				renderer.render( scene, dummyCamera );
+
+				material.uniforms.cameraWorldMatrix.value = camera.matrixWorld;
+				material.uniforms.cameraProjectionMatrixInverse.value = new THREE.Matrix4().getInverse( camera.projectionMatrix );
+
+				renderer.render( scene, camera );
 
 				stats.end();
 				requestAnimationFrame( render );