Преглед на файлове

Software renderer for Line

Mu Daosheng преди 11 години
родител
ревизия
dd7660696a
променени са 2 файла, в които са добавени 478 реда и са изтрити 1 реда
  1. 248 1
      examples/js/renderers/SoftwareRenderer.js
  2. 230 0
      examples/software_lines_colors.html

+ 248 - 1
examples/js/renderers/SoftwareRenderer.js

@@ -245,7 +245,19 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 				}				
 
-			}
+			} else if ( element instanceof THREE.RenderableLine ) {
+               
+               var shader = getMaterialShader( material );
+               
+               drawLine(
+						element.v1.positionScreen,
+						element.v2.positionScreen,
+                        element.vertexColors[0],
+                        element.vertexColors[1],
+                        shader,
+                        material
+					);
+            }
 
 		}
 
@@ -1033,6 +1045,241 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		}
 
 	}
+    
+    function drawLine( v1, v2, color1, color2, shader, material ) {
+        
+        // TODO: Implement per-pixel z-clipping
+
+		if ( v1.z < -1 || v1.z > 1 || v2.z < -1 || v2.z > 1 ) return;
+
+		// https://gist.github.com/2486101
+		// explanation: http://pouet.net/topic.php?which=8760&page=1
+
+		// 28.4 fixed-point coordinates
+
+		var x1 = (v1.x * viewportXScale + viewportXOffs) | 0;
+		var x2 = (v2.x * viewportXScale + viewportXOffs) | 0;
+
+		var y1 = (v1.y * viewportYScale + viewportYOffs) | 0;
+		var y2 = (v2.y * viewportYScale + viewportYOffs) | 0;
+
+		// Z values (.28 fixed-point)
+
+		var z1 = (v1.z * viewportZScale + viewportZOffs) | 0;
+		var z2 = (v2.z * viewportZScale + viewportZOffs) | 0;
+		
+		// Deltas
+
+		var dx12 = x1 - x2, dy12 = y2 - y1;
+
+		// Bounding rectangle
+
+		var minx = Math.max( ( Math.min( x1, x2 ) + subpixelBias ) >> subpixelBits, 0 );
+		var maxx = Math.min( ( Math.max( x1, x2 ) + subpixelBias ) >> subpixelBits, canvasWidth );
+		var miny = Math.max( ( Math.min( y1, y2 ) + subpixelBias ) >> subpixelBits, 0 );
+		var maxy = Math.min( ( Math.max( y1, y2 ) + subpixelBias ) >> subpixelBits, canvasHeight );
+
+		rectx1 = Math.min( minx, rectx1 );
+		rectx2 = Math.max( maxx, rectx2 );
+		recty1 = Math.min( miny, recty1 );
+		recty2 = Math.max( maxy, recty2 );
+
+		// Block size, standard 8x8 (must be power of two)
+
+		var q = blockSize;
+
+		// Start in corner of 8x8 block
+
+		minx &= ~(q - 1);
+		miny &= ~(q - 1);
+
+		// Constant part of half-edge functions
+
+		var minXfixscale = (minx << subpixelBits);
+		var minYfixscale = (miny << subpixelBits);
+
+		var c1 = dy12 * ((minXfixscale) - x1) + dx12 * ((minYfixscale) - y1);
+
+		// Correct for fill convention
+
+		if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
+
+		// Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
+		// It's a bit subtle. :)
+		c1 = (c1 - 1) >> subpixelBits;
+
+		// Z interpolation setup
+
+		var dz12 = z1 - z2;
+		var invDet = 1.0 / dx12;
+		var dzdx = invDet * dz12; // dz per one subpixel step in x
+		var dzdy = invDet * dz12; // dz per one subpixel step in y
+
+		// Z at top/left corner of rast area
+
+		var cz = ( z1 + ((minXfixscale) - x1) * dzdx + ((minYfixscale) - y1) * dzdy ) | 0;
+
+		// Z pixel steps
+
+		var fixscale = (1 << subpixelBits);
+		dzdx = (dzdx * fixscale) | 0;
+		dzdy = (dzdy * fixscale) | 0;
+		
+		// Set up min/max corners
+		var qm1 = q - 1; // for convenience
+		var nmin1 = 0, nmax1 = 0;
+		var nmin2 = 0, nmax2 = 0;
+		var nmin3 = 0, nmax3 = 0;
+		var nminz = 0, nmaxz = 0;
+		if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12;
+		if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12;
+		if (dzdx >= 0) nmaxz += qm1*dzdx; else nminz += qm1*dzdx;
+		if (dzdy >= 0) nmaxz += qm1*dzdy; else nminz += qm1*dzdy;
+
+		// Loop through blocks
+		var linestep = canvasWidth - q;
+		var scale = 1.0 / c1;
+
+		var cb1 = c1;
+		var cbz = cz;
+		var qstep = -q;
+		var e1x = qstep * dy12;
+		var ezx = qstep * dzdx;
+			
+		var x0 = minx;
+
+		for ( var y0 = miny; y0 < maxy; y0 += q ) {
+
+			// New block line - keep hunting for tri outer edge in old block line dir
+			while ( x0 >= minx && x0 < maxx && cb1 >= nmax1 ) {
+
+				x0 += qstep;
+				cb1 += e1x;
+				cbz += ezx;	
+			}
+
+			// Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
+			qstep = -qstep;
+			e1x = -e1x;
+			ezx = -ezx;
+			
+			while ( 1 ) {
+
+				// Step everything
+				x0 += qstep;
+				cb1 += e1x;
+				cbz += ezx;
+				
+				// We're done with this block line when at least one edge completely out
+				// If an edge function is too small and decreasing in the current traversal
+				// dir, we're done with this line.
+				if (x0 < minx || x0 >= maxx) break;
+				if (cb1 < nmax1) if (e1x < 0) break; else continue;
+				
+				// We can skip this block if it's already fully covered
+				var blockX = x0 >> blockShift;
+				var blockY = y0 >> blockShift;
+				var blockId = blockX + blockY * canvasWBlocks;
+				var minz = cbz + nminz;
+
+				// farthest point in block closer than closest point in our tri?
+				if ( blockMaxZ[ blockId ] < minz ) continue;
+
+				// Need to do a deferred clear?
+				var bflags = blockFlags[ blockId ];
+				if ( bflags & BLOCK_NEEDCLEAR) clearBlock( blockX, blockY );
+				blockFlags[ blockId ] = bflags & ~( BLOCK_ISCLEAR | BLOCK_NEEDCLEAR );
+
+				// Offset at top-left corner
+				var offset = x0 + y0 * canvasWidth;
+				
+				// Accept whole block when fully covered
+				if ( cb1 >= nmin1 ) {
+
+					var maxz = cbz + nmaxz;
+					blockMaxZ[ blockId ] = Math.min( blockMaxZ[ blockId ], maxz );
+
+					var cy1 = cb1;
+					var cyz = cbz;
+
+					for ( var iy = 0; iy < q; iy ++ ) {
+
+						var cx1 = cy1;
+						var cx2 = cy2;
+						var cxz = cyz;										 
+
+						for ( var ix = 0; ix < q; ix ++ ) {
+
+							var z = cxz;
+							 
+							if ( z < zbuffer[ offset ] ) {		 
+								shader( data, zbuffer, offset, z, 1, 1, null, null, material );								
+							}
+
+							cx1 += dy12;
+							cxz += dzdx;
+							
+							offset++;
+
+						}
+
+						cy1 += dx12;
+						cyz += dzdy;										
+						
+						offset += linestep;
+
+					}
+
+				} else { // Partially covered block
+
+					var cy1 = cb1;
+					var cyz = cbz;
+					
+					for ( var iy = 0; iy < q; iy ++ ) {
+
+						var cx1 = cy1;
+						var cxz = cyz;
+						
+						for ( var ix = 0; ix < q; ix ++ ) {
+
+							if ( ( cx1 | cx2 ) >= 0 ) {
+
+								var z = cxz;								
+
+								if ( z < zbuffer[ offset ] ) {						 
+									shader( data, zbuffer, offset, z, 1, 1, null, null, material );
+								}
+
+							}
+
+							cx1 += dy12;
+							cxz += dzdx;
+														
+							offset++;
+
+						}
+
+						cy1 += dx12;
+						cyz += dzdy;
+						
+						offset += linestep;
+
+					}
+
+				}
+
+			}
+
+			// Advance to next row of blocks
+			cb1 += q*dx12;
+			cbz += q*dzdy;
+			
+		}
+        
+        // interpolation pixel postion from vertices
+        
+        // interpolation pixel color from vertices
+    }
 
 	function clearBlock( blockX, blockY ) {
 

+ 230 - 0
examples/software_lines_colors.html

@@ -0,0 +1,230 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js software - lines - cubes - colors</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 {
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			a {
+				color:#0078ff;
+			}
+
+			#info {
+				position: absolute;
+				top: 10px; width: 100%;
+				color: #ffffff;
+				padding: 5px;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+				z-index:100;
+			}
+
+			a {
+				color: orange;
+				text-decoration: none;
+			}
+
+			a:hover {
+				color: #0080ff;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - color lines Software demo
+			[<a href="http://en.wikipedia.org/wiki/Hilbert_curve">Hilbert curve</a> thanks to <a href="http://www.openprocessing.org/visuals/?visualID=15599">Thomas Diewald</a>]
+		</div>
+
+		<script src="../build/three.js"></script>
+
+		<script src="js/geometries/hilbert3D.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+        <script src="js/renderers/SoftwareRenderer.js"></script>
+
+		<script>
+
+			var mouseX = 0, mouseY = 0,
+
+			windowHalfX = window.innerWidth / 2,
+			windowHalfY = window.innerHeight / 2,
+
+			camera, scene, renderer, material;
+
+			init();
+			animate();
+
+			function init() {
+
+				var i, container;
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 33, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.z = 700;
+
+				scene = new THREE.Scene();
+
+				renderer = new THREE.SoftwareRenderer( { antialias: false } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.autoClear = false;
+
+				container.appendChild( renderer.domElement );
+
+				var geometry = new THREE.Geometry(),
+					geometry2 = new THREE.Geometry(),
+					geometry3 = new THREE.Geometry(),
+					points = hilbert3D( new THREE.Vector3( 0,0,0 ), 200.0, 2, 0, 1, 2, 3, 4, 5, 6, 7 ),
+					colors = [], colors2 = [], colors3 = [];
+
+				for ( i = 0; i < points.length; i ++ ) {
+
+					geometry.vertices.push( points[ i ] );
+
+					colors[ i ] = new THREE.Color( 0xffffff );
+					colors[ i ].setHSL( 0.6, 1.0, Math.max( 0, ( 200 - points[ i ].x ) / 400 ) * 0.5 + 0.5 );
+
+					colors2[ i ] = new THREE.Color( 0xffffff );
+					colors2[ i ].setHSL( 0.3, 1.0, Math.max( 0, ( 200 + points[ i ].x ) / 400 ) * 0.5 );
+
+					colors3[ i ] = new THREE.Color( 0xffffff );
+					colors3[ i ].setHSL( i / points.length, 1.0, 0.5 );
+
+				}
+
+				geometry2.vertices = geometry3.vertices = geometry.vertices;
+
+				geometry.colors = colors;
+				geometry2.colors = colors2;
+				geometry3.colors = colors3;
+
+				// lines
+
+				material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 1, linewidth: 3, vertexColors: THREE.VertexColors } );
+
+				var line, p, scale = 0.3, d = 225;
+				var parameters =  [
+					[ material, scale*1.5, [-d,0,0],  geometry ],
+					[ material, scale*1.5, [0,0,0],  geometry2 ],
+					[ material, scale*1.5, [d,0,0],  geometry3 ]
+				];
+
+				for ( i = 0; i < parameters.length; ++i ) {
+
+					p = parameters[ i ];
+					line = new THREE.Line( p[ 3 ],  p[ 0 ] );
+					line.scale.x = line.scale.y = line.scale.z =  p[ 1 ];
+					line.position.x = p[ 2 ][ 0 ];
+					line.position.y = p[ 2 ][ 1 ];
+					line.position.z = p[ 2 ][ 2 ];
+					scene.add( line );
+
+				}
+
+				//
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				//container.appendChild( stats.domElement );
+
+				//
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+			}
+
+			//
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX - windowHalfX;
+				mouseY = event.clientY - windowHalfY;
+
+			}
+
+			function onDocumentTouchStart( event ) {
+
+				if ( event.touches.length > 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+
+				}
+
+			}
+
+			function onDocumentTouchMove( event ) {
+
+				if ( event.touches.length == 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+				}
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+				stats.update();
+
+			}
+
+			function render() {
+
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05;
+
+				camera.lookAt( scene.position );
+
+				var time = Date.now() * 0.0005;
+
+				for ( var i = 0; i < scene.children.length; i ++ ) {
+
+					var object = scene.children[ i ];
+					if ( object instanceof THREE.Line ) object.rotation.y = time * ( i % 2 ? 1 : -1 );
+
+				}
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>