-
Notifications
You must be signed in to change notification settings - Fork 16
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
Alternative blending for Stride ImGui region #669
Comments
That's my test patch HowTo ImGui in Stride.txt |
For my own sanity, let's write it the other way around with the hope that this will lead to more insights on how this affects the shader code that is executed in the linear pipeline...
two invalid transformations, but at least the left and right side look the same ;) the one valid part was |
Another way to put this is: If some of the transformations are invalid, and if the problem indeed is unsolvable, why is stride implementing the function
and not this way:
To my understanding, there is no right way to treat the alpha, but in our example, the original implementation leads to three invalid transformations, while the new technique only comes with two invalid transformations. |
To your last question: I think it's the way how the hardware also does it. The alpha channel is not touched during the conversions. I couldn't find anything about it in the DirectX documentation, but in OpenGL they do answer this question both when reading textures and writing to framebuffers (search for "alpha" in both texts, it will lead to the corresponding question). Update: The link they refer to in the second document is dead, I think this is a working one: http://alvyray.com/Memos/CG/Microsoft/17_nonln.pdf |
I would subscribe to this way of looking at it. But ok. Probably there is no way of offering a function that always does the right thing. Depends on how you look at the problem at hand. If you want to emulate the wrong behavior of the gamma pipeline |
So since there seems to be no correct way I would propose the user to be able to select between 6 techniques.
Plus the three counterparts that leave alpha untouched |
yet another idea for a technique:
All in all, all of these techniques only work well for dark backgrounds. The region would
|
had a look at the precompose idea. I didn't think about the best way how the 2 regions could share code before knowing if this experiment would work out. So there is a lot of duplicated code here: https://github.com/vvvv/VL.StandardLibs/tree/feature/VL.ImGui.Stride_PreComposed There is a problem with the letters, which sample the original precomposed "scene". So for now this is just an experiment that shows that the colors can be blended in a way like in gamma space if you have access to the |
Studied this further: I'd argue the best result is the one on the left. My intuition now is that the goal of having them behave as in gamma space was wrong.
This makes sure that when rendered above a black background they look like in gamma space. If there is no objection I'll do it. |
@gregsn do it |
Is your feature request related to a problem? Please describe.
Colors typically are too bright.
Describe the solution you'd like
My understanding is that this can't be fixed for the linear color space. Blending just works differently here.
That's why I would propose the user be able to choose between different techniques.
Sometimes one solution looks better than the other.
Describe alternatives you've considered
An additional in-between render target. But I think the alpha of that render target again will make a problem when applying it to the final output.
Also, I tried reasoning with some math, but to my understanding, it's not solvable.
Additional context
current:
new technique:
While the above example makes the new technique look good, there are counterexamples.
current:
new technique:
The new technique in the shader
My math and my reasoning as to why this is not solvable. I might be wrong
This is how I understand the graphics pipeline. Again, it's so *##$&ing complicated, I might be wrong. So that's just my opinion how it works ;)
drawing two triangles on top in linear color space:
destc0
,destc1
&destc2
are different states of a pixel in the target surface.srcA
andsrcB
is what the pixel shader outputs for those two calls.finalcL
is what I get to see. My understanding is that displaying a linear target surface to the gamma-based screen involves some finaltogamma()
call somewhere at the very end of the pipeline.this is how things have been with gamma colors all over the place:
drawing two triangles on top in gamma color space:
it's a bit unfair. The names are longer. But it's simpler as the final
togamma()
call isn't performed by the pipeline.task: make the final colors that hit your eye be equal
finalcL =? finalcG
ok. let's only focus on the second triangle been drawn.
We need to somehow make them equal.
togamma(srcB.c * srcB.a + destc1.c * (1 - srcB.a)) =? srcGammaB.c * srcGammaB.a + destGammac1.c * (1 - srcGammaB.a)
It already seems unlikely that this will work out.
Reasoning:
(a*b)^c = a^c*b^c
but surely
(a+b)^c != a^c+b^c
togamma(.. + ..)
already gives me no hope to break this up in a way that I'll end up with something that looks exactly like on the right side of the equation.Well, to be honest, I tried for fun. This is what I ended up with when trying to solve for srcB.a
srcB.a = [toLin(togamma(srcB.c) * srcGammaB.a + destGammac1.c * (1 - srcGammaB.a)) - destc1.c] / (srcB.c - destc1.c)
let's try again.
let's try to make them match somehow while keeping an eye on both sides without solving for one variable:
togamma(destc1.c + srcB.a * (srcB.c - destc1.c)) = destGammac1.c + srcGammaB.a * (srcGammaB.c - destGammac1.c)
not a valid transformation:
destGammac1.c + togamma(srcB.a * (srcB.c - destc1.c)) = destGammac1.c + srcGammaB.a * (srcGammaB.c - destGammac1.c)
valid:
destGammac1.c + togamma(srcB.a) * togamma(srcB.c - destc1.c) = destGammac1.c + srcGammaB.a * (srcGammaB.c - destGammac1.c)
not a valid transformation:
destGammac1.c + togamma(srcB.a) * (togamma(srcB.c) - destGammac1.c) = destGammac1.c + srcGammaB.a * (srcGammaB.c - destGammac1.c)
Ok, I have two invalid transformations in here, but funnily I see this guy here:
togamma(srcB.a)
, which is basically what I propose to do: to tweak the alpha... At least in some cases, it looks better.Design Options
So what do you think?
Can we have a boolean input pin or enum pin on the region where we choose between techniques?
Or should we playful and offer a float where you can lerp between the two solutions?
Thanks for your great work!
@kopffarben
The text was updated successfully, but these errors were encountered: