From 83e9745bf928087389764e7bdd903e701ed7f4e8 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 24 Feb 2017 14:26:02 -0800 Subject: [PATCH] WebGLRenderer: Moved renderList logic to WebGLRenderList. Implemented mult-RenderList. See #9545. --- src/renderers/WebGLRenderer.js | 129 +++--------------- src/renderers/webgl/WebGLRenderLists.js | 174 ++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 113 deletions(-) create mode 100644 src/renderers/webgl/WebGLRenderLists.js diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 2dfe898175..6e6d22ceb3 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -17,6 +17,7 @@ import { MeshBasicMaterial } from '../materials/MeshBasicMaterial'; import { PerspectiveCamera } from '../cameras/PerspectiveCamera'; import { OrthographicCamera } from '../cameras/OrthographicCamera'; import { WebGLAttributes } from './webgl/WebGLAttributes'; +import { WebGLRenderLists } from './webgl/WebGLRenderLists'; import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer'; import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer'; import { WebGLGeometries } from './webgl/WebGLGeometries'; @@ -62,10 +63,7 @@ function WebGLRenderer( parameters ) { var lights = []; - var opaqueObjects = []; - var opaqueObjectsLastIndex = - 1; - var transparentObjects = []; - var transparentObjectsLastIndex = - 1; + var currentRenderList = null; var morphInfluences = new Float32Array( 8 ); @@ -296,6 +294,7 @@ function WebGLRenderer( parameters ) { var objects = new WebGLObjects( _gl, geometries, _infoRender ); var programCache = new WebGLPrograms( this, capabilities ); var lightCache = new WebGLLights(); + var renderLists = new WebGLRenderLists(); this.info.programs = programCache.programs; @@ -527,13 +526,10 @@ function WebGLRenderer( parameters ) { this.dispose = function () { - transparentObjects = []; - transparentObjectsLastIndex = - 1; - opaqueObjects = []; - opaqueObjectsLastIndex = - 1; - _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); + renderLists.dispose(); + }; // 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 this.render = function ( scene, camera, renderTarget, forceClear ) { @@ -1116,25 +1068,22 @@ function WebGLRenderer( parameters ) { _frustum.setFromMatrix( _projScreenMatrix ); lights.length = 0; - - opaqueObjectsLastIndex = - 1; - transparentObjectsLastIndex = - 1; - sprites.length = 0; lensFlares.length = 0; _localClippingEnabled = this.localClippingEnabled; _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); + currentRenderList = renderLists.get( scene, camera ); + currentRenderList.init(); + projectObject( scene, camera, _this.sortObjects ); - opaqueObjects.length = opaqueObjectsLastIndex + 1; - transparentObjects.length = transparentObjectsLastIndex + 1; + currentRenderList.finish(); 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 ) { 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) @@ -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 ) { @@ -1457,7 +1360,7 @@ function WebGLRenderer( parameters ) { 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 ) { - pushRenderItem( object, geometry, material, _vector3.z, null ); + currentRenderList.push( object, geometry, material, _vector3.z, null ); } diff --git a/src/renderers/webgl/WebGLRenderLists.js b/src/renderers/webgl/WebGLRenderLists.js new file mode 100644 index 0000000000..0abf2c5f8f --- /dev/null +++ b/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 }; -- GitLab