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

renderer: introduce IF_FITSCREEN and RSF_2D #1145

Merged
merged 6 commits into from
Jun 6, 2024
Merged
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
2 changes: 1 addition & 1 deletion src/engine/client/cg_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void trap_S_StartBackgroundTrack( const char *intro, const char *loop
void trap_R_LoadWorldMap( const char *mapname );
qhandle_t trap_R_RegisterModel( const char *name );
qhandle_t trap_R_RegisterSkin( const char *name );
qhandle_t trap_R_RegisterShader( const char *name, RegisterShaderFlags_t flags );
qhandle_t trap_R_RegisterShader( const char *name, int flags );

void trap_R_ClearScene();
void trap_R_AddRefEntityToScene( const refEntity_t *re );
Expand Down
2 changes: 1 addition & 1 deletion src/engine/client/cl_cgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ void CGameVM::QVMSyscall(int syscallNum, Util::Reader& reader, IPC::Channel& cha

case CG_R_REGISTERSHADER:
IPC::HandleMsg<Render::RegisterShaderMsg>(channel, std::move(reader), [this] (const std::string& name, int flags, int& handle) {
handle = re.RegisterShader(name.c_str(), (RegisterShaderFlags_t) flags);
handle = re.RegisterShader(name.c_str(), flags);
});
break;

Expand Down
2 changes: 1 addition & 1 deletion src/engine/null/null_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ qhandle_t RE_RegisterSkin( const char *name )
{
return FS_FOpenFileRead( name, nullptr );
}
qhandle_t RE_RegisterShader( const char *, RegisterShaderFlags_t )
qhandle_t RE_RegisterShader( const char *, int )
{
return 1;
}
Expand Down
38 changes: 34 additions & 4 deletions src/engine/renderer/InternalImage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,40 @@ int R_GetImageCustomScalingStep( const image_t *image, const imageParams_t &imag
return 0;
}

// Consider the larger edge as the "image dimension"
int scaledDimension = std::max( image->width, image->height );

int scalingStep = 0;

// Scale down the image size according to the screen size.
if ( image->bits & IF_FITSCREEN )
{
int largerSide = std::max( glConfig.vidWidth, glConfig.vidHeight );

if ( scaledDimension > largerSide )
{
while ( scaledDimension > largerSide )
{
scaledDimension >>= 1;
scalingStep++;
}

/* With r_imageFitScreen == 1, we need the larger image size before
it becomes smaller than screen.

With r_imageFitScreen == 2 the image is never larger than screen, as
we allow the larger size that is not larger than screen, it can be the
larger size smaller than screen. */
if ( scaledDimension != largerSide && r_imageFitScreen.Get() != 2 )
{
scaledDimension <<= 1;
scalingStep--;
}
}

return scalingStep;
}

int materialMinDimension = r_ignoreMaterialMinDimension->integer ? 0 : imageParams.minDimension;
int materialMaxDimension = r_ignoreMaterialMaxDimension->integer ? 0 : imageParams.maxDimension;

Expand All @@ -130,10 +164,6 @@ int R_GetImageCustomScalingStep( const image_t *image, const imageParams_t &imag
maxDimension = std::min( maxDimension, r_imageMaxDimension->integer );
}

// Consider the larger edge as the "image dimension"
int scaledDimension = std::max( image->width, image->height );
int scalingStep = 0;

// 1st priority: scaledDimension >= minDimension
// 2nd priority: scaledDimension <= maxDimension
// 3rd priority: scalingStep >= r_picMip->integer
Expand Down
8 changes: 8 additions & 0 deletions src/engine/renderer/tr_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,14 @@ void R_UploadImage( const byte **dataArray, int numLayers, int numMips, image_t

int scaledWidth = image->width;
int scaledHeight = image->height;

// If r_imageFitScreen is disabled, use nopicmip instead.
if ( ( image->bits & IF_FITSCREEN ) && !r_imageFitScreen.Get() )
{
image->bits &= ~IF_FITSCREEN;
image->bits |= IF_NOPICMIP;
}
Comment on lines +767 to +772
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a motivation for having this be something we can disable?

Copy link
Member Author

@illwieckz illwieckz Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for asset debugging. We can for example imagine a game that would have a very large 2D minimap larger than screen and that the player could scroll. If someone finds weird the image is blurry, he can disable the feature and deduce that's because the fitscreen flag is set somewhere for that image.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same would be usable for debugging any image that would have received the fitscreen flag but should not use fitscreen like some 3D textures (or worst, lightmaps…).


int customScalingStep = R_GetImageCustomScalingStep( image, imageParams );
R_DownscaleImageDimensions( customScalingStep, &scaledWidth, &scaledHeight, &dataArray, numLayers, &numMips );

Expand Down
2 changes: 2 additions & 0 deletions src/engine/renderer/tr_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
cvar_t *r_ignoreMaterialMinDimension;
cvar_t *r_ignoreMaterialMaxDimension;
cvar_t *r_replaceMaterialMinDimensionIfPresentWithMaxDimension;
Cvar::Range<Cvar::Cvar<int>> r_imageFitScreen("r_imageFitScreen", "downscale “fitscreen” images to fit the screen size: 0: disable, 1: downscale as much as possible without being smaller than screen size (default), 2: downscale to never be larger then screen size", Cvar::NONE, 1, 0, 2);
cvar_t *r_finish;
cvar_t *r_clear;
cvar_t *r_textureMode;
Expand Down Expand Up @@ -1095,6 +1096,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p
r_ignoreMaterialMaxDimension = Cvar_Get( "r_ignoreMaterialMaxDimension", "0", CVAR_LATCH | CVAR_ARCHIVE );
r_replaceMaterialMinDimensionIfPresentWithMaxDimension
= Cvar_Get( "r_replaceMaterialMinDimensionIfPresentWithMaxDimension", "0", CVAR_LATCH | CVAR_ARCHIVE );
Cvar::Latch(r_imageFitScreen);
r_colorbits = Cvar_Get( "r_colorbits", "0", CVAR_LATCH );
r_mode = Cvar_Get( "r_mode", "-2", CVAR_LATCH | CVAR_ARCHIVE );
r_customwidth = Cvar_Get( "r_customwidth", "1600", CVAR_LATCH | CVAR_ARCHIVE );
Expand Down
9 changes: 6 additions & 3 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ enum class dynamicLightRenderer_t { LEGACY, TILED };
{
IF_NONE,
IF_NOPICMIP = BIT( 0 ),
IF_FITSCREEN = BIT( 1 ),
IF_NORMALMAP = BIT( 2 ),
IF_RGBA16F = BIT( 3 ),
IF_RGBA32F = BIT( 4 ),
Expand Down Expand Up @@ -1147,6 +1148,7 @@ enum class dynamicLightRenderer_t { LEGACY, TILED };

int deformIndex;
bool overrideNoPicMip; // for images that must always be full resolution
bool fitScreen; // For images that should be scaled to fit the screen size.
bool overrideFilterType; // for console fonts, 2D elements, etc.
filterType_t filterType;
bool overrideWrapType;
Expand Down Expand Up @@ -1282,6 +1284,7 @@ enum class dynamicLightRenderer_t { LEGACY, TILED };
float polygonOffsetValue;

bool noPicMip; // for images that must always be full resolution
bool fitScreen; // For images that should be scaled to fit the screen size.
int imageMinDimension; // for images that must not be loaded with smaller size
int imageMaxDimension; // for images that must not be loaded with larger size
filterType_t filterType; // for console fonts, 2D elements, etc.
Expand Down Expand Up @@ -2906,6 +2909,7 @@ enum class dynamicLightRenderer_t { LEGACY, TILED };
extern cvar_t *r_ignoreMaterialMinDimension;
extern cvar_t *r_ignoreMaterialMaxDimension;
extern cvar_t *r_replaceMaterialMinDimensionIfPresentWithMaxDimension;
extern Cvar::Range<Cvar::Cvar<int>> r_imageFitScreen;
extern cvar_t *r_finish;
extern cvar_t *r_drawBuffer;
extern cvar_t *r_textureMode;
Expand Down Expand Up @@ -3263,12 +3267,11 @@ inline bool checkGLErrors()

====================================================================
*/
qhandle_t RE_RegisterShader( const char *name, RegisterShaderFlags_t flags );
qhandle_t RE_RegisterShader( const char *name, int flags );
qhandle_t RE_RegisterShaderFromImage( const char *name, image_t *image );
bool RE_LoadDynamicShader( const char *shadername, const char *shadertext );

shader_t *R_FindShader( const char *name, shaderType_t type,
RegisterShaderFlags_t flags );
shader_t *R_FindShader( const char *name, shaderType_t type, int flags );
shader_t *R_GetShaderByHandle( qhandle_t hShader );
shader_t *R_FindShaderByName( const char *name );
const char *RE_GetShaderNameFromHandle( qhandle_t shader );
Expand Down
3 changes: 1 addition & 2 deletions src/engine/renderer/tr_public.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ struct refexport_t
qhandle_t ( *RegisterModel )( const char *name );
//qhandle_t (*RegisterModelAllLODs) (const char *name);
qhandle_t ( *RegisterSkin )( const char *name );
qhandle_t ( *RegisterShader )( const char *name,
RegisterShaderFlags_t flags );
qhandle_t ( *RegisterShader )( const char *name, int flags );
fontInfo_t* ( *RegisterFont )( const char *fontName, int pointSize );
void ( *UnregisterFont )( fontInfo_t *font );
void ( *Glyph )( fontInfo_t *font, const char *str, glyphInfo_t *glyph );
Expand Down
67 changes: 51 additions & 16 deletions src/engine/renderer/tr_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1479,6 +1479,11 @@ static bool LoadMap( shaderStage_t *stage, const char *buffer, stageType_t type,
imageParams.bits |= IF_NOPICMIP;
}

if ( stage->fitScreen || shader.fitScreen )
{
imageParams.bits |= IF_FITSCREEN;
}

switch ( type )
{
case stageType_t::ST_NORMALMAP:
Expand Down Expand Up @@ -2173,6 +2178,11 @@ static bool ParseStage( shaderStage_t *stage, const char **text )
imageBits |= IF_NOPICMIP;
}

if ( stage->fitScreen || shader.fitScreen )
{
imageBits |= IF_FITSCREEN;
}

if ( stage->overrideFilterType )
{
filterType = stage->filterType;
Expand Down Expand Up @@ -2294,6 +2304,11 @@ static bool ParseStage( shaderStage_t *stage, const char **text )
imageBits |= IF_NOPICMIP;
}

if ( stage->fitScreen || shader.fitScreen )
{
imageBits |= IF_FITSCREEN;
}

if ( stage->overrideFilterType )
{
filterType = stage->filterType;
Expand Down Expand Up @@ -2386,6 +2401,10 @@ static bool ParseStage( shaderStage_t *stage, const char **text )
{
stage->overrideNoPicMip = true;
}
else if ( !Q_stricmp( token, "fitScreen" ) )
{
stage->fitScreen = true;
}
// clamp, edgeClamp etc.
else if ( ParseClampType( token, &stage->wrapType ) )
{
Expand Down Expand Up @@ -4178,6 +4197,12 @@ static bool ParseShader( const char *_text )
shader.noPicMip = true;
continue;
}
// fit screen adjustment
else if ( !Q_stricmp( token, "fitScreen" ) )
{
shader.fitScreen = true;
continue;
}
// imageMinDimension enforcement
else if ( !Q_stricmp( token, "imageMinDimension" ) )
{
Expand Down Expand Up @@ -6218,8 +6243,7 @@ the vertex rgba modulate values, as appropriate for misc_model
pre-lit surfaces.
===============
*/
shader_t *R_FindShader( const char *name, shaderType_t type,
RegisterShaderFlags_t flags )
shader_t *R_FindShader( const char *name, shaderType_t type, int flags )
{
char strippedName[ MAX_QPATH ];
char fileName[ MAX_QPATH ];
Expand Down Expand Up @@ -6327,32 +6351,43 @@ shader_t *R_FindShader( const char *name, shaderType_t type,
// if not defined in the in-memory shader descriptions,
// look for a single supported image file
bits = IF_NONE;
if( flags & RSF_NOMIP )

if ( flags & RSF_NOMIP )
{
bits |= IF_NOPICMIP;
else
shader.noPicMip = true;
}

if ( flags & RSF_FITSCREEN )
{
bits |= IF_FITSCREEN;
shader.fitScreen = true;
}

if( flags & RSF_NOLIGHTSCALE )
if ( flags & RSF_NOLIGHTSCALE )
{
bits |= IF_NOLIGHTSCALE;
}

Log::Debug( "loading '%s' image as shader", fileName );

// choosing filter based on the NOMIP flag seems strange,
// maybe it should be changed to type == SHADER_2D
if( !(bits & RSF_NOMIP) ) {
LoadExtraMaps( &stages[ 0 ], fileName );

if( bits & RSF_2D )
{
imageParams_t imageParams = {};
imageParams.bits = bits;
imageParams.filterType = filterType_t::FT_DEFAULT;
imageParams.wrapType = wrapTypeEnum_t::WT_REPEAT;
imageParams.filterType = filterType_t::FT_LINEAR;
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;

image = R_FindImageFile( fileName, imageParams );
} else {
}
else
{
LoadExtraMaps( &stages[ 0 ], fileName );

imageParams_t imageParams = {};
imageParams.bits = bits;
imageParams.filterType = filterType_t::FT_LINEAR;
imageParams.wrapType = wrapTypeEnum_t::WT_CLAMP;
imageParams.filterType = filterType_t::FT_DEFAULT;
imageParams.wrapType = wrapTypeEnum_t::WT_REPEAT;

image = R_FindImageFile( fileName, imageParams );
}
Expand Down Expand Up @@ -6492,7 +6527,7 @@ This should really only be used for explicit shaders, because there is no
way to ask for different implicit lighting modes (vertex, lightmap, etc)
====================
*/
qhandle_t RE_RegisterShader( const char *name, RegisterShaderFlags_t flags )
qhandle_t RE_RegisterShader( const char *name, int flags )
{
shader_t *sh;

Expand Down
12 changes: 7 additions & 5 deletions src/engine/renderer/tr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ using bool8_t = uint8_t;
using glIndex_t = unsigned int;

enum RegisterShaderFlags_t {
RSF_DEFAULT = 0x00,
RSF_NOMIP = 0x01,
RSF_LIGHT_ATTENUATION = 0x02,
RSF_NOLIGHTSCALE = 0x04,
RSF_SPRITE = 0x08
RSF_DEFAULT = BIT( 0 ),
RSF_2D = BIT( 1 ),
RSF_NOMIP = BIT( 2 ),
RSF_FITSCREEN = BIT( 3 ),
RSF_LIGHT_ATTENUATION = BIT( 4 ),
RSF_NOLIGHTSCALE = BIT( 5 ),
RSF_SPRITE = BIT( 6 ),
};

struct polyVert_t
Expand Down
2 changes: 1 addition & 1 deletion src/shared/client/cg_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ qhandle_t trap_R_RegisterSkin( const char *name )
return handle;
}

qhandle_t trap_R_RegisterShader( const char *name, RegisterShaderFlags_t flags )
qhandle_t trap_R_RegisterShader( const char *name, int flags )
{
int handle;
VM::SendMsg<Render::RegisterShaderMsg>(name, flags, handle);
Expand Down