Socket
Socket
Sign inDemoInstall

three

Package Overview
Dependencies
0
Maintainers
2
Versions
284
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.154.0 to 0.155.0

examples/jsm/nodes/display/BumpMapNode.js

164

examples/jsm/controls/OrbitControls.js

@@ -8,3 +8,6 @@ import {

Vector2,
Vector3
Vector3,
Plane,
Ray,
MathUtils
} from 'three';

@@ -22,2 +25,5 @@

const _endEvent = { type: 'end' };
const _ray = new Ray();
const _plane = new Plane();
const TILT_LIMIT = Math.cos( 70 * MathUtils.DEG2RAD );

@@ -77,2 +83,3 @@ class OrbitControls extends EventDispatcher {

this.keyPanSpeed = 7.0; // pixels moved per arrow key push
this.zoomToCursor = false;

@@ -236,7 +243,2 @@ // Set to true to automatically rotate around the target

spherical.radius *= scale;
// restrict radius to be between desired limits
spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
// move target to panned location

@@ -254,2 +256,15 @@

// adjust the camera position based on zoom only if we're not zooming to the cursor or if it's an ortho camera
// we adjust zoom later in these cases
if ( scope.zoomToCursor && performCursorZoom || scope.object.isOrthographicCamera ) {
spherical.radius = clampDistance( spherical.radius );
} else {
spherical.radius = clampDistance( spherical.radius * scale );
}
offset.setFromSpherical( spherical );

@@ -279,3 +294,87 @@

// adjust camera position
let zoomChanged = false;
if ( scope.zoomToCursor && performCursorZoom ) {
let newRadius = null;
if ( scope.object.isPerspectiveCamera ) {
// move the camera down the pointer ray
// this method avoids floating point error
const prevRadius = offset.length();
newRadius = clampDistance( prevRadius * scale );
const radiusDelta = prevRadius - newRadius;
scope.object.position.addScaledVector( dollyDirection, radiusDelta );
scope.object.updateMatrixWorld();
} else if ( scope.object.isOrthographicCamera ) {
// adjust the ortho camera position based on zoom changes
const mouseBefore = new Vector3( mouse.x, mouse.y, 0 );
mouseBefore.unproject( scope.object );
scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
scope.object.updateProjectionMatrix();
zoomChanged = true;
const mouseAfter = new Vector3( mouse.x, mouse.y, 0 );
mouseAfter.unproject( scope.object );
scope.object.position.sub( mouseAfter ).add( mouseBefore );
scope.object.updateMatrixWorld();
newRadius = offset.length();
} else {
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled.' );
scope.zoomToCursor = false;
}
// handle the placement of the target
if ( newRadius !== null ) {
if ( this.screenSpacePanning ) {
// position the orbit target in front of the new camera position
scope.target.set( 0, 0, - 1 )
.transformDirection( scope.object.matrix )
.multiplyScalar( newRadius )
.add( scope.object.position );
} else {
// get the ray and translation plane to compute target
_ray.origin.copy( scope.object.position );
_ray.direction.set( 0, 0, - 1 ).transformDirection( scope.object.matrix );
// if the camera is 20 degrees above the horizon then don't adjust the focus target to avoid
// extremely large values
if ( Math.abs( scope.object.up.dot( _ray.direction ) ) < TILT_LIMIT ) {
object.lookAt( scope.target );
} else {
_plane.setFromNormalAndCoplanarPoint( scope.object.up, scope.target );
_ray.intersectPlane( _plane, scope.target );
}
}
}
} else if ( scope.object.isOrthographicCamera ) {
scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / scale ) );
scope.object.updateProjectionMatrix();
zoomChanged = true;
}
scale = 1;
performCursorZoom = false;

@@ -359,3 +458,2 @@ // update condition is:

const panOffset = new Vector3();
let zoomChanged = false;

@@ -374,2 +472,6 @@ const rotateStart = new Vector2();

const dollyDirection = new Vector3();
const mouse = new Vector2();
let performCursorZoom = false;
const pointers = [];

@@ -485,12 +587,6 @@ const pointerPositions = {};

