three
Advanced tools
Comparing version 0.139.2 to 0.140.0
@@ -1866,3 +1866,3 @@ ( function () { | ||
const exposePropertyNames = [ 'specular', 'shininess', 'opacity', 'diffuse', 'map', 'matcap', 'gradientMap', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalScale', 'displacemantBias', 'displacemantMap', 'displacemantScale', 'specularMap', 'alphaMap', 'envMap', 'reflectivity', 'refractionRatio' ]; | ||
const exposePropertyNames = [ 'specular', 'opacity', 'diffuse', 'map', 'matcap', 'gradientMap', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalScale', 'displacemantBias', 'displacemantMap', 'displacemantScale', 'specularMap', 'alphaMap', 'envMap', 'reflectivity', 'refractionRatio' ]; | ||
@@ -1884,4 +1884,19 @@ for ( const propertyName of exposePropertyNames ) { | ||
} | ||
} // Special path for shininess to handle zero shininess properly | ||
this._shininess = 30; | ||
Object.defineProperty( this, 'shininess', { | ||
get: function () { | ||
return this._shininess; | ||
}, | ||
set: function ( value ) { | ||
this._shininess = value; | ||
this.uniforms.shininess.value = Math.max( this._shininess, 1e-4 ); // To prevent pow( 0.0, 0.0 ) | ||
} | ||
} ); | ||
Object.defineProperty( this, 'color', Object.getOwnPropertyDescriptor( this, 'diffuse' ) ); | ||
@@ -1888,0 +1903,0 @@ this.setValues( parameters ); |
@@ -677,3 +677,3 @@ ( function () { | ||
this.onBeforeRender = function () { | ||
this.update = function () { | ||
@@ -705,12 +705,7 @@ this.count = 0; // Triangulate. Yeah, this is slow. | ||
} // reset unneeded data | ||
} // set the draw range to only the processed triangles | ||
for ( let i = this.count * 3; i < this.positionArray.length; i ++ ) { | ||
this.geometry.setDrawRange( 0, this.count ); // update geometry data | ||
this.positionArray[ i ] = 0.0; | ||
} // update geometry data | ||
geometry.getAttribute( 'position' ).needsUpdate = true; | ||
@@ -717,0 +712,0 @@ geometry.getAttribute( 'normal' ).needsUpdate = true; |
@@ -9,2 +9,3 @@ ( function () { | ||
this.type = 'Reflector'; | ||
this.camera = new THREE.PerspectiveCamera(); | ||
const scope = this; | ||
@@ -29,3 +30,3 @@ const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F ); | ||
const textureMatrix = new THREE.Matrix4(); | ||
const virtualCamera = new THREE.PerspectiveCamera(); | ||
const virtualCamera = this.camera; | ||
const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, { | ||
@@ -201,2 +202,4 @@ samples: multisample | ||
#include <encodings_fragment> | ||
}` | ||
@@ -203,0 +206,0 @@ }; |
@@ -9,2 +9,3 @@ ( function () { | ||
this.type = 'Refractor'; | ||
this.camera = new THREE.PerspectiveCamera(); | ||
const scope = this; | ||
@@ -18,3 +19,3 @@ const color = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F ); | ||
const virtualCamera = new THREE.PerspectiveCamera(); | ||
const virtualCamera = this.camera; | ||
virtualCamera.matrixAutoUpdate = false; | ||
@@ -249,2 +250,4 @@ virtualCamera.userData.refractor = true; // | ||
#include <encodings_fragment> | ||
}` | ||
@@ -251,0 +254,0 @@ }; |
@@ -305,5 +305,2 @@ ( function () { | ||
}, | ||
'dirtTexture': { | ||
value: null | ||
}, | ||
'bloomStrength': { | ||
@@ -333,3 +330,2 @@ value: 1.0 | ||
uniform sampler2D blurTexture5; | ||
uniform sampler2D dirtTexture; | ||
uniform float bloomStrength; | ||
@@ -336,0 +332,0 @@ uniform float bloomRadius; |
( function () { | ||
function computeTangents( geometry, negateSign = true ) { | ||
function computeTangents() { | ||
throw new Error( 'BufferGeometryUtils: computeTangents renamed to computeMikkTSpaceTangents.' ); | ||
} | ||
function computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) { | ||
if ( ! MikkTSpace || ! MikkTSpace.isReady ) { | ||
throw new Error( 'BufferGeometryUtils: Initialized MikkTSpace library required.' ); | ||
} | ||
if ( ! geometry.hasAttribute( 'position' ) || ! geometry.hasAttribute( 'normal' ) || ! geometry.hasAttribute( 'uv' ) ) { | ||
throw new Error( 'BufferGeometryUtils: Tangents require "position", "normal", and "uv" attributes.' ); | ||
} | ||
function getAttributeArray( attribute ) { | ||
@@ -43,3 +61,3 @@ | ||
const tangents = generateTangents( getAttributeArray( _geometry.attributes.position ), getAttributeArray( _geometry.attributes.normal ), getAttributeArray( _geometry.attributes.uv ) ); // Texture coordinate convention of glTF differs from the apparent | ||
const tangents = MikkTSpace.generateTangents( getAttributeArray( _geometry.attributes.position ), getAttributeArray( _geometry.attributes.normal ), getAttributeArray( _geometry.attributes.uv ) ); // Texture coordinate convention of glTF differs from the apparent | ||
// default of the MikkTSpace library; .w component must be flipped. | ||
@@ -60,4 +78,10 @@ | ||
return geometry.copy( _geometry ); | ||
if ( geometry !== _geometry ) { | ||
geometry.copy( _geometry ); | ||
} | ||
return geometry; | ||
} | ||
@@ -376,2 +400,94 @@ /** | ||
} // returns a new, non-interleaved version of the provided attribute | ||
function deinterleaveAttribute( attribute ) { | ||
const cons = attribute.data.array.constructor; | ||
const count = attribute.count; | ||
const itemSize = attribute.itemSize; | ||
const normalized = attribute.normalized; | ||
const array = new cons( count * itemSize ); | ||
let newAttribute; | ||
if ( attribute.isInstancedInterleavedBufferAttribute ) { | ||
newAttribute = new InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute ); | ||
} else { | ||
newAttribute = new THREE.BufferAttribute( array, itemSize, normalized ); | ||
} | ||
for ( let i = 0; i < count; i ++ ) { | ||
newAttribute.setX( i, attribute.getX( i ) ); | ||
if ( itemSize >= 2 ) { | ||
newAttribute.setY( i, attribute.getY( i ) ); | ||
} | ||
if ( itemSize >= 3 ) { | ||
newAttribute.setZ( i, attribute.getZ( i ) ); | ||
} | ||
if ( itemSize >= 4 ) { | ||
newAttribute.setW( i, attribute.getW( i ) ); | ||
} | ||
} | ||
return newAttribute; | ||
} // deinterleaves all attributes on the geometry | ||
function deinterleaveGeometry( geometry ) { | ||
const attributes = geometry.attributes; | ||
const morphTargets = geometry.morphTargets; | ||
const attrMap = new Map(); | ||
for ( const key in attributes ) { | ||
const attr = attributes[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
if ( ! attrMap.has( attr ) ) { | ||
attrMap.set( attr, deinterleaveAttribute( attr ) ); | ||
} | ||
attributes[ key ] = attrMap.get( attr ); | ||
} | ||
} | ||
for ( const key in morphTargets ) { | ||
const attr = morphTargets[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
if ( ! attrMap.has( attr ) ) { | ||
attrMap.set( attr, deinterleaveAttribute( attr ) ); | ||
} | ||
morphTargets[ key ] = attrMap.get( attr ); | ||
} | ||
} | ||
} | ||
@@ -383,3 +499,2 @@ /** | ||
function estimateBytesUsed( geometry ) { | ||
@@ -683,3 +798,3 @@ | ||
function _calculateMorphedAttributeData( object, material, attribute, morphAttribute, morphTargetsRelative, a, b, c, modifiedAttributeArray ) { | ||
function _calculateMorphedAttributeData( object, attribute, morphAttribute, morphTargetsRelative, a, b, c, modifiedAttributeArray ) { | ||
@@ -694,3 +809,3 @@ _vA.fromBufferAttribute( attribute, a ); | ||
if ( material.morphTargets && morphAttribute && morphInfluences ) { | ||
if ( morphAttribute && morphInfluences ) { | ||
@@ -775,3 +890,3 @@ _morphA.set( 0, 0, 0 ); | ||
let i, j, il, jl; | ||
let group, groupMaterial; | ||
let group; | ||
let start, end; | ||
@@ -789,3 +904,2 @@ const modifiedPosition = new Float32Array( positionAttribute.count * positionAttribute.itemSize ); | ||
group = groups[ i ]; | ||
groupMaterial = material[ group.materialIndex ]; | ||
start = Math.max( group.start, drawRange.start ); | ||
@@ -800,5 +914,5 @@ end = Math.min( group.start + group.count, drawRange.start + drawRange.count ); | ||
_calculateMorphedAttributeData( object, groupMaterial, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, groupMaterial, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -820,5 +934,5 @@ } | ||
_calculateMorphedAttributeData( object, material, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, material, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -837,3 +951,2 @@ } | ||
group = groups[ i ]; | ||
groupMaterial = material[ group.materialIndex ]; | ||
start = Math.max( group.start, drawRange.start ); | ||
@@ -848,5 +961,5 @@ end = Math.min( group.start + group.count, drawRange.start + drawRange.count ); | ||
_calculateMorphedAttributeData( object, groupMaterial, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, groupMaterial, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -868,5 +981,5 @@ } | ||
_calculateMorphedAttributeData( object, material, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, positionAttribute, morphPosition, morphTargetsRelative, a, b, c, modifiedPosition ); | ||
_calculateMorphedAttributeData( object, material, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
_calculateMorphedAttributeData( object, normalAttribute, morphNormal, morphTargetsRelative, a, b, c, modifiedNormal ); | ||
@@ -981,4 +1094,7 @@ } | ||
THREE.BufferGeometryUtils = {}; | ||
THREE.BufferGeometryUtils.computeMikkTSpaceTangents = computeMikkTSpaceTangents; | ||
THREE.BufferGeometryUtils.computeMorphedAttributes = computeMorphedAttributes; | ||
THREE.BufferGeometryUtils.computeTangents = computeTangents; | ||
THREE.BufferGeometryUtils.deinterleaveAttribute = deinterleaveAttribute; | ||
THREE.BufferGeometryUtils.deinterleaveGeometry = deinterleaveGeometry; | ||
THREE.BufferGeometryUtils.estimateBytesUsed = estimateBytesUsed; | ||
@@ -985,0 +1101,0 @@ THREE.BufferGeometryUtils.interleaveAttributes = interleaveAttributes; |
@@ -228,21 +228,4 @@ import { | ||
if ( window.TextEncoder !== undefined ) { | ||
return new TextEncoder().encode( text ).buffer; | ||
return new TextEncoder().encode( text ).buffer; | ||
} | ||
const array = new Uint8Array( new ArrayBuffer( text.length ) ); | ||
for ( let i = 0, il = text.length; i < il; i ++ ) { | ||
const value = text.charCodeAt( i ); | ||
// Replacing multi-byte character with space(0x20). | ||
array[ i ] = value > 0xFF ? 0x20 : value; | ||
} | ||
return array.buffer; | ||
} | ||
@@ -360,2 +343,24 @@ | ||
function getCanvas() { | ||
if ( cachedCanvas ) { | ||
return cachedCanvas; | ||
} | ||
if ( typeof OffscreenCanvas !== 'undefined' ) { | ||
cachedCanvas = new OffscreenCanvas( 1, 1 ); | ||
} else { | ||
cachedCanvas = document.createElement( 'canvas' ); | ||
} | ||
return cachedCanvas; | ||
} | ||
/** | ||
@@ -459,3 +464,3 @@ * Writer | ||
const reader = new window.FileReader(); | ||
const reader = new FileReader(); | ||
reader.readAsArrayBuffer( blob ); | ||
@@ -494,3 +499,3 @@ reader.onloadend = function () { | ||
const glbReader = new window.FileReader(); | ||
const glbReader = new FileReader(); | ||
glbReader.readAsArrayBuffer( glbBlob ); | ||
@@ -509,3 +514,3 @@ glbReader.onloadend = function () { | ||
const reader = new window.FileReader(); | ||
const reader = new FileReader(); | ||
reader.readAsDataURL( blob ); | ||
@@ -709,3 +714,3 @@ reader.onloadend = function () { | ||
const canvas = document.createElement( 'canvas' ); | ||
const canvas = getCanvas(); | ||
canvas.width = width; | ||
@@ -910,3 +915,3 @@ canvas.height = height; | ||
const reader = new window.FileReader(); | ||
const reader = new FileReader(); | ||
reader.readAsArrayBuffer( blob ); | ||
@@ -1063,3 +1068,3 @@ reader.onloadend = function () { | ||
const canvas = cachedCanvas = cachedCanvas || document.createElement( 'canvas' ); | ||
const canvas = getCanvas(); | ||
@@ -1078,11 +1083,4 @@ canvas.width = Math.min( image.width, options.maxTextureSize ); | ||
if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || | ||
( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || | ||
( typeof OffscreenCanvas !== 'undefined' && image instanceof OffscreenCanvas ) || | ||
( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { | ||
if ( image.data !== undefined ) { // THREE.DataTexture | ||
ctx.drawImage( image, 0, 0, canvas.width, canvas.height ); | ||
} else { | ||
if ( format !== RGBAFormat ) { | ||
@@ -1113,2 +1111,6 @@ | ||
} else { | ||
ctx.drawImage( image, 0, 0, canvas.width, canvas.height ); | ||
} | ||
@@ -1118,17 +1120,24 @@ | ||
pending.push( new Promise( function ( resolve ) { | ||
let toBlobPromise; | ||
canvas.toBlob( function ( blob ) { | ||
if ( canvas.toBlob !== undefined ) { | ||
writer.processBufferViewImage( blob ).then( function ( bufferViewIndex ) { | ||
toBlobPromise = new Promise( ( resolve ) => canvas.toBlob( resolve, mimeType ) ); | ||
imageDef.bufferView = bufferViewIndex; | ||
resolve(); | ||
} else { | ||
} ); | ||
toBlobPromise = canvas.convertToBlob( { type: mimeType } ); | ||
}, mimeType ); | ||
} | ||
} ) ); | ||
pending.push( toBlobPromise.then( blob => | ||
writer.processBufferViewImage( blob ).then( bufferViewIndex => { | ||
imageDef.bufferView = bufferViewIndex; | ||
} ) | ||
) ); | ||
} else { | ||
@@ -1135,0 +1144,0 @@ |
@@ -2136,3 +2136,2 @@ import { | ||
'specular', | ||
'shininess', | ||
'opacity', | ||
@@ -2192,2 +2191,21 @@ 'diffuse', | ||
// Special path for shininess to handle zero shininess properly | ||
this._shininess = 30; | ||
Object.defineProperty( this, 'shininess', { | ||
get: function () { | ||
return this._shininess; | ||
}, | ||
set: function ( value ) { | ||
this._shininess = value; | ||
this.uniforms.shininess.value = Math.max( this._shininess, 1e-4 ); // To prevent pow( 0.0, 0.0 ) | ||
}, | ||
} ); | ||
Object.defineProperty( | ||
@@ -2194,0 +2212,0 @@ this, |
@@ -5,3 +5,3 @@ import { | ||
} from 'three'; | ||
import { opentype } from '../libs/opentype.module.min.js'; | ||
import opentype from '../libs/opentype.module.js'; | ||
@@ -8,0 +8,0 @@ /** |
import Node from '../core/Node.js'; | ||
import { nodeObject, normalWorld, positionWorld, cameraPosition, sub, normalize, join, negate, reflect } from '../ShaderNode.js'; | ||
import { nodeObject, normalWorld, positionWorld, cameraPosition, sub, normalize, vec3, negate, reflect } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -37,3 +37,3 @@ class ReflectNode extends Node { | ||
const reflectVec = nodeObject( new ReflectNode( ReflectNode.VECTOR ) ); | ||
const cubeUV = join( negate( reflectVec.x ), reflectVec.yz ); | ||
const cubeUV = vec3( negate( reflectVec.x ), reflectVec.yz ); | ||
@@ -40,0 +40,0 @@ return cubeUV.build( builder ); |
import Node from '../core/Node.js'; | ||
import { | ||
@@ -16,3 +15,3 @@ ShaderNode, | ||
transformDirection | ||
} from '../ShaderNode.js'; | ||
} from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -86,3 +85,3 @@ import { NodeUpdateType } from '../core/constants.js'; | ||
Skinning( { | ||
Skinning.call( { | ||
index: this.skinIndexNode, | ||
@@ -89,0 +88,0 @@ weight: this.skinWeightNode, |
@@ -24,3 +24,3 @@ import Node from './Node.js'; | ||
builder.setContext( Object.assign( {}, builder.context, this.context ) ); | ||
builder.setContext( { ...builder.context, ...this.context } ); | ||
@@ -27,0 +27,0 @@ const snippet = this.node.build( builder, output ); |
@@ -11,7 +11,16 @@ import NodeUniform from './NodeUniform.js'; | ||
export const shaderStages = [ 'fragment', 'vertex' ]; | ||
export const defaultShaderStages = [ 'fragment', 'vertex' ]; | ||
export const shaderStages = [ ...defaultShaderStages, 'compute' ]; | ||
export const vector = [ 'x', 'y', 'z', 'w' ]; | ||
const typeFromLength = new Map(); | ||
typeFromLength.set( 1, 'float' ); | ||
typeFromLength.set( 2, 'vec2' ); | ||
typeFromLength.set( 3, 'vec3' ); | ||
typeFromLength.set( 4, 'vec4' ); | ||
typeFromLength.set( 9, 'mat3' ); | ||
typeFromLength.set( 16, 'mat4' ); | ||
const toFloat = ( value ) => { | ||
value = Number( value ); | ||
@@ -28,3 +37,3 @@ | ||
this.object = object; | ||
this.material = object.material; | ||
this.material = object.material || null; | ||
this.renderer = renderer; | ||
@@ -37,12 +46,17 @@ this.parser = parser; | ||
this.scene = null; | ||
this.lightsNode = null; | ||
this.fogNode = null; | ||
this.vertexShader = null; | ||
this.fragmentShader = null; | ||
this.computeShader = null; | ||
this.flowNodes = { vertex: [], fragment: [] }; | ||
this.flowCode = { vertex: '', fragment: '' }; | ||
this.uniforms = { vertex: [], fragment: [], index: 0 }; | ||
this.codes = { vertex: [], fragment: [] }; | ||
this.flowNodes = { vertex: [], fragment: [], compute: [] }; | ||
this.flowCode = { vertex: '', fragment: '', compute: [] }; | ||
this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 }; | ||
this.codes = { vertex: [], fragment: [], compute: [] }; | ||
this.attributes = []; | ||
this.varys = []; | ||
this.vars = { vertex: [], fragment: [] }; | ||
this.vars = { vertex: [], fragment: [], compute: [] }; | ||
this.flow = { code: '' }; | ||
@@ -148,2 +162,20 @@ this.stack = []; | ||
isAvailable( /*name*/ ) { | ||
return false; | ||
} | ||
getInstanceIndex() { | ||
console.warn( 'Abstract function.' ); | ||
} | ||
getFrontFacing() { | ||
console.warn( 'Abstract function.' ); | ||
} | ||
getTexture( /* textureProperty, uvSnippet */ ) { | ||
@@ -200,2 +232,6 @@ | ||
} else if ( typeLength > 4 ) { | ||
return `${ this.getType( type ) }()`; | ||
} | ||
@@ -265,3 +301,3 @@ | ||
return type === 'void' || type === 'property' || type === 'sampler'; | ||
return type === 'void' || type === 'property' || type === 'sampler' || type === 'texture' || type === 'cubeTexture'; | ||
@@ -323,11 +359,6 @@ } | ||
getTypeFromLength( type ) { | ||
getTypeFromLength( length ) { | ||
if ( type === 1 ) return 'float'; | ||
if ( type === 2 ) return 'vec2'; | ||
if ( type === 3 ) return 'vec3'; | ||
if ( type === 4 ) return 'vec4'; | ||
return typeFromLength.get( length ); | ||
return 0; | ||
} | ||
@@ -342,2 +373,4 @@ | ||
if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1; | ||
if ( /mat3/.test( type ) === true ) return 9; | ||
if ( /mat4/.test( type ) === true ) return 16; | ||
@@ -360,3 +393,3 @@ return 0; | ||
nodeData = { vertex: {}, fragment: {} }; | ||
nodeData = { vertex: {}, fragment: {}, compute: {} }; | ||
@@ -584,3 +617,3 @@ this.nodesData.set( node, nodeData ); | ||
return this.vertexShader + this.fragmentShader; | ||
return this.vertexShader + this.fragmentShader + this.computeShader; | ||
@@ -673,14 +706,13 @@ } | ||
if ( fromTypeLength === 0 ) { // fromType is matrix-like | ||
if ( fromTypeLength > 4 ) { // fromType is matrix-like | ||
const vectorType = this.getVectorFromMatrix( fromType ); | ||
// @TODO: ignore for now | ||
return this.format( `( ${ snippet } * ${ this.getType( vectorType ) }( 1.0 ) )`, vectorType, toType ); | ||
return snippet; | ||
} | ||
if ( toTypeLength === 0 ) { // toType is matrix-like | ||
if ( toTypeLength > 4 ) { // toType is matrix-like | ||
// ignore for now | ||
//return `${ this.getType( toType ) }( ${ snippet } )`; | ||
// @TODO: ignore for now | ||
@@ -687,0 +719,0 @@ return snippet; |
@@ -16,17 +16,17 @@ import Node from './Node.js'; | ||
if ( builder.context.temp !== false && type !== 'void ' && output !== 'void' && nodeData.dependenciesCount > 1 ) { | ||
if ( nodeData.propertyName !== undefined ) { | ||
if ( nodeData.snippet === undefined ) { | ||
return builder.format( nodeData.propertyName, type, output ); | ||
const snippet = super.build( builder, type ); | ||
} else if ( builder.context.temp !== false && type !== 'void ' && output !== 'void' && nodeData.dependenciesCount > 1 ) { | ||
const nodeVar = builder.getVarFromNode( this, type ); | ||
const propertyName = builder.getPropertyName( nodeVar ); | ||
const snippet = super.build( builder, type ); | ||
builder.addFlowCode( `${propertyName} = ${snippet}` ); | ||
const nodeVar = builder.getVarFromNode( this, type ); | ||
const propertyName = builder.getPropertyName( nodeVar ); | ||
nodeData.snippet = snippet; | ||
nodeData.propertyName = propertyName; | ||
builder.addFlowCode( `${propertyName} = ${snippet}` ); | ||
} | ||
nodeData.snippet = snippet; | ||
nodeData.propertyName = propertyName; | ||
@@ -43,2 +43,4 @@ return builder.format( nodeData.propertyName, type, output ); | ||
TempNode.prototype.isTempNode = true; | ||
export default TempNode; |
import Node from './Node.js'; | ||
import OperatorNode from '../math/OperatorNode.js'; | ||
class VarNode extends Node { | ||
constructor( node, name = null, nodeType = null ) { | ||
constructor( node, name = null ) { | ||
super( nodeType ); | ||
super(); | ||
@@ -14,2 +15,40 @@ this.node = node; | ||
op( op, ...params ) { | ||
this.node = new OperatorNode( op, this.node, ...params ); | ||
return this; | ||
} | ||
assign( ...params ) { | ||
return this.op( '=', ...params ); | ||
} | ||
add( ...params ) { | ||
return this.op( '+', ...params ); | ||
} | ||
sub( ...params ) { | ||
return this.op( '-', ...params ); | ||
} | ||
mul( ...params ) { | ||
return this.op( '*', ...params ); | ||
} | ||
div( ...params ) { | ||
return this.op( '/', ...params ); | ||
} | ||
getHash( builder ) { | ||
@@ -23,3 +62,3 @@ | ||
return super.getNodeType( builder ) || this.node.getNodeType( builder ); | ||
return this.node.getNodeType( builder ); | ||
@@ -30,5 +69,12 @@ } | ||
const type = builder.getVectorType( this.getNodeType( builder ) ); | ||
const node = this.node; | ||
if ( node.isTempNode === true ) { | ||
return node.build( builder ); | ||
} | ||
const name = this.name; | ||
const type = builder.getVectorType( this.getNodeType( builder ) ); | ||
@@ -54,4 +100,2 @@ const snippet = node.build( builder, type ); | ||
VarNode.prototype.isVarNode = true; | ||
export default VarNode; |
import TempNode from '../core/Node.js'; | ||
import { ShaderNode, | ||
vec3, | ||
pow, mul, sub, mix, join, | ||
lessThanEqual } from '../ShaderNode.js'; | ||
import { ShaderNode, vec3, pow, mul, sub, mix, vec4, lessThanEqual } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -27,3 +24,3 @@ import { LinearEncoding, sRGBEncoding } from 'three'; | ||
return join( rgbResult.r, rgbResult.g, rgbResult.b, value.a ); | ||
return vec4( rgbResult, value.a ); | ||
@@ -83,3 +80,3 @@ } ); | ||
return encodingFunctionNode( { | ||
return encodingFunctionNode.call( { | ||
value: node | ||
@@ -86,0 +83,0 @@ } ).build( builder, type ); |
import TempNode from '../core/TempNode.js'; | ||
import ModelNode from '../accessors/ModelNode.js'; | ||
import { ShaderNode, positionView, normalView, uv, join, cond, add, sub, mul, dFdx, dFdy, cross, max, dot, normalize, inversesqrt, equal } from '../ShaderNode.js'; | ||
import { ShaderNode, positionView, normalView, uv, vec3, cond, add, sub, mul, dFdx, dFdy, cross, max, dot, normalize, inversesqrt, equal, faceDirection } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -12,3 +12,3 @@ import { TangentSpaceNormalMap, ObjectSpaceNormalMap } from 'three'; | ||
const { eye_pos, surf_norm, mapN, faceDirection, uv } = inputs; | ||
const { eye_pos, surf_norm, mapN, uv } = inputs; | ||
@@ -60,3 +60,3 @@ const q0 = dFdx( eye_pos.xyz ); | ||
const normalMapScale = mul( normalMap.xy, scaleNode ); | ||
normalMap = join( normalMapScale, normalMap.z ); | ||
normalMap = vec3( normalMapScale, normalMap.z ); | ||
@@ -75,7 +75,6 @@ } | ||
const perturbNormal2ArbCall = perturbNormal2ArbNode( { | ||
const perturbNormal2ArbCall = perturbNormal2ArbNode.call( { | ||
eye_pos: positionView, | ||
surf_norm: normalView, | ||
mapN: normalMap, | ||
faceDirection: 1.0, | ||
uv: uv() | ||
@@ -82,0 +81,0 @@ } ); |
import Node from '../core/Node.js'; | ||
import MathNode from '../math/MathNode.js'; | ||
@@ -14,2 +15,8 @@ class FogNode extends Node { | ||
mix( outputNode ) { | ||
return new MathNode( MathNode.MIX, outputNode, this.colorNode, this ); | ||
} | ||
generate( builder ) { | ||
@@ -16,0 +23,0 @@ |
import FogNode from './FogNode.js'; | ||
import { smoothstep, negate, positionView } from '../ShaderNode.js'; | ||
import { smoothstep, negate, positionView } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -4,0 +4,0 @@ class FogRangeNode extends FogNode { |
import ContextNode from '../core/ContextNode.js'; | ||
import VarNode from '../core/VarNode.js'; | ||
import UniformNode from '../core/UniformNode.js'; | ||
import OperatorNode from '../math/OperatorNode.js'; | ||
import { PhysicalLightingModel } from '../functions/BSDFs.js'; | ||
import { Vector3 } from 'three'; | ||
import { reflectedLight } from '../shadernode/ShaderNodeBaseElements.js'; | ||
class LightContextNode extends ContextNode { | ||
constructor( node ) { | ||
constructor( node, lightingModelNode = null ) { | ||
super( node ); | ||
this.lightingModelNode = lightingModelNode; | ||
} | ||
@@ -24,26 +22,12 @@ | ||
const material = builder.material; | ||
const { lightingModelNode } = this; | ||
let lightingModel = null; | ||
this.context.reflectedLight = reflectedLight(); | ||
if ( material.isMeshStandardMaterial === true ) { | ||
if ( lightingModelNode !== null ) { | ||
lightingModel = PhysicalLightingModel; | ||
this.context.lightingModelNode = lightingModelNode; | ||
} | ||
const directDiffuse = new VarNode( new UniformNode( new Vector3() ), 'DirectDiffuse', 'vec3' ); | ||
const directSpecular = new VarNode( new UniformNode( new Vector3() ), 'DirectSpecular', 'vec3' ); | ||
this.context.directDiffuse = directDiffuse; | ||
this.context.directSpecular = directSpecular; | ||
if ( lightingModel !== null ) { | ||
this.context.lightingModel = lightingModel; | ||
} | ||
// add code | ||
const type = this.getNodeType( builder ); | ||
@@ -53,6 +37,4 @@ | ||
const totalLight = new OperatorNode( '+', directDiffuse, directSpecular ); | ||
return this.context.reflectedLight.build( builder, type ); | ||
return totalLight.build( builder, type ); | ||
} | ||
@@ -59,0 +41,0 @@ |
@@ -8,3 +8,3 @@ import Node from '../core/Node.js'; | ||
import { NodeUpdateType } from '../core/constants.js'; | ||
import { getDistanceAttenuation } from '../functions/BSDFs.js'; | ||
import getDistanceAttenuation from '../functions/light/getDistanceAttenuation.js'; | ||
@@ -55,3 +55,3 @@ import { Color } from 'three'; | ||
const lightAttenuation = getDistanceAttenuation( { | ||
const lightAttenuation = getDistanceAttenuation.call( { | ||
lightDistance, | ||
@@ -66,14 +66,12 @@ cutoffDistance: this._lightCutoffDistanceNode, | ||
const lightingModelFunction = builder.context.lightingModel; | ||
const lightingModelFunctionNode = builder.context.lightingModelNode; | ||
if ( lightingModelFunction !== undefined ) { | ||
if ( lightingModelFunctionNode !== undefined ) { | ||
const directDiffuse = builder.context.directDiffuse; | ||
const directSpecular = builder.context.directSpecular; | ||
const reflectedLight = builder.context.reflectedLight; | ||
lightingModelFunction( { | ||
lightingModelFunctionNode.call( { | ||
lightDirection, | ||
lightColor, | ||
directDiffuse, | ||
directSpecular | ||
reflectedLight | ||
}, builder ); | ||
@@ -80,0 +78,0 @@ |
@@ -0,1 +1,2 @@ | ||
import NodeMaterial from './NodeMaterial.js'; | ||
import LineBasicNodeMaterial from './LineBasicNodeMaterial.js'; | ||
@@ -8,2 +9,3 @@ import MeshBasicNodeMaterial from './MeshBasicNodeMaterial.js'; | ||
export { | ||
NodeMaterial, | ||
LineBasicNodeMaterial, | ||
@@ -16,2 +18,3 @@ MeshBasicNodeMaterial, | ||
const materialLib = { | ||
NodeMaterial, | ||
LineBasicNodeMaterial, | ||
@@ -36,1 +39,27 @@ MeshBasicNodeMaterial, | ||
}; | ||
NodeMaterial.fromMaterial = function ( material ) { | ||
const type = material.type.replace( 'Material', 'NodeMaterial' ); | ||
if ( materialLib[ type ] === undefined ) { | ||
return material; // is already a node material or cannot be converted | ||
} | ||
const nodeMaterial = new materialLib[ type ]( material ); | ||
for ( let key in material ) { | ||
if ( nodeMaterial[ key ] === undefined ) { | ||
nodeMaterial[ key ] = material[ key ]; // currently this is needed only for material.alphaTest | ||
} | ||
} | ||
return nodeMaterial; | ||
}; |
import NodeMaterial from './NodeMaterial.js'; | ||
import { | ||
float, vec3, vec4, | ||
context, assign, label, mul, invert, mix, | ||
normalView, | ||
materialRoughness, materialMetalness | ||
} from '../shadernode/ShaderNodeElements.js'; | ||
import getRoughness from '../functions/material/getRoughness.js'; | ||
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js'; | ||
import { MeshStandardMaterial } from 'three'; | ||
@@ -39,2 +48,62 @@ | ||
build( builder ) { | ||
const lightNode = this.lightNode || builder.lightNode; // use scene lights | ||
let { colorNode, diffuseColorNode } = this.generateMain( builder ); | ||
diffuseColorNode = this.generateStandardMaterial( builder, { colorNode, diffuseColorNode } ); | ||
const outgoingLightNode = this.generateLight( builder, { diffuseColorNode, lightNode } ); | ||
this.generateOutput( builder, { diffuseColorNode, outgoingLightNode } ); | ||
} | ||
generateLight( builder, { diffuseColorNode, lightNode } ) { | ||
let outgoingLightNode = super.generateLight( builder, { diffuseColorNode, lightNode, lightingModelNode: PhysicalLightingModel } ); | ||
// TONE MAPPING | ||
const renderer = builder.renderer; | ||
if ( renderer.toneMappingNode ) outgoingLightNode = context( renderer.toneMappingNode, { color: outgoingLightNode } ); | ||
return outgoingLightNode; | ||
} | ||
generateStandardMaterial( builder, { colorNode, diffuseColorNode } ) { | ||
// METALNESS | ||
let metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness; | ||
metalnessNode = builder.addFlow( 'fragment', label( metalnessNode, 'Metalness' ) ); | ||
builder.addFlow( 'fragment', assign( diffuseColorNode, vec4( mul( diffuseColorNode.rgb, invert( metalnessNode ) ), diffuseColorNode.a ) ) ); | ||
// ROUGHNESS | ||
let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness; | ||
roughnessNode = getRoughness.call( { roughness: roughnessNode } ); | ||
builder.addFlow( 'fragment', label( roughnessNode, 'Roughness' ) ); | ||
// SPECULAR COLOR | ||
const specularColorNode = mix( vec3( 0.04 ), colorNode.rgb, metalnessNode ); | ||
builder.addFlow( 'fragment', label( specularColorNode, 'SpecularColor' ) ); | ||
// NORMAL VIEW | ||
const normalNode = this.normalNode ? vec3( this.normalNode ) : normalView; | ||
builder.addFlow( 'fragment', label( normalNode, 'TransformedNormalView' ) ); | ||
return diffuseColorNode; | ||
} | ||
copy( source ) { | ||
@@ -41,0 +110,0 @@ |
import { Material, ShaderMaterial } from 'three'; | ||
import { getNodesKeys } from '../core/NodeUtils.js'; | ||
import ExpressionNode from '../core/ExpressionNode.js'; | ||
import { | ||
float, vec3, vec4, | ||
assign, label, mul, add, bypass, | ||
positionLocal, skinning, instance, modelViewProjection, lightContext, colorSpace, | ||
materialAlphaTest, materialColor, materialOpacity | ||
} from '../shadernode/ShaderNodeElements.js'; | ||
@@ -16,2 +23,114 @@ class NodeMaterial extends ShaderMaterial { | ||
build( builder ) { | ||
const { lightNode } = this; | ||
const { diffuseColorNode } = this.generateMain( builder ); | ||
const outgoingLightNode = this.generateLight( builder, { diffuseColorNode, lightNode } ); | ||
this.generateOutput( builder, { diffuseColorNode, outgoingLightNode } ); | ||
} | ||
generateMain( builder ) { | ||
const object = builder.object; | ||
// < VERTEX STAGE > | ||
let vertex = positionLocal; | ||
if ( this.positionNode !== null ) { | ||
vertex = bypass( vertex, assign( positionLocal, this.positionNode ) ); | ||
} | ||
if ( object.instanceMatrix?.isInstancedBufferAttribute === true && builder.isAvailable( 'instance' ) === true ) { | ||
vertex = bypass( vertex, instance( object ) ); | ||
} | ||
if ( object.isSkinnedMesh === true ) { | ||
vertex = bypass( vertex, skinning( object ) ); | ||
} | ||
builder.context.vertex = vertex; | ||
builder.addFlow( 'vertex', modelViewProjection() ); | ||
// < FRAGMENT STAGE > | ||
let colorNode = vec4( this.colorNode || materialColor ); | ||
let opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; | ||
// COLOR | ||
colorNode = builder.addFlow( 'fragment', label( colorNode, 'Color' ) ); | ||
const diffuseColorNode = builder.addFlow( 'fragment', label( colorNode, 'DiffuseColor' ) ); | ||
// OPACITY | ||
opacityNode = builder.addFlow( 'fragment', label( opacityNode, 'OPACITY' ) ); | ||
builder.addFlow( 'fragment', assign( diffuseColorNode.a, mul( diffuseColorNode.a, opacityNode ) ) ); | ||
// ALPHA TEST | ||
if ( this.alphaTestNode || this.alphaTest > 0 ) { | ||
const alphaTestNode = this.alphaTestNode ? float( this.alphaTestNode ) : materialAlphaTest; | ||
builder.addFlow( 'fragment', label( alphaTestNode, 'AlphaTest' ) ); | ||
// @TODO: remove ExpressionNode here and then possibly remove it completely | ||
builder.addFlow( 'fragment', new ExpressionNode( 'if ( DiffuseColor.a <= AlphaTest ) { discard; }' ) ); | ||
} | ||
return { colorNode, diffuseColorNode }; | ||
} | ||
generateLight( builder, { diffuseColorNode, lightNode, lightingModelNode } ) { | ||
// < ANALYTIC LIGHTS > | ||
// OUTGOING LIGHT | ||
let outgoingLightNode = diffuseColorNode.xyz; | ||
if ( lightNode && lightNode.hasLight !== false ) outgoingLightNode = builder.addFlow( 'fragment', label( lightContext( lightNode, lightingModelNode ), 'Light' ) ); | ||
// EMISSIVE | ||
if ( this.emissiveNode ) outgoingLightNode = add( vec3( this.emissiveNode ), outgoingLightNode ); | ||
return outgoingLightNode; | ||
} | ||
generateOutput( builder, { diffuseColorNode, outgoingLightNode } ) { | ||
// OUTPUT | ||
let outputNode = vec4( outgoingLightNode, diffuseColorNode.a ); | ||
// ENCODING | ||
outputNode = colorSpace( outputNode, builder.renderer.outputEncoding ); | ||
// FOG | ||
if ( builder.fogNode ) outputNode = builder.fogNode.mix( outputNode ); | ||
// RESULT | ||
builder.addFlow( 'fragment', label( outputNode, 'Output' ) ); | ||
return outputNode; | ||
} | ||
setDefaultValues( values ) { | ||
@@ -22,20 +141,10 @@ | ||
let value; | ||
for ( const property in values ) { | ||
value = values[ property ]; | ||
const value = values[ property ]; | ||
if ( this[ property ] === undefined ) { | ||
if ( value && typeof value.clone === 'function' ) { | ||
this[ property ] = value?.clone?.() || value; | ||
this[ property ] = value.clone(); | ||
} else { | ||
this[ property ] = value; | ||
} | ||
} | ||
@@ -108,2 +217,4 @@ | ||
static fromMaterial( /*material*/ ) { } | ||
} | ||
@@ -110,0 +221,0 @@ |
@@ -7,7 +7,7 @@ import Node from '../core/Node.js'; | ||
constructor( node, ifNode, elseNode ) { | ||
constructor( condNode, ifNode, elseNode ) { | ||
super(); | ||
this.node = node; | ||
this.condNode = condNode; | ||
@@ -41,3 +41,3 @@ this.ifNode = ifNode; | ||
const nodeSnippet = new ContextNode( this.node/*, context*/ ).build( builder, 'bool' ), | ||
const nodeSnippet = new ContextNode( this.condNode/*, context*/ ).build( builder, 'bool' ), | ||
ifSnippet = new ContextNode( this.ifNode, context ).build( builder, type ), | ||
@@ -44,0 +44,0 @@ elseSnippet = new ContextNode( this.elseNode, context ).build( builder, type ); |
@@ -11,4 +11,4 @@ import TempNode from '../core/TempNode.js'; | ||
static RAD = 'radians'; | ||
static DEG = 'degrees'; | ||
static RADIANS = 'radians'; | ||
static DEGREES = 'degrees'; | ||
static EXP = 'exp'; | ||
@@ -19,3 +19,3 @@ static EXP2 = 'exp2'; | ||
static SQRT = 'sqrt'; | ||
static INV_SQRT = 'inversesqrt'; | ||
static INVERSE_SQRT = 'inversesqrt'; | ||
static FLOOR = 'floor'; | ||
@@ -80,5 +80,5 @@ static CEIL = 'ceil'; | ||
const aLen = builder.getTypeLength( aType ); | ||
const bLen = builder.getTypeLength( bType ); | ||
const cLen = builder.getTypeLength( cType ); | ||
const aLen = builder.isMatrix( aType ) ? 0 : builder.getTypeLength( aType ); | ||
const bLen = builder.isMatrix( bType ) ? 0 : builder.getTypeLength( bType ); | ||
const cLen = builder.isMatrix( cType ) ? 0 : builder.getTypeLength( cType ); | ||
@@ -85,0 +85,0 @@ if ( aLen > bLen && aLen > cLen ) { |
@@ -11,2 +11,3 @@ // core | ||
import FunctionNode from './core/FunctionNode.js'; | ||
import InstanceIndexNode from './core/InstanceIndexNode.js'; | ||
import Node from './core/Node.js'; | ||
@@ -32,2 +33,3 @@ import NodeAttribute from './core/NodeAttribute.js'; | ||
import CubeTextureNode from './accessors/CubeTextureNode.js'; | ||
import InstanceNode from './accessors/InstanceNode.js'; | ||
import MaterialNode from './accessors/MaterialNode.js'; | ||
@@ -47,5 +49,10 @@ import MaterialReferenceNode from './accessors/MaterialReferenceNode.js'; | ||
// gpgpu | ||
import ComputeNode from './gpgpu/ComputeNode.js'; | ||
// display | ||
import ColorSpaceNode from './display/ColorSpaceNode.js'; | ||
import FrontFacingNode from './display/FrontFacingNode.js'; | ||
import NormalMapNode from './display/NormalMapNode.js'; | ||
import ToneMappingNode from './display/ToneMappingNode.js'; | ||
@@ -61,2 +68,3 @@ // math | ||
import LightsNode from './lights/LightsNode.js'; | ||
import ReflectedLightNode from './lights/ReflectedLightNode.js'; | ||
@@ -67,6 +75,7 @@ // utils | ||
import JoinNode from './utils/JoinNode.js'; | ||
import MatcapUVNode from './utils/MatcapUVNode.js'; | ||
import MaxMipLevelNode from './utils/MaxMipLevelNode.js'; | ||
import OscNode from './utils/OscNode.js'; | ||
import SplitNode from './utils/SplitNode.js'; | ||
import SpriteSheetUVNode from './utils/SpriteSheetUVNode.js'; | ||
import MatcapUVNode from './utils/MatcapUVNode.js'; | ||
import OscNode from './utils/OscNode.js'; | ||
import TimerNode from './utils/TimerNode.js'; | ||
@@ -89,5 +98,2 @@ | ||
// functions | ||
export * from './functions/BSDFs.js'; | ||
// materials | ||
@@ -97,3 +103,3 @@ export * from './materials/Materials.js'; | ||
// shader node | ||
export * from './ShaderNode.js'; | ||
export * from './shadernode/ShaderNodeElements.js'; | ||
@@ -111,2 +117,3 @@ const nodeLib = { | ||
FunctionNode, | ||
InstanceIndexNode, | ||
Node, | ||
@@ -128,2 +135,5 @@ NodeAttribute, | ||
// compute | ||
ComputeNode, | ||
// accessors | ||
@@ -133,2 +143,3 @@ BufferNode, | ||
CubeTextureNode, | ||
InstanceNode, | ||
MaterialNode, | ||
@@ -150,3 +161,5 @@ MaterialReferenceNode, | ||
ColorSpaceNode, | ||
FrontFacingNode, | ||
NormalMapNode, | ||
ToneMappingNode, | ||
@@ -162,2 +175,3 @@ // math | ||
LightsNode, | ||
ReflectedLightNode, | ||
@@ -168,6 +182,7 @@ // utils | ||
JoinNode, | ||
MatcapUVNode, | ||
MaxMipLevelNode, | ||
OscNode, | ||
SplitNode, | ||
SpriteSheetUVNode, | ||
MatcapUVNode, | ||
OscNode, | ||
TimerNode, | ||
@@ -206,2 +221,3 @@ | ||
FunctionNode, | ||
InstanceIndexNode, | ||
Node, | ||
@@ -223,2 +239,5 @@ NodeAttribute, | ||
// compute | ||
ComputeNode, | ||
// accessors | ||
@@ -228,2 +247,3 @@ BufferNode, | ||
CubeTextureNode, | ||
InstanceNode, | ||
MaterialNode, | ||
@@ -245,3 +265,5 @@ MaterialReferenceNode, | ||
ColorSpaceNode, | ||
FrontFacingNode, | ||
NormalMapNode, | ||
ToneMappingNode, | ||
@@ -257,2 +279,3 @@ // math | ||
LightsNode, | ||
ReflectedLightNode, | ||
@@ -263,6 +286,7 @@ // utils | ||
JoinNode, | ||
MatcapUVNode, | ||
MaxMipLevelNode, | ||
OscNode, | ||
SplitNode, | ||
SpriteSheetUVNode, | ||
MatcapUVNode, | ||
OscNode, | ||
TimerNode, | ||
@@ -281,3 +305,2 @@ | ||
NodeMaterialLoader | ||
}; |
import NodeFunction from '../core/NodeFunction.js'; | ||
import NodeFunctionInput from '../core/NodeFunctionInput.js'; | ||
const declarationRegexp = /^fn\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*\-\>\s*([a-z_0-9]+)?/i; | ||
const declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+)?/i; | ||
const propertiesRegexp = /[a-z_0-9]+/ig; | ||
const wgslTypeLib = { | ||
f32: 'float' | ||
}; | ||
const parse = ( source ) => { | ||
@@ -39,4 +43,6 @@ | ||
const name = propsMatches[ i ++ ][ 0 ]; | ||
const type = propsMatches[ i ++ ][ 0 ]; | ||
let type = propsMatches[ i ++ ][ 0 ]; | ||
type = wgslTypeLib[ type ] || type; | ||
// precision | ||
@@ -58,3 +64,3 @@ | ||
const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; | ||
const type = declaration[ 3 ]; | ||
const type = declaration[ 3 ] || 'void'; | ||
@@ -92,4 +98,6 @@ return { | ||
return `fn ${ name } ( ${ this.inputsCode.trim() } ) -> ${ this.type }` + this.blockCode; | ||
const type = this.type !== 'void' ? '-> ' + this.type : ''; | ||
return `fn ${ name } ( ${ this.inputsCode.trim() } ) ${ type }` + this.blockCode; | ||
} | ||
@@ -96,0 +104,0 @@ |
import Node from '../core/Node.js'; | ||
import { ShaderNode, uv, add, mul, floor, mod, sign } from '../shadernode/ShaderNodeBaseElements.js'; | ||
import { ShaderNode, uv, add, mul, floor, mod, sign } from '../ShaderNode.js'; | ||
const checkerShaderNode = new ShaderNode( ( inputs ) => { | ||
@@ -29,3 +28,3 @@ | ||
return checkerShaderNode( { uv: this.uvNode } ).build( builder ); | ||
return checkerShaderNode.call( { uv: this.uvNode } ).build( builder ); | ||
@@ -32,0 +31,0 @@ } |
@@ -1,4 +0,4 @@ | ||
import Node from '../core/Node.js'; | ||
import TempNode from '../core/Node.js'; | ||
class ArrayElementNode extends Node { | ||
class ArrayElementNode extends TempNode { | ||
@@ -23,3 +23,3 @@ constructor( node, indexNode ) { | ||
const nodeSnippet = this.node.build( builder ); | ||
const indexSnippet = this.indexNode.build( builder, 'int' ); | ||
const indexSnippet = this.indexNode.build( builder, 'uint' ); | ||
@@ -26,0 +26,0 @@ return `${nodeSnippet}[ ${indexSnippet} ]`; |
@@ -27,6 +27,5 @@ import Node from '../core/Node.js'; | ||
const convertToSnippet = builder.getType( convertTo ); | ||
const nodeSnippet = node.build( builder, convertTo ); | ||
return `${ builder.getVectorType( convertToSnippet ) }( ${ nodeSnippet } )`; | ||
return builder.format( nodeSnippet, this.getNodeType( builder ), convertTo ); | ||
@@ -33,0 +32,0 @@ } else { |
import TempNode from '../core/TempNode.js'; | ||
import { join, negate, normalize, cross, dot, mul, add, transformedNormalView, positionViewDirection } from '../ShaderNode.js'; | ||
import { vec2, vec3, negate, normalize, cross, dot, mul, add, transformedNormalView, positionViewDirection } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -14,6 +14,6 @@ class MatcapUVNode extends TempNode { | ||
const x = normalize( join( positionViewDirection.z, 0, negate( positionViewDirection.x ) ) ); | ||
const x = normalize( vec3( positionViewDirection.z, 0, negate( positionViewDirection.x ) ) ); | ||
const y = cross( positionViewDirection, x ); | ||
const uv = add( mul( join( dot( x, transformedNormalView ), dot( y, transformedNormalView ) ), 0.495 ), 0.5 ); | ||
const uv = add( mul( vec2( dot( x, transformedNormalView ), dot( y, transformedNormalView ) ), 0.495 ), 0.5 ); | ||
@@ -20,0 +20,0 @@ return uv.build( builder, this.getNodeType( builder ) ); |
import Node from '../core/Node.js'; | ||
import TimerNode from './TimerNode.js'; | ||
import { abs, fract, round, sin, add, sub, mul } from '../ShaderNode.js'; | ||
import { abs, fract, round, sin, add, sub, mul } from '../shadernode/ShaderNodeBaseElements.js'; | ||
@@ -5,0 +5,0 @@ class OscNode extends Node { |
@@ -815,3 +815,3 @@ import { | ||
this.onBeforeRender = function () { | ||
this.update = function () { | ||
@@ -847,10 +847,6 @@ this.count = 0; | ||
// reset unneeded data | ||
// set the draw range to only the processed triangles | ||
for ( let i = this.count * 3; i < this.positionArray.length; i ++ ) { | ||
this.geometry.setDrawRange( 0, this.count ); | ||
this.positionArray[ i ] = 0.0; | ||
} | ||
// update geometry data | ||
@@ -857,0 +853,0 @@ |
@@ -21,2 +21,3 @@ import { | ||
this.type = 'Reflector'; | ||
this.camera = new PerspectiveCamera(); | ||
@@ -47,3 +48,3 @@ const scope = this; | ||
const textureMatrix = new Matrix4(); | ||
const virtualCamera = new PerspectiveCamera(); | ||
const virtualCamera = this.camera; | ||
@@ -258,2 +259,4 @@ const renderTarget = new WebGLRenderTarget( textureWidth, textureHeight, { samples: multisample } ); | ||
#include <encodings_fragment> | ||
}` | ||
@@ -260,0 +263,0 @@ }; |
@@ -22,2 +22,3 @@ import { | ||
this.type = 'Refractor'; | ||
this.camera = new PerspectiveCamera(); | ||
@@ -35,3 +36,3 @@ const scope = this; | ||
const virtualCamera = new PerspectiveCamera(); | ||
const virtualCamera = this.camera; | ||
virtualCamera.matrixAutoUpdate = false; | ||
@@ -321,2 +322,4 @@ virtualCamera.userData.refractor = true; | ||
#include <encodings_fragment> | ||
}` | ||
@@ -323,0 +326,0 @@ |
@@ -357,3 +357,2 @@ import { | ||
'blurTexture5': { value: null }, | ||
'dirtTexture': { value: null }, | ||
'bloomStrength': { value: 1.0 }, | ||
@@ -379,3 +378,2 @@ 'bloomFactors': { value: null }, | ||
uniform sampler2D blurTexture5; | ||
uniform sampler2D dirtTexture; | ||
uniform float bloomStrength; | ||
@@ -382,0 +380,0 @@ uniform float bloomRadius; |
@@ -1,2 +0,2 @@ | ||
import NodeBuilder, { shaderStages } from 'three-nodes/core/NodeBuilder.js'; | ||
import NodeBuilder, { defaultShaderStages } from 'three-nodes/core/NodeBuilder.js'; | ||
import NodeFrame from 'three-nodes/core/NodeFrame.js'; | ||
@@ -88,2 +88,8 @@ import SlotNode from './SlotNode.js'; | ||
if ( material.isMeshStandardNodeMaterial !== true ) { | ||
this.replaceCode( 'fragment', getIncludeSnippet( 'tonemapping_fragment' ), '' ); | ||
} | ||
// parse inputs | ||
@@ -333,3 +339,3 @@ | ||
for ( const shaderStage of shaderStages ) { | ||
for ( const shaderStage of defaultShaderStages ) { | ||
@@ -520,3 +526,3 @@ const uniforms = this.getUniforms( shaderStage ); | ||
for ( const shaderStage of shaderStages ) { | ||
for ( const shaderStage of defaultShaderStages ) { | ||
@@ -535,3 +541,3 @@ this.addCodeAfterSnippet( | ||
for ( const shaderStage of shaderStages ) { | ||
for ( const shaderStage of defaultShaderStages ) { | ||
@@ -538,0 +544,0 @@ // uniforms |
@@ -1,4 +0,2 @@ | ||
import { LinearEncoding } from 'three'; | ||
import WebGPUNodeUniformsGroup from './WebGPUNodeUniformsGroup.js'; | ||
import WebGPUUniformsGroup from '../WebGPUUniformsGroup.js'; | ||
import { | ||
@@ -12,21 +10,22 @@ FloatNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform, | ||
import WebGPUUniformBuffer from '../WebGPUUniformBuffer.js'; | ||
import WebGPUStorageBuffer from '../WebGPUStorageBuffer.js'; | ||
import { getVectorLength, getStrideLength } from '../WebGPUBufferUtils.js'; | ||
import VarNode from 'three-nodes/core/VarNode.js'; | ||
import CodeNode from 'three-nodes/core/CodeNode.js'; | ||
import BypassNode from 'three-nodes/core/BypassNode.js'; | ||
import ExpressionNode from 'three-nodes/core/ExpressionNode.js'; | ||
import NodeBuilder from 'three-nodes/core/NodeBuilder.js'; | ||
import MaterialNode from 'three-nodes/accessors/MaterialNode.js'; | ||
import PositionNode from 'three-nodes/accessors/PositionNode.js'; | ||
import NormalNode from 'three-nodes/accessors/NormalNode.js'; | ||
import ModelViewProjectionNode from 'three-nodes/accessors/ModelViewProjectionNode.js'; | ||
import SkinningNode from 'three-nodes/accessors/SkinningNode.js'; | ||
import ColorSpaceNode from 'three-nodes/display/ColorSpaceNode.js'; | ||
import LightContextNode from 'three-nodes/lights/LightContextNode.js'; | ||
import OperatorNode from 'three-nodes/math/OperatorNode.js'; | ||
import WGSLNodeParser from 'three-nodes/parsers/WGSLNodeParser.js'; | ||
import { vec3, add, join, mix, nodeObject } from 'three-nodes/ShaderNode.js'; | ||
import { getRoughness } from 'three-nodes/functions/PhysicalMaterialFunctions.js'; | ||
import CodeNode from 'three-nodes/core/CodeNode.js'; | ||
import { NodeMaterial } from 'three-nodes/materials/Materials.js'; | ||
const gpuShaderStageLib = { | ||
'vertex': GPUShaderStage.VERTEX, | ||
'fragment': GPUShaderStage.FRAGMENT, | ||
'compute': GPUShaderStage.COMPUTE | ||
}; | ||
const supports = { | ||
instance: true | ||
}; | ||
const wgslTypeLib = { | ||
@@ -66,3 +65,4 @@ float: 'f32', | ||
dFdx: 'dpdx', | ||
dFdy: 'dpdy' | ||
dFdy: 'dpdy', | ||
inversesqrt: 'inverseSqrt' | ||
}; | ||
@@ -85,12 +85,2 @@ | ||
` ), | ||
smoothstep: new CodeNode( ` | ||
fn smoothstep( low : f32, high : f32, x : f32 ) -> f32 { | ||
let t = clamp( ( x - low ) / ( high - low ), 0.0, 1.0 ); | ||
return t * t * ( 3.0 - 2.0 * t ); | ||
} | ||
` ), | ||
repeatWrapping: new CodeNode( ` | ||
@@ -104,9 +94,2 @@ fn repeatWrapping( uv : vec2<f32>, dimension : vec2<i32> ) -> vec2<i32> { | ||
} | ||
` ), | ||
inversesqrt: new CodeNode( ` | ||
fn inversesqrt( x : f32 ) -> f32 { | ||
return 1.0 / sqrt( x ); | ||
} | ||
` ) | ||
@@ -124,7 +107,14 @@ }; | ||
this.bindings = { vertex: [], fragment: [] }; | ||
this.bindingsOffset = { vertex: 0, fragment: 0 }; | ||
this.bindings = { vertex: [], fragment: [], compute: [] }; | ||
this.bindingsOffset = { vertex: 0, fragment: 0, compute: 0 }; | ||
this.uniformsGroup = {}; | ||
this.builtins = { | ||
vertex: new Map(), | ||
fragment: new Map(), | ||
compute: new Map(), | ||
attribute: new Map() | ||
}; | ||
} | ||
@@ -134,222 +124,44 @@ | ||
this._parseObject(); | ||
const { object, material } = this; | ||
return super.build(); | ||
if ( material !== null ) { | ||
} | ||
NodeMaterial.fromMaterial( material ).build( this ); | ||
_parseObject() { | ||
} else { | ||
const object = this.object; | ||
const material = this.material; | ||
this.addFlow( 'compute', object ); | ||
// parse inputs | ||
} | ||
if ( material.isMeshStandardMaterial || material.isMeshBasicMaterial || material.isPointsMaterial || material.isLineBasicMaterial ) { | ||
return super.build(); | ||
let lightNode = material.lightNode; | ||
} | ||
if ( material.isMeshStandardMaterial && lightNode === null && this.lightNode ) { | ||
addFlowCode( code ) { | ||
// use scene lights | ||
if ( ! /;\s*$/.test( code ) ) { | ||
lightNode = this.lightNode; | ||
code += ';'; | ||
} | ||
} | ||
// VERTEX STAGE | ||
super.addFlowCode( code + '\n\t' ); | ||
let vertex = new PositionNode( PositionNode.GEOMETRY ); | ||
} | ||
if ( material.positionNode && material.positionNode.isNode ) { | ||
getSampler( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { | ||
const assignPositionNode = new OperatorNode( '=', new PositionNode( PositionNode.LOCAL ), material.positionNode ); | ||
if ( shaderStage === 'fragment' ) { | ||
vertex = new BypassNode( vertex, assignPositionNode ); | ||
return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet} )`; | ||
} | ||
} else { | ||
if ( object.isSkinnedMesh === true ) { | ||
this._include( 'repeatWrapping' ); | ||
vertex = new BypassNode( vertex, new SkinningNode( object ) ); | ||
const dimension = `textureDimensions( ${textureProperty}, 0 )`; | ||
} | ||
return `textureLoad( ${textureProperty}, repeatWrapping( ${uvSnippet}, ${dimension} ), 0 )`; | ||
this.context.vertex = vertex; | ||
this.addFlow( 'vertex', new VarNode( new ModelViewProjectionNode(), 'MVP', 'vec4' ) ); | ||
// COLOR | ||
let colorNode = null; | ||
if ( material.colorNode && material.colorNode.isNode ) { | ||
colorNode = material.colorNode; | ||
} else { | ||
colorNode = new MaterialNode( MaterialNode.COLOR ); | ||
} | ||
colorNode = this.addFlow( 'fragment', new VarNode( colorNode, 'Color', 'vec4' ) ); | ||
const diffuseColorNode = this.addFlow( 'fragment', new VarNode( colorNode, 'DiffuseColor', 'vec4' ) ); | ||
// OPACITY | ||
let opacityNode = null; | ||
if ( material.opacityNode && material.opacityNode.isNode ) { | ||
opacityNode = material.opacityNode; | ||
} else { | ||
opacityNode = new VarNode( new MaterialNode( MaterialNode.OPACITY ) ); | ||
} | ||
this.addFlow( 'fragment', new VarNode( opacityNode, 'OPACITY', 'float' ) ); | ||
this.addFlow( 'fragment', new ExpressionNode( 'DiffuseColor.a = DiffuseColor.a * OPACITY;' ) ); | ||
// ALPHA TEST | ||
let alphaTest = null; | ||
if ( material.alphaTestNode && material.alphaTestNode.isNode ) { | ||
alphaTest = material.alphaTestNode; | ||
} else if ( material.alphaTest > 0 ) { | ||
alphaTest = new MaterialNode( MaterialNode.ALPHA_TEST ); | ||
} | ||
if ( alphaTest !== null ) { | ||
this.addFlow( 'fragment', new VarNode( alphaTest, 'AlphaTest', 'float' ) ); | ||
this.addFlow( 'fragment', new ExpressionNode( 'if ( DiffuseColor.a <= AlphaTest ) { discard; }' ) ); | ||
} | ||
if ( material.isMeshStandardMaterial ) { | ||
// METALNESS | ||
let metalnessNode = null; | ||
if ( material.metalnessNode && material.metalnessNode.isNode ) { | ||
metalnessNode = material.metalnessNode; | ||
} else { | ||
metalnessNode = new MaterialNode( MaterialNode.METALNESS ); | ||
} | ||
this.addFlow( 'fragment', new VarNode( metalnessNode, 'Metalness', 'float' ) ); | ||
this.addFlow( 'fragment', new ExpressionNode( 'DiffuseColor = vec4<f32>( DiffuseColor.rgb * ( 1.0 - Metalness ), DiffuseColor.a );' ) ); | ||
// ROUGHNESS | ||
let roughnessNode = null; | ||
if ( material.roughnessNode && material.roughnessNode.isNode ) { | ||
roughnessNode = material.roughnessNode; | ||
} else { | ||
roughnessNode = new MaterialNode( MaterialNode.ROUGHNESS ); | ||
} | ||
roughnessNode = getRoughness( { roughness: roughnessNode } ); | ||
this.addFlow( 'fragment', new VarNode( roughnessNode, 'Roughness', 'float' ) ); | ||
// SPECULAR_TINT | ||
this.addFlow( 'fragment', new VarNode( new ExpressionNode( 'mix( vec3<f32>( 0.04 ), Color.rgb, Metalness )', 'vec3' ), 'SpecularColor', 'color' ) ); | ||
// NORMAL_VIEW | ||
let normalNode = null; | ||
if ( material.normalNode && material.normalNode.isNode ) { | ||
normalNode = material.normalNode; | ||
} else { | ||
normalNode = new NormalNode( NormalNode.VIEW ); | ||
} | ||
this.addFlow( 'fragment', new VarNode( normalNode, 'TransformedNormalView', 'vec3' ) ); | ||
} | ||
// LIGHT | ||
let outputNode = diffuseColorNode; | ||
if ( lightNode && lightNode.isNode && lightNode.hasLight !== false ) { | ||
const lightContextNode = new LightContextNode( lightNode ); | ||
outputNode = this.addFlow( 'fragment', new VarNode( lightContextNode, 'Light', 'vec3' ) ); | ||
} | ||
// OUTGOING LIGHT | ||
let outgoingLightNode = vec3( outputNode ); | ||
// EMISSIVE | ||
const emissiveNode = material.emissiveNode; | ||
if ( emissiveNode && emissiveNode.isNode ) { | ||
outgoingLightNode = add( emissiveNode, outgoingLightNode ); | ||
} | ||
// OUTPUT | ||
outputNode = join( vec3( outgoingLightNode ), nodeObject( diffuseColorNode ).w ); | ||
// ENCODING | ||
const outputEncoding = this.renderer.outputEncoding; | ||
if ( outputEncoding !== LinearEncoding ) { | ||
outputNode = new ColorSpaceNode( ColorSpaceNode.LINEAR_TO_LINEAR, outputNode ); | ||
outputNode.fromEncoding( outputEncoding ); | ||
} | ||
// FOG | ||
const fogNode = this.fogNode; | ||
if ( fogNode && fogNode.isFogNode ) { | ||
outputNode = mix( outputNode, fogNode.colorNode, fogNode ); | ||
} | ||
// RESULT | ||
this.addFlow( 'fragment', new VarNode( outputNode, 'Output', 'vec4' ) ); | ||
} | ||
@@ -359,19 +171,7 @@ | ||
addFlowCode( code ) { | ||
getSamplerBias( textureProperty, uvSnippet, biasSnippet, shaderStage = this.shaderStage ) { | ||
if ( ! /;\s*$/.test( code ) ) { | ||
code += ';'; | ||
} | ||
super.addFlowCode( code + '\n\t' ); | ||
} | ||
getSampler( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { | ||
if ( shaderStage === 'fragment' ) { | ||
return `textureSample( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet} )`; | ||
return `textureSampleBias( ${textureProperty}, ${textureProperty}_sampler, ${uvSnippet}, ${biasSnippet} )`; | ||
@@ -384,3 +184,3 @@ } else { | ||
return `textureLoad( ${textureProperty}, repeatWrapping( ${uvSnippet}, ${dimension} ), 0 )`; | ||
return `textureLoad( ${textureProperty}, repeatWrapping( ${uvSnippet}, ${dimension} ), i32( ${biasSnippet} ) )`; | ||
@@ -397,2 +197,8 @@ } | ||
getTextureBias( textureProperty, uvSnippet, biasSnippet, shaderStage = this.shaderStage ) { | ||
return this.getSamplerBias( textureProperty, uvSnippet, biasSnippet, shaderStage ); | ||
} | ||
getCubeTexture( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { | ||
@@ -404,2 +210,8 @@ | ||
getCubeTextureBias( textureProperty, uvSnippet, biasSnippet, shaderStage = this.shaderStage ) { | ||
return this.getSamplerBias( textureProperty, uvSnippet, biasSnippet, shaderStage ); | ||
} | ||
getPropertyName( node, shaderStage = this.shaderStage ) { | ||
@@ -424,5 +236,5 @@ | ||
} else if ( type === 'buffer' ) { | ||
} else if ( type === 'buffer' || type === 'storageBuffer' ) { | ||
return `NodeBuffer.${name}`; | ||
return `NodeBuffer_${node.node.id}.${name}`; | ||
@@ -445,3 +257,3 @@ } else { | ||
return [ ...bindings.vertex, ...bindings.fragment ]; | ||
return this.material !== null ? [ ...bindings.vertex, ...bindings.fragment ] : bindings.compute; | ||
@@ -495,7 +307,8 @@ } | ||
} else if ( type === 'buffer' || type === 'storageBuffer' ) { | ||
} else if ( type === 'buffer' ) { | ||
const bufferClass = type === 'storageBuffer' ? WebGPUStorageBuffer : WebGPUUniformBuffer; | ||
const buffer = new bufferClass( 'NodeBuffer_' + node.id, node.value ); | ||
buffer.setVisibility( gpuShaderStageLib[ shaderStage ] ); | ||
const buffer = new WebGPUUniformBuffer( 'NodeBuffer', node.value ); | ||
// add first textures in sequence and group for last | ||
@@ -515,3 +328,4 @@ const lastBinding = bindings[ bindings.length - 1 ]; | ||
uniformsGroup = new WebGPUNodeUniformsGroup( shaderStage ); | ||
uniformsGroup = new WebGPUUniformsGroup( 'nodeUniforms' ); | ||
uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] ); | ||
@@ -572,13 +386,59 @@ this.uniformsGroup[ shaderStage ] = uniformsGroup; | ||
getBuiltin( name, property, type, shaderStage = this.shaderStage ) { | ||
const map = this.builtins[ shaderStage ]; | ||
if ( map.has( name ) === false ) { | ||
map.set( name, { | ||
name, | ||
property, | ||
type | ||
} ); | ||
} | ||
return property; | ||
} | ||
getInstanceIndex() { | ||
if ( this.shaderStage === 'vertex' ) { | ||
return this.getBuiltin( 'instance_index', 'instanceIndex', 'u32', 'attribute' ); | ||
} | ||
return 'instanceIndex'; | ||
} | ||
getFrontFacing() { | ||
return this.getBuiltin( 'front_facing', 'isFront', 'bool' ); | ||
} | ||
getAttributes( shaderStage ) { | ||
let snippet = ''; | ||
const snippets = []; | ||
if ( shaderStage === 'vertex' ) { | ||
if ( shaderStage === 'vertex' || shaderStage === 'compute' ) { | ||
if ( shaderStage === 'compute' ) { | ||
this.getBuiltin( 'global_invocation_id', 'id', 'vec3<u32>', 'attribute' ); | ||
} | ||
for ( const { name, property, type } of this.builtins.attribute.values() ) { | ||
snippets.push( `@builtin( ${name} ) ${property} : ${type}` ); | ||
} | ||
const attributes = this.attributes; | ||
const length = attributes.length; | ||
snippet += '\n'; | ||
for ( let index = 0; index < length; index ++ ) { | ||
@@ -590,17 +450,9 @@ | ||
snippet += `\t@location( ${index} ) ${ name } : ${ type }`; | ||
snippets.push( `@location( ${index} ) ${ name } : ${ type }` ); | ||
if ( index + 1 < length ) { | ||
snippet += ',\n'; | ||
} | ||
} | ||
snippet += '\n'; | ||
} | ||
return snippet; | ||
return snippets.join( ',\n\t' ); | ||
@@ -611,4 +463,3 @@ } | ||
let snippet = ''; | ||
const snippets = []; | ||
const vars = this.vars[ shaderStage ]; | ||
@@ -623,7 +474,7 @@ | ||
snippet += `var ${name} : ${type}; `; | ||
snippets.push( `\tvar ${name} : ${type};` ); | ||
} | ||
return snippet; | ||
return `\n${ snippets.join( '\n' ) }\n`; | ||
@@ -634,7 +485,7 @@ } | ||
let snippet = ''; | ||
const snippets = []; | ||
if ( shaderStage === 'vertex' ) { | ||
snippet += '\t@builtin( position ) Vertex: vec4<f32>;\n'; | ||
this.getBuiltin( 'position', 'Vertex', 'vec4<f32>', 'vertex' ); | ||
@@ -647,8 +498,6 @@ const varys = this.varys; | ||
snippet += `\t@location( ${index} ) ${ vary.name } : ${ this.getType( vary.type ) };\n`; | ||
snippets.push( `@location( ${index} ) ${ vary.name } : ${ this.getType( vary.type ) }` ); | ||
} | ||
snippet = this._getWGSLStruct( 'NodeVarysStruct', snippet ); | ||
} else if ( shaderStage === 'fragment' ) { | ||
@@ -658,4 +507,2 @@ | ||
snippet += '\n'; | ||
for ( let index = 0; index < varys.length; index ++ ) { | ||
@@ -665,18 +512,18 @@ | ||
snippet += `\t@location( ${index} ) ${ vary.name } : ${ this.getType( vary.type ) }`; | ||
snippets.push( `@location( ${index} ) ${ vary.name } : ${ this.getType( vary.type ) }` ); | ||
if ( index + 1 < varys.length ) { | ||
} | ||
snippet += ',\n'; | ||
} | ||
} | ||
for ( const { name, property, type } of this.builtins[ shaderStage ].values() ) { | ||
} | ||
snippets.push( `@builtin( ${name} ) ${property} : ${type}` ); | ||
snippet += '\n'; | ||
} | ||
return snippet; | ||
const code = snippets.join( ',\n\t' ); | ||
return shaderStage === 'vertex' ? this._getWGSLStruct( 'NodeVarysStruct', '\t' + code ) : code; | ||
} | ||
@@ -688,4 +535,5 @@ | ||
let snippet = ''; | ||
let groupSnippet = ''; | ||
const bindingSnippets = []; | ||
const bufferSnippets = []; | ||
const groupSnippets = []; | ||
@@ -700,7 +548,7 @@ let index = this.bindingsOffset[ shaderStage ]; | ||
snippet += `@group( 0 ) @binding( ${index ++} ) var ${uniform.name}_sampler : sampler; `; | ||
bindingSnippets.push( `@group( 0 ) @binding( ${index ++} ) var ${uniform.name}_sampler : sampler;` ); | ||
} | ||
snippet += `@group( 0 ) @binding( ${index ++} ) var ${uniform.name} : texture_2d<f32>; `; | ||
bindingSnippets.push( `@group( 0 ) @binding( ${index ++} ) var ${uniform.name} : texture_2d<f32>;` ); | ||
@@ -711,9 +559,9 @@ } else if ( uniform.type === 'cubeTexture' ) { | ||
snippet += `@group( 0 ) @binding( ${index ++} ) var ${uniform.name}_sampler : sampler; `; | ||
bindingSnippets.push( `@group( 0 ) @binding( ${index ++} ) var ${uniform.name}_sampler : sampler;` ); | ||
} | ||
snippet += `@group( 0 ) @binding( ${index ++} ) var ${uniform.name} : texture_cube<f32>; `; | ||
bindingSnippets.push( `@group( 0 ) @binding( ${index ++} ) var ${uniform.name} : texture_cube<f32>;` ); | ||
} else if ( uniform.type === 'buffer' ) { | ||
} else if ( uniform.type === 'buffer' || uniform.type === 'storageBuffer' ) { | ||
@@ -724,5 +572,7 @@ const bufferNode = uniform.node; | ||
const bufferSnippet = `\t${uniform.name} : array< ${bufferType}, ${bufferCount} >;\n`; | ||
const bufferCountSnippet = bufferCount > 0 ? ', ' + bufferCount : ''; | ||
const bufferSnippet = `\t${uniform.name} : array< ${bufferType}${bufferCountSnippet} >\n`; | ||
const bufferAccessMode = bufferNode.isStorageBufferNode ? 'storage,read_write' : 'uniform'; | ||
snippet += this._getWGSLUniforms( 'NodeBuffer', bufferSnippet, index ++ ) + '\n\n'; | ||
bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, index ++ ) ); | ||
@@ -737,7 +587,7 @@ } else { | ||
groupSnippet += `uniform ${vectorType}[ ${length} ] ${uniform.name}; `; | ||
groupSnippets.push( `uniform ${vectorType}[ ${length} ] ${uniform.name}` ); | ||
} else { | ||
groupSnippet += `\t${uniform.name} : ${ vectorType};\n`; | ||
groupSnippets.push( `\t${uniform.name} : ${ vectorType}` ); | ||
@@ -750,9 +600,12 @@ } | ||
if ( groupSnippet ) { | ||
let code = bindingSnippets.join( '\n' ); | ||
code += bufferSnippets.join( '\n' ); | ||
snippet += this._getWGSLUniforms( 'NodeUniforms', groupSnippet, index ++ ); | ||
if ( groupSnippets.length > 0 ) { | ||
code += this._getWGSLStructBinding( 'NodeUniforms', groupSnippets.join( ',\n' ), 'uniform', index ++ ); | ||
} | ||
return snippet; | ||
return code; | ||
@@ -763,3 +616,3 @@ } | ||
const shadersData = { fragment: {}, vertex: {} }; | ||
const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; | ||
@@ -770,3 +623,3 @@ for ( const shaderStage in shadersData ) { | ||
flow += `\t${ this.flowCode[ shaderStage ] }`; | ||
flow += '\n'; | ||
flow += '\n\t'; | ||
@@ -791,3 +644,3 @@ const flowNodes = this.flowNodes[ shaderStage ]; | ||
if ( node === mainNode ) { | ||
if ( node === mainNode && shaderStage !== 'compute' ) { | ||
@@ -823,5 +676,13 @@ flow += '// FLOW RESULT\n\t'; | ||
this.vertexShader = this._getWGSLVertexCode( shadersData.vertex ); | ||
this.fragmentShader = this._getWGSLFragmentCode( shadersData.fragment ); | ||
if ( this.material !== null ) { | ||
this.vertexShader = this._getWGSLVertexCode( shadersData.vertex ); | ||
this.fragmentShader = this._getWGSLFragmentCode( shadersData.fragment ); | ||
} else { | ||
this.computeShader = this._getWGSLComputeCode( shadersData.compute, ( this.object.workgroupSize || [ 64 ] ).join( ', ' ) ); | ||
} | ||
} | ||
@@ -847,2 +708,8 @@ | ||
isAvailable( name ) { | ||
return supports[ name ] === true; | ||
} | ||
_include( name ) { | ||
@@ -924,2 +791,31 @@ | ||
_getWGSLComputeCode( shaderData, workgroupSize ) { | ||
return `${ this.getSignature() } | ||
// system | ||
var<private> instanceIndex : u32; | ||
// uniforms | ||
${shaderData.uniforms} | ||
// codes | ||
${shaderData.codes} | ||
@stage( compute ) @workgroup_size( ${workgroupSize} ) | ||
fn main( ${shaderData.attributes} ) { | ||
// system | ||
instanceIndex = id.x; | ||
// vars | ||
${shaderData.vars} | ||
// flow | ||
${shaderData.flow} | ||
} | ||
`; | ||
} | ||
_getWGSLStruct( name, vars ) { | ||
@@ -929,3 +825,3 @@ | ||
struct ${name} { | ||
\n${vars} | ||
${vars} | ||
};`; | ||
@@ -935,3 +831,3 @@ | ||
_getWGSLUniforms( name, vars, binding = 0, group = 0 ) { | ||
_getWGSLStructBinding( name, vars, access, binding = 0, group = 0 ) { | ||
@@ -943,3 +839,3 @@ const structName = name + 'Struct'; | ||
@binding( ${binding} ) @group( ${group} ) | ||
var<uniform> ${name} : ${structName};`; | ||
var<${access}> ${name} : ${structName};`; | ||
@@ -946,0 +842,0 @@ } |
@@ -76,5 +76,5 @@ class WebGPUAttributes { | ||
const buffer = this.device.createBuffer( { | ||
size: size, | ||
size, | ||
usage: usage | GPUBufferUsage.COPY_DST, | ||
mappedAtCreation: true, | ||
mappedAtCreation: true | ||
} ); | ||
@@ -90,4 +90,4 @@ | ||
version: attribute.version, | ||
buffer: buffer, | ||
usage: usage | ||
buffer, | ||
usage | ||
}; | ||
@@ -94,0 +94,0 @@ |
@@ -60,2 +60,4 @@ import { GPULoadOp, GPUStoreOp } from './constants.js'; | ||
_clearColor.multiplyScalar( _clearAlpha ); | ||
colorAttachment.clearValue = { r: _clearColor.r, g: _clearColor.g, b: _clearColor.b, a: _clearAlpha }; | ||
@@ -62,0 +64,0 @@ colorAttachment.loadOp = GPULoadOp.Clear; |
@@ -33,5 +33,5 @@ class WebGPUBindings { | ||
const renderPipeline = this.renderPipelines.get( object ); | ||
const pipeline = object.isNode ? this.computePipelines.get( object ) : this.renderPipelines.get( object ).pipeline; | ||
const bindLayout = renderPipeline.pipeline.getBindGroupLayout( 0 ); | ||
const bindLayout = pipeline.getBindGroupLayout( 0 ); | ||
const bindGroup = this._createBindGroup( bindings, bindLayout ); | ||
@@ -112,4 +112,2 @@ | ||
const buffer = binding.getBuffer(); | ||
const bufferGPU = binding.bufferGPU; | ||
const needsBufferWrite = binding.update(); | ||
@@ -119,2 +117,4 @@ | ||
const bufferGPU = binding.bufferGPU; | ||
this.device.queue.writeBuffer( bufferGPU, 0, buffer, 0 ); | ||
@@ -127,2 +127,3 @@ | ||
const attribute = binding.attribute; | ||
this.attributes.update( attribute, false, binding.usage ); | ||
@@ -195,3 +196,3 @@ | ||
size: byteLength, | ||
usage: binding.usage, | ||
usage: binding.usage | ||
} ); | ||
@@ -251,4 +252,4 @@ | ||
return this.device.createBindGroup( { | ||
layout: layout, | ||
entries: entries | ||
layout, | ||
entries | ||
} ); | ||
@@ -255,0 +256,0 @@ |
@@ -5,5 +5,6 @@ import WebGPUProgrammableStage from './WebGPUProgrammableStage.js'; | ||
constructor( device ) { | ||
constructor( device, nodes ) { | ||
this.device = device; | ||
this.nodes = nodes; | ||
@@ -17,5 +18,5 @@ this.pipelines = new WeakMap(); | ||
get( param ) { | ||
get( computeNode ) { | ||
let pipeline = this.pipelines.get( param ); | ||
let pipeline = this.pipelines.get( computeNode ); | ||
@@ -28,4 +29,9 @@ // @TODO: Reuse compute pipeline if possible, introduce WebGPUComputePipeline | ||
// get shader | ||
const nodeBuilder = this.nodes.get( computeNode ); | ||
const computeShader = nodeBuilder.computeShader; | ||
const shader = { | ||
computeShader: param.shader | ||
computeShader | ||
}; | ||
@@ -39,3 +45,3 @@ | ||
stageCompute = new WebGPUProgrammableStage( device, shader.computeShader, 'compute' ); | ||
stageCompute = new WebGPUProgrammableStage( device, computeShader, 'compute' ); | ||
@@ -50,3 +56,3 @@ this.stages.compute.set( shader, stageCompute ); | ||
this.pipelines.set( param, pipeline ); | ||
this.pipelines.set( computeNode, pipeline ); | ||
@@ -53,0 +59,0 @@ } |
@@ -175,3 +175,3 @@ import { GPUIndexFormat, GPUTextureFormat, GPUStoreOp } from './constants.js'; | ||
format: GPUTextureFormat.BGRA8Unorm, // this is the only valid context format right now (r121) | ||
compositingAlphaMode: 'opaque' | ||
compositingAlphaMode: 'premultiplied' | ||
} ); | ||
@@ -190,3 +190,3 @@ | ||
this._nodes = new WebGPUNodes( this, this._properties ); | ||
this._computePipelines = new WebGPUComputePipelines( device ); | ||
this._computePipelines = new WebGPUComputePipelines( device, this._nodes ); | ||
this._renderPipelines = new WebGPURenderPipelines( this, device, parameters.sampleCount, this._nodes ); | ||
@@ -616,3 +616,3 @@ this._bindings = this._renderPipelines.bindings = new WebGPUBindings( device, this._info, this._properties, this._textures, this._renderPipelines, this._computePipelines, this._attributes, this._nodes ); | ||
compute( computeParams ) { | ||
compute( ...computeNodes ) { | ||
@@ -623,16 +623,20 @@ const device = this._device; | ||
for ( const param of computeParams ) { | ||
for ( const computeNode of computeNodes ) { | ||
// pipeline | ||
const pipeline = this._computePipelines.get( param ); | ||
const pipeline = this._computePipelines.get( computeNode ); | ||
passEncoder.setPipeline( pipeline ); | ||
// node | ||
//this._nodes.update( computeNode ); | ||
// bind group | ||
const bindGroup = this._bindings.getForCompute( param ).group; | ||
this._bindings.update( param ); | ||
const bindGroup = this._bindings.get( computeNode ).group; | ||
this._bindings.update( computeNode ); | ||
passEncoder.setBindGroup( 0, bindGroup ); | ||
passEncoder.dispatch( param.num ); | ||
passEncoder.dispatch( computeNode.dispatchCount ); | ||
@@ -854,4 +858,5 @@ } | ||
const firstVertex = drawRange.start; | ||
const instanceCount = ( geometry.isInstancedBufferGeometry ) ? geometry.instanceCount : 1; | ||
const instanceCount = geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.isInstancedMesh ? object.count : 1 ); | ||
if ( hasIndex === true ) { | ||
@@ -965,2 +970,3 @@ | ||
usage: GPUTextureUsage.RENDER_ATTACHMENT, | ||
compositingAlphaMode: 'premultiplied', | ||
size: { | ||
@@ -967,0 +973,0 @@ width: Math.floor( this._width * this._pixelRatio ), |
@@ -451,4 +451,4 @@ import { GPUPrimitiveTopology, GPUIndexFormat, GPUCompareFunction, GPUFrontFace, GPUCullMode, GPUVertexFormat, GPUBlendFactor, GPUBlendOperation, BlendColorFactor, OneMinusBlendColorFactor, GPUColorWriteFlags, GPUStencilOperation, GPUInputStepMode } from './constants.js'; | ||
case FrontSide: | ||
descriptor.frontFace = GPUFrontFace.CCW; | ||
descriptor.cullMode = GPUCullMode.Back; | ||
descriptor.frontFace = GPUFrontFace.CW; | ||
descriptor.cullMode = GPUCullMode.Front; | ||
break; | ||
@@ -462,3 +462,3 @@ | ||
case DoubleSide: | ||
descriptor.frontFace = GPUFrontFace.CCW; | ||
descriptor.frontFace = GPUFrontFace.CW; | ||
descriptor.cullMode = GPUCullMode.None; | ||
@@ -465,0 +465,0 @@ break; |
@@ -27,3 +27,2 @@ import WebGPURenderPipeline from './WebGPURenderPipeline.js'; | ||
const device = this.device; | ||
const material = object.material; | ||
@@ -36,2 +35,4 @@ const cache = this._getCache( object ); | ||
const material = object.material; | ||
// release previous cache | ||
@@ -38,0 +39,0 @@ |
@@ -1,16 +0,13 @@ | ||
import WebGPUBinding from './WebGPUBinding.js'; | ||
import WebGPUBuffer from './WebGPUBuffer.js'; | ||
import { GPUBindingType } from './constants.js'; | ||
class WebGPUStorageBuffer extends WebGPUBinding { | ||
class WebGPUStorageBuffer extends WebGPUBuffer { | ||
constructor( name, attribute ) { | ||
super( name ); | ||
super( name, GPUBindingType.StorageBuffer, attribute.array ); | ||
this.type = GPUBindingType.StorageBuffer; | ||
this.usage |= GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE; | ||
this.usage = GPUBufferUsage.VERTEX | GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST; | ||
this.attribute = attribute; | ||
this.bufferGPU = null; // set by the renderer | ||
@@ -17,0 +14,0 @@ } |
@@ -33,6 +33,4 @@ // Copyright 2020 Brandon Jones | ||
struct VarysStruct { | ||
@builtin( position ) Position: vec4<f32>; | ||
@location( 0 ) vTex : vec2<f32>; | ||
@builtin( position ) Position: vec4<f32>, | ||
@location( 0 ) vTex : vec2<f32> | ||
}; | ||
@@ -43,3 +41,3 @@ | ||
var Varys: VarysStruct; | ||
var Varys : VarysStruct; | ||
@@ -69,3 +67,3 @@ var pos = array< vec2<f32>, 4 >( | ||
const mipmapFragmentSource = ` | ||
@group( 0 ) @binding( 0 ) | ||
@group( 0 ) @binding( 0 ) | ||
var imgSampler : sampler; | ||
@@ -108,3 +106,3 @@ | ||
module: this.mipmapVertexShaderModule, | ||
entryPoint: 'main', | ||
entryPoint: 'main' | ||
}, | ||
@@ -114,3 +112,3 @@ fragment: { | ||
entryPoint: 'main', | ||
targets: [ { format } ], | ||
targets: [ { format } ] | ||
}, | ||
@@ -117,0 +115,0 @@ primitive: { |
@@ -1,41 +0,14 @@ | ||
import WebGPUBinding from './WebGPUBinding.js'; | ||
import { getFloatLength } from './WebGPUBufferUtils.js'; | ||
import WebGPUBuffer from './WebGPUBuffer.js'; | ||
import { GPUBindingType } from './constants.js'; | ||
class WebGPUUniformBuffer extends WebGPUBinding { | ||
class WebGPUUniformBuffer extends WebGPUBuffer { | ||
constructor( name, buffer = null ) { | ||
super( name ); | ||
super( name, GPUBindingType.UniformBuffer, buffer ); | ||
this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT; | ||
this.type = GPUBindingType.UniformBuffer; | ||
this.visibility = GPUShaderStage.VERTEX; | ||
this.usage |= GPUBufferUsage.UNIFORM; | ||
this.usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST; | ||
this.buffer = buffer; | ||
this.bufferGPU = null; // set by the renderer | ||
} | ||
getByteLength() { | ||
return getFloatLength( this.buffer.byteLength ); | ||
} | ||
getBuffer() { | ||
return this.buffer; | ||
} | ||
update() { | ||
return true; | ||
} | ||
} | ||
@@ -42,0 +15,0 @@ |
@@ -14,5 +14,10 @@ import { | ||
function computeTangents() { | ||
function computeTangents( geometry, MikkTSpace, negateSign = true ) { | ||
throw new Error( 'BufferGeometryUtils: computeTangents renamed to computeMikkTSpaceTangents.' ); | ||
} | ||
function computeMikkTSpaceTangents( geometry, MikkTSpace, negateSign = true ) { | ||
if ( ! MikkTSpace || ! MikkTSpace.isReady ) { | ||
@@ -24,2 +29,8 @@ | ||
if ( ! geometry.hasAttribute( 'position' ) || ! geometry.hasAttribute( 'normal' ) || ! geometry.hasAttribute( 'uv' ) ) { | ||
throw new Error( 'BufferGeometryUtils: Tangents require "position", "normal", and "uv" attributes.' ); | ||
} | ||
function getAttributeArray( attribute ) { | ||
@@ -431,2 +442,93 @@ | ||
// returns a new, non-interleaved version of the provided attribute | ||
export function deinterleaveAttribute( attribute ) { | ||
const cons = attribute.data.array.constructor; | ||
const count = attribute.count; | ||
const itemSize = attribute.itemSize; | ||
const normalized = attribute.normalized; | ||
const array = new cons( count * itemSize ); | ||
let newAttribute; | ||
if ( attribute.isInstancedInterleavedBufferAttribute ) { | ||
newAttribute = new InstancedBufferAttribute( array, itemSize, normalized, attribute.meshPerAttribute ); | ||
} else { | ||
newAttribute = new BufferAttribute( array, itemSize, normalized ); | ||
} | ||
for ( let i = 0; i < count; i ++ ) { | ||
newAttribute.setX( i, attribute.getX( i ) ); | ||
if ( itemSize >= 2 ) { | ||
newAttribute.setY( i, attribute.getY( i ) ); | ||
} | ||
if ( itemSize >= 3 ) { | ||
newAttribute.setZ( i, attribute.getZ( i ) ); | ||
} | ||
if ( itemSize >= 4 ) { | ||
newAttribute.setW( i, attribute.getW( i ) ); | ||
} | ||
} | ||
return newAttribute; | ||
} | ||
// deinterleaves all attributes on the geometry | ||
export function deinterleaveGeometry( geometry ) { | ||
const attributes = geometry.attributes; | ||
const morphTargets = geometry.morphTargets; | ||
const attrMap = new Map(); | ||
for ( const key in attributes ) { | ||
const attr = attributes[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
if ( ! attrMap.has( attr ) ) { | ||
attrMap.set( attr, deinterleaveAttribute( attr ) ); | ||
} | ||
attributes[ key ] = attrMap.get( attr ); | ||
} | ||
} | ||
for ( const key in morphTargets ) { | ||
const attr = morphTargets[ key ]; | ||
if ( attr.isInterleavedBufferAttribute ) { | ||
if ( ! attrMap.has( attr ) ) { | ||
attrMap.set( attr, deinterleaveAttribute( attr ) ); | ||
} | ||
morphTargets[ key ] = attrMap.get( attr ); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -743,3 +845,2 @@ * @param {Array<BufferGeometry>} geometry | ||
object, | ||
material, | ||
attribute, | ||
@@ -760,3 +861,3 @@ morphAttribute, | ||
if ( material.morphTargets && morphAttribute && morphInfluences ) { | ||
if ( morphAttribute && morphInfluences ) { | ||
@@ -834,3 +935,3 @@ _morphA.set( 0, 0, 0 ); | ||
let i, j, il, jl; | ||
let group, groupMaterial; | ||
let group; | ||
let start, end; | ||
@@ -850,3 +951,2 @@ | ||
group = groups[ i ]; | ||
groupMaterial = material[ group.materialIndex ]; | ||
@@ -864,3 +964,2 @@ start = Math.max( group.start, drawRange.start ); | ||
object, | ||
groupMaterial, | ||
positionAttribute, | ||
@@ -875,3 +974,2 @@ morphPosition, | ||
object, | ||
groupMaterial, | ||
normalAttribute, | ||
@@ -901,3 +999,2 @@ morphNormal, | ||
object, | ||
material, | ||
positionAttribute, | ||
@@ -912,3 +1009,2 @@ morphPosition, | ||
object, | ||
material, | ||
normalAttribute, | ||
@@ -934,3 +1030,2 @@ morphNormal, | ||
group = groups[ i ]; | ||
groupMaterial = material[ group.materialIndex ]; | ||
@@ -948,3 +1043,2 @@ start = Math.max( group.start, drawRange.start ); | ||
object, | ||
groupMaterial, | ||
positionAttribute, | ||
@@ -959,3 +1053,2 @@ morphPosition, | ||
object, | ||
groupMaterial, | ||
normalAttribute, | ||
@@ -985,3 +1078,2 @@ morphNormal, | ||
object, | ||
material, | ||
positionAttribute, | ||
@@ -996,3 +1088,2 @@ morphPosition, | ||
object, | ||
material, | ||
normalAttribute, | ||
@@ -1129,2 +1220,3 @@ morphNormal, | ||
computeTangents, | ||
computeMikkTSpaceTangents, | ||
mergeBufferGeometries, | ||
@@ -1131,0 +1223,0 @@ mergeBufferAttributes, |
@@ -189,2 +189,6 @@ class VRButton { | ||
// WebXRViewer (based on Firefox) has a bug where addEventListener | ||
// throws a silent exception and aborts execution entirely. | ||
if ( /WebXRViewer\//i.test( navigator.userAgent ) ) return; | ||
navigator.xr.addEventListener( 'sessiongranted', () => { | ||
@@ -191,0 +195,0 @@ |
@@ -86,2 +86,4 @@ import { | ||
controller.visible = true; | ||
} ); | ||
@@ -91,2 +93,3 @@ | ||
controller.visible = false; | ||
// handModel.motionController = null; | ||
@@ -93,0 +96,0 @@ // handModel.remove( scene ); |
{ | ||
"name": "three", | ||
"version": "0.139.2", | ||
"version": "0.140.0", | ||
"description": "JavaScript 3D library", | ||
@@ -140,20 +140,20 @@ "type": "module", | ||
"devDependencies": { | ||
"@babel/core": "^7.15.5", | ||
"@babel/eslint-parser": "^7.15.7", | ||
"@babel/plugin-proposal-class-properties": "^7.14.5", | ||
"@babel/preset-env": "^7.15.6", | ||
"@rollup/plugin-babel": "^5.3.0", | ||
"@rollup/plugin-node-resolve": "^13.0.5", | ||
"chalk": "^4.1.2", | ||
"concurrently": "^6.2.2", | ||
"eslint": "^7.32.0", | ||
"@babel/core": "^7.17.9", | ||
"@babel/eslint-parser": "^7.17.0", | ||
"@babel/plugin-proposal-class-properties": "^7.16.7", | ||
"@babel/preset-env": "^7.16.11", | ||
"@rollup/plugin-babel": "^5.3.1", | ||
"@rollup/plugin-node-resolve": "^13.2.0", | ||
"chalk": "^5.0.1", | ||
"concurrently": "^7.1.0", | ||
"eslint": "^8.13.0", | ||
"eslint-config-mdcs": "^5.0.0", | ||
"eslint-plugin-compat": "^4.0.2", | ||
"eslint-plugin-html": "^6.2.0", | ||
"eslint-plugin-import": "^2.25.4", | ||
"rollup": "^2.57.0", | ||
"rollup-plugin-filesize": "^9.1.1", | ||
"eslint-plugin-import": "^2.26.0", | ||
"rollup": "^2.70.2", | ||
"rollup-plugin-filesize": "^9.1.2", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"rollup-plugin-visualizer": "^5.5.2", | ||
"servez": "^1.12.0" | ||
"rollup-plugin-visualizer": "^5.6.0", | ||
"servez": "^1.14.1" | ||
}, | ||
@@ -160,0 +160,0 @@ "jspm": { |
@@ -1,2 +0,2 @@ | ||
import { LinearEncoding, NoToneMapping } from '../constants.js'; | ||
import { NoToneMapping } from '../constants.js'; | ||
import { Object3D } from '../core/Object3D.js'; | ||
@@ -73,7 +73,5 @@ import { Vector3 } from '../math/Vector3.js'; | ||
const currentOutputEncoding = renderer.outputEncoding; | ||
const currentToneMapping = renderer.toneMapping; | ||
const currentXrEnabled = renderer.xr.enabled; | ||
renderer.outputEncoding = LinearEncoding; | ||
renderer.toneMapping = NoToneMapping; | ||
@@ -108,3 +106,2 @@ renderer.xr.enabled = false; | ||
renderer.outputEncoding = currentOutputEncoding; | ||
renderer.toneMapping = currentToneMapping; | ||
@@ -111,0 +108,0 @@ renderer.xr.enabled = currentXrEnabled; |
@@ -1,2 +0,2 @@ | ||
export const REVISION = '139'; | ||
export const REVISION = '140'; | ||
export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; | ||
@@ -3,0 +3,0 @@ export const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; |
@@ -250,3 +250,3 @@ import { | ||
const width = 3 * Math.max( this._cubeSize, 16 * 7 ); | ||
const height = 4 * this._cubeSize - 32; | ||
const height = 4 * this._cubeSize; | ||
@@ -592,5 +592,5 @@ const params = { | ||
const texelSize = 1.0 / ( sizeLod - 1 ); | ||
const min = - texelSize / 2; | ||
const max = 1 + texelSize / 2; | ||
const texelSize = 1.0 / ( sizeLod - 2 ); | ||
const min = - texelSize; | ||
const max = 1 + texelSize; | ||
const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; | ||
@@ -597,0 +597,0 @@ |
@@ -18,2 +18,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -34,2 +36,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -36,0 +40,0 @@ |
@@ -20,4 +20,2 @@ import { EventDispatcher } from '../core/EventDispatcher.js'; | ||
this.fog = true; | ||
this.blending = NormalBlending; | ||
@@ -354,2 +352,4 @@ this.side = FrontSide; | ||
if ( this.fog === false ) data.fog = false; | ||
if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; | ||
@@ -399,4 +399,2 @@ | ||
this.fog = source.fog; | ||
this.blending = source.blending; | ||
@@ -403,0 +401,0 @@ this.side = source.side; |
@@ -37,2 +37,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -70,2 +72,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -72,0 +76,0 @@ |
@@ -25,4 +25,2 @@ import { Material } from './Material.js'; | ||
this.fog = false; | ||
this.setValues( parameters ); | ||
@@ -29,0 +27,0 @@ |
@@ -24,4 +24,2 @@ import { Material } from './Material.js'; | ||
this.fog = false; | ||
this.setValues( parameters ); | ||
@@ -28,0 +26,0 @@ |
@@ -41,2 +41,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -78,2 +80,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -80,0 +84,0 @@ |
@@ -37,2 +37,4 @@ import { TangentSpaceNormalMap } from '../constants.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -70,2 +72,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -72,0 +76,0 @@ |
@@ -27,4 +27,2 @@ import { TangentSpaceNormalMap } from '../constants.js'; | ||
this.fog = false; | ||
this.flatShading = false; | ||
@@ -31,0 +29,0 @@ |
@@ -57,2 +57,4 @@ import { MultiplyOperation, TangentSpaceNormalMap } from '../constants.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -109,2 +111,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -111,0 +115,0 @@ |
@@ -59,2 +59,4 @@ import { TangentSpaceNormalMap } from '../constants.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -113,2 +115,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -115,0 +119,0 @@ |
@@ -49,2 +49,4 @@ import { TangentSpaceNormalMap } from '../constants.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -91,2 +93,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -93,0 +97,0 @@ |
@@ -21,2 +21,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -39,2 +41,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -41,0 +45,0 @@ |
@@ -78,2 +78,3 @@ import { Material } from './Material.js'; | ||
this.fog = source.fog; | ||
this.lights = source.lights; | ||
@@ -80,0 +81,0 @@ this.clipping = source.clipping; |
@@ -15,2 +15,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -26,2 +28,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -28,0 +32,0 @@ |
@@ -24,2 +24,4 @@ import { Material } from './Material.js'; | ||
this.fog = true; | ||
this.setValues( parameters ); | ||
@@ -43,2 +45,4 @@ | ||
this.fog = source.fog; | ||
return this; | ||
@@ -45,0 +49,0 @@ |
@@ -597,2 +597,10 @@ import { clamp, euclideanModulo, lerp } from './MathUtils.js'; | ||
*[ Symbol.iterator ]() { | ||
yield this.r; | ||
yield this.g; | ||
yield this.b; | ||
} | ||
} | ||
@@ -599,0 +607,0 @@ |
@@ -300,2 +300,11 @@ import { Quaternion } from './Quaternion.js'; | ||
*[ Symbol.iterator ]() { | ||
yield this._x; | ||
yield this._y; | ||
yield this._z; | ||
yield this._order; | ||
} | ||
} | ||
@@ -302,0 +311,0 @@ |
@@ -685,2 +685,11 @@ import * as MathUtils from './MathUtils.js'; | ||
*[ Symbol.iterator ]() { | ||
yield this._x; | ||
yield this._y; | ||
yield this._z; | ||
yield this._w; | ||
} | ||
} | ||
@@ -687,0 +696,0 @@ |
@@ -88,3 +88,3 @@ export default /* glsl */` | ||
vec2 uv = getUV( direction, face ) * ( faceSize - 1.0 ) + 0.5; | ||
vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; | ||
@@ -91,0 +91,0 @@ if ( face > 2.0 ) { |
@@ -7,43 +7,28 @@ export default /* glsl */` | ||
#ifdef BONE_TEXTURE | ||
uniform highp sampler2D boneTexture; | ||
uniform int boneTextureSize; | ||
uniform highp sampler2D boneTexture; | ||
uniform int boneTextureSize; | ||
mat4 getBoneMatrix( const in float i ) { | ||
mat4 getBoneMatrix( const in float i ) { | ||
float j = i * 4.0; | ||
float x = mod( j, float( boneTextureSize ) ); | ||
float y = floor( j / float( boneTextureSize ) ); | ||
float j = i * 4.0; | ||
float x = mod( j, float( boneTextureSize ) ); | ||
float y = floor( j / float( boneTextureSize ) ); | ||
float dx = 1.0 / float( boneTextureSize ); | ||
float dy = 1.0 / float( boneTextureSize ); | ||
float dx = 1.0 / float( boneTextureSize ); | ||
float dy = 1.0 / float( boneTextureSize ); | ||
y = dy * ( y + 0.5 ); | ||
y = dy * ( y + 0.5 ); | ||
vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) ); | ||
vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) ); | ||
vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) ); | ||
vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) ); | ||
vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) ); | ||
vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) ); | ||
vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) ); | ||
vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) ); | ||
mat4 bone = mat4( v1, v2, v3, v4 ); | ||
mat4 bone = mat4( v1, v2, v3, v4 ); | ||
return bone; | ||
return bone; | ||
} | ||
} | ||
#else | ||
uniform mat4 boneMatrices[ MAX_BONES ]; | ||
mat4 getBoneMatrix( const in float i ) { | ||
mat4 bone = boneMatrices[ int(i) ]; | ||
return bone; | ||
} | ||
#endif | ||
#endif | ||
`; |
@@ -119,2 +119,4 @@ import { BackSide, FrontSide, CubeUVReflectionMapping } from '../../constants.js'; | ||
boxMesh.layers.enableAll(); | ||
// push to the pre-sorted opaque render list | ||
@@ -180,2 +182,3 @@ renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null ); | ||
planeMesh.layers.enableAll(); | ||
@@ -182,0 +185,0 @@ // push to the pre-sorted opaque render list |
@@ -29,5 +29,5 @@ function WebGLBindingStates( gl, extensions, attributes, capabilities ) { | ||
updateBuffers = needsUpdate( geometry, index ); | ||
updateBuffers = needsUpdate( object, geometry, program, index ); | ||
if ( updateBuffers ) saveCache( geometry, index ); | ||
if ( updateBuffers ) saveCache( object, geometry, program, index ); | ||
@@ -52,8 +52,2 @@ } else { | ||
if ( object.isInstancedMesh === true ) { | ||
updateBuffers = true; | ||
} | ||
if ( index !== null ) { | ||
@@ -172,3 +166,3 @@ | ||
function needsUpdate( geometry, index ) { | ||
function needsUpdate( object, geometry, program, index ) { | ||
@@ -180,15 +174,30 @@ const cachedAttributes = currentState.attributes; | ||
for ( const key in geometryAttributes ) { | ||
const programAttributes = program.getAttributes(); | ||
const cachedAttribute = cachedAttributes[ key ]; | ||
const geometryAttribute = geometryAttributes[ key ]; | ||
for ( const name in programAttributes ) { | ||
if ( cachedAttribute === undefined ) return true; | ||
const programAttribute = programAttributes[ name ]; | ||
if ( cachedAttribute.attribute !== geometryAttribute ) return true; | ||
if ( programAttribute.location >= 0 ) { | ||
if ( cachedAttribute.data !== geometryAttribute.data ) return true; | ||
const cachedAttribute = cachedAttributes[ name ]; | ||
let geometryAttribute = geometryAttributes[ name ]; | ||
attributesNum ++; | ||
if ( geometryAttribute === undefined ) { | ||
if ( name === 'instanceMatrix' && object.instanceMatrix ) geometryAttribute = object.instanceMatrix; | ||
if ( name === 'instanceColor' && object.instanceColor ) geometryAttribute = object.instanceColor; | ||
} | ||
if ( cachedAttribute === undefined ) return true; | ||
if ( cachedAttribute.attribute !== geometryAttribute ) return true; | ||
if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data ) return true; | ||
attributesNum ++; | ||
} | ||
} | ||
@@ -204,3 +213,3 @@ | ||
function saveCache( geometry, index ) { | ||
function saveCache( object, geometry, program, index ) { | ||
@@ -211,19 +220,34 @@ const cache = {}; | ||
for ( const key in attributes ) { | ||
const programAttributes = program.getAttributes(); | ||
const attribute = attributes[ key ]; | ||
for ( const name in programAttributes ) { | ||
const data = {}; | ||
data.attribute = attribute; | ||
const programAttribute = programAttributes[ name ]; | ||
if ( attribute.data ) { | ||
if ( programAttribute.location >= 0 ) { | ||
data.data = attribute.data; | ||
let attribute = attributes[ name ]; | ||
} | ||
if ( attribute === undefined ) { | ||
cache[ key ] = data; | ||
if ( name === 'instanceMatrix' && object.instanceMatrix ) attribute = object.instanceMatrix; | ||
if ( name === 'instanceColor' && object.instanceColor ) attribute = object.instanceColor; | ||
attributesNum ++; | ||
} | ||
const data = {}; | ||
data.attribute = attribute; | ||
if ( attribute && attribute.data ) { | ||
data.data = attribute.data; | ||
} | ||
cache[ name ] = data; | ||
attributesNum ++; | ||
} | ||
} | ||
@@ -230,0 +254,0 @@ |
@@ -532,3 +532,2 @@ import { Color } from '../../math/Color.js'; | ||
uniforms.direction.transformDirection( viewMatrix ); | ||
uniforms.direction.normalize(); | ||
@@ -535,0 +534,0 @@ hemiLength ++; |
@@ -49,9 +49,17 @@ import { WebGLUniforms } from './WebGLUniforms.js'; | ||
const errorLine = parseInt( /ERROR: 0:(\d+)/.exec( errors )[ 1 ] ); | ||
const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); | ||
if ( errorMatches ) { | ||
// --enable-privileged-webgl-extension | ||
// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); | ||
// --enable-privileged-webgl-extension | ||
// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); | ||
return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); | ||
const errorLine = parseInt( errorMatches[ 0 ] ); | ||
return type.toUpperCase() + '\n\n' + errors + '\n\n' + handleSource( gl.getShaderSource( shader ), errorLine ); | ||
} else { | ||
return errors; | ||
} | ||
} | ||
@@ -377,3 +385,3 @@ | ||
const maxMip = Math.log2( imageHeight / 32 + 1 ) + 3; | ||
const maxMip = Math.log2( imageHeight ) - 2; | ||
@@ -457,3 +465,2 @@ const texelHeight = 1.0 / imageHeight; | ||
'#define MAX_BONES ' + parameters.maxBones, | ||
( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', | ||
@@ -503,3 +510,2 @@ ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', | ||
parameters.skinning ? '#define USE_SKINNING' : '', | ||
parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', | ||
@@ -690,3 +696,3 @@ parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', | ||
parameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', | ||
parameters.useDepthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '', | ||
@@ -693,0 +699,0 @@ '\n' |
@@ -16,4 +16,2 @@ import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, LinearEncoding, sRGBEncoding, NormalBlending } from '../../constants.js'; | ||
const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; | ||
const floatVertexTextures = capabilities.floatVertexTextures; | ||
const maxVertexUniforms = capabilities.maxVertexUniforms; | ||
const vertexTextures = capabilities.vertexTextures; | ||
@@ -40,38 +38,2 @@ let precision = capabilities.precision; | ||
function getMaxBones( object ) { | ||
const skeleton = object.skeleton; | ||
const bones = skeleton.bones; | ||
if ( floatVertexTextures ) { | ||
return 1024; | ||
} else { | ||
// default for when object is not specified | ||
// ( for example when prebuilding shader to be used with multiple objects ) | ||
// | ||
// - leave some extra space for other uniforms | ||
// - limit here is ANGLE's 254 max uniform vectors | ||
// (up to 54 should be safe) | ||
const nVertexUniforms = maxVertexUniforms; | ||
const nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); | ||
const maxBones = Math.min( nVertexMatrices, bones.length ); | ||
if ( maxBones < bones.length ) { | ||
console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); | ||
return 0; | ||
} | ||
return maxBones; | ||
} | ||
} | ||
function getParameters( material, lights, shadows, scene, object ) { | ||
@@ -91,4 +53,2 @@ | ||
const maxBones = object.isSkinnedMesh ? getMaxBones( object ) : 0; | ||
if ( material.precision !== null ) { | ||
@@ -221,3 +181,3 @@ | ||
fog: !! fog, | ||
useFog: material.fog, | ||
useFog: material.fog === true, | ||
fogExp2: ( fog && fog.isFogExp2 ), | ||
@@ -230,5 +190,3 @@ | ||
skinning: object.isSkinnedMesh === true && maxBones > 0, | ||
maxBones: maxBones, | ||
useVertexTexture: floatVertexTextures, | ||
skinning: object.isSkinnedMesh === true, | ||
@@ -267,3 +225,4 @@ morphTargets: geometry.morphAttributes.position !== undefined, | ||
depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false, | ||
useDepthPacking: !! material.depthPacking, | ||
depthPacking: material.depthPacking || 0, | ||
@@ -339,3 +298,2 @@ index0AttributeName: material.index0AttributeName, | ||
array.push( parameters.sizeAttenuation ); | ||
array.push( parameters.maxBones ); | ||
array.push( parameters.morphTargetsCount ); | ||
@@ -355,2 +313,3 @@ array.push( parameters.morphAttributeCount ); | ||
array.push( parameters.numClipIntersection ); | ||
array.push( parameters.depthPacking ); | ||
@@ -437,44 +396,42 @@ } | ||
_programLayers.enable( 3 ); | ||
if ( parameters.useVertexTexture ) | ||
if ( parameters.morphTargets ) | ||
_programLayers.enable( 4 ); | ||
if ( parameters.morphTargets ) | ||
if ( parameters.morphNormals ) | ||
_programLayers.enable( 5 ); | ||
if ( parameters.morphNormals ) | ||
if ( parameters.morphColors ) | ||
_programLayers.enable( 6 ); | ||
if ( parameters.morphColors ) | ||
if ( parameters.premultipliedAlpha ) | ||
_programLayers.enable( 7 ); | ||
if ( parameters.premultipliedAlpha ) | ||
if ( parameters.shadowMapEnabled ) | ||
_programLayers.enable( 8 ); | ||
if ( parameters.shadowMapEnabled ) | ||
if ( parameters.physicallyCorrectLights ) | ||
_programLayers.enable( 9 ); | ||
if ( parameters.physicallyCorrectLights ) | ||
if ( parameters.doubleSided ) | ||
_programLayers.enable( 10 ); | ||
if ( parameters.doubleSided ) | ||
if ( parameters.flipSided ) | ||
_programLayers.enable( 11 ); | ||
if ( parameters.flipSided ) | ||
if ( parameters.useDepthPacking ) | ||
_programLayers.enable( 12 ); | ||
if ( parameters.depthPacking ) | ||
if ( parameters.dithering ) | ||
_programLayers.enable( 13 ); | ||
if ( parameters.dithering ) | ||
if ( parameters.specularIntensityMap ) | ||
_programLayers.enable( 14 ); | ||
if ( parameters.specularIntensityMap ) | ||
if ( parameters.specularColorMap ) | ||
_programLayers.enable( 15 ); | ||
if ( parameters.specularColorMap ) | ||
if ( parameters.transmission ) | ||
_programLayers.enable( 16 ); | ||
if ( parameters.transmission ) | ||
if ( parameters.transmissionMap ) | ||
_programLayers.enable( 17 ); | ||
if ( parameters.transmissionMap ) | ||
if ( parameters.thicknessMap ) | ||
_programLayers.enable( 18 ); | ||
if ( parameters.thicknessMap ) | ||
if ( parameters.sheen ) | ||
_programLayers.enable( 19 ); | ||
if ( parameters.sheen ) | ||
if ( parameters.sheenColorMap ) | ||
_programLayers.enable( 20 ); | ||
if ( parameters.sheenColorMap ) | ||
if ( parameters.sheenRoughnessMap ) | ||
_programLayers.enable( 21 ); | ||
if ( parameters.sheenRoughnessMap ) | ||
if ( parameters.decodeVideoTexture ) | ||
_programLayers.enable( 22 ); | ||
if ( parameters.decodeVideoTexture ) | ||
if ( parameters.opaque ) | ||
_programLayers.enable( 23 ); | ||
if ( parameters.opaque ) | ||
_programLayers.enable( 24 ); | ||
@@ -481,0 +438,0 @@ array.push( _programLayers.mask ); |
@@ -700,3 +700,3 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, sRGBEncoding, LinearEncoding, UnsignedByteType, _SRGBAFormat } from '../../constants.js'; | ||
const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true ); | ||
const allocateMemory = ( textureProperties.__version === undefined ); | ||
const allocateMemory = ( textureProperties.__version === undefined ) || ( forceUpload === true ); | ||
const levels = getMipLevels( texture, image, supportsMips ); | ||
@@ -780,10 +780,14 @@ | ||
if ( useTexStorage && allocateMemory ) { | ||
if ( allocateMemory ) { | ||
state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); | ||
if ( useTexStorage ) { | ||
} else { | ||
state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height ); | ||
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); | ||
} else { | ||
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); | ||
} | ||
} | ||
@@ -929,10 +933,23 @@ | ||
if ( useTexStorage && allocateMemory ) { | ||
if ( allocateMemory ) { | ||
state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); | ||
if ( useTexStorage ) { | ||
} else { | ||
state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height ); | ||
state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null ); | ||
} else { | ||
let width = image.width, height = image.height; | ||
for ( let i = 0; i < levels; i ++ ) { | ||
state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, width, height, 0, glFormat, glType, null ); | ||
width >>= 1; | ||
height >>= 1; | ||
} | ||
} | ||
} | ||
@@ -939,0 +956,0 @@ |
@@ -838,16 +838,2 @@ /** | ||
PureArrayUniform.prototype.updateCache = function ( data ) { | ||
const cache = this.cache; | ||
if ( data instanceof Float32Array && cache.length !== data.length ) { | ||
this.cache = new Float32Array( data.length ); | ||
} | ||
copyArray( cache, data ); | ||
}; | ||
function StructuredUniform( id ) { | ||
@@ -854,0 +840,0 @@ |
@@ -62,4 +62,5 @@ import { WebGLRenderTarget } from './WebGLRenderTarget.js'; | ||
this.stencilBuffer = source.stencilBuffer; | ||
this.depthTexture = source.depthTexture; | ||
if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); | ||
this.texture.length = 0; | ||
@@ -70,2 +71,3 @@ | ||
this.texture[ i ] = source.texture[ i ].clone(); | ||
this.texture[ i ].isRenderTargetTexture = true; | ||
@@ -72,0 +74,0 @@ } |
@@ -72,3 +72,3 @@ import { | ||
if ( parameters.context !== undefined ) { | ||
if ( _context !== null ) { | ||
@@ -1205,3 +1205,3 @@ _alpha = _context.getContextAttributes().alpha; | ||
generateMipmaps: true, | ||
type: utils.convert( HalfFloatType ) !== null ? HalfFloatType : UnsignedByteType, | ||
type: extensions.has( 'EXT_color_buffer_half_float' ) ? HalfFloatType : UnsignedByteType, | ||
minFilter: LinearMipmapLinearFilter, | ||
@@ -1508,3 +1508,3 @@ samples: ( isWebGL2 && _antialias === true ) ? 4 : 0 | ||
} else if ( material.fog && materialProperties.fog !== fog ) { | ||
} else if ( material.fog === true && materialProperties.fog !== fog ) { | ||
@@ -1681,3 +1681,3 @@ needsProgramChange = true; | ||
p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); | ||
console.warn( 'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' ); | ||
@@ -1727,3 +1727,3 @@ } | ||
if ( fog && material.fog ) { | ||
if ( fog && material.fog === true ) { | ||
@@ -1730,0 +1730,0 @@ materials.refreshFogUniforms( m_uniforms, fog ); |
@@ -33,2 +33,3 @@ import { ArrayCamera } from '../../cameras/ArrayCamera.js'; | ||
let referenceSpaceType = 'local-floor'; | ||
let customReferenceSpace = null; | ||
@@ -191,6 +192,12 @@ let pose = null; | ||
return referenceSpace; | ||
return customReferenceSpace || referenceSpace; | ||
}; | ||
this.setReferenceSpace = function ( space ) { | ||
customReferenceSpace = space; | ||
}; | ||
this.getBaseLayer = function () { | ||
@@ -332,7 +339,8 @@ | ||
// Assign inputSources to available controllers | ||
// Assign controllers to available inputSources | ||
for ( let i = 0; i < controllers.length; i ++ ) { | ||
for ( let i = 0; i < inputSources.length; i ++ ) { | ||
inputSourcesMap.set( inputSources[ i ], controllers[ i ] ); | ||
const index = inputSources[ i ].handedness === 'right' ? 1 : 0; | ||
inputSourcesMap.set( inputSources[ i ], controllers[ index ] ); | ||
@@ -565,3 +573,3 @@ } | ||
pose = frame.getViewerPose( referenceSpace ); | ||
pose = frame.getViewerPose( customReferenceSpace || referenceSpace ); | ||
xrFrame = frame; | ||
@@ -648,7 +656,11 @@ | ||
const controller = controllers[ i ]; | ||
const inputSource = inputSources[ i ]; | ||
const controller = inputSourcesMap.get( inputSource ); | ||
controller.update( inputSource, frame, referenceSpace ); | ||
if ( controller !== undefined ) { | ||
controller.update( inputSource, frame, customReferenceSpace || referenceSpace ); | ||
} | ||
} | ||
@@ -655,0 +667,0 @@ |
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
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
33068294
1131
422819
26