Screen Quad Post Processing

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Screen Quad Post Processing

Post by Vectrotek »

To render a scene using "Deferred Shading" (a very deep and wide subject), the "Screen Quad" and how its Textures are manipulated by the GPU should be well understood.
The Screen Quad also allows for "Post Processing Effects" like "FXAA" Antialiasing, Radial Blurring, Posterization i.e. Tooning and much more.
Place your views on the matter here..
Last edited by Vectrotek on Thu Jun 30, 2016 9:15 pm, edited 1 time in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

Screen Quad Based Post Processing.

Image
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

Hard coded "Screen Quad Shader" Post Processing Example
Inspired by code on the forums.

This simply replaces the original Shader with something more interesting
like a Pixel Shader Based "Tooner" a.k.a. "Posterizer" (interesting math).
You'll notice that now, with the new shader, there are some unused items , but it should be amusing none the less.
I renamed the variables, objects and classes to more descriptive terms only because I learn like that.

I'd like to add a key-press-based UP or DOWN controll over the "Level" at which Posterization occurs.
I'd also like to convert the shaders that are hard coded in this code to file based shaders
so that they can be edited outside of the application for experimental purposes.
HLSL Conversion?


You can compile it with Standard Irrlicht 1.8.3 or 1.8.2 but the DLL included in the project
is recompiled for Eight Textures (replace it with your DLL if you had compiled your own *.exe).

Before playing with "Deferred Rendering" the "Screen Quad" and its "Shaded Textures"
should be understood.
It also makes FXAA and other cool Post Processing effects possible which is something I'd really like to implement.
(in searching for Screen Quad material, I would have liked this)

Here is the Project:
I G N O R E T H I S T H E N E X T I S B E T T E R . .

Controls:
"1" Render Screen Quad Post Processed Scene.
"0" Render the scene normally.
"Esc" Exit.
Last edited by Vectrotek on Wed Jul 06, 2016 4:28 pm, edited 2 times in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

A look at the code..

Code: Select all

 
 
 // Hardcoded "Screen Quad Shader" Post Processing Example..
 
 // Inspired by code on the forums..
 
 // This simply replaces the original Shader with something more interesting
 // like a Pixel Shader Based "Tooner" a.k.a. "Posteriser" (interesting math)..
 // You'll notice that now, with the new shader, there are some unused items , but it should be amusing none the less..
 // I renamed the variables and classes to more descriptive terms only because I learn like that..
 
 // I'd like to add a key-press-based UP or DOWN controll over the "Level" at which "Posterisation" occurs..
 // I'd also like to convert the shaders that are hardcoded in this code to file based shaders
 // so that they can be edited outside of the application for experimental purposes..
 // HLSL Conversion?
 
 
 // You can compile it with Standard Irrlicht 1.8.3 or 1.8.2 but the DLL included in the project
 // is recompiled for Eight Textures (replace it with your DLL if you had produced your own *.exe)..
 
 // Before playing with "Deferred Rendering" I think that the "Screen Quad" and its "Shaded Textures"
 // should be understood..
 // It should also make FXAA and other cool PP Effects possible which is something I'd really like to implement..
 
 
 
 // Early, on the road to Deferred Rendering and FXAA etc.. (for me, that is)
 
 #include <irrlicht.h>
 #include <iostream>
 
 #define IRRMEDIA "data/"
 // #define IRRMEDIA "../irrlicht-1.8.1/media/"
 using namespace irr;
 
 #ifdef _MSC_VER
 #pragma comment(lib, "Irrlicht.lib")
 #endif
 
 // Postprocessing Shader code..
//                                                                                                        
 const c8* VertForPostProcString =
 " void main(void)                                             \n"
 "  {vec2 tCoords;                                             \n"
 "   gl_Position = vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 1.0);   \n"
 "   tCoords.x = 0.5 * (1.0 + gl_Vertex.x);                    \n"
 "   tCoords.y = 0.5 * (1.0 + gl_Vertex.y);                    \n"
 "   gl_TexCoord[0].xy = tCoords.xy;                           \n"
 "  }                                                          \n";
//                                                                                                        
/* // Original..
 const c8* FragForPostProcString =
 " uniform sampler2D render;                                   \n"
 " uniform sampler2D effect;                                   \n"
 " void main(void)                                             \n"
 "  {vec4 color1 = texture2D(render, gl_TexCoord[0].xy);       \n"
 "   vec4 color2 = texture2D(effect, gl_TexCoord[0].xy);       \n"
 "   vec4 final = color2.r * color1;                           \n"
 "   if (color1.r > 0.65) final = 1.0 * color1;                \n"
 "   final.x *= 1.5;                                           \n"
 "   final.y *= 0.5;                                           \n"
 "   gl_FragColor = final;                                     \n"
 "  }                                                          \n";
 */
 //                                                                                                        
 // NEW Post-Process based "Tooning" or "Posterization"..
 const c8* FragForPostProcString =
 " uniform sampler2D render;                                                                 \n"
 " void main()                                                                               \n"
 "  {vec4 texCol = texture2D(render, gl_TexCoord[0].xy);                                     \n"
 "   vec3 col0 = texCol.rgb;                                                                 \n"
 "   float PosterizationLevel = 6.0;   // PLAY WITH THIS VALUE..                             \n"
 "   col0 = col0 * PosterizationLevel;                                                       \n"
 "   col0 = floor(col0);                                                                     \n"
 "   col0 = col0 / PosterizationLevel;                                                       \n"
 "   gl_FragColor = vec4(col0, texCol.a);                                                    \n"
 "  }                                                                                        \n";
