diff --git a/manual/examples/scenegraph-tank.html b/manual/examples/scenegraph-tank.html index fff2cfe110f588..53828bc4c31d03 100644 --- a/manual/examples/scenegraph-tank.html +++ b/manual/examples/scenegraph-tank.html @@ -275,8 +275,8 @@ targetBob.position.y = Math.sin( time * 2 ) * 4; targetMesh.rotation.x = time * 7; targetMesh.rotation.y = time * 13; - targetMaterial.emissive.setHSL( time * 10 % 1, 1, .25 ); - targetMaterial.color.setHSL( time * 10 % 1, 1, .25 ); + targetMaterial.emissive.setHSL( time * 0.3 % 1, 1, .25 ); + targetMaterial.color.setHSL( time * 0.3 % 1, 1, .25 ); // move tank const tankTime = time * .05; diff --git a/manual/pages/scenegraph.html b/manual/pages/scenegraph.html index 72ab47a76a2d85..22c65c7d3901af 100644 --- a/manual/pages/scenegraph.html +++ b/manual/pages/scenegraph.html @@ -385,8 +385,8 @@
For the tank there's an Object3D called tank which is used to move everything
below it around. The code uses a SplineCurve which it can ask for positions
diff --git a/src/core/RenderTarget.js b/src/core/RenderTarget.js
index 98b93a6d4a0967..660e6aa569f3d7 100644
--- a/src/core/RenderTarget.js
+++ b/src/core/RenderTarget.js
@@ -334,8 +334,8 @@ class RenderTarget extends EventDispatcher {
set depthTexture( current ) {
- if ( this._depthTexture !== null ) this._depthTexture.renderTarget = null;
- if ( current !== null ) current.renderTarget = this;
+ if ( this._depthTexture !== null && this._depthTexture.renderTarget === this ) this._depthTexture.renderTarget = null;
+ if ( current !== null && current.renderTarget === null ) current.renderTarget = this;
this._depthTexture = current;
@@ -453,7 +453,22 @@ class RenderTarget extends EventDispatcher {
this.storeMultisampledDepthBuffer = source.storeMultisampledDepthBuffer;
this.storeMultisampledStencilBuffer = source.storeMultisampledStencilBuffer;
- if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
+ if ( source.depthTexture !== null ) {
+
+ if ( source.depthTexture.renderTarget === source ) {
+
+ const depthTexture = source.depthTexture.clone();
+ depthTexture.renderTarget = null;
+
+ this.depthTexture = depthTexture;
+
+ } else {
+
+ this.depthTexture = source.depthTexture;
+
+ }
+
+ }
this.samples = source.samples;
this.multiview = source.multiview;
diff --git a/src/nodes/display/PassNode.js b/src/nodes/display/PassNode.js
index cc827a55cb82a6..48bddcc4b8ae04 100644
--- a/src/nodes/display/PassNode.js
+++ b/src/nodes/display/PassNode.js
@@ -250,7 +250,7 @@ class PassNode extends TempNode {
if ( this.scope === PassNode.DEPTH || options.depthBuffer !== false ) {
- depthTexture = new DepthTexture();
+ depthTexture = options.depthTexture || new DepthTexture();
depthTexture.isRenderTargetTexture = true;
//depthTexture.type = FloatType;
depthTexture.name = 'depth';
@@ -289,6 +289,38 @@ class PassNode extends TempNode {
*/
this.opaque = true;
+ /**
+ * Whether the renderer should automatically clear before rendering the pass.
+ *
+ * @type {boolean}
+ * @default true
+ */
+ this.autoClear = options.autoClear !== undefined ? options.autoClear : true;
+
+ /**
+ * Whether the color buffer should be cleared.
+ *
+ * @type {boolean}
+ * @default true
+ */
+ this.autoClearColor = options.autoClearColor !== undefined ? options.autoClearColor : true;
+
+ /**
+ * Whether the depth buffer should be cleared.
+ *
+ * @type {boolean}
+ * @default true
+ */
+ this.autoClearDepth = options.autoClearDepth !== undefined ? options.autoClearDepth : true;
+
+ /**
+ * Whether the stencil buffer should be cleared.
+ *
+ * @type {boolean}
+ * @default true
+ */
+ this.autoClearStencil = options.autoClearStencil !== undefined ? options.autoClearStencil : true;
+
/**
* An optional global context for the pass.
*
@@ -807,6 +839,9 @@ class PassNode extends TempNode {
const currentRenderTarget = renderer.getRenderTarget();
const currentMRT = renderer.getMRT();
const currentAutoClear = renderer.autoClear;
+ const currentAutoClearColor = renderer.autoClearColor;
+ const currentAutoClearDepth = renderer.autoClearDepth;
+ const currentAutoClearStencil = renderer.autoClearStencil;
const currentTransparent = renderer.transparent;
const currentOpaque = renderer.opaque;
const currentMask = camera.layers.mask;
@@ -836,7 +871,10 @@ class PassNode extends TempNode {
renderer.setRenderTarget( this.renderTarget );
renderer.setMRT( this._mrt );
- renderer.autoClear = true;
+ renderer.autoClear = this.autoClear;
+ renderer.autoClearColor = this.autoClearColor;
+ renderer.autoClearDepth = this.autoClearDepth;
+ renderer.autoClearStencil = this.autoClearStencil;
renderer.transparent = this.transparent;
renderer.opaque = this.opaque;
@@ -867,6 +905,9 @@ class PassNode extends TempNode {
renderer.setRenderTarget( currentRenderTarget );
renderer.setMRT( currentMRT );
renderer.autoClear = currentAutoClear;
+ renderer.autoClearColor = currentAutoClearColor;
+ renderer.autoClearDepth = currentAutoClearDepth;
+ renderer.autoClearStencil = currentAutoClearStencil;
renderer.transparent = currentTransparent;
renderer.opaque = currentOpaque;
renderer.contextNode = currentContextNode;
diff --git a/src/nodes/functions/PhysicalLightingModel.js b/src/nodes/functions/PhysicalLightingModel.js
index 79275d13ec4294..4f1e5e459a0353 100644
--- a/src/nodes/functions/PhysicalLightingModel.js
+++ b/src/nodes/functions/PhysicalLightingModel.js
@@ -473,6 +473,14 @@ class PhysicalLightingModel extends LightingModel {
*/
this.iridescenceF0Metallic = null;
+ /**
+ * The multi-scattering energy compensation for direct lighting.
+ *
+ * @type {?Node}
+ * @default null
+ */
+ this.multiScatteringCompensation = null;
+
}
/**
@@ -557,6 +565,18 @@ class PhysicalLightingModel extends LightingModel {
}
+ // Multi-scattering energy compensation for direct lighting
+ // Based on "Practical Multiple Scattering Compensation for Microfacet Models"
+ // https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf
+ const dotNV = normalView.dot( positionViewDirection ).clamp();
+ const fab = DFGLUT( { roughness, dotNV } );
+
+ // Energy of the single-scattering lobe in a white furnace ( F0 = F90 = 1 )
+ const Ess = fab.x.add( fab.y );
+
+ // Compensate for the energy lost to multiple scattering, tinting the added term by F0 ( equation 16 )
+ this.multiScatteringCompensation = specularColorBlended.mul( Ess.reciprocal().sub( 1.0 ) ).add( 1.0 ).toConst( 'multiScatteringCompensation' );
+
super.start( builder );
}
@@ -639,19 +659,7 @@ class PhysicalLightingModel extends LightingModel {
}
- // Multi-scattering energy compensation for direct lighting
- // Based on "Practical Multiple Scattering Compensation for Microfacet Models"
- // https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf
- const dotNV = normalView.dot( positionViewDirection ).clamp();
- const fab = DFGLUT( { roughness, dotNV } );
-
- // Energy of the single-scattering lobe in a white furnace ( F0 = F90 = 1 )
- const Ess = fab.x.add( fab.y );
-
- // Compensate for the energy lost to multiple scattering, tinting the added term by F0 ( equation 16 )
- const energyCompensation = specularColorBlended.mul( Ess.reciprocal().sub( 1.0 ) ).add( 1.0 );
-
- reflectedLight.directSpecular.addAssign( irradiance.mul( specularBRDF ).mul( energyCompensation ) );
+ reflectedLight.directSpecular.addAssign( irradiance.mul( specularBRDF ).mul( this.multiScatteringCompensation ) );
}
diff --git a/src/renderers/common/Info.js b/src/renderers/common/Info.js
index 1704c10fa712e3..1374caaefb5ff3 100644
--- a/src/renderers/common/Info.js
+++ b/src/renderers/common/Info.js
@@ -139,10 +139,10 @@ class Info {
/**
* Map for storing calculated byte sizes of tracked objects.
*
- * @type {Map