Monday, December 12, 2011

Post Processing Using DirectX


 Finally here I am after almost more than a year! Surprisingly, its not that I have been idle for all this time, but things kept me really occupied to actually spend time to update the blog. I have been working really hard on my DirectX framework lately. I have successfully added Shader Engine to the codebase alongwith support for basic Phong Shader as well. Also, I have added lighting support, so now instead of just passing single light direction vector to the shader, Shader Engine takes care of identifying light source as Omni, Directional & Spot & shaders accordingly :) Well, i will surely post more on that with screenshots but not in this post. I have also wrote basic & intermediate Renderman Shaders for Maya. One of the shader was Car Paint Shader using Renderman's Ray Tracing! Am quite proud of the result which I have obtained, but am still lacking at many things. Since, things are way too realistic in Offline rendering, more is less unlike Games where good enough & fast is acceptable. Even this will be posted in separate post. This post is all about my quest to understand how exactly Post Processing is setup in DirectX & going ahead to actually perform few Post Processing operations.

Well, there are many tutorials & guidelines available on Internet to understand how to get this done in DIrectX, though I would go ahead & try to explain how I achieved this. Please feel free to drop a comment or mail in case you find any flaws or have better suggestion regarding doing the same. Also, code is available as always on request.

Basically, Post Processing is nothing but Rendering a normal scene on an off screen buffer & then processing that buffer / texture, just before performing final render operation. So, mainly, its Creating an off screen render target where you can render scene to process & later on treating that buffer as a separate image & carry out usual image processing to achieve desired results.

Logical steps are as follows

- Get current frame buffer information
- Create a new D3D texture with frame buffer width & height, with usage as RenderTarget with Default memory pool. Make sure to get access to the render target surface level. e.g> pRenderTargetTexture->GetSurfaceLevel(0, &pRenderTargetSurface);
- Just before rendering, set this as Render Target. e.g> pDevice->SetRenderTarget(0, pRenderTargetSurface) & perform normal rendering.
- Now, set original backbuffer as render target e.g> pDevice->SetRenderTarget(0, pBackBufferSurface) & perform
rendering on a screen aligned quad which has co-ordinates already in clipping space.
- Just before drawing, texture on screen aligned quad, apply any Post Processing as required to achieve the desired result.

The most confusing part could be the rendering order, here is how I got it working, in brief :

void Render()
{
RenderToTexture()

device->clear(...);
device->BeginScene();

effect->SetTechnique(..);

// set textures & matrices, variables required by the post processing shaders here..
effect->Begin(..)

effect->End();

device->EndScene();
device->Present(...);
}

where,

void RenderToTexture()
{
device->SetRenderTarget(0, renderTargetSurface);
device->BeginScene();

// normal scene rendering goes here

device->SetRenderTarget(0, backBuffer);
device->EndScene();
}

Hope it is helpful to those who are trying to achieve the same thing. It worked for me!

Now back to the most interesting part, actual post processing!
Once we have access toe back buffer in our shader, writing Post Processing is pretty straight forward. We sample our offline texture as normal tex2D() lookup function, play around with UV values / color values to achieve the desired result. Here are some of the things which i tried :

Default:




 











Monochrome :

 

NightVision :

 

Depth Pass :


Normal Sobel Edge Detection :

 

Sobel Edge Detection with Depth :

 

Sobel Edge Detection with Normal :


Black n White :


Normal Information :

 

 
 
Old TV :

Pixelate :




 

Bath Glass :



 

These effects do look more promising in Real time than as images. Am planning to add a Video pretty soon for the same. Stay tuned for the same.

Meanwhile, I just cannot stop myself from posting images of an Object based shader Toon Rendering. This will be combined with Edge Detection Post Processing shader shown above to form a complete effect, but thats a work in progress, meanwhile here are images for simple toon rendering :)




 

The kernel used for edge detection is Sobel Edge detection kernel :
{0, 1, 0, 1, -4, 1, 0, 1, 0}

In case you need any of the shaders ( which can be googled anyways ) for post processing please let me know so that I can share them. :)

3 comments:

V12 said...

sahi hai chotte !
keep up the good work

ASHU said...

Hi can you please share the shaders please

Rupesh Mandke said...

Sure Ashu, let me know the email id & I will mail you.