-
Notifications
You must be signed in to change notification settings - Fork 622
/
Grid.tsx
126 lines (120 loc) 路 3.94 KB
/
Grid.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/** Original grid component https://github.com/threlte/threlte/blob/main/packages/extras/src/lib/components/Grid/Grid.svelte
* By https://github.com/grischaerbe and https://github.com/jerzakm
*/
import * as React from 'react'
import * as THREE from 'three'
import { extend } from '@react-three/fiber'
import { shaderMaterial } from './shaderMaterial'
export type GridMaterialType = {
/** Cell size, default: 0.5 */
cellSize?: number
/** Cell thickness, default: 0.5 */
cellThickness?: number
/** Cell color, default: black */
cellColor?: THREE.ColorRepresentation
/** Section size, default: 1 */
sectionSize?: number
/** Section thickness, default: 1 */
sectionThickness?: number
/** Section color, default: #2080ff */
sectionColor?: THREE.ColorRepresentation
/** Follow camera, default: false */
followCamera?: boolean
/** Display the grid infinitely, default: false */
infiniteGrid?: boolean
/** Fade distance, default: 100 */
fadeDistance?: number
/** Fade strength, default: 1 */
fadeStrength?: number
}
export type GridProps = GridMaterialType & {
/** Default plane-geometry arguments */
args?: ConstructorParameters<typeof THREE.PlaneGeometry>
}
declare global {
namespace JSX {
interface IntrinsicElements {
gridMaterial: JSX.IntrinsicElements['shaderMaterial'] & GridMaterialType
}
}
}
const GridMaterial = shaderMaterial(
{
cellSize: 0.5,
sectionSize: 1,
fadeDistance: 100,
fadeStrength: 1,
cellThickness: 0.5,
sectionThickness: 1,
cellColor: new THREE.Color(),
sectionColor: new THREE.Color(),
infiniteGrid: 0,
followCamera: 0,
},
`varying vec3 worldPosition;
uniform float fadeDistance;
uniform float infiniteGrid;
uniform float followCamera;
void main() {
vec3 pos = position.xzy * (1. + fadeDistance * infiniteGrid);
pos.xz += (cameraPosition.xz * followCamera);
worldPosition = pos;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}`,
`varying vec3 worldPosition;
uniform float cellSize;
uniform float sectionSize;
uniform vec3 cellColor;
uniform vec3 sectionColor;
uniform float fadeDistance;
uniform float fadeStrength;
uniform float cellThickness;
uniform float sectionThickness;
uniform float infiniteGrid;
float getGrid(float size, float thickness) {
vec2 r = worldPosition.xz / size;
vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
float line = min(grid.x, grid.y) + 1. - thickness;
return 1.0 - min(line, 1.);
}
void main() {
float g1 = getGrid(cellSize, cellThickness);
float g2 = getGrid(sectionSize, sectionThickness);
float d = 1.0 - min(distance(cameraPosition.xz, worldPosition.xz) / fadeDistance, 1.);
vec3 color = mix(cellColor, sectionColor, min(1.,sectionThickness * g2));
gl_FragColor = vec4(color, (g1 + g2) * pow(d,fadeStrength));
gl_FragColor.a = mix(0.75 * gl_FragColor.a, gl_FragColor.a, g2);
if (gl_FragColor.a <= 0.0) discard;
#include <tonemapping_fragment>
#include <encodings_fragment>
}`
)
export const Grid = React.forwardRef(
(
{
args,
cellColor = '#000000',
sectionColor = '#2080ff',
cellSize = 0.5,
sectionSize = 1,
followCamera = false,
infiniteGrid = false,
fadeDistance = 100,
fadeStrength = 1,
cellThickness = 0.5,
sectionThickness = 1,
...props
}: Omit<JSX.IntrinsicElements['mesh'], 'args'> & GridProps,
fRef: React.ForwardedRef<THREE.Mesh>
) => {
extend({ GridMaterial })
const uniforms1 = { cellSize, sectionSize, cellColor, sectionColor, cellThickness, sectionThickness }
const uniforms2 = { fadeDistance, fadeStrength, infiniteGrid, followCamera }
return (
<mesh ref={fRef} rotation-x={Math.PI} frustumCulled={false} {...props}>
<gridMaterial transparent extensions-derivatives {...uniforms1} {...uniforms2} />
<planeGeometry args={args} />
</mesh>
)
}
)