//                                                                                                        
 // the callback - called by Irrlicht before the screen quad is rendered..
 class PostProcShadCallbck : public video::IShaderConstantSetCallBack
  {public:
   virtual void OnSetConstants(video::IMaterialRendererServices* MatRenderServices,s32 userData)
    {video::IVideoDriver* AquiredVideoDriver = MatRenderServices->getVideoDriver();
     s32 TextureLayerID = 0;   // Set the textures..
     MatRenderServices->setPixelShaderConstant("render", &TextureLayerID, 1);      // To where the scne was rendered..
     TextureLayerID = 1;
     // Texture to create an effect..
     MatRenderServices->setPixelShaderConstant("effect", &TextureLayerID, 1);
    }
  };
 
 // Class to hold our Screen Quad and Render-Target texture..
 class ScreenQuadPostProcr
  {public:
   ScreenQuadPostProcr(IrrlichtDevice* PassDevice)
    {PassedIrrDevice       = PassDevice;
     AquiredVideoDriver    = PassDevice->getVideoDriver();
     // RenderTargetTexture   = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>( 1024, 1024 )); // (was 512,512)Render Target..
     RenderTargetTexture   = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>( 640, 640 )); // Could have been derived from Device Resolution..
     material.Wireframe    = false;        // material for screen quad
     material.Lighting     = false;
     material.ZWriteEnable = false;
     vert[0] = video::S3DVertex(-1, -1, 0, 0, 0, 1, video::SColor(0), 0, 1); // Screen Quad..
     vert[1] = video::S3DVertex(-1,  1, 0, 0, 0, 1, video::SColor(0), 0, 0);
     vert[2] = video::S3DVertex( 1,  1, 0, 0, 0, 1, video::SColor(0), 1, 0);
     vert[3] = video::S3DVertex( 1, -1, 0, 0, 0, 1, video::SColor(0), 1, 1);
     // Drawing order..
     index[0] = 0; index[1] = 1; index[2] = 2; index[3] = 0; index[4] = 2; index[5] = 3;
    }
  ~ScreenQuadPostProcr()
   {if ((RenderTargetTexture)) AquiredVideoDriver->removeTexture(RenderTargetTexture);
    PassedIrrDevice->drop();
   }
  void render()
   {AquiredVideoDriver->setMaterial(material);
    AquiredVideoDriver->setTransform(video::ETS_WORLD, core::matrix4());
    AquiredVideoDriver->drawIndexedTriangleList(vert, 4, index, 2);
   }
  video::SMaterial& getMaterial() {return material;}
  IrrlichtDevice* PassedIrrDevice;
  video::IVideoDriver* AquiredVideoDriver;
  video::ITexture* RenderTargetTexture;
  video::SMaterial material;
  video::S3DVertex vert[4];
  u16 index[6];
 };
 
 // SCENE..
 // Shader code..
 const c8* VertForTextureString =
 " uniform mat4 mWorldViewProj;                                 \n"
 " void main(void)                                              \n"
 "  {gl_Position = mWorldViewProj * gl_Vertex;                  \n"
 "   gl_TexCoord[0] = gl_MultiTexCoord0;                        \n"
 "  }                                                           \n";
 
 const c8* FragForTextureString =
 " uniform sampler2D myTexture;                                 \n"
 
 " void main(void)                                              \n"
 "  {gl_FragColor = texture2D(myTexture, vec2(gl_TexCoord[0])); \n"
 "  }                                                           \n";
 
 class TextureShaderCallback : public video::IShaderConstantSetCallBack
  {public:
   virtual void OnSetConstants(video::IMaterialRendererServices* MatRenderServices, s32 userData)
    {video::IVideoDriver* AquiredVideoDriver = MatRenderServices->getVideoDriver();
     core::matrix4 worldViewProj;
     worldViewProj =  AquiredVideoDriver->getTransform(video::ETS_PROJECTION);
     worldViewProj *= AquiredVideoDriver->getTransform(video::ETS_VIEW);
     worldViewProj *= AquiredVideoDriver->getTransform(video::ETS_WORLD);
     MatRenderServices->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
     s32 TextureLayerID = 0;
     MatRenderServices->setPixelShaderConstant("myTexture", &TextureLayerID, 1);
    }
  };
 // handle keystrokes
 class MyEventReceiver : public IEventReceiver
  {public:
   MyEventReceiver() : EffectsAndExit(0) {}
   virtual bool OnEvent(const SEvent& event)
    {if (event.EventType == irr::EET_KEY_INPUT_EVENT &&
     event.KeyInput.PressedDown)
     switch (event.KeyInput.Key)
      {case 27:    // ESC
       EffectsAndExit = -1;  // signal to quit
       break;
       case '0':   // no effect
       case '1':   // effect
       EffectsAndExit = event.KeyInput.Key - '0';
       break;
      }
     return false;
    }
   int EffectsAndExit;
  };
 
 int main()
  {std::cout << "main" << std::endl;
   // create an OpenGL instance
   IrrlichtDevice* TheIrrevice = createDevice(video::EDT_OPENGL, core::dimension2d<u32>( 1024, 768 ));
   if (TheIrrevice == 0)
    {std::cout << "Could not create an OpenGL context" << std::endl;
     return 1;
    }
   video::IVideoDriver* TheVideoDriver = TheIrrevice->getVideoDriver();
   video::ITexture* ImageFileTexture = TheVideoDriver->getTexture(IRRMEDIA "Colour_Image.png");
   // video::ITexture* ImageFileTexture = TheVideoDriver->getTexture("data/wall.bmp");
   if (ImageFileTexture == 0)
    {std::cout << "Could not create a texture from 'wall.bmp'" << std::endl;
     std::cout << "Check your setting of IRRMEDIA" << std::endl;
     return 2;
    }
   // Postprocessing code..
   // create material..
   video::IGPUProgrammingServices* GPUServices = TheVideoDriver->getGPUProgrammingServices();
   if (GPUServices == 0)
    {std::cout << "Could not access the GPU" << std::endl;
     return 3;
    }
   s32 IDSPostProcessing;
   PostProcShadCallbck* CallbackForPostProc = new PostProcShadCallbck();
   // Create the shaders (GLSL) (Jacques, add HLSL Please)
   IDSPostProcessing = GPUServices->addHighLevelShaderMaterial(VertForPostProcString,
                                              "vertexMain",
                                              video::EVST_VS_1_1,
                                              FragForPostProcString,
                                              "pixelMain",
                                              video::EPST_PS_1_1,
                                              CallbackForPostProc,
                                              video::EMT_SOLID,
                                              0,
                                              video::EGSL_DEFAULT);
   if (IDSPostProcessing < 0)
    {std::cout << "Could not create the postprocessing shader" << std::endl;
     return 4;
    }
   CallbackForPostProc->drop();
   // Instantiate the postprocessing class..
   ScreenQuadPostProcr InstanceOfPostProcer(TheIrrevice);
   InstanceOfPostProcer.getMaterial().MaterialType = (video::E_MATERIAL_TYPE) IDSPostProcessing;
   InstanceOfPostProcer.getMaterial().setTexture(0, InstanceOfPostProcer.RenderTargetTexture);
   InstanceOfPostProcer.getMaterial().setTexture(1, ImageFileTexture);
   // End postprocessing code..
   MyEventReceiver TheReceiver;
   TheIrrevice->setEventReceiver(&TheReceiver);
   scene::ISceneManager* TheSceneManager = TheIrrevice->getSceneManager();
   // Create Material..
   s32 IDSSceneObjects;
   TextureShaderCallback* CallbackForScene = new TextureShaderCallback();
   // Create the shaders (GLSL) (Jacques.. add HLSL Please..)
   // Jacques.. Convert this to Get from File please..
   IDSSceneObjects = GPUServices->addHighLevelShaderMaterial(VertForTextureString,
                                               "vertexMain",
                                               video::EVST_VS_1_1,
                                               FragForTextureString,
                                               "pixelMain",
                                               video::EPST_PS_1_1,
                                               CallbackForScene,
                                               video::EMT_SOLID,
                                               0,
                                               video::EGSL_DEFAULT);
   if (IDSSceneObjects < 0)
    {std::cout << "Could not create the material shader" << std::endl;
     return 5;
    }
   CallbackForScene->drop();
   // Create a test scene CubeNode with the shader material
   scene::ISceneNode* CubeNode = TheSceneManager->addCubeSceneNode(150);
   CubeNode->setPosition(core::vector3df(0,0,0));
   CubeNode->setMaterialTexture(0, ImageFileTexture);
   CubeNode->setMaterialFlag(video::EMF_LIGHTING, false); // As we have shaders..
   CubeNode->setMaterialType((video::E_MATERIAL_TYPE) IDSSceneObjects);
   // Rotate the cube..
    scene::ISceneNodeAnimator* TheNodeAnimator = TheSceneManager->createRotationAnimator(core::vector3df( 0.01, 0.3f, 0.02 ));
   // scene::ISceneNodeAnimator* TheNodeAnimator = TheSceneManager->createRotationAnimator(core::vector3df( 0.0, 0.0f, 0.0 ));
   CubeNode->addAnimator(TheNodeAnimator);
   TheNodeAnimator->drop(); 
   // Add a camera and disable the mouse cursor..
   scene::ICameraSceneNode* TheMainCamera = TheSceneManager->addCameraSceneNode(); // Perhaps FPS?
   TheMainCamera->setPosition(core::vector3df( -100,100,100 ));
   TheMainCamera->setTarget(core::vector3df(0,0,0));
   TheIrrevice->getCursorControl()->setVisible(false);
   // Draw scene..
   int lastFPS = -1;
   while(TheIrrevice->run())
   if (TheIrrevice->isWindowActive())
    {if (TheReceiver.EffectsAndExit < 0) break;  // Cool exit method!..
     // This is where its all at..
     if (TheReceiver.EffectsAndExit > 0)
      {TheVideoDriver->beginScene(true, true, video::SColor( 255, 0, 200 ,0 )); // render into the texture on Screen Quad..
      TheVideoDriver->setRenderTarget(InstanceOfPostProcer.RenderTargetTexture, true, true, video::SColor( 255 , 207 , 223 , 169 ));
      }
     else
      {TheVideoDriver->beginScene(true, true, video::SColor( 255 , 207 , 223 , 169 ));// render into the frame buffer
      }
     TheSceneManager->drawAll(); // HOW DO WE MAKE IT JUST RENDER THE SCREEN QUAD..
     if (TheReceiver.EffectsAndExit > 0)
      {// Access to the render image and set the framebuffer as the render target..
       TheVideoDriver->setRenderTarget(0, true, true, video::SColor(0));
       // Render the screen rectangle (quadrilateral) to the framebuffer..
       InstanceOfPostProcer.render();
      }
     // That's all. Swap buffers..
     TheVideoDriver->endScene();
     int fps = TheVideoDriver->getFPS();
     if (lastFPS != fps)
      {core::stringw str = L"Postprocessing example [OpenGL] FPS: ";
       str += fps;
       TheIrrevice->setWindowCaption(str.c_str());
       lastFPS = fps;
      }
    }
   std::cout << "Postprocessing example is ending" << std::endl;
   return 0;
  }
 // Inspired by code from mongoose7..
 // END..
 
 
 
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

