Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (739)
Games in Android Showcase (224)
games submitted by our members
Games in WIP (820)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  SSAO not working as expected (SOLVED)  (Read 3221 times)
0 Members and 1 Guest are viewing this topic.
Offline ShadedVertex
« Posted 2016-09-03 07:28:15 »

Hey, guys!

I tried to implement SSAO yesterday and I thought it was working, but then I realized it wasn't Sad

Basically what's happening is that as the camera moves away from the object, the object begins to fade to white, but when I move closer, the object gets darker and darker.

I think I know what the problem is. Basically, when I move closer, the depth values of the fragments decrease, so it gets darker. But when I move further away, the depth values of the fragments increase, so it appears to be whiter. But that isn't how SSAO is supposed to work.

Here are some pics:

https://anuj-rao.tinytake.com/sf/OTUxMzkyXzM5ODk2OTM

^When the camera is close to the Stanford dragon model

https://anuj-rao.tinytake.com/sf/OTUxMzkzXzM5ODk2OTQ

^When the camera moves away from the Standford dragon model

You see, it doesn't look right. Also, the corners are lighter than the actual surfaces??!!!

It looks all wrong!

Here's my SSAO fragment shader:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
#version 400 core

in vec2 passTextureCoords;

out vec4 fragColour;

uniform sampler2D gPositionDepth;
uniform sampler2D gNormals;
uniform sampler2D noiseTexture;

uniform vec3 samples[16];
uniform mat4 projMatrix;

const vec2 noiseScale = vec2(1280/4, 780/4);

void main(void){
   int kernelSize = 16;
   float radius = 1;  

   vec3 fragPos = texture(gPositionDepth, passTextureCoords).xyz;
   vec3 normal = texture(gNormals, passTextureCoords).xyz;
   vec3 randomVec = texture(noiseTexture, passTextureCoords * noiseScale).xyz;
   
   normal = normalize(normal);
   vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
   vec3 bitangent = normalize(cross(normal, tangent));
   mat3 TBN = mat3(tangent, bitangent, normal);
   
   float occlusion = 0;
   for(int i = 0; i < kernelSize; i++){
      vec3 samp = TBN * samples[i];
      samp = fragPos + samp * radius;
     
      vec4 offset = vec4(samp, 1);
      offset = projMatrix * offset;
      offset.xyz /= offset.w;
      offset.xyz = offset.xyz * 0.5 + 0.5;
     
      float sampleDepth = texture(gPositionDepth, offset.xy).w;
      float rangeCheck = smoothstep(0, 1, radius / abs(fragPos.z - sampleDepth));      
      occlusion += (sampleDepth >= samp.z ? 1 : 0) * rangeCheck;
   }
   
   occlusion = 1 - (occlusion/16);
   fragColour = vec4(vec3(pow(occlusion, 8)), 1);
}


G-buffer vertex shader:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
#version 400 core

in vec3 positions;
in vec4 colour;
in vec3 normals;

out vec4 passColour;
out vec3 fragPos;
out vec3 passNormals;

uniform mat4 transMatrix;
uniform mat4 projMatrix;
uniform mat4 viewMatrix;

void main(void){
   gl_Position = projMatrix * viewMatrix * transMatrix * vec4(positions, 1.0);
   passColour = colour;
    passNormals = (viewMatrix * transMatrix * vec4(normals, 0)).xyz;
   fragPos = (viewMatrix * transMatrix * vec4(positions, 1.0)).xyz;
}


G-buffer fragment shader:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
#version 400 core

in vec4 passColour;
in vec3 fragPos;
in vec3 passNormals;

layout (location = 0) out vec4 gPositionDepth;
layout (location = 1) out vec4 gNormals;
layout (location = 2) out vec4 gAlbedoSpec;

const float NEAR = 0.01f;
const float FAR = 1000;
float linearizeDepth(float depth)
{
    float z = depth * 2.0 - 1.0;
    return (2.0 * NEAR * FAR) / (FAR + NEAR - z * (FAR - NEAR));  
}

void main(void){
   gPositionDepth.rgb = fragPos;
   gPositionDepth.a = linearizeDepth(gl_FragCoord.z);
   gNormals = vec4(normalize(passNormals), 1);
   gAlbedoSpec = passColour;
}


And finally, here's how I generate the hemispherical sample kernel and the random rotation vectors:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
package renderer;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL30;

