|
40 | 40 |
|
41 | 41 | import * as THREE from 'three/webgpu'; |
42 | 42 |
|
43 | | - import { Fn, length, fract, vec4, positionWorld, smoothstep, max, abs, float, fwidth } from 'three/tsl'; |
| 43 | + import { Fn, abs, fract, fwidth, length, max, saturate, smoothstep, vec4, positionWorld, float } from 'three/tsl'; |
44 | 44 |
|
45 | 45 | import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; |
46 | 46 |
|
|
130 | 130 |
|
131 | 131 | const material = new THREE.MeshBasicNodeMaterial(); |
132 | 132 |
|
133 | | - const gridXZ = Fn( ( [ gridSize = float( 1.0 ), dotWidth = float( 0.1 ), lineWidth = float( 0.02 ) ] ) => { |
| 133 | + const grid = Fn( ( [ coord, lineWidth = float( 0.01 ), dotSize = float( 0.03 ) ] ) => { |
134 | 134 |
|
135 | | - const coord = positionWorld.xz.div( gridSize ); |
136 | | - const grid = fract( coord ); |
| 135 | + // https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8 |
137 | 136 |
|
138 | | - // Screen-space derivative for automatic antialiasing |
| 137 | + const g = fract( coord ); |
139 | 138 | const fw = fwidth( coord ); |
140 | | - const smoothing = max( fw.x, fw.y ).mul( 0.5 ); |
| 139 | + const gx = abs( g.x.sub( 0.5 ) ); |
| 140 | + const gy = abs( g.y.sub( 0.5 ) ); |
141 | 141 |
|
142 | | - // Create squares at cell centers |
143 | | - const squareDist = max( abs( grid.x.sub( 0.5 ) ), abs( grid.y.sub( 0.5 ) ) ); |
144 | | - const dots = smoothstep( dotWidth.add( smoothing ), dotWidth.sub( smoothing ), squareDist ); |
| 142 | + const lineX = saturate( lineWidth.sub( gx ).div( fw.x ).add( 0.5 ) ); |
| 143 | + const lineY = saturate( lineWidth.sub( gy ).div( fw.y ).add( 0.5 ) ); |
| 144 | + const lines = max( lineX, lineY ); |
145 | 145 |
|
146 | | - // Create grid lines |
147 | | - const lineX = smoothstep( lineWidth.add( smoothing ), lineWidth.sub( smoothing ), abs( grid.x.sub( 0.5 ) ) ); |
148 | | - const lineZ = smoothstep( lineWidth.add( smoothing ), lineWidth.sub( smoothing ), abs( grid.y.sub( 0.5 ) ) ); |
149 | | - const lines = max( lineX, lineZ ); |
| 146 | + const squareDist = max( gx, gy ); |
| 147 | + const aa = max( fw.x, fw.y ); |
| 148 | + const dots = smoothstep( dotSize.add( aa ), dotSize.sub( aa ), squareDist ); |
150 | 149 |
|
151 | 150 | return max( dots, lines ); |
152 | 151 |
|
153 | 152 | } ); |
154 | 153 |
|
155 | | - const radialGradient = Fn( ( [ radius = float( 10.0 ), falloff = float( 1.0 ) ] ) => { |
| 154 | + const fade = Fn( ( [ radius = float( 10.0 ), falloff = float( 1.0 ) ] ) => { |
156 | 155 |
|
157 | 156 | return smoothstep( radius, radius.sub( falloff ), length( positionWorld ) ); |
158 | 157 |
|
159 | 158 | } ); |
160 | 159 |
|
161 | | - // Create grid pattern |
162 | | - const gridPattern = gridXZ( 1.0, 0.03, 0.005 ); |
163 | | - const baseColor = vec4( 1.0, 1.0, 1.0, 0.0 ); |
164 | 160 | const gridColor = vec4( 0.5, 0.5, 0.5, 1.0 ); |
| 161 | + const baseColor = vec4( 1.0, 1.0, 1.0, 0.0 ); |
165 | 162 |
|
166 | | - // Mix base color with grid lines |
167 | | - material.colorNode = gridPattern.mix( baseColor, gridColor ).mul( radialGradient( 30.0, 20.0 ) ); |
| 163 | + material.colorNode = grid( positionWorld.xz, 0.007, 0.03 ).mix( baseColor, gridColor ).mul( fade( 30.0, 20.0 ) ); |
168 | 164 | material.transparent = true; |
169 | 165 |
|
170 | 166 | const plane = new THREE.Mesh( new THREE.CircleGeometry( 40 ), material ); |
|
0 commit comments