SFML community forums

Bindings - other languages => DotNet => Topic started by: Conduit on March 20, 2015, 08:37:38 pm

Title: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 20, 2015, 08:37:38 pm
I am creating a program which uses the previously rendered frame to create an illusion of movement. In essence:
For those familiar with the WinAmp visualizer 'Milkdrop', this process should be relatively familiar... the outcome should be more or less identical.

For testing, I am drawing a square to the RenderTexture. The square renders just fine, but the shader effects don't seem to ever be applied... This is my first time working with GLSL within any SFML program (.NET or otherwise), so I'm likely missing something (and it's probably something stupid - apologies in advance). Code below:

(click to show/hide)

(click to show/hide)
Title: Re: Fragment shader render-to-texture not working as expected
Post by: zsbzsb on March 20, 2015, 08:53:55 pm
Quote
The RenderTexture is re-rendered to itself

That simply won't work. You need a second RenderTexture to draw your original onto with your post affects (or draw directly to the window).
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 20, 2015, 09:00:28 pm
Perhaps I am missing the point of the function
m_Shader.SetParameter("texture", Shader.CurrentTexture);
then? I thought that could cause trouble, but it looked like RenderTextures were double buffered and I figured that'd take care of the obvious problems... It'd be easy enough to fix this with another texture for "buffering" the new render, I guess, though afaik the inability to do a deep copy could result in a fair amount of overhead. If it's not prohibitively difficult to explain why this is the case, I'd love to know.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Laurent on March 20, 2015, 09:07:13 pm
OpenGL strictly disallows drawing a texture onto itself. The result wouldn't be consistent, and I think the reason is obvious enough ;)

Quote
I thought that could cause trouble, but it looked like RenderTextures were double buffered
Nop.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: zsbzsb on March 20, 2015, 09:13:04 pm
Always refer to the documentation (http://www.sfml-dev.org/documentation/2.2/structsf_1_1Shader_1_1CurrentTextureType.php) when in doubt. Shader.CurrentTexture simply refers to the source that will be drawn onto the target.

Quote
it looked like RenderTextures were double buffered

That is not stated anywhere and wouldn't provide any benefit to have all RenderTextures double buffered.

Quote
inability to do a deep copy could result in a fair amount of overhead

Why? If I understand what you want to do - you want to keep updating a texture with itself drawn with a shader. Then simply implement your own buffering system. Draw what you want to texture #1. Then draw it with your post affects to #2 and then finally to your window. On the next frame draw to #2 whatever you need and then draw with post affects to #1 and then finally to the window. And repeat with switching the texture order... voila! you got double buffering and the solution to your problem.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 20, 2015, 09:18:39 pm
...and here I was hoping I'd found a gloriously simple loophole. I just KNEW this was gonna be trouble. I am now curious as to why RenderTexture.Display() is a thing. What's going on there?

Compositing on another texture should be fine (love that solution, btw, zsbzsb). Am I correct in assuming that when I call
target.draw(array, states)
'Shader.CurrentTexture' allows states.Shader to reference states.Texture?

EDIT: after further reading I think I've worked this out. It's not working yet, but I think I'm on the right track...
Title: Re: Fragment shader render-to-texture not working as expected
Post by: zsbzsb on March 20, 2015, 10:12:31 pm
Am I correct in assuming that when I call
target.draw(array, states)
'Shader.CurrentTexture' allows states.Shader to reference states.Texture?

Yes.

after further reading I think I've worked this out. It's not working yet, but I think I'm on the right track...

Make sure you share with us what it looks when you are done.  ;)
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 20, 2015, 10:26:31 pm
You say that like you could stop me, haha.

Might be a minute... currently getting no output from my self-implemented buffer (code below, if you're interested).

(click to show/hide)
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Laurent on March 20, 2015, 10:28:06 pm
Quote
I am now curious as to why RenderTexture.Display() is a thing. What's going on there?
Almost nothing.

https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/RenderTexture.cpp#L124
https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/RenderTextureImplFBO.cpp#L140
https://github.com/SFML/SFML/blob/master/src/SFML/Graphics/RenderTextureImplDefault.cpp#L79
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Laurent on March 20, 2015, 10:31:37 pm
Quote
RenderStates states = new RenderStates();
Don't use the default constructor, or overwrite all properties. My advice: don't reuse RenderStates, instanciate them directly in Draw calls, with all the relevant arguments directly given to their constructor.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 20, 2015, 10:38:46 pm
Mm, that seems to have fixed it, though the got-dang shader still isn't working.

I take it RenderStates' default constructor doesn't just default to the "normal" states? Have a couple C++ projects that need some code changes, in that case. Odd that I haven't run into this before.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Laurent on March 20, 2015, 10:48:12 pm
Quote
I take it RenderStates' default constructor doesn't just default to the "normal" states? Have a couple C++ projects that need some code changes, in that case. Odd that I haven't run into this before.
In C++ it works fine. It's purely a C# thing: in C#, structs cannot have a user-defined default constructor. You are forced to get the compiler-generated one, which sadly puts zeroes everywhere, which isn't suitable for all properties of RenderStates.

Another "workaround" is to initialize your RenderStates instance to RenderStates.Default instead of calling the default constructor.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 21, 2015, 12:25:26 am
Quote
You are forced to get the compiler-generated one, which sadly puts zeroes everywhere, which isn't suitable for all properties of RenderStates.

Ah, yeah, that makes sense. I imagine that'd end up trying to use a bunch of null pointers - not good.

We have results, though they're incorrect!

Must have messed up the shader somewhere, as it appears I've made a starfield generator. Working on it, but I am pretty rightly confused at this point... probably come back to it fresh in the morning. Feel free to peruse my code - tex coords mimic screen coords in all VertexArrays.

(click to show/hide)
(click to show/hide)
(click to show/hide)
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 21, 2015, 06:41:29 pm
Out of curiosity: do SFML or SFML.NET possess any methods that allow 4-component (or multiple) texture vertices to be added to a VertexArray? It would be LOVELY if I could add polar coordinates to simplify a couple shader calculations I have planned.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Laurent on March 21, 2015, 07:00:46 pm
Vertex definition in SFML is fixed:

2 floats for position
4 uint8 for color
2 floats for texture coordinates

If you don't use one of these attributes you can recycle its components for your own needs, otherwise you won't be able to do what you want with SFML.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 21, 2015, 07:20:05 pm
Figured that was the case, since the documentation doesn't mention anything. Bummer! Doubt I have the OpenGL know-how to extend anything but the most simple portions of the SFML graphics library at present... For now I guess I'll just have a little extra trig in my shaders. Thanks Laurent.
Title: Re: Fragment shader render-to-texture not working as expected
Post by: zsbzsb on March 21, 2015, 11:46:08 pm
It would be LOVELY if I could add polar coordinates to simplify a couple shader calculations I have planned.

My NetEXT project (port of Thor) contains a PolarVector which supports conversion to SFML's vector type. See my signature for links.

https://bitbucket.org/zsbzsb/netext/src/c4192b6723eafea9eb8913634cfda7b98b17dd72/NetEXT/Vectors/PolarVector.cs?at=master
Title: Re: Fragment shader render-to-texture not working as expected
Post by: Conduit on March 24, 2015, 06:59:11 pm
As expected, the problem was due to my noobishness with regard to OpenGL/GLSL. I'd assumed (in error) that texture coordinates being uploaded in pixels inferred that GLSL wouldn't follow the typical 0...1 standards for texture sampling. Kinda silly in retrospect. Output is a little stuttered, but I'm also using Intel HD Graphics on a three-year-old laptop, so whatevs.

zsbzsb and Laurent - I won't say my introduction to GLSL was painless by any means, but with your help it was at least palatable. Many thanks! :)

Sample output using exponential zoom, warping, color dampening, and a square for input is attached. Unfortunately I can't upload a video displaying how awesome this looks (re: Intel HD Graphics).