[WIP] HB ambient occlusion for Ogre

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

SamiTheGreat wrote:Getting it work with FSAA would be nice feature so I will look if I can do something about it
I will kneel before you <3
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [WIP] HB ambient occlusion for Ogre

Post by dark_sylinc »

This is the GLSL & HLSL shaders I used to downsample depth:

Code: Select all

#version 330

uniform sampler2D depthTexture;

vec4 gl_FragCoord;
out float gl_FragDepth;

void main()
{
	float fDepth0 = texelFetch( depthTexture, ivec2(gl_FragCoord.xy * 2.0), 0 ).x;
	float fDepth1 = texelFetch( depthTexture, ivec2(gl_FragCoord.xy * 2.0) + ivec2( 0, 1 ), 0 ).x;
	float fDepth2 = texelFetch( depthTexture, ivec2(gl_FragCoord.xy * 2.0) + ivec2( 1, 0 ), 0 ).x;
	float fDepth3 = texelFetch( depthTexture, ivec2(gl_FragCoord.xy * 2.0) + ivec2( 1, 1 ), 0 ).x;

	//gl_FragDepth = texelFetch( depthTexture, ivec2(gl_FragCoord.xy * 2.0), 0 ).x;
	gl_FragDepth = min( min( fDepth0, fDepth1 ), min( fDepth2, fDepth3 ) );
}

Code: Select all

struct PS_INPUT
{
	float2 uv0			: TEXCOORD0;
};

Texture2D<float> depthTexture	: register(t0);

float main
(
	PS_INPUT inPs,
	float4 gl_FragCoord : SV_Position
) : SV_Depth
{
	float fDepth0 = depthTexture.Load( int3( int2(gl_FragCoord.xy * 2.0), 0 ) ).x;
	float fDepth1 = depthTexture.Load( int3( int2(gl_FragCoord.xy * 2.0) + int2( 0, 1 ), 0 ) ).x;
	float fDepth2 = depthTexture.Load( int3( int2(gl_FragCoord.xy * 2.0) + int2( 1, 0 ), 0 ) ).x;
	float fDepth3 = depthTexture.Load( int3( int2(gl_FragCoord.xy * 2.0) + int2( 1, 1 ), 0 ) ).x;
	
	//return depthTexture.Load( int3( int2(gl_FragCoord.xy * 2.0), 0 ) ).x;
	return min( min( fDepth0, fDepth1 ), min( fDepth2, fDepth3 ) );
}
Changing it to handle MSAA textures should be a no-brainer (it's the same work, but you use a Texture2DMS and sample the 4 MSAA subsamples instead of sampling the 4 neighbouring samples).

The only annoying part is providing multiple shaders / or recompiling the same one that can handle the MSAA sample count being used (or no MSAA).

With Compute Jobs it's easy because shaders go through the Hlms and you can ask the Hlms whether this is an MSAA texture, and how many samples are required (honestly IMO that is awesome, but my opinion is obviously biased :P ). If MSAA count changes, the shader gets recompiled
However low level materials didn't get that feature yet, so you have to get that info and recompile yourself.
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

Hello everyone! I made research about real HBAO and I decided to continue with this hemisphere SSAO because otherwise I would need to rewrite whole system from scrath. Good news are that I was managed to fix those artifacts while running on DirectX :) Many hours I tried to figure out what the heck is wrong with the shader and then I noticed that HLSL mul function makes difference if parameters are in different order... I changed this line: float3 oSample = mul(TBN, sNoise) to this: float3 oSample = mul(sNoise, TBN) and voila, no artifacts anymore :D Another bug was that I normalized sample vector in the shader and that caused samples to be taken always at the same distance. Now occlusion is much more smoother.

Result looks like this: (note, it is rendered as half resolution so image is not that sharp as earlier)
Image

Next, I will take a look of FSAA issue and write better blur shader that uses depth. In NVIDIA slides was said that blur should be done in full resolution to prevent screen edge area artifacts.

EDIT: I implemented a better blur using vertical and horizontal gaussian pass and comparing depths. The result is much much more better now.

