1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-02-25 16:03:31 +01:00

#23 remove texture animation from shader

This commit is contained in:
XProger 2018-03-02 07:56:27 +03:00
parent 4c777de4b9
commit a8ac2b832f
10 changed files with 263 additions and 252 deletions

View File

@ -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
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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) {

View File

@ -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(&params[uType], value, size) != 0) {
memcpy(&params[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
};

View File

@ -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

View File

@ -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) {

View File

@ -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 );
}