It may be a while before I go 64 bit, but I was very pleased when
I shaded a Post Processing Screen Quad Texture with FXAA at a quality of 29!
(thought it would take years)

Image
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

This shows a way to render a 3D scene to a Screen Quad multiple
times using multiple GLSL Post Processing Effects.

Multi Pass Post Processing was already shown way back in 2011 by
"tbw" in the "XML Based Post Processing Framework" code.
That code was complex, and Multipass PP was just a part of it,
so I thought a simplified example of how MPPP can be
achieved would be a good idea..

The DLL included is my own custom (8 image) version so
replace it with your own if you re-compile the project..

Image


Here is the Project:
http://s000.tinyupload.com/?file_id=755 ... 9732371086

OR alternatively.. (smaller zip file) but then you MUST recompile, and use your own DLL..
http://s000.tinyupload.com/?file_id=038 ... 4607712750
Last edited by Vectrotek on Wed Jul 06, 2016 4:56 pm, edited 1 time in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

Code notes..

Post Processing Shader Names and what they do:
#1 "Bypass" Does nothing, used to show "no effect"..
#2 "FXAA" Fast Approximate AA. (NVIDIA) Advanced Antialiassing Technique that
analyses pixels intelligently and very fast on the GPU. (very cool)
#3 "Toon" Also known as Simple Posterisation, this shader simply decreases the
amount of colours used for an image.
#4 "Cell Shading" Like Tooning but with more functionality like "Edgeing" to produce
a classic cartoon-style effect.
#5 "Edge Detection" Usefull "utility process" used in conjunction with many other functions
for effects, including FXAA.
#6 "Grey Scale" Unlike simple RGB Averageing, these are the two main "Photographic Standards":
"ITU_R_601" & "ITU_R_709", used to convert RGB to Grey.
The standard can be selected inside the shader code.
#7 "Invert" A Simple process of Inverting RGB to produce a "Negative" of the source image.
#8 "Radial Blur" Used in many games to create the effect of a speeding point of view and if the "Origin" is
controlled, can emulate volumetric lighting.
#9 "Vertical Blur" Smudges the pixels along the Y axis and used together with "Horizontal" blurring
to produce a Final Blurred Effect. Very popular.
#10 "Horizontal Blur" Used with the effect above in a "Second Pass" to create a Final Blur,
also used as part of the popular "Bloom Effect".
#11 "Pixelize" Simple method of creating a "Reduced-Resolution" effect in which pixels
appear as large coloured squares.
#12 "Brighten" Unlike "Adding" to the values of pixels this induces a "Brightening Curve"
by Muliplying RGB values with a given factor.
#13 "Darken" Unlike "Subtracting" from the values of pixels this induces a
"Darkening Curve" by Muliplying RGB values with a given fraction under 1.0.
#14 "Squared" Emulates a form of "Increasing Contrast" by squaring RGB values.
#15 "Frost" Interesting Equation that results in an image as seen through
"Frosty Glass" (can be tweaked inside the shader cope).


