|
@@ -15,6 +15,7 @@ import ClippingContext from './ClippingContext.js';
|
|
import { Scene, Frustum, Matrix4, Vector2, Vector3, Vector4, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoColorSpace, NoToneMapping, LinearFilter, LinearSRGBColorSpace, RenderTarget, HalfFloatType, RGBAFormat } from 'three';
|
|
import { Scene, Frustum, Matrix4, Vector2, Vector3, Vector4, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoColorSpace, NoToneMapping, LinearFilter, LinearSRGBColorSpace, RenderTarget, HalfFloatType, RGBAFormat } from 'three';
|
|
import { NodeMaterial } from '../../nodes/Nodes.js';
|
|
import { NodeMaterial } from '../../nodes/Nodes.js';
|
|
import QuadMesh from '../../objects/QuadMesh.js';
|
|
import QuadMesh from '../../objects/QuadMesh.js';
|
|
|
|
+import RenderBundles from './RenderBundles.js';
|
|
|
|
|
|
const _scene = new Scene();
|
|
const _scene = new Scene();
|
|
const _drawingBufferSize = new Vector2();
|
|
const _drawingBufferSize = new Vector2();
|
|
@@ -87,6 +88,7 @@ class Renderer {
|
|
this._bindings = null;
|
|
this._bindings = null;
|
|
this._objects = null;
|
|
this._objects = null;
|
|
this._pipelines = null;
|
|
this._pipelines = null;
|
|
|
|
+ this._bundles = null;
|
|
this._renderLists = null;
|
|
this._renderLists = null;
|
|
this._renderContexts = null;
|
|
this._renderContexts = null;
|
|
this._textures = null;
|
|
this._textures = null;
|
|
@@ -111,6 +113,7 @@ class Renderer {
|
|
|
|
|
|
this._renderObjectFunction = null;
|
|
this._renderObjectFunction = null;
|
|
this._currentRenderObjectFunction = null;
|
|
this._currentRenderObjectFunction = null;
|
|
|
|
+ this._currentRenderBundle = null;
|
|
|
|
|
|
this._handleObjectFunction = this._renderObjectDirect;
|
|
this._handleObjectFunction = this._renderObjectDirect;
|
|
|
|
|
|
@@ -171,6 +174,7 @@ class Renderer {
|
|
this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info );
|
|
this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info );
|
|
this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info );
|
|
this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info );
|
|
this._renderLists = new RenderLists();
|
|
this._renderLists = new RenderLists();
|
|
|
|
+ this._bundles = new RenderBundles();
|
|
this._renderContexts = new RenderContexts();
|
|
this._renderContexts = new RenderContexts();
|
|
|
|
|
|
//
|
|
//
|
|
@@ -326,6 +330,81 @@ class Renderer {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ _renderBundle( bundle, sceneRef, lightsNode ) {
|
|
|
|
+
|
|
|
|
+ const { object, camera, renderList } = bundle;
|
|
|
|
+
|
|
|
|
+ const renderContext = this._currentRenderContext;
|
|
|
|
+ const renderContextData = this.backend.get( renderContext );
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ const renderBundle = this._bundles.get( object, camera );
|
|
|
|
+
|
|
|
|
+ const renderBundleData = this.backend.get( renderBundle );
|
|
|
|
+ if ( renderBundleData.renderContexts === undefined ) renderBundleData.renderContexts = new Set();
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ const renderBundleNeedsUpdate = renderBundleData.renderContexts.has( renderContext ) === false || object.needsUpdate === true;
|
|
|
|
+
|
|
|
|
+ renderBundleData.renderContexts.add( renderContext );
|
|
|
|
+
|
|
|
|
+ if ( renderBundleNeedsUpdate ) {
|
|
|
|
+
|
|
|
|
+ if ( renderContextData.renderObjects === undefined || object.needsUpdate === true ) {
|
|
|
|
+
|
|
|
|
+ const nodeFrame = this._nodes.nodeFrame;
|
|
|
|
+
|
|
|
|
+ renderContextData.renderObjects = [];
|
|
|
|
+ renderContextData.renderBundles = [];
|
|
|
|
+ renderContextData.scene = sceneRef;
|
|
|
|
+ renderContextData.camera = camera;
|
|
|
|
+ renderContextData.renderId = nodeFrame.renderId;
|
|
|
|
+
|
|
|
|
+ renderContextData.registerBundlesPhase = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._currentRenderBundle = renderBundle;
|
|
|
|
+
|
|
|
|
+ const opaqueObjects = renderList.opaque;
|
|
|
|
+
|
|
|
|
+ if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode );
|
|
|
|
+
|
|
|
|
+ this._currentRenderBundle = null;
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ object.needsUpdate = false;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ const renderContext = this._currentRenderContext;
|
|
|
|
+ const renderContextData = this.backend.get( renderContext );
|
|
|
|
+
|
|
|
|
+ for ( let i = 0, l = renderContextData.renderObjects.length; i < l; i ++ ) {
|
|
|
|
+
|
|
|
|
+ const renderObject = renderContextData.renderObjects[ i ];
|
|
|
|
+
|
|
|
|
+ this._nodes.updateBefore( renderObject );
|
|
|
|
+
|
|
|
|
+ //
|
|
|
|
+
|
|
|
|
+ renderObject.object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, renderObject.object.matrixWorld );
|
|
|
|
+ renderObject.object.normalMatrix.getNormalMatrix( renderObject.object.modelViewMatrix );
|
|
|
|
+
|
|
|
|
+ this._nodes.updateForRender( renderObject );
|
|
|
|
+ this._bindings.updateForRender( renderObject );
|
|
|
|
+
|
|
|
|
+ this.backend.draw( renderObject, this.info );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
render( scene, camera ) {
|
|
render( scene, camera ) {
|
|
|
|
|
|
if ( this._initialized === false ) {
|
|
if ( this._initialized === false ) {
|
|
@@ -456,7 +535,6 @@ class Renderer {
|
|
|
|
|
|
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
|
|
if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld();
|
|
|
|
|
|
-
|
|
|
|
//
|
|
//
|
|
|
|
|
|
let viewport = this._viewport;
|
|
let viewport = this._viewport;
|
|
@@ -564,8 +642,10 @@ class Renderer {
|
|
|
|
|
|
const opaqueObjects = renderList.opaque;
|
|
const opaqueObjects = renderList.opaque;
|
|
const transparentObjects = renderList.transparent;
|
|
const transparentObjects = renderList.transparent;
|
|
|
|
+ const bundles = renderList.bundles;
|
|
const lightsNode = renderList.lightsNode;
|
|
const lightsNode = renderList.lightsNode;
|
|
|
|
|
|
|
|
+ if ( bundles.length > 0 ) this._renderBundles( bundles, sceneRef, lightsNode );
|
|
if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode );
|
|
if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode );
|
|
if ( transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, sceneRef, lightsNode );
|
|
if ( transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, sceneRef, lightsNode );
|
|
|
|
|
|
@@ -1194,6 +1274,25 @@ class Renderer {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if ( object.static === true ) {
|
|
|
|
+
|
|
|
|
+ const baseRenderList = renderList;
|
|
|
|
+
|
|
|
|
+ // replace render list
|
|
|
|
+ renderList = this._renderLists.get( object, camera );
|
|
|
|
+
|
|
|
|
+ renderList.begin();
|
|
|
|
+
|
|
|
|
+ baseRenderList.pushBundle( {
|
|
|
|
+ object,
|
|
|
|
+ camera,
|
|
|
|
+ renderList,
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ renderList.finish();
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
const children = object.children;
|
|
const children = object.children;
|
|
|
|
|
|
for ( let i = 0, l = children.length; i < l; i ++ ) {
|
|
for ( let i = 0, l = children.length; i < l; i ++ ) {
|
|
@@ -1204,6 +1303,16 @@ class Renderer {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ _renderBundles( bundles, sceneRef, lightsNode ) {
|
|
|
|
+
|
|
|
|
+ for ( const bundle of bundles ) {
|
|
|
|
+
|
|
|
|
+ this._renderBundle( bundle, sceneRef, lightsNode );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
_renderObjects( renderList, camera, scene, lightsNode ) {
|
|
_renderObjects( renderList, camera, scene, lightsNode ) {
|
|
|
|
|
|
// process renderable objects
|
|
// process renderable objects
|
|
@@ -1397,8 +1506,25 @@ class Renderer {
|
|
|
|
|
|
//
|
|
//
|
|
|
|
|
|
|
|
+ if ( this._currentRenderBundle !== null && this._currentRenderBundle.needsUpdate === true ) {
|
|
|
|
+
|
|
|
|
+ const renderObjectData = this.backend.get( renderObject );
|
|
|
|
+
|
|
|
|
+ renderObjectData.bundleEncoder = undefined;
|
|
|
|
+ renderObjectData.lastPipelineGPU = undefined;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
this.backend.draw( renderObject, this.info );
|
|
this.backend.draw( renderObject, this.info );
|
|
|
|
|
|
|
|
+ if ( this._currentRenderBundle !== null ) {
|
|
|
|
+
|
|
|
|
+ const renderContextData = this.backend.get( this._currentRenderContext );
|
|
|
|
+
|
|
|
|
+ renderContextData.renderObjects.push( renderObject );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
_createObjectPipeline( object, material, scene, camera, lightsNode, passId ) {
|
|
_createObjectPipeline( object, material, scene, camera, lightsNode, passId ) {
|