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

Render GUIs on a texture, then render that texture on screen #1874

Merged

Conversation

ivan-mogilko
Copy link
Contributor

@ivan-mogilko ivan-mogilko commented Dec 28, 2022

Resolves #1838 and will potentially help #1837 after merged/ported to ags4.

After implementing rendering GUI controls as separate textures (see #988 and #1393 for details), it turned out that the implementation has a serious mistake: any additional visual effect applied to a whole GUI, such as Transparency, would apply incorrectly, as controls would blend with GUI background using same effect, producing different visual result.

I guess there may be different approaches for resolving this problem. But we also assume that in the future GUI may be assigned more various properties, such as rotation (already exists in ags4), which makes it more difficult to clip controls to GUI borders on screen, or custom shaders, which would be expected to be applied to GUI & controls in whole, while each control might also have its own individual effect, making things more complicated.

Therefore the chosen solution is to render whole GUI on a texture and then render that texture on screen. This is kind of similar in logic to what is done in software rendering, except still done as a scene render by GPU, without bitmap operations.

Additionally, same technique may be used later for anything, if necessary (maybe for room viewports, if we decide to support translucent viewports sorted among GUIs, etc).

What this PR includes:

  • Direct3D and OpenGL renderers support creating a DDB object (texture) with a purpose of being used as a render target.
  • Both support rendering a Sprite Batch to a custom render target, instead of a backbuffer. This resets all parent transforms for that batch, starting clean on a new target, but all the nested batches will be also drawn on same render target, and have merged parent-child transforms.
  • In "draw controls as textures" mode engine will now render GUIs each on its own texture buffer, then render resulting buffers as common sprites on screen. The GUI parent transparency will be applied to that final buffer (not the contents).
  • For Direct3D we have to reset all these buffer textures when changing display mode, unfortunately. This is required for D3D to be able to reset its mode. They will be recreated on fly during the very next game redraw.

@ivan-mogilko ivan-mogilko added this to the 3.6.0 milestone Dec 28, 2022
@ivan-mogilko ivan-mogilko force-pushed the 360--guitexturerenderfix4 branch 2 times, most recently from b1c8371 to a96406a Compare December 28, 2022 19:57
@ivan-mogilko
Copy link
Contributor Author

ivan-mogilko commented Dec 30, 2022

Update on this: currently there are at least 2 known errors in OpenGL renderer:
1. GUI contents are always drawn 1x1 pixels down-left.
2. GUI contents are missing (either not drawn, or draw offscreen) in "render sprites at screen resolution" mode (which is quite strange, since the gui contents are not drawn on screen directly anymore anyway).

EDIT: error 2 fixed now.
EDIT: error 1 seem to be fixed now.

@ivan-mogilko ivan-mogilko force-pushed the 360--guitexturerenderfix4 branch from 01defe8 to e6c5550 Compare December 30, 2022 23:39
@ericoporto
Copy link
Member

ericoporto commented Dec 31, 2022

Hey, this works for me! Tested and both error 1 and 2 seem to be fixed indeed! :)

I think you fixed the caveat you mention in #1837 , on item 1 , about rendering at screen res.

@ivan-mogilko
Copy link
Contributor Author

I need to tidy (squash) the commits again, and there's also one logical mistake about switching render targets that has to be fixed (it is not seen in the current setup, but may surface if there's more complex batch configuration).

I think you fixed the caveat you mention in #1837 , on item 1 , about rendering at screen res.

No, I did nothing in regards to that.

@ivan-mogilko ivan-mogilko force-pushed the 360--guitexturerenderfix4 branch from 034a529 to 173bdee Compare December 31, 2022 22:33
This lets apply additional effects, such as transparency or rotation, to the whole GUI, not worrying about visual inconsistencies or correct content clipping.
There are two problem that we have:

1. The texture which we render to also must have a valid alpha channel in the end (unlike the final backbuffer). Therefore we must make sure that it retains a sum of alphas of all the sprites drawn on top of it.
See: https://stackoverflow.com/questions/27929483/directx-render-to-texture-alpha-blending/27932112#27932112

2. The resulting texture pixels will contain colors (RGB components) already multiplied by alpha ("premultiplied alpha"). If we draw this texture onto screen using default blend op, then its source colors will again be multiplied by its alpha, producing incorrect result (source colors will look "dimmer"). Therefore we also need to use a special blend op for this, which takes source RGB as-is, but still uses src alpha to correctly blend with the dest RGB.
Oh, and it must also account for optional extra transparency.
This may be a temporary solution, but it's necessary, because otherwise engine will fail later, with a seemingly unrelated error, which will be harder to diagnose.
@ivan-mogilko ivan-mogilko force-pushed the 360--guitexturerenderfix4 branch from 173bdee to 14eb84c Compare January 1, 2023 13:24
@ivan-mogilko ivan-mogilko merged commit 1effe94 into adventuregamestudio:master Jan 1, 2023
@ivan-mogilko ivan-mogilko deleted the 360--guitexturerenderfix4 branch January 1, 2023 21:11
@ivan-mogilko
Copy link
Contributor Author

I wanted to do some additional refactor, but met couple of difficulties. So, I'll merge this pr first and make another attempt on refactor bit later.

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

Successfully merging this pull request may close these issues.

Transparent GUI's controls are incorrectly blending with the parent GUI
2 participants