if ( scope.object.isPerspectiveCamera ) {
if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {
scale /= dollyScale;
} else if ( scope.object.isOrthographicCamera ) {
scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
scope.object.updateProjectionMatrix();
zoomChanged = true;
} else {

@@ -507,12 +603,6 @@

if ( scope.object.isPerspectiveCamera ) {
if ( scope.object.isPerspectiveCamera || scope.object.isOrthographicCamera ) {
scale *= dollyScale;
} else if ( scope.object.isOrthographicCamera ) {
scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
scope.object.updateProjectionMatrix();
zoomChanged = true;
} else {

@@ -527,2 +617,31 @@

function updateMouseParameters( event ) {
if ( ! scope.zoomToCursor ) {
return;
}
performCursorZoom = true;
const rect = scope.domElement.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const w = rect.width;
const h = rect.height;
mouse.x = ( x / w ) * 2 - 1;
mouse.y = - ( y / h ) * 2 + 1;
dollyDirection.set( mouse.x, mouse.y, 1 ).unproject( object ).sub( object.position ).normalize();
}
function clampDistance( dist ) {
return Math.max( scope.minDistance, Math.min( scope.maxDistance, dist ) );
}
//

@@ -540,2 +659,3 @@ // event callbacks - update the object state

updateMouseParameters( event );
dollyStart.set( event.clientX, event.clientY );

@@ -607,2 +727,4 @@

updateMouseParameters( event );
if ( event.deltaY < 0 ) {

@@ -609,0 +731,0 @@

2

examples/jsm/environments/RoomEnvironment.js

@@ -29,3 +29,3 @@ /**

if ( renderer !== null && renderer.useLegacyLights === false ) intensity = 900;
if ( renderer !== null && renderer._useLegacyLights === false ) intensity = 900;

@@ -32,0 +32,0 @@ const mainLight = new PointLight( 0xffffff, intensity, 28, 2 );

@@ -168,2 +168,3 @@ import * as THREE from 'three';

}
defaultPrim = "Root"
metersPerUnit = 1

@@ -170,0 +171,0 @@ upAxis = "Y"

@@ -18,5 +18,8 @@ import { Vector2 } from 'three';

this.isDown = false;
this.enabled = true;
this.onPointerDown = function ( event ) {
if ( this.enabled === false ) return;
this.isDown = true;

@@ -29,2 +32,4 @@ this.onSelectStart( event );

if ( this.enabled === false ) return;
if ( this.isDown ) {

@@ -40,2 +45,4 @@

if ( this.enabled === false ) return;
this.isDown = false;

@@ -42,0 +49,0 @@ this.onSelectOver();

@@ -17,2 +17,3 @@ /**

CompressedArrayTexture,
CompressedCubeTexture,
Data3DTexture,

@@ -265,6 +266,3 @@ DataTexture,

texture = new CompressedTexture();
texture.image = faces;
texture.format = format;
texture.type = UnsignedByteType;
texture = new CompressedCubeTexture( faces, format, UnsignedByteType );

@@ -322,2 +320,3 @@ } else {

texture.mipmaps = mipmaps.map( dt => {
return {

@@ -329,2 +328,3 @@ data: dt.source.data,

};
} );

@@ -331,0 +331,0 @@ return texture;

@@ -770,3 +770,3 @@ import {

} catch {
} catch ( _ ) {

@@ -773,0 +773,0 @@ continue;

@@ -476,6 +476,6 @@ import {

volume.inverseMatrix.copy( volume.matrix ).invert();
volume.RASDimensions = [
Math.floor( volume.xLength * spacingX ),
Math.floor( volume.yLength * spacingY ),
Math.floor( volume.xLength * spacingX ),
Math.floor( volume.yLength * spacingY ),
Math.floor( volume.zLength * spacingZ )

@@ -482,0 +482,0 @@ ];

@@ -709,3 +709,3 @@ import {

return { headerText: lines.join( '\r' ) + '\r', headerLength: i };
return { headerText: lines.join( '\r' ) + '\r', headerLength: i };

@@ -712,0 +712,0 @@ }

@@ -28,3 +28,3 @@ import {

console.error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' );
throw new Error( 'THREE.TGALoader: Invalid type colormap data for indexed type.' );

@@ -43,3 +43,3 @@ }

console.error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' );
throw new Error( 'THREE.TGALoader: Invalid type colormap data for colormap type.' );

@@ -53,3 +53,3 @@ }

case TGA_TYPE_NO_DATA:
console.error( 'THREE.TGALoader: No data.' );
throw new Error( 'THREE.TGALoader: No data.' );

@@ -59,3 +59,3 @@ // Invalid type ?

default:
console.error( 'THREE.TGALoader: Invalid type "%s".', header.image_type );
throw new Error( 'THREE.TGALoader: Invalid type ' + header.image_type );

@@ -68,3 +68,3 @@ }

console.error( 'THREE.TGALoader: Invalid image size.' );
throw new Error( 'THREE.TGALoader: Invalid image size.' );

@@ -78,3 +78,3 @@ }

console.error( 'THREE.TGALoader: Invalid pixel size "%s".', header.pixel_size );
throw new Error( 'THREE.TGALoader: Invalid pixel size ' + header.pixel_size );

@@ -374,3 +374,3 @@ }

default:
console.error( 'THREE.TGALoader: Format not supported.' );
throw new Error( 'THREE.TGALoader: Format not supported.' );
break;

@@ -401,3 +401,3 @@

default:
console.error( 'THREE.TGALoader: Format not supported.' );
throw new Error( 'THREE.TGALoader: Format not supported.' );
break;

@@ -433,3 +433,3 @@

if ( buffer.length < 19 ) console.error( 'THREE.TGALoader: Not enough data to contain header.' );
if ( buffer.length < 19 ) throw new Error( 'THREE.TGALoader: Not enough data to contain header.' );

@@ -462,3 +462,3 @@ let offset = 0;

console.error( 'THREE.TGALoader: No data.' );
throw new Error( 'THREE.TGALoader: No data.' );

@@ -465,0 +465,0 @@ }

@@ -6,6 +6,4 @@ import {

FloatType,
LinearSRGBColorSpace,
Mesh,
NearestFilter,
NoToneMapping,
PlaneGeometry,

@@ -404,10 +402,5 @@ RGBAFormat,

const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
const currentOutputColorSpace = renderer.outputColorSpace;
const currentToneMapping = renderer.toneMapping;
renderer.xr.enabled = false; // Avoid camera modification
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
renderer.outputColorSpace = LinearSRGBColorSpace;
renderer.toneMapping = NoToneMapping;
mesh.material = material;

@@ -420,4 +413,2 @@ renderer.setRenderTarget( output );

renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
renderer.outputColorSpace = currentOutputColorSpace;
renderer.toneMapping = currentToneMapping;

@@ -424,0 +415,0 @@ renderer.setRenderTarget( currentRenderTarget );

@@ -343,7 +343,4 @@ import {

if ( ! this.segmentation ) {
let iLength, jLength;
if( ! this.segmentation ) {
firstDirection.applyMatrix4( volume.inverseMatrix ).normalize();

@@ -354,6 +351,7 @@ secondDirection.applyMatrix4( volume.inverseMatrix ).normalize();

}
firstDirection.arglet = 'i';
secondDirection.arglet = 'j';
iLength = Math.floor( Math.abs( firstDirection.dot( dimensions ) ) );
jLength = Math.floor( Math.abs( secondDirection.dot( dimensions ) ) );
const iLength = Math.floor( Math.abs( firstDirection.dot( dimensions ) ) );
const jLength = Math.floor( Math.abs( secondDirection.dot( dimensions ) ) );
const planeWidth = Math.abs( iLength * firstSpacing );

@@ -360,0 +358,0 @@ const planeHeight = Math.abs( jLength * secondSpacing );

@@ -32,3 +32,3 @@ import InputNode from '../core/InputNode.js';

const buffer = new InterleavedBuffer( array, stride );
const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride );
const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset );

@@ -35,0 +35,0 @@

@@ -29,2 +29,4 @@ import TextureNode from './TextureNode.js';

setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode
generate( builder, output ) {

@@ -31,0 +33,0 @@

@@ -7,2 +7,3 @@ // @TODO: Is this needed? Can it be moved in MaterialNode?

import { normalMap } from '../display/NormalMapNode.js';
import { bumpMap } from '../display/BumpMapNode.js';
import { addNodeClass } from '../core/Node.js';

@@ -43,4 +44,16 @@ import { nodeImmutable } from '../shadernode/ShaderNode.js';

node = material.normalMap ? normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) ) : normalView;
if ( material.normalMap ) {
node = normalMap( this.getTexture( 'normalMap' ), materialReference( 'normalScale', 'vec2' ) );
} else if ( material.bumpMap ) {
node = bumpMap( material.bumpMap, materialReference( 'bumpScale', 'float' ) );
} else {
node = normalView;
}
} else if ( scope === ExtendedMaterialNode.CLEARCOAT_NORMAL ) {

@@ -47,0 +60,0 @@

@@ -6,3 +6,3 @@ import Node, { addNodeClass } from '../core/Node.js';

import { nodeProxy, vec3, mat3, mat4 } from '../shadernode/ShaderNode.js';
import { DynamicDrawUsage } from 'three';
import { DynamicDrawUsage, InstancedInterleavedBuffer } from 'three';

@@ -28,13 +28,13 @@ class InstanceNode extends Node {

const instanceMesh = this.instanceMesh;
const instaceAttribute = instanceMesh.instanceMatrix;
const array = instaceAttribute.array;
const instanceAttribute = instanceMesh.instanceMatrix;
const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 );
const bufferFn = instaceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute;
const instanceBuffers = [
// F.Signature -> bufferAttribute( array, type, stride, offset )
bufferFn( array, 'vec4', 16, 0 ),
bufferFn( array, 'vec4', 16, 4 ),
bufferFn( array, 'vec4', 16, 8 ),
bufferFn( array, 'vec4', 16, 12 )
bufferFn( buffer, 'vec4', 16, 0 ),
bufferFn( buffer, 'vec4', 16, 4 ),
bufferFn( buffer, 'vec4', 16, 8 ),
bufferFn( buffer, 'vec4', 16, 12 )
];

@@ -41,0 +41,0 @@

import Node, { addNodeClass } from '../core/Node.js';
import { reference } from './ReferenceNode.js';
import { materialReference } from './MaterialReferenceNode.js';
import { nodeImmutable } from '../shadernode/ShaderNode.js';
import { nodeImmutable, float } from '../shadernode/ShaderNode.js';

@@ -15,27 +16,2 @@ class MaterialNode extends Node {

getNodeType( builder ) {
const scope = this.scope;
const material = builder.context.material;
if ( scope === MaterialNode.COLOR ) {
return material.map !== null ? 'vec4' : 'vec3';
} else if ( scope === MaterialNode.OPACITY || scope === MaterialNode.ROTATION ) {
return 'float';
} else if ( scope === MaterialNode.EMISSIVE || scope === MaterialNode.SHEEN ) {
return 'vec3';
} else if ( scope === MaterialNode.ROUGHNESS || scope === MaterialNode.METALNESS || scope === MaterialNode.SPECULAR || scope === MaterialNode.SHININESS || scope === MaterialNode.CLEARCOAT_ROUGHNESS || scope === MaterialNode.SHEEN_ROUGHNESS ) {
return 'float';
}
}
getFloat( property ) {

@@ -74,6 +50,10 @@

if ( scope === MaterialNode.ALPHA_TEST ) {
if ( scope === MaterialNode.ALPHA_TEST || scope === MaterialNode.SHININESS || scope === MaterialNode.REFLECTIVITY || scope === MaterialNode.ROTATION || scope === MaterialNode.IRIDESCENCE || scope === MaterialNode.IRIDESCENCE_IOR ) {
node = this.getFloat( 'alphaTest' );
node = this.getFloat( scope );
} else if ( scope === MaterialNode.SPECULAR_COLOR ) {
node = this.getColor( 'specular' );
} else if ( scope === MaterialNode.COLOR ) {

@@ -107,21 +87,11 @@

} else if ( scope === MaterialNode.SHININESS ) {
} else if ( scope === MaterialNode.SPECULAR_STRENGTH ) {
node = this.getFloat( 'shininess' );
} else if ( scope === MaterialNode.SPECULAR_COLOR ) {
node = this.getColor( 'specular' );
} else if ( scope === MaterialNode.REFLECTIVITY ) {
const reflectivityNode = this.getFloat( 'reflectivity' );
if ( material.specularMap && material.specularMap.isTexture === true ) {
node = reflectivityNode.mul( this.getTexture( 'specularMap' ).r );
node = this.getTexture( 'specularMap' ).r;
} else {
node = reflectivityNode;
node = float( 1 );

@@ -230,6 +200,18 @@ }

} else if ( scope === MaterialNode.ROTATION ) {
} else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) {
node = this.getFloat( 'rotation' );
const iridescenceThicknessMaximum = reference( 1, 'float', material.iridescenceThicknessRange );
if ( material.iridescenceThicknessMap ) {
const iridescenceThicknessMinimum = reference( 0, 'float', material.iridescenceThicknessRange );
node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( 'iridescenceThicknessMap' ).g ).add( iridescenceThicknessMinimum );
} else {
node = iridescenceThicknessMaximum;
}
} else {

@@ -253,3 +235,4 @@

MaterialNode.SHININESS = 'shininess';
MaterialNode.SPECULAR_COLOR = 'specularColor';
MaterialNode.SPECULAR = 'specular';
MaterialNode.SPECULAR_STRENGTH = 'specularStrength';
MaterialNode.REFLECTIVITY = 'reflectivity';

@@ -264,2 +247,5 @@ MaterialNode.ROUGHNESS = 'roughness';

MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness';
MaterialNode.IRIDESCENCE = 'iridescence';
MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR';
MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness';

@@ -274,2 +260,3 @@ export default MaterialNode;

export const materialSpecularColor = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR );
export const materialSpecularStrength = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH );
export const materialReflectivity = nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY );

@@ -283,3 +270,6 @@ export const materialRoughness = nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS );

export const materialSheenRoughness = nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS );
export const materialIridescence = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE );
export const materialIridescenceIOR = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR );
export const materialIridescenceThickness = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS );
addNodeClass( MaterialNode );

@@ -28,2 +28,6 @@ import Node from '../core/Node.js';

} else if ( scope === SceneNode.BACKGROUND_INTENSITY ) {
output = reference( 'backgroundIntensity', 'float', scene );
} else {

@@ -42,2 +46,3 @@

SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness';
SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity';

@@ -47,3 +52,4 @@ export default SceneNode;

export const backgroundBlurriness = nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS );
export const backgroundIntensity = nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY );
addNodeClass( SceneNode );

@@ -8,3 +8,3 @@ import UniformNode, { uniform } from '../core/UniformNode.js';

import { addNodeClass } from '../core/Node.js';
import { addNodeElement, nodeProxy, vec3 } from '../shadernode/ShaderNode.js';
import { addNodeElement, nodeProxy, vec3, nodeObject } from '../shadernode/ShaderNode.js';
import { NodeUpdateType } from '../core/constants.js';

@@ -14,3 +14,3 @@

constructor( value, uvNode = null, levelNode = null ) {
constructor( value, uvNode = null, levelNode = null, compareNode = null ) {

@@ -23,5 +23,9 @@ super( value );

this.levelNode = levelNode;
this.compareNode = compareNode;
this.updateType = NodeUpdateType.FRAME;
this.updateMatrix = false;
this.updateType = NodeUpdateType.NONE;
this.setUpdateMatrix( uvNode === null );
}

@@ -51,8 +55,23 @@

return uv( this.value.channel );
}
getTextureMatrix( uvNode ) {
const texture = this.value;
return uniform( texture.matrix ).mul( vec3( uv( texture.channel ), 1 ) );
return uniform( texture.matrix ).mul( vec3( uvNode, 1 ) ).xy;
}
setUpdateMatrix( value ) {
this.updateMatrix = value;
this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE;
return this;
}
construct( builder ) {

@@ -72,4 +91,10 @@

uvNode || ( uvNode = this.getDefaultUV() );
if ( ! uvNode ) uvNode = this.getDefaultUV();
if ( this.updateMatrix ) {
uvNode = this.getTextureMatrix( uvNode );
}
//

@@ -96,2 +121,3 @@

const compareNode = this.compareNode;
const texture = this.value;

@@ -137,2 +163,8 @@

} else if ( compareNode !== null ) {
const compareSnippet = compareNode.build( builder, 'float' );
snippet = builder.getTextureCompare( texture, textureProperty, uvSnippet, compareSnippet );
} else {

@@ -170,3 +202,3 @@

return textureNode;
return nodeObject( textureNode );

@@ -192,2 +224,11 @@ }

compare( compareNode ) {
const textureNode = this.clone();
textureNode.compareNode = nodeObject( compareNode );
return nodeObject( textureNode );
}
serialize( data ) {

@@ -223,3 +264,3 @@

return new this.constructor( this.value, this.uvNode, this.levelNode );
return new this.constructor( this.value, this.uvNode, this.levelNode, this.compareNode );

@@ -226,0 +267,0 @@ }

class LightingModel {
constructor( init = null, direct = null, indirectDiffuse = null, indirectSpecular = null, ambientOcclusion = null ) {
init( /*input, stack, builder*/ ) { }
this.init = init;
this.direct = direct;
this.indirectDiffuse = indirectDiffuse;
this.indirectSpecular = indirectSpecular;
this.ambientOcclusion = ambientOcclusion;
direct( /*input, stack, builder*/ ) { }
}
indirectDiffuse( /*input, stack, builder*/ ) { }
indirectSpecular( /*input, stack, builder*/ ) { }
ambientOcclusion( /*input, stack, builder*/ ) { }
}
export default LightingModel;
export const lightingModel = ( ...params ) => new LightingModel( ...params );

@@ -0,1 +1,2 @@

import { EventDispatcher } from 'three';
import { NodeUpdateType } from './constants.js';

@@ -9,7 +10,7 @@ import { getNodeChildren, getCacheKey } from './NodeUtils.js';

class Node {
class Node extends EventDispatcher {
constructor( nodeType = null ) {
this.isNode = true;
super();

@@ -23,2 +24,4 @@ this.nodeType = nodeType;

this.isNode = true;
Object.defineProperty( this, 'id', { value: _nodeId ++ } );

@@ -57,2 +60,8 @@

dispose() {
this.dispatchEvent( { type: 'dispose' } );
}
traverse( callback, replaceNode = null ) {

@@ -59,0 +68,0 @@

@@ -54,5 +54,9 @@ import Node, { addNodeClass } from './Node.js';

export const sheenRoughness = nodeImmutable( PropertyNode, 'float', 'SheenRoughness' );
export const iridescence = nodeImmutable( PropertyNode, 'float', 'Iridescence' );
export const iridescenceIOR = nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' );
export const iridescenceThickness = nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' );
export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' );
export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' );
export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' );
addNodeClass( PropertyNode );

@@ -18,3 +18,3 @@ import TempNode from '../core/TempNode.js';

const perturbNormal2ArbNode = tslFn( ( inputs ) => {
const perturbNormal2Arb = tslFn( ( inputs ) => {

@@ -84,3 +84,3 @@ const { eye_pos, surf_norm, mapN, uv } = inputs;

outputNode = perturbNormal2ArbNode( {
outputNode = perturbNormal2Arb( {
eye_pos: positionView,

@@ -87,0 +87,0 @@ surf_norm: normalView,

@@ -6,2 +6,3 @@ import F_Schlick from './F_Schlick.js';

import { positionViewDirection } from '../../accessors/PositionNode.js';
import { iridescence } from '../../core/PropertyNode.js';
import { tslFn } from '../../shadernode/ShaderNode.js';

@@ -12,3 +13,3 @@

const { lightDirection, f0, f90, roughness } = inputs;
const { lightDirection, f0, f90, roughness, iridescenceFresnel } = inputs;

@@ -26,3 +27,10 @@ const normalView = inputs.normalView || transformedNormalView;

const F = F_Schlick( { f0, f90, dotVH } );
let F = F_Schlick( { f0, f90, dotVH } );
if ( iridescenceFresnel ) {
F = iridescence.mix( F, iridescenceFresnel );
}
const V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } );

@@ -29,0 +37,0 @@ const D = D_GGX( { alpha, dotNH } );

@@ -0,28 +1,67 @@

import LightingModel from '../core/LightingModel.js';
import F_Schlick from './BSDF/F_Schlick.js';
import BRDF_Lambert from './BSDF/BRDF_Lambert.js';
import BRDF_BlinnPhong from './BSDF/BRDF_BlinnPhong.js';
import { lightingModel } from '../core/LightingModel.js';
import { diffuseColor } from '../core/PropertyNode.js';
import { materialReflectivity } from '../accessors/MaterialNode.js';
import { transformedNormalView } from '../accessors/NormalNode.js';
import { tslFn } from '../shadernode/ShaderNode.js';
import { materialSpecularStrength } from '../accessors/MaterialNode.js';
import { shininess, specularColor } from '../core/PropertyNode.js';
import { positionViewDirection } from '../accessors/PositionNode.js';
import { tslFn, float } from '../shadernode/ShaderNode.js';
const RE_Direct_BlinnPhong = tslFn( ( { lightDirection, lightColor, reflectedLight } ) => {
const G_BlinnPhong_Implicit = () => float( 0.25 );
const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );
const D_BlinnPhong = tslFn( ( { dotNH } ) => {
reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
return shininess.mul( 0.5 / Math.PI ).add( 1.0 ).mul( dotNH.pow( shininess ) );
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialReflectivity ) );
} );
const RE_IndirectDiffuse_BlinnPhong = tslFn( ( { irradiance, reflectedLight } ) => {
const BRDF_BlinnPhong = tslFn( ( { lightDirection } ) => {
reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
const halfDir = lightDirection.add( positionViewDirection ).normalize();
const dotNH = transformedNormalView.dot( halfDir ).clamp();
const dotVH = positionViewDirection.dot( halfDir ).clamp();
const F = F_Schlick( { f0: specularColor, f90: 1.0, dotVH } );
const G = G_BlinnPhong_Implicit();
const D = D_BlinnPhong( { dotNH } );
return F.mul( G ).mul( D );
} );
const phongLightingModel = lightingModel( null, RE_Direct_BlinnPhong, RE_IndirectDiffuse_BlinnPhong );
class PhongLightingModel extends LightingModel {
export default phongLightingModel;
constructor( specular = true ) {
super();
this.specular = specular;
}
direct( { lightDirection, lightColor, reflectedLight } ) {
const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );
reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
if ( this.specular === true ) {
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) );
}
}
indirectDiffuse( { irradiance, reflectedLight } ) {
reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
}
}
export default PhongLightingModel;

@@ -6,13 +6,126 @@ import BRDF_Lambert from './BSDF/BRDF_Lambert.js';

import F_Schlick from './BSDF/F_Schlick.js';
import Schlick_to_F0 from './BSDF/Schlick_to_F0.js';
import BRDF_Sheen from './BSDF/BRDF_Sheen.js';
import { lightingModel } from '../core/LightingModel.js';
import { diffuseColor, specularColor, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness } from '../core/PropertyNode.js';
import LightingModel from '../core/LightingModel.js';
import { diffuseColor, specularColor, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js';
import { transformedNormalView, transformedClearcoatNormalView } from '../accessors/NormalNode.js';
import { positionViewDirection } from '../accessors/PositionNode.js';
import { tslFn, float, vec3 } from '../shadernode/ShaderNode.js';
import { float, vec3, mat3 } from '../shadernode/ShaderNode.js';
import { cond } from '../math/CondNode.js';
import { mix, smoothstep } from '../math/MathNode.js';
const clearcoatF0 = vec3( 0.04 );
const clearcoatF90 = vec3( 1 );
//
// Iridescence
//
// XYZ to linear-sRGB color space
const XYZ_TO_REC709 = mat3(
3.2404542, - 0.9692660, 0.0556434,
- 1.5371385, 1.8760108, - 0.2040259,
- 0.4985314, 0.0415560, 1.0572252
);
// Assume air interface for top
// Note: We don't handle the case fresnel0 == 1
const Fresnel0ToIor = ( fresnel0 ) => {
const sqrtF0 = fresnel0.sqrt();
return vec3( 1.0 ).add( sqrtF0 ).div( vec3( 1.0 ).sub( sqrtF0 ) );
};
// ior is a value between 1.0 and 3.0. 1.0 is air interface
const IorToFresnel0 = ( transmittedIor, incidentIor ) => {
return transmittedIor.sub( incidentIor ).div( transmittedIor.add( incidentIor ) ).pow2();
};
// Fresnel equations for dielectric/dielectric interfaces.
// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html
// Evaluation XYZ sensitivity curves in Fourier space
const evalSensitivity = ( OPD, shift ) => {
const phase = OPD.mul( 2.0 * Math.PI * 1.0e-9 );
const val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );
const pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );
const VAR = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );
const x = float( 9.7470e-14 * Math.sqrt( 2.0 * Math.PI * 4.5282e+09 ) ).mul( phase.mul( 2.2399e+06 ).add( shift.x ).cos() ).mul( phase.pow2().mul( - 4.5282e+09 ).exp() );
let xyz = val.mul( VAR.mul( 2.0 * Math.PI ).sqrt() ).mul( pos.mul( phase ).add( shift ).cos() ).mul( phase.pow2().negate().mul( VAR ).exp() );
xyz = vec3( xyz.x.add( x ), xyz.y, xyz.z ).div( 1.0685e-7 );
const rgb = XYZ_TO_REC709.mul( xyz );
return rgb;
};
const evalIridescence = ( outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 ) => {
// Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0
const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );
// Evaluate the cosTheta on the base layer (Snell law)
const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( float( 1 ).sub( cosTheta1.pow2() ) );
// Handle TIR:
const cosTheta2Sq = float( 1 ).sub( sinTheta2Sq );
/*if ( cosTheta2Sq < 0.0 ) {
return vec3( 1.0 );
}*/
const cosTheta2 = cosTheta2Sq.sqrt();
// First interface
const R0 = IorToFresnel0( iridescenceIOR, outsideIOR );
const R12 = F_Schlick( { f0: R0, f90: 1.0, dotVH: cosTheta1 } );
//const R21 = R12;
const T121 = R12.oneMinus();
const phi12 = iridescenceIOR.lessThan( outsideIOR ).cond( Math.PI, 0.0 );
const phi21 = float( Math.PI ).sub( phi12 );
// Second interface
const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0
const R1 = IorToFresnel0( baseIOR, iridescenceIOR.vec3() );
const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } );
const phi23 = vec3(
baseIOR.x.lessThan( iridescenceIOR ).cond( Math.PI, 0.0 ),
baseIOR.y.lessThan( iridescenceIOR ).cond( Math.PI, 0.0 ),
baseIOR.z.lessThan( iridescenceIOR ).cond( Math.PI, 0.0 )
);
// Phase shift
const OPD = iridescenceIOR.mul( thinFilmThickness, cosTheta2, 2.0 );
const phi = vec3( phi21 ).add( phi23 );
// Compound terms
const R123 = R12.mul( R23 ).clamp( 1e-5, 0.9999 );
const r123 = R123.sqrt();
const Rs = T121.pow2().mul( R23 ).div( vec3( 1.0 ).sub( R123 ) );
// Reflectance term for m = 0 (DC term amplitude)
const C0 = R12.add( Rs );
let I = C0;
// Reflectance term for m > 0 (pairs of diracs)
let Cm = Rs.sub( T121 );
for ( let m = 1; m <= 2; ++ m ) {
Cm = Cm.mul( r123 );
const Sm = evalSensitivity( float( m ).mul( OPD ), float( m ).mul( phi ) ).mul( 2.0 );
I = I.add( Cm.mul( Sm ) );
}
// Since out of gamut colors might be produced, negative color values are clamped to 0.
return I.max( vec3( 0.0 ) );
};
//
// Sheen
//
// This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from

@@ -45,162 +158,188 @@ // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found

// Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
// Approximates multiscattering in order to preserve energy.
// http://www.jcgt.org/published/0008/01/03/
const computeMultiscattering = ( singleScatter, multiScatter, specularF90 = float( 1 ) ) => {
const clearcoatF0 = vec3( 0.04 );
const clearcoatF90 = vec3( 1 );
const fab = DFGApprox( { roughness } );
//
const FssEss = specularColor.mul( fab.x ).add( specularF90.mul( fab.y ) );
class PhysicalLightingModel extends LightingModel {
const Ess = fab.x.add( fab.y );
const Ems = Ess.oneMinus();
constructor( clearcoat = true, sheen = true, iridescence = true ) {
const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21
const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() );
super();
singleScatter.addAssign( FssEss );
multiScatter.addAssign( Fms.mul( Ems ) );
this.clearcoat = clearcoat;
this.sheen = sheen;
this.iridescence = iridescence;
};
this.clearcoatRadiance = null;
this.clearcoatSpecular = null;
this.sheenSpecular = null;
this.iridescenceFresnel = null;
this.iridescenceF0 = null;
const LM_Init = tslFn( ( context, stack, builder ) => {
}
if ( builder.includes( clearcoat ) ) {
init( { reflectedLight } ) {
context.clearcoatRadiance = vec3().temp();
context.reflectedLight.clearcoatSpecular = vec3().temp();
if ( this.clearcoat === true ) {
const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
this.clearcoatRadiance = vec3().temp();
this.clearcoatSpecular = vec3().temp();
const Fcc = F_Schlick( {
dotVH: dotNVcc,
f0: clearcoatF0,
f90: clearcoatF90
} );
const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
const outgoingLight = context.reflectedLight.total;
const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( context.reflectedLight.clearcoatSpecular.mul( clearcoat ) );
const Fcc = F_Schlick( {
dotVH: dotNVcc,
f0: clearcoatF0,
f90: clearcoatF90
} );
outgoingLight.assign( clearcoatLight );
const outgoingLight = reflectedLight.total;
const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecular.mul( clearcoat ) );
}
outgoingLight.assign( clearcoatLight );
if ( builder.includes( sheen ) ) {
}
context.reflectedLight.sheenSpecular = vec3().temp();
if ( this.sheen === true ) {
const outgoingLight = context.reflectedLight.total;
this.sheenSpecular = vec3().temp();
const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( context.reflectedLight.sheenSpecular );
const outgoingLight = reflectedLight.total;
outgoingLight.assign( sheenLight );
const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus();
const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecular );
}
outgoingLight.assign( sheenLight );
} );
}
const RE_IndirectSpecular_Physical = tslFn( ( context ) => {
if ( this.iridescence === true ) {
const { radiance, iblIrradiance, reflectedLight } = context;
const dotNVi = transformedNormalView.dot( positionViewDirection ).clamp();
if ( reflectedLight.sheenSpecular ) {
this.iridescenceFresnel = evalIridescence( float( 1.0 ), iridescenceIOR, dotNVi, iridescenceThickness, specularColor );
this.iridescenceF0 = Schlick_to_F0( { f: this.iridescenceFresnel, f90: 1.0, dotVH: dotNVi } );
reflectedLight.sheenSpecular.addAssign( iblIrradiance.mul(
sheen,
IBLSheenBRDF( transformedNormalView, positionViewDirection, sheenRoughness )
) );
}
}
if ( reflectedLight.clearcoatSpecular ) {
// Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
// Approximates multiscattering in order to preserve energy.
// http://www.jcgt.org/published/0008/01/03/
const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) {
const clearcoatEnv = EnvironmentBRDF( {
dotNV: dotNVcc,
specularColor: clearcoatF0,
specularF90: clearcoatF90,
roughness: clearcoatRoughness
} );
const fab = DFGApprox( { roughness } );
reflectedLight.clearcoatSpecular.addAssign( context.clearcoatRadiance.mul( clearcoatEnv ) );
const Fr = this.iridescenceF0 ? iridescence.mix( specularColor, this.iridescenceF0 ) : specularColor;
}
const FssEss = Fr.mul( fab.x ).add( specularF90.mul( fab.y ) );
// Both indirect specular and indirect diffuse light accumulate here
const Ess = fab.x.add( fab.y );
const Ems = Ess.oneMinus();
const singleScattering = vec3().temp();
const multiScattering = vec3().temp();
const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21
const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() );
computeMultiscattering( singleScattering, multiScattering );
singleScatter.addAssign( FssEss );
multiScatter.addAssign( Fms.mul( Ems ) );
const totalScattering = singleScattering.add( multiScattering );
}
const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() );
direct( { lightDirection, lightColor, reflectedLight } ) {
reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) );
reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) );
const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );
reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) );
if ( this.sheen === true ) {
} );
this.sheenSpecular.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
const RE_IndirectDiffuse_Physical = tslFn( ( context ) => {
}
const { irradiance, reflectedLight } = context;
if ( this.clearcoat === true ) {
reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp();
const ccIrradiance = dotNLcc.mul( lightColor );
} );
this.clearcoatSpecular.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
const RE_Direct_Physical = tslFn( ( inputs ) => {
}
const { lightDirection, lightColor, reflectedLight } = inputs;
reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
const dotNL = transformedNormalView.dot( lightDirection ).clamp();
const irradiance = dotNL.mul( lightColor );
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) );
if ( reflectedLight.sheenSpecular ) {
}
reflectedLight.sheenSpecular.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) );
indirectDiffuse( { irradiance, reflectedLight } ) {
reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) );
}
if ( reflectedLight.clearcoatSpecular ) {
indirectSpecular( { radiance, iblIrradiance, reflectedLight, } ) {
const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp();
const ccIrradiance = dotNLcc.mul( lightColor );
if ( this.sheen === true ) {
reflectedLight.clearcoatSpecular.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) );
this.sheenSpecular.addAssign( iblIrradiance.mul(
sheen,
IBLSheenBRDF( transformedNormalView, positionViewDirection, sheenRoughness )
) );
}
}
reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) );
if ( this.clearcoat === true ) {
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness } ) ) );
const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp();
} );
const clearcoatEnv = EnvironmentBRDF( {
dotNV: dotNVcc,
specularColor: clearcoatF0,
specularF90: clearcoatF90,
roughness: clearcoatRoughness
} );
const RE_AmbientOcclusion_Physical = tslFn( ( context ) => {
this.clearcoatSpecular.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) );
const { ambientOcclusion, reflectedLight } = context;
}
const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
// Both indirect specular and indirect diffuse light accumulate here
const aoNV = dotNV.add( ambientOcclusion );
const aoExp = roughness.mul( - 16.0 ).oneMinus().negate().exp2();
const singleScattering = vec3().temp();
const multiScattering = vec3().temp();
const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI );
const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp();
this.computeMultiscattering( singleScattering, multiScattering );
reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
const totalScattering = singleScattering.add( multiScattering );
reflectedLight.indirectSpecular.mulAssign( aoNode );
const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() );
reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) );
reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) );
} );
reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) );
const physicalLightingModel = lightingModel( LM_Init, RE_Direct_Physical, RE_IndirectDiffuse_Physical, RE_IndirectSpecular_Physical, RE_AmbientOcclusion_Physical );
}
export default physicalLightingModel;
ambientOcclusion( { ambientOcclusion, reflectedLight } ) {
const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV
const aoNV = dotNV.add( ambientOcclusion );
const aoExp = roughness.mul( - 16.0 ).oneMinus().negate().exp2();
const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp();
reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion );
reflectedLight.indirectSpecular.mulAssign( aoNode );
}
}
export default PhysicalLightingModel;

