NormalMapNode.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. * @author sunag / http://www.sunag.com.br/
  3. */
  4. import { TempNode } from '../core/TempNode.js';
  5. import { Vector2Node } from '../inputs/Vector2Node.js';
  6. import { FunctionNode } from '../core/FunctionNode.js';
  7. import { UVNode } from '../accessors/UVNode.js';
  8. import { NormalNode } from '../accessors/NormalNode.js';
  9. import { PositionNode } from '../accessors/PositionNode.js';
  10. function NormalMapNode( value, scale ) {
  11. TempNode.call( this, 'v3' );
  12. this.value = value;
  13. this.scale = scale || new Vector2Node( 1, 1 );
  14. };
  15. NormalMapNode.Nodes = (function() {
  16. var perturbNormal2Arb = new FunctionNode( [
  17. // Per-Pixel Tangent Space Normal Mapping
  18. // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
  19. "vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 mUv, vec2 normalScale ) {",
  20. // Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
  21. " vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );",
  22. " vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );",
  23. " vec2 st0 = dFdx( mUv.st );",
  24. " vec2 st1 = dFdy( mUv.st );",
  25. " float scale = sign( st1.t * st0.s - st0.t * st1.s );", // we do not care about the magnitude
  26. " vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );",
  27. " vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );",
  28. " vec3 N = normalize( surf_norm );",
  29. " mat3 tsn = mat3( S, T, N );",
  30. " vec3 mapN = map * 2.0 - 1.0;",
  31. " mapN.xy *= normalScale;",
  32. " mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );",
  33. " return normalize( tsn * mapN );",
  34. "}"
  35. ].join( "\n" ), null, { derivatives: true } );
  36. return {
  37. perturbNormal2Arb: perturbNormal2Arb
  38. };
  39. })();
  40. NormalMapNode.prototype = Object.create( TempNode.prototype );
  41. NormalMapNode.prototype.constructor = NormalMapNode;
  42. NormalMapNode.prototype.nodeType = "NormalMap";
  43. NormalMapNode.prototype.generate = function ( builder, output ) {
  44. if ( builder.isShader( 'fragment' ) ) {
  45. var perturbNormal2Arb = builder.include( NormalMapNode.Nodes.perturbNormal2Arb );
  46. this.normal = this.normal || new NormalNode( NormalNode.VIEW );
  47. this.position = this.position || new PositionNode( PositionNode.VIEW );
  48. this.uv = this.uv || new UVNode();
  49. return builder.format( perturbNormal2Arb + '( -' + this.position.build( builder, 'v3' ) + ', ' +
  50. this.normal.build( builder, 'v3' ) + ', ' +
  51. this.value.build( builder, 'v3' ) + ', ' +
  52. this.uv.build( builder, 'v2' ) + ', ' +
  53. this.scale.build( builder, 'v2' ) + ' )', this.getType( builder ), output );
  54. } else {
  55. console.warn( "THREE.NormalMapNode is not compatible with " + builder.shader + " shader." );
  56. return builder.format( 'vec3( 0.0 )', this.getType( builder ), output );
  57. }
  58. };
  59. NormalMapNode.prototype.copy = function ( source ) {
  60. TempNode.prototype.copy.call( this, source );
  61. this.value = source.value;
  62. this.scale = source.scale;
  63. };
  64. NormalMapNode.prototype.toJSON = function ( meta ) {
  65. var data = this.getJSONNode( meta );
  66. if ( ! data ) {
  67. data = this.createJSONNode( meta );
  68. data.value = this.value.toJSON( meta ).uuid;
  69. data.scale = this.scale.toJSON( meta ).uuid;
  70. }
  71. return data;
  72. };
  73. export { NormalMapNode };