mirror of
https://github.com/UberGames/lilium-voyager.git
synced 2024-11-10 14:41:42 +00:00
OpenGL2: Use an idea from ETXreal and separate world VBO into separate VBOs by shader.
This commit is contained in:
parent
08fcecc829
commit
01efe4a538
2 changed files with 278 additions and 236 deletions
|
@ -1831,10 +1831,10 @@ static void CopyVert(const srfVert_t * in, srfVert_t * out)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
R_CreateWorldVBO
|
R_CreateWorldVBOs
|
||||||
===============
|
===============
|
||||||
*/
|
*/
|
||||||
static void R_CreateWorldVBO(void)
|
static void R_CreateWorldVBOs(void)
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
|
|
||||||
|
@ -1844,19 +1844,53 @@ static void R_CreateWorldVBO(void)
|
||||||
int numTriangles;
|
int numTriangles;
|
||||||
srfTriangle_t *triangles;
|
srfTriangle_t *triangles;
|
||||||
|
|
||||||
int numSurfaces;
|
int numSortedSurfaces, numSurfaces;
|
||||||
msurface_t *surface;
|
msurface_t *surface, **firstSurf, **lastSurf, **currSurf;
|
||||||
msurface_t **surfacesSorted;
|
msurface_t **surfacesSorted;
|
||||||
|
|
||||||
|
VBO_t *vbo;
|
||||||
|
IBO_t *ibo;
|
||||||
|
|
||||||
int startTime, endTime;
|
int startTime, endTime;
|
||||||
|
|
||||||
startTime = ri.Milliseconds();
|
startTime = ri.Milliseconds();
|
||||||
|
|
||||||
|
// count surfaces
|
||||||
|
numSortedSurfaces = 0;
|
||||||
|
for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
|
||||||
|
{
|
||||||
|
if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
|
||||||
|
{
|
||||||
|
numSortedSurfaces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// presort surfaces
|
||||||
|
surfacesSorted = ri.Malloc(numSortedSurfaces * sizeof(*surfacesSorted));
|
||||||
|
|
||||||
|
j = 0;
|
||||||
|
for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++)
|
||||||
|
{
|
||||||
|
if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
|
||||||
|
{
|
||||||
|
surfacesSorted[j++] = surface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
for(firstSurf = lastSurf = surfacesSorted; firstSurf < &surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf)
|
||||||
|
{
|
||||||
|
while(lastSurf < &surfacesSorted[numSortedSurfaces] && (*lastSurf)->shader->sortedIndex == (*firstSurf)->shader->sortedIndex)
|
||||||
|
lastSurf++;
|
||||||
|
|
||||||
numVerts = 0;
|
numVerts = 0;
|
||||||
numTriangles = 0;
|
numTriangles = 0;
|
||||||
numSurfaces = 0;
|
numSurfaces = 0;
|
||||||
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces /* s_worldData.numWorldSurfaces */; k++, surface++)
|
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
|
||||||
{
|
{
|
||||||
|
surface = *currSurf;
|
||||||
if(*surface->data == SF_FACE)
|
if(*surface->data == SF_FACE)
|
||||||
{
|
{
|
||||||
srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data;
|
srfSurfaceFace_t *face = (srfSurfaceFace_t *) surface->data;
|
||||||
|
@ -1896,35 +1930,20 @@ static void R_CreateWorldVBO(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!numVerts || !numTriangles)
|
if(!numVerts || !numTriangles)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, "...calculating world VBO ( %i verts %i tris )\n", numVerts, numTriangles);
|
ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numTriangles);
|
||||||
|
|
||||||
// create arrays
|
// create arrays
|
||||||
|
|
||||||
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
|
verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t));
|
||||||
|
|
||||||
triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
|
triangles = ri.Hunk_AllocateTempMemory(numTriangles * sizeof(srfTriangle_t));
|
||||||
|
|
||||||
// presort surfaces
|
|
||||||
surfacesSorted = ri.Malloc(numSurfaces * sizeof(*surfacesSorted));
|
|
||||||
|
|
||||||
j = 0;
|
|
||||||
for(k = 0, surface = &s_worldData.surfaces[0]; k < s_worldData.numsurfaces; k++, surface++)
|
|
||||||
{
|
|
||||||
if(*surface->data == SF_FACE || *surface->data == SF_GRID || *surface->data == SF_TRIANGLES)
|
|
||||||
{
|
|
||||||
surfacesSorted[j++] = surface;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(surfacesSorted, numSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare);
|
|
||||||
|
|
||||||
// set up triangle indices
|
// set up triangle indices
|
||||||
numVerts = 0;
|
numVerts = 0;
|
||||||
numTriangles = 0;
|
numTriangles = 0;
|
||||||
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
|
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
|
||||||
{
|
{
|
||||||
|
surface = *currSurf;
|
||||||
if(*surface->data == SF_FACE)
|
if(*surface->data == SF_FACE)
|
||||||
{
|
{
|
||||||
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
||||||
|
@ -2016,8 +2035,9 @@ static void R_CreateWorldVBO(void)
|
||||||
|
|
||||||
// build vertices
|
// build vertices
|
||||||
numVerts = 0;
|
numVerts = 0;
|
||||||
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
|
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
|
||||||
{
|
{
|
||||||
|
surface = *currSurf;
|
||||||
if(*surface->data == SF_FACE)
|
if(*surface->data == SF_FACE)
|
||||||
{
|
{
|
||||||
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
||||||
|
@ -2069,31 +2089,29 @@ static void R_CreateWorldVBO(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_VERT_TANGENT_SPACE
|
#ifdef USE_VERT_TANGENT_SPACE
|
||||||
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
|
vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
|
||||||
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
|
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | ATTR_BITANGENT |
|
||||||
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
|
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
|
||||||
#else
|
#else
|
||||||
s_worldData.vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", 0), numVerts, verts,
|
vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts,
|
||||||
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
|
ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD |
|
||||||
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
|
ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s_worldData.ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", 0), numTriangles, triangles, VBO_USAGE_STATIC);
|
ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", k), numTriangles, triangles, VBO_USAGE_STATIC);
|
||||||
|
|
||||||
endTime = ri.Milliseconds();
|
// point triangle surfaces to VBO
|
||||||
ri.Printf(PRINT_ALL, "world VBO calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
|
for (currSurf = firstSurf; currSurf < lastSurf; currSurf++)
|
||||||
|
|
||||||
// point triangle surfaces to world VBO
|
|
||||||
for(k = 0, surface = surfacesSorted[k]; k < numSurfaces; k++, surface = surfacesSorted[k])
|
|
||||||
{
|
{
|
||||||
|
surface = *currSurf;
|
||||||
if(*surface->data == SF_FACE)
|
if(*surface->data == SF_FACE)
|
||||||
{
|
{
|
||||||
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
srfSurfaceFace_t *srf = (srfSurfaceFace_t *) surface->data;
|
||||||
|
|
||||||
if( srf->numVerts && srf->numTriangles)
|
if( srf->numVerts && srf->numTriangles)
|
||||||
{
|
{
|
||||||
srf->vbo = s_worldData.vbo;
|
srf->vbo = vbo;
|
||||||
srf->ibo = s_worldData.ibo;
|
srf->ibo = ibo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(*surface->data == SF_GRID)
|
else if(*surface->data == SF_GRID)
|
||||||
|
@ -2102,8 +2120,8 @@ static void R_CreateWorldVBO(void)
|
||||||
|
|
||||||
if( srf->numVerts && srf->numTriangles)
|
if( srf->numVerts && srf->numTriangles)
|
||||||
{
|
{
|
||||||
srf->vbo = s_worldData.vbo;
|
srf->vbo = vbo;
|
||||||
srf->ibo = s_worldData.ibo;
|
srf->ibo = ibo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(*surface->data == SF_TRIANGLES)
|
else if(*surface->data == SF_TRIANGLES)
|
||||||
|
@ -2112,17 +2130,23 @@ static void R_CreateWorldVBO(void)
|
||||||
|
|
||||||
if( srf->numVerts && srf->numTriangles)
|
if( srf->numVerts && srf->numTriangles)
|
||||||
{
|
{
|
||||||
srf->vbo = s_worldData.vbo;
|
srf->vbo = vbo;
|
||||||
srf->ibo = s_worldData.ibo;
|
srf->ibo = ibo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ri.Free(surfacesSorted);
|
|
||||||
|
|
||||||
ri.Hunk_FreeTempMemory(triangles);
|
ri.Hunk_FreeTempMemory(triangles);
|
||||||
ri.Hunk_FreeTempMemory(verts);
|
ri.Hunk_FreeTempMemory(verts);
|
||||||
|
|
||||||
|
k++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ri.Free(surfacesSorted);
|
||||||
|
|
||||||
|
endTime = ri.Milliseconds();
|
||||||
|
ri.Printf(PRINT_ALL, "world VBOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3006,6 +3030,7 @@ void R_MergeLeafSurfaces(void)
|
||||||
int mergedSurfIndex;
|
int mergedSurfIndex;
|
||||||
int numMergedSurfaces;
|
int numMergedSurfaces;
|
||||||
int numUnmergedSurfaces;
|
int numUnmergedSurfaces;
|
||||||
|
VBO_t *vbo;
|
||||||
IBO_t *ibo;
|
IBO_t *ibo;
|
||||||
|
|
||||||
msurface_t *mergedSurf;
|
msurface_t *mergedSurf;
|
||||||
|
@ -3025,14 +3050,6 @@ void R_MergeLeafSurfaces(void)
|
||||||
s_worldData.surfacesViewCount[i] = -1;
|
s_worldData.surfacesViewCount[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create ibo
|
|
||||||
ibo = tr.ibos[tr.numIBOs++] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
|
|
||||||
memset(ibo, 0, sizeof(*ibo));
|
|
||||||
Q_strncpyz(ibo->name, "staticWorldMesh_IBO_mergedSurfs", sizeof(ibo->name));
|
|
||||||
|
|
||||||
// allocate more than we need
|
|
||||||
iboIndexes = outIboIndexes = ri.Malloc(s_worldData.ibo->indexesSize);
|
|
||||||
|
|
||||||
// mark matching surfaces
|
// mark matching surfaces
|
||||||
for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++)
|
for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++)
|
||||||
{
|
{
|
||||||
|
@ -3166,6 +3183,9 @@ void R_MergeLeafSurfaces(void)
|
||||||
s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
|
s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// need to be synched here
|
||||||
|
R_IssuePendingRenderCommands();
|
||||||
|
|
||||||
// actually merge surfaces
|
// actually merge surfaces
|
||||||
numIboIndexes = 0;
|
numIboIndexes = 0;
|
||||||
mergedSurfIndex = 0;
|
mergedSurfIndex = 0;
|
||||||
|
@ -3188,6 +3208,26 @@ void R_MergeLeafSurfaces(void)
|
||||||
|
|
||||||
surf1 = s_worldData.surfaces + i;
|
surf1 = s_worldData.surfaces + i;
|
||||||
|
|
||||||
|
// retrieve vbo
|
||||||
|
switch(*surf1->data)
|
||||||
|
{
|
||||||
|
case SF_FACE:
|
||||||
|
vbo = ((srfSurfaceFace_t *)(surf1->data))->vbo;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SF_GRID:
|
||||||
|
vbo = ((srfGridMesh_t *)(surf1->data))->vbo;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SF_TRIANGLES:
|
||||||
|
vbo = ((srfTriangles_t *)(surf1->data))->vbo;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
vbo = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// count verts, indexes, and surfaces
|
// count verts, indexes, and surfaces
|
||||||
numSurfsToMerge = 0;
|
numSurfsToMerge = 0;
|
||||||
numTriangles = 0;
|
numTriangles = 0;
|
||||||
|
@ -3245,6 +3285,15 @@ void R_MergeLeafSurfaces(void)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create ibo
|
||||||
|
ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low);
|
||||||
|
memset(ibo, 0, sizeof(*ibo));
|
||||||
|
Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", tr.numIBOs++), sizeof(ibo->name));
|
||||||
|
numIboIndexes = 0;
|
||||||
|
|
||||||
|
// allocate indexes
|
||||||
|
iboIndexes = outIboIndexes = ri.Malloc(numTriangles * 3 * sizeof(*outIboIndexes));
|
||||||
|
|
||||||
// Merge surfaces (indexes) and calculate bounds
|
// Merge surfaces (indexes) and calculate bounds
|
||||||
ClearBounds(bounds[0], bounds[1]);
|
ClearBounds(bounds[0], bounds[1]);
|
||||||
firstIndex = numIboIndexes;
|
firstIndex = numIboIndexes;
|
||||||
|
@ -3320,7 +3369,7 @@ void R_MergeLeafSurfaces(void)
|
||||||
memset(vboSurf, 0, sizeof(*vboSurf));
|
memset(vboSurf, 0, sizeof(*vboSurf));
|
||||||
vboSurf->surfaceType = SF_VBO_MESH;
|
vboSurf->surfaceType = SF_VBO_MESH;
|
||||||
|
|
||||||
vboSurf->vbo = s_worldData.vbo;
|
vboSurf->vbo = vbo;
|
||||||
vboSurf->ibo = ibo;
|
vboSurf->ibo = ibo;
|
||||||
|
|
||||||
vboSurf->numIndexes = numTriangles * 3;
|
vboSurf->numIndexes = numTriangles * 3;
|
||||||
|
@ -3352,6 +3401,17 @@ void R_MergeLeafSurfaces(void)
|
||||||
mergedSurf->cubemapIndex = surf1->cubemapIndex;
|
mergedSurf->cubemapIndex = surf1->cubemapIndex;
|
||||||
mergedSurf->shader = surf1->shader;
|
mergedSurf->shader = surf1->shader;
|
||||||
|
|
||||||
|
// finish up the ibo
|
||||||
|
qglGenBuffersARB(1, &ibo->indexesVBO);
|
||||||
|
|
||||||
|
R_BindIBO(ibo);
|
||||||
|
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
|
||||||
|
R_BindNullIBO();
|
||||||
|
|
||||||
|
GL_CheckErrors();
|
||||||
|
|
||||||
|
ri.Free(iboIndexes);
|
||||||
|
|
||||||
// redirect view surfaces to this surf
|
// redirect view surfaces to this surf
|
||||||
for (j = 0; j < numWorldSurfaces; j++)
|
for (j = 0; j < numWorldSurfaces; j++)
|
||||||
{
|
{
|
||||||
|
@ -3372,21 +3432,6 @@ void R_MergeLeafSurfaces(void)
|
||||||
mergedSurf++;
|
mergedSurf++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish up the ibo
|
|
||||||
R_IssuePendingRenderCommands();
|
|
||||||
|
|
||||||
qglGenBuffersARB(1, &ibo->indexesVBO);
|
|
||||||
|
|
||||||
R_BindIBO(ibo);
|
|
||||||
|
|
||||||
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB);
|
|
||||||
|
|
||||||
R_BindNullIBO();
|
|
||||||
|
|
||||||
GL_CheckErrors();
|
|
||||||
|
|
||||||
ri.Free(iboIndexes);
|
|
||||||
|
|
||||||
endTime = ri.Milliseconds();
|
endTime = ri.Milliseconds();
|
||||||
|
|
||||||
ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n",
|
ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n",
|
||||||
|
@ -3743,7 +3788,7 @@ void RE_LoadWorldMap( const char *name ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create static VBOS from the world
|
// create static VBOS from the world
|
||||||
R_CreateWorldVBO();
|
R_CreateWorldVBOs();
|
||||||
if (r_mergeLeafSurfaces->integer)
|
if (r_mergeLeafSurfaces->integer)
|
||||||
{
|
{
|
||||||
R_MergeLeafSurfaces();
|
R_MergeLeafSurfaces();
|
||||||
|
|
|
@ -1334,9 +1334,6 @@ typedef struct {
|
||||||
int numDecisionNodes;
|
int numDecisionNodes;
|
||||||
mnode_t *nodes;
|
mnode_t *nodes;
|
||||||
|
|
||||||
VBO_t *vbo;
|
|
||||||
IBO_t *ibo;
|
|
||||||
|
|
||||||
int numWorldSurfaces;
|
int numWorldSurfaces;
|
||||||
|
|
||||||
int numsurfaces;
|
int numsurfaces;
|
||||||
|
|
Loading…
Reference in a new issue