A simple, robust and extendible postprocessing class
A simple, robust and extendible postprocessing class
I've seen a couple of these around, but none of them were neat enough for my liking, so I made my own;
http://www.dje.me.uk/misc/PostProcessor.zip
(project is in XCode and might/might not work as-is. just stick all the files in one project, add Irrlicht and build)
It's a collection of post processing effects, which regresses on old hardware, works in an optimized way and is easy to setup and maintain in the main code. It has:
* Black (a test shader which shows only black)
* Direct (a way of getting anti-aliasing - combine these to get 2x, 4x, 8x, etc.)
* Darken (multiplies maintaining black=black)
* Lighten (multiplies maintaining white=white)
* Range (narrows contrast)
* Invert (reverses rgba channels)
* Tint (converts to monochrome and adds tint, preserves black & white)
* Greyscale (Tint with grey)
* Sepia (Tint with brown)
* Curves (raise/lower red, green, blue. Preserves black & white)
* Noise (Pseudo-random noise, changes each render. Random function is poor)
* Coloured noise (like Noise, but red, green, blue are separate)
* Horizontal blur (basic 5-sample blur)
* Vertical blur
* Bi-directional blur (combines above 2)
* Linear blur
* Radial blur (with movable centre and x/y blur level)
* Radial beam (kind'a like sun rays, but not high enough quality to pass for them. Inspired by the halo currently-online globe)
* Rotational blur
* Horizontal & Vertical blurring by depth (background blurred)
* Horizontal & Vertical blurring by depth (foreground blurred - some problems)
* Depth of field (background & foreground blurred)
* Depth (converts alpha channel to rgb)
* Heat Haze (Adds a haze in certain parts of the render, based on a second texture)
* Heat Haze with depth (Heat Haze, but with the size of the effect dependent on the distance from heat source to object)
* Overlay (adds one texture to another with a multiplier)
* Negative Overlay (subtracts one texture from another with a multiplier Warning: Not optimized. Will cause serious performance loss)
* Motion blur (by past frames, no interpolation)
* Ambient occlusion (based on some code on these forums, heavily mutilated)
* Bloom (a mix of Lighten, Blur and Overlay)
* Gloom (like bloom, but dark. a mix of Darken, Blur and Negative Overlay)
* Night Vision (makes a grainy, green tinted, brightened view. a mix of Range, Blur, Noise and Tint)
* Transitions (a simple blend-by-texture is included and others can easily be made by subclassing IPostProc)
* Lens flare (uses pixel testing, so can be slow)
* Custom - Supply a gl and directX pixel shader, from code or external file, and specify a shader version to add any effect, with up to 4 input textures and 8 float parameters
* Old Monitor (provided as a custom effect, not part of the main code. An old, pixelated, fuzzy, distorted, de-saturated monitor. Fairly intensive so not recommended for real use)
That's over 30 built-in effects!
See the main.cpp file for an example of how to use it. It's really easy to add, change and remove effects at runtime, and each effect can be independently disabled/enabled, and has a quality setting to control how much processing power it uses.
There are a couple of limitations;
* Shaders are OpenGL only. I'm on a mac so DirectX isn't a priority. (The code does support directX - all that's needed is the shader code)
* Alpha channel gets messed up by some of the shaders. Not a concern unless you're trying to transfer data with it.
* You can't add an effect between 2 others easily (though it is possible). I'm not sure how I should implement this.
Hope this helps someone
latest update added: too much to list again - see the thread. Page 5 has the latest update.
http://www.dje.me.uk/misc/PostProcessor.zip
(project is in XCode and might/might not work as-is. just stick all the files in one project, add Irrlicht and build)
It's a collection of post processing effects, which regresses on old hardware, works in an optimized way and is easy to setup and maintain in the main code. It has:
* Black (a test shader which shows only black)
* Direct (a way of getting anti-aliasing - combine these to get 2x, 4x, 8x, etc.)
* Darken (multiplies maintaining black=black)
* Lighten (multiplies maintaining white=white)
* Range (narrows contrast)
* Invert (reverses rgba channels)
* Tint (converts to monochrome and adds tint, preserves black & white)
* Greyscale (Tint with grey)
* Sepia (Tint with brown)
* Curves (raise/lower red, green, blue. Preserves black & white)
* Noise (Pseudo-random noise, changes each render. Random function is poor)
* Coloured noise (like Noise, but red, green, blue are separate)
* Horizontal blur (basic 5-sample blur)
* Vertical blur
* Bi-directional blur (combines above 2)
* Linear blur
* Radial blur (with movable centre and x/y blur level)
* Radial beam (kind'a like sun rays, but not high enough quality to pass for them. Inspired by the halo currently-online globe)
* Rotational blur
* Horizontal & Vertical blurring by depth (background blurred)
* Horizontal & Vertical blurring by depth (foreground blurred - some problems)
* Depth of field (background & foreground blurred)
* Depth (converts alpha channel to rgb)
* Heat Haze (Adds a haze in certain parts of the render, based on a second texture)
* Heat Haze with depth (Heat Haze, but with the size of the effect dependent on the distance from heat source to object)
* Overlay (adds one texture to another with a multiplier)
* Negative Overlay (subtracts one texture from another with a multiplier Warning: Not optimized. Will cause serious performance loss)
* Motion blur (by past frames, no interpolation)
* Ambient occlusion (based on some code on these forums, heavily mutilated)
* Bloom (a mix of Lighten, Blur and Overlay)
* Gloom (like bloom, but dark. a mix of Darken, Blur and Negative Overlay)
* Night Vision (makes a grainy, green tinted, brightened view. a mix of Range, Blur, Noise and Tint)
* Transitions (a simple blend-by-texture is included and others can easily be made by subclassing IPostProc)
* Lens flare (uses pixel testing, so can be slow)
* Custom - Supply a gl and directX pixel shader, from code or external file, and specify a shader version to add any effect, with up to 4 input textures and 8 float parameters
* Old Monitor (provided as a custom effect, not part of the main code. An old, pixelated, fuzzy, distorted, de-saturated monitor. Fairly intensive so not recommended for real use)
That's over 30 built-in effects!
See the main.cpp file for an example of how to use it. It's really easy to add, change and remove effects at runtime, and each effect can be independently disabled/enabled, and has a quality setting to control how much processing power it uses.
There are a couple of limitations;
* Shaders are OpenGL only. I'm on a mac so DirectX isn't a priority. (The code does support directX - all that's needed is the shader code)
* Alpha channel gets messed up by some of the shaders. Not a concern unless you're trying to transfer data with it.
* You can't add an effect between 2 others easily (though it is possible). I'm not sure how I should implement this.
Hope this helps someone
latest update added: too much to list again - see the thread. Page 5 has the latest update.
Last edited by DavidJE13 on Sun Sep 20, 2009 1:13 am, edited 8 times in total.
thanks
Bennu (Best 2d and 3D dev-tool)
http://bennupack.blogspot.com
Pixtudio (Best 2D development tool)
http://pixtudiopack.blogspot.com
Bennu3D(3D Libs for bennu)
http://3dm8ee.blogspot.com/
Colombian Developers - Blog:
http://coldev.blogspot.com/
http://bennupack.blogspot.com
Pixtudio (Best 2D development tool)
http://pixtudiopack.blogspot.com
Bennu3D(3D Libs for bennu)
http://3dm8ee.blogspot.com/
Colombian Developers - Blog:
http://coldev.blogspot.com/
-
- Posts: 1638
- Joined: Mon Apr 30, 2007 3:24 am
- Location: Montreal, CANADA
- Contact:
thanks but have a crash in :
void IPostProc::removeOut( IPostProc* o, u8 n );
with irrlicht 1.6
void IPostProc::removeOut( IPostProc* o, u8 n );
with irrlicht 1.6
Last edited by Ovan on Tue Feb 23, 2010 1:13 am, edited 1 time in total.
yeah, I got that crash when I upgraded to OSX 10.6 today. I've fixed it now and I'll upload the fix soon (need to un-break something else first!)Ovan wrote:thanks have a crash in :
void IPostProc::removeOut( IPostProc* o, u8 n );
with irrlicht 1.6
Meantime - the fix is to find the IPostProc::init function in IPostProc.cpp and add these 2 lines:
for( u8 i = 0u; i != 4; ++ i )
follows[ i ] = NULL;
(they can go anywhere you like - I added them just above the outs.reallocate line)
Seems I was previously able to get away without initializing the class properly
Edit: download is updated now. Bug should be fixed
-
- Posts: 226
- Joined: Fri Aug 22, 2008 8:50 pm
- Contact:
freetimecoder; I think the easiest way for me to answer that is by posting an example, so here's the bare minimum code to render a single effect (in this case bloom):
and sp00n; a haze.. interesting. It could be done, although I think it would need 2 inputs - the main scene, and a second scene telling it where to put the haze. I'll give it a go.
(also, since the last update I've added depth of field. it's still a little primative so I'll try to patch that up before the next release)
Code: Select all
#ifdef _IRR_WINDOWS_
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#pragma comment(lib, "Irrlicht.lib")
#include <windows.h>
#endif
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Include the headers for post processing
#include "CRendererPostProc.h"
#include "CEffectPostProc.h"
#include "CTransitionPostProc.h"
#include "CSplitPostProc.h"
int main( ) {
// Boring generic stuff from the original example
IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16, false, false, false, 0);
if (!device) return 1;
device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->addStaticText(L"Hello World!", rect<s32>(10,10,260,22), true);
IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
if (!mesh)
return 1;
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation(scene::EMAT_STAND);
// Using the lighter fireball bitmap so we can actually see something!
node->setMaterialTexture( 0, driver->getTexture("../../media/fireball.bmp") );
}
smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
// Now the interesting stuff:
IPostProc* ppRenderer = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor(255,100,101,140) );
CEffectPostProc* ppBloom = new CEffectPostProc( ppRenderer, dimension2di( 1024, 512 ), PP_BLOOM /* Parameters here if needed */ );
while(device->run())
{
driver->beginScene( false, false );
ppBloom->render( NULL ); // Tell the last effect to render
guienv->drawAll( );
driver->endScene( );
}
device->drop();
return 0;
}
(also, since the last update I've added depth of field. it's still a little primative so I'll try to patch that up before the next release)
-
- Posts: 226
- Joined: Fri Aug 22, 2008 8:50 pm
- Contact:
Thanks, I guess i figured out how it works now
Another question, how do I tell the PP_OVERLAY shader what texture to use to overlay? When changing Bloom to overlay the overlay texture is the texture applied to sydney.
Edit:
I figured out that I can set effect inputs. So I tried to combine two effects (glow and direct) in an overlay effect:
But it is all flickering like crazy
Any suggestion whats wrong?
greetings
Another question, how do I tell the PP_OVERLAY shader what texture to use to overlay? When changing Bloom to overlay the overlay texture is the texture applied to sydney.
Edit:
I figured out that I can set effect inputs. So I tried to combine two effects (glow and direct) in an overlay effect:
Code: Select all
int main( ) {
// Boring generic stuff from the original example
IrrlichtDevice *device = createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16, false, false, false, 0);
if (!device) return 1;
device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->addStaticText(L"Hello World!", rect<s32>(10,10,260,22), true);
IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
if (!mesh)
return 1;
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation(scene::EMAT_STAND);
// Using the lighter fireball bitmap so we can actually see something!
}
smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
// Now the interesting stuff:
IPostProc* ppRenderer = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor(255,0,0,0) );
ITexture *glowTex = driver->addRenderTargetTexture(dimension2d<s32>(1024,512),"rendertex");
CEffectPostProc* ppBloom = new CEffectPostProc( ppRenderer, dimension2di( 1024, 512 ),PP_BLOOM,1 /* Parameters here if needed */ );
IPostProc* ppRenderer2 = new CRendererPostProc( smgr, dimension2di( 1024, 512 ), true, true, SColor(255,0,0,0) );
CEffectPostProc* ppDirect = new CEffectPostProc( ppRenderer2, dimension2di( 1024, 512 ),PP_DIRECT,1 /* Parameters here if needed */ );
CEffectPostProc* ppOverlay = new CEffectPostProc( ppDirect, dimension2di( 1024, 512 ),PP_OVERLAY,0.2 /* Parameters here if needed */ );
ppOverlay->setInput(0,ppDirect);
ppOverlay->setInput(1,ppBloom);
while(device->run())
{
driver->beginScene( false, false );
node->setMaterialTexture( 0, driver->getTexture("../../media/fireball.bmp") );
ppBloom->render(NULL);
node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );
ppOverlay->render(NULL);
guienv->drawAll( );
driver->endScene( );
}
device->drop();
return 0;
}
Any suggestion whats wrong?
greetings
ok, you're rendering 2 nodes to the screen each loop, hence the flicker. To render to the internal surfaces, just use Render( ) (no NULL)
You can fix your code by simply removing the NULL in the first Render call (but not the second)
This will work in this case, but is risky in general. I'll see if I can add built-in support for this type of rendering.
Edit:
Also, you don't need the setInput(0,ppDirect) line - input 0 is already set by the constructor. It's doing no harm though.
And the PP_DIRECT effect is doing absolutely nothing here - you can use ppRenderer2 in it's place and remove it (In the latest version - not uploaded yet - it will filter this out automatically but for now it's doing an extra render because of that)
Edit2:
I've now added a function specifically for this: preRender()
It does exactly the same as Render() but in a way which is safe for this type of use.
It'll be included when I next update, and I'd recommend changing the first render call in your code to it.
You can fix your code by simply removing the NULL in the first Render call (but not the second)
This will work in this case, but is risky in general. I'll see if I can add built-in support for this type of rendering.
Edit:
Also, you don't need the setInput(0,ppDirect) line - input 0 is already set by the constructor. It's doing no harm though.
And the PP_DIRECT effect is doing absolutely nothing here - you can use ppRenderer2 in it's place and remove it (In the latest version - not uploaded yet - it will filter this out automatically but for now it's doing an extra render because of that)
Edit2:
I've now added a function specifically for this: preRender()
It does exactly the same as Render() but in a way which is safe for this type of use.
It'll be included when I next update, and I'd recommend changing the first render call in your code to it.
ok, enough's changed for a new version now, I think!
I've added depth of field blurring (near, far, and both), fixed a whole load of stuff, optimized a whole load of stuff, fixed (hopefully!) a cross-platform problem found by Seven, added preRender(), increased the constructor parameter limit to 8, and updated the example file to be split into several examples (each much simpler than the old all-in-one version)
Depth of field seems to work well, although foreground blurring is a bit poor around the edges and it's a little intensive compared to the other effects.
Still no haze, but I'm working on it!
I've added depth of field blurring (near, far, and both), fixed a whole load of stuff, optimized a whole load of stuff, fixed (hopefully!) a cross-platform problem found by Seven, added preRender(), increased the constructor parameter limit to 8, and updated the example file to be split into several examples (each much simpler than the old all-in-one version)
Depth of field seems to work well, although foreground blurring is a bit poor around the edges and it's a little intensive compared to the other effects.
Still no haze, but I'm working on it!
-
- Posts: 226
- Joined: Fri Aug 22, 2008 8:50 pm
- Contact:
Hi, thanks for the help.
Here is what i accomplished: http://www.freetimestudio.de/glowshader.zip
Looks nice, but might be a little complicated for large scenes. I might come up with something easier (if I can figure out something ) Use as you please (Who am I to say that xD).
Depth Of Field sounds interesting, but how do I use it? I tried PP_DEPTH, but that just gives me a white screen.
greetings
Here is what i accomplished: http://www.freetimestudio.de/glowshader.zip
Looks nice, but might be a little complicated for large scenes. I might come up with something easier (if I can figure out something ) Use as you please (Who am I to say that xD).
Depth Of Field sounds interesting, but how do I use it? I tried PP_DEPTH, but that just gives me a white screen.
greetings