opengl - SSAO incorrect at z = 0 and at distance -


so tried implement ssao, not working intended. seems split @ position z=0 (worldspace), there white line @ position z=0. occlusion there doesn't right.

enter image description here

plus @ greater distance, when moving camera, occlusion becomes weirder enter image description here

my shader render geometry (instanciated):

vertex:

#version 330 core   layout(location = 0) in vec3 vertexposition;  layout(location = 1) in vec2 vertexuv;  layout(location = 2) in vec3 vertexcolor;  layout(location = 3) in vec3 vertexnormal;  layout(location = 4) in mat4 offset;  layout(location = 8) in vec4 instancecolor;  uniform mat4 projection; uniform mat4 view;  out vec2 uv; out vec4 color; out vec3 normal;  void main() {          mat4 model = offset;     mat4 mvp = projection * view * model;    vec4 pos = mvp * vec4(endpos,1);  gl_position = pos;  uv = vertexuv;  color = instancecolor;     normal = normalize((model * vec4(vertexnormal,0)).xyz);  } 

fragment:

    #version 330 core      in vec2 uv;     in vec4 color;     in vec3 normal;      uniform sampler2d diffuse;  void main() {     gl_fragdata[0] = vec4(color);     gl_fragdata[1] = (vec4(normal,1)+1)/2; } 

after geometry pass, apply ssao pass normal , depth information.

this noisetexture: enter image description here

i use hardware depth buffer. calculate in world space.

here fragment shader:

    #version 330 core  #define kernel_size 16 uniform sampler2d normalmap; uniform sampler2d depthmap; uniform sampler2d noisetexture; uniform vec2 noisescale;  uniform vec2 resolution;  uniform mat4 invertviewprojection;  uniform float g_sample_rad = 0.1; uniform float g_intensity = 2.0; uniform float g_scale = 0.1; uniform float g_bias = 0.0;  vec2 calctexcoord() {     return gl_fragcoord.xy / resolution; }  vec3 getposition(vec2 uv) {     vec4 worldpos;      float depth = texture2d(depthmap, uv).r;      worldpos.x = uv.x * 2.0f - 1.0f;      worldpos.y = uv.y * 2.0f - 1.0f;      worldpos.z = depth * 2.0f - 1.0f;      worldpos.w = 1.0;      worldpos = invertviewprojection * worldpos;      worldpos /= worldpos.w;      return worldpos.rgb; }  vec3 getnormal(vec2 uv) {     return normalize(texture2d(normalmap, uv).xyz * 2.0f - 1.0f); }  vec2 getrandom(vec2 uv) {     return normalize(texture2d(noisetexture, resolution*uv / noisescale).xy * 2.0f - 1.0f); }  float doambientocclusion(in vec2 tcoord, in vec2 uv, in vec3 p, in vec3 cnorm) {     vec3 diff = getposition(tcoord + uv) - p;     vec3 v = normalize(diff);     float d = length(diff)*g_scale;      return max(0.0, dot(cnorm, v) - g_bias)*(1.0 / (1.0 + d))*g_intensity; }    void main() {      vec4 kernels[kernel_size] =     vec4[](         vec4(0.355512,  -0.709318,  -0.102371,  0.0 ),         vec4(0.534186,  0.71511,    -0.115167,  0.0 ),         vec4(-0.87866,  0.157139,   -0.115167,  0.0 ),         vec4(0.140679,  -0.475516,  -0.0639818, 0.0 ),         vec4(-0.0796121,    0.158842,   -0.677075,  0.0 ),         vec4(-0.0759516,    -0.101676,  -0.483625,  0.0 ),         vec4(0.12493,   -0.0223423, -0.483625,  0.0 ),         vec4(-0.0720074,    0.243395,   -0.967251,  0.0 ),         vec4(-0.207641,     0.414286,   0.187755,   0.0 ),         vec4(-0.277332,     -0.371262,  0.187755,   0.0 ),         vec4(0.63864,   -0.114214,  0.262857,   0.0 ),         vec4(-0.184051,     0.622119,   0.262857,   0.0 ),         vec4(0.110007,  -0.219486,  0.435574,   0.0 ),         vec4(0.235085,  0.314707,   0.696918,   0.0 ),         vec4(-0.290012,     0.0518654,  0.522688,   0.0 ),         vec4(0.0975089,     -0.329594,  0.609803,   0.0 )      );     vec2 uv = calctexcoord(); //same uv coordinate vertex     vec3 p = getposition(uv);     vec3 n = getnormal(uv);     vec2 rand = getrandom(uv);      float ao = 0.0f;     float rad = g_sample_rad / p.z;      (int j = 0; j < kernel_size; ++j)     {         vec2 coord = reflect(kernels[j].xy, rand)*rad;         ao += doambientocclusion(uv, coord, p, n);     }     ao /= kernel_size;      ao = 1 - (ao);     gl_fragcolor = vec4(ao,ao,ao, 1); } 

i figured out debugging code step step.

i calculate in world space. it's easier handle there. looked @ tutorial uses view space , changed needed world space.

the error here:

 float rad = g_sample_rad / p.z; 

this calculates sampling radius based on distance. in view space, calculates sampling radius distance camera. in world space, calculates distance world coordinate, resulted in looking weird @ z=0 , weirder @ farther away.

so did fix simple this:

vec4 viewpos = camview * vec4(p,1); float ao = 0.0f; float rad = g_sample_rad/viewpos.z; 

i changed point view space , calculated sampling radius in view space, taking in account distance camera.

this fixes it.

enter image description here

i played little bit g_values fit them needs. see how looks everywhere same. that's should like.


Comments