Image
Last edited by SamiTheGreat on Mon Jun 11, 2018 10:06 am, edited 3 times in total.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

holy poop that's amazing!!
you should disable Vsync to see the actual fps and how every filter affect performance
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [WIP] HB ambient occlusion for Ogre

Post by dark_sylinc »

Holy SSAO that looks great!
zxz
Gremlin
Posts: 184
Joined: Sat Apr 16, 2016 9:25 pm
x 19

Re: [WIP] HB ambient occlusion for Ogre

Post by zxz »

Looking much better!

I am curious what difference there is between your approach and "proper" HBAO, when it comes to quality, performance, or any other interesting metric.

Edit: And if it's not a hassle, it would be sweet if you would push the changes to your bitbucket repo, so that we can try it out as well.
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

zxz wrote:Looking much better!

I am curious what difference there is between your approach and "proper" HBAO, when it comes to quality, performance, or any other interesting metric.

Edit: And if it's not a hassle, it would be sweet if you would push the changes to your bitbucket repo, so that we can try it out as well.
"Proper" HBAO is made by rotating sample kernel and finding horizon (the highest tangent angle) and comparing fragment's normal tangent and horizon tangent. You will get better results in HBAO with lower samples than in SSAO. However calculating tangents and finding horizon takes extra time. In original SSAO you just cast ray samples around spherical sample kernel and check if sample occludes the fragment. In this case, I use hemispherical sample kernel pointing to fragment's normal direction so samples are never taken "inside of object" to prevent self occlusion.

I made performance test using RenderDoc to see timings.

Code: Select all

NVIDIA GTX 580
DEBUG, FULL HD (1920x1080) windowed, half resolution SSAO, full resolution blur, 64 SSAO samples

Frametime 6.52 ms

Scene render 0.78938 ms

SSAO 4.095 ms
BlurH 0.7225 ms
BlurV 0.7224 ms
Apply 0.157 ms

AO SUM: 5.6969 ms (0.0056969 s)

FPS: 153,3 frames per second
As you can see, SSAO takes highest amount of time to calculate. I think it can be optimized more to get better results.

I will not push this version yet because I have to write the new blur shader for OpenGL also. In addition, shader code need to be clened up because there is alot of mess because of my experiments :D
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

Hi! The newest version is now available and I've pushed it to my fork. FSAA support is not included since it would have made code too messy. Enabling it should be easy. Just add quad pass before SSAO using shaders that dark_sylinc provided earlier to downsample depth before using it in SSAO (or better, make a new compositing node to render scene and give output to downsample node and then pass result to ssao node). I also made little modifications to blur shader to increase its performance and cleaned up all shader code.

I hope that you guys like it! :D

EDIT: I can make another version using FSAA and share it via zip file here if you need it. FSAA support is a feature that we need so I will code it anyway.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

=D! I am going to try this later
btw, theres a typo in the tutorial explanation (Tutorial_SSAO.cpp) "horizontal based amibent occlusion" and I think you mean Horizon, no Horizontal (??? or are the same???)
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

xrgo wrote:=D! I am going to try this later
btw, theres a typo in the tutorial explanation (Tutorial_SSAO.cpp) "horizontal based amibent occlusion" and I think you mean Horizon, no Horizontal (??? or are the same???)
Yeah, it should be horizon if it was "real" horizon based ao :D I forgot to rewrite explanation.. I will fix that. BTW I renamed this AO to HSAO (hemisphere ambient occlusion) since it describes it better.
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

Hi! I wanted to ask what is the state of merge progress? It appears that this hasn't been merged yet to Ogre 2.1 so far. I am currenly integrating my SSAO for our game engine and I remembered that dark_sylinc had some performance fix earlier to fix some depth buffer issues (that FPS drop when zooming close to the objects). If you don't have time to check this out, I can try to fix the issue for the newest version if you could send me some more information about the issue.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [WIP] HB ambient occlusion for Ogre

Post by dark_sylinc »

So it's ready to be merged by your standards? I was waiting for you to tell me to take a new look.

