Water, complete with artifacts! (still wip)
This commit is contained in:
parent
bada6f86b4
commit
d55389dacb
@ -5,24 +5,67 @@ varying vec4 clipSpace;
|
||||
uniform sampler2D reflectionTexture;
|
||||
uniform sampler2D refractionTexture;
|
||||
uniform sampler2D dudvMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D depthMap;
|
||||
|
||||
uniform float uReflectivity;
|
||||
uniform vec4 uTint;
|
||||
uniform float uDUDVOffset;
|
||||
uniform vec3 uLightColor;
|
||||
|
||||
varying vec2 uv;
|
||||
const float waveStrength = 0.002;
|
||||
varying vec3 toCameraVector;
|
||||
varying vec3 fromLightVector;
|
||||
|
||||
const float waterDistortionStrength = 0.02;
|
||||
const float shineDamper = 20.0;
|
||||
const float reflectivity = 0.6;
|
||||
|
||||
const float near = 0.1;
|
||||
const float far = 10000.0;
|
||||
|
||||
void main() {
|
||||
vec2 ndc = (clipSpace.xy / clipSpace.w) / 2.0 + 0.5;
|
||||
vec2 refractTexCoords = vec2(ndc.x, ndc.y);
|
||||
vec2 reflectTexCoords = vec2(ndc.x, 1.0 - ndc.y);
|
||||
vec2 reflectTexCoords = vec2(ndc.x, -ndc.y);
|
||||
|
||||
float depth = 2.0 * texture2D(depthMap, refractTexCoords).r - 1.0;
|
||||
float floorDistance = 2.0 * near * far / (far + near - depth * (far - near));
|
||||
depth = 2.0 * gl_FragCoord.z - 1.0;
|
||||
float waterDistance = 2.0 * near * far / (far + near - depth * (far - near));
|
||||
float waterDepth = floorDistance - waterDistance;
|
||||
|
||||
vec2 distortedTexCoords = texture2D(dudvMap, vec2(uv.x + uDUDVOffset, uv.y)).rg * 0.1;
|
||||
distortedTexCoords = uv + vec2(distortedTexCoords.x, distortedTexCoords.y + uDUDVOffset);
|
||||
|
||||
// Between -1 and 1
|
||||
vec2 totalDistortion = (texture2D(dudvMap, distortedTexCoords).rg * 2.0 - 1.0) * waterDistortionStrength;
|
||||
|
||||
refractTexCoords += totalDistortion;
|
||||
reflectTexCoords += totalDistortion;
|
||||
|
||||
vec2 distortion1 = texture2D(dudvMap, uv).xy * 2.0 - 1.0 * waveStrength;
|
||||
refractTexCoords += distortion1;
|
||||
refractTexCoords = clamp(refractTexCoords, 0.001, 0.999);
|
||||
reflectTexCoords += distortion1;
|
||||
reflectTexCoords.x = clamp(reflectTexCoords.x, 0.001, 0.999);
|
||||
reflectTexCoords.y = clamp(reflectTexCoords.y, -0.999, -0.001);
|
||||
|
||||
reflectTexCoords.y = 1.0 + reflectTexCoords.y;
|
||||
|
||||
vec4 reflectColor = texture2D(reflectionTexture, reflectTexCoords);
|
||||
vec4 refractColor = texture2D(refractionTexture, refractTexCoords);
|
||||
|
||||
gl_FragColor = mix(reflectColor, refractColor, 0.5);
|
||||
vec3 viewVector = normalize(toCameraVector);
|
||||
float refractiveFactor = dot(viewVector, vec3(0.0, 1.0, 0.0));
|
||||
refractiveFactor = pow(refractiveFactor, uReflectivity);
|
||||
|
||||
vec4 normalMapColor = texture2D(normalMap, distortedTexCoords);
|
||||
vec3 normal = vec3(normalMapColor.r * 2.0 - 1.0, normalMapColor.b, normalMapColor.g * 2.0 - 1.0);
|
||||
normal = normalize(normal);
|
||||
|
||||
vec3 reflectedLight = reflect(normalize(fromLightVector), normal);
|
||||
float specular = max(dot(reflectedLight, viewVector), 0.0);
|
||||
specular = pow(specular, shineDamper);
|
||||
vec3 specularHighlights = uLightColor * specular * reflectivity;
|
||||
|
||||
gl_FragColor = mix(reflectColor, refractColor, refractiveFactor);
|
||||
gl_FragColor = mix(gl_FragColor, vec4(uTint.xyz, 1.0), uTint.w) + vec4(specularHighlights, 0.0);
|
||||
}
|
||||
|
@ -5,14 +5,21 @@ attribute vec2 aVertexPosition;
|
||||
uniform mat4 uModelMatrix;
|
||||
uniform mat4 uViewMatrix;
|
||||
uniform mat4 uProjectionMatrix;
|
||||
uniform vec3 uCameraPosition;
|
||||
uniform vec3 uLightPosition;
|
||||
|
||||
varying vec4 clipSpace;
|
||||
varying vec2 uv;
|
||||
varying vec3 toCameraVector;
|
||||
varying vec3 fromLightVector;
|
||||
|
||||
const float tiling = 6.0;
|
||||
const float tiling = 8.0;
|
||||
|
||||
void main() {
|
||||
clipSpace = uProjectionMatrix * uViewMatrix * uModelMatrix * vec4(aVertexPosition.x, 0.0, aVertexPosition.y, 1.0);
|
||||
vec4 worldPosition = uModelMatrix * vec4(aVertexPosition.x, 0.0, aVertexPosition.y, 1.0);
|
||||
clipSpace = uProjectionMatrix * uViewMatrix * worldPosition;
|
||||
gl_Position = clipSpace;
|
||||
uv = vec2(aVertexPosition.x/2.0+0.5,aVertexPosition.y/2.0+0.5) * tiling;
|
||||
uv = (aVertexPosition / 2.0 + 0.5) * tiling;
|
||||
toCameraVector = uCameraPosition - worldPosition.xyz;
|
||||
fromLightVector = worldPosition.xyz - uLightPosition;
|
||||
}
|
||||
|
BIN
assets/textures/normalmap.png
Normal file
BIN
assets/textures/normalmap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 KiB |
@ -78,10 +78,8 @@ class WaterFBOs {
|
||||
let texture = gl.createTexture()
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture)
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, width, height, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, texture, 0)
|
||||
return texture
|
||||
}
|
||||
@ -96,9 +94,12 @@ class WaterFBOs {
|
||||
}
|
||||
|
||||
class WaterTile extends Node {
|
||||
constructor (pos, scale, rot) {
|
||||
super(pos, [scale, 0.0, scale], rot)
|
||||
constructor (pos, scale, reflectivity = 1, tint = [0.0, 0.3, 0.5, 0.2]) {
|
||||
super(pos, [scale, 0.0, scale])
|
||||
this.fbos = new WaterFBOs()
|
||||
this.reflectivity = reflectivity
|
||||
this.tint = tint
|
||||
this.phase = 1.0
|
||||
}
|
||||
|
||||
initialize (gl) {
|
||||
@ -107,7 +108,11 @@ class WaterTile extends Node {
|
||||
}
|
||||
|
||||
async useDUDV (gl, file) {
|
||||
this.dudv = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR)
|
||||
this.dudvMap = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR)
|
||||
}
|
||||
|
||||
async useNormalMap (gl, file) {
|
||||
this.normalMap = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR)
|
||||
}
|
||||
|
||||
reflect (gl, cam, render) {
|
||||
@ -129,20 +134,49 @@ class WaterTile extends Node {
|
||||
this.fbos.unbindFrameBuffer(gl)
|
||||
}
|
||||
|
||||
draw (gl, shader) {
|
||||
super.draw(gl, shader)
|
||||
prepare (gl, shader, cam, sun) {
|
||||
const transformLoc = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||
const camPosLoc = shader.getUniformLocation(gl, 'uCameraPosition')
|
||||
const refrLoc = shader.getUniformLocation(gl, 'refractionTexture')
|
||||
const reflLoc = shader.getUniformLocation(gl, 'reflectionTexture')
|
||||
const depthLoc = shader.getUniformLocation(gl, 'depthTexture')
|
||||
const dudvLoc = shader.getUniformLocation(gl, 'dudvMap')
|
||||
const normalLoc = shader.getUniformLocation(gl, 'dudvMap')
|
||||
const reflectivityLoc = shader.getUniformLocation(gl, 'uReflectivity')
|
||||
const tintLoc = shader.getUniformLocation(gl, 'uTint')
|
||||
const phaseLoc = shader.getUniformLocation(gl, 'uDUDVOffset')
|
||||
const sunPosLoc = shader.getUniformLocation(gl, 'uLightPosition')
|
||||
const sunColorLoc = shader.getUniformLocation(gl, 'uLightColor')
|
||||
|
||||
const transformLocation = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||
gl.uniformMatrix4fv(transformLocation, false, this.transform)
|
||||
gl.uniformMatrix4fv(transformLoc, false, this.transform)
|
||||
gl.uniform3fv(camPosLoc, cam.pos)
|
||||
gl.uniform3fv(sunPosLoc, sun.pos)
|
||||
gl.uniform3fv(sunColorLoc, sun.color)
|
||||
gl.uniform1f(reflectivityLoc, this.reflectivity)
|
||||
gl.uniform1f(phaseLoc, this.phase)
|
||||
gl.uniform4fv(tintLoc, this.tint)
|
||||
gl.uniform1i(reflLoc, 0)
|
||||
gl.uniform1i(refrLoc, 1)
|
||||
gl.uniform1i(dudvLoc, 2)
|
||||
gl.uniform1i(normalLoc, 3)
|
||||
gl.uniform1i(depthLoc, 4)
|
||||
|
||||
gl.activeTexture(gl.TEXTURE0)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.fbos.reflectionTexture)
|
||||
gl.activeTexture(gl.TEXTURE1)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.fbos.refractionTexture)
|
||||
if (this.dudv) {
|
||||
gl.activeTexture(gl.TEXTURE2)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.dudv.id)
|
||||
}
|
||||
gl.activeTexture(gl.TEXTURE2)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.dudvMap.id)
|
||||
gl.activeTexture(gl.TEXTURE3)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.normalMap.id)
|
||||
gl.activeTexture(gl.TEXTURE4)
|
||||
gl.bindTexture(gl.TEXTURE_2D, this.fbos.refractionDepthTexture)
|
||||
}
|
||||
|
||||
draw (gl, shader, cam, sun) {
|
||||
super.draw(gl, shader)
|
||||
|
||||
this.prepare(gl, shader, cam, sun)
|
||||
|
||||
this.mesh.prepare(gl, shader)
|
||||
this.mesh.draw(gl, shader)
|
||||
|
33
src/index.js
33
src/index.js
@ -6,7 +6,7 @@ import loadMesh from './engine/mesh/loader'
|
||||
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 { WaterTile } from './engine/components/water'
|
||||
import { SimplexHeightMap } from './engine/components/terrain/heightmap'
|
||||
import { Material, Texture } from './engine/mesh/material'
|
||||
import { GUIRenderer, GUIImage, Dim4 } from './engine/gui'
|
||||
@ -22,13 +22,14 @@ async function pipeline () {
|
||||
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)
|
||||
let waterShader = await game.shaders.createShaderFromFiles(game.gl, 'water', false)
|
||||
|
||||
entity.setRotation([0.0, 0.0, -90.0])
|
||||
|
||||
// let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
|
||||
// water.initialize(game.gl)
|
||||
// await water.useDUDV(game.gl, 'dudv')
|
||||
let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
|
||||
water.initialize(game.gl)
|
||||
await water.useDUDV(game.gl, 'dudv')
|
||||
await water.useNormalMap(game.gl, 'normalmap')
|
||||
|
||||
let arialFont = await Font.fromFile('arial')
|
||||
await arialFont.loadTextures(game.gl)
|
||||
@ -75,8 +76,8 @@ async function pipeline () {
|
||||
// Load textures and generate a mesh
|
||||
await skybox.initialize(game.gl)
|
||||
|
||||
// itms.push(new GUIImage(water.fbos.reflectionTexture, new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||
// itms.push(new GUIImage(water.fbos.refractionTexture, new Dim4(-0.3, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||
itms.push(new GUIImage(water.fbos.reflectionTexture, new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||
itms.push(new GUIImage(water.fbos.refractionTexture, new Dim4(-0.3, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0)))
|
||||
|
||||
// Update function for camera and terrain
|
||||
game.addUpdateFunction(function (dt) {
|
||||
@ -105,10 +106,6 @@ async function pipeline () {
|
||||
function drawEverything (gl) {
|
||||
game.prepare()
|
||||
|
||||
shader.use(gl)
|
||||
cam.draw(gl, shader)
|
||||
entity.draw(gl, shader)
|
||||
|
||||
// Use terrain shader
|
||||
terrainShader.use(gl)
|
||||
|
||||
@ -121,6 +118,10 @@ async function pipeline () {
|
||||
// Draw terrain
|
||||
terrain.draw(gl, terrainShader)
|
||||
|
||||
shader.use(gl)
|
||||
cam.draw(gl, shader)
|
||||
entity.draw(gl, shader)
|
||||
|
||||
// Draw the skybox
|
||||
skyboxShader.use(gl)
|
||||
skybox.draw(gl, skyboxShader, cam)
|
||||
@ -128,14 +129,14 @@ async function pipeline () {
|
||||
|
||||
// Render function for the triangle
|
||||
game.addRenderFunction(function (gl) {
|
||||
// water.reflect(gl, cam, drawEverything)
|
||||
// water.refract(gl, cam, drawEverything)
|
||||
water.reflect(gl, cam, drawEverything)
|
||||
water.refract(gl, cam, drawEverything)
|
||||
|
||||
drawEverything(gl)
|
||||
|
||||
// waterShader.use(gl)
|
||||
// cam.draw(gl, waterShader)
|
||||
// water.draw(gl, waterShader)
|
||||
waterShader.use(gl)
|
||||
cam.draw(gl, waterShader)
|
||||
water.draw(gl, waterShader, cam, env.sun)
|
||||
|
||||
// Draw GUIs
|
||||
gui.draw(gl, cam, itms)
|
||||
|
Loading…
Reference in New Issue
Block a user