@@ -47,4 +47,4 @@ import Node, { addNodeClass } from '../core/Node.js';

let minValue = this.minNode.value;
let maxValue = this.maxNode.value;
const minValue = this.minNode.value;
const maxValue = this.maxNode.value;

@@ -51,0 +51,0 @@ const minLength = builder.getTypeLength( getValueType( minValue ) );

@@ -19,2 +19,3 @@ import Node, { addNodeClass } from '../core/Node.js';

this.version = 1;
this.updateType = NodeUpdateType.OBJECT;

@@ -26,2 +27,14 @@

dispose() {
this.dispatchEvent( { type: 'dispose' } );
}
set needsUpdate( value ) {
if ( value === true ) this.version ++;
}
updateDispatchCount() {

@@ -28,0 +41,0 @@

@@ -5,10 +5,10 @@ import LightingNode from './LightingNode.js';

import { addNodeClass } from '../core/Node.js';
import { vec3 } from '../shadernode/ShaderNode.js';
import { /*vec2,*/ vec3 } from '../shadernode/ShaderNode.js';
import { reference } from '../accessors/ReferenceNode.js';
import { texture } from '../accessors/TextureNode.js';
import { positionWorld } from '../accessors/PositionNode.js';
//import { step } from '../math/MathNode.js';
import { cond } from '../math/CondNode.js';
import { normalWorld } from '../accessors/NormalNode.js';
//import { add } from '../math/OperatorNode.js';
import { Color, DepthTexture, NearestFilter } from 'three';
import { Color, DepthTexture, NearestFilter, LessCompare } from 'three';

@@ -57,3 +57,3 @@ let depthMaterial = null;

depthTexture.image.height = shadow.mapSize.height;
//depthTexture.compareFunction = THREE.LessCompare;
depthTexture.compareFunction = LessCompare;

@@ -67,27 +67,65 @@ rtt.depthTexture = depthTexture;

const bias = reference( 'bias', 'float', shadow );
const normalBias = reference( 'normalBias', 'float', shadow );
//const diffuseFactor = normalView.dot( objectViewPosition( this.light ).sub( positionView ).normalize().negate() );
//bias = mix( bias, 0, diffuseFactor );
let shadowCoord = uniform( shadow.matrix ).mul( positionWorld );
let shadowCoord = uniform( shadow.matrix ).mul( positionWorld.add( normalWorld.mul( normalBias ) ) );
shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
const frustumTest = shadowCoord.x.greaterThanEqual( 0 )
.and( shadowCoord.x.lessThanEqual( 1 ) )
.and( shadowCoord.y.greaterThanEqual( 0 ) )
.and( shadowCoord.y.lessThanEqual( 1 ) )
.and( shadowCoord.z.lessThanEqual( 1 ) );
shadowCoord = vec3(
shadowCoord.x,
shadowCoord.y.oneMinus(),
shadowCoord.z
shadowCoord.y.oneMinus(), // WebGPU: Flip Y
shadowCoord.z.add( bias ).mul( 2 ).sub( 1 ) // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ]
);
// @TODO: Optimize using WebGPU compare-sampler
const textureCompare = ( depthTexture, shadowCoord, compare ) => texture( depthTexture, shadowCoord ).compare( compare );
//const textureCompare = ( depthTexture, shadowCoord, compare ) => compare.step( texture( depthTexture, shadowCoord ) );
let depth = texture( depthTexture, shadowCoord.xy );
depth = depth.mul( .5 ).add( .5 ).add( bias );
// BasicShadowMap
shadowNode = cond( shadowCoord.z.lessThan( depth ).or( shadowCoord.y.lessThan( .000001 ) /*@TODO: find the cause and remove it soon */ ), 1, 0 );
//shadowNode = step( shadowCoord.z, depth );
shadowNode = textureCompare( depthTexture, shadowCoord.xy, shadowCoord.z );
// PCFShadowMap
/*
const mapSize = reference( 'mapSize', 'vec2', shadow );
const radius = reference( 'radius', 'float', shadow );
const texelSize = vec2( 1 ).div( mapSize );
const dx0 = texelSize.x.negate().mul( radius );
const dy0 = texelSize.y.negate().mul( radius );
const dx1 = texelSize.x.mul( radius );
const dy1 = texelSize.y.mul( radius );
const dx2 = dx0.mul( 2 );
const dy2 = dy0.mul( 2 );
const dx3 = dx1.mul( 2 );
const dy3 = dy1.mul( 2 );
shadowNode = add(
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy, shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ),
textureCompare( depthTexture, shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z )
).mul( 1 / 17 );
*/
//
this.rtt = rtt;
this.colorNode = this.colorNode.mul( shadowNode );
this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode ) );

@@ -94,0 +132,0 @@ this.shadowNode = shadowNode;

@@ -17,3 +17,3 @@ import LightingNode from './LightingNode.js';

const aoIntensity = 1;
const aoNode = this.aoNode.sub( 1.0 ).mul( aoIntensity ).add( 1.0 );
const aoNode = this.aoNode.x.sub( 1.0 ).mul( aoIntensity ).add( 1.0 );

@@ -20,0 +20,0 @@ builder.context.ambientOcclusion.mulAssign( aoNode );

@@ -20,17 +20,14 @@ import AnalyticLightNode from './AnalyticLightNode.js';

const lightingModel = builder.context.lightingModel;
const lightColor = this.colorNode;
const lightDirection = lightTargetDirection( this.light );
const lightingModelFunctionNode = builder.context.lightingModelNode;
const reflectedLight = builder.context.reflectedLight;
if ( lightingModelFunctionNode && lightingModelFunctionNode.direct ) {
lightingModel.direct( {
lightDirection,
lightColor,
reflectedLight
} );
lightingModelFunctionNode.direct( {
lightDirection,
lightColor,
reflectedLight
} );
}
}

@@ -37,0 +34,0 @@

@@ -15,2 +15,4 @@ import LightingNode from './LightingNode.js';

const envNodeCache = new WeakMap();
class EnvironmentNode extends LightingNode {

@@ -33,10 +35,20 @@

const texture = envNode.value;
const renderer = builder.renderer;
let cacheEnvNode = envNodeCache.get( envNode.value );
// @TODO: Add dispose logic here
const cubeRTT = builder.getCubeRenderTarget( 512 ).fromEquirectangularTexture( renderer, texture );
if ( cacheEnvNode === undefined ) {
envNode = cubeTexture( cubeRTT.texture );
const texture = envNode.value;
const renderer = builder.renderer;
// @TODO: Add dispose logic here
const cubeRTT = builder.getCubeRenderTarget( 512 ).fromEquirectangularTexture( renderer, texture );
cacheEnvNode = cubeTexture( cubeRTT.texture );
envNodeCache.set( envNode.value, cacheEnvNode );
}
envNode = cacheEnvNode;
}

@@ -61,12 +73,11 @@

