Browse Source

Added basic raytracing renderer.

Mr.doob 11 years ago
parent
commit
16ee65ef48
2 changed files with 284 additions and 0 deletions
  1. 161 0
      examples/js/renderers/RaytracingRenderer.js
  2. 123 0
      examples/raytracer_sandbox.html

+ 161 - 0
examples/js/renderers/RaytracingRenderer.js

@@ -0,0 +1,161 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.RaytracingRenderer = function ( parameters ) {
+
+	console.log( 'THREE.RaytracingRenderer', THREE.REVISION );
+
+	parameters = parameters || {};
+
+	var canvas = document.createElement( 'canvas' );
+	var context = canvas.getContext( '2d', {
+		alpha: parameters.alpha === true
+	} );
+
+	var canvasWidth, canvasHeight;
+	var canvasWidthHalf, canvasHeightHalf;
+
+	var clearColor = new THREE.Color( 0x000000 );
+
+	var blockX = 0;
+	var blockY = 0;
+	var blockSize = 64;
+
+	var canvasBlock = document.createElement( 'canvas' );
+	canvasBlock.width = blockSize;
+	canvasBlock.height = blockSize;
+
+	var contextBlock = canvasBlock.getContext( '2d', {
+		alpha: parameters.alpha === true
+	} );
+
+	var imagedata = contextBlock.getImageData( 0, 0, blockSize, blockSize );
+	var data = imagedata.data;
+
+	var viewMatrix = new THREE.Matrix4();
+	var viewProjectionMatrix = new THREE.Matrix4();
+
+	var origin = new THREE.Vector3();
+	var direction = new THREE.Vector3();
+
+	var raycaster = new THREE.Raycaster( origin, direction );
+
+	var objects;
+
+	this.domElement = canvas;
+
+	this.autoClear = true;
+
+	this.setClearColor = function ( color, alpha ) {
+
+		clearColor.set( color );
+
+	};
+
+	this.setSize = function ( width, height ) {
+
+		canvas.width = width;
+		canvas.height = height;
+
+		canvasWidth = canvas.width;
+		canvasHeight = canvas.height;
+
+		canvasWidthHalf = Math.floor( canvasWidth / 2 );
+		canvasHeightHalf = Math.floor( canvasHeight / 2 );
+
+		context.fillStyle = 'white';
+
+	};
+
+	this.setSize( canvas.width, canvas.height );
+
+	this.clear = function () {
+
+	};
+
+	var renderBlock = function () {
+
+		for ( var i = 0, l = data.length; i < l; i += 4 ) {
+
+			data[ i ] = 0;
+			data[ i + 1 ] = 0;
+			data[ i + 2 ] = 0;
+
+		}
+
+		var index = 0;
+
+		for ( var y = 0; y < blockSize; y ++ ) {
+
+			for ( var x = 0; x < blockSize; x ++ ) {
+
+				direction.set( x + blockX - canvasWidthHalf, y + blockY - canvasHeightHalf, - 500 );
+				direction.normalize();
+
+				var intersections = raycaster.intersectObjects( objects, true );
+
+				if ( intersections.length > 0 ) {
+
+					var intersection = intersections[ 0 ];
+
+					var object = intersection.object;
+					var material = object.material;
+					var face = intersection.face;
+
+					var color;
+
+					if ( material.vertexColors === THREE.NoColors ) {
+
+						color = material.color;
+
+					} else if ( material.vertexColors === THREE.FaceColors ) {
+
+						color = face.color;
+
+					}
+
+					data[ index ] = color.r * 255;
+					data[ index + 1 ] = color.g * 255;
+					data[ index + 2 ] = color.b * 255;
+
+				}
+
+				index += 4;
+
+			}
+
+		}
+
+		context.putImageData( imagedata, blockX, blockY );
+
+		blockX += blockSize;
+
+		if ( blockX >= canvasWidth ) {
+
+			blockX = 0;
+			blockY += blockSize;
+
+			if ( blockY >= canvasHeight ) return;
+
+		}
+
+		context.fillRect( blockX, blockY, blockSize, blockSize );
+
+		requestAnimationFrame( renderBlock );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		if ( this.autoClear === true ) this.clear();
+
+		origin.copy( camera.position );
+
+		objects = scene.children;
+
+		renderBlock();
+
+	}
+
+};

+ 123 - 0
examples/raytracer_sandbox.html

@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js - raytracing renderer</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				color: #ffffff;
+				margin: 0px;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/renderers/RaytracingRenderer.js"></script>
+
+		<script>
+
+			var container;
+
+			var camera, controls, scene, renderer;
+
+			var torus, cube;
+
+			var start = Date.now();
+
+			init();
+			render();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				var info = document.createElement( 'div' );
+				info.style.position = 'absolute';
+				info.style.top = '10px';
+				info.style.width = '100%';
+				info.style.textAlign = 'center';
+				info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js<a/> - raytracing renderer';
+				container.appendChild( info );
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.z = 600;
+
+				controls = new THREE.TrackballControls( camera );
+
+				scene = new THREE.Scene();
+
+				var geometry = new THREE.TorusKnotGeometry( 150 );
+
+				for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
+
+					geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
+
+				}
+
+				torus = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x0000ff, vertexColors: THREE.FaceColors } ) );
+				scene.add( torus );
+
+				// Plane
+
+				var geometry = new THREE.BoxGeometry( 200, 200, 200 );
+
+				for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
+
+					geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
+
+				}
+
+				cube = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0x00ff00, vertexColors: THREE.FaceColors } ) );
+				scene.add( cube );
+
+				renderer = new THREE.RaytracingRenderer();
+				renderer.setClearColor( 0xf0f0f0 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container.appendChild( renderer.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function render() {
+
+				var timer = Date.now() - start;
+
+				torus.position.y = Math.sin( timer * 0.002 ) * 150;
+				torus.rotation.x = timer * 0.0003;
+				torus.rotation.z = timer * 0.0002;
+
+				cube.rotation.x = timer * 0.0002;
+				cube.rotation.z = timer * 0.0003;
+
+				controls.update();
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>