Please take a look at the attached image of three circles, which is the output of the code below.
The left circle is the result of drawing the circle to a RenderTexture, texturing a sprite with it and drawing the sprite. It does not appear as intended.
The middle is the same sprite drawn with a modified blend mode. It appears as intended.
The right circle is drawn directly to the window without a modified blend mode. It also appears as intended.
My question is: Why does drawing the circle directly work as intended, while drawing a sprite of it requires a custom blend mode?
#include <SFML/Graphics.hpp>
int main() {
sf::CircleShape circle(100.f);
// Give the circle a texture so we can use a shader on it.
sf::RenderTexture fallback;
fallback.create(1, 1);
fallback.clear(sf::Color::White);
fallback.display();
circle.setTexture(&fallback.getTexture());
// Define a shader that goes from transparent on the left to red on the right.
const std::string shaderCode = R"*(
void main() {
gl_FragColor = vec4(1,0,0,gl_TexCoord[0].x);
}
)*";
sf::Shader shader;
shader.loadFromMemory(shaderCode, sf::Shader::Fragment);
// Draw the circle onto a RenderTexture.
sf::RenderTexture canvas;
canvas.create(200u, 200u);
canvas.clear(sf::Color::Transparent);
canvas.draw(circle, &shader);
canvas.display();
// Create a sprite from the RenderTexture.
sf::Sprite circleSprite(canvas.getTexture());
circleSprite.setPosition(50.f, 50.f);
// Create a white window to draw the sprite on.
sf::RenderWindow window(sf::VideoMode(800, 300), "Test");
window.clear(sf::Color::White);
//This appears red and gray because of the blend mode. That's unintuitive.
window.draw(circleSprite);
// Move the sprite and draw it again. This time with a modified blend mode.
circleSprite.move(250.f, 0.f);
sf::BlendMode intuitiveBlendMode;
intuitiveBlendMode.colorSrcFactor = sf::BlendMode::One;
window.draw(circleSprite, intuitiveBlendMode);
// Drawing the shape directly to the window doesn't have this problem.
circle.setPosition(550.f, 50.f);
window.draw(circle, &shader);
window.display();
while(window.isOpen()) {
sf::Event event;
while(window.pollEvent(event)) {
if(event.type == sf::Event::Closed)
window.close();
}
}
return 0;
}