let isolateClearcoatRadiance = null;
const clearcoatRadiance = builder.context.lightingModel.clearcoatRadiance;
if ( builder.context.clearcoatRadiance  ) {
if ( clearcoatRadiance ) {
const clearcoatRadiance = context( envNode, createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity );
const clearcoatRadianceContext = context( envNode, createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity );
const isolateClearcoatRadiance = cache( clearcoatRadianceContext );
isolateClearcoatRadiance = cache( clearcoatRadiance );
clearcoatRadiance.addAssign( isolateClearcoatRadiance );
builder.context.clearcoatRadiance.addAssign( isolateClearcoatRadiance );
}

@@ -77,3 +88,2 @@

properties.radiance = isolateRadiance;
properties.clearcoatRadiance = isolateClearcoatRadiance;
properties.irradiance = irradiance;

@@ -80,0 +90,0 @@

@@ -36,3 +36,3 @@ import AnalyticLightNode from './AnalyticLightNode.js';

generate( builder ) {
construct( builder ) {

@@ -39,0 +39,0 @@ const { colorNode, groundColorNode, lightDirectionNode } = this;

@@ -9,7 +9,7 @@ import ContextNode from '../core/ContextNode.js';

constructor( node, lightingModelNode = null, backdropNode = null, backdropAlphaNode = null ) {
constructor( node, lightingModel = null, backdropNode = null, backdropAlphaNode = null ) {
super( node );
this.lightingModelNode = lightingModelNode;
this.lightingModel = lightingModel;
this.backdropNode = backdropNode;

@@ -28,3 +28,3 @@ this.backdropAlphaNode = backdropAlphaNode;

const { lightingModelNode, backdropNode, backdropAlphaNode } = this;
const { lightingModel, backdropNode, backdropAlphaNode } = this;

@@ -66,3 +66,3 @@ const context = this.context = {}; // reset context

context.reflectedLight = reflectedLight;
context.lightingModelNode = lightingModelNode || context.lightingModelNode;
context.lightingModel = lightingModel || context.lightingModel;

@@ -72,9 +72,12 @@ Object.assign( properties, reflectedLight, lighting );

// @TODO: Call needed return a new node ( or rename the ShaderNodeInternal.call() function ), it's not moment to run
if ( lightingModelNode && lightingModelNode.init ) lightingModelNode.init( context, builder.stack, builder );
if ( lightingModel ) {
if ( lightingModelNode && lightingModelNode.indirectDiffuse ) lightingModelNode.indirectDiffuse( context, builder.stack, builder );
if ( lightingModelNode && lightingModelNode.indirectSpecular ) lightingModelNode.indirectSpecular( context, builder.stack, builder );
if ( lightingModelNode && lightingModelNode.ambientOcclusion ) lightingModelNode.ambientOcclusion( context, builder.stack, builder );
lightingModel.init( context, builder.stack, builder );
lightingModel.indirectDiffuse( context, builder.stack, builder );
lightingModel.indirectSpecular( context, builder.stack, builder );
lightingModel.ambientOcclusion( context, builder.stack, builder );
}
return super.construct( builder );

@@ -81,0 +84,0 @@

@@ -37,2 +37,4 @@ import AnalyticLightNode from './AnalyticLightNode.js';

const lightingModel = builder.context.lightingModel;
const lVector = objectViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode

@@ -51,15 +53,10 @@

const lightingModelFunctionNode = builder.context.lightingModelNode;
const reflectedLight = builder.context.reflectedLight;
if ( lightingModelFunctionNode && lightingModelFunctionNode.direct ) {
lightingModel.direct( {
lightDirection,
lightColor,
reflectedLight
} );
lightingModelFunctionNode.direct( {
lightDirection,
lightColor,
reflectedLight
} );
}
}

@@ -66,0 +63,0 @@

@@ -53,2 +53,4 @@ import AnalyticLightNode from './AnalyticLightNode.js';

const lightingModel = builder.context.lightingModel;
const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this;

@@ -72,15 +74,10 @@

const lightingModelFunctionNode = builder.context.lightingModelNode;
const reflectedLight = builder.context.reflectedLight;
if ( lightingModelFunctionNode && lightingModelFunctionNode.direct ) {
lightingModel.direct( {
lightDirection,
lightColor,
reflectedLight
} );
lightingModelFunctionNode.direct( {
lightDirection,
lightColor,
reflectedLight
} );
}
}

@@ -87,0 +84,0 @@

@@ -7,2 +7,3 @@ // @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports

export { default as MeshBasicNodeMaterial } from './MeshBasicNodeMaterial.js';
export { default as MeshLambertNodeMaterial } from './MeshLambertNodeMaterial.js';
export { default as MeshPhongNodeMaterial } from './MeshPhongNodeMaterial.js';

@@ -9,0 +10,0 @@ export { default as MeshStandardNodeMaterial } from './MeshStandardNodeMaterial.js';

@@ -20,2 +20,4 @@ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';

this.colorSpace = false;
this.setDefaultValues( defaultValues );

@@ -22,0 +24,0 @@

import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
import { shininess, specularColor } from '../core/PropertyNode.js';
import { materialShininess, materialSpecularColor } from '../accessors/MaterialNode.js';
import phongLightingModel from '../functions/PhongLightingModel.js';
import { float } from '../shadernode/ShaderNode.js';
import PhongLightingModel from '../functions/PhongLightingModel.js';

@@ -32,3 +32,3 @@ import { MeshPhongMaterial } from 'three';

return phongLightingModel;
return new PhongLightingModel();

@@ -35,0 +35,0 @@ }

import { addNodeMaterial } from './NodeMaterial.js';
import { transformedClearcoatNormalView } from '../accessors/NormalNode.js';
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness } from '../core/PropertyNode.js';
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js';
import { materialClearcoatNormal } from '../accessors/ExtendedMaterialNode.js';
import { materialClearcoat, materialClearcoatRoughness, materialSheen, materialSheenRoughness } from '../accessors/MaterialNode.js';
import { materialClearcoat, materialClearcoatRoughness, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness } from '../accessors/MaterialNode.js';
import { float, vec3 } from '../shadernode/ShaderNode.js';
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js';

@@ -46,2 +47,8 @@

constructLightingModel( /*builder*/ ) {
return new PhysicalLightingModel(); // @TODO: Optimize shader using parameters.
}
constructVariants( builder ) {

@@ -69,2 +76,12 @@

// IRIDESCENCE
const iridescenceNode = this.iridescenceNode ? float( this.iridescenceNode ) : materialIridescence;
const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR;
const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness;
stack.assign( iridescence, iridescenceNode );
stack.assign( iridescenceIOR, iridescenceIORNode );
stack.assign( iridescenceThickness, iridescenceThicknessNode );
}

@@ -71,0 +88,0 @@

@@ -6,3 +6,3 @@ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';

import getRoughness from '../functions/material/getRoughness.js';
import physicalLightingModel from '../functions/PhysicalLightingModel.js';
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
import { float, vec3, vec4 } from '../shadernode/ShaderNode.js';

@@ -35,3 +35,3 @@

return physicalLightingModel;
return new PhysicalLightingModel( false, false ); // ( clearcoat, sheen ) -> standard

@@ -38,0 +38,0 @@ }

@@ -1,5 +0,5 @@

import { Material, ShaderMaterial, NoColorSpace } from 'three';
import { Material, ShaderMaterial, NoColorSpace, LinearSRGBColorSpace } from 'three';
import { getNodeChildren, getCacheKey } from '../core/NodeUtils.js';
import { attribute } from '../core/AttributeNode.js';
import { diffuseColor } from '../core/PropertyNode.js';
import { output, diffuseColor } from '../core/PropertyNode.js';
import { materialNormal } from '../accessors/ExtendedMaterialNode.js';

@@ -35,4 +35,8 @@ import { materialAlphaTest, materialColor, materialOpacity, materialEmissive } from '../accessors/MaterialNode.js';

this.unlit = this.constructor === NodeMaterial.prototype.constructor; // Extended materials are not unlit by default
this.fog = true;
this.lights = true;
this.normals = true;
this.colorSpace = true;

@@ -50,4 +54,6 @@ this.lightsNode = null;

this.positionNode = null;
this.outputNode = null;
this.outputNode = null; // @TODO: Rename to fragmentNode
this.vertexNode = null;
}

@@ -81,4 +87,6 @@

if ( this.isUnlit === false ) {
let outputNode;
if ( this.unlit === false ) {
if ( this.normals === true ) this.constructNormal( builder );

@@ -91,10 +99,20 @@

builder.stack.outputNode = this.constructOutput( builder, vec4( outgoingLightNode, diffuseColor.a ) );
outputNode = this.constructOutput( builder, vec4( outgoingLightNode, diffuseColor.a ) );
// OUTPUT NODE
builder.stack.assign( output, outputNode );
//
if ( this.outputNode !== null ) outputNode = this.outputNode;
} else {
builder.stack.outputNode = this.constructOutput( builder, this.outputNode || vec4( 0, 0, 0, 1 ) );
outputNode = this.constructOutput( builder, this.outputNode || vec4( 0, 0, 0, 1 ) );
}
builder.stack.outputNode = outputNode;
builder.addFlow( 'fragment', builder.removeStack() );

@@ -137,3 +155,3 @@

return modelViewProjection();
return this.vertexNode || modelViewProjection();

@@ -314,26 +332,38 @@ }

// FOG
if ( this.fog === true ) {
const fogNode = builder.fogNode;
if ( fogNode ) outputNode = vec4( fogNode.mixAssign( outputNode.rgb ), outputNode.a );
}
// ENCODING
const renderTarget = renderer.getRenderTarget();
if ( this.colorSpace === true ) {
let outputColorSpace;
const renderTarget = renderer.getRenderTarget();
if ( renderTarget !== null ) {
let outputColorSpace;
outputColorSpace = renderTarget.texture.colorSpace;
if ( renderTarget !== null ) {
} else {
outputColorSpace = renderTarget.texture.colorSpace;
outputColorSpace = renderer.outputColorSpace;
} else {
}
outputColorSpace = renderer.outputColorSpace;
if ( outputColorSpace !== NoColorSpace ) outputNode = outputNode.linearToColorSpace( outputColorSpace );
}
// FOG
if ( outputColorSpace !== LinearSRGBColorSpace && outputColorSpace !== NoColorSpace ) {
const fogNode = builder.fogNode;
outputNode = outputNode.linearToColorSpace( outputColorSpace );
if ( fogNode ) outputNode = vec4( fogNode.mixAssign( outputNode.rgb ), outputNode.a );
}
}
return outputNode;

@@ -438,8 +468,2 @@