There are Thousands of combinations possible..

// -- -- -- -- -- -- -- -- -- -- -- -- -- --
A basic "Step-Wise Procedure" for rendering "Multi Passed Post Processing Effects"..
Here, this doesn't occur in a smart loop of any kind because there are many ways to do this..

I N I T I A L P R E P A R A T I O N (when in PP mode). .
STEP 1: Set the "Initial Render Target" to a "FIRST Alternating Texture"
assigned to the existing "Material Texture" of the "Sqreen Quad".
STEP 2: Render the "Original Scene" to this "FIRST Alternating Texture" in
the normal way (without any post processing, or include initial effects you may have).

M U L T I P A S S P O S T P R O C E S S I N G . .
STEP 1: Set the "Render Target" to the "SECOND Alternating Texture" and assign
a "Selected PP Effect Shader" to the "Material" of the Screen Quad.
STEP 2: Render the Screen Quad (now containing an image of the original render)
to the "Second Alternating Texture" using the "FIRST Selected PP Effect Shader".
(first pass done)
STEP 3: Set the "Render Target" to the "FIRST Alternating Texture"
(which we can now overwrite) with a "SECOND Selected PP Effect Shader"
to the "Material" of the Screen Quad.
STEP 4: Render the Screen Quad (image resulting from the FIRST effect) to the
"FIRST Alternating Texture" using your SECOND PP Shader Effect.
(second pass done)
STEP 5: Set the "Render Target" to the "SECOND Alternating Texture"
(which, again we can now overwrite) an assign "YET-ANOTHER Selected PP Effect Shader"
to the "Material" of the Screen Quad.
STEP 6: Render the Screen Quad (image resulting from the SECOND effect) to the
"SECOND Alternating Texture" using , YET-ANOTHER PP Shader Effect.
(third pass done)
STEP 7: Set the "Render Target" to the "FIRST Alternating Texture" (can overwrite) wich has
"YET-ANOTHER Selected PP Effect Shader" assigned to the "Material" of the Screen Quad.
STEP 8: Render the Screen Quad (resulting from the THIRD effect) to the "FIRST Alternating Texture"
using our, YET-ANOTHER PP Shader Effect.
(fourth pass done)
STEP 9: Set the "Render Target" to the "SECOND Alternating Texture" (which we can now overwrite)
and "YET-ANOTHER Selected PP Effect Shader" to the "Material" of the Screen Quad.
STEP 10: Render the Screen Quad (the FOURTH effect) to the "SECOND Alternating Texture"
using YET-ANOTHER PP Shader Effect.
(sixth pass done)

REPEAT for as many passes as you need..

LAST STEP: Set the render target to "Frame Buffer" and render the "Final Pass" to the "Screen"..


NOTES:
You'll notice a pattern developing as we "Flip-Flop" between the "FIRST Alternating" and
"SECOND Alternating" Render Target Texture.
Some effects like "Blurring" consists of TWO Passes (for Vertical & Horizontal smudging),
so don't think of a "Single Effect" necessarily meaning a "Single Pass".

Once you have control over the Screen Quad and how to use it as a Post Processor there are
literally Millions of Effects possible..
If any of your passes deal with Blurring of any sort, then you'd probably not want
to include FXAA in your Passes.

Apart from "FIRST Alternating" and "SECOND Alternating" textures we may have effects that don't
allow us to simply alternate between two images and which may need "Additional Textures".
These kinds of effects would obviously need a different (yet similar) Multipassing Procedure.
An example of such an Effect would be "Bloom" which envolves "Contrast or Cutoff", "H-Blur",
"V-Blur" and "Final Mixing" which uses multiple passes, shadings and images..
Another important issue is that some shaders use additional info like "Buffer Dimensions" and
"Intensies".
These are also examples of why you would need your own "Solutions" for handling
different "Families" of shaders and effects..
(here I simply made sure that these values (where used) are correctly hard-coded
into the shaders and matched in the appcode)
One such an example is the Buffer Sizes which is 512 x 512 in the shader code AND in the Appcode..

While experimenting with shaders for the custom node, the cohesion of the code
got a bit loose, so a nice exercise would be to turn all of this into a
"Stand-Alone-Reusable-Node" that you could paste into your own project..


Instructions: Tap 'randomly' on keys 1 to 8 (when in Screen Quad PP mode) to generate instant random combinations!
Key "9" resets all the passes to the "Bypass" for a new start..
Key "0" toggles between Normal Rendering mode and SQPP mode..

This can be quite a susefull little tool if your'e dealing with post processing effects..

I'm not writing about any of the shaders in the collection because there is lots of material
available on the net.. You could even replace these shaders with your own and use
different source images.

Conversion from GLSL to HLSL shouldn't be a problem..
(I always try things in GLSL before converting to HLSL which is a bit stricter)
The_Glitch
Competition winner
Posts: 523
Joined: Tue Jan 15, 2013 6:36 pm

Re: Screen Quad Post Processing

Post by The_Glitch »

I'll look into your fxaa shader.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

So I've got a good handle on rendering to target textures, flipping between them,
combining them them and applying Post Processing Shaders to them.
Great, but when it comes to converting the project to handle HLSL too i.e.
running in "EDT_DIRECT3D9" mode then everything seem to go haywire.
The images in these render target textures gets corrupted.

Now I'm pretty sure that the Vertex Program is fed the right UV coordinates.
Also the inter-changing between RTT textures should be O.K. like they occur in GL mode..

