1+ import { tslFn } from "three/tsl" ;
2+ import { Theme } from "../../colors/Theme" ;
3+ import { Script } from "../../export/Script" ;
4+ import { BasicInputProperty } from "../../properties/BasicInputProperty" ;
5+ import { ComboBoxProperty } from "../../properties/ComboBoxProperty" ;
6+ import { Input } from "../../properties/Input" ;
7+ import { InputOrValue } from "../../properties/InputOrValue" ;
8+ import { Output } from "../../properties/Output" ;
9+ import { WinNode } from "../WinNode" ;
10+ import { Fn } from "three/src/nodes/TSL.js" ;
11+
12+ export class BumpMapNode extends WinNode {
13+
14+ protected invert :ComboBoxProperty ;
15+ protected strength :InputOrValue ;
16+ //protected distance:InputOrValue;
17+ protected bumpHeight :BasicInputProperty ;
18+ protected normal :BasicInputProperty ;
19+
20+ constructor ( ) {
21+ super ( "Bump Map" , Theme . config . groupVector , [
22+
23+ new Output ( "Normal" , 2 ) ,
24+ new ComboBoxProperty ( "Invert" , [
25+ [ "" , "---" ] ,
26+ [ ".oneMinus()" , "Invert Height" ] ,
27+ ] ) ,
28+
29+ new InputOrValue ( 1 , { label :"Strength" , min :0 , max :10 , asBar :true , step :0.01 , defaultValue :1 } ) ,
30+ //new InputOrValue(1, { label:"Distance", step:0.01, defaultValue:0.1 }),
31+ new BasicInputProperty ( 1 , "Height" , ( ) => "float(0.1)" ) ,
32+ new BasicInputProperty ( 2 , "Normal" , ( ) => "" ) ,
33+ ] ) ;
34+
35+ this . invert = this . getChildOfType ( ComboBoxProperty ) ! ;
36+ this . strength = this . getChildOfType ( InputOrValue ) ! ;
37+ //this.distance = this.getChildOfType(InputOrValue, 1)!;
38+ this . bumpHeight = this . getChildOfType ( BasicInputProperty , 0 ) ! ;
39+ this . normal = this . getChildOfType ( BasicInputProperty , 1 ) ! ;
40+ }
41+
42+ override writeScript ( script : Script ) : string {
43+
44+ script . importModule ( "bumpMap" ) ;
45+
46+
47+ const bumpStrength = this . strength . writeScript ( script ) ;
48+ const bumpTexture = this . bumpHeight . writeScript ( script ) + this . invert . value ;
49+
50+
51+ let output = `bumpMap( ${ bumpTexture } , ${ bumpStrength } )` ;
52+
53+ const normal = this . normal . writeScript ( script ) ;
54+
55+ /**
56+ * Taken from https://github.com/mrdoob/three.js/blob/dev/src/nodes/display/BumpMapNode.js
57+ * If anyone knows a cleaner way (not repeating/copy pasting code from the threejs source) let me know...
58+ */
59+ if ( normal != "" ) // Combine Normal map + bump map
60+ {
61+ script . importModule ( [
62+ "uv" ,
63+ "float" ,
64+ "vec2" ,
65+ "faceDirection" ,
66+ "positionView" ,
67+ "Fn"
68+ ] ) ;
69+
70+ // Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen
71+ // https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf
72+ const $dHdxy_fwd = script . define ( "dHdxy_fwd" , `Fn( ( { textureNode, bumpScale } ) => {
73+
74+ // It's used to preserve the same TextureNode instance
75+ const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } );
76+
77+ const Hll = float( sampleTexture( ( uvNode ) => uvNode ) );
78+
79+ return vec2(
80+ float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ),
81+ float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll )
82+ ).mul( bumpScale );
83+
84+ } );` ) ;
85+
86+ const perturbNormalArb = script . define ( "perturbNormalArb" , `Fn( ( inputs ) => {
87+
88+ const { surf_pos, surf_norm, dHdxy } = inputs;
89+
90+ // normalize is done to ensure that the bump map looks the same regardless of the texture's scale
91+ const vSigmaX = surf_pos.dFdx().normalize();
92+ const vSigmaY = surf_pos.dFdy().normalize();
93+ const vN = surf_norm; // normalized
94+
95+ const R1 = vSigmaY.cross( vN );
96+ const R2 = vN.cross( vSigmaX );
97+
98+ const fDet = vSigmaX.dot( R1 ).mul( faceDirection );
99+
100+ const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) );
101+
102+ return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize();
103+
104+ } );` ) ;
105+
106+ //--
107+ return script . define ( this . nodeName , `
108+ const dHdxy = ${ $dHdxy_fwd } ( { textureNode: ${ bumpTexture } , bumpScale: ${ bumpStrength } } );
109+
110+ return ${ perturbNormalArb } ( {
111+ surf_pos: positionView,
112+ surf_norm: ${ normal } ,
113+ dHdxy
114+ } );
115+
116+ ` , true ) ;
117+ //--
118+
119+ }
120+ else
121+ {
122+ return script . define ( this . nodeName , output ) ;
123+ }
124+ }
125+ }
0 commit comments