Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support for mirrors seeing other mirrors #646

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions neo/renderer/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,10 @@ class idImageManager {
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;
Expand All @@ -427,6 +429,14 @@ class idImageManager {
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;
Expand Down
13 changes: 11 additions & 2 deletions neo/renderer/Image_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" );
}

Expand Down Expand Up @@ -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 );
Expand Down
4 changes: 2 additions & 2 deletions neo/renderer/RenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions neo/renderer/draw_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down Expand Up @@ -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 ) {
Expand Down
19 changes: 15 additions & 4 deletions neo/renderer/tr_subview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

/*
=================
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down