WORKING WATER! (no clipping planes implemented)

This commit is contained in:
Evert Prants 2019-12-29 19:20:04 +02:00
parent d55389dacb
commit 7590e7930e
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
4 changed files with 63 additions and 29 deletions

View File

@ -9,37 +9,38 @@ uniform sampler2D normalMap;
uniform sampler2D depthMap;
uniform float uReflectivity;
uniform vec4 uTint;
uniform float uDUDVOffset;
uniform vec3 uLightColor;
uniform vec4 uTint;
uniform float uShine;
uniform float uShineDamper;
uniform float uDistortionStrength;
uniform float uNearPlane;
uniform float uFarPlane;
varying vec2 uv;
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, -ndc.y);
float depth = 2.0 * texture2D(depthMap, refractTexCoords).r - 1.0;
float floorDistance = 2.0 * near * far / (far + near - depth * (far - near));
float floorDistance = 2.0 * uNearPlane * uFarPlane / (uFarPlane + uNearPlane - depth * (uFarPlane - uNearPlane));
depth = 2.0 * gl_FragCoord.z - 1.0;
float waterDistance = 2.0 * near * far / (far + near - depth * (far - near));
float waterDistance = 2.0 * uNearPlane * uFarPlane / (uFarPlane + uNearPlane - depth * (uFarPlane - uNearPlane));
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;
float depthDistortionBlend = clamp(waterDepth / 20.0, 0.0, 1.0);
vec2 totalDistortion = (texture2D(dudvMap, distortedTexCoords).rg * 2.0 - 1.0) * uDistortionStrength * depthDistortionBlend;
refractTexCoords += totalDistortion;
reflectTexCoords += totalDistortion;
@ -61,11 +62,14 @@ void main() {
vec3 normal = vec3(normalMapColor.r * 2.0 - 1.0, normalMapColor.b, normalMapColor.g * 2.0 - 1.0);
normal = normalize(normal);
float depthAlpha = clamp(waterDepth / 5.0, 0.0, 1.0);
vec3 reflectedLight = reflect(normalize(fromLightVector), normal);
float specular = max(dot(reflectedLight, viewVector), 0.0);
specular = pow(specular, shineDamper);
vec3 specularHighlights = uLightColor * specular * reflectivity;
specular = pow(specular, uShineDamper);
vec3 specularHighlights = uLightColor * specular * uShine * depthAlpha;
gl_FragColor = mix(reflectColor, refractColor, refractiveFactor);
gl_FragColor = mix(gl_FragColor, vec4(uTint.xyz, 1.0), uTint.w) + vec4(specularHighlights, 0.0);
gl_FragColor.a = depthAlpha;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 KiB

After

Width:  |  Height:  |  Size: 249 KiB

View File

@ -37,7 +37,7 @@ class WaterFBOs {
// create the framebuffer
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer)
// indicate that we will always render to color attachment 0
gl.drawBuffers.drawBuffersWEBGL([gl.COLOR_ATTACHMENT0])
gl.drawBuffers.drawBuffersWEBGL([gl.drawBuffers.COLOR_ATTACHMENT0_WEBGL])
return frameBuffer
}
@ -80,6 +80,8 @@ class WaterFBOs {
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.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
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.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, texture, 0)
return texture
}
@ -94,12 +96,17 @@ class WaterFBOs {
}
class WaterTile extends Node {
constructor (pos, scale, reflectivity = 1, tint = [0.0, 0.3, 0.5, 0.2]) {
constructor (pos, scale, reflectivity = 0.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
this.shininess = 0.7
this.shineDamper = 20.0
this.distortionStrength = 0.02
}
initialize (gl) {
@ -107,7 +114,7 @@ class WaterTile extends Node {
this.fbos.initialize(gl)
}
async useDUDV (gl, file) {
async useDUDVMap (gl, file) {
this.dudvMap = await Texture.createTexture2D(gl, await Resource.loadImage(file + '.png'), false, gl.LINEAR)
}
@ -136,15 +143,25 @@ class WaterTile extends Node {
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 depthLoc = shader.getUniformLocation(gl, 'depthMap')
const dudvLoc = shader.getUniformLocation(gl, 'dudvMap')
const normalLoc = shader.getUniformLocation(gl, 'dudvMap')
const normalLoc = shader.getUniformLocation(gl, 'normalMap')
const reflectivityLoc = shader.getUniformLocation(gl, 'uReflectivity')
const tintLoc = shader.getUniformLocation(gl, 'uTint')
const phaseLoc = shader.getUniformLocation(gl, 'uDUDVOffset')
const shininessLoc = shader.getUniformLocation(gl, 'uShine')
const damperLoc = shader.getUniformLocation(gl, 'uShineDamper')
const distortLoc = shader.getUniformLocation(gl, 'uDistortionStrength')
const farLoc = shader.getUniformLocation(gl, 'uFarPlane')
const nearLoc = shader.getUniformLocation(gl, 'uNearPlane')
const sunPosLoc = shader.getUniformLocation(gl, 'uLightPosition')
const sunColorLoc = shader.getUniformLocation(gl, 'uLightColor')
@ -154,6 +171,11 @@ class WaterTile extends Node {
gl.uniform3fv(sunColorLoc, sun.color)
gl.uniform1f(reflectivityLoc, this.reflectivity)
gl.uniform1f(phaseLoc, this.phase)
gl.uniform1f(shininessLoc, this.shininess)
gl.uniform1f(damperLoc, this.shineDamper)
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)
@ -178,9 +200,19 @@ class WaterTile extends Node {
this.prepare(gl, shader, cam, sun)
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)
gl.disable(gl.BLEND)
}
update (dt) {
this.phase += 0.001
if (this.phase >= 1) this.phase = 0
}
}

View File

@ -28,7 +28,7 @@ async function pipeline () {
let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
water.initialize(game.gl)
await water.useDUDV(game.gl, 'dudv')
await water.useDUDVMap(game.gl, 'dudv')
await water.useNormalMap(game.gl, 'normalmap')
let arialFont = await Font.fromFile('arial')
@ -43,9 +43,8 @@ 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 is example text!\nmulti line!', arialFont, 1.5, new Dim4(0.1, 0.0, -0.1, 0.0), new Dim4(1.0, 0.0, 0.3, 0.0), false))
itms[0].children[0].color = [1.0, 0.0, 0.2]
itms[0].updateTransform()
itms[0].addChild(new GUIText('this project is coded by an idiot', arialFont, 1.5, new Dim4(0.1, 0.0, -0.1, 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
let hmap = new SimplexHeightMap(1, 1, 256, 50)
@ -76,9 +75,6 @@ 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)))
// Update function for camera and terrain
game.addUpdateFunction(function (dt) {
if (game.input.isDown('w')) {
@ -101,10 +97,16 @@ async function pipeline () {
// Update detail levels
terrain.update(game.gl, cam)
terrain.updateLODMesh(game.gl)
// Ripple water
water.update(dt)
})
function drawEverything (gl) {
game.prepare()
// Draw the skybox
skyboxShader.use(gl)
skybox.draw(gl, skyboxShader, cam)
// Use terrain shader
terrainShader.use(gl)
@ -121,10 +123,6 @@ async function pipeline () {
shader.use(gl)
cam.draw(gl, shader)
entity.draw(gl, shader)
// Draw the skybox
skyboxShader.use(gl)
skybox.draw(gl, skyboxShader, cam)
}
// Render function for the triangle