|
|
@@ -46,6 +46,7 @@ const refreshUniforms = [
|
|
|
'normalMap',
|
|
|
'normalScale',
|
|
|
'opacity',
|
|
|
+ 'retroreflective',
|
|
|
'roughness',
|
|
|
'roughnessMap',
|
|
|
'sheen',
|
|
|
@@ -195,6 +196,7 @@ class NodeMaterialObserver {
|
|
|
|
|
|
data = {
|
|
|
geometryId: geometry.id,
|
|
|
+ materialVersion: this.getMaterialData( renderObject.material )._version,
|
|
|
worldMatrix: object.matrixWorld.clone()
|
|
|
};
|
|
|
|
|
|
@@ -335,7 +337,7 @@ class NodeMaterialObserver {
|
|
|
|
|
|
if ( data === undefined ) {
|
|
|
|
|
|
- data = { _renderId: -1, _equal: false };
|
|
|
+ data = { _renderId: -1, _version: 0 };
|
|
|
|
|
|
for ( const property of this.refreshUniforms ) {
|
|
|
|
|
|
@@ -399,19 +401,21 @@ class NodeMaterialObserver {
|
|
|
|
|
|
const materialData = this.getMaterialData( renderObject.material );
|
|
|
|
|
|
- // check the material for the "equal" state just once per render for all render objects
|
|
|
+ // check the material properties just once per render for all render objects
|
|
|
|
|
|
if ( materialData._renderId !== renderId ) {
|
|
|
|
|
|
materialData._renderId = renderId;
|
|
|
|
|
|
+ let changed = false;
|
|
|
+
|
|
|
for ( const property in materialData ) {
|
|
|
|
|
|
const value = materialData[ property ];
|
|
|
const mtlValue = material[ property ];
|
|
|
|
|
|
if ( property === '_renderId' ) continue;
|
|
|
- if ( property === '_equal' ) continue;
|
|
|
+ if ( property === '_version' ) continue;
|
|
|
|
|
|
if ( value.equals !== undefined ) {
|
|
|
|
|
|
@@ -419,8 +423,7 @@ class NodeMaterialObserver {
|
|
|
|
|
|
value.copy( mtlValue );
|
|
|
|
|
|
- materialData._equal = false;
|
|
|
- return false;
|
|
|
+ changed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -431,8 +434,7 @@ class NodeMaterialObserver {
|
|
|
value.id = mtlValue.id;
|
|
|
value.version = mtlValue.version;
|
|
|
|
|
|
- materialData._equal = false;
|
|
|
- return false;
|
|
|
+ changed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -440,34 +442,38 @@ class NodeMaterialObserver {
|
|
|
|
|
|
materialData[ property ] = mtlValue;
|
|
|
|
|
|
- materialData._equal = false;
|
|
|
- return false;
|
|
|
+ changed = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( materialData.transmission > 0 ) {
|
|
|
+ if ( changed === true ) materialData._version ++;
|
|
|
|
|
|
- const { width, height } = renderObject.context;
|
|
|
+ }
|
|
|
|
|
|
- if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) {
|
|
|
+ // a version mismatch means the material has changed since this render object was last refreshed
|
|
|
|
|
|
- renderObjectData.bufferWidth = width;
|
|
|
- renderObjectData.bufferHeight = height;
|
|
|
+ if ( renderObjectData.materialVersion !== materialData._version ) {
|
|
|
|
|
|
- materialData._equal = false;
|
|
|
- return false;
|
|
|
+ renderObjectData.materialVersion = materialData._version;
|
|
|
|
|
|
- }
|
|
|
+ return false;
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- materialData._equal = true;
|
|
|
+ if ( materialData.transmission > 0 ) {
|
|
|
|
|
|
- } else {
|
|
|
+ const { width, height } = renderObject.context;
|
|
|
|
|
|
- if ( materialData._equal === false ) return false;
|
|
|
+ if ( renderObjectData.bufferWidth !== width || renderObjectData.bufferHeight !== height ) {
|
|
|
+
|
|
|
+ renderObjectData.bufferWidth = width;
|
|
|
+ renderObjectData.bufferHeight = height;
|
|
|
+
|
|
|
+ return false;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -22883,15 +22889,24 @@ class Line2NodeMaterial extends NodeMaterial {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Setups the position in clip space for the vertex stage of the fat line.
|
|
|
- * Overrides the default model-view-projection to return the expanded fat line vertex coordinates.
|
|
|
+ * Setups the position of the expanded fat line vertex in local space.
|
|
|
*
|
|
|
* @param {NodeBuilder} builder - The current node builder.
|
|
|
- * @return {Node<vec4>} The position of the fat line vertex in clip space.
|
|
|
+ * @return {Node<vec3>} The position of the fat line vertex in local space.
|
|
|
*/
|
|
|
- setupModelViewProjection( /*builder*/ ) {
|
|
|
+ setupPosition( builder ) {
|
|
|
+
|
|
|
+ const localPosition = modelWorldMatrixInverse.mul( cameraWorldMatrix ).mul( cameraProjectionMatrixInverse ).mul( mvpLine );
|
|
|
+
|
|
|
+ positionLocal.assign( localPosition.xyz.div( localPosition.w ) );
|
|
|
|
|
|
- return mvpLine;
|
|
|
+ if ( builder.needsPreviousData() ) {
|
|
|
+
|
|
|
+ positionPrevious.assign( positionLocal );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return super.setupPosition( builder );
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -48276,8 +48291,8 @@ const mx_heighttonormal = ( input, scale/*, texcoord*/ ) => {
|
|
|
const getParallaxCorrectNormal = /*@__PURE__*/ Fn( ( [ normal, cubeSize, cubePos ] ) => {
|
|
|
|
|
|
const nDir = normalize( normal ).toVar();
|
|
|
- const rbmax = sub( float( 0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar();
|
|
|
- const rbmin = sub( float( -0.5 ).mul( cubeSize.sub( cubePos ) ), positionWorld ).div( nDir ).toVar();
|
|
|
+ const rbmax = cubeSize.mul( 0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar();
|
|
|
+ const rbmin = cubeSize.mul( -0.5 ).add( cubePos ).sub( positionWorld ).div( nDir ).toVar();
|
|
|
const rbminmax = vec3().toVar();
|
|
|
rbminmax.x = nDir.x.greaterThan( float( 0 ) ).select( rbmax.x, rbmin.x );
|
|
|
rbminmax.y = nDir.y.greaterThan( float( 0 ) ).select( rbmax.y, rbmin.y );
|
|
|
@@ -69830,12 +69845,29 @@ class WebGLTextureUtils {
|
|
|
|
|
|
if ( texture.isCompressedArrayTexture ) {
|
|
|
|
|
|
-
|
|
|
if ( texture.format !== gl.RGBA ) {
|
|
|
|
|
|
if ( glFormat !== null ) {
|
|
|
|
|
|
- gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data );
|
|
|
+ if ( texture.layerUpdates.size > 0 ) {
|
|
|
+
|
|
|
+ const layerByteLength = getByteLength( mipmap.width, mipmap.height, texture.format, texture.type );
|
|
|
+
|
|
|
+ for ( const layerIndex of texture.layerUpdates ) {
|
|
|
+
|
|
|
+ const layerData = mipmap.data.subarray(
|
|
|
+ layerIndex * layerByteLength / mipmap.data.BYTES_PER_ELEMENT,
|
|
|
+ ( layerIndex + 1 ) * layerByteLength / mipmap.data.BYTES_PER_ELEMENT
|
|
|
+ );
|
|
|
+ gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, layerData );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
@@ -69865,6 +69897,7 @@ class WebGLTextureUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ if ( texture.isCompressedArrayTexture && texture.layerUpdates.size > 0 ) texture.clearLayerUpdates();
|
|
|
|
|
|
} else if ( texture.isCubeTexture ) {
|
|
|
|