get isUnlit() {
return this.constructor === NodeMaterial.prototype.constructor;
}
copy( source ) {

@@ -458,3 +482,5 @@

this.positionNode = source.positionNode;
this.outputNode = source.outputNode;
this.vertexNode = source.vertexNode;

@@ -461,0 +487,0 @@ return super.copy( source );

@@ -7,3 +7,3 @@ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';

import { positionLocal } from '../accessors/PositionNode.js';
import { vec2, vec3, vec4 } from '../shadernode/ShaderNode.js';
import { float, vec2, vec3, vec4 } from '../shadernode/ShaderNode.js';

@@ -70,3 +70,3 @@ import { SpriteMaterial } from 'three';

const rotation = rotationNode || materialRotation;
const rotation = float( rotationNode || materialRotation );

@@ -73,0 +73,0 @@ const cosAngle = rotation.cos();

@@ -15,3 +15,3 @@ // @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports

export { default as IndexNode, vertexIndex, instanceIndex } from './core/IndexNode.js';
export { default as LightingModel, lightingModel } from './core/LightingModel.js';
export { default as LightingModel } from './core/LightingModel.js';
export { default as Node, addNodeClass, createNodeFromType } from './core/Node.js';

@@ -28,3 +28,3 @@ export { default as NodeAttribute } from './core/NodeAttribute.js';

export { default as NodeVarying } from './core/NodeVarying.js';
export { default as PropertyNode, property, diffuseColor, roughness, metalness, specularColor, shininess } from './core/PropertyNode.js';
export { default as PropertyNode, property, output, diffuseColor, roughness, metalness, specularColor, shininess } from './core/PropertyNode.js';
export { default as StackNode, stack } from './core/StackNode.js';

@@ -87,3 +87,3 @@ export { default as TempNode } from './core/TempNode.js';

export { default as SkinningNode, skinning } from './accessors/SkinningNode.js';
export { default as SceneNode, backgroundBlurriness } from './accessors/SceneNode.js';
export { default as SceneNode, backgroundBlurriness, backgroundIntensity } from './accessors/SceneNode.js';
export { default as StorageBufferNode, storage } from './accessors/StorageBufferNode.js';

@@ -161,3 +161,2 @@ export { default as TangentNode, tangentGeometry, tangentLocal, tangentView, tangentWorld, transformedTangentView, transformedTangentWorld } from './accessors/TangentNode.js';

// functions
export { default as BRDF_BlinnPhong } from './functions/BSDF/BRDF_BlinnPhong.js';
export { default as BRDF_GGX } from './functions/BSDF/BRDF_GGX.js';

@@ -175,3 +174,3 @@ export { default as BRDF_Lambert } from './functions/BSDF/BRDF_Lambert.js';

export { default as phongLightingModel } from './functions/PhongLightingModel.js';
export { default as physicalLightingModel } from './functions/PhysicalLightingModel.js';
export { default as PhongLightingModel } from './functions/PhongLightingModel.js';
export { default as PhysicalLightingModel } from './functions/PhysicalLightingModel.js';

@@ -264,3 +264,3 @@ import Node, { addNodeClass } from '../core/Node.js';

} catch {
} catch ( _ ) {

@@ -326,3 +326,3 @@ return undefined;

console.warn( 'TSL: shader() is deprecated. Use fn() instead.' );
console.warn( 'TSL: shader() is deprecated. Use tslFn() instead.' );

@@ -329,0 +329,0 @@ return new ShaderNode( jsFunc );

@@ -12,5 +12,3 @@ import {

WebGLRenderTarget,
HalfFloatType,
NoToneMapping,
LinearSRGBColorSpace
HalfFloatType
} from 'three';

@@ -151,9 +149,5 @@

const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
const currentOutputColorSpace = renderer.outputColorSpace;
const currentToneMapping = renderer.toneMapping;
renderer.xr.enabled = false; // Avoid camera modification
renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
renderer.outputColorSpace = LinearSRGBColorSpace;
renderer.toneMapping = NoToneMapping;

@@ -169,4 +163,2 @@ renderer.setRenderTarget( renderTarget );

renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
renderer.outputColorSpace = currentOutputColorSpace;
renderer.toneMapping = currentToneMapping;

@@ -173,0 +165,0 @@ renderer.setRenderTarget( currentRenderTarget );

@@ -13,4 +13,2 @@ import {

WebGLRenderTarget,
LinearSRGBColorSpace,
NoToneMapping,
HalfFloatType

@@ -198,9 +196,5 @@ } from 'three';

const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
const currentOutputColorSpace = renderer.outputColorSpace;
const currentToneMapping = renderer.toneMapping;
renderer.xr.enabled = false; // avoid camera modification
renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
renderer.outputColorSpace = LinearSRGBColorSpace;
renderer.toneMapping = NoToneMapping;

@@ -213,4 +207,2 @@ renderer.setRenderTarget( renderTarget );

renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
renderer.outputColorSpace = currentOutputColorSpace;
renderer.toneMapping = currentToneMapping;
renderer.setRenderTarget( currentRenderTarget );

@@ -217,0 +209,0 @@

@@ -48,3 +48,2 @@ import * as THREE from '../../../build/three.module.js';

renderer.setSize( width, height, false );
renderer.useLegacyLights = false;

@@ -51,0 +50,0 @@ animate();

@@ -66,3 +66,3 @@ import { Pass } from './Pass.js';

// unlock color and depth buffer for subsequent rendering
// unlock color and depth buffer and make them writable for subsequent rendering/clearing

@@ -72,2 +72,5 @@ state.buffers.color.setLocked( false );

state.buffers.color.setMask( true );
state.buffers.depth.setMask( true );
// only render where stencil is set to 1

@@ -74,0 +77,0 @@

import {
ShaderMaterial,
RawShaderMaterial,
UniformsUtils,
NoToneMapping,
LinearToneMapping,
ReinhardToneMapping,
CineonToneMapping,
ACESFilmicToneMapping
ACESFilmicToneMapping,
SRGBColorSpace
} from 'three';

@@ -15,9 +15,6 @@ import { Pass, FullScreenQuad } from './Pass.js';

constructor( toneMapping = NoToneMapping, toneMappingExposure = 1 ) {
constructor() {
super();
this.toneMapping = toneMapping;
this.toneMappingExposure = toneMappingExposure;
//

@@ -29,3 +26,3 @@

this.material = new ShaderMaterial( {
this.material = new RawShaderMaterial( {
uniforms: this.uniforms,

@@ -36,9 +33,9 @@ vertexShader: shader.vertexShader,

if ( toneMapping === LinearToneMapping ) this.material.defines.LINEAR_TONE_MAPPING = '';
else if ( toneMapping === ReinhardToneMapping ) this.material.defines.REINHARD_TONE_MAPPING = '';
else if ( toneMapping === CineonToneMapping ) this.material.defines.CINEON_TONE_MAPPING = '';
else if ( toneMapping === ACESFilmicToneMapping ) this.material.defines.ACES_FILMIC_TONE_MAPPING = '';
this.fsQuad = new FullScreenQuad( this.material );
// internal cache
this._outputColorSpace = null;
this._toneMapping = null;
}

@@ -49,4 +46,26 @@

this.uniforms[ 'tDiffuse' ].value = readBuffer.texture;
this.uniforms[ 'toneMappingExposure' ].value = this.toneMappingExposure;
this.uniforms[ 'toneMappingExposure' ].value = renderer.toneMappingExposure;
// rebuild defines if required
if ( this._outputColorSpace !== renderer.outputColorSpace || this._toneMapping !== renderer.toneMapping ) {
this._outputColorSpace = renderer.outputColorSpace;
this._toneMapping = renderer.toneMapping;
this.material.defines = {};
if ( this._outputColorSpace == SRGBColorSpace ) this.material.defines.SRGB_COLOR_SPACE = '';
if ( this._toneMapping === LinearToneMapping ) this.material.defines.LINEAR_TONE_MAPPING = '';
else if ( this._toneMapping === ReinhardToneMapping ) this.material.defines.REINHARD_TONE_MAPPING = '';
else if ( this._toneMapping === CineonToneMapping ) this.material.defines.CINEON_TONE_MAPPING = '';
else if ( this._toneMapping === ACESFilmicToneMapping ) this.material.defines.ACES_FILMIC_TONE_MAPPING = '';
this.material.needsUpdate = true;
}
//
if ( this.renderToScreen === true ) {

@@ -53,0 +72,0 @@

@@ -97,3 +97,3 @@ import {

this.separableBlurMaterials[ i ].uniforms[ 'texSize' ].value = new Vector2( resx, resy );
this.separableBlurMaterials[ i ].uniforms[ 'invSize' ].value = new Vector2( 1 / resx, 1 / resy );

@@ -196,3 +196,3 @@ resx = Math.round( resx / 2 );

this.separableBlurMaterials[ i ].uniforms[ 'texSize' ].value = new Vector2( resx, resy );
this.separableBlurMaterials[ i ].uniforms[ 'invSize' ].value = new Vector2( 1 / resx, 1 / resy );

@@ -303,7 +303,14 @@ resx = Math.round( resx / 2 );

const coefficients = [];
for ( let i = 0; i < kernelRadius; i ++ ) {
coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius );
}
return new ShaderMaterial( {
defines: {
'KERNEL_RADIUS': kernelRadius,
'SIGMA': kernelRadius
'KERNEL_RADIUS': kernelRadius
},

@@ -313,4 +320,5 @@

'colorTexture': { value: null },
'texSize': { value: new Vector2( 0.5, 0.5 ) },
'direction': { value: new Vector2( 0.5, 0.5 ) }
'invSize': { value: new Vector2( 0.5, 0.5 ) }, // inverse texture size
'direction': { value: new Vector2( 0.5, 0.5 ) },
'gaussianCoefficients': { value: coefficients } // precomputed Gaussian coefficients
},

@@ -329,19 +337,15 @@

uniform sampler2D colorTexture;
uniform vec2 texSize;
uniform vec2 invSize;
uniform vec2 direction;
uniform float gaussianCoefficients[KERNEL_RADIUS];
float gaussianPdf(in float x, in float sigma) {
return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
}
void main() {
vec2 invSize = 1.0 / texSize;
float fSigma = float(SIGMA);
float weightSum = gaussianPdf(0.0, fSigma);
vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;
float weightSum = gaussianCoefficients[0];
vec3 diffuseSum = texture2D( colorTexture, vUv ).rgb * weightSum;
for( int i = 1; i < KERNEL_RADIUS; i ++ ) {
float x = float(i);
float w = gaussianPdf(x, fSigma);
float w = gaussianCoefficients[i];
vec2 uvOffset = direction * invSize * x;
vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;
vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;
vec3 sample1 = texture2D( colorTexture, vUv + uvOffset ).rgb;
vec3 sample2 = texture2D( colorTexture, vUv - uvOffset ).rgb;
diffuseSum += (sample1 + sample2) * w;

@@ -348,0 +352,0 @@ weightSum += 2.0 * w;

import DataMap from './DataMap.js';
import { Color, Mesh, SphereGeometry, BackSide } from 'three';
import { context, positionWorldDirection, backgroundBlurriness, MeshBasicNodeMaterial } from '../../nodes/Nodes.js';
import { vec4, context, normalWorld, backgroundBlurriness, backgroundIntensity, NodeMaterial, modelViewProjection } from '../../nodes/Nodes.js';

@@ -17,4 +17,4 @@ let _clearAlpha;

this.boxMesh = null;
this.boxMeshNode = null;
this.backgroundMesh = null;
this.backgroundMeshNode = null;

@@ -26,3 +26,3 @@ }

const renderer = this.renderer;
const background = ( scene.isScene === true ) ? this.nodes.getBackgroundNode( scene ) || scene.background : null;
const background = this.nodes.getBackgroundNode( scene ) || scene.background;

@@ -54,14 +54,17 @@ let forceClear = false;

let boxMesh = this.boxMesh;
let backgroundMesh = this.backgroundMesh;
if ( boxMesh === null ) {
if ( backgroundMesh === null ) {
this.boxMeshNode = context( backgroundNode, {
this.backgroundMeshNode = context( backgroundNode, {
// @TODO: Add Texture2D support using node context
getUVNode: () => positionWorldDirection,
getUVNode: () => normalWorld,
getSamplerLevelNode: () => backgroundBlurriness
} );
} ).mul( backgroundIntensity );
const nodeMaterial = new MeshBasicNodeMaterial();
nodeMaterial.colorNode = this.boxMeshNode;
let viewProj = modelViewProjection();
viewProj = vec4( viewProj.x, viewProj.y, viewProj.w, viewProj.w );
const nodeMaterial = new NodeMaterial();
nodeMaterial.outputNode = this.backgroundMeshNode;
nodeMaterial.side = BackSide;

@@ -71,12 +74,11 @@ nodeMaterial.depthTest = false;

nodeMaterial.fog = false;
nodeMaterial.vertexNode = viewProj;
this.boxMesh = boxMesh = new Mesh( new SphereGeometry( 1, 32, 32 ), nodeMaterial );
boxMesh.frustumCulled = false;
this.backgroundMesh = backgroundMesh = new Mesh( new SphereGeometry( 1, 32, 32 ), nodeMaterial );
backgroundMesh.frustumCulled = false;
boxMesh.onBeforeRender = function ( renderer, scene, camera ) {
backgroundMesh.onBeforeRender = function ( renderer, scene, camera ) {
const scale = camera.far;
this.matrixWorld.copyPosition( camera.matrixWorld );
this.matrixWorld.makeScale( scale, scale, scale ).copyPosition( camera.matrixWorld );
};

@@ -90,5 +92,5 @@

this.boxMeshNode.node = backgroundNode;
this.backgroundMeshNode.node = backgroundNode;
boxMesh.material.needsUpdate = true;
backgroundMesh.material.needsUpdate = true;

@@ -99,3 +101,3 @@ sceneData.backgroundCacheKey = backgroundCacheKey;

renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );
renderList.unshift( backgroundMesh, backgroundMesh.geometry, backgroundMesh.material, 0, 0, null );

@@ -102,0 +104,0 @@ } else {

@@ -7,6 +7,14 @@ class Binding {

this.visibility = 0;
}
setVisibility( visibility ) {
this.visibility |= visibility;
}
}
export default Binding;

@@ -37,6 +37,4 @@ import DataMap from './DataMap.js';

const pipeline = this.pipelines.getForRender( renderObject );
this.backend.createBindings( bindings );
this.backend.createBindings( bindings, pipeline );
}

@@ -62,6 +60,4 @@

const pipeline = this.pipelines.getForCompute( computeNode );
this.backend.createBindings( bindings );
this.backend.createBindings( bindings, pipeline );
}

@@ -68,0 +64,0 @@

@@ -91,3 +91,3 @@ import DataMap from './DataMap.js';

update( renderObject ) {
updateForRender( renderObject ) {

@@ -94,0 +94,0 @@ if ( this.has( renderObject ) === false ) this.initGeometry( renderObject );

import DataMap from '../DataMap.js';
import { NoToneMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three';
import { NodeFrame, cubeTexture, texture, rangeFog, densityFog, reference, toneMapping, positionWorld, modelWorldMatrix, transformDirection, equirectUV, viewportBottomLeft } from '../../../nodes/Nodes.js';
import { NodeFrame, cubeTexture, texture, rangeFog, densityFog, reference, toneMapping, equirectUV, viewportBottomLeft, normalWorld } from '../../../nodes/Nodes.js';

@@ -80,2 +80,4 @@ class Nodes extends DataMap {

if ( this.isToneMappingState === false ) return null;
return this.renderer.toneMappingNode || this.get( this.renderer ).toneMappingNode || null;

@@ -111,2 +113,11 @@

get isToneMappingState() {
const renderer = this.renderer;
const renderTarget = renderer.getRenderTarget();
return renderTarget && renderTarget.isCubeRenderTarget ? false : true;
}
updateToneMapping() {

@@ -118,3 +129,3 @@

if ( rendererToneMapping !== NoToneMapping ) {
if ( this.isToneMappingState && rendererToneMapping !== NoToneMapping ) {

@@ -155,3 +166,3 @@ if ( rendererData.toneMapping !== rendererToneMapping ) {

backgroundNode = cubeTexture( background, transformDirection( positionWorld, modelWorldMatrix ) );
backgroundNode = cubeTexture( background, normalWorld );

@@ -172,3 +183,3 @@ } else if ( background.isTexture === true ) {

backgroundNode = texture( background, nodeUV );
backgroundNode = texture( background, nodeUV ).setUpdateMatrix( true );

@@ -175,0 +186,0 @@ } else if ( background.isColor !== true ) {

@@ -26,3 +26,3 @@ import DataMap from './DataMap.js';

getForCompute( computeNode ) {
getForCompute( computeNode, bindings ) {

@@ -33,8 +33,13 @@ const { backend } = this;

if ( data.pipeline === undefined ) {
if ( this._needsComputeUpdate( computeNode ) ) {
// release previous cache
const previousPipeline = data.pipeline;
const previousPipeline = this._releasePipeline( computeNode );
if ( previousPipeline ) {
previousPipeline.usedTimes --;
previousPipeline.computeProgram.usedTimes --;
}
// get shader

@@ -50,3 +55,3 @@

if ( previousPipeline ) this._releaseProgram( previousPipeline.computeShader );
if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram );

@@ -62,4 +67,14 @@ stageCompute = new ProgrammableStage( nodeBuilder.computeShader, 'compute' );

const pipeline = this._getComputePipeline( stageCompute );
const cacheKey = this._getComputeCacheKey( computeNode, stageCompute );
let pipeline = this.caches.get( cacheKey );
if ( pipeline === undefined ) {
if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( computeNode );
pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings );
}
// keep track of all used times

@@ -72,2 +87,3 @@

data.version = computeNode.version;
data.pipeline = pipeline;

@@ -87,8 +103,14 @@

if ( this._needsUpdate( renderObject ) ) {
if ( this._needsRenderUpdate( renderObject ) ) {
// release previous cache
const previousPipeline = data.pipeline;
const previousPipeline = this._releasePipeline( renderObject );
if ( previousPipeline ) {
previousPipeline.usedTimes --;
previousPipeline.vertexProgram.usedTimes --;
previousPipeline.fragmentProgram.usedTimes --;
}
// get shader

@@ -104,3 +126,3 @@

if ( previousPipeline ) this._releaseProgram( previousPipeline.vertexProgram );
if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram );

@@ -118,3 +140,3 @@ stageVertex = new ProgrammableStage( nodeBuilder.vertexShader, 'vertex' );

if ( previousPipeline ) this._releaseProgram( previousPipeline.fragmentShader );
if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram );

@@ -130,4 +152,18 @@ stageFragment = new ProgrammableStage( nodeBuilder.fragmentShader, 'fragment' );

const pipeline = this._getRenderPipeline( renderObject, stageVertex, stageFragment );
const cacheKey = this._getRenderCacheKey( renderObject, stageVertex, stageFragment );
let pipeline = this.caches.get( cacheKey );
if ( pipeline === undefined ) {
if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline );
pipeline = this._getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey );
} else {
renderObject.pipeline = pipeline;
}
// keep track of all used times

@@ -151,15 +187,28 @@

const pipeline = this._releasePipeline( object );
const pipeline = this.get( object ).pipeline;
if ( pipeline && pipeline.usedTimes === 0 ) {
if ( pipeline ) {
// pipeline
pipeline.usedTimes --;
if ( pipeline.usedTimes === 0 ) this._releasePipeline( pipeline );
// programs
if ( pipeline.isComputePipeline ) {
this._releaseProgram( pipeline.computeProgram );
pipeline.computeProgram.usedTimes --;
if ( pipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( pipeline.computeProgram );
} else {
this._releaseProgram( pipeline.vertexProgram );
this._releaseProgram( pipeline.fragmentProgram );
pipeline.fragmentProgram.usedTimes --;
pipeline.vertexProgram.usedTimes --;
if ( pipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( pipeline.vertexProgram );
if ( pipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( pipeline.fragmentProgram );
}

@@ -186,7 +235,13 @@

_getComputePipeline( stageCompute ) {
updateForRender( renderObject ) {
this.getForRender( renderObject );
}
_getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) {
// check for existing pipeline
const cacheKey = 'compute:' + stageCompute.id;
cacheKey = cacheKey || this._getComputeCacheKey( computeNode, stageCompute );

@@ -201,3 +256,3 @@ let pipeline = this.caches.get( cacheKey );

this.backend.createComputePipeline( pipeline );
this.backend.createComputePipeline( pipeline, bindings );

@@ -210,7 +265,7 @@ }

_getRenderPipeline( renderObject, stageVertex, stageFragment ) {
_getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey ) {
// check for existing pipeline
const cacheKey = this._getRenderCacheKey( renderObject, stageVertex, stageFragment );
cacheKey = cacheKey || this._getRenderCacheKey( renderObject, stageVertex, stageFragment );

@@ -229,11 +284,11 @@ let pipeline = this.caches.get( cacheKey );

} else {
}
// assign a shared pipeline to renderObject
return pipeline;
renderObject.pipeline = pipeline;
}
}
_getComputeCacheKey( computeNode, stageCompute ) {
return pipeline;
return 'compute' + computeNode.id + stageCompute.id;

@@ -264,32 +319,26 @@ }

_releasePipeline( object ) {
_releasePipeline( pipeline ) {
const pipeline = this.get( object ).pipeline;
this.caches.delete( pipeline.cacheKey );
//this.bindings.delete( object );
}
if ( pipeline && -- pipeline.usedTimes === 0 ) {
_releaseProgram( program ) {
this.caches.delete( pipeline.cacheKey );
const code = program.code;
const stage = program.stage;
}
this.programs[ stage ].delete( code );
return pipeline;
}
_releaseProgram( program ) {
_needsComputeUpdate( computeNode ) {
if ( -- program.usedTimes === 0 ) {
const data = this.get( computeNode );
const code = program.code;
const stage = program.stage;
return data.pipeline === undefined || data.version !== computeNode.version;
this.programs[ stage ].delete( code );
}
}
_needsUpdate( renderObject ) {
_needsRenderUpdate( renderObject ) {

@@ -330,3 +379,3 @@ const data = this.get( renderObject );

return needsUpdate || data.pipeline !== undefined;
return needsUpdate || data.pipeline === undefined;

@@ -333,0 +382,0 @@ }

@@ -32,2 +32,3 @@ import { Vector4 } from 'three';

this.activeCubeFace = 0;
this.sampleCount = 1;

@@ -34,0 +35,0 @@ }

@@ -8,12 +8,15 @@ import ChainMap from './ChainMap.js';

this.renderStates = new ChainMap();
this.chainMaps = {};
}
get( scene, camera ) {
get( scene, camera, renderTarget = null ) {
const chainKey = [ scene, camera ];
const attachmentState = renderTarget === null ? 'default' : `${renderTarget.texture.format}:${renderTarget.samples}:${renderTarget.depthBuffer}:${renderTarget.stencilBuffer}`;
let renderState = this.renderStates.get( chainKey );
const chainMap = this.getChainMap( attachmentState );
let renderState = chainMap.get( chainKey );
if ( renderState === undefined ) {

@@ -23,6 +26,8 @@

this.renderStates.set( chainKey, renderState );
chainMap.set( chainKey, renderState );
}
if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples;
return renderState;

@@ -32,5 +37,11 @@

getChainMap( attachmentState ) {
return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() );
}
dispose() {
this.renderStates = new ChainMap();
this.chainMaps = {};

@@ -37,0 +48,0 @@ }

@@ -13,4 +13,5 @@ import Animation from './Animation.js';

import Nodes from './nodes/Nodes.js';
import { Frustum, Matrix4, Vector2, Vector3, Vector4, Color, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoToneMapping } from 'three';
import { Scene, Frustum, Matrix4, Vector2, Vector3, Vector4, Color, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoToneMapping } from 'three';
const _scene = new Scene();
const _drawingBufferSize = new Vector2();

@@ -141,3 +142,3 @@ const _screen = new Vector4();

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._info );
this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this._info );
this._renderLists = new RenderLists();

@@ -186,4 +187,6 @@ this._renderContexts = new RenderContexts();

const renderContext = this._renderContexts.get( scene, camera );
const sceneRef = ( scene.isScene === true ) ? scene : _scene;
const renderTarget = this._renderTarget;
const renderContext = this._renderContexts.get( scene, camera, renderTarget );
const activeCubeFace = this._activeCubeFace;

@@ -253,2 +256,6 @@

sceneRef.onBeforeRender( this, scene, camera, renderTarget );
//
_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );

@@ -292,7 +299,7 @@ _frustum.setFromProjectionMatrix( _projScreenMatrix, coordinateSystem );

this._nodes.updateScene( scene );
this._nodes.updateScene( sceneRef );
//
this._background.update( scene, renderList, renderContext );
this._background.update( sceneRef, renderList, renderContext );

@@ -309,4 +316,4 @@ //

if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, scene, lightsNode );
if ( transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, scene, lightsNode );
if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode );
if ( transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, sceneRef, lightsNode );

@@ -324,2 +331,6 @@ // finish render pass

//
sceneRef.onAfterRender( this, scene, camera, renderTarget );
}

@@ -339,8 +350,16 @@

async getArrayBuffer( attribute ) {
getArrayBuffer( attribute ) { // @deprecated, r155
return await this.backend.getArrayBuffer( attribute );
console.warn( 'THREE.Renderer: getArrayBuffer() is deprecated. Use getArrayBufferAsync() instead.' );
return this.getArrayBufferAsync( attribute );
}
async getArrayBufferAsync( attribute ) {
return await this.backend.getArrayBufferAsync( attribute );
}
getContext() {

@@ -592,2 +611,8 @@

getRenderTarget() {
return this._renderTarget;
}
async compute( computeNodes ) {

@@ -599,7 +624,9 @@

const pipelines = this._pipelines;
const computeGroup = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];
const bindings = this._bindings;
const nodes = this._nodes;
const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ];
backend.beginCompute( computeGroup );
backend.beginCompute( computeNodes );
for ( const computeNode of computeGroup ) {
for ( const computeNode of computeList ) {

@@ -610,2 +637,16 @@ // onInit

const dispose = () => {
computeNode.removeEventListener( 'dispose', dispose );
pipelines.delete( computeNode );
bindings.delete( computeNode );
nodes.delete( computeNode );
};
computeNode.addEventListener( 'dispose', dispose );
//
computeNode.onInit( { renderer: this } );

@@ -615,22 +656,16 @@

this._nodes.updateForCompute( computeNode );
this._bindings.updateForCompute( computeNode );
nodes.updateForCompute( computeNode );
bindings.updateForCompute( computeNode );
const computePipeline = pipelines.getForCompute( computeNode );
const computeBindings = this._bindings.getForCompute( computeNode );
const computeBindings = bindings.getForCompute( computeNode );
const computePipeline = pipelines.getForCompute( computeNode, computeBindings );
backend.compute( computeGroup, computeNode, computeBindings, computePipeline );
backend.compute( computeNodes, computeNode, computeBindings, computePipeline );
}
backend.finishCompute( computeGroup );
backend.finishCompute( computeNodes );
}
getRenderTarget() {
return this._renderTarget;
}
hasFeature( name ) {

@@ -818,9 +853,2 @@

//
object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
//
material.onBeforeRender( this, scene, camera, geometry, material, group );

@@ -833,6 +861,6 @@

material.side = BackSide;
this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode, 'backSide' ); // create backSide pass id
this._renderObjectDirect( object, material, scene, camera, lightsNode, 'backSide' ); // create backSide pass id
material.side = FrontSide;
this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode ); // use default pass id
this._renderObjectDirect( object, material, scene, camera, lightsNode ); // use default pass id

@@ -843,3 +871,3 @@ material.side = DoubleSide;

this._renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode );
this._renderObjectDirect( object, material, scene, camera, lightsNode );

@@ -854,12 +882,14 @@ }

_renderObjectDirect( object, scene, camera, geometry, material, group, lightsNode, passId ) {
_renderObjectDirect( object, material, scene, camera, lightsNode, passId ) {
const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId );
//
const renderObject = this._objects.get( object, material, scene, camera, lightsNode, passId );
renderObject.context = this._currentRenderContext;
this._nodes.updateBefore( renderObject );
//
this._nodes.updateBefore( renderObject );
object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
object.normalMatrix.getNormalMatrix( object.modelViewMatrix );

@@ -869,4 +899,5 @@ //

this._nodes.updateForRender( renderObject );
this._geometries.update( renderObject );
this._geometries.updateForRender( renderObject );
this._bindings.updateForRender( renderObject );
this._pipelines.updateForRender( renderObject );

@@ -873,0 +904,0 @@ //

@@ -5,3 +5,3 @@ let id = 0;

constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode ) {
constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ) {

@@ -19,2 +19,3 @@ this._nodes = nodes;

this.lightsNode = lightsNode;
this.context = renderContext;

@@ -24,4 +25,4 @@ this.geometry = object.geometry;

this.attributes = null;
this.context = null;
this.pipeline = null;
this.vertexBuffers = null;

@@ -63,3 +64,3 @@ this._materialVersion = - 1;

return [ this.object, this.material, this.scene, this.camera, this.lightsNode ];
return [ this.object, this.material, this.context, this.lightsNode ];

@@ -76,10 +77,17 @@ }

const attributes = [];
const vertexBuffers = new Set();
for ( const nodeAttribute of nodeAttributes ) {
attributes.push( nodeAttribute.node && nodeAttribute.node.attribute ? nodeAttribute.node.attribute : geometry.getAttribute( nodeAttribute.name ) );
const attribute = nodeAttribute.node && nodeAttribute.node.attribute ? nodeAttribute.node.attribute : geometry.getAttribute( nodeAttribute.name );
attributes.push( attribute );
const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute;
vertexBuffers.add( bufferAttribute );
}
this.attributes = attributes;
this.vertexBuffers = Array.from( vertexBuffers.values() );

@@ -90,2 +98,10 @@ return attributes;

getVertexBuffers() {
if ( this.vertexBuffers === null ) this.getAttributes();
return this.vertexBuffers;
}
getCacheKey() {

@@ -92,0 +108,0 @@

@@ -7,3 +7,3 @@ import DataMap from './DataMap.js';

constructor( renderer, nodes, geometries, pipelines, info ) {
constructor( renderer, nodes, geometries, pipelines, bindings, info ) {

@@ -14,2 +14,3 @@ this.renderer = renderer;

this.pipelines = pipelines;
this.bindings = bindings;
this.info = info;

@@ -22,6 +23,6 @@

get( object, material, scene, camera, lightsNode, passId ) {
get( object, material, scene, camera, lightsNode, renderContext, passId ) {
const chainMap = this.getChainMap( passId );
const chainArray = [ object, material, scene, camera, lightsNode ];
const chainArray = [ object, material, renderContext, lightsNode ];

@@ -32,3 +33,3 @@ let renderObject = chainMap.get( chainArray );

renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, passId );
renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, passId );

@@ -46,3 +47,3 @@ chainMap.set( chainArray, renderObject );

renderObject = this.get( object, material, scene, camera, lightsNode );
renderObject = this.get( object, material, scene, camera, lightsNode, renderContext, passId );

@@ -70,8 +71,9 @@ }

createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, passId ) {
createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, passId ) {
const chainMap = this.getChainMap( passId );
const dataMap = this.dataMap;
const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode );
const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext );
const data = dataMap.get( renderObject );

@@ -85,2 +87,3 @@ data.cacheKey = renderObject.getCacheKey();

this.pipelines.delete( renderObject );
this.bindings.delete( renderObject );
this.nodes.delete( renderObject );

@@ -87,0 +90,0 @@

@@ -20,2 +20,3 @@ import DataMap from './DataMap.js';

const renderTargetData = this.get( renderTarget );
const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples;

@@ -52,5 +53,16 @@ const texture = renderTarget.texture;

this.updateTexture( texture );
this.updateTexture( depthTexture );
if ( renderTargetData.sampleCount !== sampleCount ) {
texture.needsUpdate = true;
depthTexture.needsUpdate = true;
renderTargetData.sampleCount = sampleCount;
}
const options = { sampleCount };
this.updateTexture( texture, options );
this.updateTexture( depthTexture, options );
// dispose handler

@@ -79,3 +91,3 @@

updateTexture( texture ) {
updateTexture( texture, options = {} ) {

@@ -85,6 +97,6 @@ const textureData = this.get( texture );

const isRenderTexture = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture;
const isRenderTarget = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture;
const backend = this.backend;
if ( isRenderTexture && textureData.initialized === true ) {
if ( isRenderTarget && textureData.initialized === true ) {

@@ -100,6 +112,6 @@ // it's an update

if ( isRenderTexture ) {
if ( isRenderTarget ) {
backend.createSampler( texture );
backend.createTexture( texture );
backend.createTexture( texture, options );

@@ -128,3 +140,3 @@ } else {

backend.createTexture( texture );
backend.createTexture( texture, options );

@@ -131,0 +143,0 @@ textureData.isDefaultTexture = false;

@@ -1,2 +0,2 @@

import { NoColorSpace } from 'three';
import { RenderTarget, NoColorSpace } from 'three';

@@ -15,3 +15,2 @@ import UniformsGroup from '../../common/UniformsGroup.js';

import RenderTarget from '../../common/RenderTarget.js';
import CubeRenderTarget from '../../common/CubeRenderTarget.js';

@@ -23,3 +22,2 @@

/*
const gpuShaderStageLib = {

@@ -30,3 +28,2 @@ 'vertex': GPUShaderStage.VERTEX,

};
*/

@@ -213,2 +210,16 @@ const supports = {

getTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, shaderStage = this.shaderStage ) {
if ( shaderStage === 'fragment' ) {
return `textureSampleCompare( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${compareSnippet} )`;
} else {
console.error( `WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${ shaderStage } shader.` );
}
}
getTextureLevel( texture, textureProperty, uvSnippet, biasSnippet, shaderStage = this.shaderStage ) {

@@ -280,4 +291,2 @@

const sampler = new NodeSampler( `${uniformNode.name}_sampler`, uniformNode.node );
let texture = null;

@@ -295,2 +304,4 @@

texture.setVisibility( gpuShaderStageLib[ shaderStage ] );
// add first textures in sequence and group for last

@@ -302,2 +313,5 @@ const lastBinding = bindings[ bindings.length - 1 ];

const sampler = new NodeSampler( `${uniformNode.name}_sampler`, uniformNode.node );
sampler.setVisibility( gpuShaderStageLib[ shaderStage ] );
bindings.splice( index, 0, sampler, texture );

@@ -319,3 +333,3 @@

const buffer = new bufferClass( 'NodeBuffer_' + node.id, node.value );
//buffer.setVisibility( gpuShaderStageLib[ shaderStage ] );
buffer.setVisibility( gpuShaderStageLib[ shaderStage ] );

@@ -337,3 +351,3 @@ // add first textures in sequence and group for last

uniformsGroup = new UniformsGroup( 'nodeUniforms' );
//uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );
uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] );

@@ -580,4 +594,14 @@ this.uniformsGroup[ shaderStage ] = uniformsGroup;

bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler;` );
const texture = uniform.node.value;
if ( texture.isDepthTexture === true && texture.compareFunction !== null ) {
bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler_comparison;` );
} else {
bindingSnippets.push( `@binding( ${index ++} ) @group( 0 ) var ${uniform.name}_sampler : sampler;` );
}
}

@@ -584,0 +608,0 @@

@@ -37,20 +37,28 @@ import { Float16BufferAttribute } from 'three';

const backend = this.backend;
const device = backend.device;
const bufferData = backend.get( bufferAttribute );
const array = bufferAttribute.array;
const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
let buffer = bufferData.buffer;
const buffer = device.createBuffer( {
label: bufferAttribute.name,
size: size,
usage: usage,
mappedAtCreation: true
} );
if ( buffer === undefined ) {
new array.constructor( buffer.getMappedRange() ).set( array );
const device = backend.device;
buffer.unmap();
const array = bufferAttribute.array;
const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441
backend.get( attribute ).buffer = buffer;
buffer = device.createBuffer( {
label: bufferAttribute.name,
size: size,
usage: usage,
mappedAtCreation: true
} );
new array.constructor( buffer.getMappedRange() ).set( array );
buffer.unmap();
bufferData.buffer = buffer;
}
}

@@ -65,3 +73,3 @@

const buffer = backend.get( attribute ).buffer;
const buffer = backend.get( bufferAttribute ).buffer;

@@ -98,6 +106,6 @@ const array = bufferAttribute.array;

createShaderAttributes( renderObject ) {
createShaderVertexBuffers( renderObject ) {
const attributes = renderObject.getAttributes();
const shaderAttributes = [];
const vertexBuffers = new Map();

@@ -108,26 +116,39 @@ for ( let slot = 0; slot < attributes.length; slot ++ ) {

const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT;
const bufferAttribute = this._getBufferAttribute( geometryAttribute );
const format = this._getVertexFormat( geometryAttribute );
let vertexBufferLayout = vertexBuffers.get( bufferAttribute );
let arrayStride = geometryAttribute.itemSize * bytesPerElement;
let offset = 0;
let stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
if ( vertexBufferLayout === undefined ) {
if ( geometryAttribute.isInterleavedBufferAttribute === true ) {
let arrayStride, stepMode;
// @TODO: It can be optimized for "vertexBuffers" on RenderPipeline
if ( geometryAttribute.isInterleavedBufferAttribute === true ) {
arrayStride = geometryAttribute.data.stride * bytesPerElement;
offset = geometryAttribute.offset * bytesPerElement;
if ( geometryAttribute.data.isInstancedInterleavedBuffer ) stepMode = GPUInputStepMode.Instance;
arrayStride = geometryAttribute.data.stride * bytesPerElement;
stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
} else {
arrayStride = geometryAttribute.itemSize * bytesPerElement;
stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex;
}
vertexBufferLayout = {
arrayStride,
attributes: [],
stepMode
};
vertexBuffers.set( bufferAttribute, vertexBufferLayout );
}
shaderAttributes.push( {
geometryAttribute,
arrayStride,
stepMode,
const format = this._getVertexFormat( geometryAttribute );
const offset = ( geometryAttribute.isInterleavedBufferAttribute === true ) ? geometryAttribute.offset * bytesPerElement : 0;
vertexBufferLayout.attributes.push( {
shaderLocation: slot,
offset,
format,
slot
format
} );

@@ -137,3 +158,3 @@

return shaderAttributes;
return Array.from( vertexBuffers.values() );

@@ -145,3 +166,3 @@ }

const backend = this.backend;
const data = backend.get( attribute );
const data = backend.get( this._getBufferAttribute( attribute ) );

@@ -154,3 +175,3 @@ data.buffer.destroy();

async getArrayBuffer( attribute ) {
async getArrayBufferAsync( attribute ) {

@@ -160,6 +181,4 @@ const backend = this.backend;

const data = backend.get( attribute );
const data = backend.get( this._getBufferAttribute( attribute ) );
//const bufferAttribute = this._getBufferAttribute( attribute );
const bufferGPU = data.buffer;

@@ -166,0 +185,0 @@ const size = bufferGPU.size;

import {
GPUTextureAspect, GPUTextureViewDimension
GPUTextureAspect, GPUTextureViewDimension, GPUBufferBindingType
} from './WebGPUConstants.js';

@@ -13,5 +13,85 @@

createBindings( bindings, pipeline ) {
createBindingsLayout( bindings ) {
const backend = this.backend;
const device = backend.device;
const entries = [];
let index = 0;
for ( const binding of bindings ) {
const bindingGPU = {
binding: index ++,
visibility: binding.visibility
};
if ( binding.isUniformBuffer || binding.isStorageBuffer ) {
const buffer = {}; // GPUBufferBindingLayout
if ( binding.isStorageBuffer ) {
buffer.type = GPUBufferBindingType.Storage;
}
bindingGPU.buffer = buffer;
} else if ( binding.isSampler ) {
const sampler = {}; // GPUSamplerBindingLayout
if ( binding.texture.isDepthTexture ) {
if ( binding.texture.compareFunction !== null ) {
sampler.type = 'comparison';
}
}
bindingGPU.sampler = sampler;
} else if ( binding.isSampledTexture && binding.texture.isVideoTexture ) {
bindingGPU.externalTexture = {}; // GPUExternalTextureBindingLayout
} else if ( binding.isSampledTexture ) {
const texture = {}; // GPUTextureBindingLayout
if ( binding.texture.isDepthTexture ) {
texture.sampleType = 'depth';
}
if ( binding.isSampledCubeTexture ) {
texture.viewDimension = GPUTextureViewDimension.Cube;
}
bindingGPU.texture = texture;
} else {
console.error( 'WebGPUBindingUtils: Unsupported binding "${ binding }".' );
}
entries.push( bindingGPU );
}
return device.createBindGroupLayout( { entries } );
}
createBindings( bindings ) {
const backend = this.backend;
const bindingsData = backend.get( bindings );

@@ -21,5 +101,3 @@

const pipelineGPU = backend.get( pipeline ).pipeline;
const bindLayoutGPU = pipelineGPU.getBindGroupLayout( 0 );
const bindLayoutGPU = this.createBindingsLayout( bindings );
const bindGroupGPU = this.createBindGroup( bindings, bindLayoutGPU );

@@ -26,0 +104,0 @@

@@ -217,8 +217,2 @@ export const GPUPrimitiveTopology = {

export const GPUSamplerBindingType = {
Filtering: 'filtering',
NonFiltering: 'non-filtering',
Comparison: 'comparison'
};
export const GPUFilterMode = {

@@ -232,13 +226,13 @@ Linear: 'linear',

One: 'one',
SrcColor: 'src-color',
OneMinusSrcColor: 'one-minus-src-color',
Src: 'src',
OneMinusSrc: 'one-minus-src',
SrcAlpha: 'src-alpha',
OneMinusSrcAlpha: 'one-minus-src-alpha',
DstColor: 'dst-color',
OneMinusDstColor: 'one-minus-dst-color',
Dst: 'dst',
OneMinusDstColor: 'one-minus-dst',
DstAlpha: 'dst-alpha',
OneMinusDstAlpha: 'one-minus-dst-alpha',
SrcAlphaSaturated: 'src-alpha-saturated',
BlendColor: 'blend-color',
OneMinusBlendColor: 'one-minus-blend-color'
Constant: 'constant',
OneMinusConstant: 'one-minus-constant'
};

@@ -274,14 +268,22 @@

export const GPUBindingType = {
UniformBuffer: 'uniform-buffer',
StorageBuffer: 'storage-buffer',
ReadonlyStorageBuffer: 'readonly-storage-buffer',
Sampler: 'sampler',
ComparisonSampler: 'comparison-sampler',
SampledTexture: 'sampled-texture',
MultisampledTexture: 'multisampled-texture',
ReadonlyStorageTexture: 'readonly-storage-texture',
WriteonlyStorageTexture: 'writeonly-storage-texture'
export const GPUBufferBindingType = {
Uniform: 'uniform',
Storage: 'storage',
ReadOnlyStorage: 'read-only-storage'
};
export const GPUSamplerBindingType = {
Filtering: 'filtering',
NonFiltering: 'non-filtering',
Comparison: 'comparison'
};
export const GPUTextureSampleType = {
Float: 'float',
UnfilterableFloat: 'unfilterable-float',
Depth: 'depth',
SInt: 'sint',
UInt: 'uint'
};
export const GPUTextureDimension = {

@@ -288,0 +290,0 @@ OneD: '1d',

@@ -36,21 +36,8 @@ import { BlendColorFactor, OneMinusBlendColorFactor, } from '../../common/Constants.js';

const pipelineData = backend.get( pipeline );
const bindingsData = backend.get( renderObject.getBindings() );
// determine shader attributes
const shaderAttributes = backend.attributeUtils.createShaderAttributes( renderObject );
// vertex buffers
const vertexBuffers = [];
const vertexBuffers = backend.attributeUtils.createShaderVertexBuffers( renderObject );
for ( const attribute of shaderAttributes ) {
vertexBuffers.push( {
arrayStride: attribute.arrayStride,
attributes: [ { shaderLocation: attribute.slot, offset: attribute.offset, format: attribute.format } ],
stepMode: attribute.stepMode
} );
}
// blending

@@ -62,6 +49,3 @@

blending = {
alpha: this._getAlphaBlend( material ),
color: this._getColorBlend( material )
};
blending = this._getBlending( material );

@@ -117,3 +101,5 @@ }

},
layout: 'auto'
layout: device.createPipelineLayout( {
bindGroupLayouts: [ bindingsData.layout ]
} )
} );

@@ -123,3 +109,3 @@

createComputePipeline( pipeline ) {
createComputePipeline( pipeline, bindings ) {

@@ -132,6 +118,9 @@ const backend = this.backend;

const pipelineGPU = backend.get( pipeline );
const bindingsData = backend.get( bindings );
pipelineGPU.pipeline = device.createComputePipeline( {
compute: computeProgram,
layout: 'auto'
layout: device.createPipelineLayout( {
bindGroupLayouts: [ bindingsData.layout ]
} )
} );

@@ -141,88 +130,104 @@

_getAlphaBlend( material ) {
_getBlending( material ) {
let color, alpha;
const blending = material.blending;
const premultipliedAlpha = material.premultipliedAlpha;
let alphaBlend = undefined;
if ( blending === CustomBlending ) {
switch ( blending ) {
const blendSrcAlpha = material.blendSrcAlpha !== null ? material.blendSrcAlpha : GPUBlendFactor.One;
const blendDstAlpha = material.blendDstAlpha !== null ? material.blendDstAlpha : GPUBlendFactor.Zero;
const blendEquationAlpha = material.blendEquationAlpha !== null ? material.blendEquationAlpha : GPUBlendFactor.Add;
case NormalBlending:
color = {
srcFactor: this._getBlendFactor( material.blendSrc ),
dstFactor: this._getBlendFactor( material.blendDst ),
operation: this._getBlendOperation( material.blendEquation )
};
if ( premultipliedAlpha === false ) {
alpha = {
srcFactor: this._getBlendFactor( blendSrcAlpha ),
dstFactor: this._getBlendFactor( blendDstAlpha ),
operation: this._getBlendOperation( blendEquationAlpha )
};
alphaBlend = {
srcFactor: GPUBlendFactor.One,
dstFactor: GPUBlendFactor.OneMinusSrcAlpha,
operation: GPUBlendOperation.Add
};
} else {
}
const premultipliedAlpha = material.premultipliedAlpha;
break;
const setBlend = ( srcRGB, dstRGB, srcAlpha, dstAlpha ) => {
case AdditiveBlending:
color = {
srcFactor: srcRGB,
dstFactor: dstRGB,
operation: GPUBlendOperation.Add
};
alphaBlend = {
srcFactor: GPUBlendFactor.Zero,
dstFactor: GPUBlendFactor.One,
alpha = {
srcFactor: srcAlpha,
dstFactor: dstAlpha,
operation: GPUBlendOperation.Add
};
break;
};
case SubtractiveBlending:
if ( premultipliedAlpha ) {
if ( premultipliedAlpha === true ) {
switch ( blending ) {
alphaBlend = {
srcFactor: GPUBlendFactor.OneMinusSrcColor,
dstFactor: GPUBlendFactor.OneMinusSrcAlpha,
operation: GPUBlendOperation.Add
};
case NormalBlending:
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
break;
case AdditiveBlending:
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One );
break;
case SubtractiveBlending:
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
break;
case MultiplyBlending:
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.SrcAlpha );
break;
}
break;
} else {
case MultiplyBlending:
switch ( blending ) {
if ( premultipliedAlpha === true ) {
case NormalBlending:
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha );
break;
alphaBlend = {
srcFactor: GPUBlendFactor.Zero,
dstFactor: GPUBlendFactor.SrcAlpha,
operation: GPUBlendOperation.Add
};
case AdditiveBlending:
setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.SrcAlpha, GPUBlendFactor.One );
break;
}
case SubtractiveBlending:
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One );
break;
break;
case MultiplyBlending:
setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.Src );
break;
case CustomBlending:
}
const blendSrcAlpha = material.blendSrcAlpha;
const blendDstAlpha = material.blendDstAlpha;
const blendEquationAlpha = material.blendEquationAlpha;
}
if ( blendSrcAlpha !== null && blendDstAlpha !== null && blendEquationAlpha !== null ) {
}
alphaBlend = {
srcFactor: this._getBlendFactor( blendSrcAlpha ),
dstFactor: this._getBlendFactor( blendDstAlpha ),
operation: this._getBlendOperation( blendEquationAlpha )
};
if ( color !== undefined && alpha !== undefined ) {
}
return { color, alpha };
break;
} else {
default:
console.error( 'THREE.WebGPURenderer: Blending not supported.', blending );
console.error( 'THREE.WebGPURenderer: Invalid blending: ', blending );
}
return alphaBlend;
}

@@ -245,7 +250,7 @@

case SrcColorFactor:
blendFactor = GPUBlendFactor.SrcColor;
blendFactor = GPUBlendFactor.Src;
break;
case OneMinusSrcColorFactor:
blendFactor = GPUBlendFactor.OneMinusSrcColor;
blendFactor = GPUBlendFactor.OneMinusSrc;
break;

@@ -262,3 +267,3 @@

case DstColorFactor:
blendFactor = GPUBlendFactor.DstColor;
blendFactor = GPUBlendFactor.Dst;
break;

@@ -283,7 +288,7 @@

case BlendColorFactor:
blendFactor = GPUBlendFactor.BlendColor;
blendFactor = GPUBlendFactor.Constant;
break;
case OneMinusBlendColorFactor:
blendFactor = GPUBlendFactor.OneMinusBlendColor;
blendFactor = GPUBlendFactor.OneMinusConstant;
break;

@@ -300,54 +305,2 @@

_getColorBlend( material ) {
const blending = material.blending;
const premultipliedAlpha = material.premultipliedAlpha;
const colorBlend = {
srcFactor: null,
dstFactor: null,
operation: null
};
switch ( blending ) {
case NormalBlending:
colorBlend.srcFactor = ( premultipliedAlpha === true ) ? GPUBlendFactor.One : GPUBlendFactor.SrcAlpha;
colorBlend.dstFactor = GPUBlendFactor.OneMinusSrcAlpha;
colorBlend.operation = GPUBlendOperation.Add;
break;
case AdditiveBlending:
colorBlend.srcFactor = ( premultipliedAlpha === true ) ? GPUBlendFactor.One : GPUBlendFactor.SrcAlpha;
colorBlend.dstFactor = GPUBlendFactor.One;
colorBlend.operation = GPUBlendOperation.Add;
break;
case SubtractiveBlending:
colorBlend.srcFactor = GPUBlendFactor.Zero;
colorBlend.dstFactor = ( premultipliedAlpha === true ) ? GPUBlendFactor.Zero : GPUBlendFactor.OneMinusSrcColor;
colorBlend.operation = GPUBlendOperation.Add;
break;
case MultiplyBlending:
colorBlend.srcFactor = GPUBlendFactor.Zero;
colorBlend.dstFactor = GPUBlendFactor.SrcColor;
colorBlend.operation = GPUBlendOperation.Add;
break;
case CustomBlending:
colorBlend.srcFactor = this._getBlendFactor( material.blendSrc );
colorBlend.dstFactor = this._getBlendFactor( material.blendDst );
colorBlend.operation = this._getBlendOperation( material.blendEquation );
break;
default:
console.error( 'THREE.WebGPURenderer: Blending not supported.', blending );
}
return colorBlend;
}
_getStencilCompare( material ) {

@@ -354,0 +307,0 @@

@@ -22,9 +22,9 @@ import {

[ NeverCompare ]: 'never',
[ AlwaysCompare ]: 'less',
[ LessCompare ]: 'equal',
[ LessCompare ]: 'less',
[ EqualCompare ]: 'equal',
[ LessEqualCompare ]: 'less-equal',
[ EqualCompare ]: 'greater',
[ GreaterEqualCompare ]: 'not-equal',
[ GreaterCompare ]: 'greater-equal',
[ NotEqualCompare ]: 'always'
[ GreaterCompare ]: 'greater',
[ GreaterEqualCompare ]: 'greater-equal',
[ AlwaysCompare ]: 'always',
[ NotEqualCompare ]: 'not-equal'
};

@@ -107,4 +107,5 @@

const format = texture.internalFormat || this._getFormat( texture );
//const sampleCount = texture.isRenderTargetTexture || texture.isDepthTexture ? backend.utils.getSampleCount( renderContext ) : 1;
const sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1;
const primarySampleCount = texture.isRenderTargetTexture ? 1 : sampleCount;

@@ -127,3 +128,3 @@ let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC;

mipLevelCount: mipLevelCount,
sampleCount: sampleCount,
sampleCount: primarySampleCount,
dimension: dimension,

@@ -150,2 +151,10 @@ format: format,

if ( format === undefined ) {
console.warn( 'WebGPURenderer: Texture format not supported.' );
return this.createDefaultTexture( texture );
}
textureData.texture = backend.device.createTexture( textureDescriptorGPU );

@@ -155,2 +164,13 @@

if ( texture.isRenderTargetTexture && sampleCount > 1 ) {
const msaaTextureDescriptorGPU = Object.assign( {}, textureDescriptorGPU );
msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + '-msaa';
msaaTextureDescriptorGPU.sampleCount = sampleCount;
textureData.msaaTexture = backend.device.createTexture( msaaTextureDescriptorGPU );
}
textureData.initialized = true;

@@ -170,2 +190,4 @@

if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy();
backend.delete( texture );

@@ -210,2 +232,5 @@

if ( textureDescriptorGPU === undefined ) // unsupported texture format
return;
// transfer texture data

@@ -253,2 +278,4 @@

if ( texture.onUpdate ) texture.onUpdate( texture );
}

@@ -255,0 +282,0 @@

@@ -82,3 +82,3 @@ import { GPUPrimitiveTopology, GPUTextureFormat } from './WebGPUConstants.js';

return 1;
return renderContext.sampleCount;

@@ -85,0 +85,0 @@ }

@@ -57,3 +57,4 @@ /*// debugger tools

this.depthBuffers = new WeakMap();
this.defaultDepthTexture = new DepthTexture();
this.defaultDepthTexture.name = 'depthBuffer';

@@ -127,5 +128,5 @@ this.utils = new WebGPUUtils( this );

async getArrayBuffer( attribute ) {
async getArrayBufferAsync( attribute ) {
return await this.attributeUtils.getArrayBuffer( attribute );
return await this.attributeUtils.getArrayBufferAsync( attribute );

@@ -159,5 +160,3 @@ }

// @TODO: Support RenderTarget with antialiasing.
colorAttachment.view = textureData.texture.createView( {
const view = textureData.texture.createView( {
baseMipLevel: 0,

@@ -169,2 +168,14 @@ mipLevelCount: 1,

if ( textureData.msaaTexture !== undefined ) {
colorAttachment.view = textureData.msaaTexture.createView();
colorAttachment.resolveTarget = view;
} else {
colorAttachment.view = view;
colorAttachment.resolveTarget = undefined;
}
depthStencilAttachment.view = depthTextureData.texture.createView();

@@ -445,14 +456,14 @@

const attributes = renderObject.getAttributes();
const vertexBuffers = renderObject.getVertexBuffers();
for ( let i = 0, l = attributes.length; i < l; i ++ ) {
for ( let i = 0, l = vertexBuffers.length; i < l; i ++ ) {
const attribute = attributes[ i ];
const vertexBuffer = vertexBuffers[ i ];
if ( attributesSet[ i ] !== attribute ) {
if ( attributesSet[ i ] !== vertexBuffer ) {
const buffer = this.get( attribute ).buffer;
const buffer = this.get( vertexBuffer ).buffer;
passEncoderGPU.setVertexBuffer( i, buffer );
attributesSet[ i ] = attribute;
attributesSet[ i ] = vertexBuffer;

@@ -562,5 +573,5 @@ }

createTexture( texture ) {
createTexture( texture, options ) {
this.textureUtils.createTexture( texture );
this.textureUtils.createTexture( texture, options );

@@ -622,5 +633,5 @@ }

createComputePipeline( computePipeline ) {
createComputePipeline( computePipeline, bindings ) {
this.pipelineUtils.createComputePipeline( computePipeline );
this.pipelineUtils.createComputePipeline( computePipeline, bindings );

@@ -631,11 +642,11 @@ }

createBindings( bindings, pipeline ) {
createBindings( bindings ) {
this.bindingUtils.createBindings( bindings, pipeline );
this.bindingUtils.createBindings( bindings );
}
updateBindings( bindings, pipeline ) {
updateBindings( bindings ) {
this.bindingUtils.createBindings( bindings, pipeline );
this.bindingUtils.createBindings( bindings );

@@ -764,32 +775,36 @@ }

const { depthBuffers } = this;
const { width, height } = this.getDrawingBufferSize();
let depthTexture = depthBuffers.get( renderContext );
const depthTexture = this.defaultDepthTexture;
const depthTextureGPU = this.get( depthTexture ).texture;
if ( depthTexture !== undefined && depthTexture.image.width === width && depthTexture.image.height === height ) {
let format, type;
return this.get( depthTexture ).texture;
if ( renderContext.stencil ) {
format = DepthStencilFormat;
type = UnsignedInt248Type;
} else if ( renderContext.depth ) {
format = DepthFormat;
type = UnsignedIntType;
}
this._destroyDepthBufferGPU( renderContext );
if ( depthTextureGPU !== undefined ) {
depthTexture = new DepthTexture();
depthTexture.name = 'depthBuffer';
if ( depthTexture.image.width === width && depthTexture.image.height === height && depthTexture.format === format && depthTexture.type === type ) {
if ( renderContext.stencil ) {
return depthTextureGPU;
depthTexture = new DepthTexture();
depthTexture.format = DepthStencilFormat;
depthTexture.type = UnsignedInt248Type;
}
} else if ( renderContext.depth ) {
this.textureUtils.destroyTexture( depthTexture );
depthTexture = new DepthTexture();
depthTexture.format = DepthFormat;
depthTexture.type = UnsignedIntType;
}
depthTexture.name = 'depthBuffer';
depthTexture.format = format;
depthTexture.type = type;
depthTexture.image.width = width;

@@ -800,4 +815,2 @@ depthTexture.image.height = height;

depthBuffers.set( renderContext, depthTexture );
return this.get( depthTexture ).texture;

@@ -807,18 +820,2 @@

_destroyDepthBufferGPU( renderContext ) {
const { depthBuffers } = this;
const depthTexture = depthBuffers.get( renderContext );
if ( depthTexture !== undefined ) {
this.textureUtils.destroyTexture( depthTexture );
depthBuffers.delete( renderContext );
}
}
_configureContext() {

@@ -825,0 +822,0 @@

@@ -0,1 +1,5 @@

import {
ShaderChunk
} from 'three';
const OutputShader = {

@@ -11,3 +15,10 @@

vertexShader: /* glsl */`
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;

@@ -23,6 +34,8 @@

fragmentShader: /* glsl */`
precision highp float;
uniform sampler2D tDiffuse;
#include <tonemapping_pars_fragment>
` + ShaderChunk[ 'tonemapping_pars_fragment' ] + ShaderChunk[ 'colorspace_pars_fragment' ] + `

@@ -57,4 +70,8 @@ varying vec2 vUv;

gl_FragColor = LinearTosRGB( gl_FragColor );
#ifdef SRGB_COLOR_SPACE
gl_FragColor = LinearTosRGB( gl_FragColor );
#endif
}`

@@ -61,0 +78,0 @@

@@ -1232,4 +1232,11 @@ import {

// Creates a new, non-indexed geometry with smooth normals everywhere except faces that meet at
// an angle greater than the crease angle.
/**
* Modifies the supplied geometry if it is non-indexed, otherwise creates a new,
* non-indexed geometry. Returns the geometry with smooth normals everywhere except
* faces that meet at an angle greater than the crease angle.
*
* @param {BufferGeometry} geometry
* @param {number} [creaseAngle]
* @return {BufferGeometry}
*/
function toCreasedNormals( geometry, creaseAngle = Math.PI / 3 /* 60 degrees */ ) {

@@ -1240,3 +1247,3 @@

// reusable vertors
// reusable vectors
const verts = [ new Vector3(), new Vector3(), new Vector3() ];

@@ -1258,3 +1265,5 @@ const tempVec1 = new Vector3();

const resultGeometry = geometry.toNonIndexed();
// BufferGeometry.toNonIndexed() warns if the geometry is non-indexed
// and returns the original geometry
const resultGeometry = geometry.index ? geometry.toNonIndexed() : geometry;
const posAttr = resultGeometry.attributes.position;

@@ -1261,0 +1270,0 @@ const vertexMap = {};

@@ -73,4 +73,4 @@ import * as THREE from 'three';

this.pointerGeometry.dispose();
this.pointerMesh.material.dispose();
if ( this.pointerGeometry ) this.pointerGeometry.dispose();
if ( this.pointerMesh && this.pointerMesh.material ) this.pointerMesh.material.dispose();

@@ -77,0 +77,0 @@ this.clear();

{
"name": "three",
"version": "0.154.0",
"version": "0.155.0",
"description": "JavaScript 3D library",

@@ -106,3 +106,3 @@ "type": "module",

"rollup-plugin-visualizer": "^5.9.0",
"servez": "^1.14.2"
"servez": "^2.0.0"
},

@@ -109,0 +109,0 @@ "overrides": {

@@ -439,3 +439,3 @@ // Characters [].:/ are reserved for track binding syntax.

console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' );
console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' );
return;

@@ -442,0 +442,0 @@

@@ -1,2 +0,2 @@

import { NoToneMapping, WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
import { WebGLCoordinateSystem, WebGPUCoordinateSystem } from '../constants.js';
import { Object3D } from '../core/Object3D.js';

@@ -129,6 +129,4 @@ import { PerspectiveCamera } from './PerspectiveCamera.js';

const currentToneMapping = renderer.toneMapping;
const currentXrEnabled = renderer.xr.enabled;
renderer.toneMapping = NoToneMapping;
renderer.xr.enabled = false;

@@ -162,3 +160,2 @@

renderer.toneMapping = currentToneMapping;
renderer.xr.enabled = currentXrEnabled;

@@ -165,0 +162,0 @@

@@ -1,2 +0,2 @@

export const REVISION = '154';
export const REVISION = '155';

@@ -3,0 +3,0 @@ export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };

@@ -178,2 +178,22 @@ import { Vector3 } from '../math/Vector3.js';

getComponent( index, component ) {
let value = this.array[ index * this.itemSize + component ];
if ( this.normalized ) value = denormalize( value, this.array );
return value;
}
setComponent( index, component, value ) {
if ( this.normalized ) value = normalize( value, this.array );
this.array[ index * this.itemSize + component ] = value;
return this;
}
getX( index ) {

@@ -180,0 +200,0 @@

@@ -948,3 +948,3 @@ import { Quaternion } from '../math/Quaternion.js';

this.animations = source.animations;
this.animations = source.animations.slice();

@@ -951,0 +951,0 @@ this.userData = JSON.parse( JSON.stringify( source.userData ) );

@@ -18,3 +18,3 @@ import { Path } from '../extras/core/Path.js';

radius: radius,
height: length,
length: length,
capSegments: capSegments,

@@ -21,0 +21,0 @@ radialSegments: radialSegments,

@@ -33,6 +33,25 @@ import { LinearFilter, LinearMipmapLinearFilter, ClampToEdgeWrapping } from '../constants.js';

const texData = scope.parse( buffer );
let texData;
if ( ! texData ) return;
try {
texData = scope.parse( buffer );
} catch ( error ) {
if ( onError !== undefined ) {
onError( error );
} else {
console.error( error );
return;
}
}
if ( ! texData ) return onError(); // TODO: Remove this when all loaders properly throw errors
if ( texData.image !== undefined ) {

@@ -39,0 +58,0 @@

@@ -67,3 +67,3 @@ export default /* glsl */`

return vec3( 1.0 );
return vec3( 1.0 );

@@ -77,3 +77,2 @@ }

float R12 = F_Schlick( R0, 1.0, cosTheta1 );
float R21 = R12;
float T121 = 1.0 - R12;

@@ -80,0 +79,0 @@ float phi12 = 0.0;

@@ -131,3 +131,3 @@ import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js';

} else {
} else if ( geometryPosition !== undefined ) {

@@ -147,2 +147,6 @@ const array = geometryPosition.array;

} else {
return;
}

@@ -149,0 +153,0 @@

@@ -231,3 +231,3 @@ import { BackSide } from '../../constants.js';

// artist-friendly light intensity scaling factor
const scaleFactor = ( renderer.useLegacyLights === true ) ? Math.PI : 1;
const scaleFactor = ( renderer._useLegacyLights === true ) ? Math.PI : 1;

@@ -234,0 +234,0 @@ uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor;

@@ -163,2 +163,14 @@ import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, NormalBlending, LinearSRGBColorSpace } from '../../constants.js';

let toneMapping = NoToneMapping;
if ( material.toneMapped ) {
if ( currentRenderTarget === null || currentRenderTarget.isXRRenderTarget === true ) {
toneMapping = renderer.toneMapping;
}
}
const parameters = {

@@ -324,4 +336,4 @@

toneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,
useLegacyLights: renderer.useLegacyLights,
toneMapping: toneMapping,
useLegacyLights: renderer._useLegacyLights,

@@ -328,0 +340,0 @@ premultipliedAlpha: material.premultipliedAlpha,

@@ -160,2 +160,13 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, UnsignedByteType, _SRGBAFormat, NoColorSpace, LinearSRGBColorSpace, SRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare } from '../../constants.js';

if ( glFormat === _gl.RED_INTEGER ) {
if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI;
if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI;
if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI;
if ( glType === _gl.BYTE ) internalFormat = _gl.R8I;
if ( glType === _gl.SHORT ) internalFormat = _gl.R16I;
if ( glType === _gl.INT ) internalFormat = _gl.R32I;
}
if ( glFormat === _gl.RG ) {

@@ -337,3 +348,12 @@

_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
if ( Array.isArray( renderTargetProperties.__webglFramebuffer[ i ] ) ) {
for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[ i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ][ level ] );
} else {
_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
}
if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );

@@ -345,3 +365,12 @@

_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
if ( Array.isArray( renderTargetProperties.__webglFramebuffer ) ) {
for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] );
} else {
_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
}
if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );

@@ -1321,3 +1350,3 @@ if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );

// Setup storage for target texture and bind it to correct framebuffer
function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget ) {
function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) {

@@ -1331,9 +1360,12 @@ const glFormat = utils.convert( texture.format, texture.colorSpace );

const width = Math.max( 1, renderTarget.width >> level );
const height = Math.max( 1, renderTarget.height >> level );
if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
state.texImage3D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, renderTarget.depth, 0, glFormat, glType, null );
state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType, null );
} else {
state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType, null );

@@ -1352,3 +1384,3 @@ }

_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0 );
_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level );

@@ -1574,3 +1606,3 @@ }

setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 );

@@ -1622,4 +1654,18 @@ }

renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
renderTargetProperties.__webglFramebuffer[ i ] = [];
for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
renderTargetProperties.__webglFramebuffer[ i ][ level ] = _gl.createFramebuffer();
}
} else {
renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
}
}

