You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.2 KiB
139 lines
3.2 KiB
2 years ago
|
import {
|
||
|
BackSide
|
||
|
} from '../../../../build/three.module.js';
|
||
|
|
||
|
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';
|
||
|
|
||
|
class NormalMapNode extends TempNode {
|
||
|
|
||
|
constructor( value, scale ) {
|
||
|
|
||
|
super( 'v3' );
|
||
|
|
||
|
this.value = value;
|
||
|
this.scale = scale || new Vector2Node( 1, 1 );
|
||
|
|
||
|
}
|
||
|
|
||
|
generate( builder, output ) {
|
||
|
|
||
|
if ( builder.isShader( 'fragment' ) ) {
|
||
|
|
||
|
const 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();
|
||
|
|
||
|
let scale = this.scale.build( builder, 'v2' );
|
||
|
|
||
|
if ( builder.material.side === BackSide ) {
|
||
|
|
||
|
scale = '-' + scale;
|
||
|
|
||
|
}
|
||
|
|
||
|
return builder.format( perturbNormal2Arb + '( -' + this.position.build( builder, 'v3' ) + ', ' +
|
||
|
this.normal.build( builder, 'v3' ) + ', ' +
|
||
|
this.value.build( builder, 'v3' ) + ', ' +
|
||
|
this.uv.build( builder, 'v2' ) + ', ' +
|
||
|
scale + ' )', 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 );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
copy( source ) {
|
||
|
|
||
|
super.copy( source );
|
||
|
|
||
|
this.value = source.value;
|
||
|
this.scale = source.scale;
|
||
|
|
||
|
return this;
|
||
|
|
||
|
}
|
||
|
|
||
|
toJSON( meta ) {
|
||
|
|
||
|
let 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;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
NormalMapNode.Nodes = ( function () {
|
||
|
|
||
|
const perturbNormal2Arb = new FunctionNode(
|
||
|
|
||
|
// Per-Pixel Tangent Space Normal Mapping
|
||
|
// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
|
||
|
|
||
|
`vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 map, vec2 vUv, vec2 normalScale ) {
|
||
|
|
||
|
// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
|
||
|
|
||
|
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( vUv.st );
|
||
|
vec2 st1 = dFdy( vUv.st );
|
||
|
|
||
|
float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude
|
||
|
|
||
|
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 );
|
||
|
|
||
|
vec3 mapN = map * 2.0 - 1.0;
|
||
|
|
||
|
mapN.xy *= normalScale;
|
||
|
|
||
|
#ifdef DOUBLE_SIDED
|
||
|
|
||
|
// Workaround for Adreno GPUs gl_FrontFacing bug. See #15850 and #10331
|
||
|
|
||
|
if ( dot( cross( S, T ), N ) < 0.0 ) mapN.xy *= - 1.0;
|
||
|
|
||
|
#else
|
||
|
|
||
|
mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
|
||
|
|
||
|
#endif
|
||
|
|
||
|
mat3 tsn = mat3( S, T, N );
|
||
|
return normalize( tsn * mapN );
|
||
|
|
||
|
}`, null, { derivatives: true } );
|
||
|
|
||
|
return {
|
||
|
perturbNormal2Arb: perturbNormal2Arb
|
||
|
};
|
||
|
|
||
|
} )();
|
||
|
|
||
|
NormalMapNode.prototype.nodeType = 'NormalMap';
|
||
|
|
||
|
export { NormalMapNode };
|