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

Author Topic: Transparencies with VertexArray tilemaps  (Read 3041 times)

0 Members and 2 Guests are viewing this topic.

saeyne

  • Newbie
  • *
  • Posts: 4
    • View Profile
Transparencies with VertexArray tilemaps
« on: December 02, 2012, 08:14:38 am »
Hello, I have searched the forums for an answer to my question, along with delving through the documentation, and have not figured this out, so I decided to finally post it to see some responses!

I am currently in the process of creating my Map class out of a vector of Layers (Which are just fancy wrappers for VertexArrays and their relative Textures.)  I would like to be able to change transparencies of Layers and I am not quite sure how I would do this.  Is there a way to set a transparency of a texture? 

I noticed that I could possibly use Texture::update( const Uint8 * pixels ), but then would I have to traverse every pixel of texture to change its alpha level?

The other option I am trying to figure out, is with the RenderWindow draw call for the vertex array, and sending it a RenderState, although I am not seeing anything specific about sending an alpha value this way.

Any input on this would be greatly appreciated!

Thanks,
Saeyne


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Transparencies with VertexArray tilemaps
« Reply #1 on: December 02, 2012, 08:37:24 am »
There's no direct way to do this. The best option would be to use a fragment shader; otherwise the second best solution is to change the color (alpha component) of every vertex in your vertex array.
Laurent Gomila - SFML developer

saeyne

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Transparencies with VertexArray tilemaps
« Reply #2 on: December 02, 2012, 08:42:08 am »
Thanks for the quick response!

I will get to messing around with both of these options :)

saeyne

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Transparencies with VertexArray tilemaps
« Reply #3 on: December 05, 2012, 02:39:20 am »
Ok, so I am looking into fragment shaders, and I *think* I understand the idea behind it, but I am having difficulty with putting it all together.  As in, I am having difficulty figuring out the draw call.

Also, I am unsure if I am even doing the shader correctly, I have no experience with GLSL aside from some research yesterday and today. 

What I am trying to do (incorrectly) is, create my vertex array and draw it with a transparency fragment shader. 

I have my vertex array drawn like this:

sf::RenderWindow        rw;
sf::VertexArray         vertexArray;
sf::Texture             texture;

//fill in the vertex array
//load the texture

rw.draw(vertexArray, texture);
 

Now, so far with a fragment shader, this is all I have:

sf::RenderWindow        rw;
sf::VertexArray         vertexArray;
sf::Texture             texture;
sf::Shader              transparencyShader;

//fill in the vertex array
//load the texture

//assign our shader
float transparency = 0.5;
transparencyShader.setParameter("color", sf::Color(1.0, 1.0, 1.0, transparency));

//now draw, but how do I add the shader in?
//rw.draw(vertexArray, texture);
 

Looking through the documentation and other posts,  I am under the impression that I would have to draw the vertex array and its texture to a RenderTexture, then hold the shader in a RenderState, and then call draw on the render window with the RenderTexture and RenderState as arguments.  However, I am not having much luck with this.  The error I am running into is that its not finding a draw call that takes these arguments.  However, I feel the problem is more of my understanding of how they all fit together, and then it breaks due to me telling it to behave in ways it doesn't understand :P 

Am I on the right track with this?  Also, is it correct for me to just make an sf::Shader and use setParameter() to create my fragment shader, or is it necessary to create it first from GLSL?

Thanks!

Edit:

Found a great example (http://en.sfml-dev.org/forums/index.php?topic=9767.msg66818#msg66818) and I now have a shader "working", just not as I intended.  I suppose it makes sense, based on my shader, just need to read and learn more on GLSL to figure out how to maintain the color (255, 255, 255, transparency?)

const char* fragShaderCode = "void main() { gl_FragColor = vec4(0,0,0,0.1);}";
sf::Shader transparencyShader;
transparencyShader.loadFromMemory(fragShaderCode, sf::Shader::Fragment);
sf::RenderStates renderState;
renderState.shader = transparencyShader;
 

Edit 2:  Yeah, I think I have the shader working, just need to find the right way to make a shader that can apply a transparency :)
« Last Edit: December 05, 2012, 08:09:05 am by Laurent »

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Transparencies with VertexArray tilemaps
« Reply #4 on: December 05, 2012, 04:30:26 am »
If you've got a couple 640x480 images laying around, you can try out the following:

#include <SFML\Graphics.hpp>

void main()
{
    sf::RenderWindow window(sf::VideoMode(640, 480), "SFML - Transparency");
   
    sf::Texture base ;
    base.loadFromFile("base.png");

    sf::Texture overlay ;
    overlay.loadFromFile("overlay.png") ;

    sf::Vertex wholeScreen[] =
    {
       sf::Vertex(sf::Vector2f(  0,  0), sf::Vector2f(  0,  0)),
       sf::Vertex(sf::Vector2f(639,  0), sf::Vector2f(639,  0)),
       sf::Vertex(sf::Vector2f(  0,479), sf::Vector2f(  0,479)),
       sf::Vertex(sf::Vector2f(639,479), sf::Vector2f(639,479))
    };

    float overlayOpacity = 0.5f ;

    sf::Shader transparency ;
    transparency.loadFromFile("transparency.frag", sf::Shader::Fragment) ;
    transparency.setParameter("opacity", overlayOpacity) ;
    transparency.setParameter("texture", sf::Shader::CurrentTexture) ;

    sf::RenderStates overlayStates ;
    overlayStates.blendMode = sf::BlendAlpha ;
    overlayStates.shader = &transparency ;
    overlayStates.texture = &overlay ;

    while ( window.isOpen() )
    {
        sf::Event event ;
        while ( window.pollEvent(event) )
        {
            if ( event.type == sf::Event::Closed )
                window.close() ;
            else if ( event.type == sf::Event::KeyReleased )
            {
                if ( event.key.code == sf::Keyboard::Equal )
                    if ( (overlayOpacity += 0.1f) > 0.9f )
                        overlayOpacity = 1.0f ;

                if ( event.key.code == sf::Keyboard::Dash )
                    if ( (overlayOpacity -= 0.1f) < 0.1f )
                        overlayOpacity = 0.0f ;
            }
        }

        transparency.setParameter("opacity", overlayOpacity) ;

        window.clear() ;
        window.draw(wholeScreen, 4, sf::TrianglesStrip, &base) ;
        window.draw(wholeScreen, 4, sf::TrianglesStrip, overlayStates) ;
        window.display() ;
    }
}

transparency.frag:
uniform float opacity ;
uniform sampler2D texture;

void main()
{
    vec4 color = texture2D(texture, gl_TexCoord[0].xy);
    color.a *= opacity ;
    gl_FragColor = color ;
}
 
« Last Edit: December 05, 2012, 08:11:26 am by Laurent »

saeyne

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Transparencies with VertexArray tilemaps
« Reply #5 on: December 05, 2012, 04:46:47 am »
Thanks Cire!  I think I have a solid enough understanding to incorporate this into my map!