Here is the result of rendering a 3 Layer Cloud Node, A Realistic Water Node and some geometry
to a very small Render Target Texture which is finally post processed with FXAA.
Using GLSL. (blurred text is a result of FXAA which is something I won't do at completion)

SOMEONE SHOULD COMPLAIN ABOUT TINY PIC'S USELESS LITTLE SERVICE

Here is the same procedure but using HLSL.

Image

Is there any issue with "Render Target Textures" under GLSL (OpenGL) vs HLDL (D3D)?
Baffled..
Matrices?
Last edited by Vectrotek on Sat Jul 23, 2016 9:47 pm, edited 2 times in total.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

A Bit of a mess and far from optimized, but here is the code for the Post Processor Class..
I used it as a class with its own render function and not as a Custom Scene Node like the clouds and the water
while developing.. (it works fine under GL GLSL, but HLSL ...)

Code: Select all

 
 
 
 
 #ifndef POSTPROCESSOR_INCD
 #define POSTPROCESSOR_INCD
 
 
 #include <irrlicht.h>
 
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 using namespace irr;
 using namespace core;
 using namespace scene;
 using namespace video;
 // using namespace gui;
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 
 
// class PostProcShadCallbckGLSL; // As a forward declaration because we might refer to it before we define it.. (I love c++)
//  class PostProcShadCallbckHLSL; // As a forward declaration because we might refer to it before we define it.. (I love c++)
 
 // GLSL..
 class PostProcShadCallbckGLSL : public video::IShaderConstantSetCallBack
  {public:
   virtual void OnSetConstants(video::IMaterialRendererServices* MatRenderServices,s32 userData)
    {video::IVideoDriver* AquiredVideoDriver = MatRenderServices->getVideoDriver();
     s32 TextureLayerID = 0;
     MatRenderServices->setPixelShaderConstant ("Image01", (s32*)(&TextureLayerID), 1);      // To where the scne was rendered..
     // Later, for when we deal with complex multipass effects..
     // TextureLayerID = 1;
     // Optional extra Texture used in Additional Effects..
     // MatRenderServices->setPixelShaderConstant ("Image02",(s32*)(&TextureLayerID), 1);
    }
    
  };
 
 // HLSL..
 class PostProcShadCallbckHLSL : public video::IShaderConstantSetCallBack
  {public:
   virtual void OnSetConstants(video::IMaterialRendererServices* MatRenderServices,s32 userData)
    {video::IVideoDriver* AquiredVideoDriver = MatRenderServices->getVideoDriver();
 
        // here as a test.. not used..
       M01World = AquiredVideoDriver->getTransform(video::ETS_WORLD);
       M05WorldViewProjection =   AquiredVideoDriver->getTransform(video::ETS_PROJECTION);
       M05WorldViewProjection *=  AquiredVideoDriver->getTransform(video::ETS_VIEW);
       M05WorldViewProjection *=  AquiredVideoDriver->getTransform(video::ETS_WORLD);
       M17WorldInverseTranspose = M01World.getTransposed(); // For Irrlicht this replaces the commonly used "world matrix!"
       M17WorldInverseTranspose.makeInverse();
/*
 
       MatRenderServices->setVertexShaderConstant("M01World", M01World.pointer(), 16);
       MatRenderServices->setVertexShaderConstant("M05WorldViewProjection",   M05WorldViewProjection.pointer(), 16);
       MatRenderServices->setVertexShaderConstant("M17WorldInverseTranspose", M17WorldInverseTranspose.pointer(), 16);
*/
 
     s32 TextureLayerID = 0;
     MatRenderServices->setPixelShaderConstant("Image01", (s32*)(&TextureLayerID), 1);      // To where the scne was rendered..
     // Later, for when we deal with complex multipass effects..
     // TextureLayerID = 1;
     // Optional extra Texture used in Additional Effects..
     // MatRenderServices->setPixelShaderConstant("Image02", (s32*)(&TextureLayerID), 1);
    }
 
 
 
    private:
   IrrlichtDevice*      PassedIrrDevice;
   video::IVideoDriver* AquiredVideoDriver;
  core::matrix4                   M01World;
 core::matrix4                   M05WorldViewProjection;
 core::matrix4                   M17WorldInverseTranspose;
 
  };
 
 
 
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
 
 
 // Class to hold our Screen Quad and Render-Target texture..
 class ScreenQuadAndTexture
  {public:
   // ScreenQuadAndTexture(IrrlichtDevice* PassDevice);
   ScreenQuadAndTexture();
   ~ScreenQuadAndTexture();
   void      CleanUp();
   ITexture* GetAlterTextFirst ();
   ITexture* GetAlterTextSecond ();
   ITexture* GetFlippedTexture ();
   void      FlipTextures ();
   void      WriteAltFirstToFile ();
   void      Reset();
   void      RenderSinglePass(s32 ChosenSHADERID);
   void      RenderToScreen();
   void      Draw2DImage();
   video::SMaterial& getMaterial();
   void      SetTextureSize(u32 XRes, u32 YRes);
   void      AddFragShaderByFilename(const char* TheFileName);
   void      DeleteFragShaderByFilename(const char* TheFileName);
   u32       GetFragShaderArraySize();
   const char* GetFragShaderShaderFileNameByIndex(u32 GetI);
   void      InsertFragShaderShaderFileNameAtIndex(const char* TheFileName,u32 GetInsetrI);
   void      DeleteFragShaderByIndex(u32 DelI);
 
   void      SetPassShader (u32 PassI, u32 UncheckedI); 
   void      ShiftPassShaderToNext (u32 PassI);
   void      ShiftPassShaderToPrevious (u32 PassI);
 
   void      AddPPRenderPass ();
   u32       GetPPRenderPassCount ();
 
   u32       GetPassShaderIndex (u32 PassI);
 
   u32       GetGeneratedShaderID (u32 Index);
 
   void      SetDevice (IrrlichtDevice*      SetDevice);
 
   void      RenderPassesThenToScreen();
 
 
 
   private:
   IrrlichtDevice*      PassedIrrDevice;
   video::IVideoDriver* AquiredVideoDriver;
   video::ITexture*     FlippedTexture;
   video::ITexture*     TempTexture;
   video::ITexture*     AlterTexSECOND;
   video::ITexture*     AlterTexFIRST;
   video::ITexture*     AlterTexTHIRD;
   video::SMaterial     ScreenQuadMaterial;
   video::S3DVertex vert[4];
 
   // THE OTHER VERTICES..
 
      video::S3DVertex Vertices[4]; // Screen Quad mesh..
 
   u16 index[6];
 
   u16 Indices[6];
 
   bool Flipper;
   bool FirstRender;
   irr::video::IImage* TestImage;
 
   u32 TxXRes;
   u32 TxYRes;
   core::array<const char*> ShaderFileNames; // Should include directory name relative to the EXE file..
 
   s32 PassShaderIDs [32]; // Which Effect is chosen for a given Pass..
   s32 ShaderIDarray [32]; // s32, as it is filled with Shader IDs as returned by "addHighLevelShaderMaterialFromFiles"..
 
   s32 ShaderGeneratedIDs [32];
 
   core::array<u32> GeneratedShaderIDs;
   core::array<u32> PassShaderAssignments;
   core::array<u32> CurrentShaderIDIndices;
   u32 RenderPassCount;
   u32 PPShaderCount;
   PostProcShadCallbckGLSL* TheCallbackForGLSL;
   PostProcShadCallbckHLSL* TheCallbackForHLSL;
   video::IGPUProgrammingServices* TheGPUServices;
 
    video::E_DRIVER_TYPE TheSelectedDriverType;// aquired from "AquiredVideoDriver"..
 
 
 
  };
 
 
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
 
    ScreenQuadAndTexture::ScreenQuadAndTexture() : Flipper (0), FirstRender(true)
    {
     // AquiredVideoDriver    = PassDevice->getVideoDriver();
     RenderPassCount = 0;
     PPShaderCount   = 0;
 
 
    }
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   ScreenQuadAndTexture::~ScreenQuadAndTexture()
    {// LEft here as a reminder..
   //  if ((AlterTexSECOND)) AquiredVideoDriver->removeTexture(AlterTexSECOND);
   //  if ((AlterTexFIRST))  AquiredVideoDriver->removeTexture(AlterTexFIRST);
   //  if ((AlterTexTHIRD))  AquiredVideoDriver->removeTexture(AlterTexTHIRD);
 
   //   PassedIrrDevice->drop(); // THE HIST SHOULD BE RESPONSIBLE FOR THIS....
    
    }
 
  void ScreenQuadAndTexture::CleanUp() // HOST WANTS YOU TO DO THIS AT THE RIGHT TIME..???
    {// Take a good look at how we alternate between these two textures during Multipass Rendering..
     if ((AlterTexSECOND)) AquiredVideoDriver->removeTexture(AlterTexSECOND);
     if ((AlterTexFIRST))  AquiredVideoDriver->removeTexture(AlterTexFIRST);
     if ((AlterTexTHIRD))  AquiredVideoDriver->removeTexture(AlterTexTHIRD);
    }
 
 
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   ITexture* ScreenQuadAndTexture::GetAlterTextFirst ()
    {return AlterTexFIRST;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   ITexture* ScreenQuadAndTexture::GetAlterTextSecond ()
    {return AlterTexSECOND;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   ITexture* ScreenQuadAndTexture::GetFlippedTexture ()
    {return FlippedTexture;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::FlipTextures ()
    {
     FlippedTexture = Flipper == 0 ?  AlterTexFIRST : AlterTexSECOND;
     Flipper = !Flipper;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    void ScreenQuadAndTexture::WriteAltFirstToFile ()
    {
     TestImage = AquiredVideoDriver->createImage(irr::video::ECF_A8R8G8B8,core::dimension2d<u32>( 512 , 512 ));
 
     // Someone noted..
     // You can use textures as rendertarget (IVideoDriver::setRenderTarget).
     // And then convert the texture to an IImage (IVideoDriver::createImage).
     // I don't think there is a solution aside from that in Irrlicht.
 
     TestImage->setPixel(10, 10, SColor( 255 , 207 , 223 , 169 )); // Test works..
     TestImage->fill(SColor( 255 , 207 , 0 , 0 )); // Test works..
     //  AquiredVideoDriver->setRenderTarget(TestImage, false, false); // No!
     // FIGURE THIS OUT..
     AquiredVideoDriver->writeImageToFile(TestImage,L"data/XXXXsample.jpg");
     TestImage->drop();
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::Reset()
    {FirstRender = true;
     Flipper = 0;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::RenderSinglePass(s32 ChosenSHADERID)
    {
     if (FirstRender = true )
      {FlipTextures (); FirstRender = false;}  // As the very first render was to "AlterTexFIRST"..
       // ---- --- -- -  Pass (for multipass effects this is the basis) --- --- -- - 
       ScreenQuadMaterial.setTexture(0, FlippedTexture); // Allready done in "main", but ommitting this causes a strange initial "flash"..
       ScreenQuadMaterial.MaterialType = (video::E_MATERIAL_TYPE) ChosenSHADERID;
       AquiredVideoDriver->setMaterial(ScreenQuadMaterial); // Because we had assigned the material a new shader..
       FlipTextures ();
       AquiredVideoDriver->setRenderTarget(FlippedTexture, false, false);
     //  AquiredVideoDriver->drawIndexedTriangleList(vert, 4, index, 2);
 
     // THESE DID NTO HELP FOR HLSL..
     //AquiredVideoDriver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix); // clear the projection matrix 
     //AquiredVideoDriver->setTransform(video::ETS_VIEW, core::IdentityMatrix);     // clear the view matrix 
     //AquiredVideoDriver->setTransform(video::ETS_WORLD, core::IdentityMatrix );     // set the transform
     //AquiredVideoDriver->setMaterial(ScreenQuadMaterial);
     //AquiredVideoDriver->drawIndexedTriangleList(Vertices, 4, Indices, 2); 
       // ---- --- -- - 
       FlipTextures ();
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::RenderToScreen()
    {
     // Render the "FINAL PROCESSES PIXELS" to the "FRAME BUFFER"..
     AquiredVideoDriver->setRenderTarget(video::ERT_FRAME_BUFFER, true, true);
     AquiredVideoDriver->drawIndexedTriangleList(vert, 4, index, 2);
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::RenderPassesThenToScreen()
    {
 
     for (u32 PassIndx = 0; PassIndx < RenderPassCount; PassIndx++)
      {
 
     if (FirstRender = true )
      {FlipTextures (); FirstRender = false;}  // As the very first render was to "AlterTexFIRST"..
       // ---- --- -- -  Pass (for multipass effects this is the basis) --- --- -- - 
       ScreenQuadMaterial.setTexture(0, FlippedTexture); // Allready done in "main", but ommitting this causes a strange initial "flash"..
       ScreenQuadMaterial.MaterialType 
       // = (video::E_MATERIAL_TYPE) GetGeneratedShaderID (GetPassShaderIndex (PassIndx)); // Shows how we reached this index into the array below..
        = (video::E_MATERIAL_TYPE) GeneratedShaderIDs[CurrentShaderIDIndices [PassIndx]] ;    
       AquiredVideoDriver->setMaterial(ScreenQuadMaterial); // Because we had assigned the material a new shader..
       FlipTextures (); // May need arch redo for effects..
       AquiredVideoDriver->setRenderTarget(FlippedTexture, false, false);
       AquiredVideoDriver->drawIndexedTriangleList(vert, 4, index, 2);
       // ---- --- -- - 
       FlipTextures ();
      }
     AquiredVideoDriver->setRenderTarget(video::ERT_FRAME_BUFFER, true, true);
     AquiredVideoDriver->drawIndexedTriangleList(vert, 4, index, 2); // Final render before buffers swap..
     // Reset... (also available as a function possible needed in further development)..
     FirstRender = true;
     Flipper = 0;
 
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
 
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::Draw2DImage()
    {TempTexture = Flipper == 0 ?  AlterTexFIRST : AlterTexSECOND;
     AquiredVideoDriver->draw2DImage(TempTexture,
                                     core::rect<s32>(0 + 128,
                                                     0 + 128,
                                                     (TempTexture->getSize().Width / 2) + 128,
                                                     (TempTexture->getSize().Height / 2) + 128),
                                     core::rect<s32>(0 + 128,
                                                     0 + 128,
                                                     (TempTexture->getSize().Width / 8) + 128,
                                                     (TempTexture->getSize().Height / 8) + 128 )
                                                    );
    }
   video::SMaterial& ScreenQuadAndTexture::getMaterial() 
    {return ScreenQuadMaterial;
    }
   //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::SetTextureSize(u32 XRes, u32 YRes) 
    {TxXRes = XRes;
     TxYRes = YRes;
     AlterTexSECOND = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>(XRes, YRes)); // SAME AS IN FXAA!!!
     AlterTexFIRST  = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>(XRes, YRes));
     AlterTexTHIRD  = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>(XRes, YRes)); // Future advanced stuff where images are mixed after PP..
    }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::AddFragShaderByFilename(const char* TheFileName)
  {// if(ShaderFileNames.binary_search(TheFileName) == -1) // UNDERSTAND WHY THIS WAS USED IN OTHER CODE..
   // if(ShaderFileNames.linear_search(TheFileName) == -1) // IF WE WANTED TO REFER TO A SHADER ID BY ITS FILENAME AND NOT JUST AN INDEX??
   ShaderFileNames.push_back(TheFileName); // Add  a new filename..
   CurrentShaderIDIndices.push_back(0);
   u32 ResutlingID = 0;
   //                                  
 
 
 
 
   if (TheSelectedDriverType ==  EDT_OPENGL)
    {
   TheCallbackForGLSL = new PostProcShadCallbckGLSL(); // DO THEY DIFFER BETWEEN GLSL AND HLSL? NO!..
   ResutlingID = TheGPUServices
     ->addHighLevelShaderMaterialFromFiles("Shaders/GL_0000_VERT_PP_GENERIC.glsl",
                                           "main", EVST_VS_2_0, TheFileName,
                                           "main", EPST_PS_3_0, TheCallbackForGLSL,
                                           EMT_SOLID, 0, EGSL_DEFAULT 
                                          );
     }
 
   if (TheSelectedDriverType ==  EDT_DIRECT3D9)
    {
 
     // printf("THIS HAPPENED"); while (1 == 1) {}
 
   TheCallbackForHLSL = new PostProcShadCallbckHLSL(); // DO THEY DIFFER BETWEEN GLSL AND HLSL? NO!..
   ResutlingID = TheGPUServices
     ->addHighLevelShaderMaterialFromFiles(  "Shaders/HL_0000_VERT_PP_GENERIC.hlsl", //..
                                           // TheFileName, //..
                                           "VertexMain", EVST_VS_3_0, TheFileName,
                                           "PixelMain", EPST_PS_3_0, TheCallbackForHLSL,
                                           EMT_SOLID, 0, EGSL_DEFAULT 
                                          );
 
     }
 
 
   GeneratedShaderIDs.push_back(ResutlingID);
 
   if (TheSelectedDriverType ==  EDT_OPENGL)
    {
     TheCallbackForGLSL->drop();
    }
 
   if (TheSelectedDriverType ==  EDT_DIRECT3D9)
    {
     TheCallbackForHLSL->drop();
    }
 
 
 
 
 
 
   //                                  
   PPShaderCount ++;
//      printf("THIS HAPPENED"); while (1 == 1) {}
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::DeleteFragShaderByFilename(const char* TheFileName)
  {s32 index = ShaderFileNames.binary_search(TheFileName);  // Remove node from depth pass array..
   if(index != -1) ShaderFileNames.erase(index);
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::DeleteFragShaderByIndex(u32 DelI)
  {   ShaderFileNames.erase(DelI);
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 u32 ScreenQuadAndTexture::GetFragShaderArraySize()
  {return ShaderFileNames.size();
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 const char* ScreenQuadAndTexture::GetFragShaderShaderFileNameByIndex(u32 GetI)
  {return ShaderFileNames[GetI];
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::InsertFragShaderShaderFileNameAtIndex(const char* TheFileName,u32 GetInsetrI)
  {return ShaderFileNames.insert(TheFileName,GetInsetrI);
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::SetPassShader (u32 PassI, u32 UncheckedI)
  {CurrentShaderIDIndices [PassI] = UncheckedI;
   PassShaderAssignments [PassI] = GeneratedShaderIDs[CurrentShaderIDIndices[UncheckedI]]; // CHECK FOR MAX..
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::ShiftPassShaderToNext (u32 PassI) // At least one pass must have been created..
  {
    // /* 
   if (CurrentShaderIDIndices [PassI] >= (PPShaderCount - 1)) 
    {CurrentShaderIDIndices [PassI] = 0;
     PassShaderAssignments [PassI] = GeneratedShaderIDs[CurrentShaderIDIndices [PassI]];
     return;
    }
   CurrentShaderIDIndices [PassI] ++;
   PassShaderAssignments [PassI] = GeneratedShaderIDs[CurrentShaderIDIndices [PassI]];
    // *// 
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 void ScreenQuadAndTexture::ShiftPassShaderToPrevious (u32 PassI)
  {
    // /* 
   if (CurrentShaderIDIndices [PassI] == 0) 
    {CurrentShaderIDIndices [PassI] = (PPShaderCount - 1);
     PassShaderAssignments [PassI] = GeneratedShaderIDs[CurrentShaderIDIndices [PassI]];
     return;
    }
   CurrentShaderIDIndices [PassI] --;
   PassShaderAssignments [PassI] = GeneratedShaderIDs[CurrentShaderIDIndices [PassI]];
    // */ 
  }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 u32 ScreenQuadAndTexture::GetPassShaderIndex (u32 PassI)
  {return CurrentShaderIDIndices [PassI]; // Wre not interested in the actual ID, but we are in the Index..
  }
 
 
 
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   //        case KEY_KEY_1: PassShaderIDs [0]++; if(PassShaderIDs [0] > 16) {PassShaderIDs [0] = 0;} break;
  void ScreenQuadAndTexture::AddPPRenderPass ()
   {RenderPassCount++;
    //CurrentShaderIDIndices.push_back(0); // All Created Pass Shader ID Incices at 0 (bypass)..
    PassShaderAssignments.push_back(0);
   }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   u32 ScreenQuadAndTexture::GetPPRenderPassCount ()
   {
    return RenderPassCount;
   }
 
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
   u32 ScreenQuadAndTexture::GetGeneratedShaderID (u32 Index)
    {
     return  GeneratedShaderIDs[Index];
    }
 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void ScreenQuadAndTexture::SetDevice (IrrlichtDevice*      SetDevice)
    { PassedIrrDevice = SetDevice;
          AquiredVideoDriver    = PassedIrrDevice->getVideoDriver();
 
        TheSelectedDriverType = AquiredVideoDriver->getDriverType();
 
  // PassedIrrDevice->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
  // PassedIrrDevice->getVideoDriver()->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
 
     //                                  
     // video::IGPUProgrammingServices* TheGPUServices = AquiredVideoDriver->getGPUProgrammingServices();
 
     // Done once at construction..
     TheGPUServices = AquiredVideoDriver->getGPUProgrammingServices();
     if (TheGPUServices == 0) 
      {std::cout << "Could not access the GPU" << std::endl;
      // return 3;
      }
 
   // PostProcShadCallbckGLSL* TheCallbackForGLSL = new PostProcShadCallbckGLSL();
     // TheCallbackForGLSL = new PostProcShadCallbckGLSL();
     //                                  
 
     // These "Render Target Resolutions" could have been copied from "Device Resolution"..
     // With "FXAA", this Buffer Resolution should be Identical to its reference inside the "FXAA" Shader Code..
     // While we don't control these values inside the shader code from the application we should make sure they are the same..
     // We have TWO Render Target Textures because we "Alternate" or "Flip-Flop" between them to make the "Multi Layering" of PP-Effects possible..
 
     // NOTE: When your Render Target Texture is not EXACTLY the same size (Biggest value between X and Y) as your 3d View, i.e.
     // your Window Viewport then there will be some "automatic smoothing" of the pixels in the Rendertarget
     // which means that FXAA would not be fed the bare pixels and that the full effect of FXAA may not be achieved,
     // but, FXAA still does a mrvelous job! In any case, many times our RTT is smaller than the Window Viewort.
     
     // AlterTexSECOND = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>( 512, 512 )); // SAME AS IN FXAA!!!
     // AlterTexFIRST  = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>( 512, 512 ));
     // AlterTexTHIRD  = AquiredVideoDriver->addRenderTargetTexture(core::dimension2d<u32>( 512, 512 )); // Future advanced stuff where images are mixed after PP..
 
 
     FlippedTexture = AlterTexFIRST;
 
     // When dealing with BLUR based PP Effects it is usually better to save time by using
     // smaller images as resolution becomes less important with blur..
     // Also note that these are only two images accesed in an alternating fasion for this
     // example and that we could have many images in different sizes for different effects.
     // It is however still important to keep the buffers related to FXAA at the same resolution
     // as the resolution referred to inside the FXAA Shader..
 
     ScreenQuadMaterial.Wireframe    = false;        // Material for screen quad
     ScreenQuadMaterial.Lighting     = false;
     ScreenQuadMaterial.ZWriteEnable = false;
     ScreenQuadMaterial.TextureLayer->TextureWrapU = ETC_CLAMP_TO_EDGE;
     ScreenQuadMaterial.TextureLayer->TextureWrapV = ETC_CLAMP_TO_EDGE;
 
     vert[0] = video::S3DVertex(-1, -1, 0, 0, 0, 1, video::SColor(0), 0, 1); // Screen Quad..
     vert[1] = video::S3DVertex(-1,  1, 0, 0, 0, 1, video::SColor(0), 0, 0);
     vert[2] = video::S3DVertex( 1,  1, 0, 0, 0, 1, video::SColor(0), 1, 0);
     vert[3] = video::S3DVertex( 1, -1, 0, 0, 0, 1, video::SColor(0), 1, 1);
     // Drawing order..
     index[0] = 0; index[1] = 1; index[2] = 2; index[3] = 0; index[4] = 2; index[5] = 3;
 
     Vertices[0] = video::S3DVertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, video::SColor(255,255,255,255), 0.f, 1.f); 
     Vertices[1] = video::S3DVertex(-1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f, video::SColor(255,255,255,255), 0.f, 0.f); 
     Vertices[2] = video::S3DVertex( 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 1.0f, video::SColor(255,255,255,255), 1.f, 0.f); 
     Vertices[3] = video::S3DVertex( 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, video::SColor(255,255,255,255), 1.f, 1.f); 
     Indices[0] = 0; Indices[1] = 1;  Indices[2] = 2; // setup the corresponding indices..
     Indices[3] = 2; Indices[4] = 3;  Indices[5] = 0; 
 
 }
 
 
 
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

O.K. Got rid of the bogus memory seen in the second render, but
now, unlike GL, there is no swapping the target textures..
It always only shows the effect of the shader used in the last pass.
? :x
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Screen Quad Post Processing

Post by mongoose7 »

You're probably not setting the samplers correctly. (Don't ask me, I don't do HLSL.)
The_Glitch
Competition winner
Posts: 523
Joined: Tue Jan 15, 2013 6:36 pm

Re: Screen Quad Post Processing

Post by The_Glitch »

I use DX9 and don't have that issue.
Vectrotek
Competition winner
Posts: 1087
Joined: Sat May 02, 2015 5:05 pm

Re: Screen Quad Post Processing

Post by Vectrotek »

createDeviceEx(params); messes with depth under HLSL and with Occlusion Query..
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Screen Quad Post Processing

Post by Mel »

Try disabling the stencil buffer?...
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Post Reply