mirror of
https://github.com/XProger/OpenLara.git
synced 2025-02-24 07:22:58 +01:00
#23 split rooms geometry for alpha-test; warm up shader cache; shader optimizations
This commit is contained in:
parent
d446887003
commit
ff313dabd0
70
src/cache.h
70
src/cache.h
@ -34,51 +34,43 @@ struct ShaderCache {
|
||||
|
||||
ShaderCache(IGame *game) : game(game) {
|
||||
memset(shaders, 0, sizeof(shaders));
|
||||
/*
|
||||
char def[255], ext[255];
|
||||
|
||||
ext[0] = 0;
|
||||
if (Core::support.shadowSampler) {
|
||||
#ifdef MOBILE
|
||||
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
||||
#endif
|
||||
strcat(ext, "#define SHADOW_SAMPLER\n");
|
||||
} else
|
||||
if (Core::support.depthTexture)
|
||||
strcat(ext, "#define SHADOW_DEPTH\n");
|
||||
else
|
||||
strcat(ext, "#define SHADOW_COLOR\n");
|
||||
LOG("shader: cache warm up...\n");
|
||||
compile(Core::passShadow , Shader::ENTITY, false, false, false);
|
||||
|
||||
{
|
||||
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT" };
|
||||
const char *typeNames[] = { "SPRITE", "FLASH", "ROOM", "ENTITY", "MIRROR" };
|
||||
compile(Core::passAmbient, Shader::ROOM, false, false, false);
|
||||
compile(Core::passAmbient, Shader::ROOM, false, true, false);
|
||||
compile(Core::passAmbient, Shader::ROOM, false, false, true);
|
||||
compile(Core::passAmbient, Shader::ROOM, false, true, true);
|
||||
compile(Core::passAmbient, Shader::ROOM, true, false, false);
|
||||
compile(Core::passAmbient, Shader::SPRITE, false, true, false);
|
||||
compile(Core::passAmbient, Shader::SPRITE, false, true, true);
|
||||
|
||||
int animTexRangesCount = game->getMesh()->animTexRangesCount;
|
||||
int animTexOffsetsCount = game->getMesh()->animTexOffsetsCount;
|
||||
compile(Core::passCompose, Shader::ROOM, false, false, false);
|
||||
compile(Core::passCompose, Shader::ROOM, false, true, false);
|
||||
compile(Core::passCompose, Shader::ROOM, false, true, true);
|
||||
compile(Core::passCompose, Shader::ROOM, false, false, true);
|
||||
compile(Core::passCompose, Shader::ROOM, true, false, false);
|
||||
compile(Core::passCompose, Shader::ROOM, true, false, true);
|
||||
compile(Core::passCompose, Shader::ENTITY, false, false, false);
|
||||
compile(Core::passCompose, Shader::ENTITY, false, false, true);
|
||||
compile(Core::passCompose, Shader::ENTITY, true, false, false);
|
||||
compile(Core::passCompose, Shader::ENTITY, true, false, true);
|
||||
compile(Core::passCompose, Shader::SPRITE, false, true, false);
|
||||
compile(Core::passCompose, Shader::SPRITE, false, true, true);
|
||||
compile(Core::passCompose, Shader::SPRITE, true, true, false);
|
||||
compile(Core::passCompose, Shader::SPRITE, true, true, true);
|
||||
compile(Core::passCompose, Shader::FLASH, false, true, false);
|
||||
|
||||
for (int pass = Core::passCompose; pass <= Core::passAmbient; pass++)
|
||||
for (int caustics = 0; caustics < 2; caustics++)
|
||||
for (int type = Shader::SPRITE; type <= Shader::MIRROR; type++) {
|
||||
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typeNames[type], MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
|
||||
if (caustics)
|
||||
strcat(def, "#define CAUSTICS\n");
|
||||
shaders[pass][Shader::MAX * caustics + type] = new Shader(SHADER, def);
|
||||
}
|
||||
}
|
||||
compile(Core::passFilter , Shader::FILTER_DOWNSAMPLE, false, false, false);
|
||||
|
||||
{
|
||||
const char *typeNames[] = { "DROP", "STEP", "CAUSTICS", "MASK", "COMPOSE" };
|
||||
compile(Core::passWater , Shader::WATER_MASK, false, false, false);
|
||||
compile(Core::passWater , Shader::WATER_STEP, false, false, false);
|
||||
compile(Core::passWater , Shader::WATER_CAUSTICS, false, false, false);
|
||||
compile(Core::passWater , Shader::WATER_COMPOSE, false, false, false);
|
||||
compile(Core::passWater , Shader::WATER_DROP, false, false, false);
|
||||
|
||||
for (int type = Shader::WATER_DROP; type <= Shader::WATER_COMPOSE; type++) {
|
||||
sprintf(def, "%s#define WATER_%s\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, typeNames[type], WATER_FOG_DIST);
|
||||
#ifdef WATER_USE_GRID
|
||||
strcat(def, "#define WATER_USE_GRID %d\n");
|
||||
#endif
|
||||
shaders[Core::passWater][type] = new Shader(WATER, def);
|
||||
}
|
||||
}
|
||||
shaders[Core::passFilter][Shader::FILTER_DOWNSAMPLE] = new Shader(FILTER, "");
|
||||
*/
|
||||
LOG("shader: cache is ready\n");
|
||||
}
|
||||
|
||||
~ShaderCache() {
|
||||
|
@ -405,7 +405,7 @@ struct Lara : Character {
|
||||
|
||||
if (level->extra.braid > -1)
|
||||
braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f));
|
||||
reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
|
||||
#ifdef _DEBUG
|
||||
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
|
||||
|
||||
@ -2025,13 +2025,11 @@ struct Lara : Character {
|
||||
|
||||
if (wpnCurrent != Weapon::SHOTGUN && Core::pass != Core::passShadow && (arms[0].shotTimer < MUZZLE_FLASH_TIME || arms[1].shotTimer < MUZZLE_FLASH_TIME)) {
|
||||
mat4 matrix = getMatrix();
|
||||
game->setShader(Core::pass, Shader::FLASH, false);
|
||||
game->setShader(Core::pass, Shader::FLASH, false, true);
|
||||
Core::setBlending(bmAlpha);
|
||||
Core::setDepthWrite(false);
|
||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 10, true), vec3(-10, -50, 150), arms[0].shotTimer);
|
||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 13, true), vec3( 10, -50, 150), arms[1].shotTimer);
|
||||
Core::setBlending(bmNone);
|
||||
Core::setDepthWrite(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
30
src/level.h
30
src/level.h
@ -433,22 +433,33 @@ struct Level : IGame {
|
||||
room.flags.rendered = true;
|
||||
|
||||
if (Core::pass != Core::passShadow) {
|
||||
setRoomParams(roomIndex, intensityf(room.ambient), Shader::ROOM);
|
||||
Shader *sh = Core::active.shader;
|
||||
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||
|
||||
Basis qTemp = Core::basis;
|
||||
Core::basis.translate(offset);
|
||||
sh->setParam(uBasis, Core::basis);
|
||||
|
||||
// render room geometry
|
||||
mesh->renderRoomGeometry(roomIndex);
|
||||
MeshBuilder::RoomRange &range = mesh->rooms[roomIndex];
|
||||
|
||||
for (int transp = 0; transp < 2; transp++) {
|
||||
if (!range.geometry[transp].iCount)
|
||||
continue;
|
||||
|
||||
Core::setBlending(transp ? bmAlpha : bmNone);
|
||||
|
||||
setRoomParams(roomIndex, intensityf(room.ambient), Shader::ROOM, transp > 0);
|
||||
Shader *sh = Core::active.shader;
|
||||
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||
sh->setParam(uBasis, Core::basis);
|
||||
|
||||
// render room geometry
|
||||
mesh->renderRoomGeometry(roomIndex, transp > 0);
|
||||
}
|
||||
|
||||
// render room sprites
|
||||
if (mesh->hasRoomSprites(roomIndex)) {
|
||||
if (range.sprites.iCount) {
|
||||
Core::setBlending(bmAlpha);
|
||||
setRoomParams(roomIndex, 1.0, Shader::SPRITE, true);
|
||||
sh = Core::active.shader;
|
||||
Shader *sh = Core::active.shader;
|
||||
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||
sh->setParam(uBasis, Core::basis);
|
||||
@ -457,6 +468,7 @@ struct Level : IGame {
|
||||
|
||||
Core::basis = qTemp;
|
||||
}
|
||||
Core::setBlending(bmNone);
|
||||
}
|
||||
|
||||
#ifdef LEVEL_EDITOR
|
||||
|
182
src/mesh.h
182
src/mesh.h
@ -134,7 +134,7 @@ struct MeshBuilder {
|
||||
Mesh *mesh;
|
||||
// level
|
||||
struct RoomRange {
|
||||
MeshRange geometry;
|
||||
MeshRange geometry[2]; // opaque & transparent
|
||||
MeshRange sprites;
|
||||
MeshRange **meshes;
|
||||
} *rooms;
|
||||
@ -170,17 +170,13 @@ struct MeshBuilder {
|
||||
// allocate room geometry ranges
|
||||
rooms = new RoomRange[level.roomsCount];
|
||||
|
||||
int iCount = 0, vCount = 0, aCount = 0;
|
||||
int iCount = 0, vCount = 0;
|
||||
|
||||
// get size of mesh for rooms (geometry & sprites)
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &r = level.rooms[i];
|
||||
TR::Room::Data &d = r.data;
|
||||
|
||||
RoomRange &range = rooms[i];
|
||||
|
||||
range.geometry.vStart = vCount;
|
||||
range.geometry.iStart = iCount;
|
||||
iCount += d.rCount * 6 + d.tCount * 3;
|
||||
vCount += d.rCount * 4 + d.tCount * 3;
|
||||
|
||||
@ -196,20 +192,15 @@ struct MeshBuilder {
|
||||
vCount += mesh.rCount * 4 + mesh.tCount * 3;
|
||||
}
|
||||
|
||||
range.geometry.iCount = iCount - range.geometry.iStart;
|
||||
ASSERT(vCount - range.geometry.vStart < 0xFFFF);
|
||||
|
||||
RoomRange &range = rooms[i];
|
||||
range.sprites.vStart = vCount;
|
||||
range.sprites.iStart = iCount;
|
||||
iCount += d.sCount * 6;
|
||||
vCount += d.sCount * 4;
|
||||
range.sprites.iCount = iCount - range.sprites.iStart;
|
||||
if (range.sprites.iCount)
|
||||
aCount++;
|
||||
|
||||
ASSERT(vCount - range.sprites.vStart < 0xFFFF);
|
||||
}
|
||||
aCount += level.roomsCount;
|
||||
|
||||
// get models info
|
||||
models = new MeshRange[level.modelsCount];
|
||||
@ -219,7 +210,6 @@ struct MeshBuilder {
|
||||
int index = level.meshOffsets[model.mStart + j];
|
||||
if (!index && model.mStart + j > 0)
|
||||
continue;
|
||||
aCount++;
|
||||
TR::Mesh &mesh = level.meshes[index];
|
||||
iCount += mesh.rCount * 6 + mesh.tCount * 3;
|
||||
vCount += mesh.rCount * 4 + mesh.tCount * 3;
|
||||
@ -235,7 +225,6 @@ struct MeshBuilder {
|
||||
iCount += level.spriteSequences[i].sCount * 6;
|
||||
vCount += level.spriteSequences[i].sCount * 4;
|
||||
}
|
||||
aCount += level.spriteSequencesCount;
|
||||
|
||||
// get size of simple shadow spot mesh (8 triangles, 8 vertices)
|
||||
shadowBlob.vStart = vCount;
|
||||
@ -243,7 +232,6 @@ struct MeshBuilder {
|
||||
shadowBlob.iCount = 8 * 3;
|
||||
iCount += shadowBlob.iCount;
|
||||
vCount += 8;
|
||||
aCount++;
|
||||
|
||||
// bar (health, oxygen)
|
||||
bar.vStart = vCount;
|
||||
@ -251,7 +239,6 @@ struct MeshBuilder {
|
||||
bar.iCount = 2 * 3;
|
||||
iCount += bar.iCount;
|
||||
vCount += 4;
|
||||
aCount++;
|
||||
|
||||
// quad (post effect filter)
|
||||
quad.vStart = vCount;
|
||||
@ -259,7 +246,6 @@ struct MeshBuilder {
|
||||
quad.iCount = 2 * 3;
|
||||
iCount += quad.iCount;
|
||||
vCount += 4;
|
||||
aCount++;
|
||||
|
||||
// detailed plane
|
||||
plane.vStart = vCount;
|
||||
@ -267,72 +253,46 @@ struct MeshBuilder {
|
||||
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
|
||||
iCount += plane.iCount;
|
||||
vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1);
|
||||
aCount++;
|
||||
|
||||
// make meshes buffer (single vertex buffer object for all geometry & sprites on level)
|
||||
Index *indices = new Index[iCount];
|
||||
Vertex *vertices = new Vertex[vCount];
|
||||
iCount = vCount = 0;
|
||||
int aCount = 0;
|
||||
|
||||
// build rooms
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &r = level.rooms[i];
|
||||
TR::Room::Data &d = r.data;
|
||||
TR::Room &room = level.rooms[i];
|
||||
TR::Room::Data &d = room.data;
|
||||
RoomRange &range = rooms[i];
|
||||
|
||||
// rooms geometry
|
||||
int vStart = vCount;
|
||||
for (int j = 0; j < d.rCount; j++) {
|
||||
TR::Rectangle &f = d.rectangles[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.texture];
|
||||
int vStart;
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
for (int transp = 0; transp < 2; transp++) { // opaque, opacity
|
||||
range.geometry[transp].vStart = vCount;
|
||||
range.geometry[transp].iStart = iCount;
|
||||
|
||||
addQuad(indices, iCount, vCount, vStart, vertices, &t);
|
||||
vStart = vCount;
|
||||
// rooms geometry
|
||||
buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStart);
|
||||
|
||||
TR::Vertex n;
|
||||
CHECK_ROOM_NORMAL(n);
|
||||
// static meshes
|
||||
for (int j = 0; j < room.meshesCount; j++) {
|
||||
TR::Room::Mesh &m = room.meshes[j];
|
||||
TR::StaticMesh *s = level.getMeshByID(m.meshID);
|
||||
if (!level.meshOffsets[s->mesh]) continue;
|
||||
TR::Mesh &mesh = level.meshes[level.meshOffsets[s->mesh]];
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
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, intensity(v.lighting) };
|
||||
vCount++;
|
||||
int x = m.x - room.info.x;
|
||||
int y = m.y;
|
||||
int z = m.z - room.info.z;
|
||||
int d = m.rotation.value / 0x4000;
|
||||
buildMesh(!transp, mesh, level, indices, vertices, iCount, vCount, vStart, 0, x, y, z, d);
|
||||
}
|
||||
}
|
||||
range.geometry[transp].iCount = iCount - range.geometry[transp].iStart;
|
||||
|
||||
for (int j = 0; j < d.tCount; j++) {
|
||||
TR::Triangle &f = d.triangles[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.texture];
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
|
||||
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
|
||||
|
||||
TR::Vertex n;
|
||||
CHECK_ROOM_NORMAL(n);
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
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, intensity(v.lighting) };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// static meshes
|
||||
for (int j = 0; j < r.meshesCount; j++) {
|
||||
TR::Room::Mesh &m = r.meshes[j];
|
||||
TR::StaticMesh *s = level.getMeshByID(m.meshID);
|
||||
if (!level.meshOffsets[s->mesh]) continue;
|
||||
TR::Mesh &mesh = level.meshes[level.meshOffsets[s->mesh]];
|
||||
|
||||
int x = m.x - r.info.x;
|
||||
int y = m.y;
|
||||
int z = m.z - r.info.z;
|
||||
int d = m.rotation.value / 0x4000;
|
||||
buildMesh(mesh, level, indices, vertices, iCount, vCount, vStart, 0, x, y, z, d);
|
||||
if (range.geometry[transp].iCount)
|
||||
aCount++;
|
||||
}
|
||||
|
||||
// rooms sprites
|
||||
@ -344,6 +304,8 @@ struct MeshBuilder {
|
||||
|
||||
addSprite(indices, vertices, iCount, vCount, vStart, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity(v.lighting));
|
||||
}
|
||||
|
||||
if (d.sCount) aCount++;
|
||||
}
|
||||
|
||||
// build models geometry
|
||||
@ -357,9 +319,10 @@ struct MeshBuilder {
|
||||
for (int j = 0; j < model.mCount; j++) {
|
||||
int index = level.meshOffsets[model.mStart + j];
|
||||
if (!index && model.mStart + j > 0) continue;
|
||||
|
||||
aCount++;
|
||||
TR::Mesh &mesh = level.meshes[index];
|
||||
buildMesh(mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
|
||||
buildMesh( true, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
|
||||
buildMesh(false, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
range.iCount = iCount - range.iStart;
|
||||
@ -371,6 +334,7 @@ struct MeshBuilder {
|
||||
TR::SpriteTexture &sprite = level.spriteTextures[level.spriteSequences[i].sStart + j];
|
||||
addSprite(indices, vertices, iCount, vCount, sequences[i].vStart, 0, 0, 0, sprite, 255);
|
||||
}
|
||||
aCount += level.spriteSequencesCount;
|
||||
|
||||
// build shadow spot
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@ -391,6 +355,7 @@ struct MeshBuilder {
|
||||
}
|
||||
vCount += 8;
|
||||
iCount += shadowBlob.iCount;
|
||||
aCount++;
|
||||
|
||||
// white bar
|
||||
addQuad(indices, iCount, vCount, bar.vStart, vertices, &whiteTile);
|
||||
@ -406,6 +371,7 @@ struct MeshBuilder {
|
||||
v.texCoord = { 32688, 32688, 0, 0 };
|
||||
}
|
||||
vCount += 4;
|
||||
aCount++;
|
||||
|
||||
// quad
|
||||
addQuad(indices, iCount, vCount, quad.vStart, vertices, &whiteTile);
|
||||
@ -421,6 +387,7 @@ struct MeshBuilder {
|
||||
v.texCoord = { 32688, 32688, 0, 0 };
|
||||
}
|
||||
vCount += 4;
|
||||
aCount++;
|
||||
|
||||
// plane
|
||||
for (int16 j = -PLANE_DETAIL; j <= PLANE_DETAIL; j++)
|
||||
@ -437,6 +404,7 @@ struct MeshBuilder {
|
||||
iCount += 6;
|
||||
}
|
||||
}
|
||||
aCount++;
|
||||
LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount);
|
||||
|
||||
// compile buffer and ranges
|
||||
@ -450,7 +418,10 @@ struct MeshBuilder {
|
||||
// initialize Vertex Arrays
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
RoomRange &r = rooms[i];
|
||||
mesh->initRange(r.geometry);
|
||||
if (r.geometry[0].iCount)
|
||||
mesh->initRange(r.geometry[0]);
|
||||
if (r.geometry[1].iCount)
|
||||
mesh->initRange(r.geometry[1]);
|
||||
if (r.sprites.iCount)
|
||||
mesh->initRange(r.sprites);
|
||||
}
|
||||
@ -567,13 +538,67 @@ struct MeshBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
void buildMesh(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) {
|
||||
void buildRoom(bool opaque, 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;
|
||||
|
||||
for (int j = 0; j < d.rCount; j++) {
|
||||
TR::Rectangle &f = d.rectangles[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.texture];
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
|
||||
if (opaque != (t.attribute == 0))
|
||||
continue;
|
||||
|
||||
addQuad(indices, iCount, vCount, vStart, vertices, &t);
|
||||
|
||||
TR::Vertex n;
|
||||
CHECK_ROOM_NORMAL(n);
|
||||
|
||||
for (int k = 0; k < 4; k++) {
|
||||
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, intensity(v.lighting) };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < d.tCount; j++) {
|
||||
TR::Triangle &f = d.triangles[j];
|
||||
TR::ObjectTexture &t = level.objectTextures[f.texture];
|
||||
|
||||
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
|
||||
|
||||
if (opaque != (t.attribute == 0))
|
||||
continue;
|
||||
|
||||
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
|
||||
|
||||
TR::Vertex n;
|
||||
CHECK_ROOM_NORMAL(n);
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
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, intensity(v.lighting) };
|
||||
vCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void 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) {
|
||||
TR::Color24 COLOR_WHITE = { 255, 255, 255 };
|
||||
|
||||
for (int j = 0; j < mesh.rCount; j++) {
|
||||
TR::Rectangle &f = mesh.rectangles[j];
|
||||
bool textured = !(f.texture & 0x8000);
|
||||
TR::ObjectTexture &t = textured ? level.objectTextures[f.texture] : whiteTile;
|
||||
|
||||
if (opaque != (t.attribute == 0))
|
||||
continue;
|
||||
|
||||
TR::Color24 c = textured ? COLOR_WHITE : level.getColor(f.texture);
|
||||
|
||||
addQuad(indices, iCount, vCount, vStart, vertices, &t);
|
||||
@ -593,6 +618,10 @@ struct MeshBuilder {
|
||||
TR::Triangle &f = mesh.triangles[j];
|
||||
bool textured = !(f.texture & 0x8000);
|
||||
TR::ObjectTexture &t = textured ? level.objectTextures[f.texture] : whiteTile;
|
||||
|
||||
if (opaque != (t.attribute == 0))
|
||||
continue;
|
||||
|
||||
TR::Color24 c = textured ? COLOR_WHITE : level.getColor(f.texture);
|
||||
|
||||
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
|
||||
@ -752,18 +781,15 @@ struct MeshBuilder {
|
||||
mesh->bind();
|
||||
}
|
||||
|
||||
void renderRoomGeometry(int roomIndex) {
|
||||
mesh->render(rooms[roomIndex].geometry);
|
||||
void renderRoomGeometry(int roomIndex, bool transparent) {
|
||||
ASSERT(rooms[roomIndex].geometry[transparent].iCount > 0);
|
||||
mesh->render(rooms[roomIndex].geometry[transparent]);
|
||||
}
|
||||
|
||||
void renderRoomSprites(int roomIndex) {
|
||||
mesh->render(rooms[roomIndex].sprites);
|
||||
}
|
||||
|
||||
bool hasRoomSprites(int roomIndex) {
|
||||
return rooms[roomIndex].sprites.iCount > 0;
|
||||
}
|
||||
|
||||
void renderModel(int modelIndex) {
|
||||
mesh->render(models[modelIndex]);
|
||||
}
|
||||
|
@ -22,14 +22,20 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
uniform vec3 uViewPos;
|
||||
uniform int uCaustics;
|
||||
uniform vec4 uParam;
|
||||
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
|
||||
#ifdef CAUSTICS
|
||||
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef VERTEX
|
||||
uniform mat4 uViewProj;
|
||||
uniform vec4 uBasis[32 * 2];
|
||||
|
||||
#ifdef TYPE_ENTITY
|
||||
uniform vec4 uBasis[32 * 2];
|
||||
#else
|
||||
uniform vec4 uBasis[2];
|
||||
#endif
|
||||
|
||||
#ifndef PASS_AMBIENT
|
||||
uniform mat4 uViewInv;
|
||||
@ -63,9 +69,14 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
}
|
||||
|
||||
void main() {
|
||||
int index = int(aCoord.w) * 2;
|
||||
vec4 rBasisRot = uBasis[index];
|
||||
vec4 rBasisPos = uBasis[index + 1];
|
||||
#ifdef TYPE_ENTITY
|
||||
int index = int(aCoord.w) * 2;
|
||||
vec4 rBasisRot = uBasis[index];
|
||||
vec4 rBasisPos = uBasis[index + 1];
|
||||
#else
|
||||
vec4 rBasisRot = uBasis[0];
|
||||
vec4 rBasisPos = uBasis[1];
|
||||
#endif
|
||||
|
||||
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
|
||||
|
||||
@ -94,7 +105,11 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
|
||||
#endif
|
||||
|
||||
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
|
||||
#ifdef CAUSTICS
|
||||
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
|
||||
#else
|
||||
vTexCoord.zw = vec2(1.0);
|
||||
#endif
|
||||
|
||||
vViewVec = uViewPos - coord.xyz;
|
||||
vLightProj = uLightProj * coord;
|
||||
@ -252,27 +267,9 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
vec3 applyFog(vec3 color, vec3 fogColor, float factor) {
|
||||
float fog = clamp(1.0 / exp(factor), 0.0, 1.0);
|
||||
return mix(fogColor, color, fog);
|
||||
// return color.xyz * exp(factor);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
float getLuminance(vec3 color) {
|
||||
return dot(color.xyz, vec3(0.299, 0.587, 0.114));
|
||||
}
|
||||
|
||||
vec3 getNormal() {
|
||||
const vec2 size = vec2(2.0, 0.0);
|
||||
const vec3 off = vec3(-1, 0, 1) / 1024.0;
|
||||
|
||||
float s01 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.xy).xyz);
|
||||
float s21 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.zy).xyz);
|
||||
float s10 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.yx).xyz);
|
||||
float s12 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.yz).xyz);
|
||||
vec3 va = vec3(size.xy * 0.25, s21-s01);
|
||||
vec3 vb = vec3(size.yx * 0.25, s12-s10);
|
||||
return normalize(cross(va, vb));
|
||||
}
|
||||
*/
|
||||
void main() {
|
||||
#ifndef PASS_SHADOW
|
||||
#ifndef PASS_AMBIENT
|
||||
@ -286,7 +283,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
vec4 color = texture2D(sDiffuse, vTexCoord.xy);
|
||||
|
||||
#ifdef ALPHA_TEST
|
||||
if (color.w <= 0.6)
|
||||
if (color.w <= 0.1)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
@ -300,7 +297,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
color.xyz *= uColor.xyz;
|
||||
color.xyz *= vColor.xyz;
|
||||
|
||||
color *= color; // to "linear" space
|
||||
color.xyz *= color.xyz; // to "linear" space
|
||||
|
||||
#ifdef PASS_AMBIENT
|
||||
color.xyz *= vColor.w;
|
||||
@ -308,18 +305,11 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
// calc point lights
|
||||
#ifndef TYPE_FLASH
|
||||
vec3 normal = normalize(vNormal.xyz);
|
||||
|
||||
//vec3 n = getNormal();;
|
||||
//vec3 b = normalize(cross(n, vec3(.0, -1.0, 0.0)));
|
||||
//vec3 t = normalize(cross(b, n));
|
||||
//normal = normalize(normal.x * t + normal.y * b + normal.z * n);
|
||||
|
||||
vec3 viewVec = normalize(vViewVec);
|
||||
vec3 light = vec3(0.0);
|
||||
|
||||
// for (int i = 1; i < 3; i++) // additional lights
|
||||
light += calcLight(normal, uLightPos[1], uLightColor[1]);
|
||||
light += calcLight(normal, uLightPos[2], uLightColor[2]);
|
||||
light += calcLight(normal, uLightPos[1], uLightColor[1]);
|
||||
light += calcLight(normal, uLightPos[2], uLightColor[2]);
|
||||
|
||||
// apply lighting
|
||||
#ifdef TYPE_SPRITE
|
||||
@ -358,7 +348,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
#endif
|
||||
#endif
|
||||
|
||||
color = sqrt(color); // back to "gamma" space
|
||||
color.xyz = sqrt(color.xyz); // back to "gamma" space
|
||||
|
||||
#ifdef PASS_COMPOSE
|
||||
color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST);
|
||||
|
27
src/shader.h
27
src/shader.h
@ -14,6 +14,7 @@ const char *UniformName[uMAX] = { "uParam", "uTexParam", "uViewProj", "uViewI
|
||||
struct Shader {
|
||||
GLuint ID;
|
||||
GLint uID[uMAX];
|
||||
vec4 params[uMAX][4];
|
||||
|
||||
enum Type : GLint {
|
||||
NONE = 0,
|
||||
@ -126,6 +127,8 @@ struct Shader {
|
||||
|
||||
for (int ut = 0; ut < uMAX; ut++)
|
||||
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
|
||||
|
||||
memset(params, 0, sizeof(params));
|
||||
}
|
||||
|
||||
void bind() {
|
||||
@ -135,38 +138,50 @@ struct Shader {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const float &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform1fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec2 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform2fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec3 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform3fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform4fv(uID[uType], count, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const Basis &value, int count = 1) {
|
||||
if (uID[uType] != -1)
|
||||
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
|
||||
glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user