mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-16 01:54:38 +02:00
#23 colored lights; fix water plane level; #3 temporary fix shallow water; #15 fix floor data parser for TR3; #11 fix NPOT textures loader for bmp; font shading;
This commit is contained in:
@@ -396,7 +396,7 @@ struct WaterCache {
|
||||
minZ = min(minZ, z);
|
||||
maxX = max(maxX, x);
|
||||
maxZ = max(maxZ, z);
|
||||
posY = s.ceiling * 256;
|
||||
posY = level->rooms[s.roomAbove].waterLevel;
|
||||
if (s.roomBelow != TR::NO_ROOM)
|
||||
caust = s.roomBelow;
|
||||
}
|
||||
@@ -417,8 +417,10 @@ struct WaterCache {
|
||||
bool hasWater = s.roomAbove != TR::NO_ROOM && !level->rooms[s.roomAbove].flags.water;
|
||||
if (hasWater) {
|
||||
TR::Room &rt = level->rooms[s.roomAbove];
|
||||
TR::Room::Sector &st = rt.sectors[x * rt.zSectors + z];
|
||||
hasWater = s.ceiling > st.ceiling;
|
||||
int xt = int(r.info.x + x * 1024 - rt.info.x) / 1024;
|
||||
int zt = int(r.info.z + z * 1024 - rt.info.z) / 1024;
|
||||
TR::Room::Sector &st = rt.sectors[xt * rt.zSectors + zt];
|
||||
hasWater = s.ceiling > st.ceiling; // TODO fix for LEVEL10A, use slant
|
||||
}
|
||||
|
||||
m[(x - minX) + w * (z - minZ)] = hasWater ? 0xF800 : 0;
|
||||
|
@@ -59,6 +59,17 @@ struct Character : Controller {
|
||||
updateZone();
|
||||
}
|
||||
|
||||
virtual int getRoomIndex() const {
|
||||
int index = Controller::getRoomIndex();
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
getFloorInfo(index, pos, info);
|
||||
|
||||
if (level->rooms[index].flags.water && info.roomAbove != TR::NO_ROOM && (info.floor - level->rooms[index].info.yTop) <= 512)
|
||||
return info.roomAbove;
|
||||
return index;
|
||||
}
|
||||
|
||||
bool updateZone() {
|
||||
int dx, dz;
|
||||
TR::Room::Sector &s = level->getSector(getRoomIndex(), int(pos.x), int(pos.z), dx, dz);
|
||||
|
@@ -372,7 +372,7 @@ struct Controller {
|
||||
break;
|
||||
|
||||
case TR::FloorData::CLIMB :
|
||||
info.climb = (*fd++).data; // climb mask
|
||||
info.climb = cmd.sub; // climb mask
|
||||
break;
|
||||
|
||||
case 0x07 :
|
||||
@@ -386,7 +386,7 @@ struct Controller {
|
||||
case 0x0F :
|
||||
case 0x10 :
|
||||
case 0x11 :
|
||||
case 0x12 : break; // TODO TR3 triangulation
|
||||
case 0x12 : fd++; break; // TODO TR3 triangulation
|
||||
|
||||
case 0x13 : break; // TODO TR3 monkeyswing
|
||||
|
||||
@@ -934,17 +934,19 @@ struct Controller {
|
||||
float maxAtt = 0.0f;
|
||||
|
||||
if (room.flags.sky) { // TODO trace rooms up for sun light, add direct light projection
|
||||
sunLight.x = int32(center.x);
|
||||
sunLight.y = int32(center.y) - 8192;
|
||||
sunLight.z = int32(center.z);
|
||||
targetLight = &sunLight;
|
||||
sunLight.x = int32(center.x);
|
||||
sunLight.y = int32(center.y) - 8192;
|
||||
sunLight.z = int32(center.z);
|
||||
sunLight.color = TR::Color32(255, 255, 255, 255);
|
||||
sunLight.radius = 1000 * 1024;
|
||||
targetLight = &sunLight;
|
||||
} else {
|
||||
for (int i = 0; i < room.lightsCount; i++) {
|
||||
TR::Room::Light &light = room.lights[i];
|
||||
if (light.intensity > 0x1FFF) continue;
|
||||
if ((light.color.r | light.color.g | light.color.b) == 0) continue;
|
||||
|
||||
vec3 dir = vec3(float(light.x), float(light.y), float(light.z)) - center;
|
||||
float att = max(0.0f, 1.0f - dir.length2() / float(light.radius) / float(light.radius)) * (1.0f - intensityf(light.intensity));
|
||||
float att = max(0.0f, 1.0f - dir.length2() / float(light.radius) / float(light.radius));
|
||||
|
||||
if (att > maxAtt) {
|
||||
maxAtt = att;
|
||||
@@ -962,7 +964,7 @@ struct Controller {
|
||||
}
|
||||
|
||||
vec3 tpos = vec3(float(targetLight->x), float(targetLight->y), float(targetLight->z));
|
||||
vec4 tcolor = vec4(vec3(1.0f - intensityf(targetLight->intensity)), float(targetLight->radius));
|
||||
vec4 tcolor = vec4(vec3(targetLight->color.r, targetLight->color.g, targetLight->color.b) * (1.0f / 255.0f), float(targetLight->radius));
|
||||
|
||||
if (lerp) {
|
||||
float t = Core::deltaTime * 2.0f;
|
||||
|
@@ -335,7 +335,7 @@ namespace Core {
|
||||
#define MAX_RENDER_BUFFERS 32
|
||||
#define MAX_CONTACTS 15
|
||||
#define MAX_ANIM_TEX_RANGES 32
|
||||
#define MAX_ANIM_TEX_OFFSETS 130
|
||||
#define MAX_ANIM_TEX_OFFSETS 170
|
||||
|
||||
struct Shader;
|
||||
struct Texture;
|
||||
@@ -367,7 +367,8 @@ struct Vertex {
|
||||
short4 normal; // xyz - vertex normal, w - unused
|
||||
short4 texCoord; // xy - texture coordinates, zw - trapezoid warping
|
||||
ubyte4 param; // xy - anim tex range and frame index, zw - unused
|
||||
ubyte4 color; // xyz - color, w - intensity
|
||||
ubyte4 color; // for non-textured geometry
|
||||
ubyte4 light; // xyz - color, w - use premultiplied alpha
|
||||
};
|
||||
|
||||
#ifdef PROFILE
|
||||
|
13
src/debug.h
13
src/debug.h
@@ -474,9 +474,8 @@ namespace Debug {
|
||||
for (int i = 0; i < level.roomsCount; i++)
|
||||
for (int j = 0; j < level.rooms[i].lightsCount; j++) {
|
||||
TR::Room::Light &l = level.rooms[i].lights[j];
|
||||
float a = 1.0f - intensityf(l.intensity);
|
||||
vec3 p = vec3(float(l.x), float(l.y), float(l.z));
|
||||
vec4 color = vec4(a, a, a, 1);
|
||||
vec4 color = vec4(l.color.r, l.color.g, l.color.b, 255) * (1.0f / 255.0f);
|
||||
|
||||
// if (i == room) color.x = color.z = 0;
|
||||
Debug::Draw::point(p, color);
|
||||
@@ -485,7 +484,7 @@ namespace Debug {
|
||||
Debug::Draw::sphere(p, float(l.radius), color);
|
||||
}
|
||||
|
||||
vec4 color = vec4(lara->mainLightColor.x, 0.0f, 0.0f, 1.0f);
|
||||
vec4 color = vec4(lara->mainLightColor.xyz, 1.0f);
|
||||
Debug::Draw::point(lara->mainLightPos, color);
|
||||
Debug::Draw::sphere(lara->mainLightPos, lara->mainLightColor.w, color);
|
||||
}
|
||||
@@ -658,9 +657,11 @@ namespace Debug {
|
||||
const char *getEntityName(const TR::Level &level, const TR::Entity &entity) {
|
||||
if (entity.type < TR::Entity::TR1_TYPE_MAX)
|
||||
return TR_TYPE_NAMES[entity.type - TR1_TYPES_START];
|
||||
else
|
||||
if (entity.type < TR::Entity::TR2_TYPE_MAX)
|
||||
return TR_TYPE_NAMES[entity.type - TR2_TYPES_START + TR::Entity::TR1_TYPE_MAX + 1];
|
||||
if (entity.type < TR::Entity::TR2_TYPE_MAX)
|
||||
return TR_TYPE_NAMES[entity.type - TR2_TYPES_START + (TR::Entity::TR1_TYPE_MAX - TR1_TYPES_START) + 1];
|
||||
if (entity.type < TR::Entity::TR3_TYPE_MAX)
|
||||
return TR_TYPE_NAMES[entity.type - TR3_TYPES_START + (TR::Entity::TR1_TYPE_MAX - TR1_TYPES_START) + (TR::Entity::TR2_TYPE_MAX - TR2_TYPES_START) + 2];
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
|
167
src/format.h
167
src/format.h
@@ -485,11 +485,13 @@
|
||||
E( __LARA_FLARE ) \
|
||||
E( LARA_UPV ) \
|
||||
E( VEHICLE_UPV ) \
|
||||
E( UNUSED_TR3_13 ) \
|
||||
E( VEHICLE_KAYAK ) \
|
||||
E( __VEHICLE_BOAT ) \
|
||||
E( VEHICLE_QUADBIKE ) \
|
||||
E( VEHICLE_MINECART ) \
|
||||
E( BIG_GUN ) \
|
||||
E( HYDRO_PROPELLER ) \
|
||||
E( ENEMY_TRIBESMAN_AXE ) \
|
||||
E( ENEMY_TRIBESMAN_DART ) \
|
||||
E( __ENEMY_DOG ) \
|
||||
@@ -500,8 +502,60 @@
|
||||
E( __ENEMY_CROW ) \
|
||||
E( __ENEMY_TIGER ) \
|
||||
E( ENEMY_VULTURE ) \
|
||||
\
|
||||
E( __TRAP_FLOOR = TR3_TYPES_START + 83 ) \
|
||||
E( ASSAULT_TARGET ) \
|
||||
E( ENEMY_CRAWLER_MUTANT_1 ) \
|
||||
E( ENEMY_ALLIGATOR ) \
|
||||
E( UNUSED_TR3_33 ) \
|
||||
E( ENEMY_COMPSOGNATHUS ) \
|
||||
E( ENEMY_LIZARD_MAN ) \
|
||||
E( ENEMY_PUNA ) \
|
||||
E( ENEMY_MERCENARY ) \
|
||||
E( ENEMY_RAPTOR_HUNG ) \
|
||||
E( ENEMY_RX_TECH_GUY_1 ) \
|
||||
E( ENEMY_RX_TECH_GUY_2 ) \
|
||||
E( ENEMY_ANTARC_DOG ) \
|
||||
E( ENEMY_CRAWLER_MUTANT_2 ) \
|
||||
E( UNUSED_TR3_43 ) \
|
||||
E( ENEMY_TINNOS_WASP ) \
|
||||
E( ENEMY_TINNOS_MONSTER ) \
|
||||
E( ENEMY_BRUTE_MUTANT ) \
|
||||
E( RESPAWN_TINNOS_WASP ) \
|
||||
E( RESPAWN_RAPTOR ) \
|
||||
E( ENEMY_WILLARD_SPIDER ) \
|
||||
E( ENEMY_RX_TECH_FLAME_GUY ) \
|
||||
E( ENEMY_LONDON_MERCENARY ) \
|
||||
E( UNUSED_TR3_52 ) \
|
||||
E( ENEMY_PUNK ) \
|
||||
E( UNUSED_TR3_54 ) \
|
||||
E( UNUSED_TR3_55 ) \
|
||||
E( ENEMY_LONDON_GUARD ) \
|
||||
E( ENEMY_SOPHIA ) \
|
||||
E( CLEANER_ROBOT ) \
|
||||
E( UNUSED_TR3_59 ) \
|
||||
E( ENEMY_MILITARY_1 ) \
|
||||
E( ENEMY_MILITARY_2 ) \
|
||||
E( PRISONER ) \
|
||||
E( ENEMY_MILITARY_3 ) \
|
||||
E( GUN_TURRET ) \
|
||||
E( ENEMY_DAM_GUARD ) \
|
||||
E( TRIPWIRE ) \
|
||||
E( ELECTRIC_WIRE ) \
|
||||
E( KILLER_TRIPWIRE ) \
|
||||
E( ENEMY_COBRA ) \
|
||||
E( ENEMY_SHIVA ) \
|
||||
E( ENEMY_MONKEY ) \
|
||||
E( UNUSED_TR3_72 ) \
|
||||
E( ENEMY_TONY ) \
|
||||
E( AI_GUARD ) \
|
||||
E( AI_AMBUSH ) \
|
||||
E( AI_PATROL_1 ) \
|
||||
E( AI_MODIFY ) \
|
||||
E( AI_FOLLOW ) \
|
||||
E( AI_PATROL_2 ) \
|
||||
E( AI_PATH ) \
|
||||
E( AI_CHECK ) \
|
||||
E( UNUSED_TR3_82 ) \
|
||||
E( __TRAP_FLOOR ) \
|
||||
E( UNUSED_TR3_84 ) \
|
||||
E( UNUSED_TR3_85 ) \
|
||||
E( TRAP_SWING_THING ) \
|
||||
@@ -564,7 +618,7 @@
|
||||
E( __BRIDGE_2 ) \
|
||||
E( __BRIDGE_3 ) \
|
||||
E( __INV_PASSPORT ) \
|
||||
E( __INV_COMPASS ) \
|
||||
E( __INV_STOPWATCH ) \
|
||||
E( __INV_HOME ) \
|
||||
E( __CUT_4 ) \
|
||||
E( __CUT_5 ) \
|
||||
@@ -598,7 +652,7 @@
|
||||
E( __MEDIKIT_BIG ) \
|
||||
E( __FLARES ) \
|
||||
E( __FLARE ) \
|
||||
E( __CRYSTAL ) \
|
||||
E( CRYSTAL_PICKUP ) \
|
||||
E( __INV_DETAIL ) \
|
||||
E( __INV_SOUND ) \
|
||||
E( __INV_CONTROLS ) \
|
||||
@@ -786,7 +840,11 @@
|
||||
E( __EARTHQUAKE ) \
|
||||
E( GUN_SHELL_1 ) \
|
||||
E( GUN_SHELL_2 ) \
|
||||
E( UNUSED_TR3_368 ) \
|
||||
E( UNUSED_TR3_369 ) \
|
||||
E( TINNOS_LIGHT_SHAFT ) \
|
||||
E( UNUSED_TR3_371 ) \
|
||||
E( UNUSED_TR3_372 ) \
|
||||
E( ELECTRIC_SWITCH ) \
|
||||
E( TR3_TYPE_MAX )
|
||||
|
||||
@@ -854,7 +912,9 @@ namespace TR {
|
||||
FLIP_MAP ,
|
||||
DRAW_RIGHTGUN ,
|
||||
DRAW_LEFTGUN ,
|
||||
FLICKER ,
|
||||
SHOT_RIGHTGUN ,
|
||||
SHOT_LEFTGUN ,
|
||||
FLICKER = 16,
|
||||
UNKNOWN ,
|
||||
MESH_SWAP_1 ,
|
||||
MESH_SWAP_2 ,
|
||||
@@ -1112,6 +1172,7 @@ namespace TR {
|
||||
struct { uint16 r:5, g:5, b:5, a:1; };
|
||||
uint16 value;
|
||||
|
||||
Color32 getBGR() const { return Color32((b << 3) | (b >> 2), (g << 3) | (g >> 2), (r << 3) | (r >> 2), 255); }
|
||||
operator Color24() const { return Color24((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2)); }
|
||||
operator Color32() const { return Color32((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), -a); }
|
||||
};
|
||||
@@ -1178,9 +1239,9 @@ namespace TR {
|
||||
|
||||
struct Vertex {
|
||||
TR::Vertex vertex;
|
||||
int16 lighting; // 0 (bright) .. 0x1FFF (dark)
|
||||
int16 unused_lighting; // 0 (bright) .. 0x1FFF (dark)
|
||||
uint16 attributes;
|
||||
Color16 color;
|
||||
Color32 color;
|
||||
} *vertices;
|
||||
|
||||
Rectangle *rectangles;
|
||||
@@ -1208,6 +1269,7 @@ namespace TR {
|
||||
uint8 reverbType;
|
||||
uint8 filter;
|
||||
uint8 align;
|
||||
uint32 waterLevel;
|
||||
|
||||
struct Portal {
|
||||
uint16 roomIndex;
|
||||
@@ -1239,19 +1301,15 @@ namespace TR {
|
||||
|
||||
struct Light {
|
||||
int32 x, y, z;
|
||||
uint16 intensity;
|
||||
uint16 intensity2;
|
||||
uint32 radius;
|
||||
uint32 radius2;
|
||||
Color32 color;
|
||||
} *lights;
|
||||
|
||||
struct Mesh {
|
||||
int32 x, y, z;
|
||||
angle rotation;
|
||||
Color16 color;
|
||||
int16 intensity;
|
||||
uint16 meshID;
|
||||
Color32 color;
|
||||
uint32 meshIndex; // index into static meshes array
|
||||
} *meshes;
|
||||
|
||||
@@ -1263,7 +1321,7 @@ namespace TR {
|
||||
union FloorData {
|
||||
uint16 data;
|
||||
struct Command {
|
||||
uint16 func:8, sub:7, end:1;
|
||||
uint16 func:5, tri:3, sub:7, end:1;
|
||||
} cmd;
|
||||
struct Slant {
|
||||
int8 x:8, z:8;
|
||||
@@ -1529,7 +1587,7 @@ namespace TR {
|
||||
REMAP_3( BRIDGE_2 );
|
||||
REMAP_3( BRIDGE_3 );
|
||||
REMAP_3( INV_PASSPORT );
|
||||
REMAP_3( INV_COMPASS );
|
||||
REMAP_3( INV_STOPWATCH );
|
||||
REMAP_3( INV_HOME );
|
||||
REMAP_3( CUT_4 );
|
||||
REMAP_3( CUT_5 );
|
||||
@@ -1555,7 +1613,6 @@ namespace TR {
|
||||
REMAP_3( MEDIKIT_BIG );
|
||||
REMAP_3( FLARES );
|
||||
REMAP_3( FLARE );
|
||||
REMAP_3( CRYSTAL );
|
||||
REMAP_3( INV_DETAIL );
|
||||
REMAP_3( INV_SOUND );
|
||||
REMAP_3( INV_CONTROLS );
|
||||
@@ -1660,7 +1717,16 @@ namespace TR {
|
||||
(type >= KEY_ITEM_1 && type <= KEY_ITEM_4) ||
|
||||
(type == MEDIKIT_SMALL || type == MEDIKIT_BIG) ||
|
||||
(type == SCION_PICKUP_QUALOPEC || type == SCION_PICKUP_DROP || type == SCION_PICKUP_HOLDER || type == LEADBAR) ||
|
||||
(type >= SECRET_1 && type <= SECRET_3); // TODO: recheck all items
|
||||
(type >= SECRET_1 && type <= SECRET_3) ||
|
||||
(type == M16 || type == AMMO_M16) ||
|
||||
(type == MP5 || type == AMMO_MP5) ||
|
||||
(type == AUTOPISTOLS || type == AMMO_AUTOPISTOLS) ||
|
||||
(type == DESERT_EAGLE || type == AMMO_DESERT_EAGLE) ||
|
||||
(type == GRENADE || type == AMMO_GRENADE) ||
|
||||
(type == ROCKET || type == AMMO_ROCKET) ||
|
||||
(type == HARPOON || type == AMMO_HARPOON) ||
|
||||
(type == FLARES || type == FLARE) ||
|
||||
(type >= STONE_ITEM_1 || type <= STONE_ITEM_4);
|
||||
}
|
||||
|
||||
bool isPickup() const {
|
||||
@@ -3207,6 +3273,8 @@ namespace TR {
|
||||
for (int i = 0; i < d.vCount; i++) {
|
||||
Room::Data::Vertex &v = d.vertices[i];
|
||||
|
||||
uint16 lighting;
|
||||
|
||||
if (version == VER_TR2_PSX) {
|
||||
union Compressed {
|
||||
struct { uint32 lighting:8, attributes:8, z:5, y:5, x:5, w:1; };
|
||||
@@ -3216,30 +3284,36 @@ namespace TR {
|
||||
v.vertex.x = (comp.x << 10);
|
||||
v.vertex.y = (comp.y << 8) + r.info.yTop;
|
||||
v.vertex.z = (comp.z << 10);
|
||||
v.lighting = comp.lighting;
|
||||
lighting = comp.lighting;
|
||||
v.attributes = comp.attributes;
|
||||
v.color.value = 0xFFFF;
|
||||
ASSERT(comp.w == 0);
|
||||
} else {
|
||||
stream.read(v.vertex.x);
|
||||
stream.read(v.vertex.y);
|
||||
stream.read(v.vertex.z);
|
||||
stream.read(v.lighting);
|
||||
stream.read(lighting);
|
||||
|
||||
if (version == VER_TR2_PC || version == VER_TR3_PC)
|
||||
stream.read(v.attributes);
|
||||
|
||||
if (version == VER_TR2_PC)
|
||||
stream.read(v.lighting); // real lighting value
|
||||
stream.read(lighting); // real lighting value
|
||||
|
||||
if (version == VER_TR3_PC)
|
||||
stream.read(v.color.value);
|
||||
else
|
||||
v.color.value = 0xFFFF;
|
||||
if (version == VER_TR3_PC) {
|
||||
Color16 color;
|
||||
stream.read(color.value);
|
||||
v.color = color.getBGR();
|
||||
}
|
||||
}
|
||||
|
||||
if (version & VER_PSX)
|
||||
v.lighting = 0x1FFF - (v.lighting << 5); // convert vertex luminance from PSX to PC format
|
||||
lighting = 0x1FFF - (lighting << 5); // convert vertex luminance from PSX to PC format
|
||||
|
||||
if ((version & VER_VERSION) < VER_TR3) { // lighting to color conversion
|
||||
int value = clamp((lighting > 0x1FFF) ? 255 : (255 - (lighting >> 5)), 0, 255);
|
||||
v.color.r = v.color.g = v.color.b = value;
|
||||
v.color.a = 255;
|
||||
}
|
||||
}
|
||||
|
||||
if (version == VER_TR2_PSX)
|
||||
@@ -3337,22 +3411,29 @@ namespace TR {
|
||||
stream.read(light.y);
|
||||
stream.read(light.z);
|
||||
|
||||
uint16 intensity;
|
||||
|
||||
if (version == VER_TR3_PC)
|
||||
stream.read(light.color);
|
||||
|
||||
if (version == VER_TR1_PSX) {
|
||||
uint32 intensity;
|
||||
light.intensity = stream.read(intensity);
|
||||
} else
|
||||
stream.read(light.intensity);
|
||||
stream.read(intensity);
|
||||
|
||||
if (version == VER_TR1_PSX)
|
||||
stream.seek(2);
|
||||
|
||||
if (version & (VER_TR2 | VER_TR3))
|
||||
stream.read(light.intensity2);
|
||||
stream.seek(2); // intensity2
|
||||
|
||||
stream.read(light.radius);
|
||||
|
||||
if (version & VER_TR2)
|
||||
stream.read(light.radius2);
|
||||
stream.seek(4); // radius2
|
||||
|
||||
if ((version & VER_VERSION) < VER_TR3) {
|
||||
int value = 2555 - clamp((intensity > 0x1FFF) ? 0 : (intensity >> 5), 0, 255);
|
||||
light.color.r = light.color.g = light.color.b = value;
|
||||
light.color.a = 0;
|
||||
}
|
||||
|
||||
light.radius *= 2;
|
||||
}
|
||||
@@ -3365,11 +3446,23 @@ namespace TR {
|
||||
stream.read(m.y);
|
||||
stream.read(m.z);
|
||||
stream.read(m.rotation);
|
||||
if (version & (VER_TR2 | VER_TR3))
|
||||
stream.read(m.color.value);
|
||||
if (!(version & VER_TR3))
|
||||
m.color.value = 0xFFFF;
|
||||
stream.read(m.intensity);
|
||||
if (version & VER_TR3) {
|
||||
Color16 color;
|
||||
stream.read(color.value);
|
||||
m.color = color.getBGR();
|
||||
}
|
||||
|
||||
if (version & VER_TR2)
|
||||
stream.seek(2);
|
||||
|
||||
uint16 intensity;
|
||||
stream.read(intensity);
|
||||
if ((version & VER_VERSION) < VER_TR3) {
|
||||
int value = clamp((intensity > 0x1FFF) ? 255 : (255 - (intensity >> 5)), 0, 255);
|
||||
m.color.r = m.color.g = m.color.b = value;
|
||||
m.color.a = 0;
|
||||
}
|
||||
|
||||
stream.read(m.meshID);
|
||||
if (version == VER_TR1_PSX)
|
||||
stream.seek(2); // just an align for PSX version
|
||||
|
@@ -766,7 +766,7 @@ struct Inventory {
|
||||
sprintf(buf, "%d %c", item->count, spec);
|
||||
for (int i = 0; buf[i] != ' '; i++)
|
||||
buf[i] -= 47;
|
||||
UI::textOut(pos, buf, UI::aRight, width);
|
||||
UI::textOut(pos, buf, UI::aRight, width, UI::SHADE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1071,13 +1071,13 @@ struct Inventory {
|
||||
UI::textOut(vec2( 0, 32), pageTitle[page], UI::aCenter, UI::width);
|
||||
|
||||
if (canFlipPage(-1)) {
|
||||
UI::textOut(vec2(16, 32), "[", UI::aLeft, UI::width);
|
||||
UI::textOut(vec2( 0, 32), "[", UI::aRight, UI::width - 20);
|
||||
UI::textOut(vec2(16, 32), "[", UI::aLeft, UI::width, UI::SHADE_NONE);
|
||||
UI::textOut(vec2( 0, 32), "[", UI::aRight, UI::width - 20, UI::SHADE_NONE);
|
||||
}
|
||||
|
||||
if (canFlipPage(1)) {
|
||||
UI::textOut(vec2(16, 480 - 16), "]", UI::aLeft, UI::width);
|
||||
UI::textOut(vec2(0, 480 - 16), "]", UI::aRight, UI::width - 20);
|
||||
UI::textOut(vec2(16, 480 - 16), "]", UI::aLeft, UI::width, UI::SHADE_NONE);
|
||||
UI::textOut(vec2(0, 480 - 16), "]", UI::aRight, UI::width - 20, UI::SHADE_NONE);
|
||||
}
|
||||
|
||||
if (index == targetIndex)
|
||||
|
54
src/lara.h
54
src/lara.h
@@ -949,7 +949,7 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
void updateWeapon() {
|
||||
if (level->cutEntity > -1) return;
|
||||
if (level->isCutsceneLevel()) return;
|
||||
|
||||
if (wpnNext != Weapon::EMPTY && emptyHands()) {
|
||||
wpnSet(wpnNext);
|
||||
@@ -981,13 +981,8 @@ struct Lara : Character {
|
||||
if (isRifle) break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int i = 0; i < 2; i++)
|
||||
arms[i].animation.update();
|
||||
arms[i].shotTimer += Core::deltaTime;
|
||||
|
||||
float intensity = clamp((0.1f - arms[i].shotTimer) * 20.0f, EPS, 1.0f);
|
||||
Core::lightColor[1 + i] = FLASH_LIGHT_COLOR * vec4(intensity, intensity, intensity, 1.0f / sqrtf(intensity));
|
||||
}
|
||||
|
||||
if (isRifle)
|
||||
animateShotgun();
|
||||
@@ -1382,6 +1377,8 @@ struct Lara : Character {
|
||||
case TR::Effect::LARA_HANDSFREE : break;//meshSwap(1, level->extra.weapons[wpnCurrent], BODY_LEG_L1 | BODY_LEG_R1); break;
|
||||
case TR::Effect::DRAW_RIGHTGUN : drawGun(true); break;
|
||||
case TR::Effect::DRAW_LEFTGUN : drawGun(false); break;
|
||||
case TR::Effect::SHOT_RIGHTGUN : arms[0].shotTimer = 0; break;
|
||||
case TR::Effect::SHOT_LEFTGUN : arms[1].shotTimer = 0; break;
|
||||
case TR::Effect::MESH_SWAP_1 :
|
||||
case TR::Effect::MESH_SWAP_2 :
|
||||
case TR::Effect::MESH_SWAP_3 : Character::cmdEffect(fx);
|
||||
@@ -1616,6 +1613,7 @@ struct Lara : Character {
|
||||
int goUnderwater() {
|
||||
angle.x = -PI * 0.25f;
|
||||
game->waterDrop(pos, 256.0f, 0.2f);
|
||||
stand = STAND_UNDERWATER;
|
||||
return animation.setAnim(ANIM_TO_UNDERWATER);
|
||||
}
|
||||
|
||||
@@ -2039,17 +2037,24 @@ struct Lara : Character {
|
||||
return stand;
|
||||
}
|
||||
|
||||
if (getRoom().flags.water) {
|
||||
wpnHide();
|
||||
if (stand != STAND_UNDERWATER && stand != STAND_ONWATER && (state != STATE_FALL && state != STATE_REACH && state != STATE_SWAN_DIVE && state != STATE_FAST_DIVE))
|
||||
animation.setAnim(ANIM_FALL_FORTH);
|
||||
stopScreaming();
|
||||
return STAND_UNDERWATER;
|
||||
}
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
getFloorInfo(getRoomIndex(), pos, info);
|
||||
|
||||
if (getRoom().flags.water) {
|
||||
if (stand == STAND_UNDERWATER || stand == STAND_ONWATER)
|
||||
return stand;
|
||||
wpnHide();
|
||||
if (stand == STAND_AIR) {
|
||||
//if (stand != STAND_UNDERWATER && stand != STAND_ONWATER && (state != STATE_FALL && state != STATE_REACH && state != STATE_SWAN_DIVE && state != STATE_FAST_DIVE))
|
||||
// animation.setAnim(ANIM_FALL_FORTH);
|
||||
stopScreaming();
|
||||
return STAND_UNDERWATER;
|
||||
} else {
|
||||
pos.y = info.roomCeiling;
|
||||
return STAND_ONWATER;
|
||||
}
|
||||
}
|
||||
|
||||
if ((stand == STAND_SLIDE || stand == STAND_GROUND) && (state != STATE_FORWARD_JUMP && state != STATE_BACK_JUMP)) {
|
||||
if (pos.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) {
|
||||
pos.y = info.floor;
|
||||
@@ -2081,6 +2086,8 @@ struct Lara : Character {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stand == STAND_UNDERWATER || stand == STAND_ONWATER)
|
||||
animation.setAnim(ANIM_STAND);
|
||||
return STAND_GROUND;
|
||||
}
|
||||
|
||||
@@ -2516,6 +2523,9 @@ struct Lara : Character {
|
||||
//reset(44, vec3(62976, 1536, 23040), 0);
|
||||
reset(44, vec3(62976, 1536, 23040), 0);
|
||||
break;
|
||||
case TR::LVL_TR3_TEMPLE :
|
||||
reset(204, vec3(40562, 3584, 58694), 0);
|
||||
break;
|
||||
default : game->playSound(TR::SND_NO, pos, Sound::PAN);
|
||||
}
|
||||
}
|
||||
@@ -2597,9 +2607,23 @@ struct Lara : Character {
|
||||
usedKey = TR::Entity::LARA;
|
||||
}
|
||||
|
||||
void updateFlash() {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (arms[i].shotTimer < MUZZLE_FLASH_TIME) {
|
||||
arms[i].shotTimer += Core::deltaTime;
|
||||
float intensity = clamp((0.1f - arms[i].shotTimer) * 20.0f, EPS, 1.0f);
|
||||
Core::lightColor[1 + i] = FLASH_LIGHT_COLOR * vec4(intensity, intensity, intensity, 1.0f / sqrtf(intensity));
|
||||
Core::lightPos[1 + i] = animation.getJoints(getMatrix(), i == 0 ? 10 : 13, false).pos;
|
||||
} else {
|
||||
Core::lightColor[1 + i] = vec4(0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void updateAnimation(bool commands) {
|
||||
Controller::updateAnimation(commands);
|
||||
updateWeapon();
|
||||
updateFlash();
|
||||
if (stand == STAND_UNDERWATER)
|
||||
specular = 0.0f;
|
||||
else
|
||||
|
@@ -1668,9 +1668,10 @@ struct Level : IGame {
|
||||
// Debug::Draw::box(bbox.min, bbox.max, vec4(1, 0, 1, 1));
|
||||
|
||||
// Core::setBlending(bmAlpha);
|
||||
// Core::validateRenderState();
|
||||
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
|
||||
// Debug::Level::lights(level, lara->getRoomIndex(), lara);
|
||||
// Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
|
||||
// Debug::Level::sectors(this, lara->getRoomIndex(), (int)lara->pos.y);
|
||||
// Core::setDepthTest(false);
|
||||
// Debug::Level::portals(level);
|
||||
// Core::setDepthTest(true);
|
||||
|
36
src/mesh.h
36
src/mesh.h
@@ -22,6 +22,7 @@ struct MeshRange {
|
||||
glEnableVertexAttribArray(aTexCoord);
|
||||
glEnableVertexAttribArray(aParam);
|
||||
glEnableVertexAttribArray(aColor);
|
||||
glEnableVertexAttribArray(aLight);
|
||||
|
||||
Vertex *v = (Vertex*)NULL + vStart;
|
||||
glVertexAttribPointer(aCoord, 4, GL_SHORT, false, sizeof(Vertex), &v->coord);
|
||||
@@ -29,6 +30,7 @@ struct MeshRange {
|
||||
glVertexAttribPointer(aTexCoord, 4, GL_SHORT, true, sizeof(Vertex), &v->texCoord);
|
||||
glVertexAttribPointer(aParam, 4, GL_UNSIGNED_BYTE, false, sizeof(Vertex), &v->param);
|
||||
glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->color);
|
||||
glVertexAttribPointer(aLight, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &v->light);
|
||||
}
|
||||
|
||||
void bind(GLuint *VAO) const {
|
||||
@@ -316,7 +318,7 @@ struct MeshBuilder {
|
||||
TR::Room::Data::Vertex &v = d.vertices[f.vertex];
|
||||
TR::SpriteTexture &sprite = level.spriteTextures[f.texture];
|
||||
|
||||
addSprite(indices, vertices, iCount, vCount, vStartRoom, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity(v.lighting));
|
||||
addSprite(indices, vertices, iCount, vCount, vStartRoom, v.vertex.x, v.vertex.y, v.vertex.z, sprite, v.color, v.color);
|
||||
}
|
||||
range.sprites.iCount = iCount - range.sprites.iStart;
|
||||
}
|
||||
@@ -361,7 +363,7 @@ struct MeshBuilder {
|
||||
range.iStart = iCount;
|
||||
for (int j = 0; j < level.spriteSequences[i].sCount; j++) {
|
||||
TR::SpriteTexture &sprite = level.spriteTextures[level.spriteSequences[i].sStart + j];
|
||||
addSprite(indices, vertices, iCount, vCount, vStartSprite, 0, 0, 0, sprite, 255);
|
||||
addSprite(indices, vertices, iCount, vCount, vStartSprite, 0, 0, 0, sprite, TR::Color32(255, 255, 255, 255), TR::Color32(255, 255, 255, 255));
|
||||
}
|
||||
range.iCount = iCount - range.iStart;
|
||||
}
|
||||
@@ -380,6 +382,7 @@ struct MeshBuilder {
|
||||
v0.texCoord = { whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 };
|
||||
v0.param = { 0, 0, 0, 0 };
|
||||
v0.color = { 0, 0, 0, 0 };
|
||||
v0.light = { 255, 255, 255, 255 };
|
||||
|
||||
if (i == 8) {
|
||||
v0.coord = { 0, 0, 0, 0 };
|
||||
@@ -399,6 +402,7 @@ struct MeshBuilder {
|
||||
v1 = v0;
|
||||
v1.coord = { c1, 0, s1, 0 };
|
||||
v1.color = { 255, 255, 255, 0 };
|
||||
v1.light = { 255, 255, 255, 255 };
|
||||
|
||||
int idx = iCount + i * 3 * 3;
|
||||
int j = ((i + 1) % 8) * 2;
|
||||
@@ -432,6 +436,7 @@ struct MeshBuilder {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.normal = { 0, 0, 0, 0 };
|
||||
v.color = { 255, 255, 255, 255 };
|
||||
v.light = { 255, 255, 255, 255 };
|
||||
v.texCoord = { whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 };
|
||||
v.param = { 0, 0, 0, 0 };
|
||||
}
|
||||
@@ -452,6 +457,7 @@ struct MeshBuilder {
|
||||
v.coord = { short(pos.x), short(pos.y), 0, 0 };
|
||||
v.normal = { 0, 0, 0, 0 };
|
||||
v.color = { 255, 255, 255, 255 };
|
||||
v.light = { 255, 255, 255, 255 };
|
||||
v.texCoord = { whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 };
|
||||
v.param = { 0, 0, 0, 0 };
|
||||
|
||||
@@ -575,6 +581,7 @@ struct MeshBuilder {
|
||||
}
|
||||
|
||||
void roomRemoveWaterSurfaces(TR::Room &room, int &iCount, int &vCount) {
|
||||
room.waterLevel = -1;
|
||||
// remove animated water polygons from room geometry
|
||||
for (int i = 0; i < room.data.rCount; i++) {
|
||||
TR::Rectangle &f = room.data.rectangles[i];
|
||||
@@ -601,6 +608,7 @@ struct MeshBuilder {
|
||||
if (isWaterSurface(yt, s.roomAbove, room.flags.water) ||
|
||||
isWaterSurface(yb, s.roomBelow, room.flags.water)) {
|
||||
f.vertices[0] = 0xFFFF; // mark as unused
|
||||
room.waterLevel = a.y;
|
||||
iCount -= 6;
|
||||
vCount -= 4;
|
||||
}
|
||||
@@ -630,6 +638,7 @@ struct MeshBuilder {
|
||||
if (isWaterSurface(yt, s.roomAbove, room.flags.water) ||
|
||||
isWaterSurface(yb, s.roomBelow, room.flags.water)) {
|
||||
f.vertices[0] = 0xFFFF; // mark as unused
|
||||
room.waterLevel = a.y;
|
||||
iCount -= 3;
|
||||
vCount -= 3;
|
||||
}
|
||||
@@ -664,8 +673,9 @@ struct MeshBuilder {
|
||||
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];
|
||||
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
|
||||
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
|
||||
vertices[vCount].color = { 255, 255, 255, 255 };
|
||||
TR::Color32 c = v.color;
|
||||
vertices[vCount].color = { c.b, c.g, c.r, intensity(v.lighting) };
|
||||
vertices[vCount].light = { c.r, c.g, c.b, 255 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
@@ -691,8 +701,9 @@ struct MeshBuilder {
|
||||
auto &v = d.vertices[f.vertices[k]];
|
||||
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
|
||||
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
|
||||
vertices[vCount].color = { 255, 255, 255, 255 };
|
||||
TR::Color32 c = v.color;
|
||||
vertices[vCount].color = { c.b, c.g, c.r, intensity(v.lighting) };
|
||||
vertices[vCount].light = { c.r, c.g, c.b, 255 };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
@@ -700,7 +711,7 @@ struct MeshBuilder {
|
||||
return isOpaque;
|
||||
}
|
||||
|
||||
bool buildMesh(bool opaque, const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir, const TR::Color32 &color) {
|
||||
bool buildMesh(bool opaque, const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir, const TR::Color32 &light) {
|
||||
TR::Color24 COLOR_WHITE = { 255, 255, 255 };
|
||||
bool isOpaque = true;
|
||||
|
||||
@@ -715,9 +726,6 @@ struct MeshBuilder {
|
||||
continue;
|
||||
|
||||
TR::Color32 c = f.flags.color ? level.getColor(f.flags.texture) : COLOR_WHITE;
|
||||
c.r = int(( (c.r / 255.0f) * (color.b / 255.0f) ) * 255.0f);
|
||||
c.g = int(( (c.g / 255.0f) * (color.g / 255.0f) ) * 255.0f);
|
||||
c.b = int(( (c.b / 255.0f) * (color.r / 255.0f) ) * 255.0f);
|
||||
|
||||
addQuad(indices, iCount, vCount, vStart, vertices, &t,
|
||||
mesh.vertices[f.vertices[0]].coord,
|
||||
@@ -730,7 +738,8 @@ struct MeshBuilder {
|
||||
|
||||
vertices[vCount].coord = transform(v.coord, joint, x, y, z, dir);
|
||||
vertices[vCount].normal = rotate(v.normal, dir);
|
||||
vertices[vCount].color = { c.r, c.g, c.b, intensity(v.coord.w) };
|
||||
vertices[vCount].color = { c.r, c.g, c.b, 255 };
|
||||
vertices[vCount].light = { light.r, light.g, light.b, 255 };
|
||||
|
||||
vCount++;
|
||||
}
|
||||
@@ -755,7 +764,8 @@ struct MeshBuilder {
|
||||
|
||||
vertices[vCount].coord = transform(v.coord, joint, x, y, z, dir);
|
||||
vertices[vCount].normal = rotate(v.normal, dir);
|
||||
vertices[vCount].color = { c.r, c.g, c.b, intensity(v.coord.w) };
|
||||
vertices[vCount].color = { c.r, c.g, c.b, 255 };
|
||||
vertices[vCount].light = { light.r, light.g, light.b, 255 };
|
||||
|
||||
vCount++;
|
||||
}
|
||||
@@ -905,7 +915,7 @@ struct MeshBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
void addSprite(Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 x, int16 y, int16 z, const TR::SpriteTexture &sprite, uint8 intensity, bool expand = false) {
|
||||
void addSprite(Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 x, int16 y, int16 z, const TR::SpriteTexture &sprite, const TR::Color32 &tColor, const TR::Color32 &bColor, bool expand = false) {
|
||||
addQuad(indices, iCount, vCount, vStart, NULL, NULL);
|
||||
|
||||
Vertex *quad = &vertices[vCount];
|
||||
@@ -928,7 +938,9 @@ struct MeshBuilder {
|
||||
quad[3].coord = { x0, y1, z, 0 };
|
||||
|
||||
quad[0].normal = quad[1].normal = quad[2].normal = quad[3].normal = { 0, 0, 0, 0 };
|
||||
quad[0].color = quad[1].color = quad[2].color = quad[3].color = { 255, 255, 255, intensity };
|
||||
quad[0].color = quad[1].color = { tColor.r, tColor.g, tColor.b, tColor.a };
|
||||
quad[2].color = quad[3].color = { bColor.r, bColor.g, bColor.b, bColor.a };
|
||||
quad[0].light = quad[1].light = quad[2].light = quad[3].light = { 255, 255, 255, 255 };
|
||||
quad[0].param = quad[1].param = quad[2].param = quad[3].param = { 0, 0, 0, 0 };
|
||||
|
||||
quad[0].texCoord = { sprite.texCoord[0].x, sprite.texCoord[0].y, sprite.l, sprite.t };
|
||||
|
@@ -8,7 +8,8 @@
|
||||
E( aNormal ) \
|
||||
E( aTexCoord ) \
|
||||
E( aParam ) \
|
||||
E( aColor )
|
||||
E( aColor ) \
|
||||
E( aLight )
|
||||
|
||||
#define SHADER_SAMPLERS(E) \
|
||||
E( sDiffuse ) \
|
||||
|
@@ -36,6 +36,7 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
|
||||
#ifdef OPT_SHADOW
|
||||
varying vec3 vAmbient;
|
||||
varying vec4 vLightMap;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -78,6 +79,7 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
|
||||
#ifndef PASS_SHADOW
|
||||
attribute vec4 aColor;
|
||||
attribute vec4 aLight;
|
||||
#endif
|
||||
|
||||
vec3 mulQuat(vec4 q, vec3 v) {
|
||||
@@ -140,7 +142,7 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
|
||||
void _diffuse() {
|
||||
#ifndef PASS_SHADOW
|
||||
vDiffuse = vec4(aColor.xyz * (uMaterial.x * 2.0), uMaterial.w);
|
||||
vDiffuse = vec4(aColor.xyz * (uMaterial.x * 1.8), uMaterial.w);
|
||||
|
||||
#ifdef UNDERWATER
|
||||
vDiffuse.xyz *= UNDERWATER_COLOR;
|
||||
@@ -171,7 +173,7 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
lum.x = dot(vNormal.xyz, normalize(lv0));
|
||||
att.x = dot(lv0, lv0);
|
||||
#else
|
||||
lum.x = aColor.w;
|
||||
lum.x = 1.0;
|
||||
att.x = 0.0;
|
||||
|
||||
#ifdef TYPE_SPRITE
|
||||
@@ -197,27 +199,28 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
ambient = vec3(uMaterial.y);
|
||||
#endif
|
||||
#else
|
||||
ambient = vec3(min(uMaterial.y, light.x));
|
||||
ambient = min(uMaterial.yyy, aLight.xyz);
|
||||
#endif
|
||||
|
||||
#ifdef OPT_SHADOW
|
||||
vAmbient = ambient;
|
||||
vLight = light;
|
||||
vAmbient = ambient;
|
||||
vLight = light;
|
||||
vLightMap = aLight * light.x;
|
||||
#else
|
||||
vLight.w = 0.0;
|
||||
vLight.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w;
|
||||
vLight.w = 0.0;
|
||||
|
||||
#ifdef TYPE_ENTITY
|
||||
vLight.xyz += ambient + uLightColor[0].xyz * light.x;
|
||||
#else
|
||||
vLight.xyz += light.x;
|
||||
vLight.xyz += aLight.xyz * light.x;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PASS_AMBIENT
|
||||
vLight = aColor.wwww;
|
||||
vLight = vec4(aLight.xyz, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -426,7 +429,7 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
#if !defined(TYPE_FLASH) && !defined(TYPE_MIRROR)
|
||||
|
||||
#ifdef PASS_AMBIENT
|
||||
color.xyz *= vLight.x;
|
||||
color.xyz *= vLight.xyz;
|
||||
#endif
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
@@ -450,12 +453,13 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
#endif
|
||||
|
||||
#ifdef TYPE_ROOM
|
||||
light += mix(vAmbient.x, vLight.x, rShadow);
|
||||
light += mix(vAmbient.xyz, vLightMap.xyz, rShadow);
|
||||
#endif
|
||||
|
||||
#ifdef TYPE_SPRITE
|
||||
light += vLight.x;
|
||||
light += vLightMap.xyz;
|
||||
#endif
|
||||
|
||||
#else
|
||||
vec3 light = vLight.xyz;
|
||||
#endif
|
||||
|
@@ -249,24 +249,32 @@ struct Texture {
|
||||
stream.read(width);
|
||||
stream.read(height);
|
||||
stream.seek(offset - stream.pos);
|
||||
|
||||
int dw = Core::support.texNPOT ? width : nextPow2(width);
|
||||
int dh = Core::support.texNPOT ? height : nextPow2(height);
|
||||
Color24 *data24 = new Color24[width * height];
|
||||
Color32 *data32 = new Color32[width * height];
|
||||
Color32 *data32 = new Color32[dw * dh];
|
||||
stream.raw(data24, width * height * sizeof(Color24));
|
||||
|
||||
Color32 *dst = data32;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int y = 0; y < dh; y++) {
|
||||
Color24 *src = data24 + (height - y - 1) * width;
|
||||
for (int x = 0; x < width; x++) {
|
||||
dst->r = src->b;
|
||||
dst->g = src->g;
|
||||
dst->b = src->r;
|
||||
for (int x = 0; x < dw; x++) {
|
||||
|
||||
if (x < width && y < height) {
|
||||
dst->r = src->b;
|
||||
dst->g = src->g;
|
||||
dst->b = src->r;
|
||||
src++;
|
||||
} else
|
||||
dst->r = dst->g = dst->b = 0;
|
||||
|
||||
dst->a = 255;
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
Texture *tex = new Texture(width, height, Texture::RGBA, false, data32);
|
||||
Texture *tex = new Texture(dw, dh, Texture::RGBA, false, data32);
|
||||
|
||||
delete[] data24;
|
||||
delete[] data32;
|
||||
|
44
src/ui.h
44
src/ui.h
@@ -254,12 +254,21 @@ namespace UI {
|
||||
Core::setDepthTest(true);
|
||||
}
|
||||
|
||||
void textOut(const vec2 &pos, const char *text, Align align = aLeft, float width = 0) {
|
||||
enum ShadeType {
|
||||
SHADE_NONE = 0,
|
||||
SHADE_ORANGE = 1,
|
||||
SHADE_GRAY = 2,
|
||||
};
|
||||
|
||||
void textOut(const vec2 &pos, const char *text, Align align = aLeft, float width = 0, ShadeType shade = SHADE_ORANGE, bool isShadow = false) {
|
||||
if (!text) return;
|
||||
|
||||
TR::Level *level = game->getLevel();
|
||||
MeshBuilder *mesh = game->getMesh();
|
||||
|
||||
if (shade && !isShadow && ((level->version & TR::VER_TR3)))
|
||||
textOut(pos + vec2(1, 1), text, align, width, shade, true);
|
||||
|
||||
MeshBuilder *mesh = game->getMesh();
|
||||
int seq = level->extra.glyphs;
|
||||
|
||||
int x = int(pos.x);
|
||||
@@ -291,14 +300,33 @@ namespace UI {
|
||||
flush();
|
||||
|
||||
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);
|
||||
|
||||
TR::Color32 tColor, bColor;
|
||||
if (isShadow) {
|
||||
tColor = bColor = TR::Color32(0, 0, 0, 255);
|
||||
} else {
|
||||
tColor = bColor = TR::Color32(255, 255, 255, 255);
|
||||
|
||||
if (shade && ((level->version & TR::VER_TR3))) {
|
||||
if (shade == SHADE_ORANGE) {
|
||||
tColor = TR::Color32(255, 190, 90, 255);
|
||||
bColor = TR::Color32(140, 50, 10, 255);
|
||||
}
|
||||
if (shade == SHADE_GRAY) {
|
||||
tColor = TR::Color32(255, 255, 255, 255);
|
||||
bColor = TR::Color32(128, 128, 128, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->addSprite(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, 0, x, y, 0, sprite, tColor, bColor, true);
|
||||
|
||||
x += char_width[frame] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void textOut(const vec2 &pos, StringID str, Align align = aLeft, float width = 0) {
|
||||
textOut(pos, STR[str], align, width);
|
||||
void textOut(const vec2 &pos, StringID str, Align align = aLeft, float width = 0, ShadeType shade = SHADE_ORANGE) {
|
||||
textOut(pos, STR[str], align, width, shade);
|
||||
}
|
||||
|
||||
void specOut(const vec2 &pos, char specChar) {
|
||||
@@ -311,7 +339,7 @@ namespace UI {
|
||||
flush();
|
||||
|
||||
TR::SpriteTexture &sprite = level->spriteTextures[level->spriteSequences[seq].sStart + specChar];
|
||||
mesh->addSprite(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, 0, int(pos.x), int(pos.y), 0, sprite, 255, true);
|
||||
mesh->addSprite(buffer.indices, buffer.vertices, buffer.iCount, buffer.vCount, 0, int(pos.x), int(pos.y), 0, sprite, TR::Color32(255, 255, 255, 255), TR::Color32(255, 255, 255, 255), true);
|
||||
}
|
||||
|
||||
#undef MAX_CHARS
|
||||
@@ -402,10 +430,10 @@ namespace UI {
|
||||
|
||||
void renderHelp() {
|
||||
if (showHelp)
|
||||
textOut(vec2(0, 64), STR_HELP_TEXT, aRight, width - 32);
|
||||
textOut(vec2(0, 64), STR_HELP_TEXT, aRight, width - 32, UI::SHADE_GRAY);
|
||||
else
|
||||
if (helpTipTime > 0.0f)
|
||||
textOut(vec2(0, 480 - 32), STR_HELP_PRESS, aCenter, width);
|
||||
textOut(vec2(0, 480 - 32), STR_HELP_PRESS, aCenter, width, UI::SHADE_ORANGE);
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user