re-added r_textureMode to keep GL_NEAREST compatibility

This commit is contained in:
myT 2020-01-12 22:47:09 +01:00
parent f36392c128
commit e91f6e1c08
7 changed files with 72 additions and 18 deletions

View file

@ -95,7 +95,11 @@ chg: removed FreeType 2 and the unused R_REGISTERFONT syscalls that were using i
chg: removed light flares and all related cvars (r_flare*)
chg: r_textureMode and r_measureOverdraw were removed
chg: r_textureMode <filter> (default: "best") is now latched and only supports 2 modes:
r_textureMode GL_NEAREST = LEGO(R) mode - nearest-neighbor filtering for a subset of surfaces
r_textureMode anything else = normal mode - the engine picks the most appropriate filters
chg: r_measureOverdraw was removed
chg: r_speeds 1 now reports more precise timings, V-Sync status, GPU time and the selected back-end

View file

@ -117,6 +117,14 @@ enum VertexBufferId
VB_COUNT
};
enum TextureMode
{
TM_BILINEAR,
TM_ANISOTROPIC,
TM_NEAREST,
TM_COUNT
};
// @NOTE: MSDN says "you must set the ByteWidth value of D3D11_BUFFER_DESC in multiples of 16"
#pragma pack(push, 16)
@ -286,7 +294,7 @@ struct Direct3D
Texture textures[MAX_DRAWIMAGES];
int textureCount;
ID3D11SamplerState* samplerStates[TW_COUNT * 2];
ID3D11SamplerState* samplerStates[TW_COUNT * TM_COUNT];
int samplerStateIndices[2];
ID3D11BlendState* blendStates[2 * BLEND_STATE_COUNT * BLEND_STATE_COUNT];
@ -678,14 +686,14 @@ static void UploadPendingShaderData()
}
}
static int ComputeSamplerStateIndex(int textureWrap, int bilinear)
static int ComputeSamplerStateIndex(int textureWrap, int textureMode)
{
return bilinear * TW_COUNT + textureWrap;
return textureMode * TW_COUNT + textureWrap;
}
static void ApplySamplerState(UINT slot, textureWrap_t textureWrap, qbool bilinear)
static void ApplySamplerState(UINT slot, textureWrap_t textureWrap, TextureMode textureMode)
{
const int index = ComputeSamplerStateIndex(textureWrap, bilinear);
const int index = ComputeSamplerStateIndex(textureWrap, textureMode);
if(index == d3d.samplerStateIndices[slot])
{
return;
@ -791,7 +799,7 @@ static void ApplyPipeline(PipelineId index)
{
d3ds.context->OMSetRenderTargets(1, &d3d.renderTargetViewMS, NULL);
d3ds.context->PSSetShaderResources(1, 1, &d3d.depthStencilShaderView);
ApplySamplerState(1, TW_CLAMP_TO_EDGE, qtrue); // @TODO: nearest neighbor mode?
ApplySamplerState(1, TW_CLAMP_TO_EDGE, TM_BILINEAR);
}
else
{
@ -984,7 +992,18 @@ static void BindImage(UINT slot, const image_t* image)
{
ID3D11ShaderResourceView* view = d3d.textures[image->texnum].view;
d3ds.context->PSSetShaderResources(slot, 1, &view);
ApplySamplerState(slot, image->wrapClampMode, (image->flags & IMG_NOAF) != 0);
TextureMode mode = TM_ANISOTROPIC;
if(Q_stricmp(r_textureMode->string, "GL_NEAREST") == 0 &&
!backEnd.projection2D &&
(image->flags & (IMG_LMATLAS | IMG_EXTLMATLAS | IMG_NOPICMIP)) == 0)
{
mode = TM_NEAREST;
}
else if((image->flags & IMG_NOAF) != 0)
{
mode = TM_BILINEAR;
}
ApplySamplerState(slot, image->wrapClampMode, mode);
}
static void BindBundle(UINT slot, const textureBundle_t* bundle)
@ -1275,11 +1294,11 @@ static qbool GAL_Init()
D3D11_CreateBuffer(&pixelShaderBufferDesc, NULL, &d3d.pipelines[PID_GENERIC].pixelBuffer, "generic pixel shader buffer");
// create all sampler states
for(int bilinear = 0; bilinear < 2; ++bilinear)
for(int textureMode = 0; textureMode < TM_COUNT; ++textureMode)
{
for(int wrapMode = 0; wrapMode < TW_COUNT; ++wrapMode)
{
const int index = ComputeSamplerStateIndex(wrapMode, bilinear);
const int index = ComputeSamplerStateIndex(wrapMode, textureMode);
// @NOTE: D3D10_REQ_MAXANISOTROPY == D3D11_REQ_MAXANISOTROPY
const int maxAnisotropy = Com_ClampInt(1, D3D11_REQ_MAXANISOTROPY, r_ext_max_anisotropy->integer);
@ -1287,14 +1306,16 @@ static qbool GAL_Init()
ID3D11SamplerState* samplerState;
D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
samplerDesc.Filter = (bilinear || maxAnisotropy == 1) ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_ANISOTROPIC;
samplerDesc.Filter = textureMode == TM_NEAREST ?
D3D11_FILTER_MIN_MAG_MIP_POINT :
((textureMode == TM_BILINEAR || maxAnisotropy == 1) ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_ANISOTROPIC);
samplerDesc.AddressU = mode;
samplerDesc.AddressV = mode;
samplerDesc.AddressW = mode;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.MinLOD = -D3D11_FLOAT32_MAX;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.MaxAnisotropy = bilinear ? 1 : maxAnisotropy;
samplerDesc.MaxAnisotropy = textureMode == TM_ANISOTROPIC ? maxAnisotropy : 1;
hr = d3ds.device->CreateSamplerState(&samplerDesc, &samplerState);
CheckAndName(hr, "CreateSamplerState", samplerState, va("sampler state %d", index));
@ -1306,7 +1327,7 @@ static qbool GAL_Init()
for(int i = 0; i < ARRAY_LEN(d3d.samplerStateIndices); ++i)
{
d3d.samplerStateIndices[i] = -1;
ApplySamplerState(i, TW_CLAMP_TO_EDGE, qtrue);
ApplySamplerState(i, TW_CLAMP_TO_EDGE, TM_BILINEAR);
}
// create all blend states
@ -1836,7 +1857,7 @@ static void GAL_EndFrame()
UploadPendingShaderData();
BindImage(0, tr.whiteImage);
d3ds.context->PSSetShaderResources(0, 1, &d3d.resolveTextureShaderView);
ApplySamplerState(0, TW_CLAMP_TO_EDGE, qtrue);
ApplySamplerState(0, TW_CLAMP_TO_EDGE, TM_BILINEAR);
ApplyViewportAndScissor(0, 0, glInfo.winWidth, glInfo.winHeight, glInfo.winHeight);
d3ds.context->Draw(3, 0);

View file

@ -1290,7 +1290,11 @@ static void GAL_CreateTexture( image_t* image, int mipCount, int w, int h )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_TextureWrapMode(image->wrapClampMode) );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_TextureWrapMode(image->wrapClampMode) );
if ( image->flags & IMG_NOMIPMAP ) {
if ( Q_stricmp( r_textureMode->string, "GL_NEAREST" ) == 0 &&
( image->flags & (IMG_LMATLAS | IMG_EXTLMATLAS | IMG_NOPICMIP )) == 0 ) {
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
} else if ( image->flags & IMG_NOMIPMAP ) {
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
} else {

View file

@ -2417,7 +2417,13 @@ static void GAL_CreateTexture(image_t* image, int mipCount, int w, int h)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetTextureWrapMode(image->wrapClampMode));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetTextureWrapMode(image->wrapClampMode));
if(image->flags & IMG_NOMIPMAP)
if(Q_stricmp(r_textureMode->string, "GL_NEAREST") == 0 &&
(image->flags & (IMG_EXTLMATLAS | IMG_NOPICMIP)) == 0)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else if(image->flags & IMG_NOMIPMAP)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@ -2484,8 +2490,17 @@ static void GAL_CreateTextureEx(image_t* image, int mipCount, int mipOffset, int
glTexStorage2D(GL_TEXTURE_2D, mipCount - mipOffset, GL_RGBA8, image->width, image->height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GetTextureWrapMode(image->wrapClampMode));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GetTextureWrapMode(image->wrapClampMode));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if(Q_stricmp(r_textureMode->string, "GL_NEAREST") == 0 &&
(image->flags & (IMG_LMATLAS | IMG_EXTLMATLAS | IMG_NOPICMIP)) == 0)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GetMaxAnisotropy(image));
SetDebugName(GL_TEXTURE, id, image->name);

View file

@ -79,6 +79,12 @@ S_COLOR_HELP " >" S_COLOR_VAL "1 " S_COLOR_HELP "= Brighter"
"disables rendering of portals\n" \
"Portal example: the bottom teleporter on q3dm7."
#define help_r_textureMode \
"texture filtering mode\n" \
S_COLOR_VAL " GL_NEAREST " S_COLOR_HELP "= LEGO(R) mode\n" \
" anything else " "= Normal mode\n" \
"For anisotropic filtering, refer to " S_COLOR_CVAR "r_ext_max_anisotropy" S_COLOR_HELP "."
#define help_r_swapInterval \
"Screen refresh periods to wait for before swapping buffers\n" \
S_COLOR_VAL " N < 0 " S_COLOR_HELP "= Adaptive V-Sync: tears when too late\n" \

View file

@ -95,6 +95,7 @@ cvar_t *r_shownormals;
cvar_t *r_finish;
cvar_t *r_clear;
cvar_t *r_swapInterval;
cvar_t *r_textureMode;
cvar_t *r_lockpvs;
cvar_t *r_noportals;
cvar_t *r_portalOnly;
@ -410,6 +411,8 @@ static const cvarTableItem_t r_cvars[] =
{ &r_dynamiclight, "r_dynamiclight", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables dynamic lights" },
{ &r_finish, "r_finish", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables glFinish calls" },
{ &r_swapInterval, "r_swapInterval", "0", CVAR_ARCHIVE, CVART_INTEGER, "-8", "8", help_r_swapInterval },
// r_textureMode's default value can't be an empty string because otherwise, a user-created default can stick (see Cvar_Get)
{ &r_textureMode, "r_textureMode", "best", CVAR_ARCHIVE | CVAR_LATCH, CVART_STRING, NULL, NULL, help_r_textureMode },
{ &r_gamma, "r_gamma", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.5", "3", help_r_gamma },
{ &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "controls how monochrome the final image looks" },
{ &r_noiseScale, "r_noiseScale", "1.0", CVAR_ARCHIVE, CVART_FLOAT, "0.125", "8.0", help_r_noiseScale },

View file

@ -1005,6 +1005,7 @@ extern cvar_t *r_picmip; // controls picmip values
extern cvar_t *r_finish;
extern cvar_t *r_swapInterval;
extern cvar_t *r_textureMode;
extern cvar_t *r_vertexLight; // vertex lighting mode for better performance
extern cvar_t *r_uiFullScreen; // ui is running fullscreen