From afeb4a957ddd7a4cf9d1dc75b3ed4b8a991f36b8 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Tue, 31 Dec 2019 21:00:46 +0200 Subject: [PATCH] Laggy particle system (hold y for demo) --- assets/shaders/particles.fs | 13 ++ assets/shaders/particles.vs | 28 ++++ assets/textures/particleAtlas.png | Bin 0 -> 20153 bytes src/engine/components/particles/index.js | 159 +++++++++++++++++++++++ src/engine/components/water/index.js | 4 +- src/engine/index.js | 4 +- src/engine/mesh/material.js | 10 +- src/engine/utility.js | 4 + src/index.js | 30 ++++- 9 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 assets/shaders/particles.fs create mode 100644 assets/shaders/particles.vs create mode 100644 assets/textures/particleAtlas.png create mode 100644 src/engine/components/particles/index.js diff --git a/assets/shaders/particles.fs b/assets/shaders/particles.fs new file mode 100644 index 0000000..d654f80 --- /dev/null +++ b/assets/shaders/particles.fs @@ -0,0 +1,13 @@ +precision mediump float; + +varying vec2 uv1; +varying vec2 uv2; +varying float blend; + +uniform sampler2D texture0; + +void main() { + vec4 color1 = texture2D(texture0, uv1); + vec4 color2 = texture2D(texture0, uv2); + gl_FragColor = mix(color1, color2, blend); +} diff --git a/assets/shaders/particles.vs b/assets/shaders/particles.vs new file mode 100644 index 0000000..30f7882 --- /dev/null +++ b/assets/shaders/particles.vs @@ -0,0 +1,28 @@ +precision mediump float; + +attribute vec2 aVertexPosition; + +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +uniform mat4 uProjectionMatrix; + +varying vec2 uv1; +varying vec2 uv2; +varying float blend; + +uniform vec2 uAtlasOffset1; +uniform vec2 uAtlasOffset2; +uniform vec2 uAtlasInfo; + +void main() { + + vec2 uv = aVertexPosition + vec2(0.5, 0.5); + uv.y = 1.0 - uv.y; + uv /= uAtlasInfo.x; + uv1 = uv + uAtlasOffset1; + uv2 = uv + uAtlasOffset2; + blend = uAtlasInfo.y; + + vec4 worldPosition = uModelMatrix * vec4(aVertexPosition, 0.0, 1.0); + gl_Position = uProjectionMatrix * uViewMatrix * worldPosition; +} diff --git a/assets/textures/particleAtlas.png b/assets/textures/particleAtlas.png new file mode 100644 index 0000000000000000000000000000000000000000..c202947a8a6a354563b818d3c06aebd13dfac7f3 GIT binary patch literal 20153 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 literal 0 HcmV?d00001 diff --git a/src/engine/components/particles/index.js b/src/engine/components/particles/index.js new file mode 100644 index 0000000..ee5db7a --- /dev/null +++ b/src/engine/components/particles/index.js @@ -0,0 +1,159 @@ +import { Mesh } from '../../mesh' +import { mat4 } from 'gl-matrix' + +class ParticleTexture { + constructor (texture, rows) { + this.texture = texture + this.rows = rows + } + + get id () { + return this.texture.id + } +} + +class Particle { + constructor (texture, pos, vel, gravity, life, rot, scale) { + this.texture = texture + this.pos = pos + this.vel = vel + this.gravity = gravity + this.life = life + this.rot = rot + this.scale = scale + this.elapsed = 0 + + this.texOffset1 = [0.0, 0.0] + this.texOffset2 = [0.0, 0.0] + this.texBlend = 0.0 + + this.distance = 0 + } + + _createOffset (index) { + let col = Math.floor(index % this.texture.rows) + let row = Math.floor(index / this.texture.rows) + return [ col / this.texture.rows, row / this.texture.rows ] + } + + _updateTexture () { + let lifeFactor = this.elapsed / this.life + let stages = this.texture.rows * this.texture.rows + let progression = lifeFactor * stages + let index1 = Math.floor(progression) + let index2 = (index1 < stages - 1) ? index1 + 1 : index1 + this.texBlend = progression % 1 + this.texOffset1 = this._createOffset(index1) + this.texOffset2 = this._createOffset(index2) + } + + update (dt, gravity) { + this.vel[1] += gravity * this.gravity * dt + let change = [this.vel[0] * dt, this.vel[1] * dt, this.vel[2] * dt] + this.pos = [this.pos[0] + change[0], this.pos[1] + change[1], this.pos[2] + change[2]] + this._updateTexture() + this.elapsed += dt + return this.elapsed < this.life + } +} + +class ParticleSystem { + constructor (renderer) { + this.renderer = renderer + this.particles = [] + } + + add (particle) { + this.particles.push(particle) + } + + update (dt, gravity) { + let alive = [] + for (let i in this.particles) { + let particle = this.particles[i] + let stillAlive = particle.update(dt, gravity) + if (!stillAlive) continue + alive.push(particle) + } + this.particles = alive + } + + draw (gl, cam) { + if (!this.renderer) return + this.renderer.draw(gl, this, cam) + } +} + +class ParticleRenderer { + async initialize (game) { + this.shader = await game.shaders.createShaderFromFiles(game.gl, 'particles', false) + this.createMesh(game.gl) + } + + createMesh (gl) { + this.mesh = Mesh.constructFromVertices(gl, [-0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5, -0.5], 2) + } + + createModelMatrix (shader, viewMatrix, particle) { + let modelMatrix = mat4.create() + mat4.translate(modelMatrix, modelMatrix, particle.pos) + modelMatrix[0] = viewMatrix[0] + modelMatrix[1] = viewMatrix[4] + modelMatrix[2] = viewMatrix[8] + modelMatrix[4] = viewMatrix[1] + modelMatrix[5] = viewMatrix[5] + modelMatrix[6] = viewMatrix[9] + modelMatrix[8] = viewMatrix[2] + modelMatrix[10] = viewMatrix[10] + mat4.rotate(modelMatrix, modelMatrix, particle.rot * Math.PI / 180, [0.0, 0.0, 1.0]) + mat4.scale(modelMatrix, modelMatrix, [particle.scale, particle.scale, particle.scale]) + return modelMatrix + } + + draw (gl, particles, cam) { + particles = (particles instanceof ParticleSystem) ? particles.particles : particles + let textures = [] + for (let i in particles) { + let particle = particles[i] + if (textures.indexOf(particle.texture) !== -1) continue + textures.push(particle.texture) + } + + this.shader.use(gl) + const modelLoc = this.shader.getUniformLocation(gl, 'uModelMatrix') + const off1Loc = this.shader.getUniformLocation(gl, 'uAtlasOffset1') + const off2Loc = this.shader.getUniformLocation(gl, 'uAtlasOffset2') + const atlasLoc = this.shader.getUniformLocation(gl, 'uAtlasInfo') + + cam.draw(gl, this.shader) + + gl.enable(gl.BLEND) + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) + gl.depthMask(false) + + this.mesh.prepare(gl, this.shader) + for (let i in textures) { + let texture = textures[i] + gl.activeTexture(gl.TEXTURE0) + gl.bindTexture(gl.TEXTURE_2D, texture.id) + for (let j in particles) { + let particle = particles[j] + if (particle.texture !== texture) continue + + let mat = this.createModelMatrix(this.shader, cam.view, particle) + gl.uniformMatrix4fv(modelLoc, false, mat) + gl.uniform2fv(off1Loc, particle.texOffset1) + gl.uniform2fv(off2Loc, particle.texOffset2) + gl.uniform2fv(atlasLoc, [texture.rows, particle.texBlend]) + + this.mesh.draw(gl, this.shader, gl.TRIANGLE_STRIP) + } + } + this.mesh.postdraw(gl, this.shader) + + gl.disable(gl.BLEND) + gl.depthMask(true) + } +} + +export { ParticleTexture, Particle, ParticleSystem, ParticleRenderer } diff --git a/src/engine/components/water/index.js b/src/engine/components/water/index.js index 25305cd..636cd57 100644 --- a/src/engine/components/water/index.js +++ b/src/engine/components/water/index.js @@ -115,11 +115,11 @@ class WaterTile extends Node { } async useDUDVMap (gl, file) { - this.dudvMap = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR) + this.dudvMap = await Texture.fromFile(gl, file + '.png', false, gl.LINEAR) } async useNormalMap (gl, file) { - this.normalMap = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR) + this.normalMap = await Texture.fromFile(gl, file + '.png', false, gl.LINEAR) } reflect (gl, cam, render) { diff --git a/src/engine/index.js b/src/engine/index.js index 90a71de..f4d8d40 100644 --- a/src/engine/index.js +++ b/src/engine/index.js @@ -58,12 +58,12 @@ class Engine { } update (dt) { - this.input.update() - // Updates for (let i in this.ust) { this.ust[i](dt) } + + this.input.update() } step () { diff --git a/src/engine/mesh/material.js b/src/engine/mesh/material.js index cae2f35..eecb952 100644 --- a/src/engine/mesh/material.js +++ b/src/engine/mesh/material.js @@ -1,7 +1,12 @@ import Resource from '../resource' class Texture { - static createTexture2D (gl, img, flip = true, filtering, repeat = gl.REPEAT) { + static async fromFile (gl, file, flip, filtering, repeat) { + let image = await Resource.loadImage(file) + return Texture.createTexture2D(gl, image, flip, filtering, repeat) + } + + static createTexture2D (gl, img, flip = false, filtering, repeat = gl.REPEAT) { let tex = gl.createTexture() gl.bindTexture(gl.TEXTURE_2D, tex) gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flip) @@ -63,8 +68,7 @@ class Material { for (let ti in this.textures) { let tex = this.textures[ti] if (!(tex instanceof Texture)) { - let teximg = await Resource.loadImage(tex) - let result = Texture.createTexture2D(gl, teximg) + let result = await Texture.fromFile(gl, tex, true) this.textures[ti] = result } } diff --git a/src/engine/utility.js b/src/engine/utility.js index b7df9d1..000fe23 100644 --- a/src/engine/utility.js +++ b/src/engine/utility.js @@ -1,5 +1,9 @@ import { vec3 } from 'gl-matrix' +export function randomInt (min, max) { + return Math.floor(Math.random() * (max - min + 1) + min) +} + export function clamp (num, min, max) { return Math.min(Math.max(num, min), max) } diff --git a/src/index.js b/src/index.js index 1297983..9f10d6f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,14 @@ import Engine from './engine' import Camera from './engine/camera' -import Resource from './engine/resource' import loadMesh from './engine/mesh/loader' +import { randomInt } from './engine/utility' + import { Environment } from './engine/environment' import { LODTerrain } from './engine/components/terrain/lod' import { Skybox } from './engine/components/skybox' import { WaterTile } from './engine/components/water' +import { Particle, ParticleTexture, ParticleSystem, ParticleRenderer } from './engine/components/particles' import { SimplexHeightMap } from './engine/components/terrain/heightmap' import { Material, Texture } from './engine/mesh/material' import { GUIRenderer, GUIImage, Dim4 } from './engine/gui' @@ -16,6 +18,7 @@ let game = Engine let env = new Environment() let gui = new GUIRenderer() let fnt = new FontRenderer() +let prt = new ParticleRenderer() async function pipeline () { let entity = await loadMesh(game.gl, 'test') @@ -38,8 +41,15 @@ async function pipeline () { await gui.initialize(game) await fnt.initialize(game) + // Initialize particles + await prt.initialize(game) + let particleSystem = new ParticleSystem(prt) + + // Particle texture atlas + let particleTexture = new ParticleTexture(await Texture.fromFile(game.gl, 'particleAtlas.png'), 4) + let itms = [ - new GUIImage(await Texture.createTexture2D(game.gl, await Resource.loadImage('noisy.png'), false, game.gl.LINEAR), + new GUIImage(await Texture.fromFile(game.gl, 'noisy.png', false, game.gl.LINEAR), new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)) ] // Nesting test @@ -94,6 +104,19 @@ async function pipeline () { cam.processMouseMove(game.input.mouseOffset) } + // Particles + particleSystem.update(dt, -50) + + if (game.input.isDown('y')) { + let velocity = 20 + for (let i = 0; i < 360; i += 15) { + let rad1 = i * Math.PI / 180 + let x1 = (Math.cos(rad1) * velocity) + randomInt(-5, 5) + let y1 = (Math.sin(rad1) * velocity) + randomInt(-5, 5) + particleSystem.add(new Particle(particleTexture, [0.0, 0.0, 0.0], [x1, randomInt(-velocity, velocity), y1], 0.2, 2, randomInt(0, 360), randomInt(0.1, 1))) + } + } + // Update detail levels terrain.update(game.gl, cam) terrain.updateLODMesh(game.gl) @@ -136,6 +159,9 @@ async function pipeline () { cam.draw(gl, waterShader) water.draw(gl, waterShader, cam, env.sun) + // Draw particles + particleSystem.draw(gl, cam) + // Draw GUIs gui.draw(gl, cam, itms) fnt.draw(gl, cam, itms)