diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 91f7c05fa74534b4a5f0f68b89a889abeae5d06e..df4cd75594745b487af0a4a4ec64291c73806d05 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -34,9 +34,6 @@ THREE.WebGLRenderer = function ( parameters ) { var lights = []; - var _webglObjects = {}; - var _webglObjectsImmediate = []; - var opaqueObjects = []; var transparentObjects = []; @@ -184,7 +181,7 @@ THREE.WebGLRenderer = function ( parameters ) { resetGLState(); setDefaultGLState(); - _webglObjects = {}; + objects.objects = {}; }, false); @@ -211,7 +208,7 @@ THREE.WebGLRenderer = function ( parameters ) { } var extensions = new THREE.WebGLExtensions( _gl ); - var buffers = new THREE.WebGLBuffers( _gl, this.info, extensions, getBufferMaterial ); + var objects = new THREE.WebGLObjects( _gl, this.info, extensions, getBufferMaterial ); extensions.get( 'OES_texture_float' ); extensions.get( 'OES_texture_float_linear' ); @@ -285,7 +282,7 @@ THREE.WebGLRenderer = function ( parameters ) { // shadow map - var shadowMap = new THREE.WebGLShadowMap( this, lights, _webglObjects, _webglObjectsImmediate ); + var shadowMap = new THREE.WebGLShadowMap( this, lights, objects ); this.shadowMap = shadowMap; @@ -607,30 +604,6 @@ THREE.WebGLRenderer = function ( parameters ) { // Events - var onObjectRemoved = function ( event ) { - - var object = event.target; - - object.traverse( function ( child ) { - - child.removeEventListener( 'remove', onObjectRemoved ); - - removeObject( child ); - - } ); - - }; - - var onGeometryDispose = function ( event ) { - - var geometry = event.target; - - geometry.removeEventListener( 'dispose', onGeometryDispose ); - - deallocateGeometry( geometry ); - - }; - var onTextureDispose = function ( event ) { var texture = event.target; @@ -668,82 +641,6 @@ THREE.WebGLRenderer = function ( parameters ) { // Buffer deallocation - var deallocateGeometry = function ( geometry ) { - - delete geometry.__webglInit; - - if ( geometry instanceof THREE.BufferGeometry ) { - - for ( var name in geometry.attributes ) { - - var attribute = geometry.attributes[ name ]; - - if ( attribute.buffer !== undefined ) { - - _gl.deleteBuffer( attribute.buffer ); - - delete attribute.buffer; - - } - - } - - _this.info.memory.geometries --; - - } else { - - var geometryGroupsList = geometryGroups[ geometry.id ]; - - if ( geometryGroupsList !== undefined ) { - - for ( var i = 0, l = geometryGroupsList.length; i < l; i ++ ) { - - var geometryGroup = geometryGroupsList[ i ]; - - if ( geometryGroup.numMorphTargets !== undefined ) { - - for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) { - - _gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] ); - - } - - delete geometryGroup.__webglMorphTargetsBuffers; - - } - - if ( geometryGroup.numMorphNormals !== undefined ) { - - for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) { - - _gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] ); - - } - - delete geometryGroup.__webglMorphNormalsBuffers; - - } - - buffers.delete( geometryGroup ); - - } - - delete geometryGroups[ geometry.id ]; - - } else { - - buffers.delete( geometry ); - - } - - } - - // TOFIX: Workaround for deleted geometry being currently bound - - _currentGeometryProgram = ''; - - }; - var deallocateTexture = function ( texture ) { if ( texture.image && texture.image.__webglTextureCube ) { @@ -1094,7 +991,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.visible === false ) return; - updateObject( object ); + objects.update( object ); var program = setProgram( camera, lights, fog, material, object ); @@ -1499,7 +1396,7 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.visible === false ) return; - updateObject( object ); + objects.update( object ); var program = setProgram( camera, lights, fog, material, object ); @@ -2043,9 +1940,9 @@ THREE.WebGLRenderer = function ( parameters ) { // set matrices for immediate objects - for ( var i = 0, il = _webglObjectsImmediate.length; i < il; i ++ ) { + for ( var i = 0, il = objects.objectsImmediate.length; i < il; i ++ ) { - var webglObject = _webglObjectsImmediate[ i ]; + var webglObject = objects.objectsImmediate[ i ]; var object = webglObject.object; if ( object.visible ) { @@ -2066,7 +1963,7 @@ THREE.WebGLRenderer = function ( parameters ) { renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial ); renderObjects( transparentObjects, camera, lights, fog, overrideMaterial ); - renderObjectsImmediate( _webglObjectsImmediate, '', camera, lights, fog, overrideMaterial ); + renderObjectsImmediate( objects.objectsImmediate, '', camera, lights, fog, overrideMaterial ); } else { @@ -2075,12 +1972,12 @@ THREE.WebGLRenderer = function ( parameters ) { state.setBlending( THREE.NoBlending ); renderObjects( opaqueObjects, camera, lights, fog, null ); - renderObjectsImmediate( _webglObjectsImmediate, 'opaque', camera, lights, fog, null ); + renderObjectsImmediate( objects.objectsImmediate, 'opaque', camera, lights, fog, null ); // transparent pass (back-to-front order) renderObjects( transparentObjects, camera, lights, fog, null ); - renderObjectsImmediate( _webglObjectsImmediate, 'transparent', camera, lights, fog, null ); + renderObjectsImmediate( objects.objectsImmediate, 'transparent', camera, lights, fog, null ); } @@ -2117,7 +2014,7 @@ THREE.WebGLRenderer = function ( parameters ) { } else { - initObject( object ); + objects.init( object ); if ( object instanceof THREE.Light ) { @@ -2133,7 +2030,7 @@ THREE.WebGLRenderer = function ( parameters ) { } else { - var webglObjects = _webglObjects[ object.id ]; + var webglObjects = objects.objects[ object.id ]; if ( webglObjects && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) { @@ -2329,453 +2226,6 @@ THREE.WebGLRenderer = function ( parameters ) { } - function initObject( object ) { - - if ( object.__webglInit === undefined ) { - - object.__webglInit = true; - object._modelViewMatrix = new THREE.Matrix4(); - object._normalMatrix = new THREE.Matrix3(); - - object.addEventListener( 'removed', onObjectRemoved ); - - } - - var geometry = object.geometry; - - if ( geometry === undefined ) { - - // ImmediateRenderObject - - } else if ( geometry.__webglInit === undefined ) { - - geometry.__webglInit = true; - geometry.addEventListener( 'dispose', onGeometryDispose ); - - if ( geometry instanceof THREE.BufferGeometry ) { - - _this.info.memory.geometries ++; - - } else if ( object instanceof THREE.Mesh ) { - - initGeometryGroups( object, geometry ); - - } else if ( object instanceof THREE.Line ) { - - buffers.initLineBuffers( geometry, object ); - - } else if ( object instanceof THREE.PointCloud ) { - - buffers.initPointCloudBuffers( geometry, object ); - - } - - } - - if ( object.__webglActive === undefined) { - - object.__webglActive = true; - - if ( object instanceof THREE.Mesh ) { - - if ( geometry instanceof THREE.BufferGeometry ) { - - addBuffer( _webglObjects, geometry, object ); - - } else if ( geometry instanceof THREE.Geometry ) { - - var geometryGroupsList = geometryGroups[ geometry.id ]; - - for ( var i = 0,l = geometryGroupsList.length; i < l; i ++ ) { - - addBuffer( _webglObjects, geometryGroupsList[ i ], object ); - - } - - } - - } else if ( object instanceof THREE.Line || object instanceof THREE.PointCloud ) { - - addBuffer( _webglObjects, geometry, object ); - - } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) { - - addBufferImmediate( _webglObjectsImmediate, object ); - - } - - } - - } - - // Geometry splitting - - var geometryGroups = {}; - var geometryGroupCounter = 0; - - function makeGroups( geometry, usesFaceMaterial ) { - - var maxVerticesInGroup = extensions.get( 'OES_element_index_uint' ) ? 4294967296 : 65535; - - var groupHash, hash_map = {}; - - var numMorphTargets = geometry.morphTargets.length; - var numMorphNormals = geometry.morphNormals.length; - - var group; - var groups = {}; - var groupsList = []; - - for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) { - - var face = geometry.faces[ f ]; - var materialIndex = usesFaceMaterial ? face.materialIndex : 0; - - if ( ! ( materialIndex in hash_map ) ) { - - hash_map[ materialIndex ] = { hash: materialIndex, counter: 0 }; - - } - - groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter; - - if ( ! ( groupHash in groups ) ) { - - group = { - id: geometryGroupCounter ++, - faces3: [], - materialIndex: materialIndex, - vertices: 0, - numMorphTargets: numMorphTargets, - numMorphNormals: numMorphNormals - }; - - groups[ groupHash ] = group; - groupsList.push( group ); - - } - - if ( groups[ groupHash ].vertices + 3 > maxVerticesInGroup ) { - - hash_map[ materialIndex ].counter += 1; - groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter; - - if ( ! ( groupHash in groups ) ) { - - group = { - id: geometryGroupCounter ++, - faces3: [], - materialIndex: materialIndex, - vertices: 0, - numMorphTargets: numMorphTargets, - numMorphNormals: numMorphNormals - }; - - groups[ groupHash ] = group; - groupsList.push( group ); - - } - - } - - groups[ groupHash ].faces3.push( f ); - groups[ groupHash ].vertices += 3; - - } - - return groupsList; - - } - - function initGeometryGroups( object, geometry ) { - - var material = object.material, addBuffers = false; - - if ( geometryGroups[ geometry.id ] === undefined || geometry.groupsNeedUpdate === true ) { - - delete _webglObjects[ object.id ]; - - geometryGroups[ geometry.id ] = makeGroups( geometry, material instanceof THREE.MeshFaceMaterial ); - - geometry.groupsNeedUpdate = false; - - } - - var geometryGroupsList = geometryGroups[ geometry.id ]; - - // create separate VBOs per geometry chunk - - for ( var i = 0, il = geometryGroupsList.length; i < il; i ++ ) { - - var geometryGroup = geometryGroupsList[ i ]; - - // initialise VBO on the first access - - if ( geometryGroup.__webglVertexBuffer === undefined ) { - - buffers.initMeshBuffers( geometryGroup, object ); - - geometry.verticesNeedUpdate = true; - geometry.morphTargetsNeedUpdate = true; - geometry.elementsNeedUpdate = true; - geometry.uvsNeedUpdate = true; - geometry.normalsNeedUpdate = true; - geometry.tangentsNeedUpdate = true; - geometry.colorsNeedUpdate = true; - - addBuffers = true; - - } else { - - addBuffers = false; - - } - - if ( addBuffers || object.__webglActive === undefined ) { - - addBuffer( _webglObjects, geometryGroup, object ); - - } - - } - - object.__webglActive = true; - - } - - function addBuffer( objlist, buffer, object ) { - - var id = object.id; - objlist[id] = objlist[id] || []; - objlist[id].push( - { - id: id, - buffer: buffer, - object: object, - material: null, - z: 0 - } - ); - - }; - - function addBufferImmediate( objlist, object ) { - - objlist.push( - { - id: null, - object: object, - opaque: null, - transparent: null, - z: 0 - } - ); - - }; - - // Objects updates - - function updateObject( object ) { - - var geometry = object.geometry; - - if ( geometry instanceof THREE.BufferGeometry ) { - - var attributes = geometry.attributes; - var attributesKeys = geometry.attributesKeys; - - for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) { - - var key = attributesKeys[ i ]; - var attribute = attributes[ key ]; - var bufferType = ( key === 'index' ) ? _gl.ELEMENT_ARRAY_BUFFER : _gl.ARRAY_BUFFER; - - var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute; - - if ( data.buffer === undefined ) { - - data.buffer = _gl.createBuffer(); - _gl.bindBuffer( bufferType, data.buffer ); - - var usage = _gl.STATIC_DRAW; - - if ( data instanceof THREE.DynamicBufferAttribute - || ( data instanceof THREE.InstancedBufferAttribute && data.dynamic === true ) - || ( data instanceof THREE.InterleavedBuffer && data.dynamic === true ) ) { - - usage = _gl.DYNAMIC_DRAW; - - } - - _gl.bufferData( bufferType, data.array, usage ); - - data.needsUpdate = false; - - } else if ( data.needsUpdate === true ) { - - _gl.bindBuffer( bufferType, data.buffer ); - - if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges - - _gl.bufferSubData( bufferType, 0, data.array ); - - } else if ( data.updateRange.count === 0 ) { - - THREE.error( 'THREE.WebGLRenderer.updateObject: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' ); - - } else { - - _gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT, - data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) ); - - data.updateRange.count = 0; // reset range - - } - - data.needsUpdate = false; - - } - - } - - } else if ( object instanceof THREE.Mesh ) { - - // check all geometry groups - - if ( geometry.groupsNeedUpdate === true ) { - - initGeometryGroups( object, geometry ); - - } - - var geometryGroupsList = geometryGroups[ geometry.id ]; - - for ( var i = 0, il = geometryGroupsList.length; i < il; i ++ ) { - - var geometryGroup = geometryGroupsList[ i ]; - var material = getBufferMaterial( object, geometryGroup ); - - var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); - - if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate || - geometry.uvsNeedUpdate || geometry.normalsNeedUpdate || - geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) { - - buffers.setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, ! geometry.dynamic, material ); - - } - - } - - geometry.verticesNeedUpdate = false; - geometry.morphTargetsNeedUpdate = false; - geometry.elementsNeedUpdate = false; - geometry.uvsNeedUpdate = false; - geometry.normalsNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.tangentsNeedUpdate = false; - - material.attributes && clearCustomAttributes( material ); - - } else if ( object instanceof THREE.Line ) { - - var material = getBufferMaterial( object, geometry ); - var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); - - if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) { - - buffers.setLineBuffers( geometry, _gl.DYNAMIC_DRAW ); - - } - - geometry.verticesNeedUpdate = false; - geometry.colorsNeedUpdate = false; - geometry.lineDistancesNeedUpdate = false; - - material.attributes && clearCustomAttributes( material ); - - } else if ( object instanceof THREE.PointCloud ) { - - var material = getBufferMaterial( object, geometry ); - var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); - - if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || customAttributesDirty ) { - - buffers.setPointCloudBuffers( geometry, _gl.DYNAMIC_DRAW, object ); - - } - - geometry.verticesNeedUpdate = false; - geometry.colorsNeedUpdate = false; - - material.attributes && clearCustomAttributes( material ); - - } - - } - - // Objects updates - custom attributes check - - function areCustomAttributesDirty( material ) { - - for ( var name in material.attributes ) { - - if ( material.attributes[ name ].needsUpdate ) return true; - - } - - return false; - - } - - function clearCustomAttributes( material ) { - - for ( var name in material.attributes ) { - - material.attributes[ name ].needsUpdate = false; - - } - - } - - // Objects removal - - function removeObject( object ) { - - if ( object instanceof THREE.Mesh || - object instanceof THREE.PointCloud || - object instanceof THREE.Line ) { - - delete _webglObjects[ object.id ]; - - } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) { - - removeInstances( _webglObjectsImmediate, object ); - - } - - delete object.__webglInit; - delete object._modelViewMatrix; - delete object._normalMatrix; - - delete object.__webglActive; - - } - - function removeInstances( objlist, object ) { - - for ( var o = objlist.length - 1; o >= 0; o -- ) { - - if ( objlist[ o ].object === object ) { - - objlist.splice( o, 1 ); - - } - - } - - } - // Materials var shaderIDs = { diff --git a/src/renderers/webgl/WebGLObjects.js b/src/renderers/webgl/WebGLObjects.js new file mode 100644 index 0000000000000000000000000000000000000000..ab1472e0aa414b823eeb74d2e9fac0ca422a1739 --- /dev/null +++ b/src/renderers/webgl/WebGLObjects.js @@ -0,0 +1,564 @@ +/** +* @author mrdoob / http://mrdoob.com/ +*/ + +THREE.WebGLObjects = function ( gl, info, extensions, getBufferMaterial ) { + + var buffers = new THREE.WebGLBuffers( gl, info, extensions, getBufferMaterial ); + + var objects = {}; + var objectsImmediate = []; + + var geometryGroups = {}; + var geometryGroupCounter = 0; + + function makeGroups( geometry, usesFaceMaterial ) { + + var maxVerticesInGroup = extensions.get( 'OES_element_index_uint' ) ? 4294967296 : 65535; + + var groupHash, hash_map = {}; + + var numMorphTargets = geometry.morphTargets.length; + var numMorphNormals = geometry.morphNormals.length; + + var group; + var groups = {}; + var groupsList = []; + + for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) { + + var face = geometry.faces[ f ]; + var materialIndex = usesFaceMaterial ? face.materialIndex : 0; + + if ( ! ( materialIndex in hash_map ) ) { + + hash_map[ materialIndex ] = { hash: materialIndex, counter: 0 }; + + } + + groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter; + + if ( ! ( groupHash in groups ) ) { + + group = { + id: geometryGroupCounter ++, + faces3: [], + materialIndex: materialIndex, + vertices: 0, + numMorphTargets: numMorphTargets, + numMorphNormals: numMorphNormals + }; + + groups[ groupHash ] = group; + groupsList.push( group ); + + } + + if ( groups[ groupHash ].vertices + 3 > maxVerticesInGroup ) { + + hash_map[ materialIndex ].counter += 1; + groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter; + + if ( ! ( groupHash in groups ) ) { + + group = { + id: geometryGroupCounter ++, + faces3: [], + materialIndex: materialIndex, + vertices: 0, + numMorphTargets: numMorphTargets, + numMorphNormals: numMorphNormals + }; + + groups[ groupHash ] = group; + groupsList.push( group ); + + } + + } + + groups[ groupHash ].faces3.push( f ); + groups[ groupHash ].vertices += 3; + + } + + return groupsList; + + } + + function initGeometryGroups( object, geometry ) { + + var material = object.material, addBuffers = false; + + if ( geometryGroups[ geometry.id ] === undefined || geometry.groupsNeedUpdate === true ) { + + delete objects[ object.id ]; + + geometryGroups[ geometry.id ] = makeGroups( geometry, material instanceof THREE.MeshFaceMaterial ); + + geometry.groupsNeedUpdate = false; + + } + + var geometryGroupsList = geometryGroups[ geometry.id ]; + + // create separate VBOs per geometry chunk + + for ( var i = 0, il = geometryGroupsList.length; i < il; i ++ ) { + + var geometryGroup = geometryGroupsList[ i ]; + + // initialise VBO on the first access + + if ( geometryGroup.__webglVertexBuffer === undefined ) { + + buffers.initMeshBuffers( geometryGroup, object ); + + geometry.verticesNeedUpdate = true; + geometry.morphTargetsNeedUpdate = true; + geometry.elementsNeedUpdate = true; + geometry.uvsNeedUpdate = true; + geometry.normalsNeedUpdate = true; + geometry.tangentsNeedUpdate = true; + geometry.colorsNeedUpdate = true; + + addBuffers = true; + + } else { + + addBuffers = false; + + } + + if ( addBuffers || object.__webglActive === undefined ) { + + addBuffer( objects, geometryGroup, object ); + + } + + } + + object.__webglActive = true; + + } + + function addBuffer( objlist, buffer, object ) { + + var id = object.id; + objlist[id] = objlist[id] || []; + objlist[id].push( + { + id: id, + buffer: buffer, + object: object, + material: null, + z: 0 + } + ); + + }; + + function addBufferImmediate( objlist, object ) { + + objlist.push( + { + id: null, + object: object, + opaque: null, + transparent: null, + z: 0 + } + ); + + }; + + // + + // Objects updates - custom attributes check + + function areCustomAttributesDirty( material ) { + + for ( var name in material.attributes ) { + + if ( material.attributes[ name ].needsUpdate ) return true; + + } + + return false; + + } + + function clearCustomAttributes( material ) { + + for ( var name in material.attributes ) { + + material.attributes[ name ].needsUpdate = false; + + } + + } + + // + + function onObjectRemoved ( event ) { + + var object = event.target; + + object.traverse( function ( child ) { + + child.removeEventListener( 'remove', onObjectRemoved ); + + removeObject( child ); + + } ); + + }; + + function removeObject( object ) { + + if ( object instanceof THREE.Mesh || + object instanceof THREE.PointCloud || + object instanceof THREE.Line ) { + + delete objects[ object.id ]; + + } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) { + + removeInstances( objectsImmediate, object ); + + } + + delete object.__webglInit; + delete object._modelViewMatrix; + delete object._normalMatrix; + + delete object.__webglActive; + + } + + function removeInstances( objlist, object ) { + + for ( var o = objlist.length - 1; o >= 0; o -- ) { + + if ( objlist[ o ].object === object ) { + + objlist.splice( o, 1 ); + + } + + } + + } + + // + + function onGeometryDispose ( event ) { + + var geometry = event.target; + + geometry.removeEventListener( 'dispose', onGeometryDispose ); + + deallocateGeometry( geometry ); + + }; + + function deallocateGeometry ( geometry ) { + + delete geometry.__webglInit; + + if ( geometry instanceof THREE.BufferGeometry ) { + + for ( var name in geometry.attributes ) { + + var attribute = geometry.attributes[ name ]; + + if ( attribute.buffer !== undefined ) { + + gl.deleteBuffer( attribute.buffer ); + + delete attribute.buffer; + + } + + } + + info.memory.geometries --; + + } else { + + var geometryGroupsList = geometryGroups[ geometry.id ]; + + if ( geometryGroupsList !== undefined ) { + + for ( var i = 0, l = geometryGroupsList.length; i < l; i ++ ) { + + var geometryGroup = geometryGroupsList[ i ]; + + if ( geometryGroup.numMorphTargets !== undefined ) { + + for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) { + + gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] ); + + } + + delete geometryGroup.__webglMorphTargetsBuffers; + + } + + if ( geometryGroup.numMorphNormals !== undefined ) { + + for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) { + + gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] ); + + } + + delete geometryGroup.__webglMorphNormalsBuffers; + + } + + buffers.delete( geometryGroup ); + + } + + delete geometryGroups[ geometry.id ]; + + } else { + + buffers.delete( geometry ); + + } + + } + + // TOFIX: Workaround for deleted geometry being currently bound + + _currentGeometryProgram = ''; + + }; + + // + + this.objects = objects; + this.objectsImmediate = objectsImmediate; + + this.init = function ( object ) { + + if ( object.__webglInit === undefined ) { + + object.__webglInit = true; + object._modelViewMatrix = new THREE.Matrix4(); + object._normalMatrix = new THREE.Matrix3(); + + object.addEventListener( 'removed', onObjectRemoved ); + + } + + var geometry = object.geometry; + + if ( geometry === undefined ) { + + // ImmediateRenderObject + + } else if ( geometry.__webglInit === undefined ) { + + geometry.__webglInit = true; + geometry.addEventListener( 'dispose', onGeometryDispose ); + + if ( geometry instanceof THREE.BufferGeometry ) { + + info.memory.geometries ++; + + } else if ( object instanceof THREE.Mesh ) { + + initGeometryGroups( object, geometry ); + + } else if ( object instanceof THREE.Line ) { + + buffers.initLineBuffers( geometry, object ); + + } else if ( object instanceof THREE.PointCloud ) { + + buffers.initPointCloudBuffers( geometry, object ); + + } + + } + + if ( object.__webglActive === undefined) { + + object.__webglActive = true; + + if ( object instanceof THREE.Mesh ) { + + if ( geometry instanceof THREE.BufferGeometry ) { + + addBuffer( objects, geometry, object ); + + } else if ( geometry instanceof THREE.Geometry ) { + + var geometryGroupsList = geometryGroups[ geometry.id ]; + + for ( var i = 0,l = geometryGroupsList.length; i < l; i ++ ) { + + addBuffer( objects, geometryGroupsList[ i ], object ); + + } + + } + + } else if ( object instanceof THREE.Line || object instanceof THREE.PointCloud ) { + + addBuffer( objects, geometry, object ); + + } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) { + + addBufferImmediate( objectsImmediate, object ); + + } + + } + + }; + + this.update = function ( object ) { + + var geometry = object.geometry; + + if ( geometry instanceof THREE.BufferGeometry ) { + + var attributes = geometry.attributes; + var attributesKeys = geometry.attributesKeys; + + for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) { + + var key = attributesKeys[ i ]; + var attribute = attributes[ key ]; + var bufferType = ( key === 'index' ) ? gl.ELEMENT_ARRAY_BUFFER : gl.ARRAY_BUFFER; + + var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute; + + if ( data.buffer === undefined ) { + + data.buffer = gl.createBuffer(); + gl.bindBuffer( bufferType, data.buffer ); + + var usage = gl.STATIC_DRAW; + + if ( data instanceof THREE.DynamicBufferAttribute + || ( data instanceof THREE.InstancedBufferAttribute && data.dynamic === true ) + || ( data instanceof THREE.InterleavedBuffer && data.dynamic === true ) ) { + + usage = gl.DYNAMIC_DRAW; + + } + + gl.bufferData( bufferType, data.array, usage ); + + data.needsUpdate = false; + + } else if ( data.needsUpdate === true ) { + + gl.bindBuffer( bufferType, data.buffer ); + + if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges + + gl.bufferSubData( bufferType, 0, data.array ); + + } else if ( data.updateRange.count === 0 ) { + + THREE.error( 'THREE.WebGLRenderer.updateObject: using updateRange for THREE.DynamicBufferAttribute and marked as needsUpdate but count is 0, ensure you are using set methods or updating manually.' ); + + } else { + + gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT, + data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) ); + + data.updateRange.count = 0; // reset range + + } + + data.needsUpdate = false; + + } + + } + + } else if ( object instanceof THREE.Mesh ) { + + // check all geometry groups + + if ( geometry.groupsNeedUpdate === true ) { + + initGeometryGroups( object, geometry ); + + } + + var geometryGroupsList = geometryGroups[ geometry.id ]; + + for ( var i = 0, il = geometryGroupsList.length; i < il; i ++ ) { + + var geometryGroup = geometryGroupsList[ i ]; + var material = getBufferMaterial( object, geometryGroup ); + + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + + if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate || + geometry.uvsNeedUpdate || geometry.normalsNeedUpdate || + geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) { + + buffers.setMeshBuffers( geometryGroup, object, gl.DYNAMIC_DRAW, ! geometry.dynamic, material ); + + } + + } + + geometry.verticesNeedUpdate = false; + geometry.morphTargetsNeedUpdate = false; + geometry.elementsNeedUpdate = false; + geometry.uvsNeedUpdate = false; + geometry.normalsNeedUpdate = false; + geometry.colorsNeedUpdate = false; + geometry.tangentsNeedUpdate = false; + + material.attributes && clearCustomAttributes( material ); + + } else if ( object instanceof THREE.Line ) { + + var material = getBufferMaterial( object, geometry ); + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + + if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) { + + buffers.setLineBuffers( geometry, gl.DYNAMIC_DRAW ); + + } + + geometry.verticesNeedUpdate = false; + geometry.colorsNeedUpdate = false; + geometry.lineDistancesNeedUpdate = false; + + material.attributes && clearCustomAttributes( material ); + + } else if ( object instanceof THREE.PointCloud ) { + + var material = getBufferMaterial( object, geometry ); + var customAttributesDirty = material.attributes && areCustomAttributesDirty( material ); + + if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || customAttributesDirty ) { + + buffers.setPointCloudBuffers( geometry, gl.DYNAMIC_DRAW, object ); + + } + + geometry.verticesNeedUpdate = false; + geometry.colorsNeedUpdate = false; + + material.attributes && clearCustomAttributes( material ); + + } + + }; + +}; diff --git a/src/renderers/webgl/WebGLShadowMap.js b/src/renderers/webgl/WebGLShadowMap.js index e5c0da1a62b70e83212fac23e7cb98c6cfb3cc19..bb155589061e9b82cf885be3c57f7209fd1acd26 100644 --- a/src/renderers/webgl/WebGLShadowMap.js +++ b/src/renderers/webgl/WebGLShadowMap.js @@ -3,7 +3,7 @@ * @author mrdoob / http://mrdoob.com/ */ -THREE.WebGLShadowMap = function ( _renderer, _lights, _webglObjects, _webglObjectsImmediate ) { +THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) { var _gl = _renderer.context, _frustum = new THREE.Frustum(), @@ -12,6 +12,9 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _webglObjects, _webglObjec _min = new THREE.Vector3(), _max = new THREE.Vector3(), + _webglObjects = _objects.objects, + _webglObjectsImmediate = _objects.objectsImmediate, + _matrixPosition = new THREE.Vector3(), _renderList = []; diff --git a/utils/build/includes/common.json b/utils/build/includes/common.json index 02fcdd0bdd7358fa1b5451dfa7ab0f9f4cccc58a..3355864dadf46d1c8fc3aa5189bc6551b36fd1c9 100644 --- a/utils/build/includes/common.json +++ b/utils/build/includes/common.json @@ -154,6 +154,7 @@ "src/renderers/WebGLRenderTargetCube.js", "src/renderers/webgl/WebGLBuffers.js", "src/renderers/webgl/WebGLExtensions.js", + "src/renderers/webgl/WebGLObjects.js", "src/renderers/webgl/WebGLProgram.js", "src/renderers/webgl/WebGLShader.js", "src/renderers/webgl/WebGLShadowMap.js",