Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::Shader::currentTexture  (Read 5352 times)

0 Members and 2 Guests are viewing this topic.

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
sf::Shader::currentTexture
« on: August 14, 2013, 03:36:19 pm »
Hey guys,
I have a renderTexture and my renderWindow.
Now I want to render something on the texture with a shader.
In this shader I call: vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);

I don't get the pixel from the renderTexture, but from the renderWindow...

How can I change that, so I get the pixel from the renderTexture?
Greetings
Failing to succeed does not mean failing to progress!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #1 on: August 14, 2013, 03:44:53 pm »
Current texture is the texture which you are drawing WITH, so if you draw a sprite with a shader it's the sprite's texture.
You can't access texture you are drawing TO because you can't read and write same texture at once.
What exactly are you trying to do?
Back to C++ gamedev with SFML in May 2023

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #2 on: August 14, 2013, 04:28:34 pm »
Basicially I want to change one color to another with a shader. (And yes I want to draw on the renderTexture)

If I clear the renderWindow with blue, the renderTexture with green and then draw a black shape (it can be any color though) on the renderTexture with the shader that sets the gl_fragColor to the pixel (vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);) I end up with a blue shape, so it took the texture from the renderWindow?
How can I pass the texture from the renderTexture to the shader? I thought sf::Shader::CurrentTexture does this automatically, or did I understand something wrong?
Should I give a minimum code example?
Failing to succeed does not mean failing to progress!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #3 on: August 14, 2013, 04:34:44 pm »
Yeah, it'll be much clearer that way. :P
Back to C++ gamedev with SFML in May 2023

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Shader::currentTexture
« Reply #4 on: August 14, 2013, 04:47:27 pm »
Quote
so it took the texture from the renderWindow?
No. Since there's no active texture when you draw your shape (you didn't set a texture on it, right?), the texture2D function returns garbage.

Quote
And yes I want to draw on the renderTexture
Quote
How can I pass the texture from the renderTexture to the shader?
You can't read and write the same texture at the same time. If you're drawing to the render-texture, you can't use it as a source in the fragment shader.
So basically, if you clear the render-texture to a certain color, you won't be able to use this information in your shader. Why don't you pass the color as a shader argument (shader.setParameter("color", the_color))?

Quote
I thought sf::Shader::CurrentTexture does this automatically, or did I understand something wrong?
sf::Shader::CurrentTexture refers to the texture of the object being drawn (in this case, the shape's texture, which is none).
Laurent Gomila - SFML developer

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #5 on: August 14, 2013, 04:56:52 pm »
Quote
so it took the texture from the renderWindow?
No. Since there's no active texture when you draw your shape (you didn't set a texture on it, right?), the texture2D function returns garbage.

Yeah I started to make a minimal code and now it makes sence, it is always black, because of what you said.
Alright then, what I am trying to do is: I draw stuff on my renderTexture and then I want to draw a shape on this renderTexture (let's say it's black), but where a certain color is (let's say white) I want the shape to have there white (or any other color) as well, how can I archieve that?

I am quite new to shaders and trying to experiment a bit with them, but this is still not clear for me.
Failing to succeed does not mean failing to progress!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #6 on: August 14, 2013, 05:12:35 pm »
Quote
but where a certain color is (let's say white)
If you mean there is white there on render texture then you can't do that because you can't read and write same texture at once.
You need to ping pong between two textures.
Back to C++ gamedev with SFML in May 2023

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #7 on: August 14, 2013, 05:38:40 pm »
Thats somehow stupid tbh :D
But I understand it now, thx for the explanations and I also understand why this can't work... what a pitty
Failing to succeed does not mean failing to progress!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #8 on: August 14, 2013, 05:53:38 pm »
That's how opengl works, not arbitrary SFML limitation.
Back to C++ gamedev with SFML in May 2023

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #9 on: August 14, 2013, 06:13:38 pm »
Alright I tested it now and I get something I really don't understand at all.

Thats how I understood: I should print my stuff on texture1 and then I pass this texture to the shader.
After this I draw my shape on texture2 with the shader. So I don't use the same texture for reading and drawing.

However if I draw the shape it has the color I cleared texture1 with (green) and not magenta (which I set in the shader if the pixel is black)

Thats the code:
#include <SFML/Graphics.hpp>

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test", sf::Style::Close);
        window.setFramerateLimit(60);

        sf::Event windowEvent;
        sf::RenderTexture texture, temp;
        sf::Shader shader;
        sf::RectangleShape test(sf::Vector2f(50, 50));
        test.setFillColor(sf::Color::Black);
        test.setPosition(400, 300);

        if(!texture.create(800, 600)) window.close();
        if(!temp.create(800, 600)) window.close();
        if(!shader.loadFromFile("test.frag", sf::Shader::Fragment)) window.close();

        while(window.isOpen())
        {
                while(window.pollEvent(windowEvent))
                {
                        if(windowEvent.type == sf::Event::Closed)
                                window.close();
                }

                window.clear(sf::Color::Blue);
                texture.clear(sf::Color::Green);
                temp.clear(sf::Color::Black);
                texture.draw(test);
                //texture.display();
                shader.setParameter("texture", texture.getTexture());

                temp.draw(test, &shader);

                window.draw(sf::Sprite(temp.getTexture()));

                window.display();
        }

        return EXIT_SUCCESS;
}

shader:
uniform sampler2D texture;
     
void main()
{
        vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
        if(pixel == vec4(0.0, 0.0, 0.0, 1.0))
                pixel = vec4(1.0, 0.0, 1.0, 1.0);
        gl_FragColor = pixel;
}
Failing to succeed does not mean failing to progress!

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #10 on: August 14, 2013, 07:30:08 pm »
Pixel is read from texture1 at position 0.0 0.0 because the rectangle shape vertices don't have texture coordinates so it default to 0.0 0.0 in SFML.
Also don't comment out that display in texture, it's needed.
If you replace
 temp.draw(test, &shader);
with
temp.draw(sf::Sprite(texture.getTexture()), &shader);
It'll draw a green background with magenta rectangle on it(you can also use current texture then instead of setting it to texture.getTexture()).
Back to C++ gamedev with SFML in May 2023

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
Re: sf::Shader::currentTexture
« Reply #11 on: August 14, 2013, 08:01:29 pm »
I see, now I understand completely, thx a bunch! (It works btw)
Quite difficult to find these things out, I had no idea :D
Failing to succeed does not mean failing to progress!