@@ -1629,4 +1675,18 @@

renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
renderTargetProperties.__webglFramebuffer = [];
for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer();
}
} else {
renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
}
if ( isMultipleRenderTargets ) {

@@ -1710,4 +1770,16 @@

setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, level );
}
} else {
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0 );
}
}

@@ -1734,3 +1806,3 @@

setTextureParameters( _gl.TEXTURE_2D, attachment, supportsMips );
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D );
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, 0 );

@@ -1767,4 +1839,17 @@ if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) {

setTextureParameters( glTextureType, texture, supportsMips );
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType );
if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level );
}
} else {
setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 );
}
if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {

@@ -1771,0 +1856,0 @@

@@ -47,4 +47,2 @@ import { WebGLRenderTarget } from './WebGLRenderTarget.js';

return this;
}

@@ -51,0 +49,0 @@

@@ -1,122 +0,15 @@

import { EventDispatcher } from '../core/EventDispatcher.js';
import { Texture } from '../textures/Texture.js';
import { LinearFilter, NoColorSpace, SRGBColorSpace, sRGBEncoding } from '../constants.js';
import { Vector4 } from '../math/Vector4.js';
import { Source } from '../textures/Source.js';
import { warnOnce } from '../utils.js';
import { RenderTarget } from '../core/RenderTarget.js';
/*
In options, we can specify:
* Texture parameters for an auto-generated target texture
* depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers
*/
class WebGLRenderTarget extends EventDispatcher {
class WebGLRenderTarget extends RenderTarget {
constructor( width = 1, height = 1, options = {} ) {
super();
super( width, height, options );
this.isWebGLRenderTarget = true;
this.width = width;
this.height = height;
this.depth = 1;
this.scissor = new Vector4( 0, 0, width, height );
this.scissorTest = false;
this.viewport = new Vector4( 0, 0, width, height );
const image = { width: width, height: height, depth: 1 };
if ( options.encoding !== undefined ) {
// @deprecated, r152
warnOnce( 'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' );
options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
}
this.texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
this.texture.isRenderTargetTexture = true;
this.texture.flipY = false;
this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
this.texture.internalFormat = options.internalFormat !== undefined ? options.internalFormat : null;
this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : false;
this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;
this.samples = options.samples !== undefined ? options.samples : 0;
}
setSize( width, height, depth = 1 ) {
if ( this.width !== width || this.height !== height || this.depth !== depth ) {
this.width = width;
this.height = height;
this.depth = depth;
this.texture.image.width = width;
this.texture.image.height = height;
this.texture.image.depth = depth;
this.dispose();
}
this.viewport.set( 0, 0, width, height );
this.scissor.set( 0, 0, width, height );
}
clone() {
return new this.constructor().copy( this );
}
copy( source ) {
this.width = source.width;
this.height = source.height;
this.depth = source.depth;
this.scissor.copy( source.scissor );
this.scissorTest = source.scissorTest;
this.viewport.copy( source.viewport );
this.texture = source.texture.clone();
this.texture.isRenderTargetTexture = true;
// ensure image object is not shared, see #20328
const image = Object.assign( {}, source.texture.image );
this.texture.source = new Source( image );
this.depthBuffer = source.depthBuffer;
this.stencilBuffer = source.stencilBuffer;
if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone();
this.samples = source.samples;
return this;
}
dispose() {
this.dispatchEvent( { type: 'dispose' } );
}
}
export { WebGLRenderTarget };

@@ -37,2 +37,3 @@ import { REVISION } from './constants.js';

export { CompressedArrayTexture } from './textures/CompressedArrayTexture.js';
export { CompressedCubeTexture } from './textures/CompressedCubeTexture.js';
export { CubeTexture } from './textures/CubeTexture.js';

@@ -95,2 +96,3 @@ export { CanvasTexture } from './textures/CanvasTexture.js';

export { AnimationAction } from './animation/AnimationAction.js';
export { RenderTarget } from './core/RenderTarget.js';
export { Uniform } from './core/Uniform.js';

@@ -97,0 +99,0 @@ export { UniformsGroup } from './core/UniformsGroup.js';

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc