Help me with my fullscreen glow process?

BlitzMax Forums/MiniB3D Module/Help me with my fullscreen glow process?

Sonic(Posted 2012) [#1]
[Accidental double post...]

Last edited 2012


Sonic(Posted 2012) [#2]
Hi there guys, I'm having trouble writing a solid routine to replace my fullscreen glow effect, which is currently based on the following rough pseudocode:

- render the world in lower res
- switch to Max2D
- grab a pixmap from the back buffer, the size of the low-res render
- ... and upload that to an image,
- ... then rendering that image at half size with filtering, grabbing that as an image...
- then render the the main image again at quarter res, grabbing that as an image
- and again at eighth res, grabbing that as an image
- finally drawing the original grabbed image again scaled to the native res
- then overlaying the half size grab, scaled up in additive blend, then the quarter res and so on...



This works really well in giving me a soft render with a nice glow to it. But I can only manage about a 320x240 initial render on an average machine (up to 640 across on my 2008 Mac Pro.)

What I'd really like to do is do the initial render to a framebuffer, then ideally run a shader on top of it and layer it back over the original. As I'm out of my depth with shaders, I've been trying a hybrid approach, of:

- rendering to a frame buffer instead of the back buffer in low res
- apply this texture to a fullscreen quad and re-render
- repeat this process, only rendering the fullscreen quad to the frame buffer, instead of the scene, at increasingly lower resolutions as before, grabbing each render and adding them to their own quads with additive blending
- finally re-render to the backbuffer

I've been working on some resolution-independent frame buffer code based on two pieces of code found on the forums, for frame buffer to TTexture rendering and TMesh quad generation respectively. If you run the code below in MiniB3D you can see what I mean (the yellow cube is the additive blended, lower-res render from the frame buffer.)

I just can't get the fullscreen quad to match up, ideally it would work whatever I set Graphics3D's width and height parameters to, as well as whatever I set the quad width and height to (qw# and qh#.)



Can anyone help with this? Or better still yet suggest a nice bit of shader code that could just process the frame buffer directly so I could just line up the quad by hand and always render to the same resolution?

I know this is a big ask, but I wondered if anyone had achieved this before themselves and had some pointers?

Last edited 2012

Last edited 2012


AdamRedwoods(Posted 2012) [#3]
your problem could be when drawing the quad you are relying on the camera and scaleentity. not so accurate, you need an ortho camera.

i found it's pretty easy just to draw an immediate mode quad and enable/disable camera.

code lifted from my old shader stuff:

UVH, UVW is key.
mainTextureFBO.width and .height I think is just the size of the next power-of-two for the viewport.

Last edited 2012


Sonic(Posted 2012) [#4]
Hi Adam,

That makes a lot of sense - I didn't even think about ortho projection! Unfortunately the code you've shared is a little beyond my GL level, I think I'd find it tricky to adapt as is without a bit more experience.

I wonder, seeing as I have rendering to frame buffer working, whether there's a way of grabbing the texture that's rendered to it and actually just replacing the underlying texture within a TImage? So then I could use the rest of the process I've already developed (of scaling down via Max2D and using GrabImage to render the additive passes?). The initial half-res render and grab in my current implementation is by far the most intensive resource wise, so maybe switching over to GrabImage for the lower resolution passes wouldn't take too much of a hit?

I already use a function called UploadPixmapToImage() as a faster way of replacing the texture in a TImage with a new pixmap - I wonder if there's a way to write a function which takes a frame buffer and does the same? I'm pretty sure this would still be faster than grabbing the rendered backbuffer...

Basically, all this is in aid of bypassing the stage where the pixmap must be pulled into main memory and passed back over to the GPU every frame...

Last edited 2012


AdamRedwoods(Posted 2012) [#5]
Framebuffer is already in texture memory, and the only way we can access it is throught the assigned gltexid, similar to when we use glBindTexture().

so if you swap the gltexid in the FBO with TImage, then yes, it can be done-- BUT BlitzMax's process of updating TImage may be that it uploads pixmap data every frame, so then, NO, it wont work. (my memory fails me how it is done in BMax).


My suggestion is to:
- create another camera, orthoCamera
- use a render routine similar to:
HideEntity FSQuad
HideEntity orthoCamera

RenderToTexture (FSTex)
orthoCamera.Update()
FSQuad.Update()   

Flip 


Last edited 2012


jkrankie(Posted 2012) [#6]
Hey Jasper! This may be useful to you: http://www.iquilezles.org/www/articles/feedbackfx/feedbackfx.htm

You'll likely need to switch to ortho mode to use it, but it's cheap and fast and will run on old systems just fine.

There's a code sample that comes with blitzmax that does something similar too.

Hope you're doing well, i'll have to pop up to cambridge again soon, it's been ages since i last visited!

Cheers
Charlie


SystemError51(Posted 2012) [#7]
Okay so here's what I did.

In MiniB3D, I had two cameras, instead of one. Both at the same location. The "glow" cam would follow the real one with every move and every rotation.

Things that I wanted to glow, got a special illumination marker, and self-illumination was set to fullbright.

I did a few rendering passes.

Pass 1 would reduce the viewport to 1/4 of the screen size. Turn off all lights. Everything that DOES NOT have the fullbright marker, was rendered - but with a pitch black texture (dirty trick that skips occlusion testing).

I took that render and applied an image mask with a color of 0,0,0 (black) to make those pixels transparent.

This pixmap got a quick and dirty low-cost blur routine applied.

Render the scene as normal.

Take the blurred image and apply it 8 times in a circular motion, with an offset of say 6 pixels, on top of the actual image, with very low alpha values - and rescale to full-size.

I know this is a bit intensive - but pretty effective.

Last edited 2012


Sonic(Posted 2012) [#8]
Some great stuff in here, thanks everyone.

I received Beanage's render to texture mod, which works great on 2D, but goes horrible wrong when I try to insert it into the Minib3D render pipeline, meaning I can't render the camera to the back buffer, only the 2D elements. I managed to get it to sort of appear, but it was flipped and seemed to have the z buffer back to front!

I tried your approach to improve the blur itself, SystemError ("Take the blurred image and apply it 8 times in a circular motion, with an offset of say 6 pixels"), except every 30deg, and removed the final two downscales instead: ... it worked nicely and was probably just as fast as the extra downscales but looked better. As I'm applying the blur to the full backbuffer, I won't need to set up two passes as per your per-object setup.

It's acceptably smooth on my old Mac Pro now, which is quite a bit slower than the Retina Macbook Pro it turns out! (Could be down to better memory bandwidth or something on the newer chips?) I've made it so the res can go lower and the blur scales nicely with it, it can run ok at 320x240 virtual on most machines, so it is an ok compromise, but I think I will have to solve this properly in the long-term if I want to take the game much further.

Now I have the problem of particle / bullet spawning slowing the framerate down (or perhaps it's alpha overdraw) - may be time to get a single surface sprite system in there?

But I am going to have to solve the RTT stuff at some point.

@Charlie - you should come down tomorrow man, it's the pub meet, although I'm not sure if I'll actually make it... Another busy week here. Hope to catch up soon either way!


Sonic(Posted 2012) [#9]
We solved it! A friend of mine, who'd never used BMax before, dove right in, and within half an hour he had got to the heart of the problem and added a depth buffer to the FBO section of the render, which solved the strange visual issues in one swoop, and thanks to beanage's mod, now mean my game runs about 5-10x faster!

Thanks for your help with this! I guess I might even look into applying the glow as a shader on the FBO texture, that would also speed it up a lot, as fill rate is probably now the limiting factor. Will probably need help again when the time comes though haha.