| |
| |
| |
|
|
| import { TempNode } from '../core/TempNode.js'; |
| import { Vector2Node } from '../inputs/Vector2Node.js'; |
| import { FunctionNode } from '../core/FunctionNode.js'; |
| import { UVNode } from '../accessors/UVNode.js'; |
| import { NormalNode } from '../accessors/NormalNode.js'; |
| import { PositionNode } from '../accessors/PositionNode.js'; |
|
|
| function NormalMapNode( value, scale ) { |
|
|
| TempNode.call( this, 'v3' ); |
|
|
| this.value = value; |
| this.scale = scale || new Vector2Node( 1, 1 ); |
|
|
| } |
|
|
| NormalMapNode.Nodes = ( function () { |
|
|
| var perturbNormal2Arb = new FunctionNode( [ |
|
|
| |
| |
|
|
| "vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 mUv, vec2 normalScale ) {", |
|
|
| |
|
|
| " vec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );", |
| " vec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );", |
| " vec2 st0 = dFdx( mUv.st );", |
| " vec2 st1 = dFdy( mUv.st );", |
|
|
| " float scale = sign( st1.t * st0.s - st0.t * st1.s );", |
|
|
| " vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );", |
| " vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );", |
| " vec3 N = normalize( surf_norm );", |
| " mat3 tsn = mat3( S, T, N );", |
|
|
| " vec3 mapN = map * 2.0 - 1.0;", |
|
|
| " mapN.xy *= normalScale;", |
| " mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );", |
|
|
| " return normalize( tsn * mapN );", |
|
|
| "}" |
|
|
| ].join( "\n" ), null, { derivatives: true } ); |
|
|
| return { |
| perturbNormal2Arb: perturbNormal2Arb |
| }; |
|
|
| } )(); |
|
|
| NormalMapNode.prototype = Object.create( TempNode.prototype ); |
| NormalMapNode.prototype.constructor = NormalMapNode; |
| NormalMapNode.prototype.nodeType = "NormalMap"; |
|
|
| NormalMapNode.prototype.generate = function ( builder, output ) { |
|
|
| if ( builder.isShader( 'fragment' ) ) { |
|
|
| var perturbNormal2Arb = builder.include( NormalMapNode.Nodes.perturbNormal2Arb ); |
|
|
| this.normal = this.normal || new NormalNode(); |
| this.position = this.position || new PositionNode( PositionNode.VIEW ); |
| this.uv = this.uv || new UVNode(); |
|
|
| return builder.format( perturbNormal2Arb + '( -' + this.position.build( builder, 'v3' ) + ', ' + |
| this.normal.build( builder, 'v3' ) + ', ' + |
| this.value.build( builder, 'v3' ) + ', ' + |
| this.uv.build( builder, 'v2' ) + ', ' + |
| this.scale.build( builder, 'v2' ) + ' )', this.getType( builder ), output ); |
|
|
| } else { |
|
|
| console.warn( "THREE.NormalMapNode is not compatible with " + builder.shader + " shader." ); |
|
|
| return builder.format( 'vec3( 0.0 )', this.getType( builder ), output ); |
|
|
| } |
|
|
| }; |
|
|
| NormalMapNode.prototype.copy = function ( source ) { |
|
|
| TempNode.prototype.copy.call( this, source ); |
|
|
| this.value = source.value; |
| this.scale = source.scale; |
|
|
| }; |
|
|
| NormalMapNode.prototype.toJSON = function ( meta ) { |
|
|
| var data = this.getJSONNode( meta ); |
|
|
| if ( ! data ) { |
|
|
| data = this.createJSONNode( meta ); |
|
|
| data.value = this.value.toJSON( meta ).uuid; |
| data.scale = this.scale.toJSON( meta ).uuid; |
|
|
| } |
|
|
| return data; |
|
|
| }; |
|
|
| export { NormalMapNode }; |
|
|