Browse Source

SoftwareRenderer3: Updated to raster3_ryg7.

Mr.doob 13 years ago
parent
commit
199c5a552a
2 changed files with 70 additions and 47 deletions
  1. 69 46
      examples/js/renderers/SoftwareRenderer3.js
  2. 1 1
      examples/misc_software.html

+ 69 - 46
examples/js/renderers/SoftwareRenderer3.js

@@ -205,13 +205,19 @@ THREE.SoftwareRenderer3 = function () {
 
 		// 28.4 fixed-point coordinates
 
-		x1 = Math.round( 16 * x1 );
-		x2 = Math.round( 16 * x2 );
-		x3 = Math.round( 16 * x3 );
+		var x1 = Math.round( 16 * x1 );
+		var x2 = Math.round( 16 * x2 );
+		var x3 = Math.round( 16 * x3 );
 
-		y1 = Math.round( 16 * y1 );
-		y2 = Math.round( 16 * y2 );
-		y3 = Math.round( 16 * y3 );
+		var y1 = Math.round( 16 * y1 );
+		var y2 = Math.round( 16 * y2 );
+		var y3 = Math.round( 16 * y3 );
+
+		// Deltas
+
+		var dx12 = x1 - x2, dy12 = y2 - y1;
+		var dx23 = x2 - x3, dy23 = y3 - y2;
+		var dx31 = x3 - x1, dy31 = y1 - y3;
 
 		// Bounding rectangle
 
@@ -225,12 +231,6 @@ THREE.SoftwareRenderer3 = function () {
 		recty1 = Math.min( miny, recty1 );
 		recty2 = Math.max( maxy, recty2 );
 
-		// Deltas
-
-		var dx12 = x1 - x2, dy12 = y2 - y1;
-		var dx23 = x2 - x3, dy23 = y3 - y2;
-		var dx31 = x3 - x1, dy31 = y1 - y3;
-
 		// Block size, standard 8x8 (must be power of two)
 
 		var q = blocksize;
@@ -242,9 +242,9 @@ THREE.SoftwareRenderer3 = function () {
 
 		// Constant part of half-edge functions
 
-		var c1 = -dy12 * x1 - dx12 * y1;
-		var c2 = -dy23 * x2 - dx23 * y2;
-		var c3 = -dy31 * x3 - dx31 * y3;
+		var c1 = dy12 * ((minx << 4) - x1) + dx12 * ((miny << 4) - y1);
+		var c2 = dy23 * ((minx << 4) - x2) + dx23 * ((miny << 4) - y2);
+		var c3 = dy31 * ((minx << 4) - x3) + dx31 * ((miny << 4) - y3);
 
 		// Correct for fill convention
 
@@ -274,30 +274,63 @@ THREE.SoftwareRenderer3 = function () {
 		var linestep = (canvasWidth - q) * 4;
 		var scale = 255.0 / (c1 + c2 + c3);
 
-		for ( var y0 = miny; y0 < maxy; y0 += q ) {
+		var cb1 = c1;
+		var cb2 = c2;
+		var cb3 = c3;
+		var qstep = -q;
+		var e1x = qstep * dy12;
+		var e2x = qstep * dy23;
+		var e3x = qstep * dy31;
+		var x0 = minx;
 
-			for ( var x0 = minx; x0 < maxx; x0 += q ) {
+		for (var y0 = miny; y0 < maxy; y0 += q) {
 
-				// Edge functions at top-left corner
-				var cy1 = c1 + dx12 * y0 + dy12 * x0;
-				var cy2 = c2 + dx23 * y0 + dy23 * x0;
-				var cy3 = c3 + dx31 * y0 + dy31 * x0;
+			// New block line - keep hunting for tri outer edge in old block line dir
+			while (x0 >= minx && x0 < maxx && cb1 >= nmax1 && cb2 >= nmax2 && cb3 >= nmax3) {
 
-				// Skip block when at least one edge completely out
-				if (cy1 < nmax1 || cy2 < nmax2 || cy3 < nmax3) continue;
+				x0 += qstep;
+				cb1 += e1x;
+				cb2 += e2x;
+				cb3 += e3x;
 
-				// Skip writing full block if it's already fully covered
+			}
+
+			// Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
+			qstep = -qstep;
+			e1x = -e1x;
+			e2x = -e2x;
+			e3x = -e3x;
+
+			while (1) {
+
+				// Step everything
+				x0 += qstep;
+				cb1 += e1x;
+				cb2 += e2x;
+				cb3 += e3x;
+
+				// 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;
+				if (cb2 < nmax2) if (e2x < 0) break; else continue;
+				if (cb3 < nmax3) if (e3x < 0) break; else continue;
+
+				// We can skip this block if it's already fully covered
 				var blockX = (x0 / q) | 0;
 				var blockY = (y0 / q) | 0;
 				var blockInd = blockX + blockY * canvasWBlocks;
-
 				if (block_full[blockInd]) continue;
 
 				// Offset at top-left corner
 				var offset = (x0 + y0 * canvasWidth) * 4;
 
 				// Accept whole block when fully covered
-				if (cy1 >= nmin1 && cy2 >= nmin2 && cy3 >= nmin3) {
+				if (cb1 >= nmin1 && cb2 >= nmin2 && cb3 >= nmin3) {
+
+					var cy1 = cb1;
+					var cy2 = cb2;
 
 					for ( var iy = 0; iy < q; iy ++ ) {
 
@@ -306,7 +339,6 @@ THREE.SoftwareRenderer3 = function () {
 
 						for ( var ix = 0; ix < q; ix ++ ) {
 
-							/*
 							if (!data[offset + 3]) {
 
 								var u = cx1 * scale; // 0-255!
@@ -316,14 +348,7 @@ THREE.SoftwareRenderer3 = function () {
 								data[offset + 2] = 0;
 								data[offset + 3] = 255;
 
-								data[offset] = r;
-								data[offset + 1] = g;
-								data[offset + 2] = b;
-								data[offset + 3] = 255;
-
 							}
-							*/
-							drawPixel( x0 + ix, y0 + iy, r, g, b );
 
 							cx1 += dy12;
 							cx2 += dy23;
@@ -341,6 +366,10 @@ THREE.SoftwareRenderer3 = function () {
 
 				} else { // Partially covered block
 
+					var cy1 = cb1;
+					var cy2 = cb2;
+					var cy3 = cb3;
+
 					for ( var iy = 0; iy < q; iy ++ ) {
 
 						var cx1 = cy1;
@@ -349,25 +378,14 @@ THREE.SoftwareRenderer3 = function () {
 
 						for ( var ix = 0; ix < q; ix ++ ) {
 
-							if ( (cx1 | cx2 | cx3) >= 0/* && !data[offset+3]*/) {
+							if ( (cx1 | cx2 | cx3) >= 0 && !data[offset+3]) {
 
-								/*
 								var u = cx1 * scale; // 0-255!
 								var v = cx2 * scale; // 0-255!
 								data[offset] = u;
 								data[offset + 1] = v; 
 								data[offset + 2] = 0;
 								data[offset + 3] = 255;
-								*/
-
-								/*
-								data[offset] = r;
-								data[offset + 1] = g;
-								data[offset + 2] = b;
-								data[offset + 3] = 255;
-								*/
-
-								drawPixel( x0 + ix, y0 + iy, r, g, b );
 
 							}
 
@@ -389,6 +407,11 @@ THREE.SoftwareRenderer3 = function () {
 
 			}
 
+			// Advance to next row of blocks
+			cb1 += q*dx12;
+			cb2 += q*dx23;
+			cb3 += q*dx31;
+
 		}
 
 	}

+ 1 - 1
examples/misc_software.html

@@ -66,7 +66,7 @@
 				plane.position.y = - 150;
 				scene.add( plane );
 
-				renderer = new THREE.SoftwareRenderer2();
+				renderer = new THREE.SoftwareRenderer3();
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 				container.appendChild( renderer.domElement );