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

Author Topic: Fragment Shader gl_FragCoord to SFML world coordinate  (Read 2090 times)

0 Members and 1 Guest are viewing this topic.

mistergiraffe

  • Newbie
  • *
  • Posts: 2
    • View Profile
Fragment Shader gl_FragCoord to SFML world coordinate
« on: August 14, 2020, 09:00:36 am »
Hello, I am trying to write a fragment shader that will black out anything a fixed distance around a position (like a maximum view range). The circle drawn by this shader is expected to get smaller when zoomed out as it should be of constant radius in world coordinates.

const std::string distanceFragShaderStr =
//Max dist from pos to draw
"uniform float maxDist;"
//Position to draw around
"uniform vec2 pos;"
"void main() {"
        //How to calculate?
        "vec2 fragpos = ?;"

        "if (distance(pos,fragpos) > maxDist) {"
                //Set as black (too far)
                "gl_FragColor = vec4(0.0,0.0,0.0,1.0);"
        "}"
        "else {"
                // Set as see through
                "gl_FragColor = vec4(0.0,0.0,0.0,0.0);"
        "}"
"}";
 

This shader is to be drawn to a rectangle covering the entire screen(which contains the point pos):

sf::Shader distanceShader;
if (!distanceShader.loadFromMemory(distanceFragShaderStr, sf::Shader::Fragment)) {
        std::cout << "Shader did not compile!\n";
        return -1;
}
sf::RectangleShape backgroundRect(view.getSize());
backgroundRect.setOrigin(backgroundRect.getSize() / 2.0f);
backgroundRect.setPosition(view.getCenter());
distanceShader.setUniform("pos", sf::Vector2f(window.getSize()) / 2.0f);
distanceShader.setUniform("maxDist", 400.0f);

//...

window.draw(backgroundRect, &distanceShader);
 

But I cannot seem to work out how to calculate fragpos, i.e. the world coordinates of the current fragment. I assume it needs some uniforms such as the current view size, position but I cant figure out how it is calculated, does anyone know how this could be achieved? I saw some posts about using gl_TexCoord[0] but couldn't get any results with it.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Fragment Shader gl_FragCoord to SFML world coordinate
« Reply #1 on: August 15, 2020, 11:21:27 pm »
Fragment co-ordinates are within a pixel co-ordinate system (fragments are pixels). You can calculate in your program how many pixels that distance is and send it to you shader via a uniform.
To convert from your (view) co-ordinates to pixel co-ordinates, you can use your render target's (e.g. window) conversion method: mapCoordsToPixel. See: https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1RenderTarget.php#ad92a9f0283aa5f3f67e473c1105b68cf

For example, if you know that your distance should be 50 units regardless of zoom, you can map two co-ordinates of 50 units apart and use the distance, possibly something like this:
// presuming "window" is a render target (render window, for example)
sf::Vector2f zero{ 0.f, 0.f };
sf::Vector2f fifty{ 50.f, 0.f };
sf::Vector2i zeroPixel{ window.mapCoordsToPixel(zero) };
sf::Vector2i fiftyPixel{ window.mapCoordsToPixel(fifty) };
int pixelDistance{ fiftyPixel.x - zeroPixel.x };

Then, send pixelDistance to the shader and it knows the fragment distance (in pixels).
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

mistergiraffe

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Fragment Shader gl_FragCoord to SFML world coordinate
« Reply #2 on: August 17, 2020, 04:22:27 am »
This works great for getting distances between fragments, in the end I had to convert the position to fragment coordinates (with an inverted y axis for some reason...) and pass this to the shader along with the distance.

Hapax

  • Hero Member
  • *****
  • Posts: 3351
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Fragment Shader gl_FragCoord to SFML world coordinate
« Reply #3 on: August 23, 2020, 12:20:57 am »
(with an inverted y axis for some reason...)
Ah, that's true.
OpenGL's fragment co-ordinate system is the standard +y upwards (like normal mathematics graphs, for example) whereas SFML inverts this to match the common - and often much more useful - (0, 0) at top-left (+y downwards)
You may need to send the window height to the shader too if you need accurate positioning. e.g. window height - SFML y (pixel) position = fragment y position.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*