NormalMapNode.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import TempNode from '../core/TempNode.js';
  2. import { normalView, transformNormalToView } from '../accessors/Normal.js';
  3. import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
  4. import { nodeProxy, vec3 } from '../tsl/TSLBase.js';
  5. import { TangentSpaceNormalMap, ObjectSpaceNormalMap, NoNormalPacking, NormalRGPacking, NormalGAPacking } from '../../constants.js';
  6. import { directionToFaceDirection } from './FrontFacingNode.js';
  7. import { unpackNormal } from '../utils/Packing.js';
  8. import { error } from '../../utils.js';
  9. /**
  10. * This class can be used for applying normals maps to materials.
  11. *
  12. * ```js
  13. * material.normalNode = normalMap( texture( normalTex ) );
  14. * ```
  15. *
  16. * @augments TempNode
  17. */
  18. class NormalMapNode extends TempNode {
  19. static get type() {
  20. return 'NormalMapNode';
  21. }
  22. /**
  23. * Constructs a new normal map node.
  24. *
  25. * @param {Node<vec3>} node - Represents the normal map data.
  26. * @param {?Node<vec2>} [scaleNode=null] - Controls the intensity of the effect.
  27. */
  28. constructor( node, scaleNode = null ) {
  29. super( 'vec3' );
  30. /**
  31. * Represents the normal map data.
  32. *
  33. * @type {Node<vec3>}
  34. */
  35. this.node = node;
  36. /**
  37. * Controls the intensity of the effect.
  38. *
  39. * @type {?Node<vec2>}
  40. * @default null
  41. */
  42. this.scaleNode = scaleNode;
  43. /**
  44. * The normal map type.
  45. *
  46. * @type {(TangentSpaceNormalMap|ObjectSpaceNormalMap)}
  47. * @default TangentSpaceNormalMap
  48. */
  49. this.normalMapType = TangentSpaceNormalMap;
  50. /**
  51. * Controls how to unpack the sampled normal map values.
  52. *
  53. * @type {string}
  54. * @default NoNormalPacking
  55. */
  56. this.unpackNormalMode = NoNormalPacking;
  57. }
  58. setup( { material } ) {
  59. const { normalMapType, scaleNode, unpackNormalMode } = this;
  60. let normalMap = this.node.mul( 2.0 ).sub( 1.0 );
  61. if ( normalMapType === TangentSpaceNormalMap ) {
  62. if ( unpackNormalMode === NormalRGPacking ) {
  63. normalMap = unpackNormal( normalMap.xy );
  64. } else if ( unpackNormalMode === NormalGAPacking ) {
  65. normalMap = unpackNormal( normalMap.yw );
  66. } else if ( unpackNormalMode !== NoNormalPacking ) {
  67. console.error( `THREE.NodeMaterial: Unexpected unpack normal mode: ${ unpackNormalMode }` );
  68. }
  69. } else {
  70. if ( unpackNormalMode !== NoNormalPacking ) {
  71. console.error( `THREE.NodeMaterial: Normal map type '${ normalMapType }' is not compatible with unpack normal mode '${ unpackNormalMode }'` );
  72. }
  73. }
  74. if ( scaleNode !== null ) {
  75. let scale = scaleNode;
  76. if ( material.flatShading === true ) {
  77. scale = directionToFaceDirection( scale );
  78. }
  79. normalMap = vec3( normalMap.xy.mul( scale ), normalMap.z );
  80. }
  81. let output = null;
  82. if ( normalMapType === ObjectSpaceNormalMap ) {
  83. output = transformNormalToView( normalMap );
  84. } else if ( normalMapType === TangentSpaceNormalMap ) {
  85. output = TBNViewMatrix.mul( normalMap ).normalize();
  86. } else {
  87. error( `NodeMaterial: Unsupported normal map type: ${ normalMapType }` );
  88. output = normalView; // Fallback to default normal view
  89. }
  90. return output;
  91. }
  92. }
  93. export default NormalMapNode;
  94. /**
  95. * TSL function for creating a normal map node.
  96. *
  97. * @tsl
  98. * @function
  99. * @param {Node<vec3>} node - Represents the normal map data.
  100. * @param {?Node<vec2>} [scaleNode=null] - Controls the intensity of the effect.
  101. * @returns {NormalMapNode}
  102. */
  103. export const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ).setParameterLength( 1, 2 );
粤ICP备19079148号