• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lipsryme

Separable gaussian blur too dark ?

20 posts in this topic

So I implemented a 9-tap (5-tap linear sampled) seperable gaussian blur which you can see here:

[CODE]
float4 PS(VSO input) : SV_TARGET0
{
const float offset[3] = { 0.0, 1.3846153846, 3.2307692308 };
const float weight[3] = { 0.2270270270, 0.3162162162, 0.0702702703 };
const float pixelSize = float2(1.0f / _ScreenSize.x, 1.0f / _ScreenSize.y);


float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV * pixelSize).xyz * weight[0];

for (int i = 1; i < 3; i++)
{
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV + float2(0.0f, offset[i] * pixelSize)).xyz * weight[i];
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV - float2(0.0f, offset[i] * pixelSize)).xyz * weight[i];
}

return float4(texColor.rgb, 1.0f);
}
[/CODE]

I'm just not sure if the result is correct since its quite a lot darker than the original image:
original : [url="http://cl.ly/image/093q0Z2c0m1a"]http://cl.ly/image/093q0Z2c0m1a[/url]
blurred: [url="http://cl.ly/image/3E0P2d3t0U1g"]http://cl.ly/image/3E0P2d3t0U1g[/url]

I'm trying to achieve a bloom effect so in this sense making the result darker is quite the opposite of what I want...
Am I doing something wrong ? Edited by lipsryme
0

Share this post


Link to post
Share on other sites
[s]I think you weights are off.
Shouldn't they add up to 1 ?[/s]

Nevermind, didn't really read through the algo first [img]http://public.gamedev.net//public/style_emoticons/default/wacko.png[/img] Edited by Madhed
0

Share this post


Link to post
Share on other sites
[quote name='lipsryme' timestamp='1347123465' post='4978033']
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV * pixelSize).xyz * weight[0];
[/quote]

Doesn't that always sample the top left corner (i.e Black) ?

I think it should be:
[code]
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV).xyz * weight[0];
[/code]
Not? Edited by Madhed
1

Share this post


Link to post
Share on other sites
Your first weight seems to be about half the weight it should be.
Also [eqn]w_0 + 2\sum_{i=1}^{\infty}w_i=1[/eqn]

I recommend not using a hardcoded array like this. Use a function that evaluates the gaussian filter for you instead.

[CODE]
float gaussianKernel(float x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}
[/CODE]

The compiler will compile this into constant weights, but it's easier for you to manage your code or compile this shader for multiple standard deviations.

Also, shouldn't your pixel size be a float2?
[CODE]
const float pixelSize = float2(1.0f / _ScreenSize.x, 1.0f / _ScreenSize.y);
[/CODE]

And yes, Madhed is right too. Edited by CryZe
0

Share this post


Link to post
Share on other sites
Well I was implementing it based on this implementation here:
[url="http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/"]http://rastergrid.co...inear-sampling/[/url]

or this one seems to do the same:
[url="http://www.geeks3d.com/20100909/shader-library-gaussian-blur-post-processing-filter-in-glsl/"]http://www.geeks3d.c...filter-in-glsl/[/url]


[b][u]update:[/u][/b]
You were right the initial texcolor was wrong.
This code now seems to give me a correct image:
[CODE]
float4 PS(VSO input) : SV_TARGET0
{
const float offset[3] = { 0.0, 1.3846153846, 3.2307692308 };
const float weight[3] = { 0.2270270270, 0.3162162162, 0.0702702703 };;
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV).xyz * weight[0];

for (int i = 1; i < 3; i++)
{
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV + float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight[i];
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV - float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight[i];
}

//return TargetTexture.Sample(TargetTextureSampler, input.UV);
return float4(texColor.rgb, 1.0f);

}
[/CODE]

@CryZe what are those inputs 'x' and 'standardDeviation' ?
x = i in my case ? Edited by lipsryme
0

Share this post


Link to post
Share on other sites
Yes, x is your i and standardDeviation correlates to the width of the filter (it should be about a third of the maximum i). Your weights still seem off though. I fixed them:
[CODE]
const float weight[3] = { 0.40261952, 0.2442015368, 0.0544886997 };
[/CODE] Edited by CryZe
0

