mirror of
https://github.com/XProger/OpenLara.git
synced 2025-02-25 07:52:43 +01:00
#23 remove texture animation from shader
This commit is contained in:
parent
4c777de4b9
commit
a8ac2b832f
@ -155,8 +155,6 @@ struct ShaderCache {
|
||||
if (pass == Core::passCompose) {
|
||||
if (fx & FX_CLIP_PLANE)
|
||||
strcat(def, "#define CLIP_PLANE\n");
|
||||
if (type == Shader::ROOM)
|
||||
strcat(def, "#define OPT_ANIMTEX\n");
|
||||
if (Core::settings.detail.lighting > Core::Settings::LOW && (type == Shader::ENTITY || type == Shader::ROOM))
|
||||
strcat(def, "#define OPT_LIGHTING\n");
|
||||
if (Core::settings.detail.lighting > Core::Settings::MEDIUM && (type == Shader::ENTITY))
|
||||
@ -216,9 +214,6 @@ struct ShaderCache {
|
||||
shader->setParam(uLightProj, Core::mLightProj);
|
||||
shader->setParam(uViewPos, Core::viewPos);
|
||||
shader->setParam(uParam, Core::params);
|
||||
MeshBuilder *mesh = game->getMesh();
|
||||
shader->setParam(uAnimTexRanges, mesh->animTexRanges[0], min(mesh->animTexRangesCount, MAX_ANIM_TEX_RANGES));
|
||||
shader->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], min(mesh->animTexOffsetsCount, MAX_ANIM_TEX_OFFSETS));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -406,8 +406,8 @@ struct Camera : ICamera {
|
||||
continue;
|
||||
}
|
||||
|
||||
int sx = (int(p.x) - room.info.x) / 1024;
|
||||
int sz = (int(p.z) - room.info.z) / 1024;
|
||||
int sx = clamp((int(p.x) - room.info.x) / 1024, 0, room.xSectors - 1);
|
||||
int sz = clamp((int(p.z) - room.info.z) / 1024, 0, room.zSectors - 1);
|
||||
|
||||
int boxIndex = room.sectors[sz + sx * room.zSectors].boxIndex;
|
||||
|
||||
|
42
src/core.h
42
src/core.h
@ -505,35 +505,20 @@ enum RenderState {
|
||||
typedef uint16 Index;
|
||||
|
||||
struct Vertex {
|
||||
short4 coord; // xyz - position, w - joint index (for entities only)
|
||||
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; // for non-textured geometry
|
||||
ubyte4 light; // xyz - color, w - use premultiplied alpha
|
||||
short4 coord; // xyz - position, w - joint index (for entities only)
|
||||
short4 normal; // xyz - vertex normal, w - unused
|
||||
short4 texCoord; // xy - texture coordinates, zw - trapezoid warping
|
||||
ubyte4 color; // for non-textured geometry
|
||||
ubyte4 light; // xyz - color, w - use premultiplied alpha
|
||||
};
|
||||
|
||||
#ifdef FFP
|
||||
#ifdef _PSP
|
||||
struct VertexGPU {
|
||||
short2 texCoord;
|
||||
ubyte4 color;
|
||||
short3 normal;
|
||||
short3 coord;
|
||||
};
|
||||
#else
|
||||
/*
|
||||
struct VertexGPU {
|
||||
short2 texCoord;
|
||||
ubyte4 color;
|
||||
short3 normal;
|
||||
uint16 _alignN;
|
||||
short3 coord;
|
||||
uint16 _alignC;
|
||||
};
|
||||
*/
|
||||
typedef Vertex VertexGPU;
|
||||
#endif
|
||||
#ifdef _PSP
|
||||
struct VertexGPU {
|
||||
short2 texCoord;
|
||||
ubyte4 color;
|
||||
short3 normal;
|
||||
short3 coord;
|
||||
};
|
||||
#else
|
||||
typedef Vertex VertexGPU;
|
||||
#endif
|
||||
@ -976,6 +961,7 @@ namespace Core {
|
||||
sceGuDisable(GU_LIGHT3);
|
||||
sceGuAmbientColor(0xFFFFFFFF);
|
||||
sceGuColor(0xFFFFFFFF);
|
||||
sceGuClearColor(0xffff00ff);
|
||||
|
||||
freeEDRAM();
|
||||
#else
|
||||
@ -996,6 +982,8 @@ namespace Core {
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glScalef(1.0f / 32767.0f, 1.0f / 32767.0f, 1.0f / 32767.0f);
|
||||
|
||||
glClearColor(1, 0, 1, 1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
119
src/format.h
119
src/format.h
@ -1115,7 +1115,7 @@ namespace TR {
|
||||
struct ObjectTexture {
|
||||
uint16 clut;
|
||||
Tile tile; // tile or palette index
|
||||
uint16 attribute:15, repeat:1; // 0 - opaque, 1 - transparent, 2 - blend additive,
|
||||
uint16 attribute:15, animated:1; // 0 - opaque, 1 - transparent, 2 - blend additive, animated
|
||||
short2 texCoord[4];
|
||||
|
||||
short4 getMinMax() const {
|
||||
@ -1152,6 +1152,7 @@ namespace TR {
|
||||
} flags;
|
||||
uint8 colored; // !!! not existing in file
|
||||
uint8 vCount; // !!! not existing in file
|
||||
short3 normal; // !!! not existing in file
|
||||
uint16 vertices[4];
|
||||
|
||||
static int cmp(const Face &a, const Face &b) {
|
||||
@ -1189,7 +1190,7 @@ namespace TR {
|
||||
}
|
||||
};
|
||||
|
||||
#define FACE4_SIZE (sizeof(Face) - sizeof(uint8) - sizeof(uint8))
|
||||
#define FACE4_SIZE (sizeof(uint16) + sizeof(uint16) * 4) // flags + vertices[4]
|
||||
#define FACE3_SIZE (FACE4_SIZE - sizeof(uint16))
|
||||
|
||||
struct Tile4 {
|
||||
@ -2307,6 +2308,8 @@ namespace TR {
|
||||
|
||||
int32 animTexturesDataSize;
|
||||
uint16 *animTexturesData;
|
||||
int16 animTexturesCount;
|
||||
AnimTexture **animTextures;
|
||||
|
||||
int32 entitiesBaseCount;
|
||||
int32 entitiesCount;
|
||||
@ -2622,45 +2625,15 @@ namespace TR {
|
||||
}
|
||||
stream.read(zones[i].fly, boxesCount);
|
||||
}
|
||||
|
||||
// animated textures
|
||||
stream.read(animTexturesData, stream.read(animTexturesDataSize));
|
||||
readAnimTex(stream);
|
||||
|
||||
if (version & VER_TR3)
|
||||
readObjectTex(stream);
|
||||
|
||||
// entities (enemies, items, lara etc.)
|
||||
entitiesCount = stream.read(entitiesBaseCount) + MAX_RESERVED_ENTITIES;
|
||||
entities = new Entity[entitiesCount];
|
||||
for (int i = 0; i < entitiesBaseCount; i++) {
|
||||
Entity &e = entities[i];
|
||||
uint16 type;
|
||||
e.type = Entity::Type(stream.read(type));
|
||||
stream.read(e.room);
|
||||
stream.read(e.x);
|
||||
stream.read(e.y);
|
||||
stream.read(e.z);
|
||||
stream.read(e.rotation);
|
||||
stream.read(e.intensity);
|
||||
if (version & (VER_TR2 | VER_TR3))
|
||||
stream.read(e.intensity2);
|
||||
stream.read(e.flags.value);
|
||||
|
||||
e.type = Entity::remap(version, e.type);
|
||||
|
||||
e.controller = NULL;
|
||||
e.modelIndex = getModelIndex(e.type);
|
||||
}
|
||||
for (int i = entitiesBaseCount; i < entitiesCount; i++)
|
||||
entities[i].controller = NULL;
|
||||
|
||||
if (isCutsceneLevel()) {
|
||||
for (int i = 0; i < entitiesBaseCount; i++) {
|
||||
TR::Entity &e = entities[i];
|
||||
if ((((version & VER_TR1)) && e.isActor()) ||
|
||||
(((version & (VER_TR2 | VER_TR3))) && e.isLara())) {
|
||||
cutEntity = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
readEntities(stream);
|
||||
|
||||
if (version & VER_PC) {
|
||||
stream.seek(32 * 256);
|
||||
@ -2719,6 +2692,7 @@ namespace TR {
|
||||
}
|
||||
|
||||
initRoomMeshes();
|
||||
initAnimTex();
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
@ -2770,6 +2744,7 @@ namespace TR {
|
||||
delete[] zones[i].fly;
|
||||
}
|
||||
delete[] animTexturesData;
|
||||
delete[] animTextures;
|
||||
delete[] entities;
|
||||
delete[] palette;
|
||||
delete[] palette32;
|
||||
@ -3423,6 +3398,7 @@ namespace TR {
|
||||
t.clut = c;\
|
||||
t.tile = d.tile;\
|
||||
t.attribute = d.attribute;\
|
||||
t.animated = false;\
|
||||
t.texCoord[0] = short2( d.x0, d.y0 );\
|
||||
t.texCoord[1] = short2( d.x1, d.y1 );\
|
||||
t.texCoord[2] = short2( d.x2, d.y2 );\
|
||||
@ -3535,6 +3511,59 @@ namespace TR {
|
||||
}
|
||||
}
|
||||
|
||||
void readAnimTex(Stream &stream) {
|
||||
stream.read(animTexturesData, stream.read(animTexturesDataSize));
|
||||
uint16 *ptr = animTexturesData;
|
||||
animTexturesCount = *ptr++;
|
||||
if (!animTexturesCount) {
|
||||
animTextures = NULL;
|
||||
return;
|
||||
}
|
||||
animTextures = new AnimTexture*[animTexturesCount];
|
||||
for (int i = 0; i < animTexturesCount; i++) {
|
||||
animTextures[i] = (AnimTexture*)ptr;
|
||||
animTextures[i]->count++; // count + 1
|
||||
ptr += 1 + animTextures[i]->count; // skip count and texture indices
|
||||
}
|
||||
}
|
||||
|
||||
void readEntities(Stream &stream) {
|
||||
entitiesCount = stream.read(entitiesBaseCount) + MAX_RESERVED_ENTITIES;
|
||||
entities = new Entity[entitiesCount];
|
||||
for (int i = 0; i < entitiesBaseCount; i++) {
|
||||
Entity &e = entities[i];
|
||||
uint16 type;
|
||||
e.type = Entity::Type(stream.read(type));
|
||||
stream.read(e.room);
|
||||
stream.read(e.x);
|
||||
stream.read(e.y);
|
||||
stream.read(e.z);
|
||||
stream.read(e.rotation);
|
||||
stream.read(e.intensity);
|
||||
if (version & (VER_TR2 | VER_TR3))
|
||||
stream.read(e.intensity2);
|
||||
stream.read(e.flags.value);
|
||||
|
||||
e.type = Entity::remap(version, e.type);
|
||||
|
||||
e.controller = NULL;
|
||||
e.modelIndex = getModelIndex(e.type);
|
||||
}
|
||||
for (int i = entitiesBaseCount; i < entitiesCount; i++)
|
||||
entities[i].controller = NULL;
|
||||
|
||||
if (isCutsceneLevel()) {
|
||||
for (int i = 0; i < entitiesBaseCount; i++) {
|
||||
TR::Entity &e = entities[i];
|
||||
if ((((version & VER_TR1)) && e.isActor()) ||
|
||||
(((version & (VER_TR2 | VER_TR3))) && e.isLara())) {
|
||||
cutEntity = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initRoomMeshes() {
|
||||
for (int i = 0; i < roomsCount; i++) {
|
||||
Room &room = rooms[i];
|
||||
@ -3543,6 +3572,22 @@ namespace TR {
|
||||
}
|
||||
}
|
||||
|
||||
void initAnimTex() {
|
||||
for (int i = 0; i < animTexturesCount; i++)
|
||||
for (int j = 0; j < animTextures[i]->count; j++)
|
||||
objectTextures[animTextures[i]->textures[j]].animated = true;
|
||||
}
|
||||
|
||||
void shiftAnimTex() {
|
||||
for (int i = 0; i < animTexturesCount; i++) {
|
||||
AnimTexture *at = animTextures[i];
|
||||
ObjectTexture tmp = objectTextures[at->textures[0]];
|
||||
for (int j = 0; j < at->count - 1; j++)
|
||||
objectTextures[at->textures[j]] = objectTextures[at->textures[j + 1]];
|
||||
objectTextures[at->textures[at->count - 1]] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void initTiles() {
|
||||
tiles = new Tile32[tilesCount];
|
||||
// convert to RGBA
|
||||
|
13
src/level.h
13
src/level.h
@ -15,6 +15,8 @@
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
#define ANIM_TEX_TIMESTEP (10.0f / 30.0f)
|
||||
|
||||
extern ShaderCache *shaderCache;
|
||||
extern void loadAsync(Stream *stream, void *userData);
|
||||
|
||||
@ -52,6 +54,7 @@ struct Level : IGame {
|
||||
float effectTimer;
|
||||
int effectIdx;
|
||||
float cutsceneWaitTimer;
|
||||
float animTexTimer;
|
||||
|
||||
Texture *cube360;
|
||||
|
||||
@ -587,7 +590,7 @@ struct Level : IGame {
|
||||
}
|
||||
//==============================
|
||||
|
||||
Level(Stream &stream) : level(stream), inventory(this), isEnded(false), cutsceneWaitTimer(0.0f) {
|
||||
Level(Stream &stream) : level(stream), inventory(this), isEnded(false), cutsceneWaitTimer(0.0f), animTexTimer(0.0f) {
|
||||
#ifdef _PSP
|
||||
Core::freeEDRAM();
|
||||
#endif
|
||||
@ -1272,7 +1275,7 @@ struct Level : IGame {
|
||||
int roomIndex = roomsList[i];
|
||||
MeshBuilder::RoomRange &range = mesh->rooms[roomIndex];
|
||||
|
||||
if (!range.geometry[transp].count) {
|
||||
if (!range.geometry[transp].count && !range.dynamic[transp].count) {
|
||||
i += dir;
|
||||
continue;
|
||||
}
|
||||
@ -1437,6 +1440,12 @@ struct Level : IGame {
|
||||
sndChanged = NULL;
|
||||
} else {
|
||||
params->time += Core::deltaTime;
|
||||
animTexTimer += Core::deltaTime;
|
||||
|
||||
if (animTexTimer > ANIM_TEX_TIMESTEP) {
|
||||
level.shiftAnimTex();
|
||||
animTexTimer -= ANIM_TEX_TIMESTEP;
|
||||
}
|
||||
|
||||
updateEffect();
|
||||
|
||||
|
267
src/mesh.h
267
src/mesh.h
@ -39,7 +39,6 @@ struct MeshRange {
|
||||
glEnableVertexAttribArray(aCoord);
|
||||
glEnableVertexAttribArray(aNormal);
|
||||
glEnableVertexAttribArray(aTexCoord);
|
||||
glEnableVertexAttribArray(aParam);
|
||||
glEnableVertexAttribArray(aColor);
|
||||
glEnableVertexAttribArray(aLight);
|
||||
|
||||
@ -47,7 +46,6 @@ struct MeshRange {
|
||||
glVertexAttribPointer(aCoord, 4, GL_SHORT, false, sizeof(*v), &v->coord);
|
||||
glVertexAttribPointer(aNormal, 4, GL_SHORT, true, sizeof(*v), &v->normal);
|
||||
glVertexAttribPointer(aTexCoord, 4, GL_SHORT, true, sizeof(*v), &v->texCoord);
|
||||
glVertexAttribPointer(aParam, 4, GL_UNSIGNED_BYTE, false, sizeof(*v), &v->param);
|
||||
glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, true, sizeof(*v), &v->color);
|
||||
glVertexAttribPointer(aLight, 4, GL_UNSIGNED_BYTE, true, sizeof(*v), &v->light);
|
||||
}
|
||||
@ -63,7 +61,9 @@ struct MeshRange {
|
||||
#define PLANE_DETAIL 48
|
||||
#define CIRCLE_SEGS 16
|
||||
|
||||
#define DYN_MESH_QUADS 1024
|
||||
#define DYN_MESH_QUADS 1024
|
||||
#define DOUBLE_SIDED 2
|
||||
#define MAX_ROOM_DYN_FACES 256
|
||||
|
||||
struct Mesh {
|
||||
#ifdef _PSP
|
||||
@ -211,20 +211,36 @@ struct Mesh {
|
||||
vec3 o(mVertices[f.vertices[0]]);\
|
||||
vec3 a = o - mVertices[f.vertices[1]];\
|
||||
vec3 b = o - mVertices[f.vertices[2]];\
|
||||
o = b.cross(a).normal() * 16300.0f;\
|
||||
o = b.cross(a).normal() * 32767.0f;\
|
||||
n.x = (int)o.x;\
|
||||
n.y = (int)o.y;\
|
||||
n.z = (int)o.z;\
|
||||
}\
|
||||
|
||||
#define CHECK_ROOM_NORMAL(n) \
|
||||
#define CHECK_ROOM_NORMAL(f) \
|
||||
vec3 o(d.vertices[f.vertices[0]].vertex);\
|
||||
vec3 a = o - d.vertices[f.vertices[1]].vertex;\
|
||||
vec3 b = o - d.vertices[f.vertices[2]].vertex;\
|
||||
o = b.cross(a).normal() * 16300.0f;\
|
||||
n.x = (int)o.x;\
|
||||
n.y = (int)o.y;\
|
||||
n.z = (int)o.z;
|
||||
o = b.cross(a).normal() * 32767.0f;\
|
||||
f.normal.x = (int)o.x;\
|
||||
f.normal.y = (int)o.y;\
|
||||
f.normal.z = (int)o.z;
|
||||
|
||||
#define ADD_ROOM_FACE(indices, iCount, vCount, vStart, vertices, f, t) \
|
||||
addFace(indices, iCount, vCount, vStart, vertices, f, &t,\
|
||||
d.vertices[f.vertices[0]].vertex,\
|
||||
d.vertices[f.vertices[1]].vertex,\
|
||||
d.vertices[f.vertices[2]].vertex,\
|
||||
d.vertices[f.vertices[3]].vertex);\
|
||||
for (int k = 0; k < f.vCount; k++) {\
|
||||
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];\
|
||||
vertices[vCount].coord = short4( v.vertex.x, v.vertex.y, v.vertex.z, 0 );\
|
||||
vertices[vCount].normal = short4( f.normal.x, f.normal.y, f.normal.z, 0 );\
|
||||
vertices[vCount].color = ubyte4( 255, 255, 255, 255 );\
|
||||
vertices[vCount].light = ubyte4( v.color.r, v.color.g, v.color.b, 255 );\
|
||||
vCount++;\
|
||||
}
|
||||
|
||||
|
||||
float intensityf(uint16 lighting) {
|
||||
if (lighting > 0x1FFF) return 1.0f;
|
||||
@ -299,8 +315,14 @@ struct MeshBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dynamic {
|
||||
uint16 count;
|
||||
uint16 *faces;
|
||||
};
|
||||
|
||||
struct RoomRange {
|
||||
Geometry geometry[3]; // opaque, double-side alpha, additive
|
||||
Dynamic dynamic[3]; // lists of dynamic polygons (with animated textures) like lava, waterfalls etc.
|
||||
MeshRange sprites;
|
||||
int split;
|
||||
} *rooms;
|
||||
@ -320,12 +342,6 @@ struct MeshBuilder {
|
||||
MeshRange quad, circle;
|
||||
MeshRange plane;
|
||||
|
||||
vec2 *animTexRanges;
|
||||
vec2 *animTexOffsets;
|
||||
|
||||
int animTexRangesCount;
|
||||
int animTexOffsetsCount;
|
||||
|
||||
int transparent;
|
||||
|
||||
enum {
|
||||
@ -342,8 +358,6 @@ struct MeshBuilder {
|
||||
dynMesh->initRange(dynRange);
|
||||
#endif
|
||||
|
||||
initAnimTextures(level);
|
||||
|
||||
// allocate room geometry ranges
|
||||
rooms = new RoomRange[level.roomsCount];
|
||||
|
||||
@ -372,8 +386,8 @@ struct MeshBuilder {
|
||||
|
||||
int vStartCount = vCount;
|
||||
|
||||
iCount += 2 * (d.rCount * 6 + d.tCount * 3);
|
||||
vCount += d.rCount * 4 + d.tCount * 3;
|
||||
iCount += (d.rCount * 6 + d.tCount * 3) * DOUBLE_SIDED;
|
||||
vCount += (d.rCount * 4 + d.tCount * 3);
|
||||
|
||||
if (Core::settings.detail.water > Core::Settings::LOW)
|
||||
roomRemoveWaterSurfaces(r, iCount, vCount);
|
||||
@ -384,8 +398,8 @@ struct MeshBuilder {
|
||||
if (!level.meshOffsets[s->mesh]) continue;
|
||||
TR::Mesh &mesh = level.meshes[level.meshOffsets[s->mesh]];
|
||||
|
||||
iCount += 2 * (mesh.rCount * 6 + mesh.tCount * 3);
|
||||
vCount += mesh.rCount * 4 + mesh.tCount * 3;
|
||||
iCount += (mesh.rCount * 6 + mesh.tCount * 3) * DOUBLE_SIDED;
|
||||
vCount += (mesh.rCount * 4 + mesh.tCount * 3);
|
||||
}
|
||||
|
||||
#ifdef MERGE_SPRITES
|
||||
@ -409,8 +423,8 @@ struct MeshBuilder {
|
||||
if (!index && model.mStart + j > 0)
|
||||
continue;
|
||||
TR::Mesh &mesh = level.meshes[index];
|
||||
iCount += 2 * (mesh.rCount * 6 + mesh.tCount * 3);
|
||||
vCount += mesh.rCount * 4 + mesh.tCount * 3;
|
||||
iCount += (mesh.rCount * 6 + mesh.tCount * 3) * DOUBLE_SIDED;
|
||||
vCount += (mesh.rCount * 4 + mesh.tCount * 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,7 +443,7 @@ struct MeshBuilder {
|
||||
vCount += 8 * 2 + 1;
|
||||
|
||||
// quad (post effect filter)
|
||||
iCount += 2 * 3;
|
||||
iCount += 6;
|
||||
vCount += 4;
|
||||
|
||||
// circle
|
||||
@ -438,8 +452,8 @@ struct MeshBuilder {
|
||||
|
||||
// detailed plane
|
||||
#ifdef GENERATE_WATER_PLANE
|
||||
iCount += PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
|
||||
vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1);
|
||||
iCount += SQR(PLANE_DETAIL * 2) * 6;
|
||||
vCount += SQR(PLANE_DETAIL * 2 + 1);
|
||||
#endif
|
||||
|
||||
// make meshes buffer (single vertex buffer object for all geometry & sprites on level)
|
||||
@ -468,7 +482,7 @@ struct MeshBuilder {
|
||||
Geometry &geom = range.geometry[transp];
|
||||
|
||||
// rooms geometry
|
||||
buildRoom(geom, blendMask, room, level, indices, vertices, iCount, vCount, vStartRoom);
|
||||
buildRoom(geom, range.dynamic[transp], blendMask, room, level, indices, vertices, iCount, vCount, vStartRoom);
|
||||
|
||||
// static meshes
|
||||
for (int j = 0; j < room.meshesCount; j++) {
|
||||
@ -588,7 +602,7 @@ struct MeshBuilder {
|
||||
Vertex &v0 = vertices[vCount + i * 2 + 0];
|
||||
v0.normal = short4( 0, -1, 0, 32767 );
|
||||
v0.texCoord = short4( whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 );
|
||||
v0.param = v0.color = v0.light = ubyte4( 0, 0, 0, 0 );
|
||||
v0.color = v0.light = ubyte4( 0, 0, 0, 0 );
|
||||
|
||||
if (i == 8) {
|
||||
v0.coord = short4( 0, 0, 0, 0 );
|
||||
@ -607,7 +621,6 @@ struct MeshBuilder {
|
||||
Vertex &v1 = vertices[vCount + i * 2 + 1];
|
||||
v1 = v0;
|
||||
v1.coord = short4( c1, 0, s1, 0 );
|
||||
v0.param = ubyte4( 0, 0, 0, 0 );
|
||||
v1.color = v1.light = ubyte4( 255, 255, 255, 0 );
|
||||
|
||||
int idx = iCount + i * 3 * 3;
|
||||
@ -641,20 +654,13 @@ struct MeshBuilder {
|
||||
vertices[vCount + 3].texCoord = short4( 0, 0, 0, 0 );
|
||||
vertices[vCount + 2].texCoord = short4( 32767, 0, 0, 0 );
|
||||
vertices[vCount + 1].texCoord = short4( 32767, 32767, 0, 0 );
|
||||
vertices[vCount + 0].texCoord = short4( 0, 0, 0, 0 );
|
||||
vertices[vCount + 3].light =
|
||||
vertices[vCount + 2].light =
|
||||
vertices[vCount + 1].light =
|
||||
vertices[vCount + 0].light = vertices[vCount + 3].color = ubyte4(255, 255, 255, 255);
|
||||
|
||||
vertices[vCount + 0].texCoord = short4( 0, 32767, 0, 0 );
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.normal = short4( 0, 0, 0, 32767 );
|
||||
v.texCoord = short4( whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 );
|
||||
v.param = ubyte4( 0, 0, 0, 0 );
|
||||
v.color = ubyte4( 255, 255, 255, 255 );
|
||||
v.light = ubyte4( 255, 255, 255, 255 );
|
||||
v.normal = short4( 0, 0, 0, 0 );
|
||||
v.color = ubyte4( 255, 255, 255, 255 );
|
||||
v.light = ubyte4( 255, 255, 255, 255 );
|
||||
}
|
||||
vCount += 4;
|
||||
|
||||
@ -673,7 +679,6 @@ struct MeshBuilder {
|
||||
v.coord = short4( short(pos.x), short(pos.y), 0, 0 );
|
||||
v.normal = short4( 0, 0, 0, 32767 );
|
||||
v.texCoord = short4( whiteTile.texCoord[0].x, whiteTile.texCoord[0].y, 32767, 32767 );
|
||||
v.param = ubyte4( 0, 0, 0, 0 );
|
||||
v.color = ubyte4( 255, 255, 255, 255 );
|
||||
v.light = ubyte4( 255, 255, 255, 255 );
|
||||
|
||||
@ -769,8 +774,10 @@ struct MeshBuilder {
|
||||
}
|
||||
|
||||
~MeshBuilder() {
|
||||
delete[] animTexRanges;
|
||||
delete[] animTexOffsets;
|
||||
for (int i = 0; i < level->roomsCount; i++)
|
||||
for (int j = 0; j < COUNT(rooms[i].dynamic); j++)
|
||||
delete[] rooms[i].dynamic[j].faces;
|
||||
|
||||
delete[] rooms;
|
||||
delete[] models;
|
||||
delete[] sequences;
|
||||
@ -857,46 +864,57 @@ struct MeshBuilder {
|
||||
return 1 << texAttribute;
|
||||
}
|
||||
|
||||
void buildRoom(Geometry &geom, int blendMask, const TR::Room &room, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart) {
|
||||
void buildRoom(Geometry &geom, Dynamic &dyn, int blendMask, const TR::Room &room, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart) {
|
||||
const TR::Room::Data &d = room.data;
|
||||
|
||||
dyn.count = 0;
|
||||
dyn.faces = NULL;
|
||||
|
||||
for (int j = 0; j < d.fCount; j++) {
|
||||
TR::Face &f = d.faces[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.flags.texture];
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
|
||||
CHECK_ROOM_NORMAL(f);
|
||||
|
||||
if (!(blendMask & getBlendMask(t.attribute)))
|
||||
continue;
|
||||
|
||||
if (t.animated) {
|
||||
ASSERT(dyn.count < 0xFFFF);
|
||||
dyn.count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!geom.validForTile(t.tile.index, t.clut))
|
||||
geom.getNextRange(vStart, iCount, t.tile.index, t.clut);
|
||||
|
||||
addFace(indices, iCount, vCount, vStart, vertices, f, &t,
|
||||
d.vertices[f.vertices[0]].vertex,
|
||||
d.vertices[f.vertices[1]].vertex,
|
||||
d.vertices[f.vertices[2]].vertex,
|
||||
d.vertices[f.vertices[3]].vertex);
|
||||
ADD_ROOM_FACE(indices, iCount, vCount, vStart, vertices, f, t);
|
||||
}
|
||||
|
||||
TR::Vertex n;
|
||||
CHECK_ROOM_NORMAL(n);
|
||||
// if room has non-static polygons, fill the list of dynamic faces
|
||||
if (dyn.count) {
|
||||
|
||||
for (int k = 0; k < f.vCount; k++) {
|
||||
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];
|
||||
vertices[vCount].coord = short4( v.vertex.x, v.vertex.y, v.vertex.z, 0 );
|
||||
vertices[vCount].normal = short4( n.x, n.y, n.z, int16(t.attribute == 2 ? 0 : 32767) );
|
||||
vertices[vCount].color = ubyte4( 255, 255, 255, 255 );
|
||||
TR::Color32 c = v.color;
|
||||
/*
|
||||
#ifdef FFP
|
||||
if (room.flags.water) {
|
||||
vertices[vCount].light = ubyte4( int(c.r * 0.6f), int(c.g * 0.9), int(c.b * 0.9), 255 ); // apply underwater color
|
||||
} else
|
||||
vertices[vCount].light = ubyte4( c.r, c.g, c.b, 255 );
|
||||
#endif
|
||||
*/
|
||||
vertices[vCount].light = ubyte4( c.r, c.g, c.b, 255 );
|
||||
vCount++;
|
||||
if (dyn.count > MAX_ROOM_DYN_FACES) {
|
||||
LOG("! %d > MAX_ROOM_DYN_FACES\n", int(dyn.count));
|
||||
dyn.count = MAX_ROOM_DYN_FACES;
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
dyn.faces = new uint16[dyn.count];
|
||||
dyn.count = 0;
|
||||
for (int j = 0; j < d.fCount; j++) {
|
||||
TR::Face &f = d.faces[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.flags.texture];
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
|
||||
if (!(blendMask & getBlendMask(t.attribute)))
|
||||
continue;
|
||||
|
||||
if (t.animated)
|
||||
dyn.faces[dyn.count++] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -942,76 +960,11 @@ struct MeshBuilder {
|
||||
return isOpaque;
|
||||
}
|
||||
|
||||
vec2 getTexCoord(const TR::ObjectTexture &tex) {
|
||||
return vec2(tex.texCoord[0].x / 32767.0f, tex.texCoord[0].y / 32767.0f);
|
||||
}
|
||||
|
||||
void initAnimTextures(TR::Level &level) {
|
||||
ASSERT(level.animTexturesDataSize);
|
||||
|
||||
uint16 *ptr = &level.animTexturesData[0];
|
||||
animTexRangesCount = *ptr++ + 1;
|
||||
animTexRanges = new vec2[animTexRangesCount];
|
||||
animTexRanges[0] = vec2(0.0f, 1.0f);
|
||||
animTexOffsetsCount = 1;
|
||||
for (int i = 1; i < animTexRangesCount; i++) {
|
||||
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
|
||||
|
||||
int start = animTexOffsetsCount;
|
||||
animTexOffsetsCount += animTex->count + 1;
|
||||
animTexRanges[i] = vec2((float)start, (float)(animTexOffsetsCount - start));
|
||||
|
||||
ptr += (sizeof(animTex->count) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
|
||||
}
|
||||
animTexOffsets = new vec2[animTexOffsetsCount];
|
||||
animTexOffsets[0] = vec2(0.0f);
|
||||
animTexOffsetsCount = 1;
|
||||
|
||||
ptr = &level.animTexturesData[1];
|
||||
for (int i = 1; i < animTexRangesCount; i++) {
|
||||
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
|
||||
|
||||
vec2 first = getTexCoord(level.objectTextures[animTex->textures[0]]);
|
||||
animTexOffsets[animTexOffsetsCount++] = vec2(0.0f); // first - first for first frame %)
|
||||
|
||||
for (int j = 1; j <= animTex->count; j++)
|
||||
animTexOffsets[animTexOffsetsCount++] = getTexCoord(level.objectTextures[animTex->textures[j]]) - first;
|
||||
|
||||
ptr += (sizeof(animTex->count) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
|
||||
}
|
||||
}
|
||||
|
||||
TR::ObjectTexture* getAnimTexture(TR::ObjectTexture *tex, uint8 &range, uint8 &frame) {
|
||||
range = frame = 0;
|
||||
if (!level->animTexturesDataSize)
|
||||
return tex;
|
||||
|
||||
uint16 *ptr = &level->animTexturesData[1];
|
||||
for (int i = 1; i < animTexRangesCount; i++) {
|
||||
TR::AnimTexture *animTex = (TR::AnimTexture*)ptr;
|
||||
|
||||
for (int j = 0; j <= animTex->count; j++)
|
||||
if (tex == &level->objectTextures[animTex->textures[j]]) {
|
||||
range = i;
|
||||
frame = j;
|
||||
return &level->objectTextures[animTex->textures[0]];
|
||||
}
|
||||
|
||||
ptr += (sizeof(animTex->count) + sizeof(animTex->textures[0]) * (animTex->count + 1)) / sizeof(uint16);
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
void addTexCoord(Vertex *vertices, int vCount, TR::ObjectTexture *tex, bool triangle) {
|
||||
uint8 range, frame;
|
||||
tex = getAnimTexture(tex, range, frame);
|
||||
|
||||
int count = triangle ? 3 : 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.texCoord = short4( tex->texCoord[i].x, tex->texCoord[i].y, 32767, 32767 );
|
||||
v.param = ubyte4( range, frame, 0, 0 );
|
||||
}
|
||||
|
||||
if (((level->version & TR::VER_PSX)) && !triangle) // TODO: swap vertices instead of rectangle indices and vertices.texCoords (WRONG lighting in TR2!)
|
||||
@ -1157,7 +1110,6 @@ struct MeshBuilder {
|
||||
quad[2].color = quad[3].color = ubyte4( 255, 255, 255, 255 );
|
||||
quad[0].light = quad[1].light = ubyte4( tColor.r, tColor.g, tColor.b, tColor.a );
|
||||
quad[2].light = quad[3].light = ubyte4( bColor.r, bColor.g, bColor.b, bColor.a );
|
||||
quad[0].param = quad[1].param = quad[2].param = quad[3].param = ubyte4( 0, 0, 0, 0 );
|
||||
|
||||
quad[0].texCoord = short4( sprite.texCoord[0].x, sprite.texCoord[0].y, sprite.l, -sprite.t );
|
||||
quad[1].texCoord = short4( sprite.texCoord[1].x, sprite.texCoord[0].y, sprite.r, -sprite.t );
|
||||
@ -1191,7 +1143,6 @@ struct MeshBuilder {
|
||||
short2 uv = tile.texCoord[i];
|
||||
|
||||
v.texCoord = short4( uv.x, uv.y, 32767, 32767 );
|
||||
v.param = ubyte4( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
vCount += 4;
|
||||
@ -1251,6 +1202,9 @@ struct MeshBuilder {
|
||||
}
|
||||
|
||||
void renderBuffer(Index *indices, int iCount, Vertex *vertices, int vCount) {
|
||||
if (!iCount) return;
|
||||
ASSERT(vCount > 0);
|
||||
|
||||
#ifdef _PSP
|
||||
MeshRange dynRange;
|
||||
Mesh cmdBufMesh(iCount, vCount);
|
||||
@ -1275,6 +1229,51 @@ struct MeshBuilder {
|
||||
|
||||
mesh->render(range);
|
||||
}
|
||||
|
||||
Dynamic &dyn = rooms[roomIndex].dynamic[transparent];
|
||||
if (dyn.count) {
|
||||
#ifdef SPLIT_BY_TILE
|
||||
uint16 tile = 0xFFFF, clut = 0xFFFF;
|
||||
#endif
|
||||
int iCount = 0, vCount = 0, vStart = 0;
|
||||
Index indices[MAX_ROOM_DYN_FACES * 6 * DOUBLE_SIDED];
|
||||
Vertex vertices[MAX_ROOM_DYN_FACES * 4];
|
||||
|
||||
const TR::Room::Data &d = level->rooms[roomIndex].data;
|
||||
for (int i = 0; i < dyn.count; i++) {
|
||||
TR::Face &f = d.faces[dyn.faces[i]];
|
||||
TR::ObjectTexture &t = level->objectTextures[f.flags.texture];
|
||||
|
||||
#ifdef SPLIT_BY_TILE
|
||||
if (iCount) {
|
||||
if (tile != t.tile.index
|
||||
#ifdef SPLIT_BY_CLUT
|
||||
|| clut != t.clut
|
||||
#endif
|
||||
) {
|
||||
atlas->bind(tile, clut);
|
||||
renderBuffer(indices, iCount, vertices, vCount);
|
||||
tile = t.tile.index;
|
||||
clut = t.clut;
|
||||
iCount = 0;
|
||||
vCount = 0;
|
||||
}
|
||||
} else {
|
||||
tile = t.tile.index;
|
||||
clut = t.clut;
|
||||
}
|
||||
#endif
|
||||
|
||||
ADD_ROOM_FACE(indices, iCount, vCount, vStart, vertices, f, t);
|
||||
}
|
||||
|
||||
if (iCount) {
|
||||
#ifdef SPLIT_BY_TILE
|
||||
atlas->bind(tile, clut);
|
||||
#endif
|
||||
renderBuffer(indices, iCount, vertices, vCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderRoomSprites(int roomIndex) {
|
||||
|
36
src/shader.h
36
src/shader.h
@ -7,7 +7,6 @@
|
||||
E( aCoord ) \
|
||||
E( aNormal ) \
|
||||
E( aTexCoord ) \
|
||||
E( aParam ) \
|
||||
E( aColor ) \
|
||||
E( aLight )
|
||||
|
||||
@ -84,7 +83,7 @@ struct Shader {
|
||||
}
|
||||
|
||||
ID = glCreateProgram();
|
||||
|
||||
|
||||
if (!(Core::support.shaderBinary && linkBinary(fileName))) // try to load cached shader
|
||||
if (linkSource(source, defines) && Core::support.shaderBinary) { // compile shader from source and dump it into cache
|
||||
#ifndef __EMSCRIPTEN__
|
||||
@ -202,51 +201,32 @@ struct Shader {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool checkParam(UniformType uType, const void *value, int size) {
|
||||
return true;
|
||||
/*
|
||||
if (size > sizeof(vec4) * 4) return true;
|
||||
if (memcmp(¶ms[uType], value, size) != 0) {
|
||||
memcpy(¶ms[uType], value, size);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const int &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
glUniform1iv(uID[uType], count, (GLint*)&value);
|
||||
if (uID[uType] != -1) glUniform1iv(uID[uType], count, (GLint*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const float &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform1fv(uID[uType], count, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniform1fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec2 &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform2fv(uID[uType], count, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniform2fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec3 &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform3fv(uID[uType], count, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniform3fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform4fv(uID[uType], count, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniform4fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const Basis &value, int count = 1) {
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
|
||||
if (uID[uType] != -1) glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
@ -63,15 +63,9 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPT_ANIMTEX
|
||||
uniform vec2 uAnimTexRanges[MAX_RANGES];
|
||||
uniform vec2 uAnimTexOffsets[MAX_OFFSETS];
|
||||
#endif
|
||||
|
||||
attribute vec4 aCoord;
|
||||
attribute vec4 aTexCoord;
|
||||
attribute vec4 aParam;
|
||||
attribute vec4 aNormal;
|
||||
|
||||
#ifndef PASS_SHADOW
|
||||
@ -230,13 +224,6 @@ uniform vec4 uMaterial; // x - diffuse, y - ambient, z - specular, w - alpha
|
||||
void _uv(vec3 coord) {
|
||||
vTexCoord = aTexCoord;
|
||||
#if defined(PASS_COMPOSE) && !defined(TYPE_SPRITE)
|
||||
#ifdef OPT_ANIMTEX
|
||||
// animated texture coordinates
|
||||
vec2 range = uAnimTexRanges[int(aParam.x)]; // x - start index, y - count
|
||||
float frame = fract((aParam.y + uParam.x * 4.0 - range.x) / range.y) * range.y;
|
||||
vec2 offset = uAnimTexOffsets[int(range.x + frame)]; // texCoord offset from first frame
|
||||
vTexCoord.xy += offset;
|
||||
#endif
|
||||
vTexCoord.xy *= vTexCoord.zw;
|
||||
#endif
|
||||
|
||||
|
@ -126,7 +126,8 @@ struct Texture {
|
||||
this->format = format;
|
||||
|
||||
#ifdef _PSP
|
||||
memory = NULL;//new uint8[width * height * 2];
|
||||
memory = new uint8[width * height * 4];
|
||||
memcpy(memory, data, width * height * 4);
|
||||
#else
|
||||
glGenTextures(1, &ID);
|
||||
bind(0);
|
||||
@ -262,11 +263,19 @@ struct Texture {
|
||||
|
||||
void bind(int sampler) {
|
||||
#ifdef _PSP
|
||||
if (this && !sampler && memory)
|
||||
if (this && !sampler && memory) {
|
||||
int swizzle = GU_FALSE;
|
||||
#ifdef TEX_SWIZZLE
|
||||
swizzle = GU_TRUE;
|
||||
#endif
|
||||
|
||||
sceGuTexMode(GU_PSM_8888, 0, 0, GU_FALSE);
|
||||
sceGuTexImage(0, width, height, width, memory);
|
||||
sceGuTexMode(GU_PSM_T4, 0, 0, swizzle);
|
||||
}
|
||||
#else
|
||||
#ifdef SPLIT_BY_TILE
|
||||
if (sampler || !ID) return;
|
||||
if (!this || sampler || !ID) return;
|
||||
#endif
|
||||
|
||||
if (Core::active.textures[sampler] != this) {
|
||||
|
@ -1031,7 +1031,6 @@ struct Lightning : Controller {
|
||||
v.coord = toCoord(coord, joint);
|
||||
v.normal = short4( 0, -1, 0, 0 );
|
||||
v.texCoord = short4( barTile[0].texCoord[idx].x, barTile[0].texCoord[idx].y, 32767, 32767 );
|
||||
v.param = ubyte4( 0, 0, 0, 0 );
|
||||
v.color = ubyte4( 255, 255, 255, 255 );
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user