super-three
Advanced tools
Comparing version 0.163.0 to 0.164.0
@@ -216,7 +216,8 @@ import { | ||
* | ||
* @param {number} sphereSize | ||
* @return {CCDIKHelper} | ||
*/ | ||
createHelper() { | ||
createHelper( sphereSize ) { | ||
return new CCDIKHelper( this.mesh, this.iks ); | ||
return new CCDIKHelper( this.mesh, this.iks, sphereSize ); | ||
@@ -284,2 +285,3 @@ } | ||
* @param {Array<Object>} iks | ||
* @param {number} sphereSize | ||
*/ | ||
@@ -286,0 +288,0 @@ class CCDIKHelper extends Object3D { |
@@ -15,4 +15,10 @@ import { | ||
async parse( scene, options = {} ) { | ||
parse( scene, onDone, onError, options ) { | ||
this.parseAsync( scene, options ).then( onDone ).catch( onError ); | ||
} | ||
async parseAsync( scene, options = {} ) { | ||
options = Object.assign( { | ||
@@ -19,0 +25,0 @@ ar: { |
@@ -20,6 +20,6 @@ # Draco 3D Data Compression | ||
Either variation may be used with `THREE.DRACOLoader`: | ||
Either variation may be used with `DRACOLoader`: | ||
```js | ||
var dracoLoader = new THREE.DRACOLoader(); | ||
var dracoLoader = new DRACOLoader(); | ||
dracoLoader.setDecoderPath('path/to/decoders/'); | ||
@@ -26,0 +26,0 @@ dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support. |
@@ -1272,3 +1272,3 @@ import { | ||
const outBuffer = new Uint16Array( info.width * info.scanlineBlockSize * ( info.channels * info.type ) ); | ||
const outBuffer = new Uint16Array( info.columns * info.lines * ( info.inputChannels.length * info.type ) ); | ||
const bitmap = new Uint8Array( BITMAP_SIZE ); | ||
@@ -1278,4 +1278,4 @@ | ||
let outBufferEnd = 0; | ||
const pizChannelData = new Array( info.channels ); | ||
for ( let i = 0; i < info.channels; i ++ ) { | ||
const pizChannelData = new Array( info.inputChannels.length ); | ||
for ( let i = 0, il = info.inputChannels.length; i < il; i ++ ) { | ||
@@ -1285,3 +1285,3 @@ pizChannelData[ i ] = {}; | ||
pizChannelData[ i ][ 'end' ] = pizChannelData[ i ][ 'start' ]; | ||
pizChannelData[ i ][ 'nx' ] = info.width; | ||
pizChannelData[ i ][ 'nx' ] = info.columns; | ||
pizChannelData[ i ][ 'ny' ] = info.lines; | ||
@@ -1325,3 +1325,3 @@ pizChannelData[ i ][ 'size' ] = info.type; | ||
// Wavelet decoding | ||
for ( let i = 0; i < info.channels; ++ i ) { | ||
for ( let i = 0; i < info.inputChannels.length; ++ i ) { | ||
@@ -1354,3 +1354,3 @@ const cd = pizChannelData[ i ]; | ||
for ( let c = 0; c < info.channels; c ++ ) { | ||
for ( let c = 0; c < info.inputChannels.length; c ++ ) { | ||
@@ -1380,4 +1380,5 @@ const cd = pizChannelData[ c ]; | ||
const sz = info.lines * info.channels * info.width; | ||
const tmpBuffer = ( info.type == 1 ) ? new Uint16Array( sz ) : new Uint32Array( sz ); | ||
const byteSize = info.inputChannels.length * info.lines * info.columns * info.totalBytes; | ||
const tmpBuffer = new ArrayBuffer( byteSize ); | ||
const viewer = new DataView( tmpBuffer ); | ||
@@ -1390,7 +1391,8 @@ let tmpBufferEnd = 0; | ||
for ( let c = 0; c < info.channels; c ++ ) { | ||
for ( let c = 0; c < info.inputChannels.length; c ++ ) { | ||
let pixel = 0; | ||
switch ( info.type ) { | ||
const type = info.inputChannels[ c ].pixelType; | ||
switch ( type ) { | ||
@@ -1400,6 +1402,6 @@ case 1: | ||
ptr[ 0 ] = tmpBufferEnd; | ||
ptr[ 1 ] = ptr[ 0 ] + info.width; | ||
tmpBufferEnd = ptr[ 1 ] + info.width; | ||
ptr[ 1 ] = ptr[ 0 ] + info.columns; | ||
tmpBufferEnd = ptr[ 1 ] + info.columns; | ||
for ( let j = 0; j < info.width; ++ j ) { | ||
for ( let j = 0; j < info.columns; ++ j ) { | ||
@@ -1410,4 +1412,4 @@ const diff = ( rawBuffer[ ptr[ 0 ] ++ ] << 8 ) | rawBuffer[ ptr[ 1 ] ++ ]; | ||
tmpBuffer[ writePtr ] = pixel; | ||
writePtr ++; | ||
viewer.setUint16( writePtr, pixel, true ); | ||
writePtr += 2; | ||
@@ -1421,7 +1423,7 @@ } | ||
ptr[ 0 ] = tmpBufferEnd; | ||
ptr[ 1 ] = ptr[ 0 ] + info.width; | ||
ptr[ 2 ] = ptr[ 1 ] + info.width; | ||
tmpBufferEnd = ptr[ 2 ] + info.width; | ||
ptr[ 1 ] = ptr[ 0 ] + info.columns; | ||
ptr[ 2 ] = ptr[ 1 ] + info.columns; | ||
tmpBufferEnd = ptr[ 2 ] + info.columns; | ||
for ( let j = 0; j < info.width; ++ j ) { | ||
for ( let j = 0; j < info.columns; ++ j ) { | ||
@@ -1432,4 +1434,4 @@ const diff = ( rawBuffer[ ptr[ 0 ] ++ ] << 24 ) | ( rawBuffer[ ptr[ 1 ] ++ ] << 16 ) | ( rawBuffer[ ptr[ 2 ] ++ ] << 8 ); | ||
tmpBuffer[ writePtr ] = pixel; | ||
writePtr ++; | ||
viewer.setUint32( writePtr, pixel, true ); | ||
writePtr += 4; | ||
@@ -1446,3 +1448,3 @@ } | ||
return new DataView( tmpBuffer.buffer ); | ||
return viewer; | ||
@@ -1455,3 +1457,3 @@ } | ||
const inOffset = { value: info.offset.value }; | ||
const outBuffer = new Uint8Array( info.width * info.lines * ( info.channels * info.type * INT16_SIZE ) ); | ||
const outBuffer = new Uint8Array( info.columns * info.lines * ( info.inputChannels.length * info.type * INT16_SIZE ) ); | ||
@@ -1504,5 +1506,5 @@ // Read compression header information | ||
const channels = EXRHeader.channels; | ||
const channelData = new Array( info.channels ); | ||
const channelData = new Array( info.inputChannels.length ); | ||
for ( let i = 0; i < info.channels; ++ i ) { | ||
for ( let i = 0; i < info.inputChannels.length; ++ i ) { | ||
@@ -1517,3 +1519,3 @@ const cd = channelData[ i ] = {}; | ||
cd.pLinear = channel.pLinear; | ||
cd.width = info.width; | ||
cd.width = info.columns; | ||
cd.height = info.lines; | ||
@@ -1527,3 +1529,3 @@ | ||
for ( let offset = 0; offset < info.channels; ++ offset ) { | ||
for ( let offset = 0; offset < info.inputChannels.length; ++ offset ) { | ||
@@ -1918,3 +1920,4 @@ const cd = channelData[ offset ]; | ||
'INCREASING_Y', | ||
'DECREASING_Y' | ||
'DECREASING_Y', | ||
'RANDOM_Y', | ||
]; | ||
@@ -1928,2 +1931,41 @@ | ||
function parseEnvmap( dataView, offset ) { | ||
const envmaps = [ | ||
'ENVMAP_LATLONG', | ||
'ENVMAP_CUBE' | ||
]; | ||
const envmap = parseUint8( dataView, offset ); | ||
return envmaps[ envmap ]; | ||
} | ||
function parseTiledesc( dataView, offset ) { | ||
const levelModes = [ | ||
'ONE_LEVEL', | ||
'MIPMAP_LEVELS', | ||
'RIPMAP_LEVELS', | ||
]; | ||
const roundingModes = [ | ||
'ROUND_DOWN', | ||
'ROUND_UP', | ||
]; | ||
const xSize = parseUint32( dataView, offset ); | ||
const ySize = parseUint32( dataView, offset ); | ||
const modes = parseUint8( dataView, offset ); | ||
return { | ||
xSize: xSize, | ||
ySize: ySize, | ||
levelMode: levelModes[ modes & 0xf ], | ||
roundingMode: roundingModes[ modes >> 4 ] | ||
}; | ||
} | ||
function parseV2f( dataView, offset ) { | ||
@@ -1970,2 +2012,10 @@ | ||
} else if ( type === 'envmap' ) { | ||
return parseEnvmap( dataView, offset ); | ||
} else if ( type === 'tiledesc' ) { | ||
return parseTiledesc( dataView, offset ); | ||
} else if ( type === 'lineOrder' ) { | ||
@@ -2013,2 +2063,159 @@ | ||
function roundLog2( x, mode ) { | ||
const log2 = Math.log2( x ); | ||
return mode == 'ROUND_DOWN' ? Math.floor( log2 ) : Math.ceil( log2 ); | ||
} | ||
function calculateTileLevels( tiledesc, w, h ) { | ||
let num = 0; | ||
switch ( tiledesc.levelMode ) { | ||
case 'ONE_LEVEL': | ||
num = 1; | ||
break; | ||
case 'MIPMAP_LEVELS': | ||
num = roundLog2( Math.max( w, h ), tiledesc.roundingMode ) + 1; | ||
break; | ||
case 'RIPMAP_LEVELS': | ||
throw new Error( 'THREE.EXRLoader: RIPMAP_LEVELS tiles currently unsupported.' ); | ||
} | ||
return num; | ||
} | ||
function calculateTiles( count, dataSize, size, roundingMode ) { | ||
const tiles = new Array( count ); | ||
for ( let i = 0; i < count; i ++ ) { | ||
const b = ( 1 << i ); | ||
let s = ( dataSize / b ) | 0; | ||
if ( roundingMode == 'ROUND_UP' && s * b < dataSize ) s += 1; | ||
const l = Math.max( s, 1 ); | ||
tiles[ i ] = ( ( l + size - 1 ) / size ) | 0; | ||
} | ||
return tiles; | ||
} | ||
function parseTiles() { | ||
const EXRDecoder = this; | ||
const offset = EXRDecoder.offset; | ||
const tmpOffset = { value: 0 }; | ||
for ( let tile = 0; tile < EXRDecoder.tileCount; tile ++ ) { | ||
const tileX = parseInt32( EXRDecoder.viewer, offset ); | ||
const tileY = parseInt32( EXRDecoder.viewer, offset ); | ||
offset.value += 8; // skip levels - only parsing top-level | ||
EXRDecoder.size = parseUint32( EXRDecoder.viewer, offset ); | ||
const startX = tileX * EXRDecoder.blockWidth; | ||
const startY = tileY * EXRDecoder.blockHeight; | ||
EXRDecoder.columns = ( startX + EXRDecoder.blockWidth > EXRDecoder.width ) ? EXRDecoder.width - startX : EXRDecoder.blockWidth; | ||
EXRDecoder.lines = ( startY + EXRDecoder.blockHeight > EXRDecoder.height ) ? EXRDecoder.height - startY : EXRDecoder.blockHeight; | ||
const bytesBlockLine = EXRDecoder.columns * EXRDecoder.totalBytes; | ||
const isCompressed = EXRDecoder.size < EXRDecoder.lines * bytesBlockLine; | ||
const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); | ||
offset.value += EXRDecoder.size; | ||
for ( let line = 0; line < EXRDecoder.lines; line ++ ) { | ||
const lineOffset = line * EXRDecoder.columns * EXRDecoder.totalBytes; | ||
for ( let channelID = 0; channelID < EXRDecoder.inputChannels.length; channelID ++ ) { | ||
const name = EXRHeader.channels[ channelID ].name; | ||
const lOff = EXRDecoder.channelByteOffsets[ name ] * EXRDecoder.columns; | ||
const cOff = EXRDecoder.decodeChannels[ name ]; | ||
if ( cOff === undefined ) continue; | ||
tmpOffset.value = lineOffset + lOff; | ||
const outLineOffset = ( EXRDecoder.height - ( 1 + startY + line ) ) * EXRDecoder.outLineWidth; | ||
for ( let x = 0; x < EXRDecoder.columns; x ++ ) { | ||
const outIndex = outLineOffset + ( x + startX ) * EXRDecoder.outputChannels + cOff; | ||
EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset ); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
function parseScanline() { | ||
const EXRDecoder = this; | ||
const offset = EXRDecoder.offset; | ||
const tmpOffset = { value: 0 }; | ||
for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.blockHeight; scanlineBlockIdx ++ ) { | ||
const line = parseInt32( EXRDecoder.viewer, offset ) - EXRHeader.dataWindow.yMin; // line_no | ||
EXRDecoder.size = parseUint32( EXRDecoder.viewer, offset ); // data_len | ||
EXRDecoder.lines = ( ( line + EXRDecoder.blockHeight > EXRDecoder.height ) ? ( EXRDecoder.height - line ) : EXRDecoder.blockHeight ); | ||
const bytesPerLine = EXRDecoder.columns * EXRDecoder.totalBytes; | ||
const isCompressed = EXRDecoder.size < EXRDecoder.lines * bytesPerLine; | ||
const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); | ||
offset.value += EXRDecoder.size; | ||
for ( let line_y = 0; line_y < EXRDecoder.blockHeight; line_y ++ ) { | ||
const scan_y = scanlineBlockIdx * EXRDecoder.blockHeight; | ||
const true_y = line_y + EXRDecoder.scanOrder( scan_y ); | ||
if ( true_y >= EXRDecoder.height ) continue; | ||
const lineOffset = line_y * bytesPerLine; | ||
const outLineOffset = ( EXRDecoder.height - 1 - true_y ) * EXRDecoder.outLineWidth; | ||
for ( let channelID = 0; channelID < EXRDecoder.inputChannels.length; channelID ++ ) { | ||
const name = EXRHeader.channels[ channelID ].name; | ||
const lOff = EXRDecoder.channelByteOffsets[ name ] * EXRDecoder.columns; | ||
const cOff = EXRDecoder.decodeChannels[ name ]; | ||
if ( cOff === undefined ) continue; | ||
tmpOffset.value = lineOffset + lOff; | ||
for ( let x = 0; x < EXRDecoder.columns; x ++ ) { | ||
const outIndex = outLineOffset + x * EXRDecoder.outputChannels + cOff; | ||
EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset ); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
function parseHeader( dataView, buffer, offset ) { | ||
@@ -2069,3 +2276,3 @@ | ||
if ( ( spec & ~ 0x04 ) != 0 ) { // unsupported tiled, deep-image, multi-part | ||
if ( ( spec & ~ 0x06 ) != 0 ) { // unsupported deep-image, multi-part | ||
@@ -2090,8 +2297,8 @@ console.error( 'THREE.EXRHeader:', EXRHeader ); | ||
height: EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1, | ||
channels: EXRHeader.channels.length, | ||
channelLineOffsets: {}, | ||
inputChannels: EXRHeader.channels, | ||
channelByteOffsets: {}, | ||
scanOrder: null, | ||
bytesPerLine: null, | ||
totalBytes: null, | ||
columns: null, | ||
lines: null, | ||
inputSize: null, | ||
type: null, | ||
@@ -2107,3 +2314,3 @@ uncompress: null, | ||
case 'NO_COMPRESSION': | ||
EXRDecoder.lines = 1; | ||
EXRDecoder.blockHeight = 1; | ||
EXRDecoder.uncompress = uncompressRAW; | ||
@@ -2113,3 +2320,3 @@ break; | ||
case 'RLE_COMPRESSION': | ||
EXRDecoder.lines = 1; | ||
EXRDecoder.blockHeight = 1; | ||
EXRDecoder.uncompress = uncompressRLE; | ||
@@ -2119,3 +2326,3 @@ break; | ||
case 'ZIPS_COMPRESSION': | ||
EXRDecoder.lines = 1; | ||
EXRDecoder.blockHeight = 1; | ||
EXRDecoder.uncompress = uncompressZIP; | ||
@@ -2125,3 +2332,3 @@ break; | ||
case 'ZIP_COMPRESSION': | ||
EXRDecoder.lines = 16; | ||
EXRDecoder.blockHeight = 16; | ||
EXRDecoder.uncompress = uncompressZIP; | ||
@@ -2131,3 +2338,3 @@ break; | ||
case 'PIZ_COMPRESSION': | ||
EXRDecoder.lines = 32; | ||
EXRDecoder.blockHeight = 32; | ||
EXRDecoder.uncompress = uncompressPIZ; | ||
@@ -2137,3 +2344,3 @@ break; | ||
case 'PXR24_COMPRESSION': | ||
EXRDecoder.lines = 16; | ||
EXRDecoder.blockHeight = 16; | ||
EXRDecoder.uncompress = uncompressPXR; | ||
@@ -2143,3 +2350,3 @@ break; | ||
case 'DWAA_COMPRESSION': | ||
EXRDecoder.lines = 32; | ||
EXRDecoder.blockHeight = 32; | ||
EXRDecoder.uncompress = uncompressDWA; | ||
@@ -2149,3 +2356,3 @@ break; | ||
case 'DWAB_COMPRESSION': | ||
EXRDecoder.lines = 256; | ||
EXRDecoder.blockHeight = 256; | ||
EXRDecoder.uncompress = uncompressDWA; | ||
@@ -2159,4 +2366,2 @@ break; | ||
EXRDecoder.scanlineBlockSize = EXRDecoder.lines; | ||
const channels = {}; | ||
@@ -2206,3 +2411,2 @@ for ( const channel of EXRHeader.channels ) { | ||
EXRDecoder.getter = parseFloat16; | ||
EXRDecoder.inputSize = INT16_SIZE; | ||
break; | ||
@@ -2212,3 +2416,2 @@ | ||
EXRDecoder.getter = parseUint16; | ||
EXRDecoder.inputSize = INT16_SIZE; | ||
break; | ||
@@ -2225,3 +2428,2 @@ | ||
EXRDecoder.getter = parseFloat32; | ||
EXRDecoder.inputSize = FLOAT32_SIZE; | ||
break; | ||
@@ -2231,3 +2433,2 @@ | ||
EXRDecoder.getter = decodeFloat32; | ||
EXRDecoder.inputSize = FLOAT32_SIZE; | ||
@@ -2242,9 +2443,3 @@ } | ||
EXRDecoder.blockCount = EXRDecoder.height / EXRDecoder.scanlineBlockSize; | ||
for ( let i = 0; i < EXRDecoder.blockCount; i ++ ) | ||
parseInt64( dataView, offset ); // scanlineOffset | ||
// we should be passed the scanline offset table, ready to start reading pixel data. | ||
EXRDecoder.columns = EXRDecoder.width; | ||
const size = EXRDecoder.width * EXRDecoder.height * EXRDecoder.outputChannels; | ||
@@ -2282,3 +2477,3 @@ | ||
EXRDecoder.channelLineOffsets[ channel.name ] = byteOffset * EXRDecoder.width; | ||
EXRDecoder.channelByteOffsets[ channel.name ] = byteOffset; | ||
@@ -2291,3 +2486,3 @@ } | ||
EXRDecoder.bytesPerLine = EXRDecoder.width * byteOffset; | ||
EXRDecoder.totalBytes = byteOffset; | ||
EXRDecoder.outLineWidth = EXRDecoder.width * EXRDecoder.outputChannels; | ||
@@ -2317,63 +2512,52 @@ | ||
return EXRDecoder; | ||
if ( EXRHeader.spec.singleTile ) { | ||
} | ||
EXRDecoder.blockHeight = EXRHeader.tiles.ySize; | ||
EXRDecoder.blockWidth = EXRHeader.tiles.xSize; | ||
// start parsing file [START] | ||
const numXLevels = calculateTileLevels( EXRHeader.tiles, EXRDecoder.width, EXRDecoder.height ); | ||
// const numYLevels = calculateTileLevels( EXRHeader.tiles, EXRDecoder.width, EXRDecoder.height ); | ||
const bufferDataView = new DataView( buffer ); | ||
const uInt8Array = new Uint8Array( buffer ); | ||
const offset = { value: 0 }; | ||
const numXTiles = calculateTiles( numXLevels, EXRDecoder.width, EXRHeader.tiles.xSize, EXRHeader.tiles.roundingMode ); | ||
const numYTiles = calculateTiles( numXLevels, EXRDecoder.height, EXRHeader.tiles.ySize, EXRHeader.tiles.roundingMode ); | ||
// get header information and validate format. | ||
const EXRHeader = parseHeader( bufferDataView, buffer, offset ); | ||
EXRDecoder.tileCount = numXTiles[ 0 ] * numYTiles[ 0 ]; | ||
// get input compression information and prepare decoding. | ||
const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type ); | ||
for ( let l = 0; l < numXLevels; l ++ ) | ||
for ( let y = 0; y < numYTiles[ l ]; y ++ ) | ||
for ( let x = 0; x < numXTiles[ l ]; x ++ ) | ||
parseInt64( dataView, offset ); // tileOffset | ||
const tmpOffset = { value: 0 }; | ||
EXRDecoder.decode = parseTiles.bind( EXRDecoder ); | ||
for ( let scanlineBlockIdx = 0; scanlineBlockIdx < EXRDecoder.height / EXRDecoder.scanlineBlockSize; scanlineBlockIdx ++ ) { | ||
} else { | ||
const line = parseInt32( bufferDataView, offset ) - EXRHeader.dataWindow.yMin; // line_no | ||
EXRDecoder.size = parseUint32( bufferDataView, offset ); // data_len | ||
EXRDecoder.lines = ( ( line + EXRDecoder.scanlineBlockSize > EXRDecoder.height ) ? ( EXRDecoder.height - line ) : EXRDecoder.scanlineBlockSize ); | ||
EXRDecoder.blockWidth = EXRDecoder.width; | ||
const blockCount = Math.ceil( EXRDecoder.height / EXRDecoder.blockHeight ); | ||
const isCompressed = EXRDecoder.size < EXRDecoder.lines * EXRDecoder.bytesPerLine; | ||
const viewer = isCompressed ? EXRDecoder.uncompress( EXRDecoder ) : uncompressRAW( EXRDecoder ); | ||
for ( let i = 0; i < blockCount; i ++ ) | ||
parseInt64( dataView, offset ); // scanlineOffset | ||
offset.value += EXRDecoder.size; | ||
EXRDecoder.decode = parseScanline.bind( EXRDecoder ); | ||
for ( let line_y = 0; line_y < EXRDecoder.scanlineBlockSize; line_y ++ ) { | ||
} | ||
const scan_y = scanlineBlockIdx * EXRDecoder.scanlineBlockSize; | ||
const true_y = line_y + EXRDecoder.scanOrder( scan_y ); | ||
if ( true_y >= EXRDecoder.height ) continue; | ||
return EXRDecoder; | ||
const lineOffset = line_y * EXRDecoder.bytesPerLine; | ||
const outLineOffset = ( EXRDecoder.height - 1 - true_y ) * EXRDecoder.outLineWidth; | ||
} | ||
for ( let channelID = 0; channelID < EXRDecoder.channels; channelID ++ ) { | ||
// start parsing file [START] | ||
const offset = { value: 0 }; | ||
const bufferDataView = new DataView( buffer ); | ||
const uInt8Array = new Uint8Array( buffer ); | ||
const name = EXRHeader.channels[ channelID ].name; | ||
const lOff = EXRDecoder.channelLineOffsets[ name ]; | ||
const cOff = EXRDecoder.decodeChannels[ name ]; | ||
// get header information and validate format. | ||
const EXRHeader = parseHeader( bufferDataView, buffer, offset ); | ||
if ( cOff === undefined ) continue; | ||
// get input compression information and prepare decoding. | ||
const EXRDecoder = setupDecoder( EXRHeader, bufferDataView, uInt8Array, offset, this.type ); | ||
tmpOffset.value = lineOffset + lOff; | ||
// parse input data | ||
EXRDecoder.decode(); | ||
for ( let x = 0; x < EXRDecoder.width; x ++ ) { | ||
const outIndex = outLineOffset + x * EXRDecoder.outputChannels + cOff; | ||
EXRDecoder.byteArray[ outIndex ] = EXRDecoder.getter( viewer, tmpOffset ); | ||
} | ||
} | ||
} | ||
} | ||
return { | ||
@@ -2380,0 +2564,0 @@ header: EXRHeader, |
@@ -34,3 +34,2 @@ /** | ||
RGB_PVRTC_4BPPV1_Format, | ||
RGB_S3TC_DXT1_Format, | ||
RGBA_ASTC_4x4_Format, | ||
@@ -42,2 +41,3 @@ RGBA_ASTC_6x6_Format, | ||
RGBA_S3TC_DXT5_Format, | ||
RGBA_S3TC_DXT1_Format, | ||
RGBAFormat, | ||
@@ -165,5 +165,2 @@ RGFormat, | ||
// https://github.com/mrdoob/three.js/pull/22928 | ||
this.workerConfig.etc1Supported = false; | ||
} | ||
@@ -393,3 +390,3 @@ | ||
RGB_PVRTC_4BPPV1_Format: RGB_PVRTC_4BPPV1_Format, | ||
RGB_S3TC_DXT1_Format: RGB_S3TC_DXT1_Format, | ||
RGBA_S3TC_DXT1_Format: RGBA_S3TC_DXT1_Format, | ||
}; | ||
@@ -610,3 +607,3 @@ | ||
transcoderFormat: [ TranscoderFormat.BC1, TranscoderFormat.BC3 ], | ||
engineFormat: [ EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format ], | ||
engineFormat: [ EngineFormat.RGBA_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format ], | ||
priorityETC1S: 4, | ||
@@ -613,0 +610,0 @@ priorityUASTC: 5, |
@@ -654,6 +654,9 @@ /** | ||
var number = this.reader.getUint16(); | ||
var flags = this.reader.getUint16(); // If the least significant bit of flags is set, the layer is hidden. | ||
var pivot = this.reader.getFloat32Array( 3 ); // Note: this seems to be superflous, as the geometry is translated when pivot is present | ||
var layer = { | ||
number: this.reader.getUint16(), | ||
flags: this.reader.getUint16(), // If the least significant bit of flags is set, the layer is hidden. | ||
pivot: this.reader.getFloat32Array( 3 ), // Note: this seems to be superflous, as the geometry is translated when pivot is present | ||
number: number, | ||
flags: flags, // If the least significant bit of flags is set, the layer is hidden. | ||
pivot: [ - pivot[ 0 ], pivot[ 1 ], pivot[ 2 ] ], // Note: this seems to be superflous, as the geometry is translated when pivot is present | ||
name: this.reader.getString(), | ||
@@ -680,4 +683,4 @@ }; | ||
// z -> -z to match three.js right handed coords | ||
this.currentPoints.push( this.reader.getFloat32(), this.reader.getFloat32(), - this.reader.getFloat32() ); | ||
// x -> -x to match three.js right handed coords | ||
this.currentPoints.push( - this.reader.getFloat32(), this.reader.getFloat32(), this.reader.getFloat32() ); | ||
@@ -684,0 +687,0 @@ } |
@@ -273,4 +273,10 @@ /** | ||
#include <lightmap_fragment> | ||
#ifdef USE_LIGHTMAP | ||
vec4 lightMapTexel = texture2D( lightMap, vLightMapUv ); | ||
vec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity; | ||
reflectedLight.indirectDiffuse += lightMapIrradiance; | ||
#endif | ||
reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb ); | ||
@@ -277,0 +283,0 @@ |
@@ -7,3 +7,4 @@ import { | ||
Triangle, | ||
Vector3 | ||
Vector3, | ||
Layers | ||
} from 'three'; | ||
@@ -93,2 +94,3 @@ import { Capsule } from '../math/Capsule.js'; | ||
this.triangles = []; | ||
this.layers = new Layers(); | ||
@@ -483,35 +485,39 @@ } | ||
let geometry, isTemp = false; | ||
if ( this.layers.test( obj.layers ) ) { | ||
if ( obj.geometry.index !== null ) { | ||
let geometry, isTemp = false; | ||
isTemp = true; | ||
geometry = obj.geometry.toNonIndexed(); | ||
if ( obj.geometry.index !== null ) { | ||
} else { | ||
isTemp = true; | ||
geometry = obj.geometry.toNonIndexed(); | ||
geometry = obj.geometry; | ||
} else { | ||
} | ||
geometry = obj.geometry; | ||
const positionAttribute = geometry.getAttribute( 'position' ); | ||
} | ||
for ( let i = 0; i < positionAttribute.count; i += 3 ) { | ||
const positionAttribute = geometry.getAttribute( 'position' ); | ||
const v1 = new Vector3().fromBufferAttribute( positionAttribute, i ); | ||
const v2 = new Vector3().fromBufferAttribute( positionAttribute, i + 1 ); | ||
const v3 = new Vector3().fromBufferAttribute( positionAttribute, i + 2 ); | ||
for ( let i = 0; i < positionAttribute.count; i += 3 ) { | ||
v1.applyMatrix4( obj.matrixWorld ); | ||
v2.applyMatrix4( obj.matrixWorld ); | ||
v3.applyMatrix4( obj.matrixWorld ); | ||
const v1 = new Vector3().fromBufferAttribute( positionAttribute, i ); | ||
const v2 = new Vector3().fromBufferAttribute( positionAttribute, i + 1 ); | ||
const v3 = new Vector3().fromBufferAttribute( positionAttribute, i + 2 ); | ||
this.addTriangle( new Triangle( v1, v2, v3 ) ); | ||
v1.applyMatrix4( obj.matrixWorld ); | ||
v2.applyMatrix4( obj.matrixWorld ); | ||
v3.applyMatrix4( obj.matrixWorld ); | ||
} | ||
this.addTriangle( new Triangle( v1, v2, v3 ) ); | ||
if ( isTemp ) { | ||
} | ||
geometry.dispose(); | ||
if ( isTemp ) { | ||
geometry.dispose(); | ||
} | ||
} | ||
@@ -518,0 +524,0 @@ |
import { bitangentView } from './BitangentNode.js'; | ||
import { normalView } from './NormalNode.js'; | ||
import { normalView, transformedNormalView } from './NormalNode.js'; | ||
import { tangentView } from './TangentNode.js'; | ||
import { mat3 } from '../shadernode/ShaderNode.js'; | ||
import { mix } from '../math/MathNode.js'; | ||
import { anisotropy, anisotropyB, roughness } from '../core/PropertyNode.js'; | ||
import { positionViewDirection } from './PositionNode.js'; | ||
@@ -11,1 +13,14 @@ | ||
export const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) ); | ||
export const transformedBentNormalView = ( () => { | ||
// https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy | ||
let bentNormal = anisotropyB.cross( positionViewDirection ); | ||
bentNormal = bentNormal.cross( anisotropyB ).normalize(); | ||
bentNormal = mix( bentNormal, transformedNormalView, anisotropy.mul( roughness.oneMinus() ).oneMinus().pow2().pow2() ).normalize(); | ||
return bentNormal; | ||
} )(); |
@@ -8,3 +8,3 @@ | ||
import { loop } from '../utils/LoopNode.js'; | ||
import { smoothstep } from '../math/MathNode.js'; | ||
import { smoothstep } from '../math/MathNode.js'; | ||
import { uniforms } from './UniformsNode.js'; | ||
@@ -82,3 +82,3 @@ | ||
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); | ||
distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); | ||
distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); | ||
@@ -131,2 +131,3 @@ | ||
clipped.discard(); | ||
} | ||
@@ -133,0 +134,0 @@ |
@@ -5,3 +5,5 @@ import Node, { addNodeClass } from '../core/Node.js'; | ||
import { normalView } from './NormalNode.js'; | ||
import { nodeImmutable, float } from '../shadernode/ShaderNode.js'; | ||
import { nodeImmutable, float, vec2, mat2 } from '../shadernode/ShaderNode.js'; | ||
import { uniform } from '../core/UniformNode.js'; | ||
import { Vector2 } from 'three'; | ||
@@ -93,3 +95,3 @@ const _propertyCache = new Map(); | ||
node = this.getTexture( scope ).r; | ||
node = this.getTexture( 'specular' ).r; | ||
@@ -102,2 +104,30 @@ } else { | ||
} else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { | ||
const specularIntensity = this.getFloat( scope ); | ||
if ( material.specularMap ) { | ||
node = specularIntensity.mul( this.getTexture( scope ).a ); | ||
} else { | ||
node = specularIntensity; | ||
} | ||
} else if ( scope === MaterialNode.SPECULAR_COLOR ) { | ||
const specularColorNode = this.getColor( scope ); | ||
if ( material.specularColorMap && material.specularColorMap.isTexture === true ) { | ||
node = specularColorNode.mul( this.getTexture( scope ).rgb ); | ||
} else { | ||
node = specularColorNode; | ||
} | ||
} else if ( scope === MaterialNode.ROUGHNESS ) { // TODO: cleanup similar branches | ||
@@ -231,2 +261,17 @@ | ||
} else if ( scope === MaterialNode.ANISOTROPY ) { | ||
if ( material.anisotropyMap && material.anisotropyMap.isTexture === true ) { | ||
const anisotropyPolar = this.getTexture( scope ); | ||
const anisotropyMat = mat2( materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x ); | ||
node = anisotropyMat.mul( anisotropyPolar.rg.mul( 2.0 ).sub( vec2( 1.0 ) ).normalize().mul( anisotropyPolar.b ) ); | ||
} else { | ||
node = materialAnisotropyVector; | ||
} | ||
} else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) { | ||
@@ -248,2 +293,34 @@ | ||
} else if ( scope === MaterialNode.TRANSMISSION ) { | ||
const transmissionNode = this.getFloat( scope ); | ||
if ( material.transmissionMap ) { | ||
node = transmissionNode.mul( this.getTexture( scope ).r ); | ||
} else { | ||
node = transmissionNode; | ||
} | ||
} else if ( scope === MaterialNode.THICKNESS ) { | ||
const thicknessNode = this.getFloat( scope ); | ||
if ( material.thicknessMap ) { | ||
node = thicknessNode.mul( this.getTexture( scope ).g ); | ||
} else { | ||
node = thicknessNode; | ||
} | ||
} else if ( scope === MaterialNode.IOR ) { | ||
node = this.getFloat( scope ); | ||
} else { | ||
@@ -267,4 +344,6 @@ | ||
MaterialNode.SHININESS = 'shininess'; | ||
MaterialNode.SPECULAR_COLOR = 'specular'; | ||
MaterialNode.SPECULAR = 'specular'; | ||
MaterialNode.SPECULAR_STRENGTH = 'specularStrength'; | ||
MaterialNode.SPECULAR_INTENSITY = 'specularIntensity'; | ||
MaterialNode.SPECULAR_COLOR = 'specularColor'; | ||
MaterialNode.REFLECTIVITY = 'reflectivity'; | ||
@@ -281,5 +360,11 @@ MaterialNode.ROUGHNESS = 'roughness'; | ||
MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness'; | ||
MaterialNode.ANISOTROPY = 'anisotropy'; | ||
MaterialNode.IRIDESCENCE = 'iridescence'; | ||
MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR'; | ||
MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness'; | ||
MaterialNode.IOR = 'ior'; | ||
MaterialNode.TRANSMISSION = 'transmission'; | ||
MaterialNode.THICKNESS = 'thickness'; | ||
MaterialNode.ATTENUATION_DISTANCE = 'attenuationDistance'; | ||
MaterialNode.ATTENUATION_COLOR = 'attenuationColor'; | ||
MaterialNode.LINE_SCALE = 'scale'; | ||
@@ -299,3 +384,7 @@ MaterialNode.LINE_DASH_SIZE = 'dashSize'; | ||
export const materialOpacity = nodeImmutable( MaterialNode, MaterialNode.OPACITY ); | ||
export const materialSpecular = nodeImmutable( MaterialNode, MaterialNode.SPECULAR ); | ||
export const materialSpecularIntensity = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_INTENSITY ); | ||
export const materialSpecularColor = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); | ||
export const materialSpecularStrength = nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH ); | ||
@@ -312,5 +401,11 @@ export const materialReflectivity = nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY ); | ||
export const materialSheenRoughness = nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS ); | ||
export const materialAnisotropy = nodeImmutable( MaterialNode, MaterialNode.ANISOTROPY ); | ||
export const materialIridescence = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE ); | ||
export const materialIridescenceIOR = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR ); | ||
export const materialIridescenceThickness = nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS ); | ||
export const materialTransmission = nodeImmutable( MaterialNode, MaterialNode.TRANSMISSION ); | ||
export const materialThickness = nodeImmutable( MaterialNode, MaterialNode.THICKNESS ); | ||
export const materialIOR = nodeImmutable( MaterialNode, MaterialNode.IOR ); | ||
export const materialAttenuationDistance = nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_DISTANCE ); | ||
export const materialAttenuationColor = nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_COLOR ); | ||
export const materialLineScale = nodeImmutable( MaterialNode, MaterialNode.LINE_SCALE ); | ||
@@ -322,3 +417,12 @@ export const materialLineDashSize = nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_SIZE ); | ||
export const materialPointWidth = nodeImmutable( MaterialNode, MaterialNode.POINT_WIDTH ); | ||
export const materialAnisotropyVector = uniform( new Vector2() ).onReference( function ( frame ) { | ||
return frame.material; | ||
} ).onRenderUpdate( function ( { material } ) { | ||
this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); | ||
} ); | ||
addNodeClass( 'MaterialNode', MaterialNode ); |
@@ -21,2 +21,11 @@ import BufferNode from './BufferNode.js'; | ||
if ( value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true ) { | ||
// TOOD: Improve it, possibly adding a new property to the BufferAttribute to identify it as a storage buffer read-only attribute in Renderer | ||
if ( value.isInstancedBufferAttribute ) value.isStorageInstancedBufferAttribute = true; | ||
else value.isStorageBufferAttribute = true; | ||
} | ||
} | ||
@@ -23,0 +32,0 @@ |
@@ -23,2 +23,3 @@ import UniformNode, { uniform } from '../core/UniformNode.js'; | ||
this.depthNode = null; | ||
this.gradNode = null; | ||
@@ -159,2 +160,3 @@ this.sampler = true; | ||
properties.compareNode = this.compareNode; | ||
properties.gradNode = this.gradNode; | ||
properties.depthNode = this.depthNode; | ||
@@ -170,3 +172,3 @@ | ||
generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, depthSnippet, compareSnippet ) { | ||
generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, depthSnippet, compareSnippet, gradSnippet ) { | ||
@@ -181,2 +183,6 @@ const texture = this.value; | ||
} else if ( gradSnippet ) { | ||
snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet ); | ||
} else if ( compareSnippet ) { | ||
@@ -230,3 +236,3 @@ | ||
const { uvNode, levelNode, compareNode, depthNode } = properties; | ||
const { uvNode, levelNode, compareNode, depthNode, gradNode } = properties; | ||
@@ -237,2 +243,3 @@ const uvSnippet = this.generateUV( builder, uvNode ); | ||
const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null; | ||
const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null; | ||
@@ -243,3 +250,3 @@ const nodeVar = builder.getVarFromNode( this ); | ||
const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, depthSnippet, compareSnippet ); | ||
const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, depthSnippet, compareSnippet, gradSnippet ); | ||
@@ -334,2 +341,13 @@ builder.addLineFlowCode( `${propertyName} = ${snippet}` ); | ||
grad( gradNodeX, gradNodeY ) { | ||
const textureNode = this.clone(); | ||
textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ]; | ||
textureNode.referenceNode = this; | ||
return nodeObject( textureNode ); | ||
} | ||
depth( depthNode ) { | ||
@@ -336,0 +354,0 @@ |
@@ -23,3 +23,3 @@ import Node from '../core/Node.js'; | ||
return builder.format( `${builder.getMethod( 'textureDimensions' )}( ${textureProperty}, ${levelNode} )`, this.getNodeType( builder ), output ); | ||
return builder.format( `${ builder.getMethod( 'textureDimensions' ) }( ${ textureProperty }, ${ levelNode } )`, this.getNodeType( builder ), output ); | ||
@@ -26,0 +26,0 @@ } |
@@ -130,10 +130,2 @@ import CodeNode from './CodeNode.js'; | ||
export const func = ( code, includes ) => { // @deprecated, r154 | ||
console.warn( 'TSL: func() is deprecated. Use nativeFn(), wgslFn() or glslFn() instead.' ); | ||
return nodeObject( new FunctionNode( code, includes ) ); | ||
}; | ||
addNodeClass( 'FunctionNode', FunctionNode ); |
@@ -77,2 +77,10 @@ import { EventDispatcher } from 'three'; | ||
onReference( callback ) { | ||
this.updateReference = callback.bind( this.getSelf() ); | ||
return this; | ||
} | ||
getSelf() { | ||
@@ -79,0 +87,0 @@ |
@@ -75,3 +75,2 @@ import NodeUniform from './NodeUniform.js'; | ||
this.fogNode = null; | ||
this.toneMappingNode = null; | ||
@@ -1091,18 +1090,15 @@ this.clippingContext = null; | ||
build( convertMaterial = true ) { | ||
build() { | ||
const { object, material } = this; | ||
if ( convertMaterial ) { | ||
if ( material !== null ) { | ||
if ( material !== null ) { | ||
NodeMaterial.fromMaterial( material ).build( this ); | ||
NodeMaterial.fromMaterial( material ).build( this ); | ||
} else { | ||
} else { | ||
this.addFlow( 'compute', object ); | ||
this.addFlow( 'compute', object ); | ||
} | ||
} | ||
@@ -1109,0 +1105,0 @@ |
@@ -11,5 +11,6 @@ import Node, { addNodeClass } from './Node.js'; | ||
this.isOutputStructNode = true; | ||
this.members = members; | ||
this.isOutputStructNode = true; | ||
} | ||
@@ -16,0 +17,0 @@ |
@@ -65,3 +65,8 @@ import Node, { addNodeClass } from './Node.js'; | ||
export const iridescenceThickness = nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); | ||
export const alphaT = nodeImmutable( PropertyNode, 'float', 'AlphaT' ); | ||
export const anisotropy = nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); | ||
export const anisotropyT = nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); | ||
export const anisotropyB = nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); | ||
export const specularColor = nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); | ||
export const specularF90 = nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); | ||
export const shininess = nodeImmutable( PropertyNode, 'float', 'Shininess' ); | ||
@@ -72,3 +77,8 @@ export const output = nodeImmutable( PropertyNode, 'vec4', 'Output' ); | ||
export const pointWidth = nodeImmutable( PropertyNode, 'float', 'pointWidth' ); | ||
export const ior = nodeImmutable( PropertyNode, 'float', 'IOR' ); | ||
export const transmission = nodeImmutable( PropertyNode, 'float', 'Transmission' ); | ||
export const thickness = nodeImmutable( PropertyNode, 'float', 'Thickness' ); | ||
export const attenuationDistance = nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); | ||
export const attenuationColor = nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); | ||
addNodeClass( 'PropertyNode', PropertyNode ); |
@@ -12,33 +12,12 @@ import TempNode from '../core/TempNode.js'; | ||
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) | ||
const dHdxy_fwd = tslFn( ( { textureNode, bumpScale } ) => { | ||
let texNode = textureNode; | ||
// It's used to preserve the same TextureNode instance | ||
const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } ); | ||
if ( texNode.isTextureNode !== true ) { | ||
const Hll = float( sampleTexture( ( uvNode ) => uvNode ) ); | ||
texNode.traverse( ( node ) => { | ||
if ( node.isTextureNode === true ) texNode = node; | ||
} ); | ||
} | ||
if ( texNode.isTextureNode !== true ) { | ||
throw new Error( 'THREE.TSL: dHdxy_fwd() requires a TextureNode.' ); | ||
} | ||
const Hll = float( textureNode ); | ||
const uvNode = texNode.uvNode || uv(); | ||
// It's used to preserve the same TextureNode instance | ||
const sampleTexture = ( uv ) => textureNode.cache().context( { getUV: () => uv, forceUVContext: true } ); | ||
return vec2( | ||
float( sampleTexture( uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ), | ||
float( sampleTexture( uvNode.add( uvNode.dFdy() ) ) ).sub( Hll ) | ||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ), | ||
float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll ) | ||
).mul( bumpScale ); | ||
@@ -48,2 +27,4 @@ | ||
// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) | ||
const perturbNormalArb = tslFn( ( inputs ) => { | ||
@@ -50,0 +31,0 @@ |
import Node, { addNodeClass } from '../core/Node.js'; | ||
import { nodeImmutable, float } from '../shadernode/ShaderNode.js'; | ||
import { BackSide, WebGLCoordinateSystem } from 'three'; | ||
@@ -16,2 +17,14 @@ class FrontFacingNode extends Node { | ||
const { renderer, material } = builder; | ||
if ( renderer.coordinateSystem === WebGLCoordinateSystem ) { | ||
if ( material.side === BackSide ) { | ||
return 'false'; | ||
} | ||
} | ||
return builder.getFrontFacing(); | ||
@@ -18,0 +31,0 @@ |
@@ -78,3 +78,3 @@ import Node, { addNodeClass } from '../core/Node.js'; | ||
// -near maps to 0; -far maps to 1 | ||
export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( near.sub( far ).mul( viewZ ) ); | ||
export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) ); | ||
@@ -81,0 +81,0 @@ // maps perspective depth in [ 0, 1 ] to viewZ |
@@ -24,3 +24,5 @@ import Node, { addNodeClass } from '../core/Node.js'; | ||
return this.scope === ViewportNode.VIEWPORT ? 'vec4' : 'vec2'; | ||
if ( this.scope === ViewportNode.VIEWPORT ) return 'vec4'; | ||
else if ( this.scope === ViewportNode.COORDINATE ) return 'vec3'; | ||
else return 'vec2'; | ||
@@ -103,3 +105,3 @@ } | ||
coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ resolution }.y - ${ coord }.y )`; | ||
coord = `${ builder.getType( 'vec3' ) }( ${ coord }.x, ${ resolution }.y - ${ coord }.y, ${ coord }.z )`; | ||
@@ -106,0 +108,0 @@ } |
@@ -61,4 +61,7 @@ import TextureNode from '../accessors/TextureNode.js'; | ||
return new this.constructor( this.uvNode, this.levelNode, this.value ); | ||
const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value ); | ||
viewportTextureNode.generateMipmaps = this.generateMipmaps; | ||
return viewportTextureNode; | ||
} | ||
@@ -65,0 +68,0 @@ |
import F_Schlick from './F_Schlick.js'; | ||
import V_GGX_SmithCorrelated from './V_GGX_SmithCorrelated.js'; | ||
import V_GGX_SmithCorrelated_Anisotropic from './V_GGX_SmithCorrelated_Anisotropic.js'; | ||
import D_GGX from './D_GGX.js'; | ||
import D_GGX_Anisotropic from './D_GGX_Anisotropic.js'; | ||
import { transformedNormalView } from '../../accessors/NormalNode.js'; | ||
import { positionViewDirection } from '../../accessors/PositionNode.js'; | ||
import { iridescence } from '../../core/PropertyNode.js'; | ||
import { tslFn } from '../../shadernode/ShaderNode.js'; | ||
import { iridescence, alphaT, anisotropyT, anisotropyB } from '../../core/PropertyNode.js'; | ||
import { tslFn, defined } from '../../shadernode/ShaderNode.js'; | ||
@@ -12,3 +14,3 @@ // GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility | ||
const { lightDirection, f0, f90, roughness, iridescenceFresnel } = inputs; | ||
const { lightDirection, f0, f90, roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY } = inputs; | ||
@@ -27,12 +29,29 @@ const normalView = inputs.normalView || transformedNormalView; | ||
let F = F_Schlick( { f0, f90, dotVH } ); | ||
let V, D; | ||
if ( iridescenceFresnel ) { | ||
if ( defined( USE_IRIDESCENCE ) ) { | ||
F = iridescence.mix( F, iridescenceFresnel ); | ||
F = iridescence.mix( F, f ); | ||
} | ||
const V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } ); | ||
const D = D_GGX( { alpha, dotNH } ); | ||
if ( defined( USE_ANISOTROPY ) ) { | ||
const dotTL = anisotropyT.dot( lightDirection ); | ||
const dotTV = anisotropyT.dot( positionViewDirection ); | ||
const dotTH = anisotropyT.dot( halfDir ); | ||
const dotBL = anisotropyB.dot( lightDirection ); | ||
const dotBV = anisotropyB.dot( positionViewDirection ); | ||
const dotBH = anisotropyB.dot( halfDir ); | ||
V = V_GGX_SmithCorrelated_Anisotropic( { alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ); | ||
D = D_GGX_Anisotropic( { alphaT, alphaB: alpha, dotNH, dotTH, dotBH } ); | ||
} else { | ||
V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } ); | ||
D = D_GGX( { alpha, dotNH } ); | ||
} | ||
return F.mul( V ).mul( D ); | ||
@@ -39,0 +58,0 @@ |
@@ -7,6 +7,4 @@ import { div } from '../../math/OperatorNode.js'; | ||
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf | ||
const V_GGX_SmithCorrelated = tslFn( ( inputs ) => { | ||
const V_GGX_SmithCorrelated = tslFn( ( { alpha, dotNL, dotNV } ) => { | ||
const { alpha, dotNL, dotNV } = inputs; | ||
const a2 = alpha.pow2(); | ||
@@ -13,0 +11,0 @@ |
@@ -15,3 +15,3 @@ import LightingModel from '../core/LightingModel.js'; | ||
return shininess.mul( 0.5 / Math.PI ).add( 1.0 ).mul( dotNH.pow( shininess ) ); | ||
return shininess.mul( float( 0.5 ) ).add( 1.0 ).mul( float( 1 / Math.PI ) ).mul( dotNH.pow( shininess ) ); | ||
@@ -18,0 +18,0 @@ } ); |
@@ -9,10 +9,133 @@ import BRDF_Lambert from './BSDF/BRDF_Lambert.js'; | ||
import LightingModel from '../core/LightingModel.js'; | ||
import { diffuseColor, specularColor, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js'; | ||
import { transformedNormalView, transformedClearcoatNormalView } from '../accessors/NormalNode.js'; | ||
import { positionViewDirection } from '../accessors/PositionNode.js'; | ||
import { tslFn, float, vec3, mat3 } from '../shadernode/ShaderNode.js'; | ||
import { diffuseColor, specularColor, specularF90, roughness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, ior, thickness, transmission, attenuationDistance, attenuationColor } from '../core/PropertyNode.js'; | ||
import { transformedNormalView, transformedClearcoatNormalView, transformedNormalWorld } from '../accessors/NormalNode.js'; | ||
import { positionViewDirection, positionWorld } from '../accessors/PositionNode.js'; | ||
import { tslFn, float, vec2, vec3, vec4, mat3, If } from '../shadernode/ShaderNode.js'; | ||
import { cond } from '../math/CondNode.js'; | ||
import { mix, smoothstep } from '../math/MathNode.js'; | ||
import { mix, normalize, refract, length, clamp, log2, log, exp, smoothstep } from '../math/MathNode.js'; | ||
import { div } from '../math/OperatorNode.js'; | ||
import { cameraPosition, cameraProjectionMatrix, cameraViewMatrix } from '../accessors/CameraNode.js'; | ||
import { modelWorldMatrix } from '../accessors/ModelNode.js'; | ||
import { viewportResolution } from '../display/ViewportNode.js'; | ||
import { viewportMipTexture } from '../display/ViewportTextureNode.js'; | ||
// | ||
// Transmission | ||
// | ||
const getVolumeTransmissionRay = tslFn( ( [ n, v, thickness, ior, modelMatrix ] ) => { | ||
// Direction of refracted light. | ||
const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) ); | ||
// Compute rotation-independant scaling of the model matrix. | ||
const modelScale = vec3( | ||
length( modelMatrix[ 0 ].xyz ), | ||
length( modelMatrix[ 1 ].xyz ), | ||
length( modelMatrix[ 2 ].xyz ) | ||
); | ||
// The thickness is specified in local space. | ||
return normalize( refractionVector ).mul( thickness.mul( modelScale ) ); | ||
} ).setLayout( { | ||
name: 'getVolumeTransmissionRay', | ||
type: 'vec3', | ||
inputs: [ | ||
{ name: 'n', type: 'vec3' }, | ||
{ name: 'v', type: 'vec3' }, | ||
{ name: 'thickness', type: 'float' }, | ||
{ name: 'ior', type: 'float' }, | ||
{ name: 'modelMatrix', type: 'mat4' } | ||
] | ||
} ); | ||
const applyIorToRoughness = tslFn( ( [ roughness, ior ] ) => { | ||
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and | ||
// an IOR of 1.5 results in the default amount of microfacet refraction. | ||
return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) ); | ||
} ).setLayout( { | ||
name: 'applyIorToRoughness', | ||
type: 'float', | ||
inputs: [ | ||
{ name: 'roughness', type: 'float' }, | ||
{ name: 'ior', type: 'float' } | ||
] | ||
} ); | ||
const singleViewportMipTexture = viewportMipTexture(); | ||
const getTransmissionSample = tslFn( ( [ fragCoord, roughness, ior ] ) => { | ||
const transmissionSample = singleViewportMipTexture.uv( fragCoord ); | ||
//const transmissionSample = viewportMipTexture( fragCoord ); | ||
const lod = log2( float( viewportResolution.x ) ).mul( applyIorToRoughness( roughness, ior ) ); | ||
return transmissionSample.bicubic( lod ); | ||
} ); | ||
const volumeAttenuation = tslFn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => { | ||
If( attenuationDistance.notEqual( 0 ), () => { | ||
// Compute light attenuation using Beer's law. | ||
const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance ); | ||
const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) ); | ||
return transmittance; | ||
} ); | ||
// Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all. | ||
return vec3( 1.0 ); | ||
} ).setLayout( { | ||
name: 'volumeAttenuation', | ||
type: 'vec3', | ||
inputs: [ | ||
{ name: 'transmissionDistance', type: 'float' }, | ||
{ name: 'attenuationColor', type: 'vec3' }, | ||
{ name: 'attenuationDistance', type: 'float' } | ||
] | ||
} ); | ||
const getIBLVolumeRefraction = tslFn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance ] ) => { | ||
const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); | ||
const refractedRayExit = position.add( transmissionRay ); | ||
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates. | ||
const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); | ||
const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); | ||
refractionCoords.addAssign( 1.0 ); | ||
refractionCoords.divAssign( 2.0 ); | ||
refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu | ||
// Sample framebuffer to get pixel the refracted ray hits. | ||
const transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); | ||
const transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) ); | ||
const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb ); | ||
const dotNV = n.dot( v ).clamp(); | ||
// Get the specular component. | ||
const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness | ||
dotNV, | ||
specularColor, | ||
specularF90, | ||
roughness | ||
} ) ); | ||
// As less light is transmitted, the opacity should be increased. This simple approximation does a decent job | ||
// of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color. | ||
const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 ); | ||
return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() ); | ||
} ); | ||
// | ||
// Iridescence | ||
@@ -176,3 +299,3 @@ // | ||
constructor( clearcoat = false, sheen = false, iridescence = false ) { | ||
constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false ) { | ||
@@ -184,2 +307,4 @@ super(); | ||
this.iridescence = iridescence; | ||
this.anisotropy = anisotropy; | ||
this.transmission = transmission; | ||
@@ -196,3 +321,3 @@ this.clearcoatRadiance = null; | ||
start( /*context*/ ) { | ||
start( context ) { | ||
@@ -230,2 +355,31 @@ if ( this.clearcoat === true ) { | ||
if ( this.transmission === true ) { | ||
const position = positionWorld; | ||
const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX | ||
const n = transformedNormalWorld; | ||
context.backdrop = getIBLVolumeRefraction( | ||
n, | ||
v, | ||
roughness, | ||
diffuseColor, | ||
specularColor, | ||
specularF90, // specularF90 | ||
position, // positionWorld | ||
modelWorldMatrix, // modelMatrix | ||
cameraViewMatrix, // viewMatrix | ||
cameraProjectionMatrix, // projMatrix | ||
ior, | ||
thickness, | ||
attenuationColor, | ||
attenuationDistance | ||
); | ||
context.backdropAlpha = transmission; | ||
diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) ); | ||
} | ||
} | ||
@@ -237,3 +391,3 @@ | ||
computeMultiscattering( singleScatter, multiScatter, specularF90 = float( 1 ) ) { | ||
computeMultiscattering( singleScatter, multiScatter, specularF90 ) { | ||
@@ -281,3 +435,3 @@ const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV | ||
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, iridescenceFresnel: this.iridescenceFresnel } ) ) ); | ||
reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) ); | ||
@@ -328,3 +482,3 @@ } | ||
this.computeMultiscattering( singleScattering, multiScattering ); | ||
this.computeMultiscattering( singleScattering, multiScattering, specularF90 ); | ||
@@ -331,0 +485,0 @@ const totalScattering = singleScattering.add( multiScattering ); |
@@ -13,3 +13,3 @@ import LightingNode from './LightingNode.js'; | ||
import { Color, DepthTexture, NearestFilter, LessCompare } from 'three'; | ||
import { Color, DepthTexture, NearestFilter, LessCompare, NoToneMapping } from 'three'; | ||
@@ -30,2 +30,3 @@ let overrideMaterial = null; | ||
this.shadowNode = null; | ||
this.shadowMaskNode = null; | ||
@@ -55,2 +56,6 @@ this.color = new Color(); | ||
const { object } = builder; | ||
if ( object.receiveShadow === false ) return; | ||
let shadowNode = this.shadowNode; | ||
@@ -87,3 +92,5 @@ | ||
let shadowCoord = uniform( shadow.matrix ).mul( positionWorld.add( normalWorld.mul( normalBias ) ) ); | ||
const position = object.material.shadowPositionNode || positionWorld; | ||
let shadowCoord = uniform( shadow.matrix ).mul( position.add( normalWorld.mul( normalBias ) ) ); | ||
shadowCoord = shadowCoord.xyz.div( shadowCoord.w ); | ||
@@ -152,11 +159,13 @@ | ||
).mul( 1 / 17 ); | ||
*/ | ||
*/ | ||
// | ||
const shadowColor = texture( rtt.texture, shadowCoord ); | ||
const shadowMaskNode = frustumTest.mix( 1, shadowNode.mix( shadowColor.a.mix( 1, shadowColor ), 1 ) ); | ||
this.rtt = rtt; | ||
this.colorNode = this.colorNode.mul( frustumTest.mix( 1, shadowNode.mix( shadowColor.a.mix( 1, shadowColor ), 1 ) ) ); | ||
this.colorNode = this.colorNode.mul( shadowMaskNode ); | ||
this.shadowNode = shadowNode; | ||
this.shadowMaskNode = shadowMaskNode; | ||
@@ -191,2 +200,3 @@ // | ||
const currentToneMapping = renderer.toneMapping; | ||
const currentRenderTarget = renderer.getRenderTarget(); | ||
@@ -206,2 +216,3 @@ const currentRenderObjectFunction = renderer.getRenderObjectFunction(); | ||
renderer.setRenderTarget( rtt ); | ||
renderer.toneMapping = NoToneMapping; | ||
@@ -213,2 +224,4 @@ renderer.render( scene, light.shadow.camera ); | ||
renderer.toneMapping = currentToneMapping; | ||
scene.overrideMaterial = currentOverrideMaterial; | ||
@@ -223,2 +236,3 @@ | ||
this.shadowNode = null; | ||
this.shadowMaskNode = null; | ||
this.rtt = null; | ||
@@ -225,0 +239,0 @@ |
@@ -29,3 +29,4 @@ import AnalyticLightNode from './AnalyticLightNode.js'; | ||
lightColor, | ||
reflectedLight | ||
reflectedLight, | ||
shadowMask: this.shadowMaskNode | ||
}, builder.stack, builder ); | ||
@@ -32,0 +33,0 @@ |
@@ -11,2 +11,3 @@ import LightingNode from './LightingNode.js'; | ||
import { reference } from '../accessors/ReferenceNode.js'; | ||
import { transformedBentNormalView } from '../accessors/AccessorsUtils.js'; | ||
import { pmremTexture } from '../pmrem/PMREMNode.js'; | ||
@@ -48,6 +49,11 @@ | ||
const envMap = builder.material.envMap; | ||
const { material } = builder; | ||
const envMap = material.envMap; | ||
const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode | ||
const radiance = context( envNode, createRadianceContext( roughness, transformedNormalView ) ).mul( intensity ); | ||
const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0; | ||
const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView; | ||
const radiance = context( envNode, createRadianceContext( roughness, radianceNormalView ) ).mul( intensity ); | ||
const irradiance = context( envNode, createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity ); | ||
@@ -90,3 +96,6 @@ | ||
reflectVec = positionViewDirection.negate().reflect( normalViewNode ); | ||
// Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. | ||
reflectVec = roughnessNode.mul( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); | ||
reflectVec = reflectVec.transformDirection( cameraViewMatrix ); | ||
@@ -93,0 +102,0 @@ |
@@ -98,4 +98,14 @@ import Node from '../core/Node.js'; | ||
totalDiffuse = vec3( backdropAlpha !== null ? backdropAlpha.mix( totalDiffuse, backdrop ) : backdrop ); | ||
if ( backdropAlpha !== null ) { | ||
totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) ); | ||
} else { | ||
totalDiffuse = vec3( backdrop ); | ||
} | ||
context.material.transparent = true; | ||
} | ||
@@ -102,0 +112,0 @@ |
@@ -57,3 +57,4 @@ import AnalyticLightNode from './AnalyticLightNode.js'; | ||
lightColor, | ||
reflectedLight | ||
reflectedLight, | ||
shadowMask: this.shadowMaskNode | ||
}, builder.stack, builder ); | ||
@@ -60,0 +61,0 @@ |
@@ -78,3 +78,4 @@ import AnalyticLightNode from './AnalyticLightNode.js'; | ||
lightColor, | ||
reflectedLight | ||
reflectedLight, | ||
shadowMask: this.shadowMaskNode | ||
}, builder.stack, builder ); | ||
@@ -81,0 +82,0 @@ |
@@ -46,5 +46,11 @@ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js'; | ||
this.setValues( params ); | ||
} | ||
setup( builder ) { | ||
this.setupShaders(); | ||
this.setValues( params ); | ||
super.setup( builder ); | ||
@@ -375,4 +381,2 @@ } | ||
this.needsUpdate = true; | ||
} | ||
@@ -392,3 +396,3 @@ | ||
this.useWorldUnits = value; | ||
this.setupShaders(); | ||
this.needsUpdate = true; | ||
@@ -411,3 +415,3 @@ } | ||
this.useDash = value; | ||
this.setupShaders(); | ||
this.needsUpdate = true; | ||
@@ -430,3 +434,3 @@ } | ||
this.useAlphaToCoverage = value; | ||
this.setupShaders(); | ||
this.needsUpdate = true; | ||
@@ -433,0 +437,0 @@ } |
@@ -17,1 +17,2 @@ // @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports | ||
export { default as SpriteNodeMaterial } from './SpriteNodeMaterial.js'; | ||
export { default as ShadowNodeMaterial } from './ShadowNodeMaterial.js'; |
@@ -20,4 +20,2 @@ import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js'; | ||
this.colorSpaced = false; | ||
this.setDefaultValues( defaultValues ); | ||
@@ -24,0 +22,0 @@ |
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js'; | ||
import { shininess, specularColor } from '../core/PropertyNode.js'; | ||
import { materialShininess, materialSpecularColor } from '../accessors/MaterialNode.js'; | ||
import { materialShininess, materialSpecular } from '../accessors/MaterialNode.js'; | ||
import { float } from '../shadernode/ShaderNode.js'; | ||
@@ -46,3 +46,3 @@ import PhongLightingModel from '../functions/PhongLightingModel.js'; | ||
const specularNode = this.specularNode || materialSpecularColor; | ||
const specularNode = this.specularNode || materialSpecular; | ||
@@ -49,0 +49,0 @@ specularColor.assign( specularNode ); |
import { addNodeMaterial } from './NodeMaterial.js'; | ||
import { transformedClearcoatNormalView } from '../accessors/NormalNode.js'; | ||
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness } from '../core/PropertyNode.js'; | ||
import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness } from '../accessors/MaterialNode.js'; | ||
import { float, vec3 } from '../shadernode/ShaderNode.js'; | ||
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor } from '../core/PropertyNode.js'; | ||
import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor } from '../accessors/MaterialNode.js'; | ||
import { float, vec2, vec3, If } from '../shadernode/ShaderNode.js'; | ||
import { TBNViewMatrix } from '../accessors/AccessorsUtils.js'; | ||
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js'; | ||
import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js'; | ||
import { mix, pow2, min } from '../math/MathNode.js'; | ||
import { MeshPhysicalMaterial } from 'three'; | ||
@@ -35,2 +36,3 @@ | ||
this.iorNode = null; | ||
this.transmissionNode = null; | ||
@@ -41,2 +43,4 @@ this.thicknessNode = null; | ||
this.anisotropyNode = null; | ||
this.setDefaultValues( defaultValues ); | ||
@@ -66,5 +70,27 @@ | ||
get useAnisotropy() { | ||
return this.anisotropy > 0 || this.anisotropyNode !== null; | ||
} | ||
get useTransmission() { | ||
return this.transmission > 0 || this.transmissionNode !== null; | ||
} | ||
setupSpecular() { | ||
const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; | ||
ior.assign( iorNode ); | ||
specularColor.assign( mix( min( pow2( ior.sub( 1.0 ).div( ior.add( 1.0 ) ) ).mul( materialSpecularColor ), vec3( 1.0 ) ).mul( materialSpecularIntensity ), diffuseColor.rgb, metalness ) ); | ||
specularF90.assign( mix( materialSpecularIntensity, 1.0, metalness ) ); | ||
} | ||
setupLightingModel( /*builder*/ ) { | ||
return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence ); | ||
return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission ); | ||
@@ -115,2 +141,45 @@ } | ||
// ANISOTROPY | ||
if ( this.useAnisotropy ) { | ||
const anisotropyV = ( this.anisotropyNode ? vec2( this.anisotropyNode ) : materialAnisotropy ).toVar(); | ||
anisotropy.assign( anisotropyV.length() ); | ||
If( anisotropy.equal( 0.0 ), () => { | ||
anisotropyV.assign( vec2( 1.0, 0.0 ) ); | ||
} ).else( () => { | ||
anisotropyV.divAssign( anisotropy ); | ||
anisotropy.assign( anisotropy.saturate() ); | ||
} ); | ||
// Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. | ||
alphaT.assign( anisotropy.pow2().mix( roughness.pow2(), 1.0 ) ); | ||
anisotropyT.assign( TBNViewMatrix[ 0 ].mul( anisotropyV.x ).add( TBNViewMatrix[ 1 ].mul( anisotropyV.y ) ) ); | ||
anisotropyB.assign( TBNViewMatrix[ 1 ].mul( anisotropyV.x ).sub( TBNViewMatrix[ 0 ].mul( anisotropyV.y ) ) ); | ||
} | ||
// TRANSMISSION | ||
if ( this.useTransmission ) { | ||
const transmissionNode = this.transmissionNode ? float( this.transmissionNode ) : materialTransmission; | ||
const thicknessNode = this.thicknessNode ? float( this.thicknessNode ) : materialThickness; | ||
const attenuationDistanceNode = this.attenuationDistanceNode ? float( this.attenuationDistanceNode ) : materialAttenuationDistance; | ||
const attenuationColorNode = this.attenuationColorNode ? vec3( this.attenuationColorNode ) : materialAttenuationColor; | ||
transmission.assign( transmissionNode ); | ||
thickness.assign( thicknessNode ); | ||
attenuationDistance.assign( attenuationDistanceNode ); | ||
attenuationColor.assign( attenuationColorNode ); | ||
} | ||
} | ||
@@ -151,2 +220,4 @@ | ||
this.anisotropyNode = source.anisotropyNode; | ||
return super.copy( source ); | ||
@@ -153,0 +224,0 @@ |
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js'; | ||
import { diffuseColor, metalness, roughness, specularColor } from '../core/PropertyNode.js'; | ||
import { diffuseColor, metalness, roughness, specularColor, specularF90 } from '../core/PropertyNode.js'; | ||
import { mix } from '../math/MathNode.js'; | ||
@@ -38,2 +38,11 @@ import { materialRoughness, materialMetalness } from '../accessors/MaterialNode.js'; | ||
setupSpecular() { | ||
const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); | ||
specularColor.assign( specularColorNode ); | ||
specularF90.assign( 1.0 ); | ||
} | ||
setupVariants() { | ||
@@ -56,6 +65,4 @@ | ||
const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessNode ); | ||
this.setupSpecular(); | ||
specularColor.assign( specularColorNode ); | ||
// DIFFUSE COLOR | ||
@@ -62,0 +69,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { Material, ShaderMaterial, NoColorSpace, LinearSRGBColorSpace } from 'three'; | ||
import { Material, ShaderMaterial } from 'three'; | ||
import { getNodeChildren, getCacheKey } from '../core/NodeUtils.js'; | ||
@@ -10,3 +10,3 @@ import { attribute } from '../core/AttributeNode.js'; | ||
import { batch } from '../accessors/BatchNode.js'; | ||
import { materialReference } from '../accessors/MaterialReferenceNode.js'; | ||
import { positionLocal, positionView } from '../accessors/PositionNode.js'; | ||
@@ -23,2 +23,3 @@ import { skinningReference } from '../accessors/SkinningNode.js'; | ||
import EnvironmentNode from '../lighting/EnvironmentNode.js'; | ||
import IrradianceNode from '../lighting/IrradianceNode.js'; | ||
import { depthPixel } from '../display/ViewportDepthNode.js'; | ||
@@ -47,6 +48,5 @@ import { cameraLogDepth } from '../accessors/CameraNode.js'; | ||
this.colorSpaced = true; | ||
this.lightsNode = null; | ||
this.envNode = null; | ||
this.aoNode = null; | ||
@@ -64,2 +64,3 @@ this.colorNode = null; | ||
this.shadowNode = null; | ||
this.shadowPositionNode = null; | ||
@@ -103,6 +104,6 @@ this.outputNode = null; | ||
if ( this.depthWrite === true ) this.setupDepth( builder ); | ||
if ( this.fragmentNode === null ) { | ||
if ( this.depthWrite === true ) this.setupDepth( builder ); | ||
if ( this.normals === true ) this.setupNormal( builder ); | ||
@@ -133,4 +134,12 @@ | ||
resultNode = this.setupOutput( builder, this.fragmentNode ); | ||
let fragmentNode = this.fragmentNode; | ||
if ( fragmentNode.isOutputStructNode !== true ) { | ||
fragmentNode = vec4( fragmentNode ); | ||
} | ||
resultNode = this.setupOutput( builder, fragmentNode ); | ||
} | ||
@@ -146,2 +155,4 @@ | ||
if ( builder.clippingContext === null ) return null; | ||
const { globalClippingCount, localClippingCount } = builder.clippingContext; | ||
@@ -347,8 +358,16 @@ | ||
if ( builder.material.aoMap ) { | ||
if ( builder.material.lightMap ) { | ||
materialLightsNode.push( new AONode( texture( builder.material.aoMap ) ) ); | ||
materialLightsNode.push( new IrradianceNode( materialReference( 'lightMap', 'texture' ) ) ); | ||
} | ||
if ( this.aoNode !== null || builder.material.aoMap ) { | ||
const aoNode = this.aoNode !== null ? this.aoNode : texture( builder.material.aoMap ); | ||
materialLightsNode.push( new AONode( aoNode ) ); | ||
} | ||
let lightsN = this.lightsNode || builder.lightsNode; | ||
@@ -411,38 +430,8 @@ | ||
const renderer = builder.renderer; | ||
// FOG | ||
if ( this.fog === true ) { | ||
const fogNode = builder.fogNode; | ||
const fogNode = builder.fogNode; | ||
if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a ); | ||
if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a ); | ||
} | ||
// TONE MAPPING | ||
const toneMappingNode = builder.toneMappingNode; | ||
if ( this.toneMapped === true && toneMappingNode ) { | ||
outputNode = vec4( toneMappingNode.context( { color: outputNode.rgb } ), outputNode.a ); | ||
} | ||
// ENCODING | ||
if ( this.colorSpaced === true ) { | ||
const outputColorSpace = renderer.currentColorSpace; | ||
if ( outputColorSpace !== LinearSRGBColorSpace && outputColorSpace !== NoColorSpace ) { | ||
outputNode = outputNode.linearToColorSpace( outputColorSpace ); | ||
} | ||
} | ||
return outputNode; | ||
@@ -563,2 +552,3 @@ | ||
this.shadowNode = source.shadowNode; | ||
this.shadowPositionNode = source.shadowPositionNode; | ||
@@ -565,0 +555,0 @@ this.outputNode = source.outputNode; |
@@ -29,3 +29,3 @@ // @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports | ||
export { default as ParameterNode, parameter } from './core/ParameterNode.js'; | ||
export { default as PropertyNode, property, varyingProperty, output, diffuseColor, roughness, metalness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, shininess, dashSize, gapSize, pointWidth } from './core/PropertyNode.js'; | ||
export { default as PropertyNode, property, varyingProperty, output, diffuseColor, roughness, metalness, clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, shininess, dashSize, gapSize, pointWidth, alphaT, anisotropy, anisotropyB, anisotropyT } from './core/PropertyNode.js'; | ||
export { default as StackNode, stack } from './core/StackNode.js'; | ||
@@ -79,3 +79,3 @@ export { default as TempNode } from './core/TempNode.js'; | ||
// accessors | ||
export { TBNViewMatrix, parallaxDirection, parallaxUV } from './accessors/AccessorsUtils.js'; | ||
export { TBNViewMatrix, parallaxDirection, parallaxUV, transformedBentNormalView } from './accessors/AccessorsUtils.js'; | ||
export { default as UniformsNode, uniforms } from './accessors/UniformsNode.js'; | ||
@@ -90,3 +90,3 @@ export { default as BitangentNode, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, transformedBitangentView, transformedBitangentWorld } from './accessors/BitangentNode.js'; | ||
export { default as BatchNode, batch } from './accessors/BatchNode.js'; | ||
export { default as MaterialNode, materialAlphaTest, materialColor, materialShininess, materialEmissive, materialOpacity, materialSpecularColor, materialSpecularStrength, materialReflectivity, materialRoughness, materialMetalness, materialNormal, materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialRotation, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLineScale, materialLineDashSize, materialLineGapSize, materialLineWidth, materialLineDashOffset, materialPointWidth } from './accessors/MaterialNode.js'; | ||
export { default as MaterialNode, materialAlphaTest, materialColor, materialShininess, materialEmissive, materialOpacity, materialSpecular, materialSpecularStrength, materialReflectivity, materialRoughness, materialMetalness, materialNormal, materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialRotation, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLineScale, materialLineDashSize, materialLineGapSize, materialLineWidth, materialLineDashOffset, materialPointWidth, materialAnisotropy, materialAnisotropyVector } from './accessors/MaterialNode.js'; | ||
export { default as MaterialReferenceNode, materialReference } from './accessors/MaterialReferenceNode.js'; | ||
@@ -164,2 +164,3 @@ export { default as RendererReferenceNode, rendererReference } from './accessors/RendererReferenceNode.js'; | ||
export { default as EnvironmentNode } from './lighting/EnvironmentNode.js'; | ||
export { default as IrradianceNode } from './lighting/IrradianceNode.js'; | ||
export { default as AONode } from './lighting/AONode.js'; | ||
@@ -166,0 +167,0 @@ export { default as AnalyticLightNode } from './lighting/AnalyticLightNode.js'; |
@@ -240,3 +240,3 @@ import { tslFn, int, float, vec2, vec3, vec4, If } from '../shadernode/ShaderNode.js'; | ||
return envMap.uv( uv ); | ||
return envMap.uv( uv ).grad( vec2(), vec2() ); // disable anisotropic filtering | ||
@@ -243,0 +243,0 @@ } ); |
@@ -459,2 +459,4 @@ import Node, { addNodeClass } from '../core/Node.js'; | ||
export const defined = ( value ) => value && value.value; | ||
// utils | ||
@@ -478,10 +480,2 @@ | ||
export const shader = ( jsFunc ) => { // @deprecated, r154 | ||
console.warn( 'TSL: shader() is deprecated. Use tslFn() instead.' ); | ||
return new ShaderNode( jsFunc ); | ||
}; | ||
export const tslFn = ( jsFunc ) => { | ||
@@ -488,0 +482,0 @@ |
import DataMap from './DataMap.js'; | ||
import Color4 from './Color4.js'; | ||
import { Mesh, SphereGeometry, BackSide } from 'three'; | ||
import { Mesh, SphereGeometry, BackSide, LinearSRGBColorSpace } from 'three'; | ||
import { vec4, context, normalWorld, backgroundBlurriness, backgroundIntensity, NodeMaterial, modelViewProjection } from '../../nodes/Nodes.js'; | ||
@@ -30,3 +30,3 @@ | ||
renderer._clearColor.getRGB( _clearColor, this.renderer.currentColorSpace ); | ||
renderer._clearColor.getRGB( _clearColor, LinearSRGBColorSpace ); | ||
_clearColor.a = renderer._clearColor.a; | ||
@@ -38,3 +38,3 @@ | ||
background.getRGB( _clearColor, this.renderer.currentColorSpace ); | ||
background.getRGB( _clearColor, LinearSRGBColorSpace ); | ||
_clearColor.a = 1; | ||
@@ -41,0 +41,0 @@ |
@@ -104,3 +104,3 @@ import { Matrix3, Plane, Vector4 } from 'three'; | ||
this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount; | ||
this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount; | ||
this.localClippingEnabled = parent.localClippingEnabled; | ||
@@ -107,0 +107,0 @@ this.planes = Array.from( parent.planes ); |
@@ -23,3 +23,2 @@ import NodeMaterial from '../../../nodes/materials/NodeMaterial.js'; | ||
LinearFilter, | ||
NoToneMapping, | ||
NoBlending, | ||
@@ -61,12 +60,12 @@ RGBAFormat, | ||
const _axisDirections = [ | ||
/*@__PURE__*/ new Vector3( 1, 1, 1 ), | ||
/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, 1 ), | ||
/*@__PURE__*/ new Vector3( 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), | ||
/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) | ||
/*@__PURE__*/ new Vector3( 1, 1, 1 ) | ||
]; | ||
@@ -343,6 +342,5 @@ | ||
const originalAutoClear = renderer.autoClear; | ||
const toneMapping = renderer.toneMapping; | ||
renderer.getClearColor( _clearColor ); | ||
renderer.toneMapping = NoToneMapping; | ||
renderer.autoClear = false; | ||
@@ -424,3 +422,2 @@ | ||
renderer.toneMapping = toneMapping; | ||
renderer.autoClear = originalAutoClear; | ||
@@ -475,8 +472,9 @@ scene.background = background; | ||
renderer.autoClear = false; | ||
const n = this._lodPlanes.length; | ||
for ( let i = 1; i < this._lodPlanes.length; i ++ ) { | ||
for ( let i = 1; i < n; i ++ ) { | ||
const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); | ||
const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ]; | ||
const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; | ||
@@ -717,4 +715,2 @@ this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); | ||
const material = new NodeMaterial(); | ||
material.colorSpaced = false; | ||
material.toneMapped = false; | ||
material.depthTest = false; | ||
@@ -721,0 +717,0 @@ material.depthWrite = false; |
import DataMap from '../DataMap.js'; | ||
import ChainMap from '../ChainMap.js'; | ||
import NodeBuilderState from './NodeBuilderState.js'; | ||
import { NoToneMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from 'three'; | ||
import { NodeFrame, objectGroup, renderGroup, frameGroup, cubeTexture, texture, rangeFog, densityFog, reference, toneMapping, viewportBottomLeft, normalWorld, pmremTexture } from '../../../nodes/Nodes.js'; | ||
import { EquirectangularReflectionMapping, EquirectangularRefractionMapping, NoToneMapping, SRGBColorSpace } from 'three'; | ||
import { NodeFrame, vec4, objectGroup, renderGroup, frameGroup, cubeTexture, texture, rangeFog, densityFog, reference, viewportBottomLeft, normalWorld, pmremTexture, viewportTopLeft } from '../../../nodes/Nodes.js'; | ||
@@ -116,3 +116,2 @@ class Nodes extends DataMap { | ||
nodeBuilder.fogNode = this.getFogNode( renderObject.scene ); | ||
nodeBuilder.toneMappingNode = this.getToneMappingNode(); | ||
nodeBuilder.clippingContext = renderObject.clippingContext; | ||
@@ -210,10 +209,2 @@ nodeBuilder.build(); | ||
getToneMappingNode() { | ||
if ( this.isToneMappingState === false ) return null; | ||
return this.renderer.toneMappingNode || this.get( this.renderer ).toneMappingNode || null; | ||
} | ||
getCacheKey( scene, lightsNode ) { | ||
@@ -230,3 +221,2 @@ | ||
const fogNode = this.getFogNode( scene ); | ||
const toneMappingNode = this.getToneMappingNode(); | ||
@@ -238,3 +228,2 @@ const cacheKey = []; | ||
if ( fogNode ) cacheKey.push( fogNode.getCacheKey() ); | ||
if ( toneMappingNode ) cacheKey.push( toneMappingNode.getCacheKey() ); | ||
@@ -259,3 +248,2 @@ cacheKeyData = { | ||
this.updateBackground( scene ); | ||
this.updateToneMapping(); | ||
@@ -266,38 +254,6 @@ } | ||
const renderer = this.renderer; | ||
const renderTarget = renderer.getRenderTarget(); | ||
return this.renderer.getRenderTarget() ? false : true; | ||
return renderTarget && renderTarget.isCubeRenderTarget ? false : true; | ||
} | ||
updateToneMapping() { | ||
const renderer = this.renderer; | ||
const rendererData = this.get( renderer ); | ||
const rendererToneMapping = renderer.toneMapping; | ||
if ( this.isToneMappingState && rendererToneMapping !== NoToneMapping ) { | ||
if ( rendererData.toneMapping !== rendererToneMapping ) { | ||
const rendererToneMappingNode = rendererData.rendererToneMappingNode || toneMapping( rendererToneMapping ); | ||
rendererToneMappingNode.toneMapping = rendererToneMapping; | ||
rendererData.rendererToneMappingNode = rendererToneMappingNode; | ||
rendererData.toneMappingNode = rendererToneMappingNode; | ||
rendererData.toneMapping = rendererToneMapping; | ||
} | ||
} else { | ||
// Don't delete rendererData.rendererToneMappingNode | ||
delete rendererData.toneMappingNode; | ||
delete rendererData.toneMapping; | ||
} | ||
} | ||
updateBackground( scene ) { | ||
@@ -439,2 +395,30 @@ | ||
getOutputNode( outputTexture ) { | ||
let output = texture( outputTexture, viewportTopLeft ); | ||
if ( this.isToneMappingState ) { | ||
if ( this.renderer.toneMappingNode ) { | ||
output = vec4( this.renderer.toneMappingNode.context( { color: output.rgb } ), output.a ); | ||
} else if ( this.renderer.toneMapping !== NoToneMapping ) { | ||
output = output.toneMapping( this.renderer.toneMapping ); | ||
} | ||
} | ||
if ( this.renderer.currentColorSpace === SRGBColorSpace ) { | ||
output = output.linearToColorSpace( this.renderer.currentColorSpace ); | ||
} | ||
return output; | ||
} | ||
updateBefore( renderObject ) { | ||
@@ -441,0 +425,0 @@ |
@@ -15,3 +15,5 @@ import Animation from './Animation.js'; | ||
import ClippingContext from './ClippingContext.js'; | ||
import { Scene, Frustum, Matrix4, Vector2, Vector3, Vector4, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoToneMapping } from 'three'; | ||
import { Scene, Frustum, Matrix4, Vector2, Vector3, Vector4, DoubleSide, BackSide, FrontSide, SRGBColorSpace, NoColorSpace, NoToneMapping, LinearFilter, LinearSRGBColorSpace, RenderTarget, HalfFloatType, RGBAFormat } from 'three'; | ||
import { NodeMaterial } from '../../nodes/Nodes.js'; | ||
import QuadMesh from '../../objects/QuadMesh.js'; | ||
@@ -24,2 +26,3 @@ const _scene = new Scene(); | ||
const _vector3 = new Vector3(); | ||
const _quad = new QuadMesh( new NodeMaterial() ); | ||
@@ -68,2 +71,6 @@ class Renderer { | ||
// nodes | ||
this.toneMappingNode = null; | ||
// internals | ||
@@ -96,2 +103,3 @@ | ||
this._frameBufferTarget = null; | ||
@@ -339,4 +347,53 @@ const alphaClear = this.alpha === true ? 0 : 1; | ||
_renderScene( scene, camera ) { | ||
_getFrameBufferTarget() { | ||
const { currentColorSpace } = this; | ||
const useToneMapping = this._renderTarget === null && ( this.toneMapping !== NoToneMapping || this.toneMappingNode !== null ); | ||
const useColorSpace = currentColorSpace !== LinearSRGBColorSpace && currentColorSpace !== NoColorSpace; | ||
if ( useToneMapping === false && useColorSpace === false ) return null; | ||
const { width, height } = this.getDrawingBufferSize( _drawingBufferSize ); | ||
const { depth, stencil } = this; | ||
let frameBufferTarget = this._frameBufferTarget; | ||
if ( frameBufferTarget === null ) { | ||
frameBufferTarget = new RenderTarget( width, height, { | ||
depthBuffer: depth, | ||
stencilBuffer: stencil, | ||
type: HalfFloatType, // FloatType | ||
format: RGBAFormat, | ||
colorSpace: LinearSRGBColorSpace, | ||
generateMipmaps: false, | ||
minFilter: LinearFilter, | ||
magFilter: LinearFilter, | ||
samples: this.backend.parameters.antialias ? 4 : 0 | ||
} ); | ||
frameBufferTarget.isPostProcessingRenderTarget = true; | ||
this._frameBufferTarget = frameBufferTarget; | ||
} | ||
frameBufferTarget.depthBuffer = depth; | ||
frameBufferTarget.stencilBuffer = stencil; | ||
frameBufferTarget.setSize( width, height ); | ||
frameBufferTarget.viewport.copy( this._viewport ); | ||
frameBufferTarget.scissor.copy( this._scissor ); | ||
frameBufferTarget.viewport.multiplyScalar( this._pixelRatio ); | ||
frameBufferTarget.scissor.multiplyScalar( this._pixelRatio ); | ||
frameBufferTarget.scissorTest = this._scissorTest; | ||
return frameBufferTarget; | ||
} | ||
_renderScene( scene, camera, useFrameBufferTarget = true ) { | ||
const frameBufferTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : null; | ||
// preserve render tree | ||
@@ -354,7 +411,27 @@ | ||
const renderTarget = this._renderTarget; | ||
const renderContext = this._renderContexts.get( scene, camera, renderTarget ); | ||
const outputRenderTarget = this._renderTarget; | ||
const activeCubeFace = this._activeCubeFace; | ||
const activeMipmapLevel = this._activeMipmapLevel; | ||
// | ||
let renderTarget; | ||
if ( frameBufferTarget !== null ) { | ||
renderTarget = frameBufferTarget; | ||
this.setRenderTarget( renderTarget ); | ||
} else { | ||
renderTarget = outputRenderTarget; | ||
} | ||
// | ||
const renderContext = this._renderContexts.get( scene, camera, renderTarget ); | ||
this._currentRenderContext = renderContext; | ||
@@ -514,2 +591,14 @@ this._currentRenderObjectFunction = this._renderObjectFunction || this.renderObject; | ||
if ( frameBufferTarget !== null ) { | ||
this.setRenderTarget( outputRenderTarget, activeCubeFace, activeMipmapLevel ); | ||
_quad.material.fragmentNode = this._nodes.getOutputNode( renderTarget.texture ); | ||
this._renderScene( _quad, _quad.camera, false ); | ||
} | ||
// | ||
sceneRef.onAfterRender( this, scene, camera, renderTarget ); | ||
@@ -779,4 +868,5 @@ | ||
const renderTarget = this._renderTarget || this._getFrameBufferTarget(); | ||
let renderTargetData = null; | ||
const renderTarget = this._renderTarget; | ||
@@ -975,6 +1065,8 @@ if ( renderTarget !== null ) { | ||
hasFeatureAsync( name ) { | ||
async hasFeatureAsync( name ) { | ||
return this.backend.hasFeatureAsync( name ); | ||
if ( this._initialized === false ) await this.init(); | ||
return this.backend.hasFeature( name ); | ||
} | ||
@@ -984,2 +1076,10 @@ | ||
if ( this._initialized === false ) { | ||
console.warn( 'THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead.' ); | ||
return false; | ||
} | ||
return this.backend.hasFeature( name ); | ||
@@ -1009,5 +1109,5 @@ | ||
readRenderTargetPixelsAsync( renderTarget, x, y, width, height ) { | ||
readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0 ) { | ||
return this.backend.copyTextureToBuffer( renderTarget.texture, x, y, width, height ); | ||
return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height ); | ||
@@ -1172,2 +1272,3 @@ } | ||
let overrideFragmentNode; | ||
let overrideDepthNode; | ||
@@ -1189,3 +1290,2 @@ // | ||
overridePositionNode = overrideMaterial.positionNode; | ||
overrideMaterial.positionNode = material.positionNode; | ||
@@ -1199,2 +1299,10 @@ | ||
if ( material.depthNode && material.depthNode.isNode ) { | ||
overrideDepthNode = overrideMaterial.depthNode; | ||
overrideMaterial.depthNode = material.depthNode; | ||
} | ||
if ( material.shadowNode && material.shadowNode.isNode ) { | ||
@@ -1244,6 +1352,6 @@ | ||
material.side = BackSide; | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode, 'backSide' ); // create backSide pass id | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode, group, 'backSide' ); // create backSide pass id | ||
material.side = FrontSide; | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode ); // use default pass id | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode, group ); // use default pass id | ||
@@ -1254,3 +1362,3 @@ material.side = DoubleSide; | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode ); | ||
this._handleObjectFunction( object, material, scene, camera, lightsNode, group ); | ||
@@ -1267,2 +1375,8 @@ } | ||
if ( overrideDepthNode !== undefined ) { | ||
scene.overrideMaterial.depthNode = overrideDepthNode; | ||
} | ||
if ( overrideFragmentNode !== undefined ) { | ||
@@ -1280,5 +1394,6 @@ | ||
_renderObjectDirect( object, material, scene, camera, lightsNode, passId ) { | ||
_renderObjectDirect( object, material, scene, camera, lightsNode, group, passId ) { | ||
const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId ); | ||
renderObject.drawRange = group || object.geometry.drawRange; | ||
@@ -1285,0 +1400,0 @@ // |
@@ -126,3 +126,3 @@ import { LightsNode } from '../../nodes/Nodes.js'; | ||
( material.transparent === true ? this.transparent : this.opaque ).push( renderItem ); | ||
( material.transparent === true || material.transmission > 0 ? this.transparent : this.opaque ).push( renderItem ); | ||
@@ -129,0 +129,0 @@ } |
@@ -5,2 +5,36 @@ import ClippingContext from './ClippingContext.js'; | ||
function getKeys( obj ) { | ||
const keys = Object.keys( obj ); | ||
let proto = Object.getPrototypeOf( obj ); | ||
while ( proto ) { | ||
const descriptors = Object.getOwnPropertyDescriptors( proto ); | ||
for ( const key in descriptors ) { | ||
if ( descriptors[ key ] !== undefined ) { | ||
const descriptor = descriptors[ key ]; | ||
if ( descriptor && typeof descriptor.get === 'function' ) { | ||
keys.push( key ); | ||
} | ||
} | ||
} | ||
proto = Object.getPrototypeOf( proto ); | ||
} | ||
return keys; | ||
} | ||
export default class RenderObject { | ||
@@ -26,2 +60,4 @@ | ||
this.drawRange = null; | ||
this.attributes = null; | ||
@@ -158,3 +194,3 @@ this.pipeline = null; | ||
for ( const property in material ) { | ||
for ( const property of getKeys( material ) ) { | ||
@@ -192,2 +228,8 @@ if ( /^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test( property ) ) continue; | ||
if ( object.isBatchedMesh ) { | ||
cacheKey += object._matricesTexture.uuid + ','; | ||
} | ||
return cacheKey; | ||
@@ -194,0 +236,0 @@ |
@@ -41,3 +41,3 @@ import DataMap from './DataMap.js'; | ||
depthTexture.format = renderTarget.stencilBuffer ? DepthStencilFormat : DepthFormat; | ||
depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType; | ||
depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType; // FloatType | ||
depthTexture.image.width = mipWidth; | ||
@@ -44,0 +44,0 @@ depthTexture.image.height = mipHeight; |
@@ -249,2 +249,8 @@ import { MathNode, GLSLNodeParser, NodeBuilder, UniformNode, vectorComponents } from '../../../nodes/Nodes.js'; | ||
generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet ) { | ||
return `textureGrad( ${ textureProperty }, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; | ||
} | ||
generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { | ||
@@ -251,0 +257,0 @@ |
@@ -579,10 +579,25 @@ import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, FloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, SRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare } from 'three'; | ||
if ( texture.isDepthTexture ) { | ||
const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); | ||
let mask = gl.DEPTH_BUFFER_BIT; | ||
if ( requireDrawFrameBuffer ) { | ||
if ( renderContext.stencil ) { | ||
let mask; | ||
let attachment; | ||
mask |= gl.STENCIL_BUFFER_BIT; | ||
if ( texture.isDepthTexture === true ) { | ||
mask = gl.DEPTH_BUFFER_BIT; | ||
attachment = gl.DEPTH_ATTACHMENT; | ||
if ( renderContext.stencil ) { | ||
mask |= gl.STENCIL_BUFFER_BIT; | ||
} | ||
} else { | ||
mask = gl.COLOR_BUFFER_BIT; | ||
attachment = gl.COLOR_ATTACHMENT0; | ||
} | ||
@@ -593,3 +608,3 @@ | ||
gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, textureGPU, 0 ); | ||
gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureGPU, 0 ); | ||
@@ -631,3 +646,2 @@ gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, gl.NEAREST ); | ||
if ( depthTexture && depthTexture.isDepthTexture ) { | ||
@@ -698,3 +712,3 @@ | ||
const dstBuffer = new typedArrayType( elementCount ); | ||
const dstBuffer = new typedArrayType( byteLength / typedArrayType.BYTES_PER_ELEMENT ); | ||
@@ -701,0 +715,0 @@ gl.bindBuffer( gl.PIXEL_PACK_BUFFER, buffer ); |
@@ -117,24 +117,6 @@ import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, SRGBColorSpace, NoColorSpace } from 'three'; | ||
// ETC1 | ||
// ETC | ||
if ( p === RGB_ETC1_Format ) { | ||
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { | ||
extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); | ||
if ( extension !== null ) { | ||
return extension.COMPRESSED_RGB_ETC1_WEBGL; | ||
} else { | ||
return null; | ||
} | ||
} | ||
// ETC2 | ||
if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { | ||
extension = extensions.get( 'WEBGL_compressed_texture_etc' ); | ||
@@ -144,3 +126,3 @@ | ||
if ( p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; | ||
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; | ||
if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; | ||
@@ -147,0 +129,0 @@ |
@@ -176,2 +176,3 @@ import { WebGLCoordinateSystem } from 'three'; | ||
// | ||
this.initTimestampQuery( renderContext ); | ||
@@ -572,3 +573,3 @@ | ||
const { pipeline, material, context } = renderObject; | ||
const { object, pipeline, material, context } = renderObject; | ||
const { programGPU } = this.get( pipeline ); | ||
@@ -584,4 +585,6 @@ | ||
state.setMaterial( material ); | ||
const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); | ||
state.setMaterial( material, frontFaceCW ); | ||
gl.useProgram( programGPU ); | ||
@@ -617,5 +620,4 @@ | ||
const object = renderObject.object; | ||
const geometry = renderObject.geometry; | ||
const drawRange = geometry.drawRange; | ||
const drawRange = renderObject.drawRange; | ||
const firstVertex = drawRange.start; | ||
@@ -706,13 +708,4 @@ | ||
if ( instanceCount > 1 ) { | ||
if ( object._multiDrawInstances !== null ) { | ||
// TODO: Better support with InstancedBatchedMesh | ||
if ( object._multiDrawInstances === undefined ) { | ||
object._multiDrawInstances = new Int32Array( object._maxGeometryCount ); | ||
} | ||
object._multiDrawInstances.fill( instanceCount ); | ||
renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); | ||
@@ -1123,8 +1116,2 @@ | ||
async hasFeatureAsync( name ) { | ||
return this.hasFeature( name ); | ||
} | ||
hasFeature( name ) { | ||
@@ -1138,3 +1125,2 @@ | ||
if ( extensions.has( keysMatching[ i ] ) ) return true; | ||
@@ -1141,0 +1127,0 @@ |
@@ -130,4 +130,8 @@ class WebGLBufferRenderer { | ||
info.update( object, elementCount, mode, primcount ); | ||
for ( let i = 0; i < primcount.length; i ++ ) { | ||
info.update( object, elementCount, mode, primcount[ i ] ); | ||
} | ||
} | ||
@@ -134,0 +138,0 @@ |
@@ -257,2 +257,17 @@ import { NoColorSpace, FloatType } from 'three'; | ||
generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, shaderStage = this.shaderStage ) { | ||
if ( shaderStage === 'fragment' ) { | ||
// TODO handle i32 or u32 --> uvSnippet, array_index: A, ddx, ddy | ||
return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; | ||
} else { | ||
console.error( `WebGPURenderer: THREE.TextureNode.gradient() does not support ${ shaderStage } shader.` ); | ||
} | ||
} | ||
generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { | ||
@@ -526,3 +541,3 @@ | ||
return this.getBuiltin( 'position', 'fragCoord', 'vec4<f32>' ) + '.xy'; | ||
return this.getBuiltin( 'position', 'fragCoord', 'vec4<f32>' ) + '.xyz'; | ||
@@ -529,0 +544,0 @@ } |
@@ -67,3 +67,2 @@ import { Float16BufferAttribute } from 'three'; | ||
bufferAttribute.itemSize = 4; | ||
array = new array.constructor( bufferAttribute.count * 4 ); | ||
@@ -77,2 +76,6 @@ | ||
// Update BufferAttribute | ||
bufferAttribute.itemSize = 4; | ||
bufferAttribute.array = array; | ||
} | ||
@@ -79,0 +82,0 @@ |
@@ -17,3 +17,2 @@ /*// debugger tools | ||
import WebGPUTextureUtils from './utils/WebGPUTextureUtils.js'; | ||
import WebGPU from '../../capabilities/WebGPU.js'; | ||
@@ -49,3 +48,2 @@ // | ||
this.adapter = null; | ||
this.device = null; | ||
@@ -73,40 +71,51 @@ this.context = null; | ||
const adapterOptions = { | ||
powerPreference: parameters.powerPreference | ||
}; | ||
// create the device if it is not passed with parameters | ||
const adapter = await navigator.gpu.requestAdapter( adapterOptions ); | ||
let device; | ||
if ( adapter === null ) { | ||
if ( parameters.device === undefined ) { | ||
throw new Error( 'WebGPUBackend: Unable to create WebGPU adapter.' ); | ||
const adapterOptions = { | ||
powerPreference: parameters.powerPreference | ||
}; | ||
} | ||
const adapter = await navigator.gpu.requestAdapter( adapterOptions ); | ||
// feature support | ||
if ( adapter === null ) { | ||
const features = Object.values( GPUFeatureName ); | ||
throw new Error( 'WebGPUBackend: Unable to create WebGPU adapter.' ); | ||
const supportedFeatures = []; | ||
} | ||
for ( const name of features ) { | ||
// feature support | ||
if ( adapter.features.has( name ) ) { | ||
const features = Object.values( GPUFeatureName ); | ||
supportedFeatures.push( name ); | ||
const supportedFeatures = []; | ||
for ( const name of features ) { | ||
if ( adapter.features.has( name ) ) { | ||
supportedFeatures.push( name ); | ||
} | ||
} | ||
} | ||
const deviceDescriptor = { | ||
requiredFeatures: supportedFeatures, | ||
requiredLimits: parameters.requiredLimits | ||
}; | ||
const deviceDescriptor = { | ||
requiredFeatures: supportedFeatures, | ||
requiredLimits: parameters.requiredLimits | ||
}; | ||
device = await adapter.requestDevice( deviceDescriptor ); | ||
const device = await adapter.requestDevice( deviceDescriptor ); | ||
} else { | ||
device = parameters.device; | ||
} | ||
const context = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgpu' ); | ||
this.adapter = adapter; | ||
this.device = device; | ||
@@ -877,3 +886,3 @@ this.context = context; | ||
const drawRange = geometry.drawRange; | ||
const drawRange = renderObject.drawRange; | ||
const firstVertex = drawRange.start; | ||
@@ -1227,24 +1236,6 @@ | ||
async hasFeatureAsync( name ) { | ||
const adapter = this.adapter || await WebGPU.getStaticAdapter(); | ||
// | ||
return adapter.features.has( name ); | ||
} | ||
hasFeature( name ) { | ||
if ( ! this.adapter ) { | ||
return this.device.features.has( name ); | ||
console.warn( 'WebGPUBackend: WebGPU adapter has not been initialized yet. Please use hasFeatureAsync instead' ); | ||
return false; | ||
} | ||
return this.adapter.features.has( name ); | ||
} | ||
@@ -1280,5 +1271,2 @@ | ||
copyFramebufferToTexture( texture, renderContext ) { | ||
@@ -1285,0 +1273,0 @@ |
@@ -221,3 +221,3 @@ import { Program, FunctionDeclaration, For, AccessorElements, Ternary, Varying, DynamicElement, StaticElement, FunctionParameter, Unary, Conditional, VariableDeclaration, Operator, Number, String, FunctionCall, Return, Accessor, Uniform } from './AST.js'; | ||
this.addPolyfill( 'gl_FragCoord', 'vec2 gl_FragCoord = vec2( viewportCoordinate.x, viewportCoordinate.y.oneMinus() );' ); | ||
this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( viewportCoordinate.x, viewportCoordinate.y.oneMinus(), viewportCoordinate.z );' ); | ||
@@ -224,0 +224,0 @@ } |
@@ -12,3 +12,3 @@ import { Return, VariableDeclaration, Accessor } from './AST.js'; | ||
this.addPolyfill( 'iResolution', 'vec2 iResolution = viewportResolution;' ); | ||
this.addPolyfill( 'fragCoord', 'vec2 fragCoord = vec2( viewportCoordinate.x, viewportResolution.y - viewportCoordinate.y );' ); | ||
this.addPolyfill( 'fragCoord', 'vec3 fragCoord = vec3( viewportCoordinate.x, viewportResolution.y - viewportCoordinate.y, viewportCoordinate.z );' ); | ||
@@ -15,0 +15,0 @@ } |
@@ -248,2 +248,58 @@ import { | ||
/** | ||
* @param {Object3D} object Object to traverse. | ||
* @yields {Object3D} Objects that passed the filter condition. | ||
*/ | ||
function* traverseGenerator( object ) { | ||
yield object; | ||
const children = object.children; | ||
for ( let i = 0, l = children.length; i < l; i ++ ) { | ||
yield* traverseGenerator( children[ i ] ); | ||
} | ||
} | ||
/** | ||
* @param {Object3D} object Object to traverse. | ||
* @yields {Object3D} Objects that passed the filter condition. | ||
*/ | ||
function* traverseVisibleGenerator( object ) { | ||
if ( object.visible === false ) return; | ||
yield object; | ||
const children = object.children; | ||
for ( let i = 0, l = children.length; i < l; i ++ ) { | ||
yield* traverseVisibleGenerator( children[ i ] ); | ||
} | ||
} | ||
/** | ||
* @param {Object3D} object Object to traverse. | ||
* @yields {Object3D} Objects that passed the filter condition. | ||
*/ | ||
function* traverseAncestorsGenerator( object ) { | ||
const parent = object.parent; | ||
if ( parent !== null ) { | ||
yield parent; | ||
yield* traverseAncestorsGenerator( parent ); | ||
} | ||
} | ||
export { | ||
@@ -254,3 +310,6 @@ createMeshesFromInstancedMesh, | ||
reduceVertices, | ||
sortInstancedMesh | ||
sortInstancedMesh, | ||
traverseGenerator, | ||
traverseVisibleGenerator, | ||
traverseAncestorsGenerator | ||
}; |
@@ -9,3 +9,3 @@ import { Object3D, Sphere, Box3 } from 'three'; | ||
constructor( controller, loader = null ) { | ||
constructor( controller, loader = null, onLoad = null ) { | ||
@@ -18,2 +18,3 @@ super(); | ||
this.loader = loader; | ||
this.onLoad = onLoad; | ||
@@ -30,3 +31,3 @@ this.mesh = null; | ||
this.motionController = new XRHandMeshModel( this, controller, this.path, xrInputSource.handedness, this.loader ); | ||
this.motionController = new XRHandMeshModel( this, controller, this.path, xrInputSource.handedness, this.loader, this.onLoad ); | ||
@@ -33,0 +34,0 @@ } |
@@ -43,5 +43,7 @@ import { | ||
constructor() { | ||
constructor( gltfLoader = null, onLoad = null ) { | ||
this.gltfLoader = gltfLoader; | ||
this.path = null; | ||
this.onLoad = onLoad; | ||
@@ -81,3 +83,3 @@ } | ||
handModel.motionController = new XRHandMeshModel( handModel, controller, this.path, xrInputSource.handedness ); | ||
handModel.motionController = new XRHandMeshModel( handModel, controller, this.path, xrInputSource.handedness, this.gltfLoader, this.onLoad ); | ||
@@ -84,0 +86,0 @@ } |
{ | ||
"name": "super-three", | ||
"version": "0.163.0", | ||
"version": "0.164.0", | ||
"description": "JavaScript 3D library", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -1,2 +0,2 @@ | ||
export const REVISION = '163'; | ||
export const REVISION = '164'; | ||
@@ -3,0 +3,0 @@ export const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; |
@@ -37,2 +37,4 @@ import { EventDispatcher } from './EventDispatcher.js'; | ||
stencilBuffer: false, | ||
resolveDepthBuffer: true, | ||
resolveStencilBuffer: true, | ||
depthTexture: null, | ||
@@ -62,2 +64,5 @@ samples: 0, | ||
this.resolveDepthBuffer = options.resolveDepthBuffer; | ||
this.resolveStencilBuffer = options.resolveStencilBuffer; | ||
this.depthTexture = options.depthTexture; | ||
@@ -140,2 +145,5 @@ | ||
this.resolveDepthBuffer = source.resolveDepthBuffer; | ||
this.resolveStencilBuffer = source.resolveStencilBuffer; | ||
if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); | ||
@@ -142,0 +150,0 @@ |
@@ -52,12 +52,12 @@ import { | ||
const _axisDirections = [ | ||
/*@__PURE__*/ new Vector3( 1, 1, 1 ), | ||
/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, 1 ), | ||
/*@__PURE__*/ new Vector3( 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( - 1, 1, - 1 ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), | ||
/*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), | ||
/*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), | ||
/*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), | ||
/*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ) ]; | ||
/*@__PURE__*/ new Vector3( 1, 1, 1 ) ]; | ||
@@ -448,8 +448,9 @@ /** | ||
renderer.autoClear = false; | ||
const n = this._lodPlanes.length; | ||
for ( let i = 1; i < this._lodPlanes.length; i ++ ) { | ||
for ( let i = 1; i < n; i ++ ) { | ||
const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); | ||
const poleAxis = _axisDirections[ ( i - 1 ) % _axisDirections.length ]; | ||
const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; | ||
@@ -456,0 +457,0 @@ this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); |
@@ -115,3 +115,3 @@ import { Cache } from './Cache.js'; | ||
// https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content | ||
const contentLength = response.headers.get( 'Content-Length' ) || response.headers.get( 'X-File-Size' ); | ||
const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); | ||
const total = contentLength ? parseInt( contentLength ) : 0; | ||
@@ -118,0 +118,0 @@ const lengthComputable = total !== 0; |
@@ -106,2 +106,3 @@ import { Color } from '../math/Color.js'; | ||
if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; | ||
if ( json.dispersion !== undefined ) material.dispersion = json.dispersion; | ||
if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; | ||
@@ -108,0 +109,0 @@ if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; |
@@ -221,2 +221,4 @@ import { Color } from '../math/Color.js'; | ||
if ( this.dispersion !== undefined ) data.dispersion = this.dispersion; | ||
if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; | ||
@@ -223,0 +225,0 @@ if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; |
@@ -71,2 +71,3 @@ import { Vector2 } from '../math/Vector2.js'; | ||
this._clearcoat = 0; | ||
this._dispersion = 0; | ||
this._iridescence = 0; | ||
@@ -134,2 +135,20 @@ this._sheen = 0.0; | ||
get dispersion() { | ||
return this._dispersion; | ||
} | ||
set dispersion( value ) { | ||
if ( this._dispersion > 0 !== value > 0 ) { | ||
this.version ++; | ||
} | ||
this._dispersion = value; | ||
} | ||
get sheen() { | ||
@@ -193,2 +212,3 @@ | ||
this.dispersion = source.dispersion; | ||
this.ior = source.ior; | ||
@@ -195,0 +215,0 @@ |
@@ -155,2 +155,3 @@ import { BufferAttribute } from '../core/BufferAttribute.js'; | ||
this._multiDrawCount = 0; | ||
this._multiDrawInstances = null; | ||
this._visibilityChanged = true; | ||
@@ -597,2 +598,24 @@ | ||
getInstanceCountAt( id ) { | ||
if ( this._multiDrawInstances === null ) return null; | ||
return this._multiDrawInstances[ id ]; | ||
} | ||
setInstanceCountAt( id, instanceCount ) { | ||
if ( this._multiDrawInstances === null ) { | ||
this._multiDrawInstances = new Int32Array( this._maxGeometryCount ).fill( 1 ); | ||
} | ||
this._multiDrawInstances[ id ] = instanceCount; | ||
return id; | ||
} | ||
// get bounding box and compute it if it doesn't exist | ||
@@ -599,0 +622,0 @@ getBoundingBoxAt( id, target ) { |
@@ -10,4 +10,5 @@ import { Sphere } from '../math/Sphere.js'; | ||
const _start = /*@__PURE__*/ new Vector3(); | ||
const _end = /*@__PURE__*/ new Vector3(); | ||
const _vStart = /*@__PURE__*/ new Vector3(); | ||
const _vEnd = /*@__PURE__*/ new Vector3(); | ||
const _inverseMatrix = /*@__PURE__*/ new Matrix4(); | ||
@@ -17,2 +18,5 @@ const _ray = /*@__PURE__*/ new Ray(); | ||
const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); | ||
const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); | ||
class Line extends Object3D { | ||
@@ -59,7 +63,7 @@ | ||
_start.fromBufferAttribute( positionAttribute, i - 1 ); | ||
_end.fromBufferAttribute( positionAttribute, i ); | ||
_vStart.fromBufferAttribute( positionAttribute, i - 1 ); | ||
_vEnd.fromBufferAttribute( positionAttribute, i ); | ||
lineDistances[ i ] = lineDistances[ i - 1 ]; | ||
lineDistances[ i ] += _start.distanceTo( _end ); | ||
lineDistances[ i ] += _vStart.distanceTo( _vEnd ); | ||
@@ -105,6 +109,2 @@ } | ||
const vStart = new Vector3(); | ||
const vEnd = new Vector3(); | ||
const interSegment = new Vector3(); | ||
const interRay = new Vector3(); | ||
const step = this.isLineSegments ? 2 : 1; | ||
@@ -126,28 +126,25 @@ | ||
vStart.fromBufferAttribute( positionAttribute, a ); | ||
vEnd.fromBufferAttribute( positionAttribute, b ); | ||
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, a, b ); | ||
const distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); | ||
if ( intersect ) { | ||
if ( distSq > localThresholdSq ) continue; | ||
intersects.push( intersect ); | ||
interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation | ||
} | ||
const distance = raycaster.ray.origin.distanceTo( interRay ); | ||
} | ||
if ( distance < raycaster.near || distance > raycaster.far ) continue; | ||
if ( this.isLineLoop ) { | ||
intersects.push( { | ||
const a = index.getX( end - 1 ); | ||
const b = index.getX( start ); | ||
distance: distance, | ||
// What do we want? intersection point on the ray or on the segment?? | ||
// point: raycaster.ray.at( distance ), | ||
point: interSegment.clone().applyMatrix4( this.matrixWorld ), | ||
index: i, | ||
face: null, | ||
faceIndex: null, | ||
object: this | ||
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, a, b ); | ||
} ); | ||
if ( intersect ) { | ||
intersects.push( intersect ); | ||
} | ||
} | ||
@@ -162,28 +159,22 @@ | ||
vStart.fromBufferAttribute( positionAttribute, i ); | ||
vEnd.fromBufferAttribute( positionAttribute, i + 1 ); | ||
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, i, i + 1 ); | ||
const distSq = _ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); | ||
if ( intersect ) { | ||
if ( distSq > localThresholdSq ) continue; | ||
intersects.push( intersect ); | ||
interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation | ||
} | ||
const distance = raycaster.ray.origin.distanceTo( interRay ); | ||
} | ||
if ( distance < raycaster.near || distance > raycaster.far ) continue; | ||
if ( this.isLineLoop ) { | ||
intersects.push( { | ||
const intersect = checkIntersection( this, raycaster, _ray, localThresholdSq, end - 1, start ); | ||
distance: distance, | ||
// What do we want? intersection point on the ray or on the segment?? | ||
// point: raycaster.ray.at( distance ), | ||
point: interSegment.clone().applyMatrix4( this.matrixWorld ), | ||
index: i, | ||
face: null, | ||
faceIndex: null, | ||
object: this | ||
if ( intersect ) { | ||
} ); | ||
intersects.push( intersect ); | ||
} | ||
} | ||
@@ -228,2 +219,34 @@ | ||
function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { | ||
const positionAttribute = object.geometry.attributes.position; | ||
_vStart.fromBufferAttribute( positionAttribute, a ); | ||
_vEnd.fromBufferAttribute( positionAttribute, b ); | ||
const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); | ||
if ( distSq > thresholdSq ) return; | ||
_intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation | ||
const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); | ||
if ( distance < raycaster.near || distance > raycaster.far ) return; | ||
return { | ||
distance: distance, | ||
// What do we want? intersection point on the ray or on the segment?? | ||
// point: raycaster.ray.at( distance ), | ||
point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), | ||
index: a, | ||
face: null, | ||
faceIndex: null, | ||
object: object | ||
}; | ||
} | ||
export { Line }; |
@@ -43,3 +43,2 @@ import alphahash_fragment from './ShaderChunk/alphahash_fragment.glsl.js'; | ||
import gradientmap_pars_fragment from './ShaderChunk/gradientmap_pars_fragment.glsl.js'; | ||
import lightmap_fragment from './ShaderChunk/lightmap_fragment.glsl.js'; | ||
import lightmap_pars_fragment from './ShaderChunk/lightmap_pars_fragment.glsl.js'; | ||
@@ -173,3 +172,2 @@ import lights_lambert_fragment from './ShaderChunk/lights_lambert_fragment.glsl.js'; | ||
gradientmap_pars_fragment: gradientmap_pars_fragment, | ||
lightmap_fragment: lightmap_fragment, | ||
lightmap_pars_fragment: lightmap_pars_fragment, | ||
@@ -176,0 +174,0 @@ lights_lambert_fragment: lights_lambert_fragment, |
@@ -78,2 +78,8 @@ export default /* glsl */` | ||
#ifdef USE_DISPERSION | ||
material.dispersion = dispersion; | ||
#endif | ||
#ifdef USE_IRIDESCENCE | ||
@@ -80,0 +86,0 @@ |
@@ -9,2 +9,3 @@ export default /* glsl */` | ||
float specularF90; | ||
float dispersion; | ||
@@ -11,0 +12,0 @@ #ifdef USE_CLEARCOAT |
@@ -171,20 +171,28 @@ export default /* glsl */` | ||
vec3 NeutralToneMapping( vec3 color ) { | ||
float startCompression = 0.8 - 0.04; | ||
float desaturation = 0.15; | ||
const float StartCompression = 0.8 - 0.04; | ||
const float Desaturation = 0.15; | ||
color *= toneMappingExposure; | ||
float x = min(color.r, min(color.g, color.b)); | ||
float x = min( color.r, min( color.g, color.b ) ); | ||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; | ||
color -= offset; | ||
float peak = max(color.r, max(color.g, color.b)); | ||
if (peak < startCompression) return color; | ||
float peak = max( color.r, max( color.g, color.b ) ); | ||
float d = 1. - startCompression; | ||
float newPeak = 1. - d * d / (peak + d - startCompression); | ||
if ( peak < StartCompression ) return color; | ||
float d = 1. - StartCompression; | ||
float newPeak = 1. - d * d / ( peak + d - StartCompression ); | ||
color *= newPeak / peak; | ||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); | ||
return mix(color, newPeak * vec3(1, 1, 1), g); | ||
float g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. ); | ||
return mix( color, vec3( newPeak ), g ); | ||
} | ||
@@ -191,0 +199,0 @@ |
@@ -28,3 +28,3 @@ export default /* glsl */` | ||
n, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90, | ||
pos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness, | ||
pos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness, | ||
material.attenuationColor, material.attenuationDistance ); | ||
@@ -31,0 +31,0 @@ |
@@ -172,18 +172,52 @@ export default /* glsl */` | ||
const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, | ||
const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness, | ||
const in mat4 viewMatrix, const in mat4 projMatrix, const in float dispersion, const in float ior, const in float thickness, | ||
const in vec3 attenuationColor, const in float attenuationDistance ) { | ||
vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); | ||
vec3 refractedRayExit = position + transmissionRay; | ||
vec4 transmittedLight; | ||
vec3 transmittance; | ||
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates. | ||
vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); | ||
vec2 refractionCoords = ndcPos.xy / ndcPos.w; | ||
refractionCoords += 1.0; | ||
refractionCoords /= 2.0; | ||
#ifdef USE_DISPERSION | ||
// Sample framebuffer to get pixel the refracted ray hits. | ||
vec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); | ||
float halfSpread = ( ior - 1.0 ) * 0.025 * dispersion; | ||
vec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread ); | ||
vec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); | ||
for ( int i = 0; i < 3; i ++ ) { | ||
vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix ); | ||
vec3 refractedRayExit = position + transmissionRay; | ||
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates. | ||
vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); | ||
vec2 refractionCoords = ndcPos.xy / ndcPos.w; | ||
refractionCoords += 1.0; | ||
refractionCoords /= 2.0; | ||
// Sample framebuffer to get pixel the refracted ray hits. | ||
vec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] ); | ||
transmittedLight[ i ] = transmissionSample[ i ]; | ||
transmittedLight.a += transmissionSample.a; | ||
transmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ]; | ||
} | ||
transmittedLight.a /= 3.0; | ||
#else | ||
vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); | ||
vec3 refractedRayExit = position + transmissionRay; | ||
// Project refracted vector on the framebuffer, while mapping to normalized device coordinates. | ||
vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); | ||
vec2 refractionCoords = ndcPos.xy / ndcPos.w; | ||
refractionCoords += 1.0; | ||
refractionCoords /= 2.0; | ||
// Sample framebuffer to get pixel the refracted ray hits. | ||
transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); | ||
transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ); | ||
#endif | ||
vec3 attenuatedColor = transmittance * transmittedLight.rgb; | ||
@@ -190,0 +224,0 @@ |
@@ -317,2 +317,3 @@ import { ShaderChunk } from './ShaderChunk.js'; | ||
clearcoatRoughnessMapTransform: { value: /*@__PURE__*/ new Matrix3() }, | ||
dispersion: { value: 0 }, | ||
iridescence: { value: 0 }, | ||
@@ -319,0 +320,0 @@ iridescenceMap: { value: null }, |
@@ -98,2 +98,6 @@ export const vertex = /* glsl */` | ||
#ifdef USE_DISPERSION | ||
uniform float dispersion; | ||
#endif | ||
#ifdef USE_IRIDESCENCE | ||
@@ -100,0 +104,0 @@ uniform float iridescence; |
@@ -29,5 +29,4 @@ import { BackSide, FrontSide, CubeUVReflectionMapping, SRGBTransfer } from '../../constants.js'; | ||
function render( renderList, scene ) { | ||
function getBackground( scene ) { | ||
let forceClear = false; | ||
let background = scene.isScene === true ? scene.background : null; | ||
@@ -42,2 +41,11 @@ | ||
return background; | ||
} | ||
function render( scene ) { | ||
let forceClear = false; | ||
const background = getBackground( scene ); | ||
if ( background === null ) { | ||
@@ -72,2 +80,8 @@ | ||
} | ||
function addToRenderList( renderList, scene ) { | ||
const background = getBackground( scene ); | ||
if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) { | ||
@@ -253,3 +267,4 @@ | ||
}, | ||
render: render | ||
render: render, | ||
addToRenderList: addToRenderList | ||
@@ -256,0 +271,0 @@ }; |
@@ -60,2 +60,37 @@ function WebGLBufferRenderer( gl, extensions, info ) { | ||
function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { | ||
if ( drawCount === 0 ) return; | ||
const extension = extensions.get( 'WEBGL_multi_draw' ); | ||
if ( extension === null ) { | ||
for ( let i = 0; i < starts.length; i ++ ) { | ||
renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); | ||
} | ||
} else { | ||
extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); | ||
let elementCount = 0; | ||
for ( let i = 0; i < drawCount; i ++ ) { | ||
elementCount += counts[ i ]; | ||
} | ||
for ( let i = 0; i < primcount.length; i ++ ) { | ||
info.update( elementCount, mode, primcount[ i ] ); | ||
} | ||
} | ||
} | ||
// | ||
@@ -67,2 +102,3 @@ | ||
this.renderMultiDraw = renderMultiDraw; | ||
this.renderMultiDrawInstances = renderMultiDrawInstances; | ||
@@ -69,0 +105,0 @@ } |
@@ -1,3 +0,5 @@ | ||
function WebGLCapabilities( gl, extensions, parameters ) { | ||
import { FloatType, HalfFloatType, RGBAFormat, UnsignedByteType } from '../../constants.js'; | ||
function WebGLCapabilities( gl, extensions, parameters, utils ) { | ||
let maxAnisotropy; | ||
@@ -25,2 +27,29 @@ | ||
function textureFormatReadable( textureFormat ) { | ||
if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function textureTypeReadable( textureType ) { | ||
const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has( 'EXT_color_buffer_half_float' ) || extensions.has( 'EXT_color_buffer_float' ) ); | ||
if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // Edge and Chrome Mac < 52 (#9513) | ||
textureType !== FloatType && ! halfFloatSupportedByExt ) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function getMaxPrecision( precision ) { | ||
@@ -89,2 +118,5 @@ | ||
textureFormatReadable: textureFormatReadable, | ||
textureTypeReadable: textureTypeReadable, | ||
precision: precision, | ||
@@ -91,0 +123,0 @@ logarithmicDepthBuffer: logarithmicDepthBuffer, |
@@ -69,2 +69,37 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) { | ||
function renderMultiDrawInstances( starts, counts, drawCount, primcount ) { | ||
if ( drawCount === 0 ) return; | ||
const extension = extensions.get( 'WEBGL_multi_draw' ); | ||
if ( extension === null ) { | ||
for ( let i = 0; i < starts.length; i ++ ) { | ||
renderInstances( starts[ i ] / bytesPerElement, counts[ i ], primcount[ i ] ); | ||
} | ||
} else { | ||
extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, type, starts, 0, primcount, 0, drawCount ); | ||
let elementCount = 0; | ||
for ( let i = 0; i < drawCount; i ++ ) { | ||
elementCount += counts[ i ]; | ||
} | ||
for ( let i = 0; i < primcount.length; i ++ ) { | ||
info.update( elementCount, mode, primcount[ i ] ); | ||
} | ||
} | ||
} | ||
// | ||
@@ -77,2 +112,3 @@ | ||
this.renderMultiDraw = renderMultiDraw; | ||
this.renderMultiDrawInstances = renderMultiDrawInstances; | ||
@@ -79,0 +115,0 @@ } |
@@ -473,2 +473,8 @@ import { BackSide } from '../../constants.js'; | ||
if ( material.dispersion > 0 ) { | ||
uniforms.dispersion.value = material.dispersion; | ||
} | ||
if ( material.iridescence > 0 ) { | ||
@@ -475,0 +481,0 @@ |
@@ -247,7 +247,3 @@ import { WebGLUniforms } from './WebGLUniforms.js'; | ||
const shaderChunkMap = new Map( [ | ||
[ 'encodings_fragment', 'colorspace_fragment' ], // @deprecated, r154 | ||
[ 'encodings_pars_fragment', 'colorspace_pars_fragment' ], // @deprecated, r154 | ||
[ 'output_fragment', 'opaque_fragment' ], // @deprecated, r154 | ||
] ); | ||
const shaderChunkMap = new Map(); | ||
@@ -783,2 +779,4 @@ function includeReplacer( match, include ) { | ||
parameters.dispersion ? '#define USE_DISPERSION' : '', | ||
parameters.iridescence ? '#define USE_IRIDESCENCE' : '', | ||
@@ -785,0 +783,0 @@ parameters.iridescenceMap ? '#define USE_IRIDESCENCEMAP' : '', |
@@ -132,2 +132,3 @@ import { BackSide, DoubleSide, CubeUVReflectionMapping, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping, NormalBlending, LinearSRGBColorSpace, SRGBTransfer } from '../../constants.js'; | ||
const HAS_CLEARCOAT = material.clearcoat > 0; | ||
const HAS_DISPERSION = material.dispersion > 0; | ||
const HAS_IRIDESCENCE = material.iridescence > 0; | ||
@@ -232,2 +233,4 @@ const HAS_SHEEN = material.sheen > 0; | ||
dispersion: HAS_DISPERSION, | ||
iridescence: HAS_IRIDESCENCE, | ||
@@ -513,2 +516,4 @@ iridescenceMap: HAS_IRIDESCENCEMAP, | ||
_programLayers.enable( 19 ); | ||
if ( parameters.dispersion ) | ||
_programLayers.enable( 20 ); | ||
@@ -515,0 +520,0 @@ array.push( _programLayers.mask ); |
@@ -10,4 +10,6 @@ import { WebGLLights } from './WebGLLights.js'; | ||
function init() { | ||
function init( camera ) { | ||
state.camera = camera; | ||
lightsArray.length = 0; | ||
@@ -46,5 +48,7 @@ shadowsArray.length = 0; | ||
camera: null, | ||
lights: lights, | ||
transmissionRenderTarget: null | ||
transmissionRenderTarget: {} | ||
}; | ||
@@ -51,0 +55,0 @@ |
@@ -15,3 +15,3 @@ import { FrontSide, BackSide, DoubleSide, NearestFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js'; | ||
function WebGLShadowMap( _renderer, _objects, _capabilities ) { | ||
function WebGLShadowMap( renderer, objects, capabilities ) { | ||
@@ -30,3 +30,3 @@ let _frustum = new Frustum(); | ||
_maxTextureSize = _capabilities.maxTextureSize; | ||
_maxTextureSize = capabilities.maxTextureSize; | ||
@@ -81,7 +81,7 @@ const shadowSide = { [ FrontSide ]: BackSide, [ BackSide ]: FrontSide, [ DoubleSide ]: DoubleSide }; | ||
const currentRenderTarget = _renderer.getRenderTarget(); | ||
const activeCubeFace = _renderer.getActiveCubeFace(); | ||
const activeMipmapLevel = _renderer.getActiveMipmapLevel(); | ||
const currentRenderTarget = renderer.getRenderTarget(); | ||
const activeCubeFace = renderer.getActiveCubeFace(); | ||
const activeMipmapLevel = renderer.getActiveMipmapLevel(); | ||
const _state = _renderer.state; | ||
const _state = renderer.state; | ||
@@ -160,4 +160,4 @@ // Set GL state for depth map. | ||
_renderer.setRenderTarget( shadow.map ); | ||
_renderer.clear(); | ||
renderer.setRenderTarget( shadow.map ); | ||
renderer.clear(); | ||
@@ -203,3 +203,3 @@ const viewportCount = shadow.getViewportCount(); | ||
_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); | ||
renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel ); | ||
@@ -210,3 +210,3 @@ }; | ||
const geometry = _objects.update( fullScreenMesh ); | ||
const geometry = objects.update( fullScreenMesh ); | ||
@@ -234,5 +234,5 @@ if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) { | ||
shadowMaterialVertical.uniforms.radius.value = shadow.radius; | ||
_renderer.setRenderTarget( shadow.mapPass ); | ||
_renderer.clear(); | ||
_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); | ||
renderer.setRenderTarget( shadow.mapPass ); | ||
renderer.clear(); | ||
renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null ); | ||
@@ -244,5 +244,5 @@ // horizontal pass | ||
shadowMaterialHorizontal.uniforms.radius.value = shadow.radius; | ||
_renderer.setRenderTarget( shadow.map ); | ||
_renderer.clear(); | ||
_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); | ||
renderer.setRenderTarget( shadow.map ); | ||
renderer.clear(); | ||
renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizontal, fullScreenMesh, null ); | ||
@@ -265,3 +265,3 @@ } | ||
if ( ( _renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || | ||
if ( ( renderer.localClippingEnabled && material.clipShadows === true && Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) || | ||
( material.displacementMap && material.displacementScale !== 0 ) || | ||
@@ -331,3 +331,3 @@ ( material.alphaMap && material.alphaTest > 0 ) || | ||
const materialProperties = _renderer.properties.get( result ); | ||
const materialProperties = renderer.properties.get( result ); | ||
materialProperties.light = light; | ||
@@ -353,3 +353,3 @@ | ||
const geometry = _objects.update( object ); | ||
const geometry = objects.update( object ); | ||
const material = object.material; | ||
@@ -370,7 +370,7 @@ | ||
object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); | ||
object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); | ||
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); | ||
renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); | ||
object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); | ||
object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, group ); | ||
@@ -385,7 +385,7 @@ } | ||
object.onBeforeShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); | ||
object.onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); | ||
_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); | ||
renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); | ||
object.onAfterShadow( _renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); | ||
object.onAfterShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial, null ); | ||
@@ -392,0 +392,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, RGB_ETC1_Format, DepthFormat, DepthStencilFormat, UnsignedIntType, UnsignedInt248Type, FloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, UnsignedByteType, NoColorSpace, LinearSRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare, SRGBTransfer, LinearTransfer } from '../../constants.js'; | ||
import { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedIntType, UnsignedInt248Type, FloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, UnsignedByteType, NoColorSpace, LinearSRGBColorSpace, NeverCompare, AlwaysCompare, LessCompare, LessEqualCompare, EqualCompare, GreaterEqualCompare, GreaterCompare, NotEqualCompare, SRGBTransfer, LinearTransfer } from '../../constants.js'; | ||
import { createElementNS } from '../../utils.js'; | ||
@@ -750,3 +750,3 @@ import { ColorManagement } from '../../math/ColorManagement.js'; | ||
const useTexStorage = ( texture.isVideoTexture !== true && glInternalFormat !== RGB_ETC1_Format ); | ||
const useTexStorage = ( texture.isVideoTexture !== true ); | ||
const allocateMemory = ( sourceProperties.__version === undefined ) || ( forceUpload === true ); | ||
@@ -2008,102 +2008,112 @@ const dataReady = source.dataReady; | ||
const invalidationArrayRead = []; | ||
const invalidationArrayDraw = []; | ||
function updateMultisampleRenderTarget( renderTarget ) { | ||
if ( ( renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) === false ) { | ||
if ( renderTarget.samples > 0 ) { | ||
const textures = renderTarget.textures; | ||
const width = renderTarget.width; | ||
const height = renderTarget.height; | ||
let mask = _gl.COLOR_BUFFER_BIT; | ||
const invalidationArray = []; | ||
const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; | ||
const renderTargetProperties = properties.get( renderTarget ); | ||
const isMultipleRenderTargets = ( textures.length > 1 ); | ||
if ( useMultisampledRTT( renderTarget ) === false ) { | ||
// If MRT we need to remove FBO attachments | ||
if ( isMultipleRenderTargets ) { | ||
const textures = renderTarget.textures; | ||
const width = renderTarget.width; | ||
const height = renderTarget.height; | ||
let mask = _gl.COLOR_BUFFER_BIT; | ||
const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; | ||
const renderTargetProperties = properties.get( renderTarget ); | ||
const isMultipleRenderTargets = ( textures.length > 1 ); | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
// If MRT we need to remove FBO attachments | ||
if ( isMultipleRenderTargets ) { | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, null ); | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, null, 0 ); | ||
} | ||
} | ||
} | ||
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
if ( renderTarget.resolveDepthBuffer ) { | ||
invalidationArray.push( _gl.COLOR_ATTACHMENT0 + i ); | ||
if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; | ||
if ( renderTarget.depthBuffer ) { | ||
// resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) | ||
invalidationArray.push( depthStyle ); | ||
if ( renderTarget.stencilBuffer && renderTarget.resolveStencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT; | ||
} | ||
} | ||
const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !== undefined ) ? renderTargetProperties.__ignoreDepthValues : false; | ||
if ( isMultipleRenderTargets ) { | ||
if ( ignoreDepthValues === false ) { | ||
_gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); | ||
if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT; | ||
const webglTexture = properties.get( textures[ i ] ).__webglTexture; | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); | ||
// resolving stencil is slow with a D3D backend. disable it for all transmission render targets (see #27799) | ||
} | ||
if ( renderTarget.stencilBuffer && renderTargetProperties.__isTransmissionRenderTarget !== true ) mask |= _gl.STENCIL_BUFFER_BIT; | ||
_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); | ||
} | ||
if ( supportsInvalidateFramebuffer === true ) { | ||
if ( isMultipleRenderTargets ) { | ||
invalidationArrayRead.length = 0; | ||
invalidationArrayDraw.length = 0; | ||
_gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); | ||
invalidationArrayRead.push( _gl.COLOR_ATTACHMENT0 + i ); | ||
} | ||
if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false ) { | ||
if ( ignoreDepthValues === true ) { | ||
invalidationArrayRead.push( depthStyle ); | ||
invalidationArrayDraw.push( depthStyle ); | ||
_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] ); | ||
_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); | ||
_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, invalidationArrayDraw ); | ||
} | ||
} | ||
if ( isMultipleRenderTargets ) { | ||
_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArrayRead ); | ||
const webglTexture = properties.get( textures[ i ] ).__webglTexture; | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 ); | ||
} | ||
} | ||
_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST ); | ||
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); | ||
if ( supportsInvalidateFramebuffer ) { | ||
// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments | ||
if ( isMultipleRenderTargets ) { | ||
_gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray ); | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
} | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); | ||
const webglTexture = properties.get( textures[ i ] ).__webglTexture; | ||
} | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); | ||
state.bindFramebuffer( _gl.READ_FRAMEBUFFER, null ); | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, null ); | ||
} | ||
// If MRT since pre-blit we removed the FBO we need to reconstruct the attachments | ||
if ( isMultipleRenderTargets ) { | ||
} | ||
for ( let i = 0; i < textures.length; i ++ ) { | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[ i ] ); | ||
} else { | ||
const webglTexture = properties.get( textures[ i ] ).__webglTexture; | ||
if ( renderTarget.depthBuffer && renderTarget.resolveDepthBuffer === false && supportsInvalidateFramebuffer ) { | ||
state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); | ||
_gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 + i, _gl.TEXTURE_2D, webglTexture, 0 ); | ||
const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT; | ||
_gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] ); | ||
} | ||
@@ -2113,4 +2123,2 @@ | ||
state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); | ||
} | ||
@@ -2117,0 +2125,0 @@ |
@@ -104,24 +104,6 @@ import { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, RGBA_BPTC_Format, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, NoColorSpace, SRGBTransfer, UnsignedInt5999Type, RGBFormat } from '../../constants.js'; | ||
// ETC1 | ||
// ETC | ||
if ( p === RGB_ETC1_Format ) { | ||
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { | ||
extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); | ||
if ( extension !== null ) { | ||
return extension.COMPRESSED_RGB_ETC1_WEBGL; | ||
} else { | ||
return null; | ||
} | ||
} | ||
// ETC2 | ||
if ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { | ||
extension = extensions.get( 'WEBGL_compressed_texture_etc' ); | ||
@@ -131,3 +113,3 @@ | ||
if ( p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; | ||
if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; | ||
if ( p === RGBA_ETC2_EAC_Format ) return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; | ||
@@ -134,0 +116,0 @@ |
@@ -364,3 +364,4 @@ import { ArrayCamera } from '../../cameras/ArrayCamera.js'; | ||
colorSpace: renderer.outputColorSpace, | ||
samples: attributes.antialias ? 4 : 0 | ||
samples: attributes.antialias ? 4 : 0, | ||
resolveDepthBuffer: ( glProjLayer.ignoreDepthValues === false ) | ||
}; | ||
@@ -385,5 +386,2 @@ | ||
const renderTargetProperties = renderer.properties.get( newRenderTarget ); | ||
renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues; | ||
} | ||
@@ -390,0 +388,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
21944326
982
264820