Share this post


Link to post
Share on other sites
With that in mind would this case be correct ?
[CODE]
float gaussianKernel(float x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}

float4 PS(VSO input) : SV_TARGET0
{
const float offset[3] = { 0.0, 1.3846153846, 3.2307692308 };
const float weight[3] = { 0.45405405404, 0.3162162162, 0.0702702703 };;
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV).xyz * weight[0];

for (int i = 1; i < 3; i++)
{
float weight = gaussianKernel(i, 3 / 3); // (2 / 3) also gives different results
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV + float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV - float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
}
return float4(texColor.rgb, 1.0f);
}
[/CODE]

Solving the equation with those numbers gives me different ones than my predefined ones. Edited by lipsryme
0

Share this post


Link to post
Share on other sites
[CODE]
float gaussianKernel(float x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}

float4 PS(VSO input) : SV_TARGET0
{
const int numSamples = 3;
const float standardDeviation = numSamples / 3.0;

const float offset[numSamples] = { 0.0, 1.3846153846, 3.2307692308 };
const float weight[numSamples] = { 0.40261952, 0.2442015368, 0.0544886997 }; //Either use these or the gaussianKernel function
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV).xyz * gaussianKernel(0, standardDeviation); //You forgot about this weight here

for (int i = 1; i < numSamples; i++)
{
float weight = gaussianKernel(i, standardDeviation);
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV + float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV - float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
}
return float4(texColor.rgb, 1.0f);
}
[/CODE]

You might also want to check out the implementation I'm currently using in my engine (even though I'm currently switching to a more optimized compute shader implemention with a runtime of O(log n) per pixel):
[CODE]#ifndef MIN_WEIGHT
#define MIN_WEIGHT 0.0001f
#endif
#ifndef FILTER
#error You have to define the filter. (FILTER = (GAUSSIAN|EXPONENTIAL))
#endif
#define GAUSSIAN 0
#define EXPONENTIAL 1
#if FILTER == GAUSSIAN
#ifndef STANDARD_DEVIATION
#error You have to define the standard deviation when using a gaussian kernel. (STANDARD_DEVIATION = float)
#endif
#elif FILTER == EXPONENTIAL
#ifndef MEAN_VALUE
#error You have to define the mean value when using an exponential kernel. (MEAN_VALUE = float)
#endif
#endif
#ifndef DIRECTION
#error You have to define the direction. (DIRECTION = (HORIZONTAL|VERTICAL|int2(x,y)))
#endif
#ifndef MIP
#define MIP 0
#endif
#define HORIZONTAL int2(1, 0)
#define VERTICAL int2(0, 1)
Texture2D SourceTexture : register(t0);
cbuffer InfoBuffer : register(b0)
{
float Width;
float Height;
};
struct PSIn
{
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
float2 ScreenPos : SCREEN_POSITION;
};
float gaussianKernel(int x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}
float integratedExponentialKernel(float x, float m)
{
return 0.5 * (1 - exp(-x / m) / 2) * (sign(x) + 1) - 0.25 * exp(x / m) * (sign(x) - 1);
}
float exponentialKernel(int x, float m)
{
return integratedExponentialKernel(x + 0.5, m) - integratedExponentialKernel(x - 0.5, m);
}
float filter(int x)
{
#if FILTER == GAUSSIAN
return gaussianKernel(x, STANDARD_DEVIATION);
#elif FILTER == EXPONENTIAL
return exponentialKernel(x, MEAN_VALUE);
#endif
}
float3 sample(int2 position, int offset)
{
float3 textureColor = 0.0f;
float2 newOffset = offset * DIRECTION;

if (newOffset.x >= -8 && newOffset.x <= 7 && newOffset.y >= -8 && newOffset.y <= 7)
textureColor = SourceTexture.Load(
int3(position, MIP),
newOffset);
else
textureColor = SourceTexture.Load(int3(position + newOffset, MIP));

return textureColor;
}
float4 PSMain(PSIn Input) : SV_Target
{
float3 accumulatedColor = 0.0f;

float accumulatedWeight = 0, weight = 0;
[unroll]
for (int x = 0; (weight = filter(x)) > MIN_WEIGHT; ++x)
{
accumulatedWeight += (x != 0) ? (2 * weight) : weight;
}
[unroll]
for (int x = 0; (weight = filter(x)) > MIN_WEIGHT; ++x)
{
accumulatedColor += weight / accumulatedWeight * sample((int2)Input.ScreenPos, x);
if (x != 0)
accumulatedColor += weight / accumulatedWeight * sample((int2)Input.ScreenPos, -x);
}
return float4(accumulatedColor, 1);
}
[/CODE] Edited by CryZe
1

