three
Version:
JavaScript 3D library
137 lines (81 loc) • 3.07 kB
JavaScript
import LightingNode from './LightingNode.js';
import { cache } from '../core/CacheNode.js';
import { context } from '../core/ContextNode.js';
import { roughness } from '../core/PropertyNode.js';
import { equirectUV } from '../utils/EquirectUVNode.js';
import { specularMIPLevel } from '../utils/SpecularMIPLevelNode.js';
import { cameraViewMatrix } from '../accessors/CameraNode.js';
import { transformedNormalView, transformedNormalWorld } from '../accessors/NormalNode.js';
import { positionViewDirection } from '../accessors/PositionNode.js';
import { addNodeClass } from '../core/Node.js';
import { float, vec2 } from '../shadernode/ShaderNode.js';
class EnvironmentNode extends LightingNode {
constructor( envNode = null ) {
super();
this.envNode = envNode;
}
construct( builder ) {
const envNode = this.envNode;
const properties = builder.getNodeProperties( this );
let reflectVec;
let radianceTextureUVNode;
let irradianceTextureUVNode;
const radianceContext = context( envNode, {
getUVNode: ( textureNode ) => {
let node = null;
if ( reflectVec === undefined ) {
reflectVec = positionViewDirection.negate().reflect( transformedNormalView );
reflectVec = roughness.mul( roughness ).mix( reflectVec, transformedNormalView ).normalize();
reflectVec = reflectVec.transformDirection( cameraViewMatrix );
}
if ( textureNode.isCubeTextureNode ) {
node = reflectVec;
} else if ( textureNode.isTextureNode ) {
if ( radianceTextureUVNode === undefined ) {
// @TODO: Needed PMREM
radianceTextureUVNode = equirectUV( reflectVec );
}
node = radianceTextureUVNode;
}
return node;
},
getSamplerLevelNode: () => {
return roughness;
},
getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => {
return specularMIPLevel( textureNode, levelNode );
}
} );
const irradianceContext = context( envNode, {
getUVNode: ( textureNode ) => {
let node = null;
if ( textureNode.isCubeTextureNode ) {
node = transformedNormalWorld;
} else if ( textureNode.isTextureNode ) {
if ( irradianceTextureUVNode === undefined ) {
// @TODO: Needed PMREM
irradianceTextureUVNode = equirectUV( transformedNormalWorld );
irradianceTextureUVNode = vec2( irradianceTextureUVNode.x, irradianceTextureUVNode.y.oneMinus() );
}
node = irradianceTextureUVNode;
}
return node;
},
getSamplerLevelNode: () => {
return float( 1 );
},
getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => {
return specularMIPLevel( textureNode, levelNode );
}
} );
//
const isolateRadianceFlowContext = cache( radianceContext );
//
builder.context.radiance.addAssign( isolateRadianceFlowContext );
builder.context.iblIrradiance.addAssign( irradianceContext.mul( Math.PI ) );
properties.radianceContext = isolateRadianceFlowContext;
properties.irradianceContext = irradianceContext;
}
}
export default EnvironmentNode;
addNodeClass( EnvironmentNode );