AnalyticLightNode.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import LightingNode from './LightingNode.js';
  2. import { NodeUpdateType } from '../core/constants.js';
  3. import { uniform } from '../core/UniformNode.js';
  4. import { addNodeClass } from '../core/Node.js';
  5. import { vec3 } from '../shadernode/ShaderNode.js';
  6. import { reference } from '../accessors/ReferenceNode.js';
  7. import { texture } from '../accessors/TextureNode.js';
  8. import { positionWorld } from '../accessors/PositionNode.js';
  9. //import { step } from '../math/MathNode.js';
  10. import { cond } from '../math/CondNode.js';
  11. import MeshBasicNodeMaterial from '../materials/MeshBasicNodeMaterial.js';
  12. import { Color, DepthTexture, NearestFilter } from 'three';
  13. let depthMaterial = null;
  14. class AnalyticLightNode extends LightingNode {
  15. constructor( light = null ) {
  16. super();
  17. this.updateType = NodeUpdateType.FRAME;
  18. this.light = light;
  19. this.rtt = null;
  20. this.shadowNode = null;
  21. this.color = new Color();
  22. this.colorNode = uniform( this.color );
  23. }
  24. getHash( /*builder*/ ) {
  25. return this.light.uuid;
  26. }
  27. constructShadow( builder ) {
  28. let shadowNode = this.shadowNode;
  29. if ( shadowNode === null ) {
  30. if ( depthMaterial === null ) depthMaterial = new MeshBasicNodeMaterial();
  31. const shadow = this.light.shadow;
  32. const rtt = builder.getRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
  33. const depthTexture = new DepthTexture();
  34. depthTexture.minFilter = NearestFilter;
  35. depthTexture.magFilter = NearestFilter;
  36. depthTexture.image.width = shadow.mapSize.width;
  37. depthTexture.image.height = shadow.mapSize.height;
  38. //depthTexture.compareFunction = THREE.LessCompare;
  39. rtt.depthTexture = depthTexture;
  40. shadow.camera.updateProjectionMatrix();
  41. //
  42. const bias = reference( 'bias', 'float', shadow );
  43. //const diffuseFactor = normalView.dot( objectViewPosition( this.light ).sub( positionView ).normalize().negate() );
  44. //bias = mix( bias, 0, diffuseFactor );
  45. let shadowCoord = uniform( shadow.matrix ).mul( positionWorld );
  46. shadowCoord = shadowCoord.xyz.div( shadowCoord.w );
  47. shadowCoord = vec3(
  48. shadowCoord.x,
  49. shadowCoord.y.oneMinus(),
  50. shadowCoord.z
  51. );
  52. // @TODO: Optimize using WebGPU compare-sampler
  53. let depth = texture( depthTexture, shadowCoord.xy );
  54. depth = depth.mul( .5 ).add( .5 ).add( bias );
  55. shadowNode = cond( shadowCoord.z.lessThan( depth ).or( shadowCoord.y.lessThan( .000001 ) /*@TODO: find the cause and remove it soon */ ), 1, 0 );
  56. //shadowNode = step( shadowCoord.z, depth );
  57. //
  58. this.rtt = rtt;
  59. this.colorNode = this.colorNode.mul( shadowNode );
  60. this.shadowNode = shadowNode;
  61. //
  62. this.updateBeforeType = NodeUpdateType.RENDER;
  63. }
  64. }
  65. construct( builder ) {
  66. if ( this.light.castShadow ) this.constructShadow( builder );
  67. }
  68. updateShadow( frame ) {
  69. const { rtt, light } = this;
  70. const { renderer, scene } = frame;
  71. scene.overrideMaterial = depthMaterial;
  72. rtt.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height );
  73. light.shadow.updateMatrices( light );
  74. renderer.setRenderTarget( rtt );
  75. renderer.render( scene, light.shadow.camera );
  76. renderer.setRenderTarget( null );
  77. scene.overrideMaterial = null;
  78. }
  79. updateBefore( frame ) {
  80. const { light } = this;
  81. if ( light.castShadow ) this.updateShadow( frame );
  82. }
  83. update( /*frame*/ ) {
  84. const { light } = this;
  85. this.color.copy( light.color ).multiplyScalar( light.intensity );
  86. }
  87. }
  88. export default AnalyticLightNode;
  89. addNodeClass( AnalyticLightNode );