From 24cd2f1b4ed22fb7e65553a7a63cb3a4b1c2aed5 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 8 Apr 2025 05:57:09 +0200 Subject: [PATCH 1/3] BPTC modes for image_usePrecompressedTextures + image_useCompression Both can now be set to 2 instead of just 0/1. For image_usePrecompressedTextures 1 now means "use .dds files no matter how they're compressed" and 2 means "only use .dds files if they are compressed with BPTC/BC7 or are uncompressed". For image_useCompression 1 means "compress textures with S3TC on upload" (just like before) and 2 means "compress with BPTC/BC7 if available" I wasn't sure whether this option makes sense for image_useCompression (over always using BPTC if available), but I can imagine that loading takes longer with BPTC (the driver has to compress the raw image data and compressing to S3TC might be faster than for BPTC) --- neo/renderer/Image.h | 2 +- neo/renderer/Image_init.cpp | 7 ++-- neo/renderer/Image_load.cpp | 67 +++++++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index ec7f5d0d..31dd8d2e 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -386,7 +386,7 @@ public: static idCVar image_roundDown; // round bad sizes down to nearest power of two static idCVar image_colorMipLevels; // development aid to see texture mip usage static idCVar image_downSize; // controls texture downsampling - static idCVar image_useCompression; // 0 = force everything to high quality + static idCVar image_useCompression; // 0 = force everything to high quality 1 = compress with S3TC (DXT) 2 = compress with BPTC if possible static idCVar image_filter; // changes texture filtering on mipmapped images static idCVar image_anisotropy; // set the maximum texture anisotropy if available static idCVar image_lodbias; // change lod bias on mipmapped images diff --git a/neo/renderer/Image_init.cpp b/neo/renderer/Image_init.cpp index f591b030..1e0f640a 100644 --- a/neo/renderer/Image_init.cpp +++ b/neo/renderer/Image_init.cpp @@ -53,10 +53,13 @@ idCVar idImageManager::image_forceDownSize( "image_forceDownSize", "0", CVAR_REN idCVar idImageManager::image_roundDown( "image_roundDown", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "round bad sizes down to nearest power of two" ); idCVar idImageManager::image_colorMipLevels( "image_colorMipLevels", "0", CVAR_RENDERER | CVAR_BOOL, "development aid to see texture mip usage" ); idCVar idImageManager::image_preload( "image_preload", "1", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "if 0, dynamically load all images" ); -idCVar idImageManager::image_useCompression( "image_useCompression", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "0 = force everything to high quality" ); +idCVar idImageManager::image_useCompression( "image_useCompression", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, + "Compress textures on load so they use less VRAM. 1 = compress with S3TC/DXT when uploading 2 = compress with BPTC when uploading (if available) " + "0 = upload uncompressed (unless image_usePrecompressedTextures is 1 and it's loaded from a precompressed .dds file)" ); idCVar idImageManager::image_useAllFormats( "image_useAllFormats", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "allow alpha/intensity/luminance/luminance+alpha" ); idCVar idImageManager::image_useNormalCompression( "image_useNormalCompression", "2", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "2 = use rxgb compression for normal maps, 1 = use 256 color compression for normal maps if available" ); -idCVar idImageManager::image_usePrecompressedTextures( "image_usePrecompressedTextures", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use .dds files if present" ); +idCVar idImageManager::image_usePrecompressedTextures( "image_usePrecompressedTextures", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, + "1 = use .dds files if present 2 = only use .dds files if they contain BPTC (BC7) textures (those have higher quality than S3TC/DXT) 0 = use uncompressed textures" ); idCVar idImageManager::image_writePrecompressedTextures( "image_writePrecompressedTextures", "0", CVAR_RENDERER | CVAR_BOOL, "write .dds files if necessary" ); idCVar idImageManager::image_writeNormalTGA( "image_writeNormalTGA", "0", CVAR_RENDERER | CVAR_BOOL, "write .tgas of the final normal maps for debugging" ); idCVar idImageManager::image_writeNormalTGAPalletized( "image_writeNormalTGAPalletized", "0", CVAR_RENDERER | CVAR_BOOL, "write .tgas of the final palletized normal maps for debugging" ); diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 06dfc30c..f9ae0021 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -215,6 +215,11 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in int rgbOr, rgbAnd, aOr, aAnd; int rgbDiffer, rgbaDiffer; + // TODO: or always use BC7 if available? do textures take longer to load then? + // would look better at least... + const bool useBC7compression = glConfig.bptcTextureCompressionAvailable + && globalImages->image_useCompression.GetInteger() == 2; + // determine if the rgb channels are all the same // and if either all rgb or all alpha are 255 c = width*height; @@ -262,12 +267,17 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in // catch normal maps first if ( minimumDepth == TD_BUMP ) { - if ( globalImages->image_useCompression.GetBool() && globalImages->image_useNormalCompression.GetInteger() == 1 && glConfig.sharedTexturePaletteAvailable ) { + // DG: put the glConfig.sharedTexturePaletteAvailable check first because nowadays it's usually false + if ( glConfig.sharedTexturePaletteAvailable && globalImages->image_useCompression.GetBool() && globalImages->image_useNormalCompression.GetInteger() == 1 ) { // image_useNormalCompression should only be set to 1 on nv_10 and nv_20 paths return GL_COLOR_INDEX8_EXT; } else if ( globalImages->image_useCompression.GetBool() && globalImages->image_useNormalCompression.GetInteger() && glConfig.textureCompressionAvailable ) { - // image_useNormalCompression == 2 uses rxgb format which produces really good quality for medium settings - return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + if ( useBC7compression ) { + return GL_COMPRESSED_RGBA_BPTC_UNORM; + } else { + // image_useNormalCompression == 2 uses rxgb format which produces really good quality for medium settings + return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } } else { // we always need the alpha channel for bump maps for swizzling return GL_RGBA8; @@ -282,7 +292,7 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in if ( minimumDepth == TD_SPECULAR ) { // we are assuming that any alpha channel is unintentional if ( glConfig.textureCompressionAvailable ) { - return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + return useBC7compression ? GL_COMPRESSED_RGBA_BPTC_UNORM : GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } else { return GL_RGB5; } @@ -290,6 +300,9 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in if ( minimumDepth == TD_DIFFUSE ) { // we might intentionally have an alpha channel for alpha tested textures if ( glConfig.textureCompressionAvailable ) { + if ( useBC7compression ) { + return GL_COMPRESSED_RGBA_BPTC_UNORM; + } if ( !needAlpha ) { return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; } else { @@ -319,7 +332,8 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in return GL_RGB8; // four bytes } if ( glConfig.textureCompressionAvailable ) { - return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // half byte + return useBC7compression ? GL_COMPRESSED_RGBA_BPTC_UNORM // 1byte/pixel + : GL_COMPRESSED_RGB_S3TC_DXT1_EXT; // half byte } return GL_RGB5; // two bytes } @@ -327,7 +341,7 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in // cases with alpha if ( !rgbaDiffer ) { if ( minimumDepth != TD_HIGH_QUALITY && glConfig.textureCompressionAvailable ) { - return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; // one byte + return useBC7compression ? GL_COMPRESSED_RGBA_BPTC_UNORM : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; // one byte } return GL_INTENSITY8; // single byte for all channels } @@ -346,7 +360,7 @@ GLenum idImage::SelectInternalFormat( const byte **dataPtrs, int numDataPtrs, in return GL_RGBA8; // four bytes } if ( glConfig.textureCompressionAvailable ) { - return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; // one byte + return useBC7compression ? GL_COMPRESSED_RGBA_BPTC_UNORM : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; // one byte } if ( !rgbDiffer ) { return GL_LUMINANCE8_ALPHA8; // two bytes, max quality @@ -1166,6 +1180,9 @@ void idImage::WritePrecompressedImage() { case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: header.ddspf.dwFourCC = DDS_MAKEFOURCC('D','X','T','5'); break; + case GL_COMPRESSED_RGBA_BPTC_UNORM: + header.ddspf.dwFourCC = DDS_MAKEFOURCC('B','C','7','0'); + break; } } else { header.ddspf.dwFlags = ( internalFormat == GL_COLOR_INDEX8_EXT ) ? DDSF_RGB | DDSF_ID_INDEXCOLOR : DDSF_RGB; @@ -1412,15 +1429,33 @@ bool idImage::CheckPrecompressedImage( bool fullLoad ) { // DG: same if this is a BC7 (BPTC) texture but the GPU doesn't support that // or if it uses the additional DX10 header and is *not* a BC7 texture + bool isBC7 = false; if ( ddspf_dwFourCC == DDS_MAKEFOURCC( 'D', 'X', '1', '0' ) ) { ddsDXT10addHeader_t *dx10Header = (ddsDXT10addHeader_t *)( data + 4 + sizeof(ddsFileHeader_t) ); unsigned int dxgiFormat = LittleInt( dx10Header->dxgiFormat ); - if ( dxgiFormat != 98 // DXGI_FORMAT_BC7_UNORM - || !glConfig.bptcTextureCompressionAvailable ) { - if (dxgiFormat != 98) { - common->Warning( "Image file '%s' has unsupported dxgiFormat %d - dhewm3 only supports DXGI_FORMAT_BC7_UNORM (98)!", - filename, dxgiFormat); - } + if ( dxgiFormat == 98 ) { + isBC7 = true; + } else { + common->Warning( "Image file '%s' has unsupported dxgiFormat %d - dhewm3 only supports DXGI_FORMAT_BC7_UNORM (98)!", + filename, dxgiFormat); + R_StaticFree( data ); + return false; + } + } else if ( ddspf_dwFourCC == DDS_MAKEFOURCC( 'B', 'C', '7', '0' ) + || ddspf_dwFourCC == DDS_MAKEFOURCC( 'B', 'C', '7', 'L' ) ) + { + isBC7 = true; + } + if ( isBC7 && !glConfig.bptcTextureCompressionAvailable ) { + R_StaticFree( data ); + return false; + } + if ( glConfig.bptcTextureCompressionAvailable + && globalImages->image_usePrecompressedTextures.GetInteger() == 2 ) + { + // only high quality compressed textures, i.e. BC7 (BPTC), are welcome + // or uncompressed ones (that have no FOURCC flag set) + if ( !isBC7 && (ddspf_dwFlags & DDSF_FOURCC) != 0 ) { R_StaticFree( data ); return false; } @@ -1494,7 +1529,11 @@ void idImage::UploadPrecompressedImage( byte *data, int len ) { case DDS_MAKEFOURCC( 'R', 'X', 'G', 'B' ): internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; - case DDS_MAKEFOURCC( 'D', 'X', '1', '0' ): // BC7 aka BPTC + case DDS_MAKEFOURCC( 'B', 'C', '7', '0' ): // BC7 aka BPTC - inofficial FourCCs + case DDS_MAKEFOURCC( 'B', 'C', '7', 'L' ): + internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; + break; + case DDS_MAKEFOURCC( 'D', 'X', '1', '0' ): // BC7 aka BPTC - the official dxgi way additionalHeaderOffset = 20; // Note: this is a bit hacky, but in CheckPrecompressedImage() we made sure // that only BC7 UNORM is accepted if the FourCC is 'DX10' From 164af34c04f36e638c81c76cfe5b8ab08b621788 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 8 Apr 2025 06:29:31 +0200 Subject: [PATCH 2/3] Dhewm3SettingsMenu: adjust for last commit, add image_useCompression --- neo/framework/Dhewm3SettingsMenu.cpp | 59 +++++++++++++++++++--------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/neo/framework/Dhewm3SettingsMenu.cpp b/neo/framework/Dhewm3SettingsMenu.cpp index 12394fbf..d5afcfbf 100644 --- a/neo/framework/Dhewm3SettingsMenu.cpp +++ b/neo/framework/Dhewm3SettingsMenu.cpp @@ -1706,8 +1706,9 @@ static int initialMode = 0; static int initialCustomVidRes[2]; static int initialMSAAmode = 0; static int qualityPreset = 0; -static bool initialUsePrecomprTextures = false; -static int initialUseNormalCompr = false; +static int initialUsePrecomprTextures = 0; +static int initialUseCompression = 0; +static int initialUseNormalCompr = 0; static void SetVideoStuffFromCVars() { @@ -1737,7 +1738,8 @@ static void SetVideoStuffFromCVars() qualityPreset = 1; // default to medium Quality } - initialUsePrecomprTextures = globalImages->image_usePrecompressedTextures.GetBool(); + initialUsePrecomprTextures = globalImages->image_usePrecompressedTextures.GetInteger(); + initialUseCompression = globalImages->image_useCompression.GetInteger(); initialUseNormalCompr = globalImages->image_useNormalCompression.GetInteger(); } @@ -1759,7 +1761,10 @@ static bool VideoHasResettableChanges() if ( initialMSAAmode != r_multiSamples.GetInteger() ) { return true; } - if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetBool() ) { + if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetInteger() ) { + return true; + } + if( initialUseCompression != globalImages->image_useCompression.GetInteger() ) { return true; } if ( initialUseNormalCompr != globalImages->image_useNormalCompression.GetInteger() ) { @@ -1786,12 +1791,14 @@ static bool VideoHasApplyableChanges() return true; } - if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetBool() ) { + if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetInteger() ) { return true; } // Note: value of image_useNormalCompression is only relevant if image_usePrecompressedTextures is enabled if ( initialUsePrecomprTextures - && initialUseNormalCompr != globalImages->image_useNormalCompression.GetInteger() ) { + && (initialUseNormalCompr != globalImages->image_useNormalCompression.GetInteger() + || initialUseCompression != globalImages->image_useCompression.GetInteger()) ) + { return true; } @@ -1802,8 +1809,9 @@ static bool VideoHasApplyableChanges() static void ApplyVideoSettings() { const char* cmd = "vid_restart partial\n"; - if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetBool() - || initialUseNormalCompr != globalImages->image_useNormalCompression.GetInteger() ) + if ( initialUsePrecomprTextures != globalImages->image_usePrecompressedTextures.GetInteger() + || initialUseNormalCompr != globalImages->image_useNormalCompression.GetInteger() + || initialUseCompression != globalImages->image_useCompression.GetInteger() ) { // these need a full restart (=> textures must be reloaded) cmd = "vid_restart\n"; @@ -1821,7 +1829,8 @@ static void VideoResetChanges() r_fullscreenDesktop.SetBool( initialFullscreenDesktop ); r_multiSamples.SetInteger( initialMSAAmode ); - globalImages->image_usePrecompressedTextures.SetBool( initialUsePrecomprTextures ); + globalImages->image_usePrecompressedTextures.SetInteger( initialUsePrecomprTextures ); + globalImages->image_useCompression.SetInteger( initialUseCompression ); globalImages->image_useNormalCompression.SetInteger( initialUseNormalCompr ); } @@ -1966,9 +1975,11 @@ static void DrawVideoOptionsMenu() } AddCVarOptionTooltips( r_multiSamples, "Note: Not all GPUs/drivers support all modes, esp. not 16x!" ); - bool usePreComprTex = globalImages->image_usePrecompressedTextures.GetBool(); - if ( ImGui::Checkbox( "Use precompressed textures", &usePreComprTex ) ) { - globalImages->image_usePrecompressedTextures.SetBool(usePreComprTex); + int usePreComprTex = globalImages->image_usePrecompressedTextures.GetInteger(); + if ( ImGui::Combo( "Use precompressed (.dds) textures", &usePreComprTex, + "No, only uncompressed\0Yes, no matter which format\0Only if high quality (BPCT/BC7)\0" ) ) + { + globalImages->image_usePrecompressedTextures.SetInteger(usePreComprTex); // by default I guess people also want compressed normal maps when using this // especially relevant for retexturing packs that only ship BC7 DDS files // (otherwise the lowres TGA normalmaps would be used) @@ -1977,22 +1988,32 @@ static void DrawVideoOptionsMenu() } } const char* descr = "Use precompressed (.dds) textures. Faster loading, use less VRAM, possibly worse image quality.\n" - "May also be used by highres retexturing packs for BC7-compressed textures (there image quality is not impaired)"; + "May also be used by highres retexturing packs for BC7-compressed textures (there image quality is not noticeably impaired)"; AddCVarOptionTooltips( globalImages->image_usePrecompressedTextures, descr ); - ImGui::BeginDisabled( !usePreComprTex ); + int useCompression = globalImages->image_useCompression.GetInteger(); + if ( ImGui::Combo( "Compress uncompressed textures on load", &useCompression, + "Leave uncompressed (best quality)\0Compress with S3TC (aka DXT aka BC1-3)\0Compress with BPCT (BC7)\0" ) ) + { + globalImages->image_useCompression.SetInteger(useCompression); + } + descr = "When loading non-precompressed textures, compress them so they use less VRAM.\n" + "Uncompressed has best quality. BC7 has better quality than S3TC, but may increase loading times"; + AddCVarOptionTooltips( globalImages->image_useCompression, descr ); + + ImGui::BeginDisabled( !usePreComprTex && !useCompression ); bool useNormalCompr = globalImages->image_useNormalCompression.GetBool(); - ImGui::Dummy( ImVec2(16, 0) ); - ImGui::SameLine(); - if ( ImGui::Checkbox( "Use precompressed normalmaps", &useNormalCompr ) ) { + if ( ImGui::Checkbox( "Use compressed normalmaps", &useNormalCompr ) ) { // image_useNormalCompression 1 is not supported by modern GPUs globalImages->image_useNormalCompression.SetInteger(useNormalCompr ? 2 : 0); } if ( usePreComprTex ) { - const char* descr = "Also use precompressed textures for normalmaps"; + const char* descr = "Also use precompressed textures for normalmaps or compress them on load.\n" + "Uncompressed often has better quality, but uses more VRAM.\n" + "When using highres retexturing packs, you should definitely enable this."; AddCVarOptionTooltips( globalImages->image_useNormalCompression, descr ); } else { - AddTooltip( "Can only be used if precompressed textures are enabled!" ); + AddTooltip( "Can only be used if (pre)compressed textures are enabled!" ); } ImGui::EndDisabled(); From 1fa2d7891d15601ea74a2a6cb9832355a3d5b114 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Wed, 9 Apr 2025 23:06:07 +0200 Subject: [PATCH 3/3] Document image_use*compress* 2 in Configuration.md and Changelog --- Changelog.md | 12 ++++++++---- Configuration.md | 26 +++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1584ebc9..d4b0fdb0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,11 +15,15 @@ Note: Numbers starting with a "#" like #330 refer to the bugreport with that num a quarter of the VRAM (TGA: 4 bytes per pixel, BC7: 1 byte per pixel) and loading *significantly* faster because mipmaps are contained and don't have to be generated on load. If you have such DDS files and want to use them (instead of TGAs), you must set - `image_usePrecompressedTextures 1` and `image_useNormalCompression 1`. + `image_usePrecompressedTextures 1` and `image_useNormalCompression 2`. + You can also set `image_usePrecompressedTextures 2`, then dhewm3 will only load .dds textures + with BC7 data - if it only finds an old one (with S3TC/DXT/BC-13 compression) it will use the + uncompressed TGA textures instead. If you want to *create* .dds files with BC7 texture data, you can use any common texture compression - tool, **except** for **normalmaps**, those must be created with my [**customized bc7enc**](https://github.com/DanielGibson/bc7enc_rdo) - with the `-r2a` flag! *(Because Doom3 requires that normalmaps have the red channel moved into the - alpha channel, id confusingly called that "RXGB", and AFAIK no other tool supports that for BC7.)* + tool, **except** for **normalmaps**, those must be created with my + [**customized bc7enc**](https://github.com/DanielGibson/bc7enc_rdo) with the `-r2a` flag! + *(Because Doom3 requires that normalmaps have the red channel moved into the alpha channel, + id confusingly called that "RXGB", and AFAIK no other tool supports that for BC7.)* Just like the old DXT .dds files, they must be in the `dds/` subdirectory of a mod (either directly in the filesystem or in a .pk4). * Support SDL3 (SDL2 and, to some degree, SDL1.2 are also still supported) diff --git a/Configuration.md b/Configuration.md index c561ce0e..b99266f3 100644 --- a/Configuration.md +++ b/Configuration.md @@ -233,6 +233,29 @@ This can be configured with the following CVars: - `r_glDebugContext` Enable OpenGL debug context and printing warnings/errors from the graphics driver. Changing that CVar requires a `vid_restart` (or set it as startup argument) +- `image_usePrecompressedTextures` can now also be set to `2`. + - `1` Use precompressed textures (.dds files), no matter which format they're in + - `2` Only use precompressed textures if they're in BPTC (BC7) format, which has better quality + than the old ones shipped with Doom3 that use S3TC/DXT. If no BPTC/BC7 (or uncompressed) .dds file + is found, fall back to uncompressed .tga. Especially useful when using high-res texture + packs that use BC7 compression. + - `0` Don't use precompressed (.dds) textures but the uncompressed ones (.tga) +- `image_useCompression` can now also be set to `2`. + - `1` When loading an uncompressed (.tga) texture, let the GPU (driver) compress it to S3TC/DXT + so it uses less VRAM (Video memory on the GPU) but doesn't look as good as leaving it + uncompressed or using precompressed textures, if available. + **Note:** IMHO this only makes sense together with `image_usePrecompressedTextures 1`, + so .dds textures are preferred (they should have better encoding quality than what the GPU + driver produces on the fly *and* load faster) and only if a texture doesn't exist as .dds, + the uncompressed TGA is loaded and then compressed on upload. + - `2` When loading an uncompressed (.tga) texture, let the GPU (driver) compress it to BPTC/BC7 + (if the GPU supports it). Has better quality than S3TC/DXT but loading textures might take longer. + *Probably only makes sense with high-res texturing packs that don't use BPTC/BC7, because + if your GPU supports BPTC, it most probably has enough VRAM for the uncompressed original TGA + textures, which look at least as good, but for high resolution textures saving VRAM by + compressing on load can help)*. + - `0` Don't compress uncompressed textures when loading them - best quality, but uses more VRAM. + - `s_alReverbGain` reduce strength of OpenAL (EAX-like) EFX reverb effects, `0.0` - `1.0` (default `0.5`) - `s_alHRTF` Enable [HRTF](https://en.wikipedia.org/w/index.php?title=Head-related_transfer_function) for better surround sound with stereo **headphones**. `0`: Disable, `1`: Enable, `-1`: Let OpenAL decide (default). @@ -243,7 +266,8 @@ This can be configured with the following CVars: including the current HRTF state (if supported by your OpenAL version). - `s_alOutputLimiter` Configure OpenAL's output-limiter which temporarily reduces the overall volume when too many too loud sounds play at once, to avoid issues like clipping. `0`: Disable, `1`: Enable, `-1`: Let OpenAL decide (default) -- `s_scaleDownAndClamp` Clamp and reduce volume of all sounds to prevent clipping or temporary downscaling by OpenAL's output limiter (default `1`) +- `s_scaleDownAndClamp` Clamp and reduce volume of all sounds to prevent clipping or temporary + downscaling by OpenAL's output limiter (default `1`) - `imgui_scale` Factor to scale ImGui menus by (especially relevant for HighDPI displays). Should be a positive factor like `1.5` or `2`; or `-1` (the default) to let dhewm3 automatically