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

Heretic: Opacity of Transparent HUD Elements not correct in TrueColor #1269

Open
Noseey opened this issue Feb 5, 2025 · 7 comments · May be fixed by #1272
Open

Heretic: Opacity of Transparent HUD Elements not correct in TrueColor #1269

Noseey opened this issue Feb 5, 2025 · 7 comments · May be fixed by #1272

Comments

@Noseey
Copy link

Noseey commented Feb 5, 2025

@fabiangreffrath @JNechaevsky

Background

Version of Crispy Doom: 7.0.0 (master 05.02.2025 for translucent Crispyhud)

Operating System and version: Windows 10

Game: Heretic

Any loaded WADs and mods (please include full command line): -

Bug description

Observed behavior:

When implementing the transparent Crispyhud for Heretic, I noticed that it has a very low opacity in Truecolor mode. Here some screenshots for comparison:

Truecolor: Heretic Crispyhud Artibox:
Image

Palette: Heretic Crispyhud Artibox (transpucent patch):
Image

.. while the Fullscreen Artibox opacity is too high in true-color:

Truecolor: Heretic Fullscreen Artibox:
Image

Palette: Heretic Fullscreen Artibox (alt translucent patch):
Image

Expected behavior:

The Fullscreen Artibox should have less opacity than the Crispyhud one, like it can be seen in the Palette mode. In other words: The drawtinttab should have more opacity than the drawalttinttab.

In the Code, I think it comes down to these blending functions:

i_truecolor.c:

// [crispy] TINTTAB blending emulation, used for Heretic and Hexen
const uint32_t I_BlendOverTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x60); // 96 (38% opacity)
}

// [crispy] More opaque ("Alt") TINTTAB blending emulation, used for Hexen's MF_ALTSHADOW drawing
const uint32_t I_BlendOverAltTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x8E); // 142 (56% opacity)
}

I think those work fine for Hexen, but not for Heretic, since the tinttab in Heretic has the dominant color on the Rows instead of Columns:
Image

My suggestion would be to swap those opacity values (38%, 56%) in case of Truecolor-Heretic, maybe that already gets it close enough to the Palette one. If not, it might need a separate set of opacity-values.

What do you think?

@Noseey
Copy link
Author

Noseey commented Feb 5, 2025

One remark: This finding was based upon the HUD elements. I didn't check if the same would apply also e. g. for the DrawTLColumn, I will have a closer look there.

Edit: So the Translucent Column drawing works in alternative mode for Palette:

r_draw.c:
Image

.. and since the BlendOverTinttab is assigned here (currently working like the alternative translucency), this part seems fine.
Image

Just note, that if the above suggestion to swap it for Heretic is considered, this blend function assignment is impacted aswell.

@Noseey Noseey changed the title Heretic: Opacity of Transparent Elements not correct in TrueColor Heretic: Opacity of Transparent HUD Elements not correct in TrueColor Feb 5, 2025
@JNechaevsky
Copy link
Collaborator

😟 I'm out of ideas how to make it proper. TrueColor support for Heretic was implemented before Hexen, and it's normal (non-alt) translucency was picked after some joint testing, but looks likes I have missed alt-one.

Another problem is - we don't have a formulas to set a proper percent for opacity, so...

Probably easiest way will be to have a separate I_BlendOverAltTinttab function with different values?

@Noseey
Copy link
Author

Noseey commented Feb 6, 2025

😟 I'm out of ideas how to make it proper. TrueColor support for Heretic was implemented before Hexen, and it's normal (non-alt) translucency was picked after some joint testing, but looks likes I have missed alt-one.

I wouldn't say that the alternative one is missed, rather that it requires a swapped behavior to Hexen. Currently in truecolor Heretic, the alt one has too much opacity, while the normal one has too little. In terms of functions, here an example how it could be corrected:

i_truecolor.c:

// [crispy] TINTTAB blending emulation, used for Hexen
const uint32_t I_BlendOverHexTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x60); // 96 (38% opacity)
}

// [crispy] More opaque ("Alt") TINTTAB blending emulation
const uint32_t I_BlendOverHexAltTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x8E); // 142 (56% opacity)
}

// [crispy] TINTTAB blending emulation, used for Heretic
const uint32_t I_BlendOverHerTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x8E); // 96 (56% opacity)
}

// [crispy] Less opaque ("Alt") TINTTAB blending emulation
const uint32_t I_BlendOverHerAltTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, 0x60); // 142 (38% opacity)
}

Another problem is - we don't have a formulas to set a proper percent for opacity, so...

Yeah, getting it 100% right might be another topic. A swap would be a start to get it closer to vanilla, in my opinion.

Probably easiest way will be to have a separate I_BlendOverAltTinttab function with different values?

This could be one way, like the abstract posted above. Another alternative could be to have global variables with the opacity being initialized differently based upon the game and used for calling the I_BlendOver functions.

// [crispy] TINTTAB blending emulation, used for Hexen and Heretic
const uint32_t I_BlendOverHexTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, He_Normal_Opacity);
}

// [crispy] ("Alt") TINTTAB blending emulation, used for Hexen and Heretic
const uint32_t I_BlendOverHexAltTinttab (const uint32_t bg, const uint32_t fg)
{
    return I_BlendOver(bg, fg, He_Alt_Opacity); 
}

One could also alter the returns of the functions based upon the active game.

@Noseey
Copy link
Author

Noseey commented Feb 8, 2025

I have created a first suggestion based upon the global variables approach:
master...Noseey:crispy-doom:Heretic_TC_Transparency_Fix

@fabiangreffrath
Copy link
Owner

I have created a first suggestion based upon the global variables approach: master...Noseey:crispy-doom:Heretic_TC_Transparency_Fix

Thanks for that! However, you know, I'm a friend of function pointers and generally prefer them over global variables. So, you could keep the current I_BlendOverTinttab()/I_BlendOverAltTinttab() functions with the constant opacity values but under different names, and let an init function which takes the gamemission as a parameter (c.f. d_mode.h) decide which of both functions the actual I_BlendOverTinttab()/I_BlendOverAltTinttab() function pointers point to.

@Noseey
Copy link
Author

Noseey commented Feb 10, 2025

... and let an init function which takes the gamemission as a parameter (c.f. d_mode.h) decide which of both functions the actual I_BlendOverTinttab()/I_BlendOverAltTinttab() function pointers point to.

Would it be acceptable to modify V_LoadTintTable to do so? It would - depending on the compile-switch - either load the tinttable or assign those functions for the blending (which acts like a "tinttable"-selection for truecolor).

@fabiangreffrath
Copy link
Owner

Could you prepare a PR, please. It's easier to discuss actual code changes than some written ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants