fixed draw surface sorting

got broken with commit 633c5bd13c
This commit is contained in:
myT 2020-11-05 03:47:55 +01:00
parent 3e0f5b2760
commit f4e8e81ab5
3 changed files with 44 additions and 15 deletions

View file

@ -505,8 +505,9 @@ struct drawSurf_t {
unsigned sort; // bit combination for fast compares unsigned sort; // bit combination for fast compares
float depth; // transparent surface's midpoint's depth float depth; // transparent surface's midpoint's depth
const surfaceType_t* surface; // any of surface*_t const surfaceType_t* surface; // any of surface*_t
int index; // transparent surface's registration order
qhandle_t model; // MD3 model handle qhandle_t model; // MD3 model handle
int index; // transparent surface's registration order
float shaderSort; // transparent surface's shader sort
}; };
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( const void* ); extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( const void* );
@ -797,15 +798,11 @@ compared quickly during the qsorting process
the bits are allocated as follows: the bits are allocated as follows:
31-31 : unused (1 bit) 29-31 : zero (3 bits)
30-30 : depth fade (1 bit)
29-29 : polygon offset (1 bit)
15-28 : sorted shader index (14 bits) 15-28 : sorted shader index (14 bits)
5-14 : entity index (10 bits) 5-14 : entity index (10 bits)
0- 4 : fog index (5 bits) 0- 4 : fog index (5 bits)
*/ */
#define QSORT_DEPTHFADE_SHIFT 30
#define QSORT_POLYOFF_SHIFT 29
#define QSORT_SHADERNUM_SHIFT 15 #define QSORT_SHADERNUM_SHIFT 15
#define QSORT_ENTITYNUM_SHIFT 5 #define QSORT_ENTITYNUM_SHIFT 5
#define QSORT_FOGNUM_SHIFT 0 #define QSORT_FOGNUM_SHIFT 0

View file

@ -1072,9 +1072,7 @@ void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int fo
// the sort data is packed into a single 32 bit value so it can be // the sort data is packed into a single 32 bit value so it can be
// compared quickly during the qsorting process // compared quickly during the qsorting process
tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT) tr.refdef.drawSurfs[index].sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
| tr.shiftedEntityNum | (fogIndex << QSORT_FOGNUM_SHIFT) | tr.shiftedEntityNum | (fogIndex << QSORT_FOGNUM_SHIFT);
| ((shader->dfType != DFT_NONE) << QSORT_DEPTHFADE_SHIFT)
| (shader->polygonOffset << QSORT_POLYOFF_SHIFT);
tr.refdef.drawSurfs[index].surface = surface; tr.refdef.drawSurfs[index].surface = surface;
tr.refdef.drawSurfs[index].model = tr.currentModel != NULL ? tr.currentModel->index : 0; tr.refdef.drawSurfs[index].model = tr.currentModel != NULL ? tr.currentModel->index : 0;
} }
@ -1088,9 +1086,7 @@ void R_AddLitSurf( const surfaceType_t* surface, const shader_t* shader, int fog
litSurf_t* litsurf = &tr.refdef.litSurfs[index]; litSurf_t* litsurf = &tr.refdef.litSurfs[index];
litsurf->sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT) litsurf->sort = (shader->sortedIndex << QSORT_SHADERNUM_SHIFT)
| tr.shiftedEntityNum | (fogIndex << QSORT_FOGNUM_SHIFT) | tr.shiftedEntityNum | (fogIndex << QSORT_FOGNUM_SHIFT);
| ((shader->dfType != DFT_NONE) << QSORT_DEPTHFADE_SHIFT)
| (shader->polygonOffset << QSORT_POLYOFF_SHIFT);
litsurf->surface = surface; litsurf->surface = surface;
if (!tr.light->head) if (!tr.light->head)
@ -1210,14 +1206,17 @@ c) What we really want is true order-independent transparency (OIT).
- Per-pixel fixed-size arrays (there are several methods). - Per-pixel fixed-size arrays (there are several methods).
- Depth peeling (there are also several methods). - Depth peeling (there are also several methods).
*/ */
static int R_CompareDrawSurfDepth( const void* aPtr, const void* bPtr ) static int R_CompareDrawSurf( const void* aPtr, const void* bPtr )
{ {
const drawSurf_t* a = ( const drawSurf_t* )aPtr; const drawSurf_t* a = ( const drawSurf_t* )aPtr;
const drawSurf_t* b = ( const drawSurf_t* )bPtr; const drawSurf_t* b = ( const drawSurf_t* )bPtr;
if ( a->shaderSort < b->shaderSort )
return -1;
if ( a->shaderSort > b->shaderSort )
return 1;
if ( a->depth > b->depth ) if ( a->depth > b->depth )
return -1; return -1;
if ( a->depth < b->depth ) if ( a->depth < b->depth )
return 1; return 1;
@ -1288,10 +1287,21 @@ static void R_SortDrawSurfs( int firstDrawSurf, int firstLitSurf )
drawSurfs[i].depth = R_ComputeSurfaceDepth( drawSurfs[i].surface, entityNum, drawSurfs[i].model ); drawSurfs[i].depth = R_ComputeSurfaceDepth( drawSurfs[i].surface, entityNum, drawSurfs[i].model );
drawSurfs[i].index = i; drawSurfs[i].index = i;
drawSurfs[i].shaderSort = shader->sort;
} }
// sort transparent surfaces by depth // sort transparent surfaces by depth
qsort( drawSurfs + numDrawSurfs - numTranspSurfs, numTranspSurfs, sizeof(drawSurf_t), &R_CompareDrawSurfDepth ); qsort( drawSurfs + numDrawSurfs - numTranspSurfs, numTranspSurfs, sizeof(drawSurf_t), &R_CompareDrawSurf );
#if defined(_DEBUG)
float prevSort = -1.0f;
for ( int i = 0; i < numDrawSurfs; ++i )
{
R_DecomposeSort( (drawSurfs + i)->sort, &entityNum, &shader, &fogNum );
assert( shader->sort >= prevSort );
prevSort = shader->sort;
}
#endif
// all the lit surfaces are in a single queue // all the lit surfaces are in a single queue
// but each light's surfaces are sorted within its subsection // but each light's surfaces are sorted within its subsection

View file

@ -1508,6 +1508,22 @@ static qbool ParseShader( const char** text )
} }
static int R_CompareShaders( const void* aPtr, const void* bPtr )
{
const shader_t* const a = *(const shader_t**)aPtr;
const shader_t* const b = *(const shader_t**)bPtr;
if ( a->sort < b->sort )
return -1;
if ( a->sort > b->sort )
return 1;
if ( a->polygonOffset ^ b->polygonOffset )
return a->polygonOffset - b->polygonOffset;
return a->cullType - b->cullType;
}
/* /*
Positions the most recently created shader in the tr.sortedShaders[] array Positions the most recently created shader in the tr.sortedShaders[] array
such that the shader->sort key is sorted relative to the other shaders. such that the shader->sort key is sorted relative to the other shaders.
@ -1530,6 +1546,12 @@ static void SortNewShader()
newShader->sortedIndex = i+1; newShader->sortedIndex = i+1;
tr.sortedShaders[i+1] = newShader; tr.sortedShaders[i+1] = newShader;
// sort it more aggressively for better performance
qsort( tr.sortedShaders, tr.numShaders, sizeof(shader_t*), &R_CompareShaders );
for ( i = 0; i < tr.numShaders; ++i ) {
tr.sortedShaders[i]->sortedIndex = i;
}
} }