1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-16 01:54:38 +02:00

#23 reduce number of VAOs

This commit is contained in:
XProger
2017-08-15 05:43:42 +03:00
parent 2a9e6f2cb4
commit f23f481b29
3 changed files with 97 additions and 84 deletions

View File

@@ -118,7 +118,7 @@ struct ShaderCache {
} }
} }
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "VOLUME", "GUI" }; const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "GUI" };
const char *src = NULL; const char *src = NULL;
const char *typ = NULL; const char *typ = NULL;
switch (pass) { switch (pass) {

View File

@@ -16,7 +16,7 @@ struct MeshRange {
int vStart; int vStart;
int aIndex; int aIndex;
MeshRange() : aIndex(-1) {} MeshRange() : iStart(0), iCount(0), vStart(0), aIndex(-1) {}
void setup() const { void setup() const {
glEnableVertexAttribArray(aCoord); glEnableVertexAttribArray(aCoord);
@@ -224,14 +224,8 @@ struct MeshBuilder {
vCount += mesh.rCount * 4 + mesh.tCount * 3; vCount += mesh.rCount * 4 + mesh.tCount * 3;
} }
RoomRange &range = rooms[i];
range.sprites.vStart = vCount;
range.sprites.iStart = iCount;
iCount += d.sCount * 6; iCount += d.sCount * 6;
vCount += d.sCount * 4; vCount += d.sCount * 4;
range.sprites.iCount = iCount - range.sprites.iStart;
ASSERT(vCount - range.sprites.vStart < 0xFFFF);
} }
// get models info // get models info
@@ -251,39 +245,24 @@ struct MeshBuilder {
// get size of mesh for sprite sequences // get size of mesh for sprite sequences
sequences = new MeshRange[level.spriteSequencesCount]; sequences = new MeshRange[level.spriteSequencesCount];
for (int i = 0; i < level.spriteSequencesCount; i++) { for (int i = 0; i < level.spriteSequencesCount; i++) {
sequences[i].vStart = vCount;
sequences[i].iStart = iCount;
sequences[i].iCount = level.spriteSequences[i].sCount * 6;
iCount += level.spriteSequences[i].sCount * 6; iCount += level.spriteSequences[i].sCount * 6;
vCount += level.spriteSequences[i].sCount * 4; vCount += level.spriteSequences[i].sCount * 4;
} }
// shadow blob mesh (8 triangles, 8 vertices) // shadow blob mesh (8 triangles, 8 vertices)
shadowBlob.vStart = vCount; iCount += 8 * 3 * 3;
shadowBlob.iStart = iCount;
shadowBlob.iCount = 8 * 3 * 3;
iCount += shadowBlob.iCount;
vCount += 8 * 2 + 1; vCount += 8 * 2 + 1;
// quad (post effect filter) // quad (post effect filter)
quad.vStart = vCount; iCount += 2 * 3;
quad.iStart = iCount;
quad.iCount = 2 * 3;
iCount += quad.iCount;
vCount += 4; vCount += 4;
// circle // circle
circle.vStart = vCount; iCount += CIRCLE_SEGS * 3;
circle.iStart = iCount;
circle.iCount = CIRCLE_SEGS * 3;
iCount += circle.iCount;
vCount += CIRCLE_SEGS + 1; vCount += CIRCLE_SEGS + 1;
// detailed plane // detailed plane
plane.vStart = vCount; iCount += PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
plane.iStart = iCount;
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
iCount += plane.iCount;
vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1); vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1);
// make meshes buffer (single vertex buffer object for all geometry & sprites on level) // make meshes buffer (single vertex buffer object for all geometry & sprites on level)
@@ -293,20 +272,20 @@ struct MeshBuilder {
int aCount = 0; int aCount = 0;
// build rooms // build rooms
int vStartRoom = vCount;
aCount++;
for (int i = 0; i < level.roomsCount; i++) { for (int i = 0; i < level.roomsCount; i++) {
TR::Room &room = level.rooms[i]; TR::Room &room = level.rooms[i];
TR::Room::Data &d = room.data; TR::Room::Data &d = room.data;
RoomRange &range = rooms[i]; RoomRange &range = rooms[i];
int vStart;
for (int transp = 0; transp < 2; transp++) { // opaque, opacity for (int transp = 0; transp < 2; transp++) { // opaque, opacity
range.geometry[transp].vStart = vCount; range.geometry[transp].vStart = vStartRoom;
range.geometry[transp].iStart = iCount; range.geometry[transp].iStart = iCount;
vStart = vCount;
// rooms geometry // rooms geometry
buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStart); buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStartRoom);
// static meshes // static meshes
for (int j = 0; j < room.meshesCount; j++) { for (int j = 0; j < room.meshesCount; j++) {
@@ -319,44 +298,44 @@ struct MeshBuilder {
int y = m.y; int y = m.y;
int z = m.z - room.info.z; int z = m.z - room.info.z;
int d = m.rotation.value / 0x4000; int d = m.rotation.value / 0x4000;
buildMesh(!transp, mesh, level, indices, vertices, iCount, vCount, vStart, 0, x, y, z, d); buildMesh(!transp, mesh, level, indices, vertices, iCount, vCount, vStartRoom, 0, x, y, z, d);
} }
range.geometry[transp].iCount = iCount - range.geometry[transp].iStart; range.geometry[transp].iCount = iCount - range.geometry[transp].iStart;
if (range.geometry[transp].iCount)
aCount++;
} }
// rooms sprites // rooms sprites
vStart = vCount; range.sprites.vStart = vStartRoom;
range.sprites.iStart = iCount;
for (int j = 0; j < d.sCount; j++) { for (int j = 0; j < d.sCount; j++) {
TR::Room::Data::Sprite &f = d.sprites[j]; TR::Room::Data::Sprite &f = d.sprites[j];
TR::Room::Data::Vertex &v = d.vertices[f.vertex]; TR::Room::Data::Vertex &v = d.vertices[f.vertex];
TR::SpriteTexture &sprite = level.spriteTextures[f.texture]; TR::SpriteTexture &sprite = level.spriteTextures[f.texture];
addSprite(indices, vertices, iCount, vCount, vStart, 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, intensity(v.lighting));
} }
range.sprites.iCount = iCount - range.sprites.iStart;
if (d.sCount) aCount++;
} }
// build models geometry // build models geometry
int vStartModel = vCount;
aCount++;
for (int i = 0; i < level.modelsCount; i++) { for (int i = 0; i < level.modelsCount; i++) {
TR::Model &model = level.models[i]; TR::Model &model = level.models[i];
ModelRange &range = models[i]; ModelRange &range = models[i];
int vStart = vCount;
range.geometry.vStart = vStart; range.geometry.vStart = vStartModel;
range.geometry.iStart = iCount; range.geometry.iStart = iCount;
range.opaque = true; range.opaque = true;
for (int j = 0; j < model.mCount; j++) { for (int j = 0; j < model.mCount; j++) {
int index = level.meshOffsets[model.mStart + j]; int index = level.meshOffsets[model.mStart + j];
if (!index && model.mStart + j > 0) continue; if (!index && model.mStart + j > 0) continue;
aCount++;
TR::Mesh &mesh = level.meshes[index]; TR::Mesh &mesh = level.meshes[index];
bool opaque = buildMesh(true, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0); bool opaque = buildMesh(true, mesh, level, indices, vertices, iCount, vCount, vStartModel, j, 0, 0, 0, 0);
if (!opaque) if (!opaque)
buildMesh(false, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0); buildMesh(false, mesh, level, indices, vertices, iCount, vCount, vStartModel, j, 0, 0, 0, 0);
TR::Entity::fixOpaque(model.type, opaque); TR::Entity::fixOpaque(model.type, opaque);
range.opaque &= opaque; range.opaque &= opaque;
} }
@@ -364,14 +343,27 @@ struct MeshBuilder {
} }
// build sprite sequences // build sprite sequences
for (int i = 0; i < level.spriteSequencesCount; i++) int vStartSprite = vCount;
aCount++;
for (int i = 0; i < level.spriteSequencesCount; i++) {
MeshRange &range = sequences[i];
range.vStart = vStartSprite;
range.iStart = iCount;
for (int j = 0; j < level.spriteSequences[i].sCount; j++) { for (int j = 0; j < level.spriteSequences[i].sCount; j++) {
TR::SpriteTexture &sprite = level.spriteTextures[level.spriteSequences[i].sStart + j]; TR::SpriteTexture &sprite = level.spriteTextures[level.spriteSequences[i].sStart + j];
addSprite(indices, vertices, iCount, vCount, sequences[i].vStart, 0, 0, 0, sprite, 255); addSprite(indices, vertices, iCount, vCount, vStartSprite, 0, 0, 0, sprite, 255);
} }
aCount += level.spriteSequencesCount; range.iCount = iCount - range.iStart;
}
// build shadow blob // build common primitives
int vStartCommon = vCount;
aCount++;
shadowBlob.vStart = vStartCommon;
shadowBlob.iStart = iCount;
shadowBlob.iCount = 8 * 3 * 3;
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
Vertex &v0 = vertices[vCount + i * 2 + 0]; Vertex &v0 = vertices[vCount + i * 2 + 0];
v0.normal = { 0, -1, 0, 0 }; v0.normal = { 0, -1, 0, 0 };
@@ -414,10 +406,13 @@ struct MeshBuilder {
} }
vCount += 8 * 2 + 1; vCount += 8 * 2 + 1;
iCount += shadowBlob.iCount; iCount += shadowBlob.iCount;
aCount++;
// quad // quad
addQuad(indices, iCount, vCount, quad.vStart, vertices, &whiteTile); quad.vStart = vStartCommon;
quad.iStart = iCount;
quad.iCount = 2 * 3;
addQuad(indices, iCount, vCount, vStartCommon, vertices, &whiteTile);
vertices[vCount + 3].coord = { -1, -1, 0, 0 }; vertices[vCount + 3].coord = { -1, -1, 0, 0 };
vertices[vCount + 2].coord = { 1, -1, 1, 0 }; vertices[vCount + 2].coord = { 1, -1, 1, 0 };
vertices[vCount + 1].coord = { 1, 1, 1, 1 }; vertices[vCount + 1].coord = { 1, 1, 1, 1 };
@@ -431,12 +426,16 @@ struct MeshBuilder {
v.param = { 0, 0, 0, 0 }; v.param = { 0, 0, 0, 0 };
} }
vCount += 4; vCount += 4;
aCount++;
// circle // circle
circle.vStart = vStartCommon;
circle.iStart = iCount;
circle.iCount = CIRCLE_SEGS * 3;
vec2 pos(32767.0f, 0.0f); vec2 pos(32767.0f, 0.0f);
vec2 cs(cosf(PI2 / CIRCLE_SEGS), sinf(PI2 / CIRCLE_SEGS)); vec2 cs(cosf(PI2 / CIRCLE_SEGS), sinf(PI2 / CIRCLE_SEGS));
int baseIdx = vCount - vStartCommon;
for (int i = 0; i < CIRCLE_SEGS; i++) { for (int i = 0; i < CIRCLE_SEGS; i++) {
Vertex &v = vertices[vCount + i]; Vertex &v = vertices[vCount + i];
pos.rotate(cs); pos.rotate(cs);
@@ -446,22 +445,25 @@ struct MeshBuilder {
v.texCoord = { 32688, 32688, 32767, 32767 }; v.texCoord = { 32688, 32688, 32767, 32767 };
v.param = { 0, 0, 0, 0 }; v.param = { 0, 0, 0, 0 };
indices[iCount++] = i; indices[iCount++] = baseIdx + i;
indices[iCount++] = (i + 1) % CIRCLE_SEGS; indices[iCount++] = baseIdx + (i + 1) % CIRCLE_SEGS;
indices[iCount++] = CIRCLE_SEGS; indices[iCount++] = baseIdx + CIRCLE_SEGS;
} }
vertices[vCount + CIRCLE_SEGS] = vertices[vCount]; vertices[vCount + CIRCLE_SEGS] = vertices[vCount];
vertices[vCount + CIRCLE_SEGS].coord = { 0, 0, 0, 0 }; vertices[vCount + CIRCLE_SEGS].coord = { 0, 0, 0, 0 };
vCount += CIRCLE_SEGS + 1; vCount += CIRCLE_SEGS + 1;
aCount++;
// plane // plane
plane.vStart = vStartCommon;
plane.iStart = iCount;
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
baseIdx = vCount - vStartCommon;
for (int16 j = -PLANE_DETAIL; j <= PLANE_DETAIL; j++) for (int16 j = -PLANE_DETAIL; j <= PLANE_DETAIL; j++)
for (int16 i = -PLANE_DETAIL; i <= PLANE_DETAIL; i++) { for (int16 i = -PLANE_DETAIL; i <= PLANE_DETAIL; i++) {
vertices[vCount++].coord = { i, j, 0, 0 }; vertices[vCount++].coord = { i, j, 0, 0 };
if (j < PLANE_DETAIL && i < PLANE_DETAIL) { if (j < PLANE_DETAIL && i < PLANE_DETAIL) {
int idx = (j + PLANE_DETAIL) * (PLANE_DETAIL * 2 + 1) + i + PLANE_DETAIL; int idx = baseIdx + (j + PLANE_DETAIL) * (PLANE_DETAIL * 2 + 1) + i + PLANE_DETAIL;
indices[iCount + 0] = idx + PLANE_DETAIL * 2 + 1; indices[iCount + 0] = idx + PLANE_DETAIL * 2 + 1;
indices[iCount + 1] = idx + 1; indices[iCount + 1] = idx + 1;
indices[iCount + 2] = idx; indices[iCount + 2] = idx;
@@ -471,7 +473,7 @@ struct MeshBuilder {
iCount += 6; iCount += 6;
} }
} }
aCount++;
LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount); LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount);
// compile buffer and ranges // compile buffer and ranges
@@ -483,24 +485,35 @@ struct MeshBuilder {
PROFILE_LABEL(BUFFER, mesh->ID[1], "Geometry vertices"); PROFILE_LABEL(BUFFER, mesh->ID[1], "Geometry vertices");
// initialize Vertex Arrays // initialize Vertex Arrays
MeshRange rangeRoom;
rangeRoom.vStart = vStartRoom;
mesh->initRange(rangeRoom);
for (int i = 0; i < level.roomsCount; i++) { for (int i = 0; i < level.roomsCount; i++) {
RoomRange &r = rooms[i]; RoomRange &r = rooms[i];
if (r.geometry[0].iCount) r.geometry[0].aIndex = rangeRoom.aIndex;
mesh->initRange(r.geometry[0]); r.geometry[1].aIndex = rangeRoom.aIndex;
if (r.geometry[1].iCount) r.sprites.aIndex = rangeRoom.aIndex;
mesh->initRange(r.geometry[1]);
if (r.sprites.iCount)
mesh->initRange(r.sprites);
} }
for (int i = 0; i < level.spriteSequencesCount; i++) MeshRange rangeModel;
mesh->initRange(sequences[i]); rangeModel.vStart = vStartModel;
mesh->initRange(rangeModel);
for (int i = 0; i < level.modelsCount; i++) for (int i = 0; i < level.modelsCount; i++)
mesh->initRange(models[i].geometry); models[i].geometry.aIndex = rangeModel.aIndex;
mesh->initRange(shadowBlob);
mesh->initRange(quad); MeshRange rangeSprite;
mesh->initRange(circle); rangeSprite.vStart = vStartSprite;
mesh->initRange(plane); mesh->initRange(rangeSprite);
for (int i = 0; i < level.spriteSequencesCount; i++)
sequences[i].aIndex = rangeSprite.aIndex;
MeshRange rangeCommon;
rangeCommon.vStart = vStartCommon;
mesh->initRange(rangeCommon);
shadowBlob.aIndex = rangeCommon.aIndex;
quad.aIndex = rangeCommon.aIndex;
circle.aIndex = rangeCommon.aIndex;
plane.aIndex = rangeCommon.aIndex;
} }
~MeshBuilder() { ~MeshBuilder() {
@@ -808,8 +821,8 @@ struct MeshBuilder {
int count = triangle ? 3 : 4; int count = triangle ? 3 : 4;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
Vertex &v = vertices[vCount + i]; Vertex &v = vertices[vCount + i];
v.texCoord.x = ((tx + tex->texCoord[i].x) << 5) + 16; v.texCoord.x = ((tx + tex->texCoord[i].x) * 32767) / 1024 + 16;
v.texCoord.y = ((ty + tex->texCoord[i].y) << 5) + 16; v.texCoord.y = ((ty + tex->texCoord[i].y) * 32767) / 1024 + 16;
v.texCoord.z = 32767; v.texCoord.z = 32767;
v.texCoord.w = 32767; v.texCoord.w = 32767;
v.param = { range, frame, 0, 0 }; v.param = { range, frame, 0, 0 };
@@ -924,10 +937,10 @@ struct MeshBuilder {
int tx = (sprite.tile % 4) * 256; int tx = (sprite.tile % 4) * 256;
int ty = (sprite.tile / 4) * 256; int ty = (sprite.tile / 4) * 256;
int16 u0 = (((tx + sprite.texCoord[0].x) << 5)); int16 u0 = (((tx + sprite.texCoord[0].x) * 32767) / 1024) + 16;
int16 v0 = (((ty + sprite.texCoord[0].y) << 5)); int16 v0 = (((ty + sprite.texCoord[0].y) * 32767) / 1024) + 16;
int16 u1 = (((tx + sprite.texCoord[1].x) << 5)); int16 u1 = (((tx + sprite.texCoord[1].x) * 32767) / 1024) + 24;
int16 v1 = (((ty + sprite.texCoord[1].y) << 5)); int16 v1 = (((ty + sprite.texCoord[1].y) * 32767) / 1024) + 24;
quad[0].texCoord = { u0, v0, sprite.l, sprite.t }; quad[0].texCoord = { u0, v0, sprite.l, sprite.t };
quad[1].texCoord = { u1, v0, sprite.r, sprite.t }; quad[1].texCoord = { u1, v0, sprite.r, sprite.t };

View File

@@ -259,16 +259,16 @@ namespace Sound {
int s = (s1 * inc[pred] + s2 * dec[pred]) >> 6; int s = (s1 * inc[pred] + s2 * dec[pred]) >> 6;
s = clamp((value >> shift) + s, -32768, 32767); s = clamp((value >> shift) + s, -32768, 32767);
s2 = s1; s2 = s1;
s1 = s; s1 = s;
} }
void resample(Frame *frames, short value) { void resample(Frame *frames, short value) {
predicate(value); predicate(value);
frames[0].L = frames[0].R = s2 + (s1 - s2) / 4; // 0.25 frames[0].L = frames[0].R = s2 + (s1 - s2) / 4; // 0.25
frames[1].L = frames[1].R = s2 + (s1 - s2) / 2; // 0.50 frames[1].L = frames[1].R = s2 + (s1 - s2) / 2; // 0.50
frames[2].L = frames[2].R = s2 + (s1 - s2) * 3 / 4; // 0.75 frames[2].L = frames[2].R = s2 + (s1 - s2) * 3 / 4; // 0.75
frames[3].L = frames[3].R = s1; // 1.00 frames[3].L = frames[3].R = s1; // 1.00
} }
int processBlock() { int processBlock() {
@@ -472,7 +472,7 @@ namespace Sound {
decoder = new VAG(stream); decoder = new VAG(stream);
} }
#endif #endif
isPlaying = decoder != NULL; isPlaying = decoder != NULL;
ASSERT(isPlaying); ASSERT(isPlaying);
} }