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

Author Topic: Polygon to shader  (Read 6742 times)

0 Members and 2 Guests are viewing this topic.

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Polygon to shader
« on: October 16, 2012, 04:03:15 pm »
Hello, I'm rendering everything to RenderTexture: image and polygon. It looks like 1.png from attachment. The code is:

    sf::Texture img;
    img.loadFromFile("test.png");
    RENDER_TEXTURE->draw(sf::Sprite(img));

    sf::ConvexShape polygon;
    polygon.setPointCount(3);
    polygon.setPoint(0, sf::Vector2f(0, 0));
    polygon.setPoint(1, sf::Vector2f(230, 10));
    polygon.setPoint(2, sf::Vector2f(70, 200));
    polygon.setOutlineColor(sf::Color::Red);
    polygon.setFillColor(sf::Color::Transparent);
    polygon.setOutlineThickness(5);

    RENDER_TEXTURE->draw(polygon);

Now I want to apply some shader for the area inside that polygon. I wrote a simple one:

uniform sampler2D texture;

void main()
{
    vec4 color = texture2D(texture, gl_TexCoord[0].xy);
    if (color.a != 0.)
    {
        color.r += 0.4;
    }

    gl_FragColor = color;
}

And changed the code of polygon drawing to:
shader.setParameter("texture", sf::Shader::CurrentTexture);
RENDER_TEXTURE->draw(polygon, shader);

The result you could see at second attachment. So, the shader is applied only for polygon, not for the whole texture inside it. But what to do if I want to pass that area inside polygon into shader and make it more red?

[attachment deleted by admin]
« Last Edit: October 16, 2012, 04:05:10 pm by Ockonal »
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #1 on: October 16, 2012, 04:26:07 pm »
What's behind the polygon is already drawn, you can't use it in the shader to re-draw it. You would have to assign the texture to the polygon as well (in case there's only one texture, and not a complex scene behind that polygon), and calculate the texture rectangle of the polygon so that the texture is mapped on it the same way it appears behind.

If you just want to make the polygon area more red, apply an alpha of 0.4 to your red polygon and draw it with alpha-blending (the default). No need for a shader here.
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #2 on: October 16, 2012, 04:35:29 pm »
Thanks for the reply.

>If you just want to make the polygon area more red, apply an alpha of 0.4 to your red polygon and draw it with alpha-blending (the default). No need for a shader here.

No, I need in more advanced effects on that area. Before this I had not convex polygon but rectangle. I was passing that rectangle into shader and worked with it. But now I have polygon and I don't know how to map texture to it.

>in case there's only one texture, and not a complex scene behind that polygon
Yeah, everything before this is rendered into single render texture so I can access the full area behind the polygon.

So the only question is how to map that texture to the polygon, right? But I don't know what to google and where to look for.
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #3 on: October 16, 2012, 04:44:07 pm »
polygon.setTexture(img);
polygon.setTextureRect(sf::IntRect(...)); // something based on polygon.getGlobalBounds() should work

That should be all you need to change to make your code work.
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #4 on: October 16, 2012, 04:49:30 pm »
Look at attachment, please.

Green area - texture. Red bounds - my polygon. I can get texture related to polygon size.
The question:
After this line of code texture would be automatically cut for polygon bounds?
polygon.setTexture(img);

And for what purposes is second line?

[attachment deleted by admin]
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #5 on: October 16, 2012, 04:57:07 pm »
Quote
After this line of code texture would be automatically cut for polygon bounds?
Yes of course, otherwise it wouldn't be a polygon anymore, it would become a regular sprite.

Quote
And for what purposes is second line?
To define which part of the texture is mapped on the polygon, this is the same as for sprites. The fact that this function takes a rectangular area makes it easier to handle (at the cost of less flexibility), but the result is still a polygon.

What happens with these two lines of code is exactly what your previous attachment shows.
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #6 on: October 17, 2012, 01:15:54 pm »
Thanks!

    sf::IntRect rect = sf::IntRect(leftTopX, leftTopY, rightBottomX, rightBottomY);
    sf::Sprite shaderSprite(mTarget->getTexture(), rect);

I'm using that coords for sf::RectangleShape and everything is okay with sizing and position. But when I'm trying to save shaderSprite:
shaderSprite.getTexture()->copyToImage().saveToFile("WaterSubrect.png");

It saves the whole fullsize texture.

mTarget is render texture for the full screen. What's wrong? How to get that rectangle from texture?
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #7 on: October 17, 2012, 01:41:28 pm »
It seems that you don't completely understand how texture mapping works ;)

The texture is an image that lives in video memory. Then you have some geometry (a rectangle, a polygon, whatever) which defines texture coordinates for its points (vertices). Then, when you draw your geometry using the texture, the graphics card applies the mapping and computes which pixels of the texture are visible on the geometry, to produce the final textured shape that you see on screen.

So the texture itself is never actually touched, it always stays the same. So if you save a sprite's texture to a file, you'll always get the full original image. When you call setTextureRect, nothing actually happens to the texture, it just modifies the texture coordinates of the 4 corners of the sprite so that the texture is mapped differently on it.

So if you want to save only a small rect of the original texture, you'll have to cut it manually. Given the current state of the API, you'll need (pseudo-code):
image = texture->copyToImage()
sf::Image final(rect.size());
final.copy(image, rect);
final.saveToFile("...");
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #8 on: October 17, 2012, 01:53:47 pm »
Thanks for a fast reply! Everything works now :)
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #9 on: October 17, 2012, 02:22:13 pm »
Sorry for disturbing. Yet another problem related to this. Some pseudocode:

    // Generate my polygon
    sf::ConvexShape polygon;
    polygon.setPoint(...);

    // Apply texture to it
    sf::IntRect rect = sf::IntRect(leftTopX, leftTopY, rightBottomX, rightBottomY);
    polygon.setTexture(&mTarget->getTexture());
    polygon.setTextureRect(rect);

    // Draw that polygon in global texture with applying of shader
    mTarget->draw(polygon, shaderEffect);

