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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Jamin Grey

Pages: [1] 2
1
Feature requests / sf::BlendMode::apply() function
« on: December 17, 2014, 05:15:55 am »
Hi! I love the new sf::BlendMode. I was planning to work around it with my own butchered hacks when SFML added it (I was specifically wanting Multiply2, or as PaintShopPro calls it, 'Overlay'). Thank you, gents!

Anyway, many of SFML's classes can be used directly with OpenGL, instead of going through SFML's 2D graphics API.

For example, sf::Shader and sf::Texture both have a bind() function.

Currently, if I want to use sf::BlendMode with OpenGL directly, I basically have to replicate the code in void sf::RenderTarget::applyBlendMode(const BlendMode& mode); (RenderTarget.cpp, line 421 in the current master)

Why not extract that exact same code into a new sf::BlendMode function (possibly called 'apply()' or maybe 'bind()')?

It'd look like this:
void BlendMode::apply() const
{
    // Apply the blend mode, falling back to the non-separate versions if necessary
    if (GLEXT_blend_func_separate)
    {
        glCheck(GLEXT_glBlendFuncSeparate(
            factorToGlConstant(colorSrcFactor), factorToGlConstant(colorDstFactor),
            factorToGlConstant(alphaSrcFactor), factorToGlConstant(alphaDstFactor)));
    }
    else
    {
        glCheck(glBlendFunc(
            factorToGlConstant(colorSrcFactor),
            factorToGlConstant(colorDstFactor)));
    }

    if (GLEXT_blend_equation_separate)
    {
        glCheck(GLEXT_glBlendEquationSeparate(
            equationToGlConstant(colorEquation),
            equationToGlConstant(alphaEquation)));
    }
    else
    {
        glCheck(GLEXT_glBlendEquation(equationToGlConstant(colorEquation)));
    }
}
(The only change is instead of taking 'mode' as a parameter, the class is directly using its own members)

And then RenderTarget::applyBlendMode() would be changed to this:
void RenderTarget::applyBlendMode(const BlendMode& mode)
{
     mode.apply();
     m_cache.lastBlendMode = mode;
}

Perfectly backwards compatible with prior SFML versions, cleans up RenderTarget of some of its responsibilities, and also makes sf::BlendMode more flexible and usable for general OpenGL users.

(Sorry for not contributing it directly to the GitHub. I don't currently have a GitHub account, and don't use git for my source control)

2
I got it to work using OpenGL functions intermixed with SFML draw calls:
//Set the currently selected texture to TEXTURE-1, for OpenGL functions to operate on.
glCheck(glClientActiveTextureARB(GL_TEXTURE1_ARB));
//Tell OpenGL that this texture (TEXTURE-1) is going to be used in the next draw call.
glEnable(GL_TEXTURE_2D);

//Give OpenGL (bypassing SFML) the second pair of texture coords.
const char* data = reinterpret_cast<const char*>(&maskTexCoords[0]);
glTexCoordPointer(2, GL_FLOAT, sizeof(sf::Vector2f), data);

//Tell OpenGL that we want to use texture coordinates for TEXTURE-1 in the next draw call.
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

//WARNING: Commented out as an optimization because SFML _currently_ doesn't get confused (SFML remembers to set the OpenGL active texture itself).
//If it later does, just uncomment this.
/*
        //Switch back to TEXTURE 0 being the selected OpenGL texture for functions to operate on, so SFML doesn't get confused.
        glClientActiveTextureARB(GL_TEXTURE0_ARB);
*/


//Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
destination.draw(vertices, 4, sf::Quads, states);

//Disable texture coordinates for TEXTURE 1.
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

//WARNING: Commented out as an optimization because SFML _currently_ doesn't get confused (SFML remembers to set the OpenGL active texture itself).
//If it later does, just uncomment this.
/*
        //Switch back to TEXTURE 0 being the selected OpenGL texture for functions to operate on, so SFML doesn't get confused.
        glClientActiveTextureARB(GL_TEXTURE0_ARB);
*/

//VERTEX SHADER

void main()
{
    //Transform the vertex position.
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    //Transform the texture's TexCoords.
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    //Transform the mask's TexCoords.
    gl_TexCoord[1] = gl_TextureMatrix[0] * gl_MultiTexCoord1;

    //Forward the vertex color.
    gl_FrontColor = gl_Color;
}

