-
First of all, sorry for my worst english,
i hope you understand me anyway.
(http://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/Alpha_compositing.svg/500px-Alpha_compositing.svg.png)
i want do get the effect of the third picture of the first row.
is it possible?
-
I don't know of any SFML function that could do this, so I guess it's not possible. If yxou really need it you might be able to do such a thing with OpenGL, but I'm not an expert on OpenGL... ;)
-
thanks for the fast answering, i hope you are wrong, i doesn't know much about OpenGl.
In an German Forum some guy said that i have to use Render Textures, but he can't explain i have to do this.
-
Do you want this effect to be applied in real time? Or can it be done once at init?
-
it should "Simulate" a point light in real time
-
Hum... how does subtracting two textures simulate a point light?
-
I make the whole screen black and on the place i want i cut a circle out. So i have a simple point light
-
Ok, so in fact you want to create a mask.
This is possible, you can do it this way:
- create a RenderTexture which covers your screen
- clear it with opaque black
- draw your spot light to it, with blend mode = sf::BlendNone (so that its alpha is copied rather than interpreted)
- draw your RenderTexture to your window with a sprite
-
Sounds good, but can you write a short sample, i don't really get it.
-
I think something like this (
untested):
sf::CircleShape point(10);
point.setColor(255, 255, 255, 1);
sf::RenderTexture rtex;
rtex.create(windowWidth, windowHeight);
rtex.clear();
rtex.draw(point, sf::BlendNone);
rtex.display();
sf::Sprite sprite;
sprite.setTexture(rtex.getTexture());
// ...
window.draw(sprite);
Interesting enough the alpha channel of the circle/punch hole, can't be fully transparent, otherwise it will just be ignored.
@Laurent is this the intended behavior?
Anyways since I found the question interesting and somehow on another board has asked about the same questions here goes a complete example: ;D
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(300, 300), "Hello World!");
window.setFramerateLimit(30);
window.setMouseCursorVisible(false);
sf::RectangleShape rect(sf::Vector2f(100.f, 100.f));
rect.setFillColor(sf::Color::Red);
rect.setPosition(10, 10);
sf::CircleShape circle(20);
circle.setRadius(20);
circle.setPosition(110, 110);
circle.setFillColor(sf::Color(255, 255, 255, 1));
sf::RenderTexture rtex;
rtex.create(300, 300);
sf::Sprite sprite;
sprite.setTexture(rtex.getTexture(), true);
sprite.setPosition(0, 0);
while(window.isOpen())
{
sf::Event event;
while(window.pollEvent(event))
{
if(event.type == sf::Event::Closed)
window.close();
}
circle.setPosition(static_cast<sf::Vector2f>(sf::Mouse::getPosition(window)));
rtex.clear();
rtex.draw(circle, sf::BlendNone);
rtex.display();
sprite.setTexture(rtex.getTexture(), true);
window.clear(sf::Color::Blue);
window.draw(rect);
window.draw(sprite);
window.display();
}
}
But keep in mind drawing to the render texture every frame is quite a heavy task, it's like drawing two frames at once, so if it's not really needed don't do this every frame iteration. ;)
-
You all are awesome, i'll test it and post the result.
-
@Laurent is this the intended behavior?
Did you use the RC? I thought I already fixed it.
-
@Laurent is this the intended behavior?
Did you use the RC? I thought I already fixed it.
Nope, a one or two week old SFML release...
Edit: Just updated SFML to the latest commit and transparency with alpha channel = 0 and BlendNone still just doesn't draw anything...
(Windows, MinGW 4.7.0, static, debug)
-
Hmm... it was fixed the 15th of march:
http://en.sfml-dev.org/forums/index.php?topic=7294.msg48230#msg48230
https://github.com/SFML/SFML/commit/78e7dcea38b33bdee29105d39e30814a260fe47d
-
Ok, wait, there's another bug (was supposed to be a feature ;D), specific to shapes.
I'll see what I can do.
-
Does it mean i wont work?
-
Does it mean i wont work?
It works as long as you use an alpha channel greater than 0. ;)
-
It's fixed, you can now use completely transparent shapes.
-
8) it work fine.
but it doesn't work if i use more than one "Light"
-
but it doesn't work if i use more than one "Light"
What happens? Can you show the code?
-
i make a class for the light, if i add an other light the visible range is at the overlab, omg my english is so bad ^^
#ifndef CLIGHTS_HPP
#define CLIGHTS_HPP
#include <iostream>
#include <SFML\Graphics.hpp>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
class CLights
{
public:
CLights(int SizeX, int SizeY);
void SetPosition(int PosX, int PosY);
void SetLightSize(float Radius);
void SetLightColor(sf::Color LightColor);
void SetLightPosition(int PosX, int PosY);
void BackgroundColor(sf::Color Color);
void Draw(sf::RenderWindow &window);
private:
float m_Radius;
sf::Color m_LigthColor;
int m_PosX;
int m_PosY;
int m_LightPosX;
int m_LightPosY;
sf::CircleShape m_CircleLight;
sf::RenderTexture m_RTex;
sf::Sprite m_ShapeBackground;
};
#endif
#include <iostream>
#include <SFML\Graphics.hpp>
#include <SFML\Audio.hpp>
#include "Lights.hpp"
#include <string>
#include <vector>
#include <sstream>
using namespace std;
CLights::CLights(int SizeX, int SizeY)
{
m_RTex.create(640,480);
m_CircleLight.setRadius(0);
m_CircleLight.setPosition(0,0);
m_CircleLight.setFillColor(sf::Color(255,255,255,1));
m_ShapeBackground.setTexture(m_RTex.getTexture(), true);
m_ShapeBackground.setPosition(0,0);
}
void CLights::SetLightColor(sf::Color LightColor)
{
m_CircleLight.setFillColor(LightColor);
}
void CLights::SetLightSize(float Radius)
{
m_Radius = Radius;
m_CircleLight.setRadius(m_Radius);
}
void CLights::SetLightPosition(int PosX, int PosY)
{
m_LightPosX = PosX;
m_LightPosY = PosY;
m_CircleLight.setPosition(sf::Vector2f(m_LightPosX, m_LightPosY));
}
void CLights::SetPosition(int PosX, int PosY)
{
m_PosX = PosX;
m_PosY = PosY;
m_CircleLight.setPosition(sf::Vector2f(m_PosX, m_PosY));
}
void CLights::BackgroundColor(sf::Color Color)
{
m_ShapeBackground.setColor(Color);
}
void CLights::Draw(sf::RenderWindow &window)
{
m_RTex.clear();
m_RTex.draw(m_CircleLight, sf::BlendNone);
m_RTex.display();
m_ShapeBackground.setTexture(m_RTex.getTexture(), true);
window.draw(m_ShapeBackground);
}
-
You must draw all your lights to the same render texture. You should take some time to figure out how this code works, it seems that you have no idea what it does ;)
m_RTex.clear(sf::Color::Black); // to make it more obvious
m_RTex.draw(light1, sf::BlendNone);
m_RTex.draw(light2, sf::BlendNone);
m_RTex.draw(light3, sf::BlendNone);
...
m_RTex.display();
// no need to call it everytime
// m_ShapeBackground.setTexture(m_RTex.getTexture(), true);
window.draw(m_ShapeBackground);
So of course you need to redesign your class a little bit.
the visible range is at the overlab, omg my english is so bad
I have no idea what "overlab" means, and my dictionnary couldn't help ;D
-
He just meant that only the last light will should up.
Also keep in mind that if lights do overlap you'll have to draw them in the right order to the rendertexture, although it will still lead to some unwanted effects...
-
I give google translate a try
but yet, I figure it already slow. this is definitely a huge help.
-
i tried wiht a vector but it doesn't work, one light is nice. but with a RenderTexture there is no way to add lights if the "Game" is running.
CLights::CLights(int SizeX, int SizeY)
{
m_SizeX = SizeX;
m_SizeY = SizeY;
m_RTex.create(m_SizeX, m_SizeY);
}
void CLights::AddLigth(int PosX, int PosY, int Radius, sf::Color TempColor, sf::RenderWindow &window)
{
m_SpriteBackground.setTexture(m_RTex.getTexture(), true);
m_SpriteBackground.setPosition(0, 0);
m_SpriteBackground.setColor(sf::Color(0,0,0,255));
m_CircleLight.setPosition(sf::Vector2f(Mouse.getPosition(window).x, Mouse.getPosition(window).y));
m_CircleLight.setRadius(Radius);
m_CircleLight.setFillColor(sf::Color(255,255,255,1));
m_VectorShape.push_back(m_CircleLight);
}
void CLights::Draw(sf::RenderWindow &window)
{
for(int i = 0; i < m_VectorShape.size(); i++)
{
m_SpriteBackground.setColor(sf::Color(0,0,0,240));
m_RTex.clear();
m_RTex.draw(m_VectorShape[i], sf::BlendNone);
m_RTex.display();
m_SpriteBackground.setTexture(m_RTex.getTexture(), true);
window.draw(m_SpriteBackground);
}
}
-
Please make use of the code=cpp tag!! :)
You still don't understand how it works, don't you? Please at least try to understand it! ;)
You only have to clear and display the render texture once and not with every single light...
-
Or just look at the code I posted above.
-
@Laurent
in your code i have to write every single light in my class, i cant add lights while the program is running
@eXpl0it3r
please believe me, i try to understand ;D
-
He meant that you don't call clear() and display() in ever iteration.
Lets take an easy analogy:
The window is a piece of paper with a drawing on it. The render texture is another piece of paper on top of the other one and it is just black.
Now to see what's underneath you go and cut out some parts of the black paper. After that you can look through that cutout part onto your window.
What you did in the code with the vector is. Everytime you've cut out a square, you threw away the black paper with the hole and took a new black paper and cut out the next hole. Obviously you'll always just see one hole (since you've thrown the other holes away).
What you actually want is to take the black paper, punch as many holes as you want into it and the overlay it with the drawing paper.
Got it? ;)
-
:( i give up, now i can place many lights bur can move the one of the playercharakter
-
YES YES YES, i made it YES YES YES 8)
Edit:
it still works, but at 5 lights the performance is terrible
-
Here is the result
http://www55.zippyshare.com/v/54013397/file.html
-
I don't see where there are multiple 'lights' but congrats! ;)
Btw it crashes at exit on my PC.
-
Sorry, with T you can add a torchlight.
EDIT:
This funktion is the problem, maybe someone have a idea how i can fix this.
void CLights::SyncLightPosition(int PosX, int PosY)
{
for(int i = 0; i < m_VectorShape.size(); i++)
{
m_RTex.clear();
m_VectorShape[0].setPosition(PosX, PosY);
for(int i = 0; i < m_VectorShape.size(); i++)
{
m_RTex.draw(m_VectorShape[i], sf::BlendNone);
}
}
}
-
void CLights::SyncLightPosition(int PosX, int PosY)
{
m_RTex.clear();
m_VectorShape[0].setPosition(PosX, PosY);
for(int i = 0; i < m_VectorShape.size(); i++)
{
m_RTex.draw(m_VectorShape[i], sf::BlendNone);
}
m_RTex.display();
}
-
as i used one for loop it doesn't work, but now is works fine, 40 lights and still playable.
thank you guys!