Shader:

uniform sampler2D texture;
void main()
{
    vec4 color = texture2D(texture, gl_TexCoord[0].xy);
    color.r = 1.0;
    gl_FragColor = color;
}

No vertex shaader, texture attribute is set to sf::Shader::CurrentTexture.

Red area is my polygon. But it has opacity :( I set red component to 1.0 so it should be fully red. I've also tried to use: color.b = 1.0; and nothing happens. Green attrbute works like red one.

What's wrong?

[attachment deleted by admin]
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #10 on: October 17, 2012, 02:33:53 pm »
Is it the full setup of your polygon (there's nothing else in your code?)?

What are we supposed to see on your screenshot? Can you explain it?

Can you show a screenshot of the texture which is applied to your polygon?
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #11 on: October 17, 2012, 02:42:32 pm »
>Is it the full setup of your polygon (there's nothing else in your code?)?
Yeah, that's everything I've applied to it.
Like you show before I'm trying here to store shape which would be passed to polygon:
    sf::Image image = mTarget->getTexture().copyToImage();
    sf::Image final;
    final.create(rect.width, rect.height);
    final.copy(image, 0, 0, rect);
    final.saveToFile("TEST.png");

The result in attachments. So there is normal image.

So what about scene: I have a water with dynamic surface. It could be changed with contacts of physic bodies. So I want to pass water polygon with surface deformation. In TEST.png you can see red line - surface line.

[attachment deleted by admin]
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #12 on: October 17, 2012, 02:46:06 pm »
In new attachment I made a blue rectangle - that area is saved into TEST.png in my previous post.

Some ideas: maybe, when I setPoint to the polygon I don't specify vertex color and it's maybe becomes sf::Color::Transparent. So, all vertices of polygon becomes transparent points and shader tries to interpolate  between them, that's why everything receives opacity. Could it be so?

[attachment deleted by admin]
« Last Edit: October 17, 2012, 02:47:55 pm by Ockonal »
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Polygon to shader
« Reply #13 on: October 17, 2012, 03:28:09 pm »
No, all the vertices of the polygon have the color defined with setFillColor, and it's opaque white by default (so that it doesn't interfere with the texture).

Are you sure that the source texture is opaque?

Once thing you can try, is to set color.a = 1.0 in your shader. That will give us more information about the source of the problem.
« Last Edit: October 17, 2012, 03:29:57 pm by Laurent »
Laurent Gomila - SFML developer

Ockonal

  • Jr. Member
  • **
  • Posts: 58
    • ICQ Messenger - 449909010
    • View Profile
    • WinCode
Re: Polygon to shader
« Reply #14 on: October 17, 2012, 03:41:57 pm »
TEST.png is opaque, so I think it really is.

color.a = 1.0 or  color.a = 0.0 doesn't affect on image. Still ~50% opacity for red color.
Developing 2d engine&game using: sfml, box2d, librocket, spark2, zoom&zoost, thor