//FRAGMENT SHADER

uniform sampler2D texture;
uniform sampler2D mask;

//gl_Color
void main()
{
    vec4 textureColor = texture2D(texture, gl_TexCoord[0].xy);
    vec4 maskColor    = texture2D(mask, gl_TexCoord[1].xy);

    //Undo the alpha change by any algorithm, and instead use the alpha passed in as the 'Coloration' of the image.
    gl_FragColor = (textureColor * gl_Color);

    //Just use the red color channel of the mask for the alpha color.
    //But multiply it against the existing alpha instead of setting it, just incase the texture has alpha parts in it.
    gl_FragColor.a = (gl_FragColor.a * maskColor.r);
}
 

This kinda tricks SFML and isn't very stable since it depends on implementation details of SFML.



I'd definitely like a more native SFML method if it could be done.

I understand what you are saying about passing in GLSL uniforms using SFML, but I don't get how to use that to replace gl_MultiTexCoord1, since the vertex shader would make gl_MultiTexCoord1 a different value depending on which of the four vertices are being passed to the shader.

3
Not ideal, but will get you where you want to go.

Thanks for responding!

How would I write the vertex shader to use that?

I guess part of my confusion is a lack of familiarity with shaders:
void main()
{
    // transform the vertex position
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

What am I supposed to assign to gl_TextCoord[1]?

4
Okay, I got alot of it working now. My biggest challenge remaining is I have no clue how to pass in a second sf::FloatRect for the Vertex shader to use for the mask. Is this possible with SFML?

5
Hi, I'm new to OpenGL and shaders. Also, my math is poor so matrixes are throwing me for a loop.  :(
I'm trying to understand them while working through this task, and bits and pieces are coming together, but it's too many things coming at once so I'm getting confused.

I'm trying to take one grayscale sf::Texture, and use it as the alpha channel for another sf::Texture.
Okay, easy enough:
gl_FragColor = (texture2D(texture, gl_TexCoord[0].xy) * gl_Color);
gl_FragColor.a = texture2D(mask, gl_TextCoord[0].xy).a;
(where 'mask' is uniform sampler2D mask; passed into the shader)

My difficulties arise because:
A) I want the textures to be able to be mirrored horizontally and/or vertically.
B) I want the textures to be able to be rotated (the mask rotated relative to the main texture, and the mask only rotated in 90 degree increments)
C) I want the mask to stretch itself to conform to the size of the texture if the mask happens to be larger or smaller or of unequal width/height.
D) I want the two textures to be rotated seperately from each other.

For the sake of convenience and experimentation, I'm doing this in a C++ function called 'SfmlDrawTextureWithMask()', where I pass in the textures separately with their rotations and other settings.

Right now, I'm playing with a shader like this: (SFML's basic vertex shader example)
uniform mat4 textureOrientation;
//uniform mat4 maskOrientation;

void main()
{
    // transform the vertex position
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // transform the texture coordinates
    gl_TexCoord[0] = gl_TextureMatrix[0] * textureOrientation * gl_MultiTexCoord0;

    // forward the vertex color
    gl_FrontColor = gl_Color;
}

My problems so far, are that:
A) 'textureOrientation' isn't stretching to fill the texture, it's sampling outside of the texture and just has the usual bands of the border pixels:


I realize that this is because I'm rotating the texture coordinates and not the vertices themselves, and that I can use sf::Transform to rotate the primary sf::Texture by passing it into the secondary parameter of sf::RenderTarget::draw() - still, since I'm wanting to rotate the mask texture separately, I'm not sure exactly how to compensate for the rotation - I guess I could pass in the mask texture's size, use it to normalize the mask's texture coordinates, and then re-adjust with width and height swapped?

B) I don't know how gl_TexCoord[0] is created or passed to the fragment shader. It looks like an array (because of my C++ background), but I don't know the size of the array, so I don't know if that means I can just start using gl_TexCoord[1] to hold my mask texture's texture coordinates or if that'll overflow the buffer.

Why does gl_TexCoord[] and gl_MultiTexCoord0 exist? That seems to me like OpenGL supports binding multiple textures at once, but SFML only publicly exposes binding one texture at a time. Am I way off track here?
Is gl_TexCoord[1] available for me to use, and if so, do I have to do anything special to 'enable' it? I mean, I can't just use gl_TexCoord[999] can I?

