#SSAO Moving

354 messages · Page 1 of 1 (latest)

regal perch
#

My ssao is having this weird issue up-close where the ao moves around with the camera.
Any ideas what i should check to figure out what could be causing this?

#

or it might just be an unavoidable issue from it being screen-space idk

shrewd jetty
#

This looks many levels of wrong. What AO technique are you using?

regal perch
#

i just sample random positions in a hemsiphere (using depth and normal textures)

#

wdym by "many levels of wrong" tho

#

as far as i can tell the only issue is the effect moving around when up-close (and the edges of the screen not having correct ao but thats to be expected)

shrewd jetty
#

Alright, so imma warn you against doing that. It’s simple but looks bad, figure out horizons.

How do you reconstruct position from depth?

regal perch
#

also i have heard of horizon based ssao but it doesnt look any better to me

#

maybe im just not looking at the right comparisons tho

shrewd jetty
#

It looks much better. I don’t think your average joe can’t tell, though.

#

Hmm, right. In my time I’ve just did clip, depth remap and multiply xy etc etc, without inverting stuff.

#

I’d try that

#

Gimme a sec, imma get you a snippet

regal perch
shrewd jetty
#

Yeah, it’s just perspective though, correct?

regal perch
#

yeah

shrewd jetty
#

Can avoid that

regal perch
#

oh are you meaning like dont use the projection matrix at all?

shrewd jetty
#

Just as a test

regal perch
#

hm if i dont use the projection matrix than there just no ao appearing at all

shrewd jetty
#
float3 getViewPos(float2 uv, float z) {
    float fin_z = remap(z, 0., 1., n, f);
    float2 norm = (uv - 0.5.xx) * 2.0;
    float fl = 2.0 * tan(FOV * 0.5);
    
    float3 pos = float3(norm * fl * fin_z, fin_z);
    pos.y *= rcp(BUFFER_ASPECT_RATIO);
    
    return pos;
}```

n is nearplane, f is farplane, fl is focal length
#

you'll need to reverse it, though

#

i seem to have misplaced the inversion, but you can figure it out yourself

regal perch
#

ngl ive got no idea what that is doin

#

i dont think anything is wrong with my current reconstruction tho

shrewd jetty
#

well, okay, what rng are you using

regal perch
#

i use the randomVec for offset and randomFloat for radius (which now that i think about it is redundant)

const vec3 SSAO_NOISE[16] = vec3[](
    vec3( 0.7071,  0.7071, 0.0), vec3(-0.3827,  0.9239, 0.0), vec3( 0.9808, -0.1951, 0.0), vec3(-0.8315, -0.5556, 0.0),
    vec3( 0.1951, -0.9808, 0.0), vec3( 0.9239,  0.3827, 0.0), vec3(-0.5556,  0.8315, 0.0), vec3(-0.9808,  0.1951, 0.0),
    vec3( 0.3827, -0.9239, 0.0), vec3( 0.8315,  0.5556, 0.0), vec3(-0.7071, -0.7071, 0.0), vec3(-0.1951,  0.9808, 0.0),
    vec3( 0.5556, -0.8315, 0.0), vec3( 0.9808,  0.1951, 0.0), vec3(-0.3827, -0.9239, 0.0), vec3(-0.9239, -0.3827, 0.0));
vec3 randomVec() {
    int x = int(mod(gl_FragCoord.x, 4.0));
    int y = int(mod(gl_FragCoord.y, 4.0));
    return SSAO_NOISE[x * 4 + y];
}
float randomFloat(int y) {
    int x = int(mod(gl_FragCoord.x, 4.0));
    return SSAO_NOISE[x * 4 + y].x;
}
shrewd jetty
#

boi

regal perch
#

?

shrewd jetty
#

just use this for now

#

because its quite likely you're looking at correlations that appear because of

#

well

#

mod()

#

on coords

#

oh, and also, random inside sphere, right

#

hmm

regal perch
#

ok so i get a random vector to use as the direction

#

multiply it by the random float used as radius

#

and i use the normal to make sure it is a hemisphere

shrewd jetty
#

random vector is not the same as random direction

regal perch
#

how so?

shrewd jetty
#

imagine a cube

#

that's where the random vector lies

#

now smooth it out

#

you'll be cutting away at the corners, while the faces will sort of remain remain

#

that's my best intuitive explanation

#

also, not what you need

regal perch
#

yeah idk what you mean by any of that

shrewd jetty
#

also, you're not picking a random direction

#

unless you're not doing crytek ao

regal perch
#

idk what crytek is so i probably aint doin that

shrewd jetty
#

you're picking a random point in the volume

shrewd jetty
regal perch
#

tbh i dont remember, i made this like a month ago

#

i think i used multiple guides tho

shrewd jetty
#

rn it seems to me youre trying to make de-assified crytek ao

#

which is the simplest

regal perch
#

i do see a pattern

#

so yeah its probably wrong

shrewd jetty
#

yeah it's bad

#

ok, use the hashes from the link

regal perch
#

ok

shrewd jetty
#

only for testing, replace with something else later

#

do AO debug view, output just the AO

regal perch
#

im confused about the hashing

#

one of the methods wants a vec2 and outputs just one float

#

the other wants a vec3 and outputs a vec3

#

i do want a vec3 but idk what i would input for the third number

#

depth maybe?

#

they are using time in the example

#

but i dont think i want the ao moving over time

shrewd jetty
#

not depth

#

it can be constant

#

just 1.0

regal perch
#

ah

#

yeah this looks much more random

shrewd jetty
#

discord agrees

#

use that for now

#

also AO buffer!!

regal perch
#

alright

#

looks about the same to me

#

still has the moving around problem up-close too

shrewd jetty
#

hm

#

so first off, you want points in a sphere

#

a simple (but not efficient on GPU) method is to just reroll the RNG until length < 1

regal perch
#

and why would i want the points in a sphere instead of hemisphere?

regal perch
#

i made it show red if any channel is greater than 1 and green if its not

regal perch
shrewd jetty
#

Length(rng)

#

Or better yet, dot(rng,rng) for that one extra bit of speed

regal perch
#

for what

#

idk where you want me to put length(rng)

shrewd jetty
#

Ok, what I’m saying is that your random numbers need to be in a sphere with radius one in accordance with crytek ao

#

Just because each individual component of a vector is < 1, doesn’t mean the vectors length has to be < 1

regal perch
#

ohhh

shrewd jetty
#

Imagine a vector (0,1,1)

#

That’s length sqrt(2), a bit over 1.41

regal perch
#

why does the length matter tho i dont currently get the length anywhere

shrewd jetty
#

Ok so at the corner of the block, right?

#

There’s a sharp 90 degree angle

#

That should dissapear

#

(I think at least)

regal perch
#

ohhh i see

shrewd jetty
#

But overall, that’s what the technique requires

regal perch
#

couldnt i just do hash = hash/length(hash)

#

to avoid the >1 length
apparently that doesnt work like i thought it would, still has some greater than 1 lengths

shrewd jetty
#

You can, but your samples will just be non-uniformly distributed on the surface of a sphere

#

They need to be (at least for the most part), uniform and inside the sphere

regal perch
#

i could just divide the result by 1.5 or smth

#

whatever the max possible length is (1,1,1)

#

1.732

shrewd jetty
#

What is it with people and bandaiding shit

#

Yes, you can

regal perch
#

bandaid?

shrewd jetty
#

However, you can a smaller cube

regal perch
#

its reducing it to the right range

shrewd jetty
#

Which is, for the exact same reasons, not what you want

regal perch
#

its not?

#

i dont understand why

shrewd jetty
#

You need this.

#

As for why, see if drawing it can help

#

Same shit in 2D

#

Or just plt that shit, because numeric experiments are based

regal perch
#

plt?

shrewd jetty
#

Matplotlib

#

Python library that lets you easily plot data

regal perch
#

i mean the dividing by 1.732 seems to work

shrewd jetty
#

You can just, run that calculation and visually see the clumping near the corners

regal perch
#

although none of this affects the up-close moving around issue

#

also smth i noticed is the hashing made the ao noisy

shrewd jetty
shrewd jetty
#

But before, you had 16 or so predetermined values which caused banding instead

regal perch
#

ohh

#

i still have the banding

#

its just also noisy

shrewd jetty
#

I see no bands here tbh

#

Oh nvm

#

You’re not slicing the array with those values, right?

#

Just using them directly?

regal perch
#

im just using them directly

shrewd jetty
#

Guh

regal perch
#

maybe the kernel is causing it idk

shrewd jetty
#

Probably just looking at the wrong distribution

#

Yes, the kernel is wrong

regal perch
#
vec3 SSAO_KERNEL[32] = vec3[](vec3( 0.021,  0.183,  0.512), vec3( 0.392,  0.041,  0.734), vec3(-0.221,  0.114,  0.612), vec3( 0.134, -0.287,  0.553), vec3(-0.341, -0.102,  0.487), vec3( 0.287,  0.331,  0.682), vec3(-0.129,  0.412,  0.731), vec3( 0.512, -0.221,  0.612), vec3(-0.412, -0.331,  0.682), vec3( 0.221,  0.129,  0.341), vec3(-0.183, -0.021,  0.512), vec3( 0.331, -0.412,  0.731), vec3(-0.041,  0.392,  0.734), vec3( 0.102, -0.341,  0.487), vec3(-0.287,  0.134,  0.553), vec3( 0.412,  0.287,  0.612), vec3(-0.512, -0.183,  0.512), vec3( 0.341, -0.102,  0.487), vec3(-0.129,  0.221,  0.341), vec3( 0.183,  0.412,  0.731), vec3(-0.392,  0.041,  0.734), vec3( 0.102, -0.512,  0.612), vec3(-0.221, -0.392,  0.682), vec3( 0.331,  0.129,  0.341), vec3(-0.041, -0.183,  0.512), vec3( 0.287, -0.412,  0.731), vec3(-0.134,  0.341,  0.487), vec3( 0.412, -0.287,  0.612), vec3(-0.512,  0.183,  0.512), vec3( 0.341,  0.102,  0.487), vec3(-0.129, -0.221,  0.341), vec3( 0.183, -0.412,  0.731));
for (int i = 0; i < KERNEL_SIZE; i++) {
  vec3 sampleVec = TBN * SSAO_KERNEL[i];

hmm

shrewd jetty
#

Ok so

regal perch
#

maybe i should use the random number instead of a kernel?

shrewd jetty
#

If you have tabulated values that are guaranteed correct inside of a sphere, you can roll with those

#

Though I’m a stickler for actually generating white noise until you run into quality issues with it

#

But when shit doesn’t look correct, getting it to the most minimal point is the right move

regal perch
#

yeah using a random number instead of a kernel got rid of the banding

#

its even more noisy now tho

#

and less stable

shrewd jetty
#

Yes! But more debugfavle

#

So, first off, the hash does fract()

#

So it returns a value from 0-1

regal perch
#

right

shrewd jetty
#

So just -0.5.xxx that shit

regal perch
#

oh yeah true i forgot i need -1 to 1 not 0 to 1

shrewd jetty
#

It just needs to be symmetrical around 0, you can skip the *2, that’s just radius for now

regal perch
#

ooh that actually looks super good if you ignore the noise

#

theres highlights on edges

shrewd jetty
#

Which is very wrong

regal perch
#

but looks good

shrewd jetty
#

But, the hemisphere check is supposed to fix that

regal perch
#

yeah odd that it isnt

shrewd jetty
#

I like it myself

#

Though there are probably cheaper ways to achieve it

#

Also, I think it’s still asymmetrical

#

You remapped all components of the vector, right?

regal perch
#

asymmetry would explain the issue with the moving around up close

#

wdym by remapped

shrewd jetty
#

As in -.5

#

You need to do that for every component

#

Or just -0.5.xxx the entire thing

regal perch
#

yeah:

vec3 hash(){
    vec3 p = vec3(uv.xy, 1);
    p = vec3(dot(p, vec3(127.1,311.7, 74.7)), dot(p, vec3(269.5,183.3,246.1)), dot(p, vec3(113.5,271.9,124.6)));
    return (fract(sin(p)*43758.5453123)-0.5f)*2;
}
shrewd jetty
#

Add the .xxx swizzle so that I may sleep tonight

regal perch
#

lol ok

shrewd jetty
#

Idk the default behavior for glsl

regal perch
#

it multiplies all components

#

but im confused on what you mean by .xxx

#

where do i put it, never seen that before

shrewd jetty
#

Yeah, though scalar + vector is technically undefined in a mathematical sense

shrewd jetty
regal perch
#

ok i put the .xxx

#

didnt change anything visually

#

i'll just keep it there tho

shrewd jetty
#

Ok, good. Explicit is better then implicit (to a point bleakekw)

regal perch
#

looks like it is asymmetry yeah

shrewd jetty
#

Yeah

#

So

#

That’s the box random numbers showing themselves

regal perch
#

which one of the solutions there should i do

#

i could just do the last one it looks pretty uniform

shrewd jetty
#

Whatever is the simplest

#

Last one is good

#

Avoid the first one, its probably really bad for GPU or something

regal perch
#

oof the last one isnt possible

#

it uses Math.random

#

i think they all do actually

shrewd jetty
#

Fam

regal perch
#

maybe i could re-use the hashing for that instead

shrewd jetty
regal perch
shrewd jetty
#

Yeah

#

So what you need is the information on where the numbers are

#

They’re probably 0-1

#

So you can just reuse the hash

regal perch
shrewd jetty
#

Remove the .5.xxx and *2 though

shrewd jetty
regal perch
#

where what numbers are tho

shrewd jetty
#

So scroll down (or don’t, I already told you what to do)

#

And look at the range

regal perch
#

range of what??

shrewd jetty
#

The rng

regal perch
#

idk what you are talking about

#

i cant use javascript methods in glsl

shrewd jetty
#

Yes, you use a hash

regal perch
#

right

shrewd jetty
#

But you need to match up the example code and GLSL

regal perch
#

ohhh

#

yeah i see what you mean

shrewd jetty
#

And just to be sure, you should check what Math.random() does

regal perch
#

i need to figure out what range javascript's Math.random() returns

shrewd jetty
#

Genau

regal perch
#

yeah its the same as the hash perfect

shrewd jetty
#

Yep

#

Don’t forget you’ve modified it

regal perch
#

yeah i undid the +0.5 and /2 thing

#

also do you know what the x:x, y:y, z:z from the example means?

#

is that some kind of bitwise operation

#

idk

#

x:x aint valid in glsl

#

maybe its just a weird way to make a vec3 in some other language idk

shrewd jetty
#

That’s iirc just shorthand init of a class that contains x,y,z

regal perch
#

ah

#

and ofc glsl has no method to get the cube root

shrewd jetty
#

Heard of jsons? Ofc you did, you probably had the fun of fucking around with them because modding.

regal perch
#

yeah

shrewd jetty
regal perch
#

arent those two different operations?

#

i could look into how cubic roots are calculated and recreate that method maybe

shrewd jetty
#

Elementary school level math

regal perch
#

bro they dont teach cubic roots at any stage of education

#

maybe in college actually

#

but yeah not in normal schools

shrewd jetty
#

A root is just a non-whole power

#

Just uhh

#

Pow(…,1./3.)

#

Wonder if that has edge cases in negative numbers…

regal perch
#

i googled it and it said smth like that

#

also need to abs it if theres negatives

shrewd jetty
#

Ah, it’s UB

regal perch
#

but i aint got negatives from the hash anyways

#

so should be able to just do pow(hash.z, 0.333333333f);

shrewd jetty
regal perch
#

whats the point in sign if its always 1

shrewd jetty
#

You’d

#

Not should, mb

regal perch
#

ah

shrewd jetty
#

Yep, all nice and defined here

regal perch
#

implementing the last example from that website doesnt change the results noticably

#

maybe the issue is that randomVec is the same every time i call it from one pixel

shrewd jetty
#

Yeah, it is

#

But show pls

regal perch
#
float getAO(float depth, vec3 normal) {
    vec3 posVS = reconstructViewPos(uv.xy, depth);
    vec3 normalVS = normalize((globalUbo.view * vec4(normal.xyz, 0.f)).xyz);
    vec3 randVec = randomVec();
    vec3 tangent = normalize(randVec - normalVS * dot(randVec, normalVS));
    vec3 bitangent = cross(normalVS, tangent);
    mat3 TBN = mat3(tangent, bitangent, normalVS);
    float occlusion = 0.f;
    for (int i = 0; i < KERNEL_SIZE; i++) {
        vec3 sampleVec = TBN * randomVec();//SSAO_KERNEL[i];
shrewd jetty
#

ok

#

sampleVec, where is it used?

#

Also, show debug pic

regal perch
#
sampleVec = posVS + sampleVec * radius;
vec4 offset = globalUbo.proj * vec4(sampleVec, 1.0);
offset.xyz /= offset.w;
vec2 sampleUV = (offset.xy*0.5)+0.5;
if (!(sampleUV.x < 0 || sampleUV.x > 1 || sampleUV.y < 0 || sampleUV.y > 1)) {
    vec3 sampleVS = reconstructViewPos(sampleUV, texture(ddaDepth, sampleUV).r);
    float rangeCheck = smoothstep(0.f, 1.f, (radius/AO_STRENGTH)/length(sampleVS-posVS));
    vec3 viewDirVS = normalize(posVS);
    bool occluded = sampleVS.z <= sampleVec.z-0.05f;
    occlusion += (occluded ? 1.f : 0.f) * rangeCheck * AO_STRENGTH;
}
#

radius is just 1

shrewd jetty
#

Any reason why you TBN* it?

regal perch
#

for the hemisphere

shrewd jetty
#

Don’t for now

#

Also thats wrong I believe

#

Plus you said you liked the outlines 😛

regal perch
#

if i dont tbn it then it gets very broken

shrewd jetty
#

So it’s not hemisphere then

regal perch
#

yeah i get the outlines with the tbn lol

#

well it was hemisphere

#

with the old random method

shrewd jetty
#

That’s just because the points were distributed as such

shrewd jetty
#

Radius

#

Has to be the radius, riight?

regal perch
#

radius is just 1

regal perch
#

it wasnt caused by removing the tbn

#

it was from me making the randomvec inputs different in the loop

#

this is without tbn

#

and yeah its perfectly stable now

#

no asymmetry

shrewd jetty
#

Looks correct

#

Now, the original “motion” issue

regal perch
#

the asymmetry was the motion issue

#

its gone now

shrewd jetty
#

Neat!

regal perch
#

and the blur should get rid of the noise

#

once i add blur

#

so i think its working good

shrewd jetty
#

Well, it’s a lot of noise

regal perch
#

true

shrewd jetty
#

The best way to get rid of noise is to not create it

regal perch
#

ah like by going back to the kernel? (nvm that breaks everything)

shrewd jetty
#

In other words, steal a GTAO impl

#

It’s lower integration dimensionality will make your life way easier

regal perch
#

i'll google what that is

#

oof is it actually 3-6x more expensive than ssao?

shrewd jetty
#

… as for noise reduction

  • Don’t blur, use a basic À-Trous with a few passes
  • Temporal accumulation is really good for quality, but is difficult to get perfect
  • avoid white noise and hashes. they’re really good to debug, but ass for production. See blue noise. It’s also easier to do so with GTAO.
shrewd jetty
#

Pretty much, it’s worth it, imo

#

I’ll also tell you to avoid bitmasking for the time being, it’s cool but much more difficult and is missing the ground truth of GTAO if used as-is

regal perch
#

i dont think im doin any bitmasking

shrewd jetty
#

Yeah

#

Stick with barebones GTAO

regal perch
#

is it a good idea to change the randomVec in my loop to be different from the one outside of it?
randomVec(uv.xy+(i/100))

#

like by using the iteration

shrewd jetty
#

Every time you need a new random number it should be unique and ideally uncorrelated to an extent. That’s why .nextRandom() is a thing in rng patterns.

#

Don’t uv+something, use an rng with extra inputs

regal perch
#

what inputs tho

shrewd jetty
#

UV, index, optionally time

#

3 or 4

regal perch
#

index is what i was just using tho

shrewd jetty
#

ah

#

What’s the issue then?

regal perch
#

or wait i see what you mean

#

i shouldnt add the index to the uv

#

i should make the 3rd parameter in the vec3 the hash uses

shrewd jetty
#

Exactly

#

Should once again avoid correlations, which is usually good

#

Anyhow, imma log off for now. You should probably shoot me a dm or something if you need me.

regal perch
#

alright

#

thanks for the help

regal perch
#

i cant find anything good for how to implement gtao

#

so i think maybe i'll just add taa and hope it hides the noise

#

(also tried using blue noise but it brought back banding and asymetry / ao moving around up-close)

shrewd jetty