diff --git a/examples/jsm/nodes/core/FunctionNode.js b/examples/jsm/nodes/core/FunctionNode.js index 23d9d5cfa9eb57..32403c57edc201 100644 --- a/examples/jsm/nodes/core/FunctionNode.js +++ b/examples/jsm/nodes/core/FunctionNode.js @@ -12,6 +12,7 @@ var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s*\((.*?)\)/i, function FunctionNode( src, includes, extensions, keywords, type ) { this.isMethod = type === undefined; + this.isInterface = false; TempNode.call( this, type ); @@ -139,7 +140,11 @@ FunctionNode.prototype.generate = function ( builder, output ) { } else if ( this.isMethod ) { - builder.include( this, false, src ); + if ( ! this.isInterface ) { + + builder.include( this, false, src ); + + } return this.name; @@ -181,7 +186,7 @@ FunctionNode.prototype.parse = function ( src, includes, extensions, keywords ) var qualifier = inputs[ i ++ ]; var type, name; - if ( qualifier == 'in' || qualifier == 'out' || qualifier == 'inout' ) { + if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) { type = inputs[ i ++ ]; @@ -204,6 +209,8 @@ FunctionNode.prototype.parse = function ( src, includes, extensions, keywords ) } + this.isInterface = this.src.indexOf('{') === -1; + } else { this.type = ''; diff --git a/examples/jsm/nodes/materials/nodes/StandardNode.js b/examples/jsm/nodes/materials/nodes/StandardNode.js index 8159cbaa909346..e3e71d355b88c4 100644 --- a/examples/jsm/nodes/materials/nodes/StandardNode.js +++ b/examples/jsm/nodes/materials/nodes/StandardNode.js @@ -34,8 +34,6 @@ StandardNode.prototype.build = function ( builder ) { builder.define( this.clearCoat || this.clearCoatRoughness ? 'PHYSICAL' : 'STANDARD' ); - if ( this.energyPreservation ) builder.define( 'ENERGY_PRESERVATION' ); - builder.requires.lights = true; builder.extensions.shaderTextureLOD = true; diff --git a/examples/jsm/nodes/misc/TextureCubeNode.js b/examples/jsm/nodes/misc/TextureCubeNode.js index 14dc2fd1422429..b318b57ef94c08 100644 --- a/examples/jsm/nodes/misc/TextureCubeNode.js +++ b/examples/jsm/nodes/misc/TextureCubeNode.js @@ -11,17 +11,19 @@ import { NormalNode } from '../accessors/NormalNode.js'; import { ColorSpaceNode } from '../utils/ColorSpaceNode.js'; import { BlinnExponentToRoughnessNode } from '../bsdfs/BlinnExponentToRoughnessNode.js'; -function TextureCubeNode( value, textureSize ) { +function TextureCubeNode( value, textureSize, uv, bias ) { TempNode.call( this, 'v4' ); this.value = value; this.textureSize = textureSize || new FloatNode( 1024 ); + this.uv = uv || new ReflectNode( ReflectNode.VECTOR ); + this.bias = bias || new BlinnExponentToRoughnessNode(); this.radianceCache = { uv: new TextureCubeUVNode( - new ReflectNode( ReflectNode.VECTOR ), + this.uv, this.textureSize, - new BlinnExponentToRoughnessNode() + this.bias ) }; this.irradianceCache = { uv: new TextureCubeUVNode( diff --git a/examples/webgl_materials_nodes.html b/examples/webgl_materials_nodes.html index e8569fb63d3078..9fef823e39f39a 100644 --- a/examples/webgl_materials_nodes.html +++ b/examples/webgl_materials_nodes.html @@ -71,63 +71,56 @@ } - var cubemap = function () { + var premTexture, pmremCube, pmremGenerator, pmremCubeUVPacker, premSize = 1024; - var path = "textures/cube/Park2/"; - var format = '.jpg'; - var urls = [ - path + 'posx' + format, path + 'negx' + format, - path + 'posy' + format, path + 'negy' + format, - path + 'posz' + format, path + 'negz' + format - ]; + function updatePREM( textureCube ) { - var textureCube = new THREE.CubeTextureLoader().load( urls ); - textureCube.format = THREE.RGBFormat; + pmremCube = pmremCube || textureCube; - library[ textureCube.uuid ] = textureCube; + if ( ! pmremCube || ! renderer ) return; - return textureCube; + var minFilter = pmremCube.minFilter; + var magFilter = pmremCube.magFilter; + var generateMipmaps = pmremCube.generateMipmaps; - }(); + pmremGenerator = new PMREMGenerator( pmremCube, undefined, premSize / 4 ); + pmremGenerator.update( renderer ); - function generatePREM( cubeMap, textureSize ) { + pmremCubeUVPacker = new PMREMCubeUVPacker( pmremGenerator.cubeLods ); + pmremCubeUVPacker.update( renderer ); - textureSize = textureSize || 1024; + pmremCube.minFilter = minFilter; + pmremCube.magFilter = magFilter; + pmremCube.generateMipmaps = pmremCube.generateMipmaps; + pmremCube.needsUpdate = true; - var pmremGenerator = new PMREMGenerator( cubeMap, undefined, textureSize / 4 ); - pmremGenerator.update( renderer ); + premTexture = pmremCubeUVPacker.CubeUVRenderTarget.texture - var pmremCubeUVPacker = new PMREMCubeUVPacker( pmremGenerator.cubeLods ); - pmremCubeUVPacker.update( renderer ); + library[ premTexture.uuid ] = premTexture; pmremGenerator.dispose(); pmremCubeUVPacker.dispose(); - return pmremCubeUVPacker.CubeUVRenderTarget.texture; - } - var premTexture; - - function getPREM( callback, textureSize ) { - - if ( premTexture ) return callback( premTexture ); - - var hdrUrls = [ 'px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr' ]; - var hdrCubeMap = new HDRCubeTextureLoader() - .setPath( './textures/cube/pisaHDR/' ) - .setDataType( THREE.UnsignedByteType ) - .load( hdrUrls, function () { + var cubemap = function () { - premTexture = generatePREM( hdrCubeMap, textureSize ); + var path = "textures/cube/Park2/"; + var format = '.jpg'; + var urls = [ + path + 'posx' + format, path + 'negx' + format, + path + 'posy' + format, path + 'negy' + format, + path + 'posz' + format, path + 'negz' + format + ]; - library[ premTexture.uuid ] = premTexture; + var textureCube = new THREE.CubeTextureLoader().load( urls, updatePREM ); + textureCube.format = THREE.RGBFormat; - callback( premTexture ); + library[ textureCube.uuid ] = textureCube; - } ); + return textureCube; - } + }(); window.addEventListener( 'load', init ); @@ -176,6 +169,8 @@ library[ camera.uuid ] = camera; library[ mesh.uuid ] = mesh; + updatePREM(); + window.addEventListener( 'resize', onWindowResize, false ); updateMaterial(); @@ -226,6 +221,7 @@ 'adv / expression': 'expression', 'adv / sss': 'sss', 'adv / translucent': 'translucent', + 'adv / bias': 'bias', 'node / position': 'node-position', 'node / normal': 'node-normal', 'node / reflect': 'node-reflect', @@ -504,14 +500,8 @@ mtl.normal = new Nodes.NormalMapNode( new Nodes.TextureNode( getTexture( "grassNormal" ) ) ); mtl.normal.scale = normalMask; - getPREM(function(texture) { - - var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( texture ) ); - - mtl.environment = new Nodes.OperatorNode( envNode, intensity, Nodes.OperatorNode.MUL ); - mtl.needsUpdate = true; - - }); + var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( premTexture ) ); + mtl.environment = new Nodes.OperatorNode( envNode, intensity, Nodes.OperatorNode.MUL ); // GUI @@ -587,18 +577,13 @@ mtl.normal = new Nodes.NormalMapNode( new Nodes.TextureNode( getTexture( "grassNormal" ) ) ); mtl.normal.scale = normalScale; - getPREM(function(texture) { - - var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( texture ) ); + var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( premTexture ) ); - var subSlotNode = new Nodes.SubSlotNode(); - subSlotNode.slots['radiance'] = new Nodes.OperatorNode( radiance, envNode, Nodes.OperatorNode.MUL ); - subSlotNode.slots['irradiance'] = new Nodes.OperatorNode( irradiance, envNode, Nodes.OperatorNode.MUL ); + var subSlotNode = new Nodes.SubSlotNode(); + subSlotNode.slots['radiance'] = new Nodes.OperatorNode( radiance, envNode, Nodes.OperatorNode.MUL ); + subSlotNode.slots['irradiance'] = new Nodes.OperatorNode( irradiance, envNode, Nodes.OperatorNode.MUL ); - mtl.environment = subSlotNode; - mtl.needsUpdate = true; - - }); + mtl.environment = subSlotNode // GUI @@ -2483,6 +2468,71 @@ break; + case 'bias': + + // PREREQUISITES + + var image = cubemap.image[ 0 ]; + var maxMIPLevel = image !== undefined ? Math.log( Math.max( image.width, image.height ) ) * Math.LOG2E : 0; + + // MATERIAL + + var bias = new Nodes.FloatNode( .5 ); + var mipsBias = new Nodes.OperatorNode( bias, new Nodes.FloatNode( maxMIPLevel ), Nodes.OperatorNode.MUL ); + + mtl = new Nodes.PhongNodeMaterial(); + mtl.color.value.setHex( 0xFFFFFF ); + + function biasMode( val ) { + + switch( val ) { + + case 'prem': + + mtl.color = new Nodes.TextureCubeNode( new Nodes.TextureNode( premTexture ), undefined, undefined, bias ); + + break; + + case 'lod': + + var textureCubeFunction = new Nodes.FunctionNode( 'vec4 textureCubeLodEXT( samplerCube texture, vec3 uv, float bias );', undefined, { shaderTextureLOD: true } ); + + mtl.color = new Nodes.FunctionCallNode( textureCubeFunction, [ new Nodes.CubeTextureNode( cubemap ), new Nodes.ReflectNode(), mipsBias ] ); + + break; + + case 'basic': + + var textureCubeFunction = new Nodes.FunctionNode( 'vec4 textureCube( samplerCube texture, vec3 uv, float bias );' ); + + mtl.color = new Nodes.FunctionCallNode( textureCubeFunction, [ new Nodes.CubeTextureNode( cubemap ), new Nodes.ReflectNode(), mipsBias ] ); + + break; + + } + + mtl.needsUpdate = true; + + } + + biasMode( 'prem' ); + + // GUI + + addGui( 'scope', { + PREM: 'prem', + LOD: 'lod', + BASIC: 'basic' + }, biasMode ); + + addGui( 'bias', bias.value, function ( val ) { + + bias.value = val; + + }, false, 0, 1 ); + + break; + case 'node-position': // MATERIAL