mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-15 01:24:35 +02:00
#22 fix pickup offsets, fix qualopec scion pickup; #22 fix bats falling after death, fix qualopec mummy hit points for blood sprites, fix Lara blocking with enemies; #23 add stereo mode support for 3D displays (SBS)
This commit is contained in:
@@ -691,7 +691,7 @@ struct WaterCache {
|
||||
Core::invalidateTarget(false, true);
|
||||
Core::setTarget(NULL);
|
||||
}
|
||||
Core::copyTarget(refract, 0, 0, 0, 0, w, h); // copy framebuffer into refraction texture
|
||||
Core::copyTarget(refract, 0, 0, int(Core::viewportDef.x), int(Core::viewportDef.y), w, h); // copy framebuffer into refraction texture
|
||||
}
|
||||
|
||||
void simulate() {
|
||||
|
13
src/camera.h
13
src/camera.h
@@ -39,10 +39,7 @@ struct Camera : ICamera {
|
||||
Controller* viewTarget;
|
||||
float speed;
|
||||
|
||||
bool firstPerson;
|
||||
bool isVR;
|
||||
|
||||
Camera(IGame *game, Character *owner) : ICamera(), game(game), level(game->getLevel()), owner(owner), frustum(new Frustum()), timer(-1.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL), isVR(false) {
|
||||
Camera(IGame *game, Character *owner) : ICamera(), game(game), level(game->getLevel()), owner(owner), frustum(new Frustum()), timer(-1.0f), viewIndex(-1), viewIndexLast(-1), viewTarget(NULL) {
|
||||
changeView(false);
|
||||
if (owner->getEntity().type != TR::Entity::LARA && level->cameraFrames) {
|
||||
state = STATE_CUTSCENE;
|
||||
@@ -323,10 +320,12 @@ struct Camera : ICamera {
|
||||
}
|
||||
|
||||
mViewInv = mat4(pos, target, vec3(0, -1, 0));
|
||||
if (isVR) {
|
||||
/*
|
||||
if (Core::settings.detail.VR) {
|
||||
mat4 head = Input::head.getMatrix();
|
||||
mViewInv = mViewInv * head;
|
||||
}
|
||||
*/
|
||||
updateListener();
|
||||
}
|
||||
|
||||
@@ -347,8 +346,8 @@ struct Camera : ICamera {
|
||||
if (shake > 0.0f)
|
||||
Core::mView.translate(vec3(0.0f, sinf(shake * PI * 7) * shake * 48.0f, 0.0f));
|
||||
|
||||
if (isVR)
|
||||
Core::mView.translate(Core::mViewInv.right.xyz * (-Core::eye * 32.0f));
|
||||
if (Core::settings.detail.stereo)
|
||||
Core::mView.translate(Core::mViewInv.right.xyz * (-Core::eye * (firstPerson ? 8.0f : 32.0f) ));
|
||||
|
||||
Core::mProj = getProjMatrix();
|
||||
|
||||
|
@@ -21,6 +21,7 @@ struct ICamera {
|
||||
vec4 *reflectPlane;
|
||||
vec3 pos;
|
||||
float shake;
|
||||
bool firstPerson;
|
||||
|
||||
ICamera() : reflectPlane(NULL), pos(0.0f), shake(0.0f) {}
|
||||
|
||||
|
20
src/core.h
20
src/core.h
@@ -186,14 +186,17 @@ namespace Core {
|
||||
struct Settings {
|
||||
enum Quality : uint8 { LOW, MEDIUM, HIGH };
|
||||
|
||||
union {
|
||||
struct {
|
||||
Quality filter;
|
||||
Quality lighting;
|
||||
Quality shadows;
|
||||
Quality water;
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
Quality filter;
|
||||
Quality lighting;
|
||||
Quality shadows;
|
||||
Quality water;
|
||||
};
|
||||
Quality quality[4];
|
||||
};
|
||||
Quality quality[4];
|
||||
bool stereo;
|
||||
|
||||
void setFilter(Quality value) {
|
||||
if (value > MEDIUM && !(support.maxAniso > 1))
|
||||
@@ -448,7 +451,7 @@ namespace Core {
|
||||
mat4 mView, mProj, mViewProj, mViewInv, mLightProj;
|
||||
Basis basis;
|
||||
vec3 viewPos;
|
||||
vec3 lightPos[MAX_LIGHTS];
|
||||
vec4 lightPos[MAX_LIGHTS];
|
||||
vec4 lightColor[MAX_LIGHTS];
|
||||
vec4 params;
|
||||
vec4 contacts[MAX_CONTACTS];
|
||||
@@ -688,6 +691,7 @@ namespace Core {
|
||||
settings.detail.setLighting (Core::Settings::HIGH);
|
||||
settings.detail.setShadows (Core::Settings::HIGH);
|
||||
settings.detail.setWater (Core::Settings::HIGH);
|
||||
settings.detail.stereo = false;
|
||||
|
||||
settings.audio.music = 0.7f;
|
||||
settings.audio.sound = 0.7f;
|
||||
|
@@ -537,7 +537,7 @@ namespace Debug {
|
||||
TR::Entity &t = level.entities[j];
|
||||
if (j == i || ((!t.isEnemy() || !t.flags.active) && t.type != TR::Entity::LARA)) continue;
|
||||
Controller *enemy = (Controller*)t.controller;
|
||||
if (!controller->getBoundingBox().intersect(enemy->getBoundingBox()))
|
||||
if (!enemy || !controller->getBoundingBox().intersect(enemy->getBoundingBox()))
|
||||
continue;
|
||||
bboxIntersect = true;
|
||||
mask |= controller->collide(enemy);
|
||||
|
11
src/enemy.h
11
src/enemy.h
@@ -850,6 +850,17 @@ struct Bat : Enemy {
|
||||
lift(waypoint.y - pos.y, BAT_LIFT_SPEED);
|
||||
Enemy::updatePosition();
|
||||
}
|
||||
|
||||
virtual void deactivate(bool removeFromList = false) {
|
||||
if (health <= 0.0f) {
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info);
|
||||
if (info.floor > pos.y)
|
||||
return;
|
||||
pos.y = float(info.floor);
|
||||
}
|
||||
Enemy::deactivate(removeFromList);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@@ -619,7 +619,7 @@ namespace TR {
|
||||
};
|
||||
|
||||
TR::Vertex center;
|
||||
uint16 radius;
|
||||
int16 radius;
|
||||
union {
|
||||
struct {
|
||||
uint16 transparent:1, reserved:15;
|
||||
|
@@ -466,10 +466,10 @@ struct Inventory {
|
||||
}
|
||||
|
||||
if (item->type == TR::Entity::INV_DETAIL) {
|
||||
int count = 5;
|
||||
int count = 6;
|
||||
if (key == cUp ) { slot = (slot - 1 + count) % count; };
|
||||
if (key == cDown ) { slot = (slot + 1) % count; };
|
||||
if (slot < count - 1) {
|
||||
if (slot < count - 2) {
|
||||
Core::Settings::Quality q = settings.detail.quality[slot];
|
||||
if (key == cLeft && q > Core::Settings::LOW ) { q = Core::Settings::Quality(q - 1); }
|
||||
if (key == cRight && q < Core::Settings::HIGH ) { q = Core::Settings::Quality(q + 1); }
|
||||
@@ -485,7 +485,10 @@ struct Inventory {
|
||||
}
|
||||
}
|
||||
|
||||
if (slot == count -1 && key == cAction) {
|
||||
if (slot == count - 2 && (key == cLeft || key == cRight)) // stereo
|
||||
settings.detail.stereo = !settings.detail.stereo;
|
||||
|
||||
if (slot == count - 1 && key == cAction) { // apply
|
||||
game->applySettings(settings);
|
||||
chosen = false;
|
||||
}
|
||||
@@ -734,10 +737,13 @@ struct Inventory {
|
||||
void renderPassport(Item *item) {
|
||||
if (item->anim->dir != 0.0f) return; // check for "Load Game" page
|
||||
|
||||
float y = 120.0f;
|
||||
float eye = UI::width * Core::eye * 0.02f;
|
||||
float h = 20.0f;
|
||||
float w = 320.0f;
|
||||
|
||||
float x = (UI::width - w) * 0.5f - eye;
|
||||
float y = 120.0f;
|
||||
|
||||
StringID str = STR_LOAD_GAME;
|
||||
|
||||
if (game->getLevel()->id == TR::TITLE) {
|
||||
@@ -757,19 +763,19 @@ struct Inventory {
|
||||
if (item->value != 0) return;
|
||||
|
||||
// background
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - w - 16.0f) * 0.5f, y - 16.0f), vec2(w + 16.0f, h * 16.0f), 0.0f, 0, 0xC0000000);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x - 8.0f, y - 16.0f), vec2(w + 16.0f, h * 16.0f), 0.0f, 0, 0xC0000000);
|
||||
// title
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - w) * 0.5f, y - h + 6), vec2(w, h - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
||||
UI::textOut(vec2(0, y), STR_SELECT_LEVEL, UI::aCenter, UI::width);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - h + 6), vec2(w, h - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
||||
UI::textOut(vec2(x, y), STR_SELECT_LEVEL, UI::aCenter, w);
|
||||
|
||||
y += h * 2;
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - w) * 0.5f, y + slot * h + 6 - h), vec2(w, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y + slot * h + 6 - h), vec2(w, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
|
||||
for (int i = 0; i < passportSlotCount; i++)
|
||||
if (passportSlots[i] == TR::LEVEL_MAX)
|
||||
UI::textOut(vec2(0, y + i * h), STR_AUTOSAVE, UI::aCenter, UI::width);
|
||||
UI::textOut(vec2(x, y + i * h), STR_AUTOSAVE, UI::aCenter, w);
|
||||
else
|
||||
UI::textOut(vec2(0, y + i * h), TR::LEVEL_INFO[passportSlots[i]].title, UI::aCenter, UI::width);
|
||||
UI::textOut(vec2(x, y + i * h), TR::LEVEL_INFO[passportSlots[i]].title, UI::aCenter, w);
|
||||
}
|
||||
|
||||
float printBool(float x, float y, float w, StringID oStr, bool active, bool value) {
|
||||
@@ -812,25 +818,27 @@ struct Inventory {
|
||||
float w = 320.0f;
|
||||
float h = 20.0f;
|
||||
|
||||
float x = (UI::width - w) * 0.5f;
|
||||
float y = 192.0f;
|
||||
float eye = UI::width * Core::eye * 0.02f;
|
||||
float x = (UI::width - w) * 0.5f - eye;
|
||||
float y = 192.0f - h;
|
||||
|
||||
// background
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - 16.0f), vec2(w, h * 8.0f + 8.0f), 0.0f, 0, 0xC0000000);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - 16.0f), vec2(w, h * 9.0f + 8.0f), 0.0f, 0, 0xC0000000);
|
||||
// title
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - h + 6), vec2(w, h - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
||||
UI::textOut(vec2(0, y), STR_SELECT_DETAIL, UI::aCenter, UI::width);
|
||||
UI::textOut(vec2(x, y), STR_SELECT_DETAIL, UI::aCenter, w);
|
||||
|
||||
y += h * 2;
|
||||
x += 8.0f;
|
||||
w -= 16.0f;
|
||||
float aw = slot == 4 ? (w - 128.0f) : w;
|
||||
float aw = slot == 5 ? (w - 128.0f) : w;
|
||||
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - aw) * 0.5f, y + (slot > 3 ? 5 : slot) * h + 6 - h), vec2(aw, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - aw) * 0.5f - eye, y + (slot > 4 ? 6 : slot) * h + 6 - h), vec2(aw, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
y = printQuality(x, y, w, STR_OPT_DETAIL_FILTER, slot == 0, settings.detail.filter);
|
||||
y = printQuality(x, y, w, STR_OPT_DETAIL_LIGHTING, slot == 1, settings.detail.lighting);
|
||||
y = printQuality(x, y, w, STR_OPT_DETAIL_SHADOWS, slot == 2, settings.detail.shadows);
|
||||
y = printQuality(x, y, w, STR_OPT_DETAIL_WATER, slot == 3, settings.detail.water);
|
||||
y = printBool(x + 32.0f, y, w - 64.0f - 16.0f, STR_OPT_DETAIL_STEREO, slot == 4, settings.detail.stereo);
|
||||
y += h;
|
||||
UI::textOut(vec2(x + 64.0f, y), STR_APPLY, UI::aCenter, w - 128.0f);
|
||||
}
|
||||
@@ -839,26 +847,27 @@ struct Inventory {
|
||||
float w = 320.0f;
|
||||
float h = 20.0f;
|
||||
|
||||
float x = (UI::width - w) * 0.5f;
|
||||
float eye = UI::width * Core::eye * 0.02f;
|
||||
float x = (UI::width - w) * 0.5f - eye;
|
||||
float y = 192.0f;
|
||||
|
||||
// background
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - 16.0f), vec2(w, h * 5.0f + 8.0f), 0.0f, 0, 0xC0000000);
|
||||
// title
|
||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - h + 6), vec2(w, h - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
||||
UI::textOut(vec2(0, y), STR_SET_VOLUMES, UI::aCenter, UI::width);
|
||||
UI::textOut(vec2(x, y), STR_SET_VOLUMES, UI::aCenter, w);
|
||||
|
||||
y += h * 2;
|
||||
x += 8.0f;
|
||||
w -= 16.0f;
|
||||
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - w) * 0.5f, y + slot * h + 6 - h), vec2(w, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
UI::renderBar(UI::BAR_OPTION, vec2((UI::width - w) * 0.5f - eye, y + slot * h + 6 - h), vec2(w, h - 6), 1.0f, 0xFFD8377C, 0);
|
||||
|
||||
float aw = w - 64.0f;
|
||||
aw -= 4.0f;
|
||||
|
||||
y = printBar((UI::width - w) * 0.5f, y, w, 0xFF0080FF, 101, slot == 0, Core::settings.audio.music);
|
||||
y = printBar((UI::width - w) * 0.5f, y, w, 0xFFFF8000, 102, slot == 1, Core::settings.audio.sound);
|
||||
y = printBar((UI::width - w) * 0.5f - eye, y, w, 0xFF0080FF, 101, slot == 0, Core::settings.audio.music);
|
||||
y = printBar((UI::width - w) * 0.5f - eye, y, w, 0xFFFF8000, 102, slot == 1, Core::settings.audio.sound);
|
||||
y = printBool(x + 32.0f, y, w - 64.0f, STR_REVERBERATION, slot == 2, Core::settings.audio.reverb);
|
||||
}
|
||||
|
||||
@@ -979,7 +988,7 @@ struct Inventory {
|
||||
Core::mLightProj.identity();
|
||||
|
||||
Core::mView.identity();
|
||||
Core::mView.translate(vec3(0, 0, -1286)); // y = -96 in title
|
||||
Core::mView.translate(vec3(-Core::eye * 8.0f, 0, -1286)); // y = -96 in title
|
||||
|
||||
Core::mView.up *= -1.0f;
|
||||
Core::mView.dir *= -1.0f;
|
||||
|
43
src/lara.h
43
src/lara.h
@@ -865,7 +865,7 @@ struct Lara : Character {
|
||||
vec3 hit = trace(getRoomIndex(), p, t, room, false);
|
||||
if (arm->target && checkHit(arm->target, p, hit, hit)) {
|
||||
TR::Entity::Type type = arm->target->getEntity().type;
|
||||
((Character*)arm->target)->hit(wpnGetDamage());
|
||||
((Character*)arm->target)->hit(wpnGetDamage(), this);
|
||||
hit -= d * 64.0f;
|
||||
if (type != TR::Entity::SCION_TARGET)
|
||||
Sprite::add(game, TR::Entity::BLOOD, room, (int)hit.x, (int)hit.y, (int)hit.z, Sprite::FRAME_ANIMATED);
|
||||
@@ -1274,15 +1274,18 @@ struct Lara : Character {
|
||||
vec3 v = to - from;
|
||||
|
||||
if (box.intersect(m, from, v, t)) {
|
||||
t *= v.length();
|
||||
v = v.normal();
|
||||
Sphere spheres[MAX_SPHERES];
|
||||
int count;
|
||||
target->getSpheres(spheres, count);
|
||||
for (int i = 0; i < count; i++)
|
||||
if (spheres[i].intersect(from, v, t)) {
|
||||
point = from + v * t;
|
||||
for (int i = 0; i < count; i++) {
|
||||
float st;
|
||||
if (spheres[i].intersect(from, v, st)) {
|
||||
point = from + v * max(t, st);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1651,7 +1654,15 @@ struct Lara : Character {
|
||||
if ((state != STATE_STOP && state != STATE_TREAD && state != STATE_PUSH_PULL_READY) || !action || !emptyHands())
|
||||
return false;
|
||||
|
||||
vec3 tmpAngle = controller->angle;
|
||||
vec3 ctrlAngle = controller->angle;
|
||||
if (stand == STAND_UNDERWATER)
|
||||
ctrlAngle.x = -25 * DEG2RAD;
|
||||
if (!limit->alignAngle)
|
||||
ctrlAngle.y = angle.y;
|
||||
controller->angle = ctrlAngle;
|
||||
mat4 m = controller->getMatrix();
|
||||
controller->angle = tmpAngle;
|
||||
|
||||
float fx = 0.0f;
|
||||
if (!limit->alignHoriz)
|
||||
@@ -1661,20 +1672,9 @@ struct Lara : Character {
|
||||
|
||||
vec3 deltaAbs = pos - targetPos;
|
||||
|
||||
vec3 tmpAngle = controller->angle;
|
||||
vec3 ctrlAngle = controller->angle;
|
||||
if (stand == STAND_UNDERWATER)
|
||||
ctrlAngle.x = -25 * DEG2RAD;
|
||||
if (!limit->alignAngle)
|
||||
ctrlAngle.y = angle.y;
|
||||
controller->angle = ctrlAngle;
|
||||
|
||||
vec3 deltaRel = (controller->getMatrix().transpose() * vec4(pos - controller->pos, 0.0f)).xyz; // inverse transform
|
||||
|
||||
controller->angle = tmpAngle;
|
||||
vec3 deltaRel = (m.transpose() * vec4(pos - controller->pos, 0.0f)).xyz; // inverse transform
|
||||
|
||||
// set item orientation to hack limits check
|
||||
|
||||
if (limit->box.contains(deltaRel)) {
|
||||
float deltaAngY = shortAngle(angle.y, ctrlAngle.y);
|
||||
|
||||
@@ -2760,7 +2760,7 @@ struct Lara : Character {
|
||||
if (e.isEnemy()) { // enemy collision
|
||||
if (!collide(controller, false))
|
||||
continue;
|
||||
velocity.x = velocity.y = 0.0f;
|
||||
// velocity.x = velocity.y = 0.0f;
|
||||
} else { // door collision
|
||||
p += box.pushOut2D(p);
|
||||
p = (p.rotateY(-controller->angle.y) + controller->pos) - pos;
|
||||
@@ -2769,10 +2769,10 @@ struct Lara : Character {
|
||||
|
||||
if (e.type == TR::Entity::ENEMY_REX && ((Character*)controller)->health <= 0)
|
||||
return true;
|
||||
if (!e.isEnemy())
|
||||
if (!e.isEnemy() || e.type == TR::Entity::ENEMY_BAT)
|
||||
return true;
|
||||
|
||||
if (canHitAnim()) {
|
||||
if (canHitAnim()) { // TODO: check enemy type and health here
|
||||
// get hit dir
|
||||
if (hitDir == -1) {
|
||||
if (health > 0)
|
||||
@@ -3015,7 +3015,12 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
|
||||
uint32 visMask = visibleMask;
|
||||
if (Core::pass != Core::passShadow && game->getCamera()->firstPerson) // hide head from first person view
|
||||
visibleMask &= ~BODY_HEAD;
|
||||
Controller::render(frustum, mesh, type, caustics);
|
||||
visibleMask = visMask;
|
||||
|
||||
chestOffset = animation.getJoints(getMatrix(), jointChest).pos; // TODO: move to update func
|
||||
|
||||
if (braid)
|
||||
|
74
src/level.h
74
src/level.h
@@ -209,7 +209,7 @@ struct Level : IGame {
|
||||
atlas->bind(sDiffuse);
|
||||
Core::whiteTex->bind(sNormal);
|
||||
Core::whiteTex->bind(sMask);
|
||||
Core::whiteTex->bind(sReflect);
|
||||
Core::whiteTex->bind(sReflect);
|
||||
cube->bind(sEnvironment);
|
||||
Core::basis.identity();
|
||||
}
|
||||
@@ -964,7 +964,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (isCutscene() && (lara->health > 0.0f && !sndSoundtrack))
|
||||
if (level.isCutsceneLevel() && (lara->health > 0.0f && !sndSoundtrack))
|
||||
return;
|
||||
|
||||
if (Input::state[cInventory] && level.id != TR::TITLE) {
|
||||
@@ -1185,8 +1185,6 @@ struct Level : IGame {
|
||||
|
||||
virtual void renderView(int roomIndex, bool water) {
|
||||
PROFILE_MARKER("VIEW");
|
||||
Core::Pass pass = Core::pass;
|
||||
|
||||
if (water && waterCache) {
|
||||
waterCache->reset();
|
||||
}
|
||||
@@ -1203,7 +1201,10 @@ struct Level : IGame {
|
||||
for (int i = 0; i < roomsCount; i++)
|
||||
waterCache->setVisible(roomsList[i]);
|
||||
waterCache->renderReflect();
|
||||
|
||||
Core::Pass pass = Core::pass;
|
||||
waterCache->simulate();
|
||||
Core::pass = pass;
|
||||
}
|
||||
|
||||
// clear visibility flag for rooms
|
||||
@@ -1212,24 +1213,24 @@ struct Level : IGame {
|
||||
level.entities[i].flags.rendered = false;
|
||||
|
||||
if (water) {
|
||||
Core::setTarget(NULL, true); // render to back buffer
|
||||
Core::setTarget(NULL, !Core::settings.detail.stereo); // render to back buffer
|
||||
setupBinding();
|
||||
}
|
||||
|
||||
camera->setup(Core::pass == Core::passCompose);
|
||||
|
||||
Core::pass = pass;
|
||||
|
||||
renderRooms(roomsList, roomsCount);
|
||||
|
||||
if (Core::pass != Core::passAmbient)
|
||||
renderEntities();
|
||||
|
||||
if (water && waterCache && waterCache->visible) {
|
||||
Core::Pass pass = Core::pass;
|
||||
waterCache->renderMask();
|
||||
waterCache->getRefract();
|
||||
setMainLight(lara);
|
||||
waterCache->render();
|
||||
Core::pass = pass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,13 +1537,43 @@ struct Level : IGame {
|
||||
if (shadow) shadow->bind(sShadow);
|
||||
Core::pass = Core::passCompose;
|
||||
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true);
|
||||
if (Core::settings.detail.stereo) {
|
||||
Core::setTarget(NULL, true);
|
||||
Core::validateRenderState();
|
||||
}
|
||||
|
||||
if (Core::settings.detail.stereo) {
|
||||
Core::viewportDef = vec4(0.0f, 0.0f, float(Core::width) * 0.5f, float(Core::height));
|
||||
Core::eye = -1.0f;
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true);
|
||||
|
||||
Core::viewportDef = vec4(float(Core::width) * 0.5f, 0.0f, float(Core::width) * 0.5f, float(Core::height));
|
||||
Core::eye = 1.0f;
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true);
|
||||
|
||||
Core::viewportDef = vec4(0.0f, 0.0f, float(Core::width), float(Core::height));
|
||||
Core::eye = 0.0f;
|
||||
} else {
|
||||
setup();
|
||||
renderView(camera->getRoomIndex(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void renderInventory() {
|
||||
Core::setTarget(NULL, true);
|
||||
inventory.render();
|
||||
if (Core::settings.detail.stereo) {
|
||||
Core::setViewport(0, 0, Core::width / 2, Core::height);
|
||||
Core::eye = -1.0f;
|
||||
inventory.render();
|
||||
Core::setViewport(Core::width / 2, 0, Core::width / 2, Core::height);
|
||||
Core::eye = 1.0f;
|
||||
inventory.render();
|
||||
Core::setViewport(0, 0, Core::width, Core::height);
|
||||
Core::eye = 0.0f;
|
||||
} else
|
||||
inventory.render();
|
||||
}
|
||||
|
||||
void renderUI() {
|
||||
@@ -1562,18 +1593,20 @@ struct Level : IGame {
|
||||
if (oxygen <= 0.2f) oxygen = 0.0f;
|
||||
}
|
||||
|
||||
float eye = inventory.active ? 0.0f : UI::width * Core::eye * 0.02f;
|
||||
|
||||
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f))) {
|
||||
UI::renderBar(UI::BAR_HEALTH, vec2(UI::width - 32 - size.x, 32), size, health);
|
||||
UI::renderBar(UI::BAR_HEALTH, vec2(UI::width - 32 - size.x - eye, 32), size, health);
|
||||
|
||||
if (!inventory.active && !lara->emptyHands()) { // ammo
|
||||
int index = inventory.contains(lara->getCurrentWeaponInv());
|
||||
if (index > -1)
|
||||
inventory.renderItemCount(inventory.items[index], vec2(UI::width - 32 - size.x, 64), size.x);
|
||||
inventory.renderItemCount(inventory.items[index], vec2(UI::width - 32 - size.x - eye, 64), size.x);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lara->dozy && (lara->stand == Lara::STAND_ONWATER || lara->stand == Character::STAND_UNDERWATER))
|
||||
UI::renderBar(UI::BAR_OXYGEN, vec2(32, 32), size, oxygen);
|
||||
UI::renderBar(UI::BAR_OXYGEN, vec2(32 - eye, 32), size, oxygen);
|
||||
}
|
||||
|
||||
inventory.renderUI();
|
||||
@@ -1599,7 +1632,10 @@ struct Level : IGame {
|
||||
|
||||
if (copyBg) {
|
||||
Core::defaultTarget = inventory.background[0];
|
||||
bool stereo = Core::settings.detail.stereo;
|
||||
Core::settings.detail.stereo = false;
|
||||
renderGame();
|
||||
Core::settings.detail.stereo = stereo;
|
||||
Core::defaultTarget = NULL;
|
||||
|
||||
inventory.prepareBackground();
|
||||
@@ -1611,7 +1647,17 @@ struct Level : IGame {
|
||||
if (title)
|
||||
renderInventory();
|
||||
|
||||
renderUI();
|
||||
if (Core::settings.detail.stereo) {
|
||||
Core::setViewport(0, 0, Core::width / 2, Core::height);
|
||||
Core::eye = -1.0f;
|
||||
renderUI();
|
||||
Core::setViewport(Core::width / 2, 0, Core::width / 2, Core::height);
|
||||
Core::eye = 1.0f;
|
||||
renderUI();
|
||||
Core::setViewport(0, 0, Core::width, Core::height);
|
||||
Core::eye = 0.0f;
|
||||
} else
|
||||
renderUI();
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -159,8 +159,11 @@ struct Shader {
|
||||
|
||||
void init() {
|
||||
bind();
|
||||
for (int st = 0; st < sMAX; st++)
|
||||
glUniform1iv(glGetUniformLocation(ID, (GLchar*)SamplerName[st]), 1, &st);
|
||||
for (int st = 0; st < sMAX; st++) {
|
||||
GLint idx = glGetUniformLocation(ID, (GLchar*)SamplerName[st]);
|
||||
if (idx != -1)
|
||||
glUniform1iv(idx, 1, &st);
|
||||
}
|
||||
|
||||
for (int ut = 0; ut < uMAX; ut++)
|
||||
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
|
||||
|
@@ -19,7 +19,7 @@ uniform mat4 uLightProj;
|
||||
uniform mat4 uViewProj;
|
||||
uniform vec3 uViewPos;
|
||||
uniform vec4 uParam; // x - time, y - water height, z - clip plane sign, w - clip plane height
|
||||
uniform vec3 uLightPos[MAX_LIGHTS];
|
||||
uniform vec4 uLightPos[MAX_LIGHTS];
|
||||
uniform vec4 uLightColor[MAX_LIGHTS]; // xyz - color, w - radius * intensity
|
||||
|
||||
uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
|
@@ -14,7 +14,7 @@ varying vec3 vLightVec;
|
||||
|
||||
uniform vec3 uViewPos;
|
||||
uniform mat4 uViewProj;
|
||||
uniform vec3 uLightPos;
|
||||
uniform vec4 uLightPos;
|
||||
uniform vec3 uPosScale[2];
|
||||
|
||||
uniform vec4 uTexParam;
|
||||
@@ -71,7 +71,7 @@ uniform sampler2D sNormal;
|
||||
#endif
|
||||
#endif
|
||||
vViewVec = uViewPos - vCoord.xyz;
|
||||
vLightVec = uLightPos - vCoord.xyz;
|
||||
vLightVec = uLightPos.xyz - vCoord.xyz;
|
||||
}
|
||||
#else
|
||||
uniform sampler2D sDiffuse;
|
||||
|
2
src/ui.h
2
src/ui.h
@@ -43,6 +43,7 @@ enum StringID {
|
||||
, STR_OPT_DETAIL_LIGHTING
|
||||
, STR_OPT_DETAIL_SHADOWS
|
||||
, STR_OPT_DETAIL_WATER
|
||||
, STR_OPT_DETAIL_STEREO
|
||||
// sound options
|
||||
, STR_SET_VOLUMES
|
||||
, STR_REVERBERATION
|
||||
@@ -132,6 +133,7 @@ const char *STR[STR_MAX] = {
|
||||
, "Lighting"
|
||||
, "Shadows"
|
||||
, "Water"
|
||||
, "Stereo"
|
||||
// sound options
|
||||
, "Set Volumes"
|
||||
, "Reverberation"
|
||||
|
@@ -283,6 +283,7 @@ struct vec4 {
|
||||
vec4() {}
|
||||
vec4(float s) : x(s), y(s), z(s), w(s) {}
|
||||
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
vec4(const vec3 &xyz) : x(xyz.x), y(xyz.y), z(xyz.z), w(0) {}
|
||||
vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
|
||||
vec4(const vec2 &xy, const vec2 &zw) : x(xy.x), y(xy.y), z(zw.x), w(zw.y) {}
|
||||
|
||||
|
Reference in New Issue
Block a user