WORKING WATER! (no clipping planes implemented)
This commit is contained in:
parent
d55389dacb
commit
7590e7930e
@ -9,37 +9,38 @@ uniform sampler2D normalMap;
|
|||||||
uniform sampler2D depthMap;
|
uniform sampler2D depthMap;
|
||||||
|
|
||||||
uniform float uReflectivity;
|
uniform float uReflectivity;
|
||||||
uniform vec4 uTint;
|
|
||||||
uniform float uDUDVOffset;
|
uniform float uDUDVOffset;
|
||||||
uniform vec3 uLightColor;
|
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 vec2 uv;
|
||||||
varying vec3 toCameraVector;
|
varying vec3 toCameraVector;
|
||||||
varying vec3 fromLightVector;
|
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() {
|
void main() {
|
||||||
vec2 ndc = (clipSpace.xy / clipSpace.w) / 2.0 + 0.5;
|
vec2 ndc = (clipSpace.xy / clipSpace.w) / 2.0 + 0.5;
|
||||||
vec2 refractTexCoords = vec2(ndc.x, ndc.y);
|
vec2 refractTexCoords = vec2(ndc.x, ndc.y);
|
||||||
vec2 reflectTexCoords = vec2(ndc.x, -ndc.y);
|
vec2 reflectTexCoords = vec2(ndc.x, -ndc.y);
|
||||||
|
|
||||||
float depth = 2.0 * texture2D(depthMap, refractTexCoords).r - 1.0;
|
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;
|
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;
|
float waterDepth = floorDistance - waterDistance;
|
||||||
|
|
||||||
vec2 distortedTexCoords = texture2D(dudvMap, vec2(uv.x + uDUDVOffset, uv.y)).rg * 0.1;
|
vec2 distortedTexCoords = texture2D(dudvMap, vec2(uv.x + uDUDVOffset, uv.y)).rg * 0.1;
|
||||||
distortedTexCoords = uv + vec2(distortedTexCoords.x, distortedTexCoords.y + uDUDVOffset);
|
distortedTexCoords = uv + vec2(distortedTexCoords.x, distortedTexCoords.y + uDUDVOffset);
|
||||||
|
|
||||||
// Between -1 and 1
|
// 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;
|
refractTexCoords += totalDistortion;
|
||||||
reflectTexCoords += 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);
|
vec3 normal = vec3(normalMapColor.r * 2.0 - 1.0, normalMapColor.b, normalMapColor.g * 2.0 - 1.0);
|
||||||
normal = normalize(normal);
|
normal = normalize(normal);
|
||||||
|
|
||||||
|
float depthAlpha = clamp(waterDepth / 5.0, 0.0, 1.0);
|
||||||
|
|
||||||
vec3 reflectedLight = reflect(normalize(fromLightVector), normal);
|
vec3 reflectedLight = reflect(normalize(fromLightVector), normal);
|
||||||
float specular = max(dot(reflectedLight, viewVector), 0.0);
|
float specular = max(dot(reflectedLight, viewVector), 0.0);
|
||||||
specular = pow(specular, shineDamper);
|
specular = pow(specular, uShineDamper);
|
||||||
vec3 specularHighlights = uLightColor * specular * reflectivity;
|
vec3 specularHighlights = uLightColor * specular * uShine * depthAlpha;
|
||||||
|
|
||||||
gl_FragColor = mix(reflectColor, refractColor, refractiveFactor);
|
gl_FragColor = mix(reflectColor, refractColor, refractiveFactor);
|
||||||
gl_FragColor = mix(gl_FragColor, vec4(uTint.xyz, 1.0), uTint.w) + vec4(specularHighlights, 0.0);
|
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 |
@ -37,7 +37,7 @@ class WaterFBOs {
|
|||||||
// create the framebuffer
|
// create the framebuffer
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer)
|
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer)
|
||||||
// indicate that we will always render to color attachment 0
|
// 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
|
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.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_MAG_FILTER, gl.NEAREST)
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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)
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, texture, 0)
|
||||||
return texture
|
return texture
|
||||||
}
|
}
|
||||||
@ -94,12 +96,17 @@ class WaterFBOs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class WaterTile extends Node {
|
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])
|
super(pos, [scale, 0.0, scale])
|
||||||
this.fbos = new WaterFBOs()
|
this.fbos = new WaterFBOs()
|
||||||
|
|
||||||
this.reflectivity = reflectivity
|
this.reflectivity = reflectivity
|
||||||
this.tint = tint
|
this.tint = tint
|
||||||
this.phase = 1.0
|
this.phase = 1.0
|
||||||
|
|
||||||
|
this.shininess = 0.7
|
||||||
|
this.shineDamper = 20.0
|
||||||
|
this.distortionStrength = 0.02
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize (gl) {
|
initialize (gl) {
|
||||||
@ -107,7 +114,7 @@ class WaterTile extends Node {
|
|||||||
this.fbos.initialize(gl)
|
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)
|
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) {
|
prepare (gl, shader, cam, sun) {
|
||||||
const transformLoc = shader.getUniformLocation(gl, 'uModelMatrix')
|
const transformLoc = shader.getUniformLocation(gl, 'uModelMatrix')
|
||||||
|
|
||||||
const camPosLoc = shader.getUniformLocation(gl, 'uCameraPosition')
|
const camPosLoc = shader.getUniformLocation(gl, 'uCameraPosition')
|
||||||
const refrLoc = shader.getUniformLocation(gl, 'refractionTexture')
|
const refrLoc = shader.getUniformLocation(gl, 'refractionTexture')
|
||||||
const reflLoc = shader.getUniformLocation(gl, 'reflectionTexture')
|
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 dudvLoc = shader.getUniformLocation(gl, 'dudvMap')
|
||||||
const normalLoc = shader.getUniformLocation(gl, 'dudvMap')
|
const normalLoc = shader.getUniformLocation(gl, 'normalMap')
|
||||||
|
|
||||||
const reflectivityLoc = shader.getUniformLocation(gl, 'uReflectivity')
|
const reflectivityLoc = shader.getUniformLocation(gl, 'uReflectivity')
|
||||||
const tintLoc = shader.getUniformLocation(gl, 'uTint')
|
const tintLoc = shader.getUniformLocation(gl, 'uTint')
|
||||||
const phaseLoc = shader.getUniformLocation(gl, 'uDUDVOffset')
|
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 sunPosLoc = shader.getUniformLocation(gl, 'uLightPosition')
|
||||||
const sunColorLoc = shader.getUniformLocation(gl, 'uLightColor')
|
const sunColorLoc = shader.getUniformLocation(gl, 'uLightColor')
|
||||||
|
|
||||||
@ -154,6 +171,11 @@ class WaterTile extends Node {
|
|||||||
gl.uniform3fv(sunColorLoc, sun.color)
|
gl.uniform3fv(sunColorLoc, sun.color)
|
||||||
gl.uniform1f(reflectivityLoc, this.reflectivity)
|
gl.uniform1f(reflectivityLoc, this.reflectivity)
|
||||||
gl.uniform1f(phaseLoc, this.phase)
|
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.uniform4fv(tintLoc, this.tint)
|
||||||
gl.uniform1i(reflLoc, 0)
|
gl.uniform1i(reflLoc, 0)
|
||||||
gl.uniform1i(refrLoc, 1)
|
gl.uniform1i(refrLoc, 1)
|
||||||
@ -178,9 +200,19 @@ class WaterTile extends Node {
|
|||||||
|
|
||||||
this.prepare(gl, shader, cam, sun)
|
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.prepare(gl, shader)
|
||||||
this.mesh.draw(gl, shader)
|
this.mesh.draw(gl, shader)
|
||||||
this.mesh.postdraw(gl, shader)
|
this.mesh.postdraw(gl, shader)
|
||||||
|
|
||||||
|
gl.disable(gl.BLEND)
|
||||||
|
}
|
||||||
|
|
||||||
|
update (dt) {
|
||||||
|
this.phase += 0.001
|
||||||
|
if (this.phase >= 1) this.phase = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/index.js
20
src/index.js
@ -28,7 +28,7 @@ async function pipeline () {
|
|||||||
|
|
||||||
let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
|
let water = new WaterTile([100.0, 0.0, 100.0], 100.0)
|
||||||
water.initialize(game.gl)
|
water.initialize(game.gl)
|
||||||
await water.useDUDV(game.gl, 'dudv')
|
await water.useDUDVMap(game.gl, 'dudv')
|
||||||
await water.useNormalMap(game.gl, 'normalmap')
|
await water.useNormalMap(game.gl, 'normalmap')
|
||||||
|
|
||||||
let arialFont = await Font.fromFile('arial')
|
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))
|
new Dim4(-0.9, 0.0, 0.9, 0.0), new Dim4(0.1, 0.0, 0.1, 0.0))
|
||||||
]
|
]
|
||||||
// Nesting test
|
// 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].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 = [1.0, 0.0, 0.2]
|
itms[0].children[0].color = [0.0, 0.2, 1.0]
|
||||||
itms[0].updateTransform()
|
|
||||||
|
|
||||||
// Create a height map based on OpenSimplex noise
|
// Create a height map based on OpenSimplex noise
|
||||||
let hmap = new SimplexHeightMap(1, 1, 256, 50)
|
let hmap = new SimplexHeightMap(1, 1, 256, 50)
|
||||||
@ -76,9 +75,6 @@ async function pipeline () {
|
|||||||
// Load textures and generate a mesh
|
// Load textures and generate a mesh
|
||||||
await skybox.initialize(game.gl)
|
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
|
// Update function for camera and terrain
|
||||||
game.addUpdateFunction(function (dt) {
|
game.addUpdateFunction(function (dt) {
|
||||||
if (game.input.isDown('w')) {
|
if (game.input.isDown('w')) {
|
||||||
@ -101,10 +97,16 @@ async function pipeline () {
|
|||||||
// Update detail levels
|
// Update detail levels
|
||||||
terrain.update(game.gl, cam)
|
terrain.update(game.gl, cam)
|
||||||
terrain.updateLODMesh(game.gl)
|
terrain.updateLODMesh(game.gl)
|
||||||
|
|
||||||
|
// Ripple water
|
||||||
|
water.update(dt)
|
||||||
})
|
})
|
||||||
|
|
||||||
function drawEverything (gl) {
|
function drawEverything (gl) {
|
||||||
game.prepare()
|
game.prepare()
|
||||||
|
// Draw the skybox
|
||||||
|
skyboxShader.use(gl)
|
||||||
|
skybox.draw(gl, skyboxShader, cam)
|
||||||
|
|
||||||
// Use terrain shader
|
// Use terrain shader
|
||||||
terrainShader.use(gl)
|
terrainShader.use(gl)
|
||||||
@ -121,10 +123,6 @@ async function pipeline () {
|
|||||||
shader.use(gl)
|
shader.use(gl)
|
||||||
cam.draw(gl, shader)
|
cam.draw(gl, shader)
|
||||||
entity.draw(gl, shader)
|
entity.draw(gl, shader)
|
||||||
|
|
||||||
// Draw the skybox
|
|
||||||
skyboxShader.use(gl)
|
|
||||||
skybox.draw(gl, skyboxShader, cam)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render function for the triangle
|
// Render function for the triangle
|
||||||
|
Loading…
Reference in New Issue
Block a user