mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-13 00:24:24 +02:00
#23 reduce number of VAOs
This commit is contained in:
@@ -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 *typ = NULL;
|
||||
switch (pass) {
|
||||
|
167
src/mesh.h
167
src/mesh.h
@@ -16,7 +16,7 @@ struct MeshRange {
|
||||
int vStart;
|
||||
int aIndex;
|
||||
|
||||
MeshRange() : aIndex(-1) {}
|
||||
MeshRange() : iStart(0), iCount(0), vStart(0), aIndex(-1) {}
|
||||
|
||||
void setup() const {
|
||||
glEnableVertexAttribArray(aCoord);
|
||||
@@ -224,14 +224,8 @@ struct MeshBuilder {
|
||||
vCount += mesh.rCount * 4 + mesh.tCount * 3;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ASSERT(vCount - range.sprites.vStart < 0xFFFF);
|
||||
}
|
||||
|
||||
// get models info
|
||||
@@ -251,39 +245,24 @@ struct MeshBuilder {
|
||||
// get size of mesh for sprite sequences
|
||||
sequences = new MeshRange[level.spriteSequencesCount];
|
||||
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;
|
||||
vCount += level.spriteSequences[i].sCount * 4;
|
||||
}
|
||||
|
||||
// shadow blob mesh (8 triangles, 8 vertices)
|
||||
shadowBlob.vStart = vCount;
|
||||
shadowBlob.iStart = iCount;
|
||||
shadowBlob.iCount = 8 * 3 * 3;
|
||||
iCount += shadowBlob.iCount;
|
||||
iCount += 8 * 3 * 3;
|
||||
vCount += 8 * 2 + 1;
|
||||
|
||||
// quad (post effect filter)
|
||||
quad.vStart = vCount;
|
||||
quad.iStart = iCount;
|
||||
quad.iCount = 2 * 3;
|
||||
iCount += quad.iCount;
|
||||
iCount += 2 * 3;
|
||||
vCount += 4;
|
||||
|
||||
// circle
|
||||
circle.vStart = vCount;
|
||||
circle.iStart = iCount;
|
||||
circle.iCount = CIRCLE_SEGS * 3;
|
||||
iCount += circle.iCount;
|
||||
iCount += CIRCLE_SEGS * 3;
|
||||
vCount += CIRCLE_SEGS + 1;
|
||||
|
||||
// detailed plane
|
||||
plane.vStart = vCount;
|
||||
plane.iStart = iCount;
|
||||
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
|
||||
iCount += plane.iCount;
|
||||
iCount += PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
|
||||
vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1);
|
||||
|
||||
// make meshes buffer (single vertex buffer object for all geometry & sprites on level)
|
||||
@@ -293,20 +272,20 @@ struct MeshBuilder {
|
||||
int aCount = 0;
|
||||
|
||||
// build rooms
|
||||
int vStartRoom = vCount;
|
||||
aCount++;
|
||||
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &room = level.rooms[i];
|
||||
TR::Room::Data &d = room.data;
|
||||
RoomRange &range = rooms[i];
|
||||
|
||||
int vStart;
|
||||
|
||||
for (int transp = 0; transp < 2; transp++) { // opaque, opacity
|
||||
range.geometry[transp].vStart = vCount;
|
||||
range.geometry[transp].vStart = vStartRoom;
|
||||
range.geometry[transp].iStart = iCount;
|
||||
|
||||
vStart = vCount;
|
||||
// rooms geometry
|
||||
buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStart);
|
||||
buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStartRoom);
|
||||
|
||||
// static meshes
|
||||
for (int j = 0; j < room.meshesCount; j++) {
|
||||
@@ -319,44 +298,44 @@ struct MeshBuilder {
|
||||
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);
|
||||
buildMesh(!transp, mesh, level, indices, vertices, iCount, vCount, vStartRoom, 0, x, y, z, d);
|
||||
}
|
||||
range.geometry[transp].iCount = iCount - range.geometry[transp].iStart;
|
||||
|
||||
if (range.geometry[transp].iCount)
|
||||
aCount++;
|
||||
}
|
||||
|
||||
// rooms sprites
|
||||
vStart = vCount;
|
||||
range.sprites.vStart = vStartRoom;
|
||||
range.sprites.iStart = iCount;
|
||||
for (int j = 0; j < d.sCount; j++) {
|
||||
TR::Room::Data::Sprite &f = d.sprites[j];
|
||||
TR::Room::Data::Vertex &v = d.vertices[f.vertex];
|
||||
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));
|
||||
}
|
||||
|
||||
if (d.sCount) aCount++;
|
||||
range.sprites.iCount = iCount - range.sprites.iStart;
|
||||
}
|
||||
|
||||
// build models geometry
|
||||
int vStartModel = vCount;
|
||||
aCount++;
|
||||
|
||||
for (int i = 0; i < level.modelsCount; i++) {
|
||||
TR::Model &model = level.models[i];
|
||||
ModelRange &range = models[i];
|
||||
int vStart = vCount;
|
||||
range.geometry.vStart = vStart;
|
||||
|
||||
range.geometry.vStart = vStartModel;
|
||||
range.geometry.iStart = iCount;
|
||||
range.opaque = true;
|
||||
|
||||
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];
|
||||
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)
|
||||
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);
|
||||
range.opaque &= opaque;
|
||||
}
|
||||
@@ -364,14 +343,27 @@ struct MeshBuilder {
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
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++) {
|
||||
Vertex &v0 = vertices[vCount + i * 2 + 0];
|
||||
v0.normal = { 0, -1, 0, 0 };
|
||||
@@ -414,10 +406,13 @@ struct MeshBuilder {
|
||||
}
|
||||
vCount += 8 * 2 + 1;
|
||||
iCount += shadowBlob.iCount;
|
||||
aCount++;
|
||||
|
||||
// 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 + 2].coord = { 1, -1, 1, 0 };
|
||||
vertices[vCount + 1].coord = { 1, 1, 1, 1 };
|
||||
@@ -431,12 +426,16 @@ struct MeshBuilder {
|
||||
v.param = { 0, 0, 0, 0 };
|
||||
}
|
||||
vCount += 4;
|
||||
aCount++;
|
||||
|
||||
// circle
|
||||
circle.vStart = vStartCommon;
|
||||
circle.iStart = iCount;
|
||||
circle.iCount = CIRCLE_SEGS * 3;
|
||||
|
||||
vec2 pos(32767.0f, 0.0f);
|
||||
vec2 cs(cosf(PI2 / CIRCLE_SEGS), sinf(PI2 / CIRCLE_SEGS));
|
||||
|
||||
int baseIdx = vCount - vStartCommon;
|
||||
for (int i = 0; i < CIRCLE_SEGS; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
pos.rotate(cs);
|
||||
@@ -446,22 +445,25 @@ struct MeshBuilder {
|
||||
v.texCoord = { 32688, 32688, 32767, 32767 };
|
||||
v.param = { 0, 0, 0, 0 };
|
||||
|
||||
indices[iCount++] = i;
|
||||
indices[iCount++] = (i + 1) % CIRCLE_SEGS;
|
||||
indices[iCount++] = CIRCLE_SEGS;
|
||||
indices[iCount++] = baseIdx + i;
|
||||
indices[iCount++] = baseIdx + (i + 1) % CIRCLE_SEGS;
|
||||
indices[iCount++] = baseIdx + CIRCLE_SEGS;
|
||||
}
|
||||
vertices[vCount + CIRCLE_SEGS] = vertices[vCount];
|
||||
vertices[vCount + CIRCLE_SEGS].coord = { 0, 0, 0, 0 };
|
||||
|
||||
vCount += CIRCLE_SEGS + 1;
|
||||
aCount++;
|
||||
|
||||
// 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 i = -PLANE_DETAIL; i <= PLANE_DETAIL; i++) {
|
||||
vertices[vCount++].coord = { i, j, 0, 0 };
|
||||
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 + 1] = idx + 1;
|
||||
indices[iCount + 2] = idx;
|
||||
@@ -471,7 +473,7 @@ struct MeshBuilder {
|
||||
iCount += 6;
|
||||
}
|
||||
}
|
||||
aCount++;
|
||||
|
||||
LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount);
|
||||
|
||||
// compile buffer and ranges
|
||||
@@ -483,24 +485,35 @@ struct MeshBuilder {
|
||||
PROFILE_LABEL(BUFFER, mesh->ID[1], "Geometry vertices");
|
||||
|
||||
// initialize Vertex Arrays
|
||||
MeshRange rangeRoom;
|
||||
rangeRoom.vStart = vStartRoom;
|
||||
mesh->initRange(rangeRoom);
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
RoomRange &r = rooms[i];
|
||||
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);
|
||||
r.geometry[0].aIndex = rangeRoom.aIndex;
|
||||
r.geometry[1].aIndex = rangeRoom.aIndex;
|
||||
r.sprites.aIndex = rangeRoom.aIndex;
|
||||
}
|
||||
|
||||
for (int i = 0; i < level.spriteSequencesCount; i++)
|
||||
mesh->initRange(sequences[i]);
|
||||
MeshRange rangeModel;
|
||||
rangeModel.vStart = vStartModel;
|
||||
mesh->initRange(rangeModel);
|
||||
for (int i = 0; i < level.modelsCount; i++)
|
||||
mesh->initRange(models[i].geometry);
|
||||
mesh->initRange(shadowBlob);
|
||||
mesh->initRange(quad);
|
||||
mesh->initRange(circle);
|
||||
mesh->initRange(plane);
|
||||
models[i].geometry.aIndex = rangeModel.aIndex;
|
||||
|
||||
MeshRange rangeSprite;
|
||||
rangeSprite.vStart = vStartSprite;
|
||||
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() {
|
||||
@@ -808,8 +821,8 @@ struct MeshBuilder {
|
||||
int count = triangle ? 3 : 4;
|
||||
for (int i = 0; i < count; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.texCoord.x = ((tx + tex->texCoord[i].x) << 5) + 16;
|
||||
v.texCoord.y = ((ty + tex->texCoord[i].y) << 5) + 16;
|
||||
v.texCoord.x = ((tx + tex->texCoord[i].x) * 32767) / 1024 + 16;
|
||||
v.texCoord.y = ((ty + tex->texCoord[i].y) * 32767) / 1024 + 16;
|
||||
v.texCoord.z = 32767;
|
||||
v.texCoord.w = 32767;
|
||||
v.param = { range, frame, 0, 0 };
|
||||
@@ -924,10 +937,10 @@ struct MeshBuilder {
|
||||
int tx = (sprite.tile % 4) * 256;
|
||||
int ty = (sprite.tile / 4) * 256;
|
||||
|
||||
int16 u0 = (((tx + sprite.texCoord[0].x) << 5));
|
||||
int16 v0 = (((ty + sprite.texCoord[0].y) << 5));
|
||||
int16 u1 = (((tx + sprite.texCoord[1].x) << 5));
|
||||
int16 v1 = (((ty + sprite.texCoord[1].y) << 5));
|
||||
int16 u0 = (((tx + sprite.texCoord[0].x) * 32767) / 1024) + 16;
|
||||
int16 v0 = (((ty + sprite.texCoord[0].y) * 32767) / 1024) + 16;
|
||||
int16 u1 = (((tx + sprite.texCoord[1].x) * 32767) / 1024) + 24;
|
||||
int16 v1 = (((ty + sprite.texCoord[1].y) * 32767) / 1024) + 24;
|
||||
|
||||
quad[0].texCoord = { u0, v0, sprite.l, sprite.t };
|
||||
quad[1].texCoord = { u1, v0, sprite.r, sprite.t };
|
||||
|
12
src/sound.h
12
src/sound.h
@@ -259,16 +259,16 @@ namespace Sound {
|
||||
|
||||
int s = (s1 * inc[pred] + s2 * dec[pred]) >> 6;
|
||||
s = clamp((value >> shift) + s, -32768, 32767);
|
||||
s2 = s1;
|
||||
s2 = s1;
|
||||
s1 = s;
|
||||
}
|
||||
|
||||
void resample(Frame *frames, short value) {
|
||||
predicate(value);
|
||||
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[2].L = frames[2].R = s2 + (s1 - s2) * 3 / 4; // 0.75
|
||||
frames[3].L = frames[3].R = s1; // 1.00
|
||||
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[2].L = frames[2].R = s2 + (s1 - s2) * 3 / 4; // 0.75
|
||||
frames[3].L = frames[3].R = s1; // 1.00
|
||||
}
|
||||
|
||||
int processBlock() {
|
||||
@@ -472,7 +472,7 @@ namespace Sound {
|
||||
decoder = new VAG(stream);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
isPlaying = decoder != NULL;
|
||||
ASSERT(isPlaying);
|
||||
}
|
||||
|
Reference in New Issue
Block a user