Or to clarify my question: How do I pass my mask's separate texture coordinates from the vertex shader to the fragment shader (keeping in mind that they need to be interpolated for each fragment)?

And how do I get my mask's separate texture coordinates into the vertex shader in the first place? Especially considering that the mask might be only a subrect of a large texture container multiple masks. The first texture's tex coords are stored in gl_MultiTexCoord0, right? And they are passed into SFML using the attributes of the vertices - but a secondary mask texture wouldn't have vertices. How can I use SFML (or failing that, OpenGL) to put my mask texture's texcoords into gl_MultiTexCoord1?

Please keep your answers simple! I'm new to GLSL and OpenGL.  :-\

6
Graphics / Re: Why does SFML unbind the shader after each draw call?
« on: December 26, 2013, 05:17:10 am »
Ah, at the bottom of that source file is the revealing code comment:
// * Texture
//   Storing the pointer or OpenGL ID of the last used texture
//   is not enough; if the sf::Texture instance is destroyed,
//   both the pointer and the OpenGL ID might be recycled in
//   a new texture instance. We need to use our own unique
//   identifier system to ensure consistent caching.
//
// * Shader
//   Shaders are very hard to optimize, because they have
//   parameters that can be hard (if not impossible) to track,
//   like matrices or textures. The only optimization that we
//   do is that we avoid setting a null shader if there was
//   already none for the previous draw.

Gotcha.

7
Graphics / Why does SFML unbind the shader after each draw call?
« on: December 25, 2013, 10:22:21 pm »
In the source of SFML 2.0, in void RenderTarget::draw(...), I see this code:

Code: [Select]
void RenderTarget::draw(const Vertex* vertices, unsigned int vertexCount,
                        PrimitiveType type, const RenderStates& states)
{
    // Nothing to draw?
    if (!vertices || (vertexCount == 0))
        return;

    if (activate(true))
    {
        // First set the persistent OpenGL states if it's the very first call
        if (!m_cache.glStatesSet)
            resetGLStates();

        // Check if the vertex count is low enough so that we can pre-transform them
        bool useVertexCache = (vertexCount <= StatesCache::VertexCacheSize);
        if (useVertexCache)
        {
            // Pre-transform the vertices and store them into the vertex cache
            for (unsigned int i = 0; i < vertexCount; ++i)
            {
                Vertex& vertex = m_cache.vertexCache[i];
                vertex.position = states.transform * vertices[i].position;
                vertex.color = vertices[i].color;
                vertex.texCoords = vertices[i].texCoords;
            }

            // Since vertices are transformed, we must use an identity transform to render them
            if (!m_cache.useVertexCache)
                applyTransform(Transform::Identity);
        }
        else
        {
            applyTransform(states.transform);
        }

        // Apply the view
        if (m_cache.viewChanged)
            applyCurrentView();

        // Apply the blend mode
        if (states.blendMode != m_cache.lastBlendMode)
            applyBlendMode(states.blendMode);

        // Apply the texture
        Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
        if (textureId != m_cache.lastTextureId)
            applyTexture(states.texture);

        // Apply the shader
        if (states.shader)
            applyShader(states.shader);

        // If we pre-transform the vertices, we must use our internal vertex cache
        if (useVertexCache)
        {
            // ... and if we already used it previously, we don't need to set the pointers again
            if (!m_cache.useVertexCache)
                vertices = m_cache.vertexCache;
            else
                vertices = NULL;
        }

        // Setup the pointers to the vertices' components
        if (vertices)
        {
            const char* data = reinterpret_cast<const char*>(vertices);
            glCheck(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), data + 0));
            glCheck(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), data + 8));
            glCheck(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), data + 12));
        }

        // Find the OpenGL primitive type
        static const GLenum modes[] = {GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES,
                                       GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS};
        GLenum mode = modes[type];

        // Draw the primitives
        glCheck(glDrawArrays(mode, 0, vertexCount));

        // Unbind the shader, if any
        if (states.shader)
            applyShader(NULL);

        // Update the cache
        m_cache.useVertexCache = useVertexCache;
    }
}

That makes me curious. If it's bad for performance to change shaders and textures, so developers try to reduce those calls as much as possible, why does SFML unbind the shader after every draw call?

