Halflife: [OpenGL] Non-power of two textures are getting re-scaled.

Created on 6 Sep 2015  路  26Comments  路  Source: ValveSoftware/halflife

When playing the game in OpenGL, textures that aren't sized in a power of two (32, 64, 128, etc) are being scaled down to the nearest Po2 number. For example, this medkit texture which dimensions are 64x96:
firstaid
(Note how the wall texture behind it isn't getting re-sampled.)

I realize that this is a leftover bug from Quake's OpenGL port, but some community-made Quake source ports (like FitzQuake) have fixed this issue. I would really appreciate a patch for this, as it makes the game look very rough, and playing the game in software mode is unbearable.

Thanks.

鈥擲haun

Most helpful comment

Hey @SamVanheer, this should be fixed in the latest HL1/OpFor/TFC/CS betas with NPOT textures used and the default texture filters being GL_NEAREST if the support is available.

All 26 comments

If you want the game to look like software mode without actually using software mode you can type 'GL_texturemode GL_Nearest' into the console to remove texture filtering entirely, I'm also not sure why that is happening since when I go to that very wall in Anomalous Materials it appears to have texture filtering as OpenGL should filter all world textures in the game.

I actually did turn off texture filtering in the gif above to show the issue more clearly. The problem isn't the filter, it's that textures are literally being _scaled down_ resulting in lower resolution textures and non-uniform pixel sizes.

I'd also like to say that I've since discovered a cvar, "gl_round_down" that controls how the game handles non-Po2 textures, but it's not 100%. By default it's 3, but even when set to 0 there is still some detail lost:
po2

Playing this on Ubuntu 14.04 and 15.10 I also noticed this because I'm playing the game with "gl_texturemode GL_NEAREST". Just because don't like the blurry textures that much. (so nice to have this option! and valve please don't remove it).

However I came across this also, that some signs etc. are barely readable. This gif by ShaunNoWay shows this perfectly: https://cloud.githubusercontent.com/assets/14033754/9702906/89563e54-543e-11e5-852c-a03d56616ee1.gif

@ShaunNoWay by the way, thanks for gl_round_down hint! I found there is also "gl_dither" -- sounds like it could be useful. gl_fog also. I don't know.

PS: Is someone at Valve actually still looking at this bugtracker?

If I remember correctly all you need to do is a trivial feature check for non-power-of-2 textures (available for at least 10 years now across the board). There is no fancy features involved. Even just deleting the down-scaling code might work. I'd fix it myself on a quiet week-end. ;-)

This is still an issue and it makes me so very very sad. :(

It's in the hw.dll I assume, which is not open sourced. Gotta wait and see if it will eventually be "declassified". You can imagine that - as happened with classics like Doom or Quake - there are enthusiasts out there that are just waiting to throw the latest tech into Half-Life's engine. (Although its colored radiosity lighting is already pretty "rad" in terms of indoor realism.)

@mikela-valve any chance we could get an option to disable this behavior if the card supports non-power of two textures? Half-Life was designed with NPOT textures in mind, so this would restore original behavior.

See also:
https://stackoverflow.com/questions/3046597/how-to-detect-if-opengl-card-supports-non-power-of-2
https://www.khronos.org/opengl/wiki/NPOT_Texture
https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_non_power_of_two.txt

Checking the SDL2 source code for 2.0.8 shows that the default GL context version is 2.1, or 2.0 for the Raspberry PI (not applicable here for the moment) and ES2, or 1.1 for ES.

GoldSource uses regular GL so it uses 2.1 here, verified by reverse engineering the SDL2 library:

      *(_DWORD *)(v7 + 312) = 2;
      *(_DWORD *)(v7 + 316) = 1;

These offsets correspond to the major and minor version, as seen in SDL_GL_SetAttribute:

        case 0x11u:
          *(_DWORD *)(dword_DD5CC + 312) = a2;
          result = 0;
          break;
        case 0x12u:
          *(_DWORD *)(dword_DD5CC + 316) = a2;
          result = 0;
          break;

SDL_GLattr constants SDL_GL_CONTEXT_MAJOR_VERSION (17, or 0x11) and SDL_GL_CONTEXT_MINOR_VERSION (18, or 0x12) are these values.

The engine is implicitly using a 2.1 or higher context already since the attributes for major and minor are not set by the engine in CGame::CreateGameWindow.

Since 2.0 and higher are always supposed to support NPOT textures (with the exception of 2 series of old video cards released 15+ years ago) this shouldn't introduce any system requirements changes. Since it should be a video option this would not break support for those cards either.

It may also be a good idea to add an option to disable texture resizing altogether, and maybe the resampling that results in blurring and transparent pixels (the blue color seen in { textures, sprites, etc) affecting opaque pixels.

This would allow textures to look just as they do in Software mode, ensuring that the game will be visually identical to the original release (with the exception of gl_overbright being disabled).

@SamVanheer I was actually already checking this out the other day. It looks like we already have some code in that is disabled to check for NPOT textures so what I'm thinking I'll do is re-enable those checks and change the default min/mag filters to nearest if the NPOT support is available:

image

Could you possibly post an image showing resampling interacting with transparency effects so I know what to look for if I dig into that as well?

Looks like that's an issue with the textures themselves rather than the resampling.

Here's an example:
https://cdn.discordapp.com/attachments/291678871856742400/567814715359756299/70_20190416225114_1.png
https://cdn.discordapp.com/attachments/291678871856742400/567814747555102730/70_20190416225054_1.png

This texture has blue in it as a result of some blending done in an image editor, it's not affected by resampling.

Here's an example of how turning off NPOT resizing, gl_round_down and resampling can affect the look of a texture:
https://i.imgur.com/zsYcbgO.png
https://i.imgur.com/Xtkdx3B.png

The black was originally blue, but the engine changes the color. The resampling can result in this black being mixed in since it picks colors from the area around a pixel. You can see the black on the edges on the grate texture in the first screenshot.

Disabling the resampling will fix that and make the texture sharper as a result.

The NPOT changes sound good, i've heard people say they want to have the OpenGL version look that way.

Hey @SamVanheer, this should be fixed in the latest HL1/OpFor/TFC/CS betas with NPOT textures used and the default texture filters being GL_NEAREST if the support is available.

I can confirm that, some screenshots here: https://imgur.com/a/6qDmwsg

It may be a good idea to have some config file used to set the default settings for each game, like cfg/defaultgraphics.cfg. Games can then override this cfg file to initialize everything. It should execute before any user cfg files so those files can override the setting.

CS 1.6, tested on de_dust2_2x2 and de_dust2
All far textures "flicker" when player moves.

Aliasing due to no mip-mapping?

Looks like it, which isn't surprised since I should have set a min filter with mipmapping rather than setting both the min and mag filters to GL_NEAREST. I still get a bit of flickering with nearest mipmapping so probably going with GL_NEAREST_MIPMAPPING_LINEAR is the best option.

I just loaded beta for others fixes and noticed the difference with this very cool I actually like the fine detail, I was using GL_NEAREST I switched to GL_NEAREST_MIPMAP_LINEAR and it doesn't flicker now.

@mikela-valve the game has always defaulted to filtered textures in OpenGL, and this is how most people would have played the game, so for the sake of keeping the original vision intact I think it is wise to keep it at that setting. The non-PO2 fix is much appreciated however, as it shows the textures closer to how the texture artists originally intended it to be seen.

gl_texturemode gl_linear_mipmap_linear would be the preferable setting.

May I ask if there are plans to put back the thibgs that disappeared from the game when it came to steam? Camera tilt and more nuanced viewmodel tilting for example. There are a lot of animation bugs too that I believe are at least partially caused by framerates exceeding 70-something fps?

What I like about this is when you're shooting you can really see where the bullet decals are hitting with accuracy not just some blurred decal, makes compensating recoil easier.

Based on user feedback i recommend changing the default filter settings back to what they were before because the vast majority of players prefer those settings. The current settings also seem to be causing Z fighting that doesn't occur with other filtering settings:
https://cdn.discordapp.com/attachments/206490370605973504/569574988110102579/zfighting.jpg

Based on user feedback i recommend changing the default filter settings back to what they were before because the vast majority of players prefer those settings. The current settings also seem to be causing Z fighting that doesn't occur with other filtering settings:
https://cdn.discordapp.com/attachments/206490370605973504/569574988110102579/zfighting.jpg

Hey, which map is that? For me, it seems more like bad mapping (bad level design), just like some lamps in crossfire.

Based on user feedback i recommend changing the default filter settings back to what they were before because the vast majority of players prefer those settings. The current settings also seem to be causing Z fighting that doesn't occur with other filtering settings:
https://cdn.discordapp.com/attachments/206490370605973504/569574988110102579/zfighting.jpg

Hey, which map is that? For me, it seems more like bad mapping (bad level design), just like some lamps in crossfire.

c2a5 (Surface Tension), far end of the dam. I checked it myself and you're right, it happens with all filter settings.

I concur, next release I'll have it back to the default of GL_LINEAR_MIPMAP_LINEAR/GL_LINEAR.

Changed back to GL_LINEAR_MIPMAP_LINEAR/GL_LINEAR in beta 'Exe build: 11:12:36 May 21 2019 (8244)'.

Closing as fixed.

Sorry to bump a closed issue, but I just want to make sure I understand correctly how the fix worked.

I'd also like to say that I've since discovered a cvar, "gl_round_down" that controls how the game handles non-Po2 textures, but it's not 100%. By default it's 3, but even when set to 0 there is still some detail lost:

The default still is 3 (I installed it with the recent 2-month free weekend), and gl_round_down still works. Was the fix to change gl_round_down to not lose any detail if the GPU supports NPOT textures, as opposed to the prior minimal loss that Shaun showed? Thanks for the clarification.

Was this page helpful?
0 / 5 - 0 ratings