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

Author Topic: Fragment shader render-to-texture not working as expected  (Read 8810 times)

0 Members and 1 Guest are viewing this topic.

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Fragment shader render-to-texture not working as expected
« 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:
  • Objects are drawn on a RenderTexture
  • The RenderTexture is drawn to a RenderWindow using a full-screen quad
  • The RenderTexture is re-rendered to itself with a handful of shader effects
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)
« Last Edit: March 20, 2015, 10:11:20 pm by Conduit »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #1 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).
« Last Edit: March 20, 2015, 08:57:48 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #2 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.
« Last Edit: March 20, 2015, 09:02:48 pm by Conduit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #3 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.
Laurent Gomila - SFML developer

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #4 on: March 20, 2015, 09:13:04 pm »
Always refer to the documentation 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.
« Last Edit: March 20, 2015, 09:16:15 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #5 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...
« Last Edit: March 20, 2015, 10:09:47 pm by Conduit »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #6 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.  ;)
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #7 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)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #9 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.
Laurent Gomila - SFML developer

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #10 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.
« Last Edit: March 20, 2015, 10:41:12 pm by Conduit »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #11 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.
« Last Edit: March 20, 2015, 10:50:30 pm by Laurent »
Laurent Gomila - SFML developer

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #12 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)
« Last Edit: March 21, 2015, 08:49:28 am by Conduit »

Conduit

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: Fragment shader render-to-texture not working as expected
« Reply #13 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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Fragment shader render-to-texture not working as expected
« Reply #14 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.
Laurent Gomila - SFML developer