Right now I'm extremely busy (contract work + Metal), so I think it may be quite a while until I can take a look at your SSAO again (think ~7 weekends). If suddenly I become more available I may be able to take a look earlier. I really want to push this into main repo, subjectively speaking looks really good.

Cheers
Matias
User avatar
GlowingPotato
Goblin
Posts: 211
Joined: Wed May 08, 2013 2:58 pm
x 10

Re: [WIP] HB ambient occlusion for Ogre

Post by GlowingPotato »

I can say that we are using your AO code and its working flawless.

It does have bugs when using with FSAA, but since we are using FXAA 3.1, this is not an issue for us.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [WIP] HB ambient occlusion for Ogre

Post by dark_sylinc »

I'm just here to tell you I'm integrating your code. Done some performance improvements.

Turns out your demo uncovered a bug!

I was puzzled by this:

Code: Select all

float fDepth = texture( depthTexture, uv*2.0).x; //multiply uv coords by 2 because we are working with half res
It made no sense to multiply by 2.0; it shouldn't have been there (D3D doesn't need it). Turns out "depth_copy" pass was affecting the GL Viewport state, without restoring it; thus causing a bug which you could counter by multiplying by 2.0.
But still GL & D3D diverged a little.

Now that the bug is fixed the 2.0 isn't needed anymore, and OpenGL version looks the same as D3D.
User avatar
SamiTheGreat
Bronze Sponsor
Bronze Sponsor
Posts: 102
Joined: Sat Aug 30, 2008 11:57 am
Location: Finland
x 8

Re: [WIP] HB ambient occlusion for Ogre

Post by SamiTheGreat »

dark_sylinc wrote:I'm just here to tell you I'm integrating your code. Done some performance improvements.

Turns out your demo uncovered a bug!

I was puzzled by this:

Code: Select all

float fDepth = texture( depthTexture, uv*2.0).x; //multiply uv coords by 2 because we are working with half res
It made no sense to multiply by 2.0; it shouldn't have been there (D3D doesn't need it). Turns out "depth_copy" pass was affecting the GL Viewport state, without restoring it; thus causing a bug which you could counter by multiplying by 2.0.
But still GL & D3D diverged a little.

Now that the bug is fixed the 2.0 isn't needed anymore, and OpenGL version looks the same as D3D.
Thanks for the bug fixes and optimization! Giving sample vector as uniform inputs is indeed better solution since sampling the texture is not needed anymore. I got also one optimization idea for blur shaders. Depth could be linearized with projectionParams to temp texture so we don't need to do it two times (now it calculates it in both vertical and horizontal blur). I am not sure if it worth since it is tradeoff between performance and memory.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

Hello! I tried to use this SSAO in my project but I get this glitches:
Image
I am using it as is, just copied all the files and using the same workspace as the sample, and included the lines that creates the kernel samples and noise texture.
maybe someone recognize the error?
Thanks!
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [WIP] HB ambient occlusion for Ogre

Post by dark_sylinc »

Could be that your depth buffer contains garbage (maybe depth sharing ended up using the depth buffer for something unrelated in the middle, destroying its contents).
Could be that something (i.e. uniform parameters) expects the depth buffer to be in a different resolution.
Could be sampler units not being correctly initialized (thus everything is reading from the same tex unit).
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

The problem appears in the SSAO/HS material, the input textures seems correct, depth looksgood and noise texture too (but seems strange to me that it only uses a 2x2 texture).
Then I noticed that I was lacking "psParams->setNamedConstant("projection", mainCamera->getProjectionMatrix());" that in the example is in the "update" method, I put it in the framrenderingqueue and now the output of SSAO/HS looks like this:

Image
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: [WIP] HB ambient occlusion for Ogre

Post by xrgo »

solved, the problem was this part:

Code: Select all

        psParams->setNamedConstant( "noiseScale", Ogre::Vector2(
                                ( mGraphicsSystem->getRenderWindow()->getWidth() * 0.5f ) / 2.0f,
                                ( mGraphicsSystem->getRenderWindow()->getHeight() * 0.5f ) / 2.0f ) );
since I am running inside a qt window, for some reason it was giving the wrong width and height

Thanks for this feature, its awesome!!
Post Reply