diff --git a/scripts/esm/grid.mjs b/scripts/esm/grid.mjs index 055d8ca5566..2fe27c1dafd 100644 --- a/scripts/esm/grid.mjs +++ b/scripts/esm/grid.mjs @@ -3,43 +3,34 @@ import { SEMANTIC_POSITION, SEMANTIC_TEXCOORD0, BLEND_NORMAL, - CULLFACE_NONE, - PlaneGeometry, - Mesh, - MeshInstance, Color, - Script, - Vec2 + Script } from 'playcanvas'; /** @import { AppBase, Entity } from 'playcanvas' */ -const tmpVa = new Vec2(); - -const EPISILON = 1e-3; - const vertexCode = /* glsl */ ` attribute vec3 vertex_position; - attribute vec2 aUv0; uniform mat4 matrix_model; uniform mat4 matrix_viewProjection; - varying vec2 uv0; + varying vec3 vPosition; void main(void) { - gl_Position = matrix_viewProjection * matrix_model * vec4(vertex_position, 1.0); - uv0 = aUv0; + vec4 worldPosition = matrix_model * vec4(vertex_position, 1.0); + vPosition = worldPosition.xyz; + gl_Position = matrix_viewProjection * worldPosition; } `; const fragmentCode = /* glsl */ ` - uniform vec2 uHalfExtents; uniform vec3 uColorX; uniform vec3 uColorZ; uniform int uResolution; + uniform vec3 view_position; - varying vec2 uv0; + varying vec3 vPosition; // https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#1e7c float pristineGrid(in vec2 uv, in vec2 ddx, in vec2 ddy, vec2 lineWidth) { @@ -65,30 +56,35 @@ const fragmentCode = /* glsl */ ` } void main(void) { - vec2 uv = uv0; - - vec2 pos = (uv * 2.0 - 1.0) * uHalfExtents; - vec2 ddx = dFdx(pos); - vec2 ddy = dFdy(pos); + vec3 pos = vPosition; + vec2 ddx = dFdx(pos.xz); + vec2 ddy = dFdy(pos.xz); float epsilon = 1.0 / 255.0; - vec2 levelPos; + // calculate fade + float fade = 1.0 - smoothstep(400.0, 1000.0, length(pos - view_position)); + if (fade < epsilon) { + discard; + } + + vec3 levelPos; float levelSize; float levelAlpha; levelPos = pos * 0.1; levelSize = 2.0 / 1000.0; - levelAlpha = pristineGrid(levelPos, ddx * 0.1, ddy * 0.1, vec2(levelSize)); + levelAlpha = pristineGrid(levelPos.xz, ddx * 0.1, ddy * 0.1, vec2(levelSize)) * fade; if (levelAlpha > epsilon) { vec3 color; - if (abs(levelPos.x) < levelSize) { - if (abs(levelPos.y) < levelSize) { + vec2 loc = max(vec2(0.0), abs(levelPos.xz) - abs(ddx * 0.1) - abs(ddy * 0.1)); + if (loc.x < levelSize) { + if (loc.y < levelSize) { color = vec3(1.0); } else { color = uColorZ; } - } else if (abs(levelPos.y) < levelSize) { + } else if (loc.y < levelSize) { color = uColorX; } else { color = vec3(0.9); @@ -99,7 +95,7 @@ const fragmentCode = /* glsl */ ` levelPos = pos; levelSize = 1.0 / 100.0; - levelAlpha = pristineGrid(levelPos, ddx, ddy, vec2(levelSize)); + levelAlpha = pristineGrid(levelPos.xz, ddx, ddy, vec2(levelSize)) * fade; if (levelAlpha > epsilon) { if (uResolution < 1) { discard; @@ -110,7 +106,7 @@ const fragmentCode = /* glsl */ ` levelPos = pos * 10.0; levelSize = 1.0 / 100.0; - levelAlpha = pristineGrid(levelPos, ddx * 10.0, ddy * 10.0, vec2(levelSize)); + levelAlpha = pristineGrid(levelPos.xz, ddx * 10.0, ddy * 10.0, vec2(levelSize)) * fade; if (levelAlpha > epsilon) { if (uResolution < 2) { discard; @@ -145,18 +141,6 @@ class Grid extends Script { */ _material; - /** - * @type {MeshInstance} - * @private - */ - _meshInstance; - - /** - * @type {Vec2} - * @private - */ - _halfExtents = new Vec2(); - /** * @type {Color} * @private @@ -176,10 +160,9 @@ class Grid extends Script { _resolution = Grid.RESOLUTION_HIGH; initialize() { - // ensure the entity has a render component if (!this.entity.render) { - this.entity.addComponent('render'); + this.entity.addComponent('render', { type: 'plane' }); } // create shader material @@ -193,55 +176,21 @@ class Grid extends Script { } }); this._material.blendType = BLEND_NORMAL; - this._material.cull = CULLFACE_NONE; + this._material.depthWrite = false; this._material.update(); - // create mesh - const mesh = Mesh.fromGeometry(this.app.graphicsDevice, new PlaneGeometry()); - this._meshInstance = new MeshInstance(mesh, this._material); - this.entity.render.meshInstances = [this._meshInstance]; + this.entity.render.material = this._material; + this.entity.render.castShadows = false; // set the initial values this.colorX = this._colorX; this.colorZ = this._colorZ; this.resolution = this._resolution; - - // calculate half extents - this._set('uHalfExtents', this._calcHalfExtents(tmpVa)); - - // update the half extents when the entity scale changes - this.app.on('prerender', () => { - if (!this.enabled) { - return; - } - const halfExtents = this._calcHalfExtents(tmpVa); - if (this._halfExtents.distance(halfExtents) > EPISILON) { - this._set('uHalfExtents', halfExtents); - } - }); - - // enable/disable the mesh instance - this.on('enable', () => { - this.entity.render.meshInstances = [this._meshInstance]; - }); - this.on('disable', () => { - this.entity.render.meshInstances = []; - }); - } - - /** - * @param {Vec2} vec - The vector to copy the half extents to. - * @returns {Vec2} - The half extents. - * @private - */ - _calcHalfExtents(vec) { - const scale = this.entity.getLocalScale(); - return vec.set(scale.x / 2, scale.z / 2); } /** * @param {string} name - The name of the parameter. - * @param {Color|Vec2|number} value - The value of the parameter. + * @param {Color|number} value - The value of the parameter. * @private */ _set(name, value) { @@ -254,17 +203,9 @@ class Grid extends Script { this._material.setParameter(name, [value.r, value.g, value.b]); } - if (value instanceof Vec2) { - this._material.setParameter(name, [value.x, value.y]); - } - if (typeof value === 'number') { this._material.setParameter(name, value); } - - this._material.update(); - - this._meshInstance.material = this._material; } /**