[2.1] Compositor texture ping pong
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
[2.1] Compositor texture ping pong
Hello! probably a very noob question, its something really simple but I cant make it work =(
I need to make a "brush" so I can paint on a texture, everything in shader code (no pass scenes, just pass quads).
I have this "brush" texture that paints the texture as I send the coordinates to the shader. the problem is that I need to sample in the shader the same texture that I am writing on so I can make my brush strokes persistent.
I think that's called ping pong, but I am having trouble to set that up in compositor scripts.
does anyone have a sample script that can share?
thanks in advance!
I need to make a "brush" so I can paint on a texture, everything in shader code (no pass scenes, just pass quads).
I have this "brush" texture that paints the texture as I send the coordinates to the shader. the problem is that I need to sample in the shader the same texture that I am writing on so I can make my brush strokes persistent.
I think that's called ping pong, but I am having trouble to set that up in compositor scripts.
does anyone have a sample script that can share?
thanks in advance!
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Compositor texture ping pong
Postprocessing sample does this.
There are many effects that need to do ping pong (e.g. Radial Blur)
It has two textures and alternates/swaps the Inputs & Outputs between the nodes in order to make the ping pong, thus Output 0 from Node A becomes Input 1 (source) for Node B and Output 1 becomes Input 0 (target); and the final output is always in Output 0
In a graphical way:
Alternatively, Bloom performs this ping pong within the same node on "rt0" and "rt1" which are both 1/4th of the RTT resolution, and alternate between rendering to rt0 and rt1.
Depending on what you need to do, you may have to use a pass_quad to copy rt0(input) -> rt1(target), and then render with your intended shader to rt0(target) by sourcing from rt1(input).
This would be the case if your shader performs alpha blending:
There are many effects that need to do ping pong (e.g. Radial Blur)
It has two textures and alternates/swaps the Inputs & Outputs between the nodes in order to make the ping pong, thus Output 0 from Node A becomes Input 1 (source) for Node B and Output 1 becomes Input 0 (target); and the final output is always in Output 0
In a graphical way:
Alternatively, Bloom performs this ping pong within the same node on "rt0" and "rt1" which are both 1/4th of the RTT resolution, and alternate between rendering to rt0 and rt1.
Depending on what you need to do, you may have to use a pass_quad to copy rt0(input) -> rt1(target), and then render with your intended shader to rt0(target) by sourcing from rt1(input).
This would be the case if your shader performs alpha blending:
Code: Select all
compositor_node MagicShaderNode
{
in 0 rt_input
in 1 rt_output
custom_id Ogre/Postprocess
//Copy rt_input -> rt_output so that both RTTs contain exactly the same
target rt_output
{
pass render_quad
{
load { all dont_care }
material Ogre/Copy/4xFP32
input 0 rt_input
}
}
target rt_input
{
pass render_quad
{
material Postprocess/YourMagicShaderWithAlphaBlending
input 0 rt_output
}
}
//Do NOT swap, because we've performed two passes and now rt_input
//contains the last render and should be the output of this node
out 0 rt_input
out 1 rt_output
}
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
Re: [2.1] Compositor texture ping pong
thank you!
I actually didn't find the file Postprocessing.compositor until just now, I thought it was all done in code since it wasn't in the scripts\Compositors folder...
So I managed to copy the Bloom script part, so I have something like this:
the "DisplaceMat" has this shader (for testing)
but I have no "PostprocessingSampleStdRenderer" analog since I render everything via shader, I tried something like this:
but its not working (the brush just moves, its not persistent)
still not sure where the ping pong part is xD
I actually didn't find the file Postprocessing.compositor until just now, I thought it was all done in code since it wasn't in the scripts\Compositors folder...
So I managed to copy the Bloom script part, so I have something like this:
Code: Select all
compositor_node WeldDisplaceRenderingNode
{
in 0 rt_input
in 1 rt_output
texture rt0 target_width target_height PF_FLOAT16_R
target rt0
{
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rt_input
}
}
target rt_output
{
pass render_quad
{
material DisplaceMat
input 0 rt_input
input 1 rt0
}
}
out 0 rt_output
out 1 rt_input
}
compositor_node FinalComposition
{
in 0 rt_output
in 1 rtN
target rt_output
{
pass clear
{
colour_value 1 0 0 1
buffers colour
discard_only true
}
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rtN
}
}
}
workspace WeldDisplaceRenderingWorkspace
{
connect PostprocessingSampleStdRenderer WeldDisplaceRenderingNode
connect_output FinalComposition 0
connect WeldDisplaceRenderingNode 0 FinalComposition 1
}
Code: Select all
#version 330
layout(location = 0, index = 0) out vec4 outColour;
in block
{
vec2 uv0;
} inPs;
uniform sampler2D RT;
uniform sampler2D Blur1;
uniform sampler2D brushSampler;
uniform vec2 brushPos;
void main()
{
vec4 brush = texture( brushSampler, inPs.uv0*10 + brushPos );
vec4 sharp = texture( RT, inPs.uv0 );
vec4 blur = texture( Blur1, inPs.uv0 );
outColour = blur + sharp + brush;
}
Code: Select all
compositor_node PostprocessingSampleStdRenderer
{
texture rt0 target_width target_height PF_FLOAT16_R
texture rt1 target_width target_height PF_FLOAT16_R
target rt0
{
pass clear
{
buffers depth
}
}
target rt1
{
pass clear
{
buffers depth
}
}
out 0 rt0
out 1 rt1
}
still not sure where the ping pong part is xD
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Compositor texture ping pong
I don't know what you're trying to do.
This:
Is the same as this:
And with the definition of PostprocessingSampleStdRenderer you posted, you're not ping ponging anything. rt0 & rt1 are both uninitialized and most likely Windows is initializing them for you to black (you should NOT rely on this behavior) so you're just rendering what's in brushSampler:
To fix the uninitialization, perform a clear and use num_initial 1 to just do it on the first frame.
I suspect you want some form of accumulation of results, like Motion Blur (this one is created from C++ to show how to do it from C++...). If that's the case you should do this:
HDR may be a good example of this:
HdrRenderingNode creates oldLumRt which contains the Luminance from last frame, and clears oldLumRt only on the first frame to set an initial value
HdrPostprocessingNode computes auto-exposure on lumRt0 by averaging the current luminance and the one stored from previous frame in lumRt1 (lumRt1 is oldLumRt). After that, it copies lumRt0 -> lumRt1 so that it can carry over the value to the next frame.
In pseudo code:
This is the same, but in the compositor.
This:
Code: Select all
compositor_node WeldDisplaceRenderingNode
{
...
target rt0
{
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rt_input
}
}
target rt_output
{
pass render_quad
{
material DisplaceMat
input 0 rt_input
input 1 rt0
}
}
...
}
Code: Select all
compositor_node WeldDisplaceRenderingNode
{
...
target rt0
{
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rt_input
}
}
target rt_output
{
pass render_quad
{
material DisplaceMat
input 0 rt_input
input 1 rt_input //<---
}
}
...
}
Code: Select all
outColour = blur = 0 + sharp = 0 + brush;
//Thus:
outColour = brush;
I suspect you want some form of accumulation of results, like Motion Blur (this one is created from C++ to show how to do it from C++...). If that's the case you should do this:
Code: Select all
compositor_node WeldDisplaceRenderingNode
{
...
target rt0
{
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rt_input
}
}
target rt_output
{
pass render_quad
{
material DisplaceMat
input 0 rt_input
input 1 rt0
}
}
//Copy rt_output -> rt_input AFTER you've executed your shader, so the results are carried over for the next frame.
target rt_input
{
pass render_quad
{
material Ogre/Copy/4xFP32
input 0 rt_output
}
}
...
}
HdrRenderingNode creates oldLumRt which contains the Luminance from last frame, and clears oldLumRt only on the first frame to set an initial value
HdrPostprocessingNode computes auto-exposure on lumRt0 by averaging the current luminance and the one stored from previous frame in lumRt1 (lumRt1 is oldLumRt). After that, it copies lumRt0 -> lumRt1 so that it can carry over the value to the next frame.
In pseudo code:
Code: Select all
float oldLumRt = 1.0f;
while( true )
{
float lumRt = calculateLuminance();
lumRt = (lumRt + oldLumRt) * 0.5f;
oldLumRt = lumRt; //Carry over to the next frame.
}
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 168
Re: [2.1] Compositor texture ping pong
thanks again!
I understand what I was missing now
thank you so much!! and sorry for the noob question, not so "OGRE Expert User" by my side
yeah.. that's what I was aiming for, because I dint know this:dark_sylinc wrote: ↑Wed Oct 24, 2018 12:03 am And with the definition of PostprocessingSampleStdRenderer you posted, you're not ping ponging anything
dark_sylinc wrote: ↑Wed Oct 24, 2018 12:03 am To fix the uninitialization, perform a clear and use num_initial 1 to just do it on the first frame.
This makes it work!!dark_sylinc wrote: ↑Wed Oct 24, 2018 12:03 am I suspect you want some form of accumulation of results, like Motion Blur (this one is created from C++ to show how to do it from C++...). If that's the case you should do this:
I understand what I was missing now
thank you so much!! and sorry for the noob question, not so "OGRE Expert User" by my side