1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-14 00:54:05 +02:00

#23 add bubbles, fix water refraction quality

This commit is contained in:
XProger
2017-02-08 03:40:38 +03:00
parent 4c9ea91744
commit 86cf3f8db9
6 changed files with 84 additions and 34 deletions

View File

@@ -2,6 +2,7 @@
#define H_CHARACTER #define H_CHARACTER
#include "controller.h" #include "controller.h"
#include "trigger.h"
struct Character : Controller { struct Character : Controller {
int target; int target;
@@ -140,6 +141,18 @@ struct Character : Controller {
velocity.z = cosf(angleExt) * vel.z; velocity.z = cosf(angleExt) * vel.z;
stand = STAND_AIR; 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 #endif

View File

@@ -313,9 +313,8 @@ struct Controller {
return pos; return pos;
} }
void doBubbles() { virtual void doBubbles() {
if (rand() % 10 <= 6) return; //
playSound(TR::SND_BUBBLE, pos, Sound::Flags::PAN);
} }
void activateNext() { // activate next entity (for triggers) void activateNext() { // activate next entity (for triggers)

View File

@@ -483,7 +483,7 @@ struct Level : IGame {
// get refraction texture // get refraction texture
if (!refract || Core::width > refract->width || Core::height > refract->height) { if (!refract || Core::width > refract->width || Core::height > refract->height) {
delete refract; 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 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"); PROFILE_MARKER("PASS_COMPOSE");
setPassShader(Core::passCompose); setPassShader(Core::passCompose);
Core::setBlending(bmNone); Core::setBlending(bmAlpha);
Core::clear(vec4(0.0f)); Core::setDepthTest(true);
Core::setDepthWrite(true);
Core::clear(vec4(0.0f, 0.0f, 0.0f, 1.0f));
shadow->bind(sShadow); shadow->bind(sShadow);
renderScene(roomIndex); renderScene(roomIndex);
Core::setBlending(bmNone);
} }
void render() { void render() {

View File

@@ -73,6 +73,10 @@ uniform int uType;
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w); vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
#ifndef PASS_SHADOW
vColor = aColor;
#endif
#ifdef PASS_COMPOSE #ifdef PASS_COMPOSE
if (uType != TYPE_SPRITE) { if (uType != TYPE_SPRITE) {
// animated texture coordinates // animated texture coordinates
@@ -83,31 +87,27 @@ uniform int uType;
vTexCoord.xy = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated vTexCoord.xy = (aTexCoord.xy + offset) * TEXCOORD_SCALE; // first frame + offset * isAnimated
vNormal = vec4(mulQuat(rBasisRot, aNormal.xyz), aNormal.w); 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 { } else {
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w; coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE; vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE;
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0); 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)); vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
vViewVec = uViewPos - coord.xyz; vViewVec = uViewPos - coord.xyz;
vLightProj = uLightProj * coord; vLightProj = uLightProj * coord;
vCoord = coord.xyz; vCoord = coord.xyz;
#else
vTexCoord.xy = aTexCoord.xy * TEXCOORD_SCALE;
vTexCoord.zw = vec2(0.0);
#endif #endif
gl_Position = uViewProj * coord; gl_Position = uViewProj * coord;
@@ -268,8 +268,9 @@ uniform int uType;
#endif #endif
vec4 color = texture2D(sDiffuse, vTexCoord.xy); vec4 color = texture2D(sDiffuse, vTexCoord.xy);
if (color.w < 0.6) if (color.w <= 0.6) {
discard; discard;
}
#ifdef PASS_SHADOW #ifdef PASS_SHADOW
#ifdef SHADOW_COLOR #ifdef SHADOW_COLOR
@@ -281,7 +282,7 @@ uniform int uType;
color.xyz *= uColor.xyz; color.xyz *= uColor.xyz;
color.xyz *= vColor.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 #ifdef PASS_AMBIENT
color.xyz *= vColor.w; color.xyz *= vColor.w;
@@ -333,16 +334,16 @@ uniform int uType;
} }
#endif #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 #ifdef PASS_COMPOSE
color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST); color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST);
if (uCaustics != 0) { if (uCaustics != 0) {
float d = abs((vCoord.y - max(uViewPos.y, uParam.y)) / normalize(vViewVec).y); float d = abs((vCoord.y - max(uViewPos.y, uParam.y)) / normalize(vViewVec).y);
d *= step(0.0, vCoord.y - uParam.y); d *= step(0.0, vCoord.y - uParam.y);
color.xyz = applyFog(color.xyz, uColor.xyz * 0.2, d * WATER_FOG_DIST); color.xyz = applyFog(color.xyz, uColor.xyz * 0.2, d * WATER_FOG_DIST);
} }
#endif #endif
gl_FragColor = color; gl_FragColor = color;
#endif #endif

View File

@@ -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(); TR::Level *level = game->getLevel();
int index = level->entityAdd(type, room, x, y, z, 0, -1); int index = level->entityAdd(type, room, x, y, z, 0, -1);
if (index > -1) { if (index > -1) {
level->entities[index].intensity = 0x1FFF - level->rooms[room].ambient; 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() { TR::SpriteSequence& getSequence() {
return level->spriteSequences[-(getEntity().modelIndex + 1)]; return level->spriteSequences[-(getEntity().modelIndex + 1)];
} }
void update() { virtual void update() {
if (flag >= 0) return; if (flag >= 0) return;
bool remove = false; bool remove = false;

View File

@@ -338,7 +338,7 @@ struct Waterfall : Trigger {
dropStrength = randf() * 0.1f + 0.05f; dropStrength = randf() * 0.1f + 0.05f;
vec2 p = (vec2(randf(), randf()) * 2.0f - 1.0f) * (512.0f - dropRadius); 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); 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 #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 #endif