Share this post


Link to post
Share on other sites
@cryze

OP's initial weights were alright. I stumbled across this also the first time I had a look at the code. He is doing 2 samples per loop iteration, so the weights add up to 1 as they should be.
0

Share this post


Link to post
Share on other sites
He was / is not doing it for the sample with the index 0. Both samples with index 1 had higher weights, which would not have resulted in a proper gaussian blur. Edited by CryZe
2

Share this post


Link to post
Share on other sites
One of my friends has a good blog post he did on the issue you can check it out here:
http://theinstructionlimit.com/gaussian-blur-experiments

Hope this helps! :)
1

Share this post


Link to post
Share on other sites
[quote name='CryZe' timestamp='1347129215' post='4978056']
[CODE]
float gaussianKernel(float x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}

float4 PS(VSO input) : SV_TARGET0
{
const int numSamples = 3;
const float standardDeviation = numSamples / 3.0;

const float offset[numSamples] = { 0.0, 1.3846153846, 3.2307692308 };
const float weight[numSamples] = { 0.40261952, 0.2442015368, 0.0544886997 }; //Either use these or the gaussianKernel function
float3 texColor = TargetTexture.Sample(TargetTextureSampler, input.UV).xyz * gaussianKernel(0, standardDeviation); //You forgot about this weight here

for (int i = 1; i < numSamples; i++)
{
float weight = gaussianKernel(i, standardDeviation);
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV + float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
texColor += TargetTexture.Sample(TargetTextureSampler, input.UV - float2(offset[i], 0.0f) / _ScreenSize.x).rgb * weight;
}
return float4(texColor.rgb, 1.0f);
}
[/CODE]

