EnvironmentLightNode.js 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import LightingNode from './LightingNode.js';
  2. import ContextNode from '../core/ContextNode.js';
  3. import MaxMipLevelNode from '../utils/MaxMipLevelNode.js';
  4. //import ReflectNode from '../accessors/ReflectNode.js';
  5. import { ShaderNode, float, add, mul, div, log2, clamp, roughness, reflect, mix, vec3, positionViewDirection, negate, normalize, transformedNormalView, transformedNormalWorld, transformDirection, cameraViewMatrix } from '../shadernode/ShaderNodeElements.js';
  6. // taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
  7. const getSpecularMIPLevel = new ShaderNode( ( { texture, levelNode } ) => {
  8. const maxMIPLevelScalar = new MaxMipLevelNode( texture );
  9. const sigma = div( mul( Math.PI, mul( levelNode, levelNode ) ), add( 1.0, levelNode ) );
  10. const desiredMIPLevel = add( maxMIPLevelScalar, log2( sigma ) );
  11. return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
  12. } );
  13. /*
  14. const getMaxMIPLevel = new ShaderNode( ( { texture } ) => {
  15. return new MaxMipLevelNode( texture );
  16. } );
  17. */
  18. class EnvironmentLightNode extends LightingNode {
  19. constructor( envNode = null ) {
  20. super();
  21. this.envNode = envNode;
  22. }
  23. generate( builder ) {
  24. const envNode = this.envNode;
  25. const flipNormalWorld = vec3( negate( transformedNormalWorld.x ), transformedNormalWorld.yz );
  26. let reflectVec = reflect( negate( positionViewDirection ), transformedNormalView );
  27. reflectVec = normalize( mix( reflectVec, transformedNormalView, mul( roughness, roughness ) ) );
  28. reflectVec = transformDirection( reflectVec, cameraViewMatrix );
  29. reflectVec = vec3( negate( reflectVec.x ), reflectVec.yz );
  30. //reflectVec = normalize( mix( new ReflectNode(), flipNormalWorld, mul( roughness, roughness ) ) );
  31. const radianceContext = new ContextNode( envNode, {
  32. tempRead: false,
  33. uvNode: reflectVec,
  34. levelNode: roughness,
  35. levelShaderNode: getSpecularMIPLevel
  36. } );
  37. const irradianceContext = new ContextNode( envNode, {
  38. tempRead: false,
  39. uvNode: flipNormalWorld,
  40. levelNode: float( 1 ),
  41. levelShaderNode: getSpecularMIPLevel
  42. } );
  43. builder.context.radiance.add( radianceContext );
  44. builder.context.iblIrradiance.add( mul( Math.PI, irradianceContext ) );
  45. }
  46. }
  47. export default EnvironmentLightNode;