SFML community forums

Help => Graphics => Topic started by: Qix on January 11, 2013, 06:17:14 am

Title: Shaders: General questions
Post by: Qix on January 11, 2013, 06:17:14 am
Alright so I've spent the past few days reading up on shaders. I know I'm probably going to get scolded and/or flamed for some/all of these but I figured I'd ask here. I'm trying to grasp a few things about shaders before I go about doing anything serious with them.

Here is a list of questions that have been on my mind for a while now and that pertain almost specifically to SFML (for the most part). I realize there are a lot, but hopefully a few of them can be answered at the least.

- To clip drawing textures, would I use a fragment shader as opposed to a vertex shader (and update the bounds using parameters?) then setting the alpha to 0 if the pixel lies outside of the bounds? My current understanding of shaders says yes but more or less I'd like some confirmation that I'm not too entirely crazy.

- Are shaders faster/more ideal than using sf::Sprite and an sf::Texture to draw images each frame?

- What's the difference (internally) between drawing an sf::Sprite with a texture and just a set of polygons with a shader that draws a texture specified? Is there any advantage? If SFML isn't using a built-in shader to do this, how is SFML drawing a texture to the screen?

- If shaders -are- faster, to draw an image with a shader (assuming the shader has been passed the appropriate texture as a parameter) would I just draw four points do the draw() method and then pass the shader as part of the render state?

- Are `uniform` constants (variables) in shaders just the parameters set by SFML's setParameter() method, verbatim?

- If so, what happens when I want to use a uniform constant that hasn't been set by the application? Is it undefined behavior?

- Are parameters sticky - meaning, if I set a parameter one frame, and not the next, does the value from the first time I set the parameter "stick" (persist) throughout the rest of the frames until it is explicitely set again?

- Can/will shaders lock up the computer if something unexpected happens (like drivers do)?

- For maximum compatibility (the application in question is not a game) should I target the lowest possible shader version?


Keep in mind I've been reading tons of articles on the structure of a shader, the pipeline flow, etc. However, I'm still trying to map out how exactly to incorporate shaders into my program. I've already decided to use them because I know there will be a direct advantage over my previous methods.
Title: Re: Shaders: General questions
Post by: Laurent on January 11, 2013, 08:14:50 am
Quote
- To clip drawing textures, would I use a fragment shader as opposed to a vertex shader (and update the bounds using parameters?) then setting the alpha to 0 if the pixel lies outside of the bounds? My current understanding of shaders says yes but more or less I'd like some confirmation that I'm not too entirely crazy.
Yes. There's even a GLSL function to discard a fragment, instead of hacking its alpha to 0.
There are other solutions for clipping but I don't think they are compatible with SFML.

Quote
- Are shaders faster/more ideal than using sf::Sprite and an sf::Texture to draw images each frame?
Shaders don't create anything, they just change how geometry and/or pixels are rendered. So you still need to feed them with geometry (sf::Sprite) and texture (sf::Texture).
You can't draw something with just shaders.

Quote
- What's the difference (internally) between drawing an sf::Sprite with a texture and just a set of polygons with a shader that draws a texture specified? Is there any advantage? If SFML isn't using a built-in shader to do this, how is SFML drawing a texture to the screen?
See my answer above. Shaders work on the provided geometry and texture, they don't replace them.
You should read more about the fixed pipeline functions and the graphics pipeline in general, probably on wikipedia.

Quote
- If shaders -are- faster, to draw an image with a shader (assuming the shader has been passed the appropriate texture as a parameter) would I just draw four points do the draw() method and then pass the shader as part of the render state?
Same answer, again.

Quote
- Are `uniform` constants (variables) in shaders just the parameters set by SFML's setParameter() method, verbatim?
Yes. But not verbatim: for example, sf::Color components are normalized. sf::Transform is passed as a 4x4 matrix.

Quote
- If so, what happens when I want to use a uniform constant that hasn't been set by the application? Is it undefined behavior?
Probably. Or maybe it has a default value of 0, I don't know.

Quote
- Are parameters sticky - meaning, if I set a parameter one frame, and not the next, does the value from the first time I set the parameter "stick" (persist) throughout the rest of the frames until it is explicitely set again?
Yes.