You might also want to check out the implementation I'm currently using in my engine (even though I'm currently switching to a more optimized compute shader implemention with a runtime of O(log n) per pixel):
[CODE]#ifndef MIN_WEIGHT
#define MIN_WEIGHT 0.0001f
#endif
#ifndef FILTER
#error You have to define the filter. (FILTER = (GAUSSIAN|EXPONENTIAL))
#endif
#define GAUSSIAN 0
#define EXPONENTIAL 1
#if FILTER == GAUSSIAN
#ifndef STANDARD_DEVIATION
#error You have to define the standard deviation when using a gaussian kernel. (STANDARD_DEVIATION = float)
#endif
#elif FILTER == EXPONENTIAL
#ifndef MEAN_VALUE
#error You have to define the mean value when using an exponential kernel. (MEAN_VALUE = float)
#endif
#endif
#ifndef DIRECTION
#error You have to define the direction. (DIRECTION = (HORIZONTAL|VERTICAL|int2(x,y)))
#endif
#ifndef MIP
#define MIP 0
#endif
#define HORIZONTAL int2(1, 0)
#define VERTICAL int2(0, 1)
Texture2D SourceTexture : register(t0);
cbuffer InfoBuffer : register(b0)
{
float Width;
float Height;
};
struct PSIn
{
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
float2 ScreenPos : SCREEN_POSITION;
};
float gaussianKernel(int x, float standardDeviation)
{
return exp(-(x * x) / (2 * standardDeviation * standardDeviation)) / (sqrt(2 * 3.14159265) * standardDeviation);
}
float integratedExponentialKernel(float x, float m)
{
return 0.5 * (1 - exp(-x / m) / 2) * (sign(x) + 1) - 0.25 * exp(x / m) * (sign(x) - 1);
}
float exponentialKernel(int x, float m)
{
return integratedExponentialKernel(x + 0.5, m) - integratedExponentialKernel(x - 0.5, m);
}
float filter(int x)
{
#if FILTER == GAUSSIAN
return gaussianKernel(x, STANDARD_DEVIATION);
#elif FILTER == EXPONENTIAL
return exponentialKernel(x, MEAN_VALUE);
#endif
}
float3 sample(int2 position, int offset)
{
float3 textureColor = 0.0f;
float2 newOffset = offset * DIRECTION;

if (newOffset.x >= -8 &amp;&amp; newOffset.x <= 7 &amp;&amp; newOffset.y >= -8 &amp;&amp; newOffset.y <= 7)
textureColor = SourceTexture.Load(
int3(position, MIP),
newOffset);
else
textureColor = SourceTexture.Load(int3(position + newOffset, MIP));

return textureColor;
}
float4 PSMain(PSIn Input) : SV_Target
{
float3 accumulatedColor = 0.0f;

float accumulatedWeight = 0, weight = 0;
[unroll]
for (int x = 0; (weight = filter(x)) > MIN_WEIGHT; ++x)
{
accumulatedWeight += (x != 0) ? (2 * weight) : weight;
}
[unroll]
for (int x = 0; (weight = filter(x)) > MIN_WEIGHT; ++x)
{
accumulatedColor += weight / accumulatedWeight * sample((int2)Input.ScreenPos, x);
if (x != 0)
accumulatedColor += weight / accumulatedWeight * sample((int2)Input.ScreenPos, -x);
}
return float4(accumulatedColor, 1);
}
[/CODE]
[/quote]

Hi,

I have few questions about your approach:

1) why you use the custom semantic SCREEN_POSITION and not the SV_Position which is actually the same once you get it in the pixel shader as input.

2) which kind of kernel is the exponential one with respect to the standard gaussian one and which visual results it gives and what is best for?

3) Also, do you support a poisson sampling kernel as well ? If yes what's the best way to express it and what is good for (I mean in what situation)

4) do you apply you filter on downsampled version of your buffer? If yes how much and how that will impact the correctness of the end result ? I guess no, because I see you don't sample at the pixels edges ... (that should help biliniear sampling when you stretch at fullscreen, right?)

5) Last :D, do you know any good resource on the web where I can find a list of filters along with their use case situation (I mean something like when it's good to use that filter or that other one and in which case and how it looks like etc.)

Thanks in advance for any reply
0

Share this post


Link to post
Share on other sites
[quote name='MegaPixel' timestamp='1347185499' post='4978236']
1) why you use the custom semantic SCREEN_POSITION and not the SV_Position which is actually the same once you get it in the pixel shader as input.
[/quote]
Oh, I didn't even know about that, thanks [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

[quote name='MegaPixel' timestamp='1347185499' post='4978236']
2) which kind of kernel is the exponential one with respect to the standard gaussian one and which visual results it gives and what is best for?
[/quote]
The exponential kernel is the exponential distribution from probability theory. It's sharper in the center than a gaussian kernel. This is the reason why it's better suited for bloom than a gaussian kernel. In the Unreal Engine 4 Elemental Demo they used multiple gaussian kernels of different widths and summed them together to approximate an exponential distribution. The thing is, that it's not really separable. That's why they chose to sum multiple gaussians. I implemented it before knowing that it was not separable, that's why it's even in my code. I still don't know which one to choose for my engine. Here's a visual comparison of all of these filters:
[img]http://unlimitedengine.us.to/filters.png[/img]

[quote name='MegaPixel' timestamp='1347185499' post='4978236']
3) Also, do you support a poisson sampling kernel as well ? If yes what's the best way to express it and what is good for (I mean in what situation)
[/quote]
No, I can't think of a situation where it would make any sense.