Is this a precaution incase the user of SFML lets the sf::Shader go out of scope?
Does the unbinding and then rebinding of the same shader cause a small hit to the performance?

I also noticed the sf::Texture getting bound, but not later unbound. Why is the sf::Shader unbound after the call, but not the sf::Texture?

I use SFML alot, and I'm an OpenGL noob trying to learn it, and I just encountered this in SFML's source and was curious.
If my code is entirely positive that the sf::Shader won't get destructed between two draw calls, do I still have to unbind it between them?
Also, do shaders ever need to be unbound when the program ends, or can I leave the last used shader bound? e.g. is it like calling delete() on what you new(), and important unbinding-processes are occuring, or is 'unbinding' just saying, "use the default shader" and not actually required to clean up when the program is exiting?

8
Np, thanks for having responded.

9
Odd, I searched the forums multiple times. :-X Clearly I wasn't using the correct search terms. ("mirroring texture", "texture flipping", etc...). I think I was limiting my search to just the Graphics subforum, but even so, that should've turned up something.

If I couldn't find it, when actively trying to, perhaps it should be made more prominently displayed someplace? Not that you should work to make things easier for me specifically, but I'm a fairly stubborn person who really does search to find a solution before posting asking for help - so other users might also be having difficulty finding that information. Or maybe it's just me having difficulty. ;)

When I searched the documentation, I didn't even think of checking sf::Sprite::setTextureRect (but I can't find it documented there either). What's the proper way to do it? If I do: setTextureRect(sf::IntRect(50, 50, -20, -20)), does that mean it'll grab the equivalent of (50,50,20,20) and then flip the texture, or does that mean it'll grab the equivalent of (30,30,50,50) flipped? I'm betting the latter, but if you're planning to document the feature, that'd be a good thing to mention.

Though, I still think the change:
Code: [Select]
//At "SFML/Graphics/Sprite.cpp" (line 161)
void Sprite::updateTexCoords()
{
    float left   = static_cast<float>(m_textureRect.left);
    float right  = left + m_textureRect.width;
    float top    = static_cast<float>(m_textureRect.top);
    float bottom = top + m_textureRect.height;

//----<added>----
if(m_flipHorizontally) std::swap(left, right);
if(m_flipVertically) std::swap(top, bottom);
//----</added>----

    m_vertices[0].texCoords = Vector2f(left, top);
    m_vertices[1].texCoords = Vector2f(left, bottom);
    m_vertices[2].texCoords = Vector2f(right, bottom);
    m_vertices[3].texCoords = Vector2f(right, top);
}

//----<added>----
void Sprite::setHorizontallyFlipped(bool flipped)
{
    m_flipHorizontally = flipped;
this->updateTexCoords();
}

void Sprite::setVerticallyFlipped(bool flipped)
{
    m_flipVertically = flipped;
this->updateTexCoords();
}
//----</added>----

...would be alot easier for users to understand. At least, it'd be alot easier for me to understand!  :)

10
I still needed a function that draws a single texture without using a sprite - I've nothing against sf::Sprite, and use it, but in a few parts of my code, sf::Sprite gets in the way more than it helps. In other areas, it's really useful.

I've heard that negative scales flip textures, but the information wasn't available - the last I heard (after searching these forums before writing it myself) was Laurent saying, "It doesn't work, but I'll consider it later" (2011 or somewhere thereabouts).

I checked the documentation, and it wasn't mentioned there. [sf::Transformable 2.0][sf::Transformable 2.1]
I also searched what others were doing on the forum, and they had weird clunky solutions using modified RenderTextures or by modifying SFML's sourcecode.

But even if setScale with negative numbers *does* work, it'd need to be added to the documentation (or maybe I'm just not seeing it?), and even if it did work, why *should* negative setScales flip textures? That's unintuitive (despite OpenGL doing the same thing), and a setHorizontallyFlipped(bool) and setVerticallyFlipped(bool) would be much more self-documenting in written code and easier to search for, right?

11
I wrote a function that allows you to draw a sf::Texture without using a sf::Sprite, and also allows you to flip/mirror the texture. I needed this for my own project, but hopefully others find it useful as well.

