@@ -4,42 +4,37 @@ import {
4
4
SEMANTIC_TEXCOORD0 ,
5
5
BLEND_NORMAL ,
6
6
CULLFACE_NONE ,
7
- PlaneGeometry ,
8
- Mesh ,
9
- MeshInstance ,
10
7
Color ,
11
- Script ,
12
- Vec2
8
+ Script
13
9
} from 'playcanvas' ;
14
10
15
11
/** @import { AppBase, Entity } from 'playcanvas' */
16
12
17
- const tmpVa = new Vec2 ( ) ;
18
-
19
- const EPISILON = 1e-3 ;
20
-
21
13
const vertexCode = /* glsl */ `
22
14
attribute vec3 vertex_position;
23
- attribute vec2 aUv0;
24
15
25
16
uniform mat4 matrix_model;
26
17
uniform mat4 matrix_viewProjection;
27
18
28
- varying vec2 uv0 ;
19
+ varying vec3 vPosition ;
29
20
30
21
void main(void) {
31
- gl_Position = matrix_viewProjection * matrix_model * vec4(vertex_position, 1.0);
32
- uv0 = aUv0;
22
+ vec4 worldPosition = matrix_model * vec4(vertex_position, 1.0);
23
+ vPosition = worldPosition.xyz;
24
+ gl_Position = matrix_viewProjection * worldPosition;
33
25
}
34
26
` ;
35
27
36
28
const fragmentCode = /* glsl */ `
37
- uniform vec2 uHalfExtents;
38
29
uniform vec3 uColorX;
39
30
uniform vec3 uColorZ;
40
31
uniform int uResolution;
32
+ uniform sampler2D blueNoiseTex32;
41
33
42
- varying vec2 uv0;
34
+ uniform vec3 view_position;
35
+ uniform mat4 matrix_viewProjection;
36
+
37
+ varying vec3 vPosition;
43
38
44
39
// https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#1e7c
45
40
float pristineGrid(in vec2 uv, in vec2 ddx, in vec2 ddy, vec2 lineWidth) {
@@ -64,58 +59,77 @@ const fragmentCode = /* glsl */ `
64
59
return mix(grid2.x, 1.0, grid2.y);
65
60
}
66
61
67
- void main(void) {
68
- vec2 uv = uv0;
62
+ float calcDepth(vec3 p) {
63
+ vec4 v = matrix_viewProjection * vec4(p, 1.0);
64
+ return (v.z / v.w) * 0.5 + 0.5;
65
+ }
66
+
67
+ bool writeDepth(float alpha) {
68
+ vec2 uv = fract(gl_FragCoord.xy / 32.0);
69
+ float noise = texture2DLod(blueNoiseTex32, uv, 0.0).y;
70
+ return alpha > noise;
71
+ }
69
72
70
- vec2 pos = (uv * 2.0 - 1.0) * uHalfExtents;
71
- vec2 ddx = dFdx(pos);
72
- vec2 ddy = dFdy(pos);
73
+ void main(void) {
74
+ vec3 pos = vPosition;
75
+ vec2 ddx = dFdx(pos.xz);
76
+ vec2 ddy = dFdy(pos.xz);
73
77
74
78
float epsilon = 1.0 / 255.0;
75
79
76
- vec2 levelPos;
80
+ // calculate fade
81
+ float fade = 1.0 - smoothstep(400.0, 1000.0, length(pos - view_position));
82
+ if (fade < epsilon) {
83
+ discard;
84
+ }
85
+
86
+ vec3 levelPos;
77
87
float levelSize;
78
88
float levelAlpha;
79
89
80
90
levelPos = pos * 0.1;
81
91
levelSize = 2.0 / 1000.0;
82
- levelAlpha = pristineGrid(levelPos, ddx * 0.1, ddy * 0.1, vec2(levelSize));
92
+ levelAlpha = pristineGrid(levelPos.xz , ddx * 0.1, ddy * 0.1, vec2(levelSize)) * fade ;
83
93
if (levelAlpha > epsilon) {
84
94
vec3 color;
85
- if (abs(levelPos.x) < levelSize) {
86
- if (abs(levelPos.y) < levelSize) {
95
+ vec2 loc = max(vec2(0.0), abs(levelPos.xz) - abs(ddx * 0.1) - abs(ddy * 0.1));
96
+ if (loc.x < levelSize) {
97
+ if (loc.y < levelSize) {
87
98
color = vec3(1.0);
88
99
} else {
89
100
color = uColorZ;
90
101
}
91
- } else if (abs(levelPos.y) < levelSize) {
102
+ } else if (loc.y < levelSize) {
92
103
color = uColorX;
93
104
} else {
94
105
color = vec3(0.9);
95
106
}
96
107
gl_FragColor = vec4(color, levelAlpha);
108
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
97
109
return;
98
110
}
99
111
100
112
levelPos = pos;
101
113
levelSize = 1.0 / 100.0;
102
- levelAlpha = pristineGrid(levelPos, ddx, ddy, vec2(levelSize));
114
+ levelAlpha = pristineGrid(levelPos.xz , ddx, ddy, vec2(levelSize)) * fade ;
103
115
if (levelAlpha > epsilon) {
104
116
if (uResolution < 1) {
105
117
discard;
106
118
}
107
119
gl_FragColor = vec4(vec3(0.7), levelAlpha);
120
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
108
121
return;
109
122
}
110
123
111
124
levelPos = pos * 10.0;
112
125
levelSize = 1.0 / 100.0;
113
- levelAlpha = pristineGrid(levelPos, ddx * 10.0, ddy * 10.0, vec2(levelSize));
126
+ levelAlpha = pristineGrid(levelPos.xz , ddx * 10.0, ddy * 10.0, vec2(levelSize)) * fade ;
114
127
if (levelAlpha > epsilon) {
115
128
if (uResolution < 2) {
116
129
discard;
117
130
}
118
131
gl_FragColor = vec4(vec3(0.7), levelAlpha);
132
+ gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
119
133
return;
120
134
}
121
135
@@ -145,18 +159,6 @@ class Grid extends Script {
145
159
*/
146
160
_material ;
147
161
148
- /**
149
- * @type {MeshInstance }
150
- * @private
151
- */
152
- _meshInstance ;
153
-
154
- /**
155
- * @type {Vec2 }
156
- * @private
157
- */
158
- _halfExtents = new Vec2 ( ) ;
159
-
160
162
/**
161
163
* @type {Color }
162
164
* @private
@@ -179,7 +181,7 @@ class Grid extends Script {
179
181
180
182
// ensure the entity has a render component
181
183
if ( ! this . entity . render ) {
182
- this . entity . addComponent ( 'render' ) ;
184
+ this . entity . addComponent ( 'render' , { type : 'plane' } ) ;
183
185
}
184
186
185
187
// create shader material
@@ -196,52 +198,17 @@ class Grid extends Script {
196
198
this . _material . cull = CULLFACE_NONE ;
197
199
this . _material . update ( ) ;
198
200
199
- // create mesh
200
- const mesh = Mesh . fromGeometry ( this . app . graphicsDevice , new PlaneGeometry ( ) ) ;
201
- this . _meshInstance = new MeshInstance ( mesh , this . _material ) ;
202
- this . entity . render . meshInstances = [ this . _meshInstance ] ;
201
+ this . entity . render . material = this . _material ;
203
202
204
203
// set the initial values
205
204
this . colorX = this . _colorX ;
206
205
this . colorZ = this . _colorZ ;
207
206
this . resolution = this . _resolution ;
208
-
209
- // calculate half extents
210
- this . _set ( 'uHalfExtents' , this . _calcHalfExtents ( tmpVa ) ) ;
211
-
212
- // update the half extents when the entity scale changes
213
- this . app . on ( 'prerender' , ( ) => {
214
- if ( ! this . enabled ) {
215
- return ;
216
- }
217
- const halfExtents = this . _calcHalfExtents ( tmpVa ) ;
218
- if ( this . _halfExtents . distance ( halfExtents ) > EPISILON ) {
219
- this . _set ( 'uHalfExtents' , halfExtents ) ;
220
- }
221
- } ) ;
222
-
223
- // enable/disable the mesh instance
224
- this . on ( 'enable' , ( ) => {
225
- this . entity . render . meshInstances = [ this . _meshInstance ] ;
226
- } ) ;
227
- this . on ( 'disable' , ( ) => {
228
- this . entity . render . meshInstances = [ ] ;
229
- } ) ;
230
- }
231
-
232
- /**
233
- * @param {Vec2 } vec - The vector to copy the half extents to.
234
- * @returns {Vec2 } - The half extents.
235
- * @private
236
- */
237
- _calcHalfExtents ( vec ) {
238
- const scale = this . entity . getLocalScale ( ) ;
239
- return vec . set ( scale . x / 2 , scale . z / 2 ) ;
240
207
}
241
208
242
209
/**
243
210
* @param {string } name - The name of the parameter.
244
- * @param {Color|Vec2| number } value - The value of the parameter.
211
+ * @param {Color|number } value - The value of the parameter.
245
212
* @private
246
213
*/
247
214
_set ( name , value ) {
@@ -254,17 +221,10 @@ class Grid extends Script {
254
221
this . _material . setParameter ( name , [ value . r , value . g , value . b ] ) ;
255
222
}
256
223
257
- if ( value instanceof Vec2 ) {
258
- this . _material . setParameter ( name , [ value . x , value . y ] ) ;
259
- }
260
-
261
224
if ( typeof value === 'number' ) {
262
225
this . _material . setParameter ( name , value ) ;
263
226
}
264
227
265
- this . _material . update ( ) ;
266
-
267
- this . _meshInstance . material = this . _material ;
268
228
}
269
229
270
230
/**
0 commit comments