SFML community forums

General => Feature requests => Topic started by: Krozark on August 13, 2015, 01:49:57 pm

Title: [CLOSED] Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 13, 2015, 01:49:57 pm
Hi everyone,

I'm working on a light system with a friend, and we face a limitation of SFML, a missing BlendMode.
Currently, GL_FUNC_ADD ( alias GLEXT_GL_FUNC_ADD) and  GLEXT_GL_FUNC_SUBTRACT (alias GL_FUNC_SUBTRACT) are implemented. But what about GL_FUNC_REVERSE_SUBTRACT ?

In our specific case, it was needed to subtract light from another one (a sort of negative light).
But there is no way to do it without using a shader right now.

Am I missing a way to do this with current tool set apart from using a shader or direct OpenGL code ? If not is there any possibility of adding a ReverseSubtract to sf::BlendMode::Equation as an alias of GL_FUNC_REVERSE_SUBTRACT?

White we're at it, would it be interesting to add the GL_MIN and GL_MAX equations as well ?

If need I can take care of adding this functionality. Already made on my fork

Thanks.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 13, 2015, 02:15:02 pm
Would it be possible to draw them in the reversed (swapped) order and use the (forwards) subtract?
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 13, 2015, 02:47:58 pm
With you approach, the result will not be the one expected, expect if I'm missing something.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 13, 2015, 03:28:25 pm
What is the expected result?
According to this documentation (https://www.opengl.org/wiki/GLAPI/glBlendEquationSeparate), the reverse subtraction is the source being subtracted from the destination rather than the destination being subtract from the source.
Can you not form this in an sf::BlendMode (http://www.sfml-dev.org/documentation/2.3.1/structsf_1_1BlendMode.php)?
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: DaiMysha on August 13, 2015, 03:39:28 pm
I'm the one who initiated the light system project.

We did some testing with a local fork of SFML and implemented the modification (which consists of 13 changed lines)

Tried it using that custom version and the result is as expected, see screenshot below.
The light emitted from the blue rectangle is white negative and cancels the lights emitted everywhere else.

If you know a way to do this without using the gl reverse subtract function reaching the result given in the screenshot i am curious because we didn't find anything that worked.

What is the expected result?
According to this documentation (https://www.opengl.org/wiki/GLAPI/glBlendEquationSeparate), the reverse subtraction is the source being subtracted from the destination rather than the destination being subtract from the source.
Can you not form this in an sf::BlendMode (http://www.sfml-dev.org/documentation/2.3.1/structsf_1_1BlendMode.php)?

We cannot. I am rendering the lights individually on a global RenderTexture that I then draw on the window. It's not possible to invert the two textures.

The expected result is this one:

result = destination - source

That is exactly what GL_FUNC_REVERSE_SUBTRACT does
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 13, 2015, 07:07:40 pm
The light emitted from the blue rectangle is white negative
What blue rectangle?

I am rendering the lights individually on a global RenderTexture that I then draw on the window. It's not possible to invert the two textures.
Invert them? I was suggesting swapping them.

The expected result is this one:
result = destination - source
What is the destination and what is the source?

If you know a way to do this without using the gl reverse subtract function reaching the result given in the screenshot i am curious because we didn't find anything that worked.
Do what without using it? To reach the result, could do with knowing what we're using to create it. Could help if you provided the layers you are trying to blend, and in what order.


I started to guess at what you mean. Would it be:
draw a blue rectangle on something white and it would turn yellow?
If so, you could draw them in the opposite order. Draw blue rectangle first then (forwards) subtract the white.


I think you're right, though. This should (probably - any reason not to?) be added. Not sure why min and max are required.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: DaiMysha on August 13, 2015, 08:17:44 pm
Apologies for the unclear answer. Let me try to explain.

What we are trying to achieve is a light that, instead of adding its component to the world, substracts them.
Say you have a purple light (red and blue), if you were to put a blue negative light on it, you would end up seeing a red light. It's what happens with the dark cone in the screenshot, since it's a pure white light, it removes every color in its path resulting in the shadow cone seen.
The underlying calcul here is (255,0,255) - (0,0,255) = (255,0,0)

My Light Manager works in (currently) 3 steps.

First step is the user drawing his world on the screen. Then the light manager draws its lights on its own texture (let's call it the light layer texture) and draws that texture on top of the users' world with a multiply.

To (hopefully) optimize the rendering, every light registered to the light manager also has its own texture in which it pre renders itself and passes onto the light manager to be draw on the light layer texture.

The light manager then adds all the lights textures into his own texture to create the light later which is then drawn on top of the user's world.
The idea of a negative light would be that instead of adding it to the light layer, it is substracted from it.

That's why it's not possible for me to invert the two texture concerned, the light manager's light layer and the lights's pre rendered texture. Inverting them would mean that i draw the light layer on top of a light's inner texture, and that cannot work.

Quote from: Hapax
What blue rectangle?
It doesn't see well because the window is dark, but at the origin of the dark cone, in the screenshot, there is a blue square representing the player's position.

Quote from: Hapax
What is the destination and what is the source?
In this case, the result is what you see on the screen (the black cone, after multiplying it to the user's world),
the destination is the light manager's light layer texture and the source is the light's pre-rendered texture

If we suppose layers are added from left to right, what i'm trying to achieve here is :
[users's world] * [light manager base color + lights - negative lights]

The issue here being the - negative lights part. We could have it by using a shader or pure OpenGL code but we simply don't understand why this option hasn't been made available right from the start.

Quote from: Hapax
Not sure why min and max are required.
I don't know why they would be, but i don't see a reason not to include them. They've been made available by OpenGL so why not ? And if one day someone actually finds a use to them, he'll be happy that they are available and don't find themseves in my position.

Hopefully this answer is clearer regarding our intentions and issue.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 13, 2015, 08:24:33 pm
What we are trying to achieve is a light that, instead of adding its component to the world, substracts them.
sf::BlendMode reverseSubtract(sf::BlendMode::Zero, sf::BlendMode::OneMinusSrcColor, sf::BlendMode::Equation::Add);
8)

I don't know why they would be, but i don't see a reason not to include them. They've been made available by OpenGL so why not ? And if one day someone actually finds a use to them, he'll be happy that they are available and don't find themseves in my position.
From previous discussions on this forum that I've seen, this seems to me to be a certain reason for rejection. Including stuff because you can in hope that someone might want it someday does not seem to be the philosophy behind SFML, which makes sense.

EDIT: altered variable's name in the code for clarification
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 14, 2015, 10:00:33 am
From previous discussions on this forum that I've seen, this seems to me to be a certain reason for rejection. Including stuff because you can in hope that someone might want it someday does not seem to be the philosophy behind SFML, which makes sense.

Here, we don't ask this feature for Fun but because : it is available on OpenGL, and SFML doesn't allow us to use theme. Why?
OpenGL allows 5 blend mode (GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN and GL_MAX), but only two of theme are available (GL_FUNC_ADD, GL_FUNC_SUBTRACT).

The request is : Make the five available on SFML. This is as simple as that.
Here is a link to the commit on the fork to show you the changes : https://github.com/Krozark/SFML/commit/0a84d785c5de6fe34f90e41ba65fd2e1218ad209 (https://github.com/Krozark/SFML/commit/0a84d785c5de6fe34f90e41ba65fd2e1218ad209)

Now, concerning the project, we tried a lot a combinations of sf::BlendMode before posting here, including your proposal (which gives a good approximation but not exactly the result we wanted).  None of theme works as expected using sf::BlendMode::Equation::Add or sf::BlendMode::Equation::Substract. For our case we NEED (yes, in big) GL_FUNC_REVERSE_SUBTRACT.
Concerning Min and Max, we don't need them at all, but I already explained my opinion on this at the beginning of this post.

We did additional tests to show that the result we get with your solution isn't exactly what we wanted. See the results in the attached screenshots.

We picked three spots with a (50,0,50) light, giving a center spot of a (150,0,150) color.
We used a negative color of (0,0,50) in the center of it. We expect a center resulting value of (150,0,100), which we obtain with the ReverseSubtract, while your solution gives us a color of (150,0,121). While being a good approximation, it isn't exactly what we need and a difference of 21% (here) is too high to be accepted because visible to the naked eye.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Laurent on August 14, 2015, 10:36:22 am
If GL_FUNC_REVERSE_SUBTRACT exists, I guess you can trust OpenGL that this is because it can't be emulated with other modes. So indeed, you'll probbaly never have the exact same result with any other combination of blend modes.

So, adding it to SFML is an option. However I still don't understand what these "negative" lights mean; what effects do you achieve with them? Could it be that this concept of "negative light" is a wrong solution to a more fundamental problem (lighting algorithm)?

Regarding the other OpenGL blend modes, there is an obvious reason to not add them "just because they exist": SFML is a simple library, not a 1:1 wrapper on top of OpenGL. OpenGL is at the lowest level of graphics abstraction, its API is (and has to be) a direct mapping of what the graphics card can do, because there's no other way to access these features otherwise. SFML is at a higher-level, it tries to extract a meaningful set of features from all this clutter. However, simple doesn't mean limited, and if one day GL_MIN and GL_MAX prove to be useful, then they'll be considered more seriously.

Note that this is my personal opinion, others (including team members) may disagree.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Mario on August 14, 2015, 11:11:53 am
@Laurend I'd actually consider Min/Max to be more important than Reverse Substract. :)
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 14, 2015, 11:17:14 am
However I still don't understand what these "negative" lights mean; what effects do you achieve with them?

In reality negative light don't exist at all, but let take the case of a RPG. Imagine that your hero can throw spell of darkness, witch remove a color.
This is the idea of negative light.

Example :
Ambient color = (127,50,203)
Darkness spell  = (0,12,150)

final scene color = Ambient color  - Darkness spell
                = (127, 38, 53)

Could it be that this concept of "negative light" is a wrong solution to a more fundamental problem (lighting algorithm)?

I don't think so. It' more a new concept (which is be a bit confusing, I agree).


Regarding the other OpenGL blend modes, there is an obvious reason to not add them "just because they exist": SFML is a simple library, not a 1:1 wrapper on top of OpenGL.

I understand It. This is why, through this thread, we try to convince you (and other SFML team member) the need of it through concert example.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 14, 2015, 01:06:35 pm
Negative lights are actually a rather commonly used concept. Sometimes it's simpler to "add darkness" than to adjust all lights to make that area darker. Maybe not that common in 2D gaming but still...

your proposal...which gives a good approximation but not exactly the result we wanted
It's true that it wasn't perfect as it's based on multiplication rather than linear subtraction. I find it ironic, though, that you found it unacceptable as multiplication is more commonly done via multiplication, and I'm not sure why you need exact numbers. Since it's lighting, the negative light's 'power' could be 'turned up' to accommodate.
Saying that, it was only a suggestion.

it is available on OpenGL, and SFML doesn't allow us to use theme. Why?
SFML's graphics module doesn't provide abstract access to everything that OpenGL does but SFML itself does allow access to OpenGL, if you're willing to use OpenGL.

Again, I still agree that it should be included; it's just sometimes your reasoning isn't best put  ;)

I'd actually consider Min/Max to be more important than Reverse Substract. :)
Why?
Its not that I disagree; I just wonder what they'd be so commonly used for.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: shadowmouse on August 14, 2015, 01:14:09 pm
I agree this is a good idea. The SFML interface is easier to use than OpenGL, because it is simpler, but I don't think that purposefully excluding functionality in this way makes it easier to use. Correct me if I'm wrong, but this just extending an enum (from the user's point of view) and that doesn't make SFML harder to use, especially if in tutorials you were to say "These are the basic blend modes, then you have these for specific circumstances". Also on the topic of negative light, I think that being able to create, for example, black plasma blast style effects, or even just a black fire/lantern is not only cool graphically but can add to games. Should not the ideal library give you as much control as possible, in the easiest way possible. Personally, I've never had to use blend modes (because SFML does it for me by default), hence it is simple, but being a powerful library means it should give you control when you need it.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 14, 2015, 01:36:13 pm
Correct me if I'm wrong, but this just extending an enum (from the user's point of view) and that doesn't make SFML harder to use

Exactly, and a switch on this enum  values to complete (from a SFML developer point of view).
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Laurent on August 14, 2015, 01:50:03 pm
More options means the functionality is less straight-forward to use. It is more complex for someone without knowledge on blending modes, to figure out what he needs if all possible options are exposed to him, rather than just the most useful ones.

Quote
Also on the topic of negative light, I think that being able to create, for example, black plasma blast style effects, or even just a black fire/lantern is not only cool graphically but can add to games.
As already said, this kind of effects are usually done with multiplicative blending, to modulate the amount of final light rather than subtracting a fixed quantity.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: shadowmouse on August 14, 2015, 01:54:50 pm
More options means the functionality is less straight-forward to use. It is more complex for someone without knowledge on blending modes, to figure out what he needs if all possible options are exposed to him, rather than just the most useful ones.
Surely this is what tutorials and documentation are for? You can highlight which ones are the most commonly used ones and which ones are more advanced as well as what each one does. Surely you don't expect that people work out what to write purely by guessing what it will be called and then using the auto-complete/intellisense functions of an IDE.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 14, 2015, 02:12:17 pm
More options means the functionality is less straight-forward to use. It is more complex for someone without knowledge on blending modes, to figure out what he needs if all possible options are exposed to him, rather than just the most useful ones.
Surely this is what tutorials and documentation are for? You can highlight which ones are the most commonly used ones and which ones are more advanced as well as what each one does. Surely you don't expect that people work out what to write purely by guessing what it will be called and then using the auto-complete/intellisense functions of an IDE.
+1 : totally agree.

Moreover, if a user start to use BlendMode, we can say that it's not a novice anymore. I'm sure that he will know how to search thought the documentation (which is very complete) to find the needed informations.

Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: eXpl0it3r on August 14, 2015, 11:50:03 pm
I personally think it won't make things a lot more complex. As Krozark already said once you're start using blend modes, you're not a novice anymore who just looks at the auto-completion of the IDE and tries to find out what it does by trial and error.
So the current implementation is only artificially limiting the ones who actually want to use the blend modes more complex. And I think we're lucky that this has been brought up for discussion, because I can easily imagine that there have been others who wanted that feature before and just patched SFML locally and never reported it.

Would be nice to hear some opinions from other team members. :)
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Tank on August 15, 2015, 08:25:12 am
My opinion is probably clear, but here it is: I see no conflicting complexity by adding more options. Blending is already part of the library, and not including special modes is 1) trying to predict how people use blending and 2) expecting that all SFML users only use the simple things, thus leaving the experienced people behind.

As we really want experienced people to be able to enjoy SFML and not be forced to use raw OpenGL everywhere (or even choose another library), I highly suggest to add the missing modes.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 15, 2015, 05:53:15 pm
I'm glad this conversation is fruitful.

I'll open an issue on the SFML github, then make a  pull request with the appropriate modifications.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Tank on August 15, 2015, 08:04:25 pm
Thanks! :)
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Nexus on August 16, 2015, 03:51:14 pm
Keep in mind that the original discussion (http://en.sfml-dev.org/forums/index.php?topic=14148.0) about adding blend modes explicitly omitted those options because they are not so common, and the API would be simpler to use without them. Users agreed at that time with the API. So, the omission was not an overlook, but by design.

If the assumptions have truly changed in the meantime and we have good use cases (rather than "just provide it because OpenGL does"), I'm okay with adding the options. It would be cool if you could quickly summarize what effect you're trying to achieve that can't be achieved otherwise (e.g. with multiplicative blending).
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Laurent on August 16, 2015, 05:12:44 pm
I especially like this (quoted from the author of the feature) from the original discussion:

Quote
If anything, min and max could be dropped as they serve little purpose from a graphical perspective and they also operate differently than the other equations (that is, they ignore the blending factors).

As library authors, we must predict what users will need, to provide the cleanest interface. It has never been the philosophy of SFML to add something without knowing if it will actually be useful. If we added a feature without knowing its effects and how users will use it, then we poorly did our job. And no, no matter how good your documentation is, a cluttered API is a cluttered API.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Tank on August 17, 2015, 08:24:25 am
Quote
As library authors, we must predict what users will need, to provide the cleanest interface
Of course, but we should also find a good compromise between API "clutter" and functionality. In this case, we decided to drop reverse subtract because in our eyes, there was no use to it. But obviously we did not know better, because there is a use to it (see this thread).

To support it, we need to add one enum value. And the same perhaps happens with min and max now.

I totally agree that keeping the API clean and simple is the ultimate goal. But sacrificing potential functionality and users just to avoid adding three enum values, sorry, that's too much in my opinion. And don't forget that one also learns about new things when striving through the API docs to find something that might fit their needs.

Speaking of myself, I would be totally annoyed if I had to stick to raw OpenGL every time I needed something that wasn't proven to be a well-known use-case.

Quote
And no, no matter how good your documentation is, a cluttered API is a cluttered API.
I just want to emphasize this: We are talking about some enum values.

Quote
So, the omission was not an overlook, but by design.
That's correct, and I guess nobody is questioning the author of the changes.

Quote
It would be cool if you could quickly summarize what effect you're trying to achieve that can't be achieved otherwise (e.g. with multiplicative blending).
Krozark gave an example in the first post already. ;)
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Laurent on August 17, 2015, 08:57:41 am
Quote
I just want to emphasize this: We are talking about some enum values.
Yeah, it was a more generic answer to someone who basically said "any added complexity is not a problem, there's the doc".

Quote
Krozark gave an example in the first post already.
In case it was not clear: I'm ok for adding reverse subtract, my objections are only about min and max.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 17, 2015, 09:57:46 am
In case it was not clear: I'm ok for adding reverse subtract, my objections are only about min and max.

Ok, I don't have any example for Min, here is for Max:

Let's take the case of a game were your hero have only light as weapons (in fact, this is the plot of the game that DaiMysha is working on).
Imagine some monster that can be see only by specifics light color (let's take the example of a pure Red).
Now put you hero in a dark dungeon plain of this kind of monster. He turn on his torch light in Blue, and nothing appear. Change it's light color to Red, and .... plenty of monster appear where nothing was visible with the blue light.

I hope you understand the example.

Concerning the implementation, I think there is a lot of solutions, but this is one using BlendMode.
Just make a Min between you light map (texture with only the light), and draw the monster texture (of Red color) with a Min on the top of it.
Now, I don't know if it's the best example to illustrate the Min functionalities.

I am really mixed about these features (Min/Max), and personally I think I would never use them.
I join point of view of Laurent.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Hapax on August 17, 2015, 04:05:31 pm
Krozark, your min/max example is a little complicated/mixed. It looks like you switch from describing min and max.
Still, the example itself (red things not showing under blue light but showing under red light) seems to be the kind of thing you would do with multiplication.

I 'vote' for adding ReverseSubtract and leaving off Min and Max.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Krozark on August 17, 2015, 04:19:59 pm
Still, the example itself (red things not showing under blue light but showing under red light) seems to be the kind of thing you would do with multiplication.
I was trying to find an example of usage, and you're right, multiplication is a better solution.

My opinion (in case of ambiguity): Add ReverseSubtract only
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: zsbzsb on August 17, 2015, 04:27:55 pm
I agree, reverse subtract is good without adding min/max.
Title: Re: Add sf::BlendMode::ReverseSubtract
Post by: Tank on August 17, 2015, 06:04:44 pm
So shall it be.