Quote
- Can/will shaders lock up the computer if something unexpected happens (like drivers do)?
Nop. They will just produce weird results.

Quote
- For maximum compatibility (the application in question is not a game) should I target the lowest possible shader version?
Probably. I think it's enough for most shaders -- unless you really want to implement crazy stuff.
Title: Re: Shaders: General questions
Post by: Qix on January 11, 2013, 09:40:45 am
Ahh so textures are applied using normalized coordinates per-vertex, much like assigning a color per-vertex? And the shader just works with the color/texture that's already there?

Also, thank you for the discard tip.

I think I was overthinking shaders. Really the whole process is quite simple in theory.

Thanks for all of the answer, Laurent!
Title: Re: Shaders: General questions
Post by: ZenonSeth on January 11, 2013, 02:51:48 pm
...
There are other solutions for clipping but I don't think they are compatible with SFML.
...

I'm doing rendering with sfml2.0 for my UI, and I use glScissor (http://www.opengl.org/sdk/docs/man/xhtml/glScissor.xml) to clip the rendering area (with a Textbox in my case) like this:
glScissor(position.x, position.y, size.x, size.y);
// do my background/text rendering using sfml here
glScissor(0,0,appw, apph);  // where appw and apph are the window's width and height, respectively.
 
The downside with using glScissor is that you can only clip to a rectangle area, but that's what I needed in my case.

Title: Re: Shaders: General questions
Post by: kaB00M on January 11, 2013, 08:16:07 pm
I  hope the OP doesn't mind, but I have some questions regarding shaders, and having all the answers in the same thread seems like something good to have. If not, my apologies and I will move this post to a new thread.

    My questions regard global post-effects using shaders:

1. Can sf::RenderWindow's applyShader function be used as a way to make post-effects. If the answer in no, the what's the purpose of it?

2. I tried using the 'sf::Texture::update(Window&)' method for applying post-effects as show here (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Shader.php). Initially it works fine, but if the window is re-sized the 'top image' doesn't update and I get a still image with the game running under it. I believe this is because the texture size have to be the same size as the window-view size, yet I tried changing the size of the texture on run time and the problem persists. Does anyone know how can this be fixed?

 Is my only option then the 'draw everything to a sf::RenderTexture' method?
Title: Re: Shaders: General questions
Post by: Laurent on January 11, 2013, 09:59:43 pm
Quote
1. Can sf::RenderWindow's applyShader function be used as a way to make post-effects. If the answer in no, the what's the purpose of it?
It's not public, you don't have to care about this function. Post-effects are explained in the documentation of sf::Shader.

Quote
2. I tried using the 'sf::Texture::update(Window&)' method for applying post-effects as show here. Initially it works fine, but if the window is re-sized the 'top image' doesn't update and I get a still image with the game running under it. I believe this is because the texture size have to be the same size as the window-view size, yet I tried changing the size of the texture on run time and the problem persists. Does anyone know how can this be fixed?
Please show a complete and minimal code that reproduces the problem (in a new thread).

Quote
Is my only option then the 'draw everything to a sf::RenderTexture' method?
Not the only one, but definitely the best.
Title: Re: Shaders: General questions
Post by: FRex on January 12, 2013, 09:34:30 am
Can I assign vec4 with non normalized components to gl_FragColor? (it's for computation, not graphics)
Title: Re: Shaders: General questions
Post by: Laurent on January 12, 2013, 09:42:27 am
Quote
Can I assign vec4 with non normalized components to gl_FragColor? (it's for computation, not graphics)
I don't know. Why don't you check directly? Or check in the GLSL specification?
Title: Re: Shaders: General questions
Post by: Ancurio on January 12, 2013, 02:52:30 pm
Can I assign vec4 with non normalized components to gl_FragColor? (it's for computation, not graphics)

Why not? It's just a bunch of floats. Although they must be normalized to be interpreted correctly I guess.
What would be the purpose of passing non-normalized floats to gl_FragColor? It's not like you can later
sample them 1 to 1 again from the resulting color..