Browse Source

WebGLRenderer: Moved renderList logic to WebGLRenderList. Implemented mult-RenderList. See #9545.

Mr.doob 8 years ago
parent
commit
83e9745bf9
2 changed files with 190 additions and 113 deletions
  1. 16 113
      src/renderers/WebGLRenderer.js
  2. 174 0
      src/renderers/webgl/WebGLRenderLists.js

+ 16 - 113
src/renderers/WebGLRenderer.js

@@ -17,6 +17,7 @@ import { MeshBasicMaterial } from '../materials/MeshBasicMaterial';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
 import { WebGLAttributes } from './webgl/WebGLAttributes';
 import { WebGLAttributes } from './webgl/WebGLAttributes';
+import { WebGLRenderLists } from './webgl/WebGLRenderLists';
 import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer';
 import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer';
 import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer';
 import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer';
 import { WebGLGeometries } from './webgl/WebGLGeometries';
 import { WebGLGeometries } from './webgl/WebGLGeometries';
@@ -62,10 +63,7 @@ function WebGLRenderer( parameters ) {
 
 
 	var lights = [];
 	var lights = [];
 
 
-	var opaqueObjects = [];
-	var opaqueObjectsLastIndex = - 1;
-	var transparentObjects = [];
-	var transparentObjectsLastIndex = - 1;
+	var currentRenderList = null;
 
 
 	var morphInfluences = new Float32Array( 8 );
 	var morphInfluences = new Float32Array( 8 );
 
 
@@ -296,6 +294,7 @@ function WebGLRenderer( parameters ) {
 	var objects = new WebGLObjects( _gl, geometries, _infoRender );
 	var objects = new WebGLObjects( _gl, geometries, _infoRender );
 	var programCache = new WebGLPrograms( this, capabilities );
 	var programCache = new WebGLPrograms( this, capabilities );
 	var lightCache = new WebGLLights();
 	var lightCache = new WebGLLights();
+	var renderLists = new WebGLRenderLists();
 
 
 	this.info.programs = programCache.programs;
 	this.info.programs = programCache.programs;
 
 
@@ -527,13 +526,10 @@ function WebGLRenderer( parameters ) {
 
 
 	this.dispose = function () {
 	this.dispose = function () {
 
 
-		transparentObjects = [];
-		transparentObjectsLastIndex = - 1;
-		opaqueObjects = [];
-		opaqueObjectsLastIndex = - 1;
-
 		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
 		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
 
 
+		renderLists.dispose();
+
 	};
 	};
 
 
 	// Events
 	// Events
@@ -1041,50 +1037,6 @@ function WebGLRenderer( parameters ) {
 
 
 	}
 	}
 
 
-	function painterSortStable( a, b ) {
-
-		if ( a.object.renderOrder !== b.object.renderOrder ) {
-
-			return a.object.renderOrder - b.object.renderOrder;
-
-		} else if ( a.material.program && b.material.program && a.material.program !== b.material.program ) {
-
-			return a.material.program.id - b.material.program.id;
-
-		} else if ( a.material.id !== b.material.id ) {
-
-			return a.material.id - b.material.id;
-
-		} else if ( a.z !== b.z ) {
-
-			return a.z - b.z;
-
-		} else {
-
-			return a.id - b.id;
-
-		}
-
-	}
-
-	function reversePainterSortStable( a, b ) {
-
-		if ( a.object.renderOrder !== b.object.renderOrder ) {
-
-			return a.object.renderOrder - b.object.renderOrder;
-
-		} if ( a.z !== b.z ) {
-
-			return b.z - a.z;
-
-		} else {
-
-			return a.id - b.id;
-
-		}
-
-	}
-
 	// Rendering
 	// Rendering
 
 
 	this.render = function ( scene, camera, renderTarget, forceClear ) {
 	this.render = function ( scene, camera, renderTarget, forceClear ) {
@@ -1116,25 +1068,22 @@ function WebGLRenderer( parameters ) {
 		_frustum.setFromMatrix( _projScreenMatrix );
 		_frustum.setFromMatrix( _projScreenMatrix );
 
 
 		lights.length = 0;
 		lights.length = 0;
-
-		opaqueObjectsLastIndex = - 1;
-		transparentObjectsLastIndex = - 1;
-
 		sprites.length = 0;
 		sprites.length = 0;
 		lensFlares.length = 0;
 		lensFlares.length = 0;
 
 
 		_localClippingEnabled = this.localClippingEnabled;
 		_localClippingEnabled = this.localClippingEnabled;
 		_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
 		_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
 
 
+		currentRenderList = renderLists.get( scene, camera );
+		currentRenderList.init();
+
 		projectObject( scene, camera, _this.sortObjects );
 		projectObject( scene, camera, _this.sortObjects );
 
 
-		opaqueObjects.length = opaqueObjectsLastIndex + 1;
-		transparentObjects.length = transparentObjectsLastIndex + 1;
+		currentRenderList.finish();
 
 
 		if ( _this.sortObjects === true ) {
 		if ( _this.sortObjects === true ) {
 
 
-			opaqueObjects.sort( painterSortStable );
-			transparentObjects.sort( reversePainterSortStable );
+			currentRenderList.sort();
 
 
 		}
 		}
 
 
@@ -1244,6 +1193,9 @@ function WebGLRenderer( parameters ) {
 
 
 		//
 		//
 
 
+		var opaqueObjects = currentRenderList.opaque;
+		var transparentObjects = currentRenderList.transparent;
+
 		if ( scene.overrideMaterial ) {
 		if ( scene.overrideMaterial ) {
 
 
 			var overrideMaterial = scene.overrideMaterial;
 			var overrideMaterial = scene.overrideMaterial;
@@ -1287,55 +1239,6 @@ function WebGLRenderer( parameters ) {
 
 
 	};
 	};
 
 
-	function pushRenderItem( object, geometry, material, z, group ) {
-
-		var array, index;
-
-		// allocate the next position in the appropriate array
-
-		if ( material.transparent ) {
-
-			array = transparentObjects;
-			index = ++ transparentObjectsLastIndex;
-
-		} else {
-
-			array = opaqueObjects;
-			index = ++ opaqueObjectsLastIndex;
-
-		}
-
-		// recycle existing render item or grow the array
-
-		var renderItem = array[ index ];
-
-		if ( renderItem ) {
-
-			renderItem.id = object.id;
-			renderItem.object = object;
-			renderItem.geometry = geometry;
-			renderItem.material = material;
-			renderItem.z = _vector3.z;
-			renderItem.group = group;
-
-		} else {
-
-			renderItem = {
-				id: object.id,
-				object: object,
-				geometry: geometry,
-				material: material,
-				z: _vector3.z,
-				group: group
-			};
-
-			// assert( index === array.length );
-			array.push( renderItem );
-
-		}
-
-	}
-
 	/*
 	/*
 	// TODO Duplicated code (Frustum)
 	// TODO Duplicated code (Frustum)
 
 
@@ -1424,7 +1327,7 @@ function WebGLRenderer( parameters ) {
 
 
 				}
 				}
 
 
-				pushRenderItem( object, null, object.material, _vector3.z, null );
+				currentRenderList.push( object, null, object.material, _vector3.z, null );
 
 
 			} else if ( object.isMesh || object.isLine || object.isPoints ) {
 			} else if ( object.isMesh || object.isLine || object.isPoints ) {
 
 
@@ -1457,7 +1360,7 @@ function WebGLRenderer( parameters ) {
 
 
 							if ( groupMaterial && groupMaterial.visible ) {
 							if ( groupMaterial && groupMaterial.visible ) {
 
 
-								pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );
+								currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
 
 
 							}
 							}
 
 
@@ -1465,7 +1368,7 @@ function WebGLRenderer( parameters ) {
 
 
 					} else if ( material.visible ) {
 					} else if ( material.visible ) {
 
 
-						pushRenderItem( object, geometry, material, _vector3.z, null );
+						currentRenderList.push( object, geometry, material, _vector3.z, null );
 
 
 					}
 					}
 
 

+ 174 - 0
src/renderers/webgl/WebGLRenderLists.js

@@ -0,0 +1,174 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+function painterSortStable( a, b ) {
+
+	if ( a.object.renderOrder !== b.object.renderOrder ) {
+
+		return a.object.renderOrder - b.object.renderOrder;
+
+	} else if ( a.material.program && b.material.program && a.material.program !== b.material.program ) {
+
+		return a.material.program.id - b.material.program.id;
+
+	} else if ( a.material.id !== b.material.id ) {
+
+		return a.material.id - b.material.id;
+
+	} else if ( a.z !== b.z ) {
+
+		return a.z - b.z;
+
+	} else {
+
+		return a.id - b.id;
+
+	}
+
+}
+
+function reversePainterSortStable( a, b ) {
+
+	if ( a.object.renderOrder !== b.object.renderOrder ) {
+
+		return a.object.renderOrder - b.object.renderOrder;
+
+	} if ( a.z !== b.z ) {
+
+		return b.z - a.z;
+
+	} else {
+
+		return a.id - b.id;
+
+	}
+
+}
+
+function WebGLRenderList() {
+
+	var opaque = [];
+	var opaqueLastIndex = - 1;
+
+	var transparent = [];
+	var transparentLastIndex = - 1;
+
+	function init() {
+
+		opaqueLastIndex = - 1;
+		transparentLastIndex = - 1;
+
+	}
+
+	function push( object, geometry, material, z, group ) {
+
+		var array, index;
+
+		// allocate the next position in the appropriate array
+
+		if ( material.transparent ) {
+
+			array = transparent;
+			index = ++ transparentLastIndex;
+
+		} else {
+
+			array = opaque;
+			index = ++ opaqueLastIndex;
+
+		}
+
+		// recycle existing render item or grow the array
+
+		var renderItem = array[ index ];
+
+		if ( renderItem ) {
+
+			renderItem.id = object.id;
+			renderItem.object = object;
+			renderItem.geometry = geometry;
+			renderItem.material = material;
+			renderItem.z = z;
+			renderItem.group = group;
+
+		} else {
+
+			renderItem = {
+				id: object.id,
+				object: object,
+				geometry: geometry,
+				material: material,
+				z: z,
+				group: group
+			};
+
+			// assert( index === array.length );
+			array.push( renderItem );
+
+		}
+
+	}
+
+	function finish() {
+
+		opaque.length = opaqueLastIndex + 1;
+		transparent.length = transparentLastIndex + 1;
+
+	}
+
+	function sort() {
+
+		opaque.sort( painterSortStable );
+		transparent.sort( reversePainterSortStable );
+
+	}
+
+	return {
+		opaque: opaque,
+		transparent: transparent,
+
+		init: init,
+		push: push,
+		finish: finish,
+
+		sort: sort
+	};
+
+}
+
+function WebGLRenderLists() {
+
+	var lists = {};
+
+	function get( scene, camera ) {
+
+		var hash = scene.id + ',' + camera.id;
+		var list = lists[ hash ];
+
+		if ( list === undefined ) {
+
+			list = new WebGLRenderList();
+			lists[ hash ] = list;
+
+		}
+
+		return list;
+
+	}
+
+	function dispose() {
+
+		lists = {};
+
+	}
+
+	return {
+		get: get,
+		dispose: dispose
+	};
+
+}
+
+
+export { WebGLRenderLists };