Here's the code:
void SfmlDrawTexture(sf::RenderTarget &destination, const sf::Vector2f &location, const sf::Texture &texture,
                                         sf::IntRect subRect, const sf::Color &coloration, float rotation,
                                         bool flipHorizontally, bool flipVertically, sf::BlendMode blendMode, const sf::Shader *shader)
{
        //If no rect is specified, use the entire texture.
        if(subRect.width == 0 || subRect.height == 0)
        {
                subRect.top = 0;
                subRect.left = 0;
                subRect.width = texture.getSize().x;
                subRect.height = texture.getSize().y;
        }
       
        //Set the position in space.
        sf::Transform translation;
        translation.translate(location);
       
        //Set the rotation (rotated around the center, since this sf::Transform wasn't moved).
        sf::Transform rotationTransform;
        rotationTransform.rotate(rotation);

        //Setup the render state.
        sf::RenderStates states(blendMode, (translation * rotationTransform), &texture, shader);
       
        //Setup the vertices and their attributes.
        sf::Vertex vertices[4];
       
        //The transparency:
        vertices[0].color = coloration;
        vertices[1].color = coloration;
        vertices[2].color = coloration;
        vertices[3].color = coloration;
       
        //The pre-transform position and size:
        float widthBeforeTransform = static_cast<float>(subRect.width);
        float heightBeforeTransform = static_cast<float>(subRect.height);
    vertices[0].position = sf::Vector2f(0, 0);
    vertices[1].position = sf::Vector2f(0, heightBeforeTransform);
    vertices[2].position = sf::Vector2f(widthBeforeTransform, heightBeforeTransform);
    vertices[3].position = sf::Vector2f(widthBeforeTransform, 0);
       
        //Calculate the texture coordinates:
        float left   = static_cast<float>(subRect.left);
    float right  = left + subRect.width;
    float top    = static_cast<float>(subRect.top);
    float bottom = top + subRect.height;
       
        //If we're mirroring, swap the texture coordinates vertically and/or horizontally.
        if(flipVertically)              std::swap(left, right);
        if(flipHorizontally)    std::swap(top, bottom);

        //Set the texture coordinates:
    vertices[0].texCoords = sf::Vector2f(left, top);
    vertices[1].texCoords = sf::Vector2f(left, bottom);
    vertices[2].texCoords = sf::Vector2f(right, bottom);
    vertices[3].texCoords = sf::Vector2f(right, top);
       
        //Use the sf::RenderTarget to draw the vertices using the sf::RenderStates we set up.
        destination.draw(vertices, 4, sf::Quads, states);
}
 

To handle mirroring, I swapped the texture coordinates... currently this only works because SFML doesn't disable back-face culling (at least, not in SFML 2.0), but whatever. =)

It'd be nice if this (flipping/mirroring) was available as a feature for sf::Sprites.

12
General / Re: Integration with Qt Widgets
« on: September 04, 2013, 11:53:29 pm »
I'm using Qt5.1 with SFML 2 - I haven't had much problems modifying the original SFML 1.6 / Qt 4.6 tutorial.

A few minor modifications were needed, though I forget what exactly I changed.

Here's the code I've been using successfully for several good months.

13
Graphics / Re: Drawing lines in sfml.
« on: August 02, 2013, 03:08:04 am »
Just incase someone doesn't realize thePyro_13 is joking, the old (SFML 1.6) removed function was called:
sf::Shape::Line and drew a single line slowly.

The new method (SFML 2.x), using sf::VertexArray, as eXpl0it3r mentioned, draws many lines at once (a much faster way to draw, if you're drawing more than one line).

14
I want to load a sf::Texture from memory, return it immediately, but start a new thread (using C++11's std::thread) that will (in a local thread-owned sf::Image) modify the pixel that, and upload the new pixel data when finished.

Can I call sf::Texture::update(sf::Image) from this new thread? My code doesn't call that specific function anyplace else, though it's possible the texture could be getting drawn at the exact same time.

15
Graphics / Re: Keeping objects at the same size, regardless of zoom
« on: July 27, 2012, 02:41:16 am »
Thankfully, I'm not using rotated views. I think, since I keep track of the scale anyway, I'll just scale it the opposite of what the view is scaling - it's working fine. I decided to actually slightly reduce the size of the text as it scales (because it obscures too much), so it does get somewhat smaller, but not as small as it'd normally get.

Thank you for the help.

Pages: [1] 2
anything