mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-16 18:14:05 +02:00
#11 health & oxygen bars; #23 auto-retarget when enemy died; remove unused shaders; fix underwater sound stop in Web version
This commit is contained in:
31
src/cache.h
31
src/cache.h
@@ -27,10 +27,6 @@ const char FILTER[] =
|
|||||||
#include "shaders/filter.glsl"
|
#include "shaders/filter.glsl"
|
||||||
;
|
;
|
||||||
|
|
||||||
const char VOLUME[] =
|
|
||||||
#include "shaders/volume.glsl"
|
|
||||||
;
|
|
||||||
|
|
||||||
const char GUI[] =
|
const char GUI[] =
|
||||||
#include "shaders/gui.glsl"
|
#include "shaders/gui.glsl"
|
||||||
;
|
;
|
||||||
@@ -45,15 +41,15 @@ struct ShaderCache {
|
|||||||
memset(shaders, 0, sizeof(shaders));
|
memset(shaders, 0, sizeof(shaders));
|
||||||
|
|
||||||
LOG("shader: cache warm up...\n");
|
LOG("shader: cache warm up...\n");
|
||||||
if (Core::settings.shadows)
|
if (Core::settings.detail.shadows)
|
||||||
compile(Core::passShadow, Shader::ENTITY, FX_NONE);
|
compile(Core::passShadow, Shader::ENTITY, FX_NONE);
|
||||||
|
|
||||||
if (Core::settings.ambient) {
|
if (Core::settings.detail.ambient) {
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_NONE);
|
compile(Core::passAmbient, Shader::ROOM, FX_NONE);
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_ALPHA_TEST);
|
compile(Core::passAmbient, Shader::ROOM, FX_ALPHA_TEST);
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_UNDERWATER);
|
compile(Core::passAmbient, Shader::ROOM, FX_UNDERWATER);
|
||||||
compile(Core::passAmbient, Shader::SPRITE, FX_ALPHA_TEST);
|
compile(Core::passAmbient, Shader::SPRITE, FX_ALPHA_TEST);
|
||||||
if (Core::settings.water) {
|
if (Core::settings.detail.water) {
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_CLIP_PLANE);
|
compile(Core::passAmbient, Shader::ROOM, FX_CLIP_PLANE);
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_ALPHA_TEST | FX_CLIP_PLANE);
|
compile(Core::passAmbient, Shader::ROOM, FX_ALPHA_TEST | FX_CLIP_PLANE);
|
||||||
compile(Core::passAmbient, Shader::ROOM, FX_UNDERWATER | FX_CLIP_PLANE);
|
compile(Core::passAmbient, Shader::ROOM, FX_UNDERWATER | FX_CLIP_PLANE);
|
||||||
@@ -61,7 +57,7 @@ struct ShaderCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Core::settings.water) {
|
if (Core::settings.detail.water) {
|
||||||
compile(Core::passWater, Shader::WATER_MASK, FX_NONE);
|
compile(Core::passWater, Shader::WATER_MASK, FX_NONE);
|
||||||
compile(Core::passWater, Shader::WATER_STEP, FX_NONE);
|
compile(Core::passWater, Shader::WATER_STEP, FX_NONE);
|
||||||
compile(Core::passWater, Shader::WATER_CAUSTICS, FX_NONE);
|
compile(Core::passWater, Shader::WATER_CAUSTICS, FX_NONE);
|
||||||
@@ -83,7 +79,7 @@ struct ShaderCache {
|
|||||||
compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST);
|
compile(Core::passCompose, Shader::SPRITE, FX_ALPHA_TEST);
|
||||||
compile(Core::passCompose, Shader::SPRITE, FX_UNDERWATER | FX_ALPHA_TEST);
|
compile(Core::passCompose, Shader::SPRITE, FX_UNDERWATER | FX_ALPHA_TEST);
|
||||||
compile(Core::passCompose, Shader::FLASH, FX_ALPHA_TEST);
|
compile(Core::passCompose, Shader::FLASH, FX_ALPHA_TEST);
|
||||||
if (Core::settings.water) {
|
if (Core::settings.detail.water) {
|
||||||
compile(Core::passCompose, Shader::ROOM, FX_CLIP_PLANE);
|
compile(Core::passCompose, Shader::ROOM, FX_CLIP_PLANE);
|
||||||
compile(Core::passCompose, Shader::ROOM, FX_ALPHA_TEST | FX_CLIP_PLANE);
|
compile(Core::passCompose, Shader::ROOM, FX_ALPHA_TEST | FX_CLIP_PLANE);
|
||||||
compile(Core::passCompose, Shader::ROOM, FX_UNDERWATER | FX_CLIP_PLANE);
|
compile(Core::passCompose, Shader::ROOM, FX_UNDERWATER | FX_CLIP_PLANE);
|
||||||
@@ -108,7 +104,7 @@ struct ShaderCache {
|
|||||||
Shader* compile(Core::Pass pass, Shader::Type type, int fx) {
|
Shader* compile(Core::Pass pass, Shader::Type type, int fx) {
|
||||||
char def[1024], ext[255];
|
char def[1024], ext[255];
|
||||||
ext[0] = 0;
|
ext[0] = 0;
|
||||||
if (Core::settings.shadows) {
|
if (Core::settings.detail.shadows) {
|
||||||
if (Core::support.shadowSampler) {
|
if (Core::support.shadowSampler) {
|
||||||
#ifdef MOBILE
|
#ifdef MOBILE
|
||||||
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
||||||
@@ -139,10 +135,10 @@ struct ShaderCache {
|
|||||||
if (fx & FX_UNDERWATER) strcat(def, "#define UNDERWATER\n" UNDERWATER_COLOR);
|
if (fx & FX_UNDERWATER) strcat(def, "#define UNDERWATER\n" UNDERWATER_COLOR);
|
||||||
if (fx & FX_ALPHA_TEST) strcat(def, "#define ALPHA_TEST\n");
|
if (fx & FX_ALPHA_TEST) strcat(def, "#define ALPHA_TEST\n");
|
||||||
if (fx & FX_CLIP_PLANE) strcat(def, "#define CLIP_PLANE\n");
|
if (fx & FX_CLIP_PLANE) strcat(def, "#define CLIP_PLANE\n");
|
||||||
if (Core::settings.ambient) strcat(def, "#define OPT_AMBIENT\n");
|
if (Core::settings.detail.ambient) strcat(def, "#define OPT_AMBIENT\n");
|
||||||
if (Core::settings.lighting) strcat(def, "#define OPT_LIGHTING\n");
|
if (Core::settings.detail.lighting) strcat(def, "#define OPT_LIGHTING\n");
|
||||||
if (Core::settings.shadows) strcat(def, "#define OPT_SHADOW\n");
|
if (Core::settings.detail.shadows) strcat(def, "#define OPT_SHADOW\n");
|
||||||
if (Core::settings.water) strcat(def, "#define OPT_WATER\n");
|
if (Core::settings.detail.water) strcat(def, "#define OPT_WATER\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Core::passWater : {
|
case Core::passWater : {
|
||||||
@@ -162,13 +158,6 @@ struct ShaderCache {
|
|||||||
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
|
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Core::passVolume : {
|
|
||||||
static const char *typeNames[] = { "DEFAULT" };
|
|
||||||
src = VOLUME;
|
|
||||||
typ = typeNames[type];
|
|
||||||
sprintf(def, "%s#define PASS_%s\n", ext, passNames[pass]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Core::passGUI : {
|
case Core::passGUI : {
|
||||||
static const char *typeNames[] = { "DEFAULT" };
|
static const char *typeNames[] = { "DEFAULT" };
|
||||||
src = GUI;
|
src = GUI;
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include "trigger.h"
|
#include "trigger.h"
|
||||||
|
|
||||||
struct Character : Controller {
|
struct Character : Controller {
|
||||||
int health;
|
float health;
|
||||||
float tilt;
|
float tilt;
|
||||||
quat rotHead, rotChest;
|
quat rotHead, rotChest;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ struct Character : Controller {
|
|||||||
|
|
||||||
Collision collision;
|
Collision collision;
|
||||||
|
|
||||||
Character(IGame *game, int entity, int health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), velocity(0.0f), angleExt(0.0f) {
|
Character(IGame *game, int entity, float health) : Controller(game, entity), health(health), tilt(0.0f), stand(STAND_GROUND), lastInput(0), velocity(0.0f), angleExt(0.0f) {
|
||||||
animation.initOverrides();
|
animation.initOverrides();
|
||||||
rotHead = rotChest = quat(0, 0, 0, 1);
|
rotHead = rotChest = quat(0, 0, 0, 1);
|
||||||
|
|
||||||
@@ -68,8 +68,8 @@ struct Character : Controller {
|
|||||||
angle.x = clamp(angle.x + delta, -PI * 0.49f, PI * 0.49f);
|
angle.x = clamp(angle.x + delta, -PI * 0.49f, PI * 0.49f);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void hit(int damage, Controller *enemy = NULL) {
|
virtual void hit(float damage, Controller *enemy = NULL) {
|
||||||
health -= damage;
|
health = max(0.0f, health - damage);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void checkRoom() {
|
virtual void checkRoom() {
|
||||||
|
16
src/core.h
16
src/core.h
@@ -308,7 +308,7 @@ namespace Core {
|
|||||||
|
|
||||||
Texture *blackTex, *whiteTex;
|
Texture *blackTex, *whiteTex;
|
||||||
|
|
||||||
enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passVolume, passGUI, passMAX } pass;
|
enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass;
|
||||||
|
|
||||||
GLuint FBO, defaultFBO;
|
GLuint FBO, defaultFBO;
|
||||||
Texture *defaultTarget;
|
Texture *defaultTarget;
|
||||||
@@ -362,10 +362,16 @@ namespace Core {
|
|||||||
} stats;
|
} stats;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool ambient;
|
struct {
|
||||||
bool lighting;
|
bool ambient;
|
||||||
bool shadows;
|
bool lighting;
|
||||||
bool water;
|
bool shadows;
|
||||||
|
bool water;
|
||||||
|
} detail;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool retarget;
|
||||||
|
} controls;
|
||||||
} settings;
|
} settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/enemy.h
10
src/enemy.h
@@ -72,7 +72,7 @@ struct Enemy : Character {
|
|||||||
bool targetFromView; // enemy in target view zone
|
bool targetFromView; // enemy in target view zone
|
||||||
bool targetCanAttack;
|
bool targetCanAttack;
|
||||||
|
|
||||||
Enemy(IGame *game, int entity, int health, int radius, float length, float aggression) : Character(game, entity, health), ai(AI_RANDOM), mood(MOOD_SLEEP), wound(false), nextState(0), targetBox(-1), thinkTime(1.0f / 30.0f), length(length), aggression(aggression), radius(radius), target(NULL), path(NULL) {
|
Enemy(IGame *game, int entity, float health, int radius, float length, float aggression) : Character(game, entity, health), ai(AI_RANDOM), mood(MOOD_SLEEP), wound(false), nextState(0), targetBox(-1), thinkTime(1.0f / 30.0f), length(length), aggression(aggression), radius(radius), target(NULL), path(NULL) {
|
||||||
stepHeight = 256;
|
stepHeight = 256;
|
||||||
dropHeight = -256;
|
dropHeight = -256;
|
||||||
|
|
||||||
@@ -257,12 +257,12 @@ struct Enemy : Character {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void hit(int damage, Controller *enemy = NULL) {
|
virtual void hit(float damage, Controller *enemy = NULL) {
|
||||||
Character::hit(damage, enemy);
|
Character::hit(damage, enemy);
|
||||||
wound = true;
|
wound = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
void bite(const vec3 &pos, int damage) {
|
void bite(const vec3 &pos, float damage) {
|
||||||
ASSERT(target);
|
ASSERT(target);
|
||||||
target->hit(damage, this);
|
target->hit(damage, this);
|
||||||
Sprite::add(game, TR::Entity::BLOOD, target->getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z, Sprite::FRAME_ANIMATED);
|
Sprite::add(game, TR::Entity::BLOOD, target->getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z, Sprite::FRAME_ANIMATED);
|
||||||
@@ -605,7 +605,7 @@ struct Wolf : Enemy {
|
|||||||
case STATE_ATTACK :
|
case STATE_ATTACK :
|
||||||
case STATE_BITE :
|
case STATE_BITE :
|
||||||
if (nextState == STATE_NONE && targetInView && (collide(target) & HIT_MASK)) {
|
if (nextState == STATE_NONE && targetInView && (collide(target) & HIT_MASK)) {
|
||||||
bite(animation.getJoints(getMatrix(), jointHead, true).pos, state == STATE_ATTACK ? 50 : 100);
|
bite(animation.getJoints(getMatrix(), jointHead, true).pos, state == STATE_ATTACK ? 50.0f : 100.0f);
|
||||||
nextState = state == STATE_ATTACK ? STATE_RUN : STATE_GROWL;
|
nextState = state == STATE_ATTACK ? STATE_RUN : STATE_GROWL;
|
||||||
}
|
}
|
||||||
return state == STATE_ATTACK ? STATE_RUN : state;
|
return state == STATE_ATTACK ? STATE_RUN : state;
|
||||||
@@ -753,7 +753,7 @@ struct Bear : Enemy {
|
|||||||
case STATE_BITE :
|
case STATE_BITE :
|
||||||
case STATE_ATTACK :
|
case STATE_ATTACK :
|
||||||
if (nextState == STATE_NONE && (collide(target) & HIT_MASK)) {
|
if (nextState == STATE_NONE && (collide(target) & HIT_MASK)) {
|
||||||
bite(animation.getJoints(getMatrix(), jointHead, true).pos, state == STATE_BITE ? 200 : 400);
|
bite(animation.getJoints(getMatrix(), jointHead, true).pos, state == STATE_BITE ? 200.0f : 400.0f);
|
||||||
nextState = state == STATE_BITE ? STATE_STOP : STATE_HOWL;
|
nextState = state == STATE_BITE ? STATE_STOP : STATE_HOWL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -393,12 +393,13 @@ namespace TR {
|
|||||||
Color32(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) {}
|
Color32(uint8 r, uint8 g, uint8 b, uint8 a) : r(r), g(g), b(b), a(a) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Color24 {
|
struct Color24 {
|
||||||
uint8 r, g, b;
|
uint8 r, g, b;
|
||||||
|
|
||||||
Color24() {}
|
Color24() {}
|
||||||
Color24(uint8 r, uint8 g, uint8 b) : r(r), g(g), b(b) {}
|
Color24(uint8 r, uint8 g, uint8 b) : r(r), g(g), b(b) {}
|
||||||
|
|
||||||
|
operator Color32() const { return Color32(r, g, b, 255); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Color16 {
|
struct Color16 {
|
||||||
|
10
src/game.h
10
src/game.h
@@ -19,10 +19,12 @@ namespace Game {
|
|||||||
void init(Stream *lvl, Stream *snd) {
|
void init(Stream *lvl, Stream *snd) {
|
||||||
Core::init();
|
Core::init();
|
||||||
|
|
||||||
Core::settings.ambient = true;
|
Core::settings.detail.ambient = true;
|
||||||
Core::settings.lighting = true;
|
Core::settings.detail.lighting = true;
|
||||||
Core::settings.shadows = true;
|
Core::settings.detail.shadows = true;
|
||||||
Core::settings.water = Core::support.texFloat || Core::support.texHalf;
|
Core::settings.detail.water = Core::support.texFloat || Core::support.texHalf;
|
||||||
|
|
||||||
|
Core::settings.controls.retarget = true;
|
||||||
|
|
||||||
level = NULL;
|
level = NULL;
|
||||||
startLevel(lvl, snd, false, false);
|
startLevel(lvl, snd, false, false);
|
||||||
|
@@ -277,6 +277,26 @@ struct Inventory {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getAngle(int index, int count) {
|
||||||
|
return PI * 2.0f / float(count) * index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getItemsCount(int page) {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < itemsCount; i++)
|
||||||
|
if (items[i].desc.page == page)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool showHealthBar() {
|
||||||
|
int idx = getItemIndex(page, index);
|
||||||
|
TR::Entity::Type type = items[idx].type;
|
||||||
|
return active && phaseRing == 1.0f && index == targetIndex && phasePage == 1.0f && (type == TR::Entity::INV_MEDIKIT_SMALL || type == TR::Entity::INV_MEDIKIT_BIG);
|
||||||
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
doPhase(active, 2.0f, phaseRing);
|
doPhase(active, 2.0f, phaseRing);
|
||||||
doPhase(true, 1.6f, phasePage);
|
doPhase(true, 1.6f, phasePage);
|
||||||
@@ -334,7 +354,7 @@ struct Inventory {
|
|||||||
|
|
||||||
float w = 90.0f * DEG2RAD * Core::deltaTime;
|
float w = 90.0f * DEG2RAD * Core::deltaTime;
|
||||||
|
|
||||||
int itemIndex = getItemIndex(page, index);
|
int itemIndex = index == targetIndex ? getItemIndex(page, index) : -1;
|
||||||
|
|
||||||
for (int i = 0; i < itemsCount; i++) {
|
for (int i = 0; i < itemsCount; i++) {
|
||||||
items[i].update();
|
items[i].update();
|
||||||
@@ -420,20 +440,6 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float getAngle(int index, int count) {
|
|
||||||
return PI * 2.0f / float(count) * index;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getItemsCount(int page) {
|
|
||||||
int count = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < itemsCount; i++)
|
|
||||||
if (items[i].desc.page == page)
|
|
||||||
count++;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderPage(int page) {
|
void renderPage(int page) {
|
||||||
float phase = page == targetPage ? phasePage : (1.0f - phasePage);
|
float phase = page == targetPage ? phasePage : (1.0f - phasePage);
|
||||||
|
|
||||||
@@ -465,15 +471,16 @@ struct Inventory {
|
|||||||
float ia = item.angle;
|
float ia = item.angle;
|
||||||
float ra = ringTilt;
|
float ra = ringTilt;
|
||||||
float rd = radius;
|
float rd = radius;
|
||||||
|
float rh = ringHeight;
|
||||||
|
|
||||||
if (itemIndex == pageItemIndex[page] && (chosen || phaseChoose > 0.0f)) {
|
if (itemIndex == pageItemIndex[page] && (chosen || phaseChoose > 0.0f)) {
|
||||||
ia *= 1.0f - phaseChoose;
|
ia *= 1.0f - phaseChoose;
|
||||||
ra *= 1.0f - phaseChoose;
|
rh -= 128 * phaseChoose;
|
||||||
rd += 296 * phaseChoose;
|
rd += 296 * phaseChoose;
|
||||||
}
|
}
|
||||||
|
|
||||||
Basis basis = Basis(quat(vec3(1, 0, 0), ra), vec3(0.0f));
|
Basis basis = Basis(quat(vec3(1, 0, 0), ra), vec3(0.0f));
|
||||||
basis = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item.desc.page * INVENTORY_HEIGHT - ringHeight, 0));
|
basis = basis * Basis(quat(vec3(0, 1, 0), PI + ia - a), vec3(sinf(a), 0, -cosf(a)) * rd - vec3(0, item.desc.page * INVENTORY_HEIGHT - rh, 0));
|
||||||
|
|
||||||
item.render(game, basis);
|
item.render(game, basis);
|
||||||
|
|
||||||
@@ -531,46 +538,27 @@ struct Inventory {
|
|||||||
renderPage(page);
|
renderPage(page);
|
||||||
if (page != targetPage)
|
if (page != targetPage)
|
||||||
renderPage(targetPage);
|
renderPage(targetPage);
|
||||||
|
}
|
||||||
|
|
||||||
if (phaseRing < 1.0f)
|
void renderUI() {
|
||||||
return;
|
if (!active || phaseRing < 1.0f) return;
|
||||||
|
|
||||||
Core::setDepthTest(false);
|
|
||||||
Core::setBlending(bmAlpha);
|
|
||||||
Core::setCulling(cfNone);
|
|
||||||
game->setupBinding();
|
|
||||||
|
|
||||||
float w = 480 * aspect;
|
|
||||||
Core::mViewProj = mat4(0.0f, w, 480, 0.0f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
game->setShader(Core::passGUI, Shader::DEFAULT);
|
|
||||||
Core::active.shader->setParam(uMaterial, vec4(1.0f));
|
|
||||||
Core::active.shader->setParam(uPosScale, vec4(0.0f, 0.0f, 1.0f, 1.0f));
|
|
||||||
|
|
||||||
UI::textBegin();
|
|
||||||
|
|
||||||
static const char* pageTitle[PAGE_MAX] = { "OPTION", "INVENTORY", "ITEMS" };
|
static const char* pageTitle[PAGE_MAX] = { "OPTION", "INVENTORY", "ITEMS" };
|
||||||
|
|
||||||
UI::textOut(game, vec2( 0, 32), pageTitle[page], UI::aCenter, w);
|
UI::textOut(game, vec2( 0, 32), pageTitle[page], UI::aCenter, UI::width);
|
||||||
|
|
||||||
if (page < PAGE_ITEMS && getItemsCount(page + 1)) {
|
if (page < PAGE_ITEMS && getItemsCount(page + 1)) {
|
||||||
UI::textOut(game, vec2(16, 32), "\x5B", UI::aLeft, w);
|
UI::textOut(game, vec2(16, 32), "\x5B", UI::aLeft, UI::width);
|
||||||
UI::textOut(game, vec2( 0, 32), "\x5B", UI::aRight, w - 20);
|
UI::textOut(game, vec2( 0, 32), "\x5B", UI::aRight, UI::width - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page > PAGE_OPTION && getItemsCount(page - 1)) {
|
if (page > PAGE_OPTION && getItemsCount(page - 1)) {
|
||||||
UI::textOut(game, vec2(16, 480 - 16), "\x5D", UI::aLeft, w);
|
UI::textOut(game, vec2(16, 480 - 16), "\x5D", UI::aLeft, UI::width);
|
||||||
UI::textOut(game, vec2(0, 480 - 16), "\x5D", UI::aRight, w - 20);
|
UI::textOut(game, vec2(0, 480 - 16), "\x5D", UI::aRight, UI::width - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == targetIndex)
|
if (index == targetIndex)
|
||||||
renderItemText(items[getItemIndex(page, index)], w);
|
renderItemText(items[getItemIndex(page, index)], UI::width);
|
||||||
|
|
||||||
UI::textEnd(game);
|
|
||||||
|
|
||||||
Core::setCulling(cfFront);
|
|
||||||
Core::setBlending(bmNone);
|
|
||||||
Core::setDepthTest(true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
50
src/lara.h
50
src/lara.h
@@ -20,7 +20,8 @@
|
|||||||
#define LARA_TILT_SPEED (DEG2RAD * 37.5f)
|
#define LARA_TILT_SPEED (DEG2RAD * 37.5f)
|
||||||
#define LARA_TILT_MAX (DEG2RAD * 10.0f)
|
#define LARA_TILT_MAX (DEG2RAD * 10.0f)
|
||||||
|
|
||||||
#define LARA_MAX_HEALTH 1000
|
#define LARA_MAX_HEALTH 1000.0f
|
||||||
|
#define LARA_MAX_OXYGEN 60.0f
|
||||||
|
|
||||||
#define LARA_HANG_OFFSET 724
|
#define LARA_HANG_OFFSET 724
|
||||||
#define LARA_HEIGHT 762
|
#define LARA_HEIGHT 762
|
||||||
@@ -36,6 +37,8 @@
|
|||||||
#define LARA_WET_SPECULAR 0.5f
|
#define LARA_WET_SPECULAR 0.5f
|
||||||
#define LARA_WET_TIMER (LARA_WET_SPECULAR / 16.0f) // 4 sec
|
#define LARA_WET_TIMER (LARA_WET_SPECULAR / 16.0f) // 4 sec
|
||||||
|
|
||||||
|
#define LARA_DAMAGE_TIME (40.0f / 30.0f)
|
||||||
|
|
||||||
#define PICKUP_FRAME_GROUND 40
|
#define PICKUP_FRAME_GROUND 40
|
||||||
#define PICKUP_FRAME_UNDERWATER 18
|
#define PICKUP_FRAME_UNDERWATER 18
|
||||||
#define PUZZLE_FRAME 80
|
#define PUZZLE_FRAME 80
|
||||||
@@ -219,6 +222,8 @@ struct Lara : Character {
|
|||||||
int roomPrev; // water out from room
|
int roomPrev; // water out from room
|
||||||
vec2 rotFactor;
|
vec2 rotFactor;
|
||||||
|
|
||||||
|
float oxygen;
|
||||||
|
float damageTime;
|
||||||
float hitTime;
|
float hitTime;
|
||||||
int hitDir;
|
int hitDir;
|
||||||
vec3 collisionOffset;
|
vec3 collisionOffset;
|
||||||
@@ -393,8 +398,10 @@ struct Lara : Character {
|
|||||||
animation.setAnim(ANIM_STAND);
|
animation.setAnim(ANIM_STAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
hitDir = -1;
|
oxygen = LARA_MAX_OXYGEN;
|
||||||
hitTime = 0.0f;
|
hitDir = -1;
|
||||||
|
damageTime = LARA_DAMAGE_TIME;
|
||||||
|
hitTime = 0.0f;
|
||||||
|
|
||||||
getEntity().flags.active = 1;
|
getEntity().flags.active = 1;
|
||||||
initMeshOverrides();
|
initMeshOverrides();
|
||||||
@@ -426,7 +433,7 @@ struct Lara : Character {
|
|||||||
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
||||||
|
|
||||||
//reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge)
|
//reset(14, vec3(20215, 6656, 52942), PI); // level 1 (bridge)
|
||||||
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||||
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
//reset(61, vec3(27221, -1024, 29205), PI * 0.5f); // level 2 (blade)
|
||||||
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
|
||||||
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
|
||||||
@@ -520,7 +527,7 @@ struct Lara : Character {
|
|||||||
wpnSetState(wState);
|
wpnSetState(wState);
|
||||||
}
|
}
|
||||||
|
|
||||||
int wpnGetDamage() {
|
float wpnGetDamage() {
|
||||||
switch (wpnCurrent) {
|
switch (wpnCurrent) {
|
||||||
case Weapon::PISTOLS : return 1;
|
case Weapon::PISTOLS : return 1;
|
||||||
case Weapon::SHOTGUN : return 1;
|
case Weapon::SHOTGUN : return 1;
|
||||||
@@ -1059,8 +1066,18 @@ struct Lara : Character {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// auto retarget
|
||||||
|
bool retarget = false;
|
||||||
|
if (Core::settings.controls.retarget) {
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
if (arms[i].tracking == -1 || ((Character*)level->entities[arms[i].tracking].controller)->health <= 0.0f) {
|
||||||
|
retarget = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int count = wpnCurrent != Weapon::SHOTGUN ? 2 : 1;
|
int count = wpnCurrent != Weapon::SHOTGUN ? 2 : 1;
|
||||||
if (!(input & ACTION)) {
|
if (!(input & ACTION) || retarget) {
|
||||||
getTargets(arms[0].tracking, arms[1].tracking);
|
getTargets(arms[0].tracking, arms[1].tracking);
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
arms[1].tracking = -1;
|
arms[1].tracking = -1;
|
||||||
@@ -1219,8 +1236,10 @@ struct Lara : Character {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void hit(int damage, Controller *enemy = NULL) {
|
virtual void hit(float damage, Controller *enemy = NULL) {
|
||||||
health -= damage;
|
damageTime = LARA_DAMAGE_TIME;
|
||||||
|
|
||||||
|
Character::hit(damage, enemy);
|
||||||
if (damage == 10000) { // T-Rex attack (fatal)
|
if (damage == 10000) { // T-Rex attack (fatal)
|
||||||
pos = enemy->pos;
|
pos = enemy->pos;
|
||||||
angle = enemy->angle;
|
angle = enemy->angle;
|
||||||
@@ -1244,6 +1263,7 @@ struct Lara : Character {
|
|||||||
case TR::Entity::INV_UZIS : wpnChange(Lara::Weapon::UZIS); break;
|
case TR::Entity::INV_UZIS : wpnChange(Lara::Weapon::UZIS); break;
|
||||||
case TR::Entity::INV_MEDIKIT_SMALL :
|
case TR::Entity::INV_MEDIKIT_SMALL :
|
||||||
case TR::Entity::INV_MEDIKIT_BIG :
|
case TR::Entity::INV_MEDIKIT_BIG :
|
||||||
|
damageTime = LARA_DAMAGE_TIME;
|
||||||
health = min(LARA_MAX_HEALTH, health + (item == TR::Entity::INV_MEDIKIT_SMALL ? LARA_MAX_HEALTH / 2 : LARA_MAX_HEALTH));
|
health = min(LARA_MAX_HEALTH, health + (item == TR::Entity::INV_MEDIKIT_SMALL ? LARA_MAX_HEALTH / 2 : LARA_MAX_HEALTH));
|
||||||
playSound(TR::SND_HEALTH, pos, Sound::PAN);
|
playSound(TR::SND_HEALTH, pos, Sound::PAN);
|
||||||
break;
|
break;
|
||||||
@@ -1866,7 +1886,7 @@ struct Lara : Character {
|
|||||||
|
|
||||||
virtual int getStateDeath() {
|
virtual int getStateDeath() {
|
||||||
velocity = vec3(0.0f);
|
velocity = vec3(0.0f);
|
||||||
return STATE_DEATH;
|
return (stand == STAND_UNDERWATER || stand == STAND_ONWATER) ? STATE_UNDERWATER_DEATH : STATE_DEATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int getStateDefault() {
|
virtual int getStateDefault() {
|
||||||
@@ -1952,6 +1972,18 @@ struct Lara : Character {
|
|||||||
|
|
||||||
virtual void update() {
|
virtual void update() {
|
||||||
Character::update();
|
Character::update();
|
||||||
|
|
||||||
|
if (damageTime > 0.0f)
|
||||||
|
damageTime = max(0.0f, damageTime - Core::deltaTime);
|
||||||
|
|
||||||
|
if (stand == STAND_UNDERWATER) {
|
||||||
|
if (oxygen > 0.0f)
|
||||||
|
oxygen -= Core::deltaTime;
|
||||||
|
else
|
||||||
|
hit(Core::deltaTime * 150.0f);
|
||||||
|
} else
|
||||||
|
if (oxygen < LARA_MAX_OXYGEN)
|
||||||
|
oxygen = min(LARA_MAX_OXYGEN, oxygen += Core::deltaTime * 10.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateAnimation(bool commands) {
|
virtual void updateAnimation(bool commands) {
|
||||||
|
65
src/level.h
65
src/level.h
@@ -295,10 +295,10 @@ struct Level : IGame {
|
|||||||
|
|
||||||
level.cameraController = camera;
|
level.cameraController = camera;
|
||||||
|
|
||||||
ambientCache = Core::settings.ambient ? new AmbientCache(this) : NULL;
|
ambientCache = Core::settings.detail.ambient ? new AmbientCache(this) : NULL;
|
||||||
waterCache = Core::settings.water ? new WaterCache(this) : NULL;
|
waterCache = Core::settings.detail.water ? new WaterCache(this) : NULL;
|
||||||
zoneCache = new ZoneCache(this);
|
zoneCache = new ZoneCache(this);
|
||||||
shadow = Core::settings.shadows ? new Texture(SHADOW_TEX_SIZE, SHADOW_TEX_SIZE, Texture::SHADOW, false) : NULL;
|
shadow = Core::settings.detail.shadows ? new Texture(SHADOW_TEX_SIZE, SHADOW_TEX_SIZE, Texture::SHADOW, false) : NULL;
|
||||||
|
|
||||||
initReflections();
|
initReflections();
|
||||||
|
|
||||||
@@ -379,11 +379,29 @@ struct Level : IGame {
|
|||||||
int i = y * 1024 + x;
|
int i = y * 1024 + x;
|
||||||
data[i].r = data[i].g = data[i].b = data[i].a = 255; // white texel for colored triangles
|
data[i].r = data[i].g = data[i].b = data[i].a = 255; // white texel for colored triangles
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
|
// uint32 healthBar[1+5+1] = { 0xFF2C5C70, 0xFF2C5C70, 0xFF4878A4, 0xFF2C5C70, 0xFF004458, 0xFF143050, 0xFF143050 };
|
||||||
|
uint32 healthBar[1+5+1] = { 0xFF2C5D71, 0xFF2C5D71, 0xFF5E81AE, 0xFF2C5D71, 0xFF1B4557, 0xFF16304F, 0xFF16304F };
|
||||||
|
|
||||||
|
for (int y = 0; y < COUNT(healthBar); y++)
|
||||||
|
for (int x = 0; x < 2; x++) {
|
||||||
|
int i = (TEX_HEALTH_BAR_Y + y) * 1024 + (TEX_HEALTH_BAR_X + x);
|
||||||
|
*((uint32*)&data[i]) = healthBar[y];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 oxygenBar[1+5+1] = { 0xFF647464, 0xFF647464, 0xFFA47848, 0xFF647464, 0xFF4C504C, 0xFF303030, 0xFF303030 };
|
||||||
|
for (int y = 0; y < COUNT(oxygenBar); y++)
|
||||||
|
for (int x = 0; x < 2; x++) {
|
||||||
|
int i = (TEX_OXYGEN_BAR_Y + y) * 1024 + (TEX_OXYGEN_BAR_X + x);
|
||||||
|
*((uint32*)&data[i]) = oxygenBar[y];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
FILE *f = fopen("atlas.raw", "wb");
|
FILE *f = fopen("atlas.raw", "wb");
|
||||||
fwrite(data, 1024 * 1024 * 4, 1, f);
|
fwrite(data, 1024 * 1024 * 4, 1, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
atlas = new Texture(1024, 1024, Texture::RGBA, false, data);
|
atlas = new Texture(1024, 1024, Texture::RGBA, false, data);
|
||||||
PROFILE_LABEL(TEXTURE, atlas->ID, "atlas");
|
PROFILE_LABEL(TEXTURE, atlas->ID, "atlas");
|
||||||
@@ -590,7 +608,7 @@ struct Level : IGame {
|
|||||||
|
|
||||||
if (isModel) { // model
|
if (isModel) { // model
|
||||||
vec3 pos = controller->getPos();
|
vec3 pos = controller->getPos();
|
||||||
if (Core::settings.ambient) {
|
if (Core::settings.detail.ambient) {
|
||||||
AmbientCache::Cube cube;
|
AmbientCache::Cube cube;
|
||||||
if (Core::stats.frame != controller->frameIndex) {
|
if (Core::stats.frame != controller->frameIndex) {
|
||||||
ambientCache->getAmbient(entity.room, pos, cube);
|
ambientCache->getAmbient(entity.room, pos, cube);
|
||||||
@@ -647,11 +665,9 @@ struct Level : IGame {
|
|||||||
|
|
||||||
sndCurrent = camera->isUnderwater() ? sndUnderwater : sndSoundtrack;
|
sndCurrent = camera->isUnderwater() ? sndUnderwater : sndSoundtrack;
|
||||||
|
|
||||||
if (sndCurrent) {
|
if (sndSoundtrack && sndCurrent != sndSoundtrack) sndSoundtrack->volume = 0.0f;
|
||||||
if (sndSoundtrack && sndCurrent != sndSoundtrack) sndSoundtrack->volume = 0.0f;
|
if (sndUnderwater && sndCurrent != sndUnderwater) sndUnderwater->volume = 0.0f;
|
||||||
if (sndUnderwater && sndCurrent != sndUnderwater) sndUnderwater->volume = 0.0f;
|
if (sndCurrent) sndCurrent->volume = 1.0f;
|
||||||
sndCurrent->volume = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waterCache)
|
if (waterCache)
|
||||||
waterCache->update();
|
waterCache->update();
|
||||||
@@ -949,6 +965,31 @@ struct Level : IGame {
|
|||||||
inventory.render();
|
inventory.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void renderUI() {
|
||||||
|
UI::begin();
|
||||||
|
|
||||||
|
// render health & oxygen bars
|
||||||
|
vec2 size = vec2(180, 10);
|
||||||
|
|
||||||
|
float health = lara->health / float(LARA_MAX_HEALTH);
|
||||||
|
float oxygen = lara->oxygen / float(LARA_MAX_OXYGEN);
|
||||||
|
|
||||||
|
if ((params->time - int(params->time)) < 0.5f) { // blinking
|
||||||
|
if (health <= 0.2f) health = 0.0f;
|
||||||
|
if (oxygen <= 0.2f) oxygen = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inventory.showHealthBar() || (!inventory.active && (!lara->emptyHands() || lara->damageTime > 0.0f || health <= 0.2f)))
|
||||||
|
UI::renderBar(0, vec2(32, 32), size, health);
|
||||||
|
|
||||||
|
if (lara->stand == Lara::STAND_ONWATER || lara->stand == Character::STAND_UNDERWATER)
|
||||||
|
UI::renderBar(1, vec2(UI::width - 32 - size.x, 32), size, oxygen);
|
||||||
|
|
||||||
|
inventory.renderUI();
|
||||||
|
|
||||||
|
UI::end();
|
||||||
|
}
|
||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
bool title = isTitle();
|
bool title = isTitle();
|
||||||
bool copyBg = title && lastTitle != title;
|
bool copyBg = title && lastTitle != title;
|
||||||
@@ -970,6 +1011,8 @@ struct Level : IGame {
|
|||||||
if (title)
|
if (title)
|
||||||
renderInventory();
|
renderInventory();
|
||||||
|
|
||||||
|
renderUI();
|
||||||
|
|
||||||
lastTitle = title;
|
lastTitle = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
148
src/mesh.h
148
src/mesh.h
@@ -4,6 +4,12 @@
|
|||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
|
||||||
|
#define TEX_HEALTH_BAR_X 1000
|
||||||
|
#define TEX_HEALTH_BAR_Y 1000
|
||||||
|
|
||||||
|
#define TEX_OXYGEN_BAR_X 1002
|
||||||
|
#define TEX_OXYGEN_BAR_Y 1000
|
||||||
|
|
||||||
typedef unsigned short Index;
|
typedef unsigned short Index;
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
@@ -184,7 +190,6 @@ struct MeshBuilder {
|
|||||||
MeshRange *sequences;
|
MeshRange *sequences;
|
||||||
// procedured
|
// procedured
|
||||||
MeshRange shadowBlob, shadowBox;
|
MeshRange shadowBlob, shadowBox;
|
||||||
MeshRange bar;
|
|
||||||
MeshRange quad, circle;
|
MeshRange quad, circle;
|
||||||
MeshRange plane;
|
MeshRange plane;
|
||||||
|
|
||||||
@@ -227,7 +232,7 @@ struct MeshBuilder {
|
|||||||
iCount += d.rCount * 6 + d.tCount * 3;
|
iCount += d.rCount * 6 + d.tCount * 3;
|
||||||
vCount += d.rCount * 4 + d.tCount * 3;
|
vCount += d.rCount * 4 + d.tCount * 3;
|
||||||
|
|
||||||
if (Core::settings.water)
|
if (Core::settings.detail.water)
|
||||||
roomRemoveWaterSurfaces(r, iCount, vCount);
|
roomRemoveWaterSurfaces(r, iCount, vCount);
|
||||||
|
|
||||||
for (int j = 0; j < r.meshesCount; j++) {
|
for (int j = 0; j < r.meshesCount; j++) {
|
||||||
@@ -288,13 +293,6 @@ struct MeshBuilder {
|
|||||||
iCount += shadowBox.iCount;
|
iCount += shadowBox.iCount;
|
||||||
vCount += 4 * 6;
|
vCount += 4 * 6;
|
||||||
|
|
||||||
// bar (health, oxygen)
|
|
||||||
bar.vStart = vCount;
|
|
||||||
bar.iStart = iCount;
|
|
||||||
bar.iCount = 2 * 3;
|
|
||||||
iCount += bar.iCount;
|
|
||||||
vCount += 4;
|
|
||||||
|
|
||||||
// quad (post effect filter)
|
// quad (post effect filter)
|
||||||
quad.vStart = vCount;
|
quad.vStart = vCount;
|
||||||
quad.iStart = iCount;
|
quad.iStart = iCount;
|
||||||
@@ -498,22 +496,6 @@ struct MeshBuilder {
|
|||||||
aCount++;
|
aCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// white bar
|
|
||||||
addQuad(indices, iCount, vCount, bar.vStart, vertices, &whiteTile);
|
|
||||||
vertices[vCount + 0].coord = { 0, 0, 0, 0 };
|
|
||||||
vertices[vCount + 1].coord = { 1, 0, 0, 0 };
|
|
||||||
vertices[vCount + 2].coord = { 1, 1, 0, 0 };
|
|
||||||
vertices[vCount + 3].coord = { 0, 1, 0, 0 };
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Vertex &v = vertices[vCount + i];
|
|
||||||
v.normal = { 0, 0, 0, 0 };
|
|
||||||
v.color = { 255, 255, 255, 255 };
|
|
||||||
v.texCoord = { 32688, 32688, 0, 0 };
|
|
||||||
}
|
|
||||||
vCount += 4;
|
|
||||||
aCount++;
|
|
||||||
|
|
||||||
// quad
|
// quad
|
||||||
addQuad(indices, iCount, vCount, quad.vStart, vertices, &whiteTile);
|
addQuad(indices, iCount, vCount, quad.vStart, vertices, &whiteTile);
|
||||||
vertices[vCount + 3].coord = { -1, -1, 0, 0 };
|
vertices[vCount + 3].coord = { -1, -1, 0, 0 };
|
||||||
@@ -595,7 +577,6 @@ struct MeshBuilder {
|
|||||||
mesh->initRange(models[i].geometry);
|
mesh->initRange(models[i].geometry);
|
||||||
mesh->initRange(shadowBlob);
|
mesh->initRange(shadowBlob);
|
||||||
mesh->initRange(shadowBox);
|
mesh->initRange(shadowBox);
|
||||||
mesh->initRange(bar);
|
|
||||||
mesh->initRange(quad);
|
mesh->initRange(quad);
|
||||||
mesh->initRange(circle);
|
mesh->initRange(circle);
|
||||||
mesh->initRange(plane);
|
mesh->initRange(plane);
|
||||||
@@ -978,6 +959,93 @@ struct MeshBuilder {
|
|||||||
vCount += 4;
|
vCount += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addBar(Index *indices, Vertex *vertices, int &iCount, int &vCount, int type, const vec2 &pos, const vec2 &size, uint32 color) {
|
||||||
|
addQuad(indices, iCount, vCount, 0, vertices, NULL);
|
||||||
|
|
||||||
|
int16 minX = int16(pos.x);
|
||||||
|
int16 minY = int16(pos.y);
|
||||||
|
int16 maxX = int16(size.x) + minX;
|
||||||
|
int16 maxY = int16(size.y) + minY;
|
||||||
|
|
||||||
|
vertices[vCount + 0].coord = { minX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 1].coord = { maxX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 2].coord = { maxX, maxY, 0, 0 };
|
||||||
|
vertices[vCount + 3].coord = { minX, maxY, 0, 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
Vertex &v = vertices[vCount + i];
|
||||||
|
v.normal = { 0, 0, 0, 0 };
|
||||||
|
v.color = *((ubyte4*)&color);
|
||||||
|
|
||||||
|
int16 s, t;
|
||||||
|
|
||||||
|
if (type == 0) { // health bar
|
||||||
|
s = TEX_HEALTH_BAR_X + 1;
|
||||||
|
t = TEX_HEALTH_BAR_Y + 1;
|
||||||
|
} else { // oxygen bar
|
||||||
|
s = TEX_OXYGEN_BAR_X + 1;
|
||||||
|
t = TEX_OXYGEN_BAR_Y + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 1) t += 5;
|
||||||
|
|
||||||
|
s = int(s) * 32767 / 1024;
|
||||||
|
t = int(t) * 32767 / 1024;
|
||||||
|
|
||||||
|
v.texCoord = { s, t, 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
vCount += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFrame(Index *indices, Vertex *vertices, int &iCount, int &vCount, const vec2 &pos, const vec2 &size, uint32 color1, uint32 color2) {
|
||||||
|
int16 minX = int16(pos.x);
|
||||||
|
int16 minY = int16(pos.y);
|
||||||
|
int16 maxX = int16(size.x) + minX;
|
||||||
|
int16 maxY = int16(size.y) + minY;
|
||||||
|
|
||||||
|
vertices[vCount + 0].coord = { minX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 1].coord = { maxX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 2].coord = { maxX, int16(minY + 1), 0, 0 };
|
||||||
|
vertices[vCount + 3].coord = { minX, int16(minY + 1), 0, 0 };
|
||||||
|
|
||||||
|
vertices[vCount + 4].coord = { minX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 5].coord = { int16(minX + 1), minY, 0, 0 };
|
||||||
|
vertices[vCount + 6].coord = { int16(minX + 1), maxY, 0, 0 };
|
||||||
|
vertices[vCount + 7].coord = { minX, maxY, 0, 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
Vertex &v = vertices[vCount + i];
|
||||||
|
v.normal = { 0, 0, 0, 0 };
|
||||||
|
v.color = *((ubyte4*)&color1);
|
||||||
|
v.texCoord = { 32688, 32688, 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
addQuad(indices, iCount, vCount, 0, vertices, NULL); vCount += 4;
|
||||||
|
addQuad(indices, iCount, vCount, 0, vertices, NULL); vCount += 4;
|
||||||
|
|
||||||
|
vertices[vCount + 0].coord = { minX, int16(maxY - 1), 0, 0 };
|
||||||
|
vertices[vCount + 1].coord = { maxX, int16(maxY - 1), 0, 0 };
|
||||||
|
vertices[vCount + 2].coord = { maxX, maxY, 0, 0 };
|
||||||
|
vertices[vCount + 3].coord = { minX, maxY, 0, 0 };
|
||||||
|
|
||||||
|
vertices[vCount + 4].coord = { int16(maxX - 1), minY, 0, 0 };
|
||||||
|
vertices[vCount + 5].coord = { maxX, minY, 0, 0 };
|
||||||
|
vertices[vCount + 6].coord = { maxX, maxY, 0, 0 };
|
||||||
|
vertices[vCount + 7].coord = { int16(maxX - 1), maxY, 0, 0 };
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
Vertex &v = vertices[vCount + i];
|
||||||
|
v.normal = { 0, 0, 0, 0 };
|
||||||
|
v.color = *((ubyte4*)&color2);
|
||||||
|
v.texCoord = { 32688, 32688, 0, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
addQuad(indices, iCount, vCount, 0, vertices, NULL); vCount += 4;
|
||||||
|
addQuad(indices, iCount, vCount, 0, vertices, NULL); vCount += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void bind() {
|
void bind() {
|
||||||
mesh->bind();
|
mesh->bind();
|
||||||
}
|
}
|
||||||
@@ -1029,34 +1097,6 @@ struct MeshBuilder {
|
|||||||
void renderPlane() {
|
void renderPlane() {
|
||||||
mesh->render(plane);
|
mesh->render(plane);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderBar(const vec2 &size, float value) {
|
|
||||||
/*
|
|
||||||
float w = size.y / 9.0f;
|
|
||||||
// health bar
|
|
||||||
enum Colors {
|
|
||||||
clBlack = 0xFF000000,
|
|
||||||
clGrayL = 0xFF748474,
|
|
||||||
clGrayD = 0xFF4C504C,
|
|
||||||
clRed1 = 0xFF705C2C,
|
|
||||||
clRed2 = 0xFFA47848,
|
|
||||||
clRed3 = 0xFF705C2C,
|
|
||||||
clRed4 = 0xFF584400,
|
|
||||||
clRed5 = 0xFF503014,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32 *d = (uint32*)&data[0];
|
|
||||||
d[0] = clGrayD; d[1] = clGrayD; d[2] = clGrayD; d[3] = clGrayD; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clBlack; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clRed1; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clRed2; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clRed3; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clRed4; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clRed5; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clBlack; d[2] = clBlack; d[3] = clBlack; d[4] = clGrayL; d+= 1024;
|
|
||||||
d[0] = clGrayD; d[1] = clGrayL; d[2] = clGrayL; d[3] = clGrayL; d[4] = clGrayL; d+= 1024;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -215,12 +215,9 @@
|
|||||||
<ClInclude Include="..\..\utils.h" />
|
<ClInclude Include="..\..\utils.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\shaders\depth.glsl" />
|
|
||||||
<None Include="..\..\shaders\filter.glsl" />
|
<None Include="..\..\shaders\filter.glsl" />
|
||||||
<None Include="..\..\shaders\gui.glsl" />
|
<None Include="..\..\shaders\gui.glsl" />
|
||||||
<None Include="..\..\shaders\shader.glsl" />
|
<None Include="..\..\shaders\shader.glsl" />
|
||||||
<None Include="..\..\shaders\shadow.glsl" />
|
|
||||||
<None Include="..\..\shaders\volume.glsl" />
|
|
||||||
<None Include="..\..\shaders\water.glsl" />
|
<None Include="..\..\shaders\water.glsl" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@@ -42,9 +42,6 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\shaders\depth.glsl">
|
|
||||||
<Filter>shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="..\..\shaders\filter.glsl">
|
<None Include="..\..\shaders\filter.glsl">
|
||||||
<Filter>shaders</Filter>
|
<Filter>shaders</Filter>
|
||||||
</None>
|
</None>
|
||||||
@@ -54,12 +51,6 @@
|
|||||||
<None Include="..\..\shaders\shader.glsl">
|
<None Include="..\..\shaders\shader.glsl">
|
||||||
<Filter>shaders</Filter>
|
<Filter>shaders</Filter>
|
||||||
</None>
|
</None>
|
||||||
<None Include="..\..\shaders\shadow.glsl">
|
|
||||||
<Filter>shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="..\..\shaders\volume.glsl">
|
|
||||||
<Filter>shaders</Filter>
|
|
||||||
</None>
|
|
||||||
<None Include="..\..\shaders\water.glsl">
|
<None Include="..\..\shaders\water.glsl">
|
||||||
<Filter>shaders</Filter>
|
<Filter>shaders</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
@@ -3,10 +3,12 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
<LocalDebuggerCommandArguments>data/LEVEL3A.PSX</LocalDebuggerCommandArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
<LocalDebuggerCommandArguments>data/LEVEL2.PHD</LocalDebuggerCommandArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
||||||
@@ -15,5 +17,6 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
<LocalDebuggerWorkingDirectory>../../../bin</LocalDebuggerWorkingDirectory>
|
||||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||||
|
<LocalDebuggerCommandArguments>data/LEVEL2.PSX</LocalDebuggerCommandArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
@@ -1,80 +0,0 @@
|
|||||||
R"====(
|
|
||||||
#ifdef GL_ES
|
|
||||||
precision lowp int;
|
|
||||||
precision highp float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ALPHA_TEST)
|
|
||||||
varying vec2 vTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TEXCOORD_SCALE (1.0 / 32767.0)
|
|
||||||
|
|
||||||
#ifdef VERTEX
|
|
||||||
attribute vec4 aCoord;
|
|
||||||
|
|
||||||
#if defined(TYPE_SPRITE) || defined(ALPHA_TEST)
|
|
||||||
attribute vec4 aTexCoord;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TYPE_SPRITE
|
|
||||||
uniform mat4 uViewInv;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform mat4 uViewProj;
|
|
||||||
|
|
||||||
#ifdef TYPE_ENTITY
|
|
||||||
uniform vec4 uBasis[32 * 2];
|
|
||||||
#else
|
|
||||||
uniform vec4 uBasis[2];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec3 mulQuat(vec4 q, vec3 v) {
|
|
||||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 mulBasis(vec4 rot, vec4 pos, vec3 v) {
|
|
||||||
return mulQuat(rot, v) + pos.xyz;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 _transform() {
|
|
||||||
#ifdef TYPE_ENTITY
|
|
||||||
int index = int(aCoord.w * 2.0);
|
|
||||||
vec4 rBasisRot = uBasis[index];
|
|
||||||
vec4 rBasisPos = uBasis[index + 1];
|
|
||||||
#else
|
|
||||||
vec4 rBasisRot = uBasis[0];
|
|
||||||
vec4 rBasisPos = uBasis[1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
|
|
||||||
|
|
||||||
#ifdef TYPE_SPRITE
|
|
||||||
coord.xyz += uViewInv[0].xyz * aTexCoord.z - uViewInv[1].xyz * aTexCoord.w;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ALPHA_TEST)
|
|
||||||
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return coord;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = uViewProj * _transform();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#ifdef ALPHA_TEST
|
|
||||||
uniform sampler2D sDiffuse;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#ifdef ALPHA_TEST
|
|
||||||
if (texture2D(sDiffuse, vTexCoord).w <= 0.5)
|
|
||||||
discard;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_FragColor = vec4(0.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
)===="
|
|
@@ -5,26 +5,29 @@ R"====(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
varying vec2 vTexCoord;
|
varying vec2 vTexCoord;
|
||||||
|
varying vec4 vColor;
|
||||||
|
|
||||||
#ifdef VERTEX
|
#ifdef VERTEX
|
||||||
uniform mat4 uViewProj;
|
uniform mat4 uViewProj;
|
||||||
uniform vec4 uPosScale;
|
uniform vec4 uPosScale;
|
||||||
|
uniform vec4 uMaterial;
|
||||||
|
|
||||||
attribute vec4 aCoord;
|
attribute vec4 aCoord;
|
||||||
attribute vec4 aTexCoord;
|
attribute vec4 aTexCoord;
|
||||||
|
attribute vec4 aColor;
|
||||||
|
|
||||||
#define TEXCOORD_SCALE (1.0 / 32767.0)
|
#define TEXCOORD_SCALE (1.0 / 32767.0)
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
|
vTexCoord = aTexCoord.xy * TEXCOORD_SCALE;
|
||||||
|
vColor = aColor * uMaterial;
|
||||||
gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
|
gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uniform sampler2D sDiffuse;
|
uniform sampler2D sDiffuse;
|
||||||
uniform vec4 uMaterial;
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = texture2D(sDiffuse, vTexCoord) * uMaterial;
|
gl_FragColor = texture2D(sDiffuse, vTexCoord) * vColor;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
)===="
|
)===="
|
@@ -1,135 +0,0 @@
|
|||||||
R"====(
|
|
||||||
#ifdef GL_ES
|
|
||||||
precision lowp int;
|
|
||||||
precision highp float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
varying vec3 vNormal;
|
|
||||||
varying vec4 vLightProj;
|
|
||||||
varying vec3 vLightVec;
|
|
||||||
|
|
||||||
uniform vec3 uLightPos[MAX_LIGHTS];
|
|
||||||
uniform vec4 uLightColor[MAX_LIGHTS]; // xyz - color, w - radius * intensity
|
|
||||||
|
|
||||||
#ifdef VERTEX
|
|
||||||
attribute vec4 aCoord;
|
|
||||||
attribute vec4 aNormal;
|
|
||||||
|
|
||||||
uniform mat4 uViewProj;
|
|
||||||
uniform mat4 uLightProj;
|
|
||||||
|
|
||||||
#ifdef TYPE_ENTITY
|
|
||||||
uniform vec4 uBasis[32 * 2];
|
|
||||||
#else
|
|
||||||
uniform vec4 uBasis[2];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec3 mulQuat(vec4 q, vec3 v) {
|
|
||||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 mulBasis(vec4 rot, vec4 pos, vec3 v) {
|
|
||||||
return mulQuat(rot, v) + pos.xyz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
#ifdef TYPE_ENTITY
|
|
||||||
int index = int(aCoord.w * 2.0);
|
|
||||||
vec4 rBasisRot = uBasis[index];
|
|
||||||
vec4 rBasisPos = uBasis[index + 1];
|
|
||||||
#else
|
|
||||||
vec4 rBasisRot = uBasis[0];
|
|
||||||
vec4 rBasisPos = uBasis[1];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vNormal = normalize(mulQuat(rBasisRot, aNormal.xyz));
|
|
||||||
|
|
||||||
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
|
|
||||||
|
|
||||||
vLightProj = uLightProj * coord;
|
|
||||||
vLightVec = (uLightPos[0].xyz - coord.xyz) * uLightColor[0].w;
|
|
||||||
|
|
||||||
gl_Position = uViewProj * coord;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#ifdef SHADOW_SAMPLER
|
|
||||||
uniform sampler2DShadow sShadow;
|
|
||||||
#ifdef GL_ES
|
|
||||||
#define SHADOW(V) (shadow2DEXT(sShadow, V))
|
|
||||||
#else
|
|
||||||
#define SHADOW(V) (shadow2D(sShadow, V).x)
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
uniform sampler2D sShadow;
|
|
||||||
#define CMP(a,b) step(b, a)
|
|
||||||
|
|
||||||
#ifdef SHADOW_DEPTH
|
|
||||||
#define compare(p, z) CMP(texture2D(sShadow, (p)).x, (z));
|
|
||||||
#elif defined(SHADOW_COLOR)
|
|
||||||
float unpack(vec4 value) {
|
|
||||||
vec4 bitSh = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
|
|
||||||
return dot(value, bitSh);
|
|
||||||
}
|
|
||||||
#define compare(p, z) CMP(unpack(texture2D(sShadow, (p))), (z));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float SHADOW(vec3 p) {
|
|
||||||
return compare(p.xy, p.z);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SHADOW_TEXEL (2.0 / 1024.0)
|
|
||||||
|
|
||||||
float random(vec3 seed, float freq) {
|
|
||||||
float dt = dot(floor(seed * freq), vec3(53.1215, 21.1352, 9.1322));
|
|
||||||
return fract(sin(dt) * 2105.2354);
|
|
||||||
}
|
|
||||||
|
|
||||||
float randomAngle(vec3 seed, float freq) {
|
|
||||||
return random(seed, freq) * 6.283285;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 rotate(vec2 sc, vec2 v) {
|
|
||||||
return vec3(v.x * sc.y + v.y * sc.x, v.x * -sc.x + v.y * sc.y, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
float getShadow(vec4 lightProj) {
|
|
||||||
vec3 p = lightProj.xyz / lightProj.w;
|
|
||||||
|
|
||||||
float rShadow = SHADOW(SHADOW_TEXEL * vec3(-0.93289, -0.03146, 0.0) + p) +
|
|
||||||
SHADOW(SHADOW_TEXEL * vec3( 0.81628, -0.05965, 0.0) + p) +
|
|
||||||
SHADOW(SHADOW_TEXEL * vec3(-0.18455, 0.97225, 0.0) + p) +
|
|
||||||
SHADOW(SHADOW_TEXEL * vec3( 0.04032, -0.85898, 0.0) + p);
|
|
||||||
|
|
||||||
if (rShadow > 0.1 && rShadow < 3.9) {
|
|
||||||
float angle = randomAngle(gl_FragCoord.xyz, 15.0);
|
|
||||||
vec2 sc = vec2(sin(angle), cos(angle));
|
|
||||||
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2(-0.54316, 0.21186)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2(-0.03925, -0.34345)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2( 0.07695, 0.40667)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2(-0.66378, -0.54068)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2(-0.54130, 0.66730)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2( 0.69301, 0.46990)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2( 0.37228, 0.03811)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2( 0.28597, 0.80228)) + p);
|
|
||||||
rShadow += SHADOW(SHADOW_TEXEL * rotate(sc, vec2( 0.44801, -0.43844)) + p);
|
|
||||||
rShadow /= 13.0;
|
|
||||||
} else
|
|
||||||
rShadow /= 4.0;
|
|
||||||
|
|
||||||
float fade = clamp(dot(vLightVec, vLightVec), 0.0, 1.0);
|
|
||||||
|
|
||||||
return mix(rShadow, 1.0, fade);
|
|
||||||
}
|
|
||||||
|
|
||||||
float getShadow() {
|
|
||||||
return min(dot(vNormal.xyz, vLightVec), vLightProj.w) > 0.0 ? getShadow(vLightProj) : 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float s = getShadow();
|
|
||||||
gl_FragColor = vec4(s, s, s, 1.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
)===="
|
|
@@ -1,45 +0,0 @@
|
|||||||
R"====(
|
|
||||||
#ifdef GL_ES
|
|
||||||
precision lowp int;
|
|
||||||
precision highp float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
varying vec3 color;
|
|
||||||
|
|
||||||
#ifdef VERTEX
|
|
||||||
attribute vec4 aCoord;
|
|
||||||
attribute vec4 aNormal;
|
|
||||||
attribute vec4 aColor;
|
|
||||||
|
|
||||||
uniform mat4 uViewProj;
|
|
||||||
uniform vec4 uBasis[2]; // quat rot, pos
|
|
||||||
uniform vec3 uPosScale; // xyz - scale
|
|
||||||
uniform vec4 uLightPos; // xyz - pos, w - radius
|
|
||||||
|
|
||||||
vec3 mulQuat(vec4 q, vec3 v) {
|
|
||||||
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 mulBasis(vec4 rot, vec4 pos, vec3 v) {
|
|
||||||
return mulQuat(rot, v) + pos.xyz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 c = vec4(mulBasis(uBasis[0], uBasis[1], aCoord.xyz * uPosScale), 1.0);
|
|
||||||
vec3 n = mulQuat(uBasis[0], normalize(aNormal.xyz));
|
|
||||||
vec3 lv = uLightPos.xyz - c.xyz;
|
|
||||||
|
|
||||||
if (dot(lv, n) < 0.0)
|
|
||||||
c.xyz -= normalize(lv) * uLightPos.w;
|
|
||||||
|
|
||||||
color = aColor.xyz;
|
|
||||||
|
|
||||||
gl_Position = uViewProj * c;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = vec4(color, 1.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
)===="
|
|
36
src/ui.h
36
src/ui.h
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
namespace UI {
|
namespace UI {
|
||||||
IGame *game;
|
IGame *game;
|
||||||
|
float width;
|
||||||
|
|
||||||
const static uint8 char_width[110] = {
|
const static uint8 char_width[110] = {
|
||||||
14, 11, 11, 11, 11, 11, 11, 13, 8, 11, 12, 11, 13, 13, 12, 11, 12, 12, 11, 12, 13, 13, 13, 12,
|
14, 11, 11, 11, 11, 11, 11, 13, 8, 11, 12, 11, 13, 13, 12, 11, 12, 12, 11, 12, 13, 13, 13, 12,
|
||||||
@@ -43,17 +44,37 @@ namespace UI {
|
|||||||
int vCount;
|
int vCount;
|
||||||
} buffer;
|
} buffer;
|
||||||
|
|
||||||
void textBegin() {
|
void begin() {
|
||||||
|
Core::setDepthTest(false);
|
||||||
|
Core::setBlending(bmAlpha);
|
||||||
|
Core::setCulling(cfNone);
|
||||||
|
game->setupBinding();
|
||||||
|
|
||||||
|
float aspect = float(Core::width) / float(Core::height);
|
||||||
|
width = 480 * aspect;
|
||||||
|
Core::mViewProj = mat4(0.0f, width, 480, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
game->setShader(Core::passGUI, Shader::DEFAULT);
|
||||||
|
Core::active.shader->setParam(uMaterial, vec4(1));
|
||||||
|
Core::active.shader->setParam(uPosScale, vec4(0, 0, 1, 1));
|
||||||
|
|
||||||
buffer.iCount = buffer.vCount = 0;
|
buffer.iCount = buffer.vCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void textEnd(IGame *game) {
|
void flush() {
|
||||||
if (buffer.iCount > 0) {
|
if (buffer.iCount > 0) {
|
||||||
game->getMesh()->renderBuffer(buffer.indices, buffer.iCount, buffer.vertices, buffer.vCount);
|
game->getMesh()->renderBuffer(buffer.indices, buffer.iCount, buffer.vertices, buffer.vCount);
|
||||||
buffer.iCount = buffer.vCount = 0;
|
buffer.iCount = buffer.vCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void end() {
|
||||||
|
flush();
|
||||||
|
Core::setCulling(cfFront);
|
||||||
|
Core::setBlending(bmNone);
|
||||||
|
Core::setDepthTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
void textOut(IGame *game, const vec2 &pos, const char *text, Align align = aLeft, float width = 0) {
|
void textOut(IGame *game, const vec2 &pos, const char *text, Align align = aLeft, float width = 0) {
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
@@ -80,7 +101,7 @@ namespace UI {
|
|||||||
int frame = charRemap(c);
|
int frame = charRemap(c);
|
||||||
|
|
||||||
if (buffer.iCount == MAX_CHARS * 6)
|
if (buffer.iCount == MAX_CHARS * 6)
|
||||||
textEnd(game);
|
flush();
|
||||||
|
|
||||||
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + frame];
|
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + frame];
|
||||||
mesh->addSprite(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, 0, x, y, 0, sprite, 255, true);
|
mesh->addSprite(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, 0, x, y, 0, sprite, 255, true);
|
||||||
@@ -137,8 +158,13 @@ namespace UI {
|
|||||||
Core::setDepthTest(true);
|
Core::setDepthTest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderBar(const vec2 &pos, const vec2 &size, float value) {
|
void renderBar(int type, const vec2 &pos, const vec2 &size, float value) {
|
||||||
//
|
MeshBuilder *mesh = game->getMesh();
|
||||||
|
|
||||||
|
mesh->addFrame(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, pos - 2.0f, size + 4.0f, 0xFF4C504C, 0xFF748474);
|
||||||
|
mesh->addBar(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, type, pos - 1.0f, size + 2.0f, 0x80000000);
|
||||||
|
if (value > 0.0f)
|
||||||
|
mesh->addBar(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, type, pos, vec2(size.x * value, size.y), 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user