🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Can I apply post processing to different portions of the screen?

Started by
9 comments, last by ddlox 3 years, 8 months ago

Hello all! I've managed to render multiple scenes and split them into 4 “monitors" similar to CCTV thanks to help from you all.

However, my post processing effects are of course rendering at full screen. Effects like vignette or just curving the screen are rendering at window size. Hopefully you can notice the window split in 4 screens though.

Is there a way I can specify the viewport x,y, width, height but in GLSL? For example, I got a curve function from shader toy:

vec2 curve(vec2 uv) {
uv = (uv - 0.5) * 2.0;
uv *= 1.1;
uv.x *= 1.0 + pow((abs(uv.y) / 5.0), 2.0);
uv.y *= 1.0 + pow((abs(uv.x) / 4.0), 2.0);
uv  = (uv / 2.0) + 0.5;
uv =  uv *0.92 + 0.04;
return uv;
}

and to make it work I just replace the current uv vec2 with one calculated by the curve function:

vec2 uvs = curve( uv );

What I'm trying to do is apply the curve effect to all 4 screens. I have no idea how to do this :( What if I wanted to add a glitch effec to each one? I hope my question made sense, not good with words.

Thanks all, always helpful!

Btw, I'm sure you all know this, but just in case: I'm using 1 FBO to record the scene and render the scene texture to a quad that takes up the screen, which is what yous see above.

Advertisement

Wouldn't it be more easy to instead shift the UV coords of your quad and instead render 4 quads which each cover ¼rd of the screen? This way you don't have to bother with shader offsets instead of apply your post processing to each quad one at a time.

UV coords usually range from 0 to 1, you could instead use 0 to 0.5 e.g. 0.5 to 1 to just render half of your texture in each direction

…. or you can still use 1 quad, 1 fbo, but then what u do is each time u render a viewport, tell your shader what viewport is currently active (u can submit this as integer to your shader via uniform (glsl) or constant buffer (hlsl) along side some other effects parameters).

In yr shader u can then do, assuming that ID 0 is your left-top viewport, …:

//pseudo for glsl
uniform int viewport_id;
uniform int curve_force_parameter_from_infinity_and_beyond;
uniform bool enable_effectXXX;

// get the correct uv for a given viewport
// remember that in gl, coords go from 0,0 at the (left,bottom) of yr screen to 1,1 to (top,right)
// so from the bottom up, here we go:

vec2 min_uv ;
vec2 max_uv ;

void find_range()
{
	if (viewport_id == 0) // left top vp
  	min_uv = vec2(0, 0.5), max_uv = vec2(0.5, 1)

	if (viewport_id == 1) // right top vp
  	min_uv = vec2(0.5, 0.5),  max_uv = vec2(1, 1)

	if (viewport_id == 2) // left botm vp
  	min_uv = vec2(0, 0), max_uv = vec2(0.5, 0.5)

	if (viewport_id == 3) // right botm vp
   	min_uv = vec2(0.5, 0), max_uv = vec2(1, 0.5)
}
   
void apply_curve_on_vp (uv) 
{
  if ( min_uv <= uv <= max_uv)
  {
  		// curve it and use curve_force_parameter_from_infinity_and_beyond to apply on effect
  }
}

void apply_glitch_on_vp (uv) 
{
  if (min_uv <= uv <= max_uv)
  {
  }
}

// call
if (enable_effectXXX)
    apply_XXXXXX_on_vp(uv);
...
apply_YYYYYY_on_vp(uv);
...

Double-check on these texture coord space values as I'm writing from the top of my head, but it should do the trick ?

The effect will only be applied if the current uv falls in a given range.

U can send to the shader another uniform to toggle the effect on/off as u wish… etc…

That's it … all the best ?

Sorry @ddlox but this solution is slow at it's best and very work intensive in worst case. If you think about it, you'll see that this won't work in a single render pass, so you have to render the same quad 4 times which will result in a much slower solution than rendering 4 quads at once (which can be baked into one single render pass). Because how will your shader know which viewport you currently want to render … it needs input from the outside and that input can't be changed in the middle of a render pass.

The work needed to add more effects to apply is also not suiteable. You'll need to implement your code over and over again or create something called “uber-shader” that contains all effects that can be applied to the scenes. Nothing very “prototyping friendly” in my opinion

@shaarigan , thanks I appreciate the comments;

my answer is really a follow-on from here: https://gamedev.net/forums/topic/708149-whats-the-best-way-to-show-multiple-camera-views-like-security-cameras-with-opengl/5431730/​

Not sure if u have seen it…. This OP here is really based on that other previous OP. I guess… in hindsight , I don't know if the OP knew that he had a need to render post-fx to multi-screens… but the solution I've offered here works for those vp render passes.

The shader doesn't have to be uber ?, various shaders can be created prior to rendering and set contextually CPU-side per viewport as the need arises. In this solution here, I am showing that you can still do a bit more with a shader but definitely not suggesting that it should grow into an uber.

I hope this clarifies this ?

Post-processing is usually implement as a full-screen pass. Fullscreen pass are usually rendered with a fullscreen quad, discounting the case of using an overside triangle, rendering a scaled quad covering the region where post-processing should be applied should address the issue.

@cgrant i thought about it as well, but let's say if blurring was the post-fx to apply then downscaling the said-quad would add subtle blurring to the whole effect, wouldn't it ? i think it is good suggestion but maybe not for all kinds of fx, unless i'm missing to see an honourable point in it ?

Thanks ?

@ddlox Well good point, so naively apply the ¼ size quad would not work. Seeing that the post-processing may resulting in downsizing the source rendertarget in the process. The only way it seems you would be able to achieve this is by doing each scene individually and then compositing them into a final view. Meaning you will run the post-processing operation on each of the multiple scene, since these are a quarter size, shouldn't really be that much of a perf hit.

But how are you rendering these 4 different views? if you use glViewport and render each view, Then when doing postprocessing you specify the same viewport, rendering at fullscreen means it covers the specified viewport.

@cgrant thanks, that is my point indeed

@_weirdcat_ the rendering is done by using/setting 4 quarter-sized vps on the same fscreen fbo which is then blasted to 1 fscreen quad. Have a look at the link posted earlier to see where all this started from ?

Until then ?

This topic is closed to new replies.

Advertisement