You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
2.2 KiB

2 years ago
import LightingNode from './LightingNode.js';
import ContextNode from '../core/ContextNode.js';
import MaxMipLevelNode from '../utils/MaxMipLevelNode.js';
import { ShaderNode, float, add, mul, div, log2, clamp, roughness, reflect, mix, positionViewDirection, negate, normalize, transformedNormalView, transformedNormalWorld, transformDirection, cameraViewMatrix } from '../shadernode/ShaderNodeElements.js';
// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
const getSpecularMIPLevel = new ShaderNode( ( { texture, levelNode } ) => {
const maxMIPLevelScalar = new MaxMipLevelNode( texture );
const sigma = div( mul( Math.PI, mul( levelNode, levelNode ) ), add( 1.0, levelNode ) );
const desiredMIPLevel = add( maxMIPLevelScalar, log2( sigma ) );
return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
} );
class EnvironmentNode extends LightingNode {
constructor( envNode = null ) {
super();
this.envNode = envNode;
}
construct( builder ) {
const envNode = this.envNode;
const properties = builder.getNodeProperties( this );
let reflectVec = reflect( negate( positionViewDirection ), transformedNormalView );
reflectVec = normalize( mix( reflectVec, transformedNormalView, mul( roughness, roughness ) ) );
reflectVec = transformDirection( reflectVec, cameraViewMatrix );
const radianceContext = new ContextNode( envNode, {
tempRead: false,
uvNode: reflectVec,
levelNode: roughness,
levelShaderNode: getSpecularMIPLevel
} );
const irradianceContext = new ContextNode( envNode, {
tempRead: false,
uvNode: transformedNormalWorld,
levelNode: float( 1 ),
levelShaderNode: getSpecularMIPLevel
} );
// it's used to cache the construct only if necessary: See `CubeTextureNode.getConstructReference()`
radianceContext.context.environmentContext = radianceContext;
irradianceContext.context.environmentContext = irradianceContext;
builder.context.radiance.add( radianceContext );
builder.context.iblIrradiance.add( mul( Math.PI, irradianceContext ) );
properties.radianceContext = radianceContext;
properties.irradianceContext = irradianceContext;
}
}
export default EnvironmentNode;