There's a simpler and more efficient solution to this problem. You can create holes in the render-texture by rendering stuff with alpha = 0 and blend mode set to BlendNone. This way there's no need for a custom pixel shader, transparency is directly and correctly written to the target.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML holes");
window.setVerticalSyncEnabled(true);
sf::RenderTexture target;
if (!target.create(window.getSize().x, window.getSize().y))
return -1;
target.clear(sf::Color::White);
target.display();
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sf::Vertex point(sf::Vector2f(sf::Mouse::getPosition(window)), sf::Color::Transparent);
target.draw(&point, 1, sf::Points, sf::BlendNone);
target.display();
}
window.clear();
window.draw(sf::Sprite(target.getTexture()));
window.display();
}
return 0;
}
Okay, this version prevents you from using a texture to cut out areas. It will remove the complete bounding box of the sprite, no matter what the texture contains (I guess due to the BlendNone thing).
Yep. Could probably also be solved with the right blending mode.
I'd like to try out the pixel shader one, but I have absolutely no clue how to write shaders.
Here is a shader that sets alpha = 0 for pixels equal to a predefined colorkey:
uniform sampler2D texture;
uniform vec4 colorkey;
void main()
{
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
if (pixel == colorkey)
pixel.a = 0;
gl_FragColor = pixel;
}
sf::Shader shader;
shader.loadFromFile("colorkey.frag", sf::Shader::Fragment);
shader.setParameter("texture", sf::Shader::CurrentTexture);
shader.setParameter("colorkey", sf::Color(/* whatever (magenta) */));
...
window.draw(sf::Sprite(target.getTexture()), &shader);
There's a simpler and more efficient solution to this problem. You can create holes in the render-texture by rendering stuff with alpha = 0 and blend mode set to BlendNone. This way there's no need for a custom pixel shader, transparency is directly and correctly written to the target.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML holes");
window.setVerticalSyncEnabled(true);
sf::RenderTexture target;
if (!target.create(window.getSize().x, window.getSize().y))
return -1;
target.clear(sf::Color::White);
target.display();
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sf::Vertex point(sf::Vector2f(sf::Mouse::getPosition(window)), sf::Color::Transparent);
target.draw(&point, 1, sf::Points, sf::BlendNone);
target.display();
}
window.clear();
window.draw(sf::Sprite(target.getTexture()));
window.display();
}
return 0;
}
What the... I asked about this a week or so ago and we both agreed that it didn't work O_O
BTW just wondering, why are the completely transparent sprites won't do the same thing?
VertexArrays set to Quads will thought, so it doesn't really matter, but nonetheless.