[quote name='MegaPixel' timestamp='1347185499' post='4978236']
4) do you apply you filter on downsampled version of your buffer? If yes how much and how that will impact the correctness of the end result ? I guess no, because I see you don't sample at the pixels edges ... (that should help biliniear sampling when you stretch at fullscreen, right?)
[/quote]
I point sample the Mip 1 and render the result to a texture with half the size. I didn't really do any benchmarks. But it doesn't really look much worse. I'm currently implementing a compute shader version with logarithmic runtime. It should be fast enough to run in full resolution.

[quote name='MegaPixel' timestamp='1347185499' post='4978236']
5) Last , do you know any good resource on the web where I can find a list of filters along with their use case situation (I mean something like when it's good to use that filter or that other one and in which case and how it looks like etc.)
[/quote]
I don't know a good website that shows the different kernels. I just came up with the exponential distribution as a filter myself while seeing that Epic Games summed multiple gaussians together, which resulted in the shape of an exponential distribution, which let me think about why one does not simply implement a filter with exponential distribution instead of summing gaussians together. Edited by CryZe
0

Share this post


Link to post
Share on other sites
So to get a good looking bloom do I have to blur my lighting image several times or is there something else I have to change ?
Because as it is now its just slightly blurred but you can't even tell the difference when being added to the rest of the scene (albedo, ....)
0

Share this post


Link to post
Share on other sites


[quote name='MegaPixel' timestamp='1347185499' post='4978236']
5) Last , do you know any good resource on the web where I can find a list of filters along with their use case situation (I mean something like when it's good to use that filter or that other one and in which case and how it looks like etc.)
[/quote]
[quote]
I don't know a good website that shows the different kernels. I just came up with the exponential distribution as a filter myself while seeing that Epic Games summed multiple gaussians together, which resulted in the shape of an exponential distribution, which let me think about why one does not simply implement a filter with exponential distribution instead of summing gaussians together.
[/quote]

Well because is not separable! You also said that :). While Gaussian blur is separable.
0

Share this post


Link to post
Share on other sites
[quote name='lipsryme' timestamp='1347193797' post='4978281']
So to get a good looking bloom do I have to blur my lighting image several times or is there something else I have to change ?
Because as it is now its just slightly blurred but you can't even tell the difference when being added to the rest of the scene (albedo, ....)
[/quote]

You blur multiple times until you are satisfied ! Like 3/4 times will give you good results ! You do that by ping ponging and blurring repeatedly the same blurred image ! But then you can also use more or less taps or varying the standard deviation and see what happens ! Fx are not really rocket science. The rule is always tweak tweak tweak until it looks good :)
1

Share this post


Link to post
Share on other sites
[quote name='MegaPixel' timestamp='1347222451' post='4978383']
[quote name='lipsryme' timestamp='1347193797' post='4978281']
So to get a good looking bloom do I have to blur my lighting image several times or is there something else I have to change ?
Because as it is now its just slightly blurred but you can't even tell the difference when being added to the rest of the scene (albedo, ....)
[/quote]

You blur multiple times until you are satisfied ! Like 3/4 times will give you good results ! You do that by ping ponging and blurring repeatedly the same blurred image ! But then you can also use more or less taps or varying the standard deviation and see what happens ! Fx are not really rocket science. The rule is always tweak tweak tweak until it looks good [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]

Ok it's quite a bit better now with 4 x blur but I still seem to be putting it wrong together. What I currently do is on the last blur I return the blurred image + the original lighting image and then in my deferred composition shader I put it together like so:

[CODE]
float4 albedo = ToLinear(AlbedoTarget.Sample(LinearTargetSampler, input.UV));
float4 lighting = LightMapTarget.Sample(LinearTargetSampler, input.UV);
float AO = SSAOTarget.Sample(LinearTargetSampler, input.UV).r;
output = albedo * (float4(lighting.rgb, 1.0f) + AO);
[/CODE]

The lighting itself does look okay but when being combined with the rest it doesn't seem to do anything except give it a blurry border.
0

Share this post


