This commit is contained in:
Daniel Gibson 2025-04-14 08:42:22 +08:00 committed by GitHub
commit b819ca24d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 45 additions and 10 deletions

View file

@ -426,8 +426,10 @@ public:
idImage * fogImage; // increasing alpha is denser fog
idImage * fogEnterImage; // adjust fogImage alpha based on terminator plane
idImage * cinematicImage;
idImage * scratchImage;
idImage * scratchImage2;
unsigned nextScratchImage;
idImage * scratchImages[8]; // DG: replacing scratchImage(2) with an array of scratch images
idImage * scratchImage; // but keep original "_scratch" around, it's used by gamecode
idImage * accumImage;
idImage * currentRenderImage; // for SS_POST_PROCESS shaders
idImage * scratchCubeMapImage;
@ -444,6 +446,14 @@ public:
void SetNormalPalette();
void ChangeTextureFilter();
// Get a (hopefully) unused scratch image, used for rendering subviews like mirrors etc
// it just cycles through the scratch images.. we used to have only two so I guess the
// chance of using (overwriting) one that's already in use is slim enough..
idImage * GetNextScratchImage()
{
return scratchImages[ nextScratchImage++ % ( sizeof(scratchImages)/sizeof(scratchImages[0]) ) ];
}
idList<idImage*> images;
idStrList ddsList;
idHashIndex ddsHash;

View file

@ -1468,7 +1468,7 @@ idImage *idImageManager::ImageFromFunction( const char *_name, void (*generatorF
idImage *image;
int hash;
if ( !name ) {
if ( !_name ) {
common->FatalError( "idImageManager::ImageFromFunction: NULL name" );
}
@ -2001,8 +2001,17 @@ void idImageManager::Init() {
// cinematicImage is used for cinematic drawing
// scratchImage is used for screen wipes/doublevision etc..
cinematicImage = ImageFromFunction("_cinematic", R_RGBA8Image );
// DG: to allow mirrors mirroring mirrors or cameras filming mirrors or similar nonsense,
// I added multiple scratchImages used by subviews (instead of just _scratch and _scratch2)
nextScratchImage = 0;
for( int i=0; i < sizeof(scratchImages)/sizeof(scratchImages[0]); ++i ) {
idStr scratchName = idStr::Format("_scratch%d", i);
scratchImages[i] = ImageFromFunction(scratchName, R_RGBA8Image );
}
// keeping _scratch around, it's used by gamecode
scratchImage = ImageFromFunction("_scratch", R_RGBA8Image );
scratchImage2 = ImageFromFunction("_scratch2", R_RGBA8Image );
accumImage = ImageFromFunction("_accum", R_RGBA8Image );
scratchCubeMapImage = ImageFromFunction("_scratchCubeMap", makeNormalizeVectorCubeMap );
currentRenderImage = ImageFromFunction("_currentRender", R_RGBA8Image );

View file

@ -834,12 +834,12 @@ void idRenderSystemLocal::CropRenderSize( int width, int height, bool makePowerO
height >>= 1;
}
currentRenderCrop++;
if ( currentRenderCrop == MAX_RENDER_CROPS ) {
common->Error( "idRenderSystemLocal::CropRenderSize: currentRenderCrop == MAX_RENDER_CROPS" );
}
currentRenderCrop++;
rc = &renderCrops[currentRenderCrop];
rc->x = 0;

View file

@ -155,6 +155,10 @@ void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *s
}
if ( pStage->texture.texgen == TG_GLASSWARP ) {
// DG: this doesn't work with the scratchImage array, and the shader is missing anyway
// so I commented out the code and added this warning
common->Warning( "RB_PrepareStageTexturing(): Someone is trying to use the glasswarp shader, but it's not implemented..." );
#if 0
if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) {
qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP );
qglEnable( GL_FRAGMENT_PROGRAM_ARB );
@ -192,6 +196,7 @@ void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *s
GL_SelectTexture( 0 );
}
#endif // 0
}
if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {

View file

@ -35,6 +35,8 @@ typedef struct {
idMat3 axis;
} orientation_t;
static idCVar r_maxMirrorRecursion( "r_maxMirrorRecursion", "2", CVAR_RENDERER | /*CVAR_ARCHIVE |*/ CVAR_INTEGER,
"how deep subviews with mirrors can watch each other", 0, MAX_RENDER_CROPS-3 );
/*
=================
@ -330,7 +332,7 @@ static void R_RemoteRender( drawSurf_t *surf, textureStage_t *stage ) {
// copy this rendering to the image
stage->dynamicFrameCount = tr.frameCount;
if (!stage->image) {
stage->image = globalImages->scratchImage;
stage->image = globalImages->GetNextScratchImage();
}
tr.CaptureRenderToImage( stage->image->imgName );
@ -381,7 +383,7 @@ void R_MirrorRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect sciss
// copy this rendering to the image
stage->dynamicFrameCount = tr.frameCount;
stage->image = globalImages->scratchImage;
stage->image = globalImages->GetNextScratchImage();
tr.CaptureRenderToImage( stage->image->imgName );
tr.UnCrop();
@ -431,7 +433,7 @@ void R_XrayRender( drawSurf_t *surf, textureStage_t *stage, idScreenRect scissor
// copy this rendering to the image
stage->dynamicFrameCount = tr.frameCount;
stage->image = globalImages->scratchImage2;
stage->image = globalImages->GetNextScratchImage();
tr.CaptureRenderToImage( stage->image->imgName );
tr.UnCrop();
@ -531,9 +533,18 @@ bool R_GenerateSurfaceSubview( drawSurf_t *drawSurf ) {
case DI_REMOTE_RENDER:
R_RemoteRender( drawSurf, const_cast<textureStage_t *>(&stage->texture) );
break;
case DI_MIRROR_RENDER:
case DI_MIRROR_RENDER: {
// DG: prevent mirrors from mirroring each other to infinity
// and also prevent tr.renderCrops from overflowing (with some extra wiggle
// room in case other cropping things are involved)
int maxDepth = Min(r_maxMirrorRecursion.GetInteger(), MAX_RENDER_CROPS-3);
if ( tr.currentRenderCrop >= maxDepth ) {
const_cast<textureStage_t &>(stage->texture).image = NULL;
return false;
}
R_MirrorRender( drawSurf, const_cast<textureStage_t *>(&stage->texture), scissor );
break;
}
case DI_XRAY_RENDER:
R_XrayRender( drawSurf, const_cast<textureStage_t *>(&stage->texture), scissor );
break;