mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-04-20 08:24:50 +00:00
fixed delayed shader loads leading to incorrect rendering and crashes (dynamic lights)
This commit is contained in:
parent
981f059b7b
commit
dbfb3c5028
4 changed files with 33 additions and 0 deletions
|
@ -25,6 +25,8 @@ chg: with r_backend GL3, depth fade with MSAA now requires GLSL 4.00 at a minimu
|
|||
|
||||
chg: with r_backend GL3, alpha to coverage now requires GLSL 4.00 at a minimum
|
||||
|
||||
fix: delayed shader loads could lead to incorrect rendering and crashes (mostly with dynamic lights)
|
||||
|
||||
fix: the nextdemo variable wasn't used to start the playback of a new demo when:
|
||||
- a drop error happened during demo playback
|
||||
- the engine failed to open the current demo file
|
||||
|
|
|
@ -508,6 +508,7 @@ struct drawSurf_t {
|
|||
qhandle_t model; // MD3 model handle
|
||||
int index; // transparent surface's registration order
|
||||
float shaderSort; // transparent surface's shader sort
|
||||
int shaderNum; // unsorted shader index, for when we need to do fix-ups
|
||||
};
|
||||
|
||||
extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( const void* );
|
||||
|
@ -515,6 +516,7 @@ extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( const void* );
|
|||
|
||||
struct litSurf_t {
|
||||
unsigned sort; // bit combination for fast compares
|
||||
int shaderNum; // unsorted shader index, for when we need to do fix-ups
|
||||
const surfaceType_t* surface; // any of surface*_t
|
||||
litSurf_t* next;
|
||||
};
|
||||
|
|
|
@ -1074,6 +1074,7 @@ void R_AddDrawSurf( const surfaceType_t* surface, const shader_t* shader, int fo
|
|||
drawSurf->sort = R_ComposeSort( tr.currentEntityNum, shader, fogIndex );
|
||||
drawSurf->surface = surface;
|
||||
drawSurf->model = tr.currentModel != NULL ? tr.currentModel->index : 0;
|
||||
drawSurf->shaderNum = shader->index;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1087,6 +1088,7 @@ void R_AddLitSurf( const surfaceType_t* surface, const shader_t* shader, int fog
|
|||
litSurf_t* const litSurf = &tr.refdef.litSurfs[tr.refdef.numLitSurfs++];
|
||||
litSurf->sort = R_ComposeSort( tr.currentEntityNum, shader, fogIndex );
|
||||
litSurf->surface = surface;
|
||||
litSurf->shaderNum = shader->index;
|
||||
|
||||
if (!tr.light->head)
|
||||
tr.light->head = litSurf;
|
||||
|
|
|
@ -1552,6 +1552,33 @@ static void SortNewShader()
|
|||
for ( i = 0; i < tr.numShaders; ++i ) {
|
||||
tr.sortedShaders[i]->sortedIndex = i;
|
||||
}
|
||||
|
||||
//
|
||||
// If we register a new shader when surfaces are already added,
|
||||
// the decoded sorted shader index for the added surfaces will not always be correct anymore.
|
||||
// This can lead to incorrect rendering (wrong shader used)
|
||||
// and potentially crashes too (lit surfaces referencing shaders with no diffuse stage).
|
||||
// We'll therefore update all surfaces that have already been added for this entire frame,
|
||||
// not just the last view. Hence why we don't use firstDrawSurf / firstLitSurf.
|
||||
// The extra CPU cost for the fix-up is nothing compared to loading new textures mid-frame.
|
||||
//
|
||||
|
||||
int entityNum, fogNum;
|
||||
const shader_t* wrongShader;
|
||||
|
||||
const int numDrawSurfs = tr.refdef.numDrawSurfs;
|
||||
drawSurf_t* drawSurfs = tr.refdef.drawSurfs;
|
||||
for( int i = 0; i < numDrawSurfs; ++i, ++drawSurfs ) {
|
||||
R_DecomposeSort( drawSurfs->sort, &entityNum, &wrongShader, &fogNum );
|
||||
drawSurfs->sort = R_ComposeSort( entityNum, tr.shaders[drawSurfs->shaderNum], fogNum );
|
||||
}
|
||||
|
||||
const int numLitSurfs = tr.refdef.numLitSurfs;
|
||||
litSurf_t* litSurfs = tr.refdef.litSurfs;
|
||||
for ( int i = 0; i < numLitSurfs; ++i, ++litSurfs ) {
|
||||
R_DecomposeSort( litSurfs->sort, &entityNum, &wrongShader, &fogNum );
|
||||
litSurfs->sort = R_ComposeSort( entityNum, tr.shaders[litSurfs->shaderNum], fogNum );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue