TASEmulators / BizHawk

BizHawk is a multi-system emulator written in C#. BizHawk provides nice features for casual gamers such as full screen, and joypad support in addition to full rerecording and debugging tools for all system cores.
http://tasvideos.org/BizHawk.html
Other
2.14k stars 380 forks source link

[2.10 rc1] Opacity in gui.drawRectangle not working as expected #4043

Open Brian0255 opened 2 hours ago

Brian0255 commented 2 hours ago

Summary

This is a bit hard to describe, but when one rectangle is drawn over another, the overlapped area will draw with full opacity instead of "blending" like previously if the opacity is less than 0xFF.

Repro

  1. Load an NDS ROM
  2. Load a Lua script with the following code:
    
    client.SetGameExtraPadding(0, 0, 199, 0)

gui.drawRectangle(257, 50, 150, 100, 0xFF606060, 0xFF606060) gui.drawRectangle(270, 40, 100, 50, 0x80FF0000, 0x80FF0000)



### Host env.
[//]: # "List the computers you've found the bug with. If there's a version that doesn't have the bug, please put that in too. Here are some examples:"
- BizHawk 2.10 rc1; Win11; AMD/NVIDIA

[//]: # "(screenshots, if applicable)"
### Screenshots
<img src="https://github.com/user-attachments/assets/bf9e8b47-8842-4e52-9817-32534543a750" width="400">
<br />
<br />

For a more practical example, this is how it was used in another dev's Pokémon tracking Lua script (and how it was affected):

<img src="https://github.com/user-attachments/assets/b2d30a7d-4042-494f-9e51-f10cbc2b13a1" width="700">

[//]: # "That's it! If you'd like to help more, you could try a dev build (see Testing in the readme) or an older release. Click submit now and you can edit it later."
CasualPokePlayer commented 2 hours ago

This is something of a tricky situation, the code currently was some kind of approximate to mimic GDI+'s blending based on some other lua scripts, but it seems to be very wrong in various cases.

Some stack overflow threads seem to indicate the formula is something much more complicated and evil: https://stackoverflow.com/a/2223241 https://stackoverflow.com/a/34131698

These seem to indicate GDI+ uses a very odd custom blending formula, something not representable with typical blending modes. Mimicking this in a shader necessitates knowing the color of the destination pixel before writing it, which is typically not possible. I think the only way I can really end up correctly mimicing the blending here is to have 2 passes, 1 pass to copy the destination pixels to another render target, and another doing the actual blending using those copied pixels.