ViewportDepthNode.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import Node, { addNodeClass } from '../core/Node.js';
  2. import { nodeImmutable, nodeProxy } from '../shadernode/ShaderNode.js';
  3. import { cameraNear, cameraFar } from '../accessors/CameraNode.js';
  4. import { positionView } from '../accessors/PositionNode.js';
  5. import { viewportDepthTexture } from './ViewportDepthTextureNode.js';
  6. class ViewportDepthNode extends Node {
  7. constructor( scope, valueNode = null ) {
  8. super( 'float' );
  9. this.scope = scope;
  10. this.valueNode = valueNode;
  11. this.isViewportDepthNode = true;
  12. }
  13. generate( builder ) {
  14. const { scope } = this;
  15. if ( scope === ViewportDepthNode.DEPTH ) {
  16. return builder.getFragDepth();
  17. }
  18. return super.generate( builder );
  19. }
  20. setup( { camera } ) {
  21. const { scope } = this;
  22. const texture = this.valueNode;
  23. let node = null;
  24. if ( scope === ViewportDepthNode.DEPTH ) {
  25. if ( texture !== null ) {
  26. node = depthBase().assign( texture );
  27. } else {
  28. if ( camera.isPerspectiveCamera ) {
  29. node = viewZToPerspectiveDepth( positionView.z, cameraNear, cameraFar );
  30. } else {
  31. node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar );
  32. }
  33. }
  34. } else if ( scope === ViewportDepthNode.LINEAR_DEPTH ) {
  35. if ( texture !== null ) {
  36. if ( camera.isPerspectiveCamera ) {
  37. const viewZ = perspectiveDepthToViewZ( texture, cameraNear, cameraFar );
  38. node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );
  39. } else {
  40. node = texture;
  41. }
  42. } else {
  43. node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar );
  44. }
  45. }
  46. return node;
  47. }
  48. }
  49. // NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera
  50. // -near maps to 0; -far maps to 1
  51. export const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) );
  52. // maps orthographic depth in [ 0, 1 ] to viewZ
  53. export const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near );
  54. // NOTE: https://twitter.com/gonnavis/status/1377183786949959682
  55. // -near maps to 0; -far maps to 1
  56. export const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) );
  57. // maps perspective depth in [ 0, 1 ] to viewZ
  58. export const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) );
  59. ViewportDepthNode.DEPTH = 'depth';
  60. ViewportDepthNode.LINEAR_DEPTH = 'linearDepth';
  61. export default ViewportDepthNode;
  62. const depthBase = nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH );
  63. export const depth = nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH );
  64. export const linearDepth = nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH );
  65. export const viewportLinearDepth = linearDepth( viewportDepthTexture() );
  66. depth.assign = ( value ) => depthBase( value );
  67. addNodeClass( 'ViewportDepthNode', ViewportDepthNode );