Skip to content

Commit f5df46d

Browse files
committed
Refactor grid shader code
1 parent 64fafcd commit f5df46d

File tree

1 file changed

+44
-84
lines changed

1 file changed

+44
-84
lines changed

scripts/esm/grid.mjs

+44-84
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,37 @@ import {
44
SEMANTIC_TEXCOORD0,
55
BLEND_NORMAL,
66
CULLFACE_NONE,
7-
PlaneGeometry,
8-
Mesh,
9-
MeshInstance,
107
Color,
11-
Script,
12-
Vec2
8+
Script
139
} from 'playcanvas';
1410

1511
/** @import { AppBase, Entity } from 'playcanvas' */
1612

17-
const tmpVa = new Vec2();
18-
19-
const EPISILON = 1e-3;
20-
2113
const vertexCode = /* glsl */ `
2214
attribute vec3 vertex_position;
23-
attribute vec2 aUv0;
2415
2516
uniform mat4 matrix_model;
2617
uniform mat4 matrix_viewProjection;
2718
28-
varying vec2 uv0;
19+
varying vec3 vPosition;
2920
3021
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;
3325
}
3426
`;
3527

3628
const fragmentCode = /* glsl */ `
37-
uniform vec2 uHalfExtents;
3829
uniform vec3 uColorX;
3930
uniform vec3 uColorZ;
4031
uniform int uResolution;
32+
uniform sampler2D blueNoiseTex32;
4133
42-
varying vec2 uv0;
34+
uniform vec3 view_position;
35+
uniform mat4 matrix_viewProjection;
36+
37+
varying vec3 vPosition;
4338
4439
// https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#1e7c
4540
float pristineGrid(in vec2 uv, in vec2 ddx, in vec2 ddy, vec2 lineWidth) {
@@ -64,58 +59,77 @@ const fragmentCode = /* glsl */ `
6459
return mix(grid2.x, 1.0, grid2.y);
6560
}
6661
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+
}
6972
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);
7377
7478
float epsilon = 1.0 / 255.0;
7579
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;
7787
float levelSize;
7888
float levelAlpha;
7989
8090
levelPos = pos * 0.1;
8191
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;
8393
if (levelAlpha > epsilon) {
8494
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) {
8798
color = vec3(1.0);
8899
} else {
89100
color = uColorZ;
90101
}
91-
} else if (abs(levelPos.y) < levelSize) {
102+
} else if (loc.y < levelSize) {
92103
color = uColorX;
93104
} else {
94105
color = vec3(0.9);
95106
}
96107
gl_FragColor = vec4(color, levelAlpha);
108+
gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
97109
return;
98110
}
99111
100112
levelPos = pos;
101113
levelSize = 1.0 / 100.0;
102-
levelAlpha = pristineGrid(levelPos, ddx, ddy, vec2(levelSize));
114+
levelAlpha = pristineGrid(levelPos.xz, ddx, ddy, vec2(levelSize)) * fade;
103115
if (levelAlpha > epsilon) {
104116
if (uResolution < 1) {
105117
discard;
106118
}
107119
gl_FragColor = vec4(vec3(0.7), levelAlpha);
120+
gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
108121
return;
109122
}
110123
111124
levelPos = pos * 10.0;
112125
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;
114127
if (levelAlpha > epsilon) {
115128
if (uResolution < 2) {
116129
discard;
117130
}
118131
gl_FragColor = vec4(vec3(0.7), levelAlpha);
132+
gl_FragDepth = writeDepth(levelAlpha) ? calcDepth(pos) : 1.0;
119133
return;
120134
}
121135
@@ -145,18 +159,6 @@ class Grid extends Script {
145159
*/
146160
_material;
147161

148-
/**
149-
* @type {MeshInstance}
150-
* @private
151-
*/
152-
_meshInstance;
153-
154-
/**
155-
* @type {Vec2}
156-
* @private
157-
*/
158-
_halfExtents = new Vec2();
159-
160162
/**
161163
* @type {Color}
162164
* @private
@@ -179,7 +181,7 @@ class Grid extends Script {
179181

180182
// ensure the entity has a render component
181183
if (!this.entity.render) {
182-
this.entity.addComponent('render');
184+
this.entity.addComponent('render', { type: 'plane' });
183185
}
184186

185187
// create shader material
@@ -196,52 +198,17 @@ class Grid extends Script {
196198
this._material.cull = CULLFACE_NONE;
197199
this._material.update();
198200

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;
203202

204203
// set the initial values
205204
this.colorX = this._colorX;
206205
this.colorZ = this._colorZ;
207206
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);
240207
}
241208

242209
/**
243210
* @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.
245212
* @private
246213
*/
247214
_set(name, value) {
@@ -254,17 +221,10 @@ class Grid extends Script {
254221
this._material.setParameter(name, [value.r, value.g, value.b]);
255222
}
256223

257-
if (value instanceof Vec2) {
258-
this._material.setParameter(name, [value.x, value.y]);
259-
}
260-
261224
if (typeof value === 'number') {
262225
this._material.setParameter(name, value);
263226
}
264227

265-
this._material.update();
266-
267-
this._meshInstance.material = this._material;
268228
}
269229

270230
/**

0 commit comments

Comments
 (0)