mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-14 09:04:31 +02:00
#23 add bubbles, fix water refraction quality
This commit is contained in:
@@ -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
|
@@ -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)
|
||||||
|
@@ -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() {
|
||||||
|
@@ -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,7 +334,7 @@ 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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
Reference in New Issue
Block a user