From 86cf3f8db922d122857c1f3a63e7487c8055eb82 Mon Sep 17 00:00:00 2001 From: XProger Date: Wed, 8 Feb 2017 03:40:38 +0300 Subject: [PATCH] #23 add bubbles, fix water refraction quality --- src/character.h | 13 +++++++++++++ src/controller.h | 5 ++--- src/level.h | 9 ++++++--- src/shader.glsl | 49 ++++++++++++++++++++++++------------------------ src/sprite.h | 7 ++++--- src/trigger.h | 35 +++++++++++++++++++++++++++++++++- 6 files changed, 84 insertions(+), 34 deletions(-) diff --git a/src/character.h b/src/character.h index be732ae..1b6eef2 100644 --- a/src/character.h +++ b/src/character.h @@ -2,6 +2,7 @@ #define H_CHARACTER #include "controller.h" +#include "trigger.h" struct Character : Controller { int target; @@ -140,6 +141,18 @@ struct Character : Controller { velocity.z = cosf(angleExt) * vel.z; stand = STAND_AIR; } + + virtual void doBubbles() { + int count = rand() % 3; + if (!count) return; + playSound(TR::SND_BUBBLE, pos, Sound::Flags::PAN); + vec3 head = animation.getJoints(getMatrix(), 14, true) * vec3(0.0f, 0.0f, 50.0f); + for (int i = 0; i < count; i++) { + int index = Sprite::add(game, TR::Entity::BUBBLE, getRoomIndex(), int(head.x), int(head.y), int(head.z), Sprite::FRAME_RANDOM, true); + if (index > -1) + level->entities[index].controller = new Bubble(game, index); + } + } }; #endif \ No newline at end of file diff --git a/src/controller.h b/src/controller.h index 51eff1d..ba1f5e2 100644 --- a/src/controller.h +++ b/src/controller.h @@ -313,9 +313,8 @@ struct Controller { return pos; } - void doBubbles() { - if (rand() % 10 <= 6) return; - playSound(TR::SND_BUBBLE, pos, Sound::Flags::PAN); + virtual void doBubbles() { + // } void activateNext() { // activate next entity (for triggers) diff --git a/src/level.h b/src/level.h index 1c672db..8bacf21 100644 --- a/src/level.h +++ b/src/level.h @@ -483,7 +483,7 @@ struct Level : IGame { // get refraction texture if (!refract || Core::width > refract->width || Core::height > refract->height) { delete refract; - refract = new Texture(nextPow2(Core::width), nextPow2(Core::height), Texture::RGBA16, false); + refract = new Texture(nextPow2(Core::width), nextPow2(Core::height), Texture::RGBA, false); } Core::copyTarget(refract, 0, 0, 0, 0, Core::width, Core::height); // copy framebuffer into refraction texture @@ -1309,10 +1309,13 @@ struct Level : IGame { PROFILE_MARKER("PASS_COMPOSE"); setPassShader(Core::passCompose); - Core::setBlending(bmNone); - Core::clear(vec4(0.0f)); + Core::setBlending(bmAlpha); + Core::setDepthTest(true); + Core::setDepthWrite(true); + Core::clear(vec4(0.0f, 0.0f, 0.0f, 1.0f)); shadow->bind(sShadow); renderScene(roomIndex); + Core::setBlending(bmNone); } void render() { diff --git a/src/shader.glsl b/src/shader.glsl index 2add420..5d47934 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -73,6 +73,10 @@ uniform int uType; vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w); + #ifndef PASS_SHADOW + vColor = aColor; + #endif + #ifdef PASS_COMPOSE if (uType != TYPE_SPRITE) { // animated texture coordinates @@ -83,31 +87,27 @@ uniform int uType; vTexCoord.xy = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated vNormal = vec4(mulQuat(rBasisRot, aNormal.xyz), aNormal.w); + + if (uCaustics != 0) { + float sum = coord.x + coord.y + coord.z; + vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 1.5 + 0.5; // color dodge + } + } else { coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w; vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE; vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0); } - #else - vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE; - vTexCoord.zw = vec2(0.0); - #endif - #ifndef PASS_SHADOW - vColor = aColor; - #endif - - #ifdef PASS_COMPOSE - if (uCaustics != 0) { - float sum = coord.x + coord.y + coord.z; - vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 1.5 + 0.5; // color dodge - } vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0)); vViewVec = uViewPos - coord.xyz; vLightProj = uLightProj * coord; vCoord = coord.xyz; + #else + vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE; + vTexCoord.zw = vec2(0.0); #endif gl_Position = uViewProj * coord; @@ -268,8 +268,9 @@ uniform int uType; #endif vec4 color = texture2D(sDiffuse, vTexCoord.xy); - if (color.w < 0.6) + if (color.w <= 0.6) { discard; + } #ifdef PASS_SHADOW #ifdef SHADOW_COLOR @@ -281,7 +282,7 @@ uniform int uType; color.xyz *= uColor.xyz; color.xyz *= vColor.xyz; - color.xyz = pow(abs(color.xyz), vec3(2.2)); // to linear space + color *= color; // to "linear" space #ifdef PASS_AMBIENT color.xyz *= vColor.w; @@ -333,16 +334,16 @@ uniform int uType; } #endif - color.xyz = pow(abs(color.xyz), vec3(1.0/2.2)); // back to gamma space + color = sqrt(color); // back to "gamma" space - #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 + #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/sprite.h b/src/sprite.h index 00a97db..c237f1f 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -24,20 +24,21 @@ struct Sprite : Controller { } } - static void add(IGame *game, TR::Entity::Type type, int room, int x, int y, int z, int frame = -1) { + static int add(IGame *game, TR::Entity::Type type, int room, int x, int y, int z, int frame = -1, bool empty = false) { TR::Level *level = game->getLevel(); int index = level->entityAdd(type, room, x, y, z, 0, -1); if (index > -1) { level->entities[index].intensity = 0x1FFF - level->rooms[room].ambient; - level->entities[index].controller = new Sprite(game, index, true, frame); + level->entities[index].controller = empty ? NULL : new Sprite(game, index, true, frame); } + return index; } TR::SpriteSequence& getSequence() { return level->spriteSequences[-(getEntity().modelIndex + 1)]; } - void update() { + virtual void update() { if (flag >= 0) return; bool remove = false; diff --git a/src/trigger.h b/src/trigger.h index f1292f5..77570f3 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -338,7 +338,7 @@ struct Waterfall : Trigger { dropStrength = randf() * 0.1f + 0.05f; vec2 p = (vec2(randf(), randf()) * 2.0f - 1.0f) * (512.0f - dropRadius); - dropPos = pos + vec3(p.x, 0.0f, p.y); + dropPos = pos + vec3(p.x, 0.0f, p.y); Sprite::add(game, TR::Entity::WATER_SPLASH, getRoomIndex(), (int)dropPos.x, (int)dropPos.y, (int)dropPos.z); } @@ -346,4 +346,37 @@ struct Waterfall : Trigger { #undef SPLASH_TIMESTEP }; +struct Bubble : Sprite { + float speed; + + Bubble(IGame *game, int entity) : Sprite(game, entity, true, Sprite::FRAME_RANDOM) { + speed = (10.0f + randf() * 6.0) * 30.0f; + // get water height => bubble life time + TR::Entity &e = getEntity(); + int dx, dz; + int room = getRoomIndex(); + int h = e.y; + while (room != TR::NO_ROOM && level->rooms[room].flags.water) { + TR::Room::Sector &s = level->getSector(room, e.x, e.z, dx, dz); + h = s.ceiling * 256; + room = s.roomAbove; + } + time -= (e.y - h) / speed - (1.0f / SPRITE_FPS); + } + + virtual ~Bubble() { + game->waterDrop(pos, 64.0f, 0.01f); + } + + virtual void update() { + pos.y -= speed * Core::deltaTime; + angle.x += 30.0f * 13.0f * DEG2RAD * Core::deltaTime; + angle.y += 30.0f * 9.0f * DEG2RAD * Core::deltaTime; + pos.x += sin(angle.y) * 11.0f * 30.0f * Core::deltaTime; + pos.z += cos(angle.x) * 8.0f * 30.0f * Core::deltaTime; + updateEntity(); + Sprite::update(); + } +}; + #endif \ No newline at end of file