halflife icon indicating copy to clipboard operation
halflife copied to clipboard

[HL/HL:BS/HL:OF/TFC/DOD/CS/RICOCHET] gl_overbright

Open teasouse opened this issue 5 years ago • 7 comments

Is it really so difficult to make working this in OpenGL? I know many people are missing the old graphics. Without overbright, the levels look wrong, the skyboxes look too bright compared to the levels.

teasouse avatar Jul 25 '18 11:07 teasouse

If the engine finds the OpenGL extension string of GL_ARB_multitexture, it will make use of hardware multitexturing capabilities to draw lightmaps and detail textures. Unfortunately, this breaks the functionality of gl_overbright, and the only way to restore it is to manually disable the OpenGL extension at the driver level. The lacking functionality of this feature is often incorrectly attributed to a total removal in the Steam version of the game, but the reason for its presence in older versions of the game is that the engine instead checked for an OpenGL extension string named GL_SGIS_multitexture, and because this string is obsolete and not reported in modern graphics drivers, the engine assumes that multitexturing is not supported. A simple option to toggle multitexturing independently of its driver availability in the game would eliminate this problem.

Enokilis avatar Apr 24 '19 19:04 Enokilis

Workaround: https://www.vogons.org/viewtopic.php?f=8&t=63930

Not perfect, but it works.

Matthaiks avatar Apr 26 '19 17:04 Matthaiks

That seems very cool, also it looks like it fixes issues of low fps with dynamic lights like flashlight, etc.

Quote from that link: https://www.vogons.org/viewtopic.php?f=8&t=63930

As a sort of experiment, using GLIntercept (https://github.com/dtrebilco/glintercept), and using the command gl_dump in console to get a list of OpenGL extensions that the game detected, I attempted to remove a number of extensions until I came across one: "GL_ARB_multitexture". By removing this specific extension from being detected and used by the game, not only did it seemingly fix the performance around the lights, it also fixes gl_overbright so that it actually works on maps using that feature. Kind of surprised since overbrights don't normally function in the GL renderer.

rtxa avatar Apr 26 '19 20:04 rtxa

I did a little research to figure out why overbright is forced off when multitexture support is available.

I don't think overbright itself is the problem here, rather when you have multitexture support (needed for detail textures) it disables overbright as well as texture sorting.

Overbright relies on texture sorting to function, whereas detail textures work by immediately drawing textures instead of sorting visible surfaces by texture and then drawing them all.

This page about the gl_texsort cvar (doesn't exist as a cvar in GoldSource) seems to explain why: https://quakewiki.org/wiki/Gl_texsort

The only problem with turning this on is that it also disables multitexture, forcing the engine to render the lighting in a separate pass.

In Quake 1 and GoldSource with sorting disabled each visible surface is drawn followed immediately by the lightmap, which is blended with the surface itself: https://github.com/id-Software/Quake/blob/bf4ac424ce754894ac8f1dae6a3981954bc9852d/WinQuake/gl_rsurf.c#L467-L488

In GoldSource the order is:

  • Diffuse texture
  • Light map texture (or filter texture if you call pfnSetFilterMode, which replaces all lightmaps with a single color multiplier)
  • Detail texture (if present)

With sorting enabled every visible surface is added to a list of all surfaces using the same texture. Those lists are all drawn, the lightmaps are added to another set of lists based on the lightmap texture, and then those lightmaps are also drawn.

The difference between those two is that when sorting is enabled entire lightmap textures are updated before being drawn, whereas with sorting disabled it updates one lightmap in a texture and draws it.

The code that disables texture sorting dates back to Quake 1: https://github.com/id-Software/Quake/blob/bf4ac424ce754894ac8f1dae6a3981954bc9852d/WinQuake/gl_rmisc.c#L196-L197

GoldSource just adds a second line to disable overbright as well.

This comment is probably relevant:

Systems that have fast state and texture changes can just do everything as it passes with no need to sort

So it all boils down to the engine handling lighting in a way that makes overbright not mix well when it's done with sorting disabled.

I did a test by patching the engine to always have overbright enabled, but to leave texture sorting disabled. Even with the overbright code paths enabled it still didn't work, so sorting has to be enabled for overbright to function. The code that handles overbright is used when sorting is disabled, but evidently it's not applying the effects. There must be some code that only works when sorting is enabled.

I think a proper fix would be to update lightmaps first and then drawing everything. That way the lighting effects are already there regardless of how it draws the surfaces. This may require a second pass over the visible entities list as well to update BSP model lightmaps. Way back when this code as written (late 1996-early 1997) the extra set of texture binds calls would've mattered, but now i don't think it'll make any significant difference.

Of course this may break mods that use OpenGL calls to manipulate what the engine draws, no way to know that for sure.

A solution could be to make a separate remastered engine that fixes this (and uses modern OpenGL).

It's worth noting that the engine uses glActiveTextureARB, which doesn't define an absolute minimum number of texture units (the engine requires at least 3 to use detail textures). glActiveTexture, the version that exists from OpenGL 2 onwards is documented to have at least 80. I think every GPU made in the last decade supports at least 3.

SamVanheer avatar Sep 29 '22 18:09 SamVanheer

I did a little research to figure out why overbright is forced off when multitexture support is available.

I'm pretty sure the lack of overbright functionality with multitexturing comes down to OpenGL limitations. The basic ARB multitexture extension does not have all of the blending modes that exist in the base OpenGL specification, namely glBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ). As far as I know, the only way to achieve the same effect in one rendering pass is to use the texture combiner extension, as I did here. gl_overbright

Enokilis avatar Oct 01 '22 08:10 Enokilis

Makes sense. I suppose it would be easier to implement in a shader then since you can control the blending more precisely with any number of textures.

SamVanheer avatar Oct 01 '22 10:10 SamVanheer

Makes sense. I suppose it would be easier to implement in a shader then since you can control the blending more precisely with any number of textures.

It's also worth noting that gl_overbright never worked well to begin with. In the software renderer, all lit surfaces are affected, but when activated in the accelerated renderer, vertex-lit objects remain capped at 100% brightness, due to how this effect relies on blending two passes together. This creates an undesirable disparity.

There are also certain quirks in how the engine processes lightmaps with consequences for the visual fidelity. When gl_overbright is disabled, the engine tries to compensate by boosting the brightness of the lightmaps at the cost of dynamic range. This behavior was not present in the early release versions of the game. The VHLT map compiler takes this modern behavior into consideration at the detriment of restored overbright functionality.

Enokilis avatar Oct 01 '22 12:10 Enokilis