From e56adeeb10b8e59e1251c51b8c4c7c64b7194a08 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Wed, 1 Jan 2020 01:39:40 +0200 Subject: [PATCH] reorganize water renderer --- src/engine/components/water/index.js | 87 ++++++++++++++++------------ src/engine/gui/font.js | 1 + src/index.js | 32 +++++----- 3 files changed, 64 insertions(+), 56 deletions(-) diff --git a/src/engine/components/water/index.js b/src/engine/components/water/index.js index 636cd57..040ca2b 100644 --- a/src/engine/components/water/index.js +++ b/src/engine/components/water/index.js @@ -2,7 +2,6 @@ import { Node } from '../' import { Mesh } from '../../mesh' import { Texture } from '../../mesh/material' import Screen from '../../screen' -import Resource from '../../resource' class WaterFBOs { constructor (reflectionWidth = 320, reflectionHeight = 180, refractionWidth = 1280, refractionHeight = 720) { @@ -96,8 +95,13 @@ class WaterFBOs { } class WaterTile extends Node { - constructor (pos, scale, reflectivity = 0.1, tint = [0.0, 0.3, 0.5, 0.2]) { + constructor (pos, scale) { super(pos, [scale, 0.0, scale]) + } +} + +class WaterRenderer { + constructor (reflectivity = 0.1, tint = [0.0, 0.3, 0.5, 0.2]) { this.fbos = new WaterFBOs() this.reflectivity = reflectivity @@ -107,11 +111,7 @@ class WaterTile extends Node { this.shininess = 0.7 this.shineDamper = 20.0 this.distortionStrength = 0.02 - } - - initialize (gl) { - this.mesh = Mesh.constructFromVertices(gl, [-1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1], 2) - this.fbos.initialize(gl) + this.waveSpeed = 0.001 } async useDUDVMap (gl, file) { @@ -124,7 +124,7 @@ class WaterTile extends Node { reflect (gl, cam, render) { this.fbos.bindReflectionFrameBuffer(gl) - let dist = 2 * (cam.pos[1] - this.pos[1]) + let dist = 2 * cam.pos[1] cam.pos[1] -= dist cam.rotation[1] *= -1 cam.updateTransform() @@ -141,31 +141,35 @@ class WaterTile extends Node { this.fbos.unbindFrameBuffer(gl) } - prepare (gl, shader, cam, sun) { - const transformLoc = shader.getUniformLocation(gl, 'uModelMatrix') + async initialize (game) { + this.shader = await game.shaders.createShaderFromFiles(game.gl, 'water', false) + this.mesh = Mesh.constructFromVertices(game.gl, [-1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, 1], 2) + this.fbos.initialize(game.gl) + } - const camPosLoc = shader.getUniformLocation(gl, 'uCameraPosition') - const refrLoc = shader.getUniformLocation(gl, 'refractionTexture') - const reflLoc = shader.getUniformLocation(gl, 'reflectionTexture') - const depthLoc = shader.getUniformLocation(gl, 'depthMap') - const dudvLoc = shader.getUniformLocation(gl, 'dudvMap') - const normalLoc = shader.getUniformLocation(gl, 'normalMap') + prepare (gl, cam, sun) { + const camPosLoc = this.shader.getUniformLocation(gl, 'uCameraPosition') + const refrLoc = this.shader.getUniformLocation(gl, 'refractionTexture') + const reflLoc = this.shader.getUniformLocation(gl, 'reflectionTexture') + const depthLoc = this.shader.getUniformLocation(gl, 'depthMap') + const dudvLoc = this.shader.getUniformLocation(gl, 'dudvMap') + const normalLoc = this.shader.getUniformLocation(gl, 'normalMap') - const reflectivityLoc = shader.getUniformLocation(gl, 'uReflectivity') - const tintLoc = shader.getUniformLocation(gl, 'uTint') - const phaseLoc = shader.getUniformLocation(gl, 'uDUDVOffset') + const reflectivityLoc = this.shader.getUniformLocation(gl, 'uReflectivity') + const tintLoc = this.shader.getUniformLocation(gl, 'uTint') + const phaseLoc = this.shader.getUniformLocation(gl, 'uDUDVOffset') - const shininessLoc = shader.getUniformLocation(gl, 'uShine') - const damperLoc = shader.getUniformLocation(gl, 'uShineDamper') - const distortLoc = shader.getUniformLocation(gl, 'uDistortionStrength') + const shininessLoc = this.shader.getUniformLocation(gl, 'uShine') + const damperLoc = this.shader.getUniformLocation(gl, 'uShineDamper') + const distortLoc = this.shader.getUniformLocation(gl, 'uDistortionStrength') - const farLoc = shader.getUniformLocation(gl, 'uFarPlane') - const nearLoc = shader.getUniformLocation(gl, 'uNearPlane') + const farLoc = this.shader.getUniformLocation(gl, 'uFarPlane') + const nearLoc = this.shader.getUniformLocation(gl, 'uNearPlane') - const sunPosLoc = shader.getUniformLocation(gl, 'uLightPosition') - const sunColorLoc = shader.getUniformLocation(gl, 'uLightColor') + const sunPosLoc = this.shader.getUniformLocation(gl, 'uLightPosition') + const sunColorLoc = this.shader.getUniformLocation(gl, 'uLightColor') - gl.uniformMatrix4fv(transformLoc, false, this.transform) + gl.uniform4fv(tintLoc, this.tint) gl.uniform3fv(camPosLoc, cam.pos) gl.uniform3fv(sunPosLoc, sun.pos) gl.uniform3fv(sunColorLoc, sun.color) @@ -176,7 +180,6 @@ class WaterTile extends Node { gl.uniform1f(distortLoc, this.distortionStrength) gl.uniform1f(nearLoc, cam.nearPlane) gl.uniform1f(farLoc, cam.farPlane) - gl.uniform4fv(tintLoc, this.tint) gl.uniform1i(reflLoc, 0) gl.uniform1i(refrLoc, 1) gl.uniform1i(dudvLoc, 2) @@ -195,25 +198,35 @@ class WaterTile extends Node { gl.bindTexture(gl.TEXTURE_2D, this.fbos.refractionDepthTexture) } - draw (gl, shader, cam, sun) { - super.draw(gl, shader) - - this.prepare(gl, shader, cam, sun) + draw (gl, waters, cam, sun) { + this.shader.use(gl) gl.enable(gl.BLEND) gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) - this.mesh.prepare(gl, shader) - this.mesh.draw(gl, shader) - this.mesh.postdraw(gl, shader) + // Send camera matrices to the shader + cam.draw(gl, this.shader) + + // Bind uniforms and textures + this.prepare(gl, cam, sun) + + // Render a mesh at every tile location + this.mesh.prepare(gl, this.shader) + for (let i in waters) { + const transformLoc = this.shader.getUniformLocation(gl, 'uModelMatrix') + gl.uniformMatrix4fv(transformLoc, false, waters[i].transform) + + this.mesh.draw(gl, this.shader) + } + this.mesh.postdraw(gl, this.shader) gl.disable(gl.BLEND) } update (dt) { - this.phase += 0.001 + this.phase += this.waveSpeed if (this.phase >= 1) this.phase = 0 } } -export { WaterTile, WaterFBOs } +export { WaterRenderer, WaterTile } diff --git a/src/engine/gui/font.js b/src/engine/gui/font.js index 0a1e03f..888aa43 100644 --- a/src/engine/gui/font.js +++ b/src/engine/gui/font.js @@ -373,6 +373,7 @@ class GUIText extends Node2D { draw (gl, shader) { // Let only the font shader be used to render text if (shader.name !== 'font') return super.draw(gl, shader) + if (!this.text) return const transformLocation = shader.getUniformLocation(gl, 'uTransformation') const cLocation = shader.getUniformLocation(gl, 'uColor') const wLocation = shader.getUniformLocation(gl, 'uWidth') diff --git a/src/index.js b/src/index.js index af92f0d..acfda58 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ 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 { WaterRenderer, 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' @@ -22,17 +22,17 @@ let prt = new ParticleRenderer() async function pipeline () { let entity = await loadMesh(game.gl, 'test') - let shader = await game.shaders.createShaderFromFiles(game.gl, 'basic', false) let terrainShader = await game.shaders.createShaderFromFiles(game.gl, 'terrain', false) let skyboxShader = await game.shaders.createShaderFromFiles(game.gl, 'skybox', false) - let waterShader = await game.shaders.createShaderFromFiles(game.gl, 'water', false) entity.setRotation([0.0, 0.0, -90.0]) + // Initialize water + let waterRenderer = new WaterRenderer() let water = new WaterTile([100.0, 0.0, 100.0], 100.0) - water.initialize(game.gl) - await water.useDUDVMap(game.gl, 'dudv') - await water.useNormalMap(game.gl, 'normalmap') + await waterRenderer.initialize(game) + await waterRenderer.useDUDVMap(game.gl, 'dudv') + await waterRenderer.useNormalMap(game.gl, 'normalmap') let arialFont = await Font.fromFile('arial') await arialFont.loadTextures(game.gl) @@ -53,7 +53,7 @@ async function pipeline () { new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)) ] // Nesting test - itms[0].addChild(new GUIText('this project is coded by an idiot', arialFont, 0.8, new Dim4(0.2, 0.0, 0.0, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), false)) + itms[0].addChild(new GUIText('', arialFont, 0.8, new Dim4(0.2, 0.0, 0.0, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), false)) itms[0].children[0].color = [0.0, 0.2, 1.0] // Create a height map based on OpenSimplex noise @@ -123,7 +123,7 @@ async function pipeline () { terrain.updateLODMesh(game.gl) // Ripple water - water.update(dt) + waterRenderer.update(dt) // Set text to FPS fpsTimer++ @@ -135,37 +135,31 @@ async function pipeline () { function drawEverything (gl) { game.prepare() + // Draw the skybox skyboxShader.use(gl) skybox.draw(gl, skyboxShader, cam) // Use terrain shader terrainShader.use(gl) - // Set environment variables in shader env.draw(gl, terrainShader) - // Set the viewport uniforms cam.draw(gl, terrainShader) - // Draw terrain terrain.draw(gl, terrainShader) - shader.use(gl) - cam.draw(gl, shader) - entity.draw(gl, shader) + entity.draw(gl, terrainShader) } // Render function for the triangle game.addRenderFunction(function (gl) { - water.reflect(gl, cam, drawEverything) - water.refract(gl, cam, drawEverything) + waterRenderer.reflect(gl, cam, drawEverything) + waterRenderer.refract(gl, cam, drawEverything) drawEverything(gl) - waterShader.use(gl) - cam.draw(gl, waterShader) - water.draw(gl, waterShader, cam, env.sun) + waterRenderer.draw(gl, [water], cam, env.sun) // Draw particles particleSystem.draw(gl, cam)