From 4c9ea91744a069f1f7085671fbfda171ad1abf74 Mon Sep 17 00:00:00 2001 From: XProger Date: Tue, 7 Feb 2017 05:46:14 +0300 Subject: [PATCH] #23 underwater fog --- src/core.h | 2 +- src/debug.h | 2 +- src/level.h | 56 ++++++++++++++++++++++++++++++------------------- src/shader.glsl | 20 ++++++++++++------ src/water.glsl | 27 +++++++++++++++++++----- 5 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/core.h b/src/core.h index 461593f..6726cb8 100644 --- a/src/core.h +++ b/src/core.h @@ -422,7 +422,7 @@ namespace Core { memset(&active, 0, sizeof(active)); glEnable(GL_DEPTH_TEST); setCulling(cfFront); - setBlending(bmAlpha); + setBlending(bmNone); } } diff --git a/src/debug.h b/src/debug.h index b991c31..2dd597f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -329,7 +329,7 @@ namespace Debug { glEnd(); glDepthMask(GL_TRUE); - Core::setBlending(bmAlpha); + Core::setBlending(bmNone); } void entities(const TR::Level &level) { diff --git a/src/level.h b/src/level.h index 918e852..1c672db 100644 --- a/src/level.h +++ b/src/level.h @@ -29,6 +29,9 @@ const char GUI[] = #include "gui.glsl" ; +#define FOG_DIST (18 * 1024) +#define WATER_FOG_DIST (8 * 1024) + struct Level : IGame { enum { shCompose, shShadow, shAmbient, shFilter, shWater, shGUI, shMAX }; @@ -42,9 +45,14 @@ struct Level : IGame { Camera *camera; Texture *shadow; - float time; - float clipHeight; - float clipSign; + vec3 waterColor; + + struct { + float time; + float waterHeight; + float clipSign; + float clipHeight; + } params; struct AmbientCache { Level *level; @@ -374,10 +382,13 @@ struct Level : IGame { if (!item || !item->caustics) { Core::blackTex->bind(sReflect); Core::active.shader->setParam(uRoomSize, vec4(0.0f)); + level->params.waterHeight = -10000000.0f; } else { item->caustics->bind(sReflect); Core::active.shader->setParam(uRoomSize, vec4(item->pos.x - item->size.x, item->pos.z - item->size.z, item->pos.x + item->size.x, item->pos.z + item->size.z)); + level->params.waterHeight = item->pos.y; } + Core::active.shader->setParam(uParam, *((vec4*)&level->params)); } void addDrop(const vec3 &pos, float radius, float strength) { @@ -497,11 +508,11 @@ struct Level : IGame { //bool underwater = level->camera->pos.y > item.pos.y; level->camera->reflectPlane = &reflectPlane; - level->clipSign = underwater ? -1.0f : 1.0f; - level->clipHeight = item.pos.y * level->clipSign; + level->params.clipSign = underwater ? -1.0f : 1.0f; + level->params.clipHeight = item.pos.y * level->params.clipSign; level->renderCompose(underwater ? item.from : item.to); - level->clipHeight = 1000000.0f; - level->clipSign = 1.0f; + level->params.clipHeight = 1000000.0f; + level->params.clipSign = 1.0f; level->camera->reflectPlane = NULL; level->camera->setup(true); @@ -509,7 +520,6 @@ struct Level : IGame { // simulate water level->setPassShader(Core::passWater); - Core::setBlending(bmNone); Core::setDepthTest(false); item.mask->bind(sMask); @@ -522,7 +532,6 @@ struct Level : IGame { } Core::setTarget(NULL); - Core::setBlending(bmAlpha); Core::setDepthTest(true); // render water plane @@ -540,6 +549,7 @@ struct Level : IGame { Core::active.shader->setParam(uLightPos, Core::lightPos[0], 1); Core::active.shader->setParam(uLightColor, Core::lightColor[0], 1); Core::active.shader->setParam(uParam, vec4(float(Core::width) / refract->width, float(Core::height) / refract->height, 0.05f, 0.02f)); + Core::active.shader->setParam(uColor, vec4(level->waterColor * 0.2f, 1.0f)); float sx = item.size.x * DETAIL / (item.data[0]->width / 2); float sz = item.size.z * DETAIL / (item.data[0]->height / 2); @@ -618,7 +628,9 @@ struct Level : IGame { } - Level(Stream &stream, bool demo, bool home) : level(stream, demo), lara(NULL), time(0.0f) { + Level(Stream &stream, bool demo, bool home) : level(stream, demo), lara(NULL), waterColor(0.6f, 0.9f, 0.9f) { + params.time = 0.0f; + #ifdef _DEBUG Debug::init(); #endif @@ -817,14 +829,15 @@ struct Level : IGame { else strcat(ext, "#define SHADOW_COLOR\n"); - sprintf(def, "%s#define PASS_COMPOSE\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n", ext, MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount); + sprintf(def, "%s#define PASS_COMPOSE\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, MAX_LIGHTS, mesh->animTexRangesCount, mesh->animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST); shaders[shCompose] = new Shader(SHADER, def); sprintf(def, "%s#define PASS_SHADOW\n", ext); shaders[shShadow] = new Shader(SHADER, def); sprintf(def, "%s#define PASS_AMBIENT\n", ext); shaders[shAmbient] = new Shader(SHADER, def); shaders[shFilter] = new Shader(FILTER, ""); - shaders[shWater] = new Shader(WATER, ""); + sprintf(def, "#define WATER_FOG_DIST (1.0/%d.0)\n", WATER_FOG_DIST); + shaders[shWater] = new Shader(WATER, def); shaders[shGUI] = new Shader(GUI, ""); } @@ -947,7 +960,7 @@ struct Level : IGame { TR::Room &room = level.rooms[roomIndex]; if (room.flags.water) { - Core::color = vec4(0.6f, 0.9f, 0.9f, intensity); + Core::color = vec4(waterColor, intensity); Core::active.shader->setParam(uCaustics, 1); /* // trace to water surface room @@ -1120,7 +1133,7 @@ struct Level : IGame { } void update() { - time += Core::deltaTime; + params.time += Core::deltaTime; for (int i = 0; i < level.entitiesCount; i++) { TR::Entity &e = level.entities[i]; @@ -1162,7 +1175,7 @@ struct Level : IGame { sh->setParam(uLightProj, Core::mLightProj); sh->setParam(uViewInv, Core::mViewInv); sh->setParam(uViewPos, Core::viewPos); - sh->setParam(uParam, vec4(time, 0.0f, clipSign, clipHeight)); + sh->setParam(uParam, *((vec4*)¶ms)); sh->setParam(uLightsCount, 3); sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount); sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount); @@ -1270,7 +1283,6 @@ struct Level : IGame { for (int i = 0; i < 6; i++) { setupCubeCamera(pos, i); setPassShader(Core::passAmbient); - Core::setBlending(bmAlpha); Texture *target = targets[0]->cube ? targets[0] : targets[i * stride]; Core::setTarget(target, i); Core::clear(vec4(0, 0, 0, 1)); @@ -1297,15 +1309,16 @@ struct Level : IGame { PROFILE_MARKER("PASS_COMPOSE"); setPassShader(Core::passCompose); - Core::setBlending(bmAlpha); + Core::setBlending(bmNone); Core::clear(vec4(0.0f)); shadow->bind(sShadow); renderScene(roomIndex); } void render() { - clipHeight = 1000000.0f; - clipSign = 1.0f; + params.clipHeight = 1000000.0f; + params.clipSign = 1.0f; + params.waterHeight = params.clipHeight; Core::resetStates(); ambientCache->precessQueue(); @@ -1359,7 +1372,7 @@ struct Level : IGame { // renderModel(level.models[modelIndex], level.entities[4]); */ Debug::begin(); - + /* glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); @@ -1397,6 +1410,7 @@ struct Level : IGame { glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); + */ // Debug::Level::rooms(level, lara->pos, lara->getEntity().room); @@ -1406,7 +1420,7 @@ struct Level : IGame { // Debug::Level::portals(level); // Core::setDepthTest(true); // Debug::Level::meshes(level); - Debug::Level::entities(level); + // Debug::Level::entities(level); /* static int dbg_ambient = 0; dbg_ambient = int(time * 2) % 4; diff --git a/src/shader.glsl b/src/shader.glsl index 6aaed3d..2add420 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -25,6 +25,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords uniform int uType; #ifdef PASS_COMPOSE + uniform vec3 uViewPos; uniform int uCaustics; uniform vec4 uParam; uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ @@ -40,7 +41,6 @@ uniform int uType; #endif #ifdef PASS_COMPOSE - uniform vec3 uViewPos; uniform vec2 uAnimTexRanges[MAX_RANGES]; uniform vec2 uAnimTexOffsets[MAX_OFFSETS]; #endif @@ -235,6 +235,11 @@ uniform int uType; return 0.0; } + vec3 applyFog(vec3 color, vec3 fogColor, float factor) { + float fog = clamp(1.0 / exp(factor), 0.0, 1.0); + return mix(fogColor, color, fog); +// return color.xyz * exp(factor); + } #endif /* float getLuminance(vec3 color) { @@ -323,8 +328,6 @@ uniform int uType; } color.xyz *= light; - -//color.xyz = normal * 0.5 + 0.5; } else { color.w = uColor.w; } @@ -332,9 +335,14 @@ uniform int uType; color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); // back to gamma space - // apply fog - float fog = clamp(1.0 / exp(gl_FragCoord.z / gl_FragCoord.w * 0.000025), 0.0, 1.0); - color = mix(vec4(0.0, 0.0, 0.0, 1.0), color, fog); + #ifdef PASS_COMPOSE + color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST); + if (uCaustics != 0) { + float d = abs((vCoord.y - max(uViewPos.y, uParam.y)) / normalize(vViewVec).y); + d *= step(0.0, vCoord.y - uParam.y); + color.xyz = applyFog(color.xyz, uColor.xyz * 0.2, d * WATER_FOG_DIST); + } + #endif gl_FragColor = color; #endif diff --git a/src/water.glsl b/src/water.glsl index 56d656a..c4eca75 100644 --- a/src/water.glsl +++ b/src/water.glsl @@ -9,6 +9,8 @@ varying vec2 vTexCoord; varying vec4 vProjCoord; varying vec3 vRefPos1; varying vec3 vRefPos2; +varying vec3 vViewVec; +varying vec3 vLightVec; #define WATER_DROP 0 #define WATER_STEP 1 @@ -19,10 +21,12 @@ varying vec3 vRefPos2; uniform int uType; uniform vec3 uViewPos; uniform mat4 uViewProj; +uniform vec3 uLightPos; uniform vec3 uPosScale[2]; uniform vec4 uTexParam; uniform vec4 uParam; +uniform vec4 uColor; uniform sampler2D sNormal; @@ -72,14 +76,15 @@ uniform sampler2D sNormal; gl_Position = vec4(aCoord.xyz, 1.0); } - } + } + vViewVec = uViewPos - vCoord.xyz; + vLightVec = uLightPos - vCoord.xyz; } #else uniform sampler2D sDiffuse; uniform sampler2D sReflect; uniform sampler2D sMask; - uniform vec3 uLightPos; uniform vec4 uLightColor; #define PI 3.141592653589793 @@ -89,6 +94,11 @@ uniform sampler2D sNormal; return clamp(fbias + (1.0 - fbias) * pow(f, fpow), 0.0, 1.0); } + vec3 applyFog(vec3 color, vec3 fogColor, float factor) { + float fog = clamp(1.0 / exp(factor), 0.0, 1.0); + return mix(fogColor, color, fog); + } + vec4 drop() { vec2 tc = gl_FragCoord.xy * uTexParam.xy; vec4 v = texture2D(sDiffuse, tc); @@ -146,9 +156,9 @@ uniform sampler2D sNormal; vec2 dudv = (uViewProj * vec4(normal.x, 0.0, normal.z, 0.0)).xy; - vec3 viewVec = normalize(uViewPos - vCoord); + vec3 viewVec = normalize(vViewVec); vec3 rv = reflect(-viewVec, normal); - vec3 lv = normalize(uLightPos - vCoord.xyz); + vec3 lv = normalize(vLightVec); float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5; @@ -158,7 +168,14 @@ uniform sampler2D sNormal; vec4 refl = texture2D(sReflect, vec2(tc.x, 1.0 - tc.y) + dudv * uParam.w); float fresnel = calcFresnel(dot(normal, viewVec), 0.1, 2.0); - return mix(refr, refl, fresnel) + spec; + + vec4 color = mix(refr, refl, fresnel) + spec; + + float d = abs((vCoord.y - uViewPos.y) / normalize(vViewVec).y); + d *= step(0.0, uViewPos.y - vCoord.y); // apply fog only when camera is underwater + color.xyz = applyFog(color.xyz, uColor.xyz, d * WATER_FOG_DIST); + + return color; } vec4 pass() {