Link to post
Share on other sites
[quote name='lipsryme' timestamp='1347308965' post='4978688']
[quote name='MegaPixel' timestamp='1347222451' post='4978383']
[quote name='lipsryme' timestamp='1347193797' post='4978281']
So to get a good looking bloom do I have to blur my lighting image several times or is there something else I have to change ?
Because as it is now its just slightly blurred but you can't even tell the difference when being added to the rest of the scene (albedo, ....)
[/quote]

You blur multiple times until you are satisfied ! Like 3/4 times will give you good results ! You do that by ping ponging and blurring repeatedly the same blurred image ! But then you can also use more or less taps or varying the standard deviation and see what happens ! Fx are not really rocket science. The rule is always tweak tweak tweak until it looks good [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[/quote]

Ok it's quite a bit better now with 4 x blur but I still seem to be putting it wrong together. What I currently do is on the last blur I return the blurred image + the original lighting image and then in my deferred composition shader I put it together like so:

[CODE]
float4 albedo = ToLinear(AlbedoTarget.Sample(LinearTargetSampler, input.UV));
float4 lighting = LightMapTarget.Sample(LinearTargetSampler, input.UV);
float AO = SSAOTarget.Sample(LinearTargetSampler, input.UV).r;
output = albedo * (float4(lighting.rgb, 1.0f) + AO);
[/CODE]

The lighting itself does look okay but when being combined with the rest it doesn't seem to do anything except give it a blurry border.
[/quote]

Do you blur the AO buffer right ?... The AO term should be part of the ambient part of the lighting equation, so it should be:

output = (albedo * float4(lighting.rgb, 1.0f) ) + AO;

becuase AO is part of the global illumination interaction so it should add as part of the ambient term...
0

Share this post


Link to post
Share on other sites
I always thought the ambient term has to only be added to the diffuse/specular light.
[b]edit[/b]: Actually no, if I add it to the albedo*lighting I get a weird merged ssao (white/grey) and albedo picture.
But anyway the AO term isn't the problem.

I guess showing it on pictures is easier:

Note: The blurred images already include tonemapping and BG lighting is turned down (0.2f)

Lighing only (blur off): [url="http://cl.ly/image/3x0o1w451W2x"]http://cl.ly/image/3x0o1w451W2x[/url]
Compose (blur off): [url="http://cl.ly/image/3K022S2a2Y0g"]http://cl.ly/image/3K022S2a2Y0g[/url]

Lighting only (4x blur): [url="http://cl.ly/image/0g0q0z1n0937"]http://cl.ly/image/0g0q0z1n0937[/url]
Compose (4x blur): [url="http://cl.ly/image/3D2j0K04413Y"]http://cl.ly/image/3D2j0K04413Y[/url]

As you can also see the back of the cube is leaking the light from the background, too which is a problem... Edited by lipsryme
0

Share this post


Link to post
Share on other sites
[quote name='lipsryme' timestamp='1347359565' post='4978853']
I always thought the ambient term has to only be added to the diffuse/specular light.
[b]edit[/b]: Actually no, if I add it to the albedo*lighting I get a weird merged ssao (white/grey) and albedo picture.
But anyway the AO term isn't the problem.

I guess showing it on pictures is easier:

Note: The blurred images already include tonemapping and BG lighting is turned down (0.2f)

Lighing only (blur off): [url="http://cl.ly/image/3x0o1w451W2x"]http://cl.ly/image/3x0o1w451W2x[/url]
Compose (blur off): [url="http://cl.ly/image/3K022S2a2Y0g"]http://cl.ly/image/3K022S2a2Y0g[/url]

Lighting only (4x blur): [url="http://cl.ly/image/0g0q0z1n0937"]http://cl.ly/image/0g0q0z1n0937[/url]
Compose (4x blur): [url="http://cl.ly/image/3D2j0K04413Y"]http://cl.ly/image/3D2j0K04413Y[/url]

As you can also see the back of the cube is leaking the light from the background, too which is a problem...
[/quote]

sorry my fault, you should actually modulate with the SSAO term. Try:

output = AO*albedo * float4(lighting.rgb, 1.0f);

But then I don't know very well how you structured your pipeline, so If there is a problem elsewhere It would probably influence your results...
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0