import util.MathUtils;

public class SSAO {
   
   public static List<Vector3f> getSSAOKernel(){
      List<Vector3f> kernel = new ArrayList<Vector3f>();
      for(int i = 0; i < 16; i++){
         Vector3f sample = new Vector3f(((float)Math.random()) * 2 - 1, ((float)Math.random()) * 2 - 1, ((float)Math.random()));
         sample.normalize();
         sample.mul(((float)Math.random()));
         float scale = 1f/16f;
         scale = MathUtils.lerp(0.1f, 1f, scale * scale);
         sample.mul(scale);
         kernel.add(sample);
      }
      return kernel;
   }
   
   public static int createSSAONoiseTexture(){
      List<Vector3f> ssaoNoise = new ArrayList<Vector3f>();
      for(int i = 0; i < 16; i++){
         Vector3f noise = new Vector3f(((float)Math.random()) * 2 - 1, ((float)Math.random()) * 2 - 1, 0);
         noise.normalize();
         ssaoNoise.add(noise);
      }
      int noisetexture = GL11.glGenTextures();
      Loader.TEXTURE_LIST.add(noisetexture);
      FloatBuffer buffer = BufferUtils.createFloatBuffer(ssaoNoise.size() * 3);
      for(Vector3f v : ssaoNoise){
         buffer.put(v.x);
         buffer.put(v.y);
         buffer.put(v.z);
      }
      buffer.flip();
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, noisetexture);
      GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL30.GL_RGB16F, 4, 4, 0, GL11.GL_RGB, GL11.GL_FLOAT, buffer);
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
      GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
      GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
      return noisetexture;
   }

}


I'm following the tutorial from learnopengl.com

A little help would really be appreciated. I've already scoured the Internet for answers and I can't think of any myself. Thanks Smiley
Offline orange451

JGO Kernel


Medals: 344
Projects: 6
Exp: 6 years


Your face. Your ass. What's the difference?


« Reply #1 - Posted 2016-09-03 23:02:00 »

Have you debugged your GBuffer to make sure it's correct?
Show some pictures. Including your linearized depth buffer.

I've written at least 4-5 SSAO implementations so far, hopefully I can help! Smiley

First Recon. A java made online first person shooter!
Offline ShadedVertex
« Reply #2 - Posted 2016-09-04 01:04:26 »

orange451:

here's the vertex position texture (in view space):

https://anuj-rao.tinytake.com/sf/OTUxODQyXzM5OTI1MTM

here's the normal texture (also in view space):

https://anuj-rao.tinytake.com/sf/OTUxODQ4XzM5OTI1Mjk

And here's the linearized depth texture:

https://anuj-rao.tinytake.com/sf/OTUxODU2XzM5OTI1Mzc

The linearized depth values look completely white, but when I move really close to the model, it gets darker and turns almost black.

Here's my linearization formula:

(2.0 * NEAR * FAR) / (FAR + NEAR - z * (FAR - NEAR))

The z value is in normalized device coordinates.

Thanks Smiley
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ShadedVertex
« Reply #3 - Posted 2016-09-04 04:11:02 »

Fixed it. I changed

1  
sampleDepth = -texture(gPositionDepth, offset.xy).w;


to

1  
sampleDepth = texture(gPositionDepth, offset.xy).z;


Results:

https://anuj-rao.tinytake.com/sf/OTUyMDM1XzM5OTMwNzE

Yay Smiley
Offline orange451

JGO Kernel


Medals: 344
Projects: 6
Exp: 6 years


Your face. Your ass. What's the difference?


« Reply #4 - Posted 2016-09-05 05:00:02 »

Glad you got it working! Smiley

First Recon. A java made online first person shooter!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 
Ecumene (49 views)
2017-09-30 02:57:34

theagentd (74 views)
2017-09-26 18:23:31

cybrmynd (183 views)
2017-08-02 12:28:51

cybrmynd (181 views)
2017-08-02 12:19:43

cybrmynd (188 views)
2017-08-02 12:18:09

Sralse (195 views)
2017-07-25 17:13:48

Archive (745 views)
2017-04-27 17:45:51

buddyBro (878 views)
2017-04-05 03:38:00

CopyableCougar4 (1428 views)
2017-03-24 15:39:42

theagentd (1317 views)
2017-03-24 15:32:08
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!