2015-06-03 5 views
0

Поэтому я попытался реализовать SSAO, но он не работает должным образом. Кажется, что он разделен на позицию z = 0 (мировое пространство), есть белая линия в положении z = 0. Также Окклюзия там выглядит не так.SSAO неверно при z = 0 и на расстоянии

enter image description here

Plus на большем расстоянии, так что при перемещении камеры, закупорка становится еще страннее enter image description here

My Shader для визуализации геометрии (инстанциирован):

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); 

} 

Фрагмент:

#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; 
} 

После прохождения геометрии я применяю пропуск SSAO с информацией о нормалях и глубинах.

Это мой NoiseTexture: enter image description here

Я использую аппаратный буфер глубины. Я подсчитываю все в мировом пространстве.

Вот фрагмент 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 as UV Coordinate from Vertex 
    vec3 p = getPosition(uv); 
    vec3 n = getNormal(uv); 
    vec2 rand = getRandom(uv); 

    float ao = 0.0f; 
    float rad = g_sample_rad/p.z; 

    for (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); 
} 
+0

Я не совсем понимаю, когда вы говорите z = 0. О каком пространстве координат вы говорите? В пространстве NDC, который будет центром вашего видимого вида, и он будет параллелен плоскости изображения, не работающей по диагонали, как показано на снимках экрана. В других местах это может быть ваш ближний или дальний клип, насколько я знаю.Единственное, что я могу вам сказать, это то, что многие из этих шумов могут быть уменьшены, если вы используете линейный/логарифмический буфер глубины вместо перспективы. –

+0

Что для меня работает, это своего рода гибридный подход. Я использую буфер глубины с плавающей запятой с инвертированным диапазоном глубины (это определяет не менее оптимальное распределение точности в перспективе), что устраняет эти артефакты группировки, а затем различные методы пост-обработки на основе глубины на самом деле требуют линейной глубины, поэтому я также буду возьмите буфер глубины оборудования, описанный выше, и линеаризуйте его по мере необходимости в шейдере. –

+0

Я вычисляю все в мировом пространстве, потому что мое освещение вычисляется в мировом пространстве, поэтому я не хочу переключаться между пробелами. для расчета моей позиции в мире Мне не нужна линейная глубина. Я проверил его, взяв образец из текстуры, где я сохранил позицию раньше, и оба дают мне тот же результат. Что я имел в виду под z = 0, это позиция в мире. Если я перемещаю камеру в направлении z и смотрю на вершины, которые находятся дальше от z = 0, они выглядят искаженными, как показано на рисунке 2. – PuRe

ответ

0

Я понял это по отладке шаг за шагом кода.

Я подсчитываю все в мировом пространстве. С этим легче справиться. Я посмотрел учебник, в котором используется пространство просмотра и изменилось все, что мне нужно для мирового пространства.

Ошибка здесь:

float rad = g_sample_rad/p.z; 

это вычисляет радиус выборки на основе расстояния. В поле зрения это вычисляет радиус выборки для расстояния от камеры. Но в мировом пространстве это вычисляется для расстояния от мировой координаты, что привело к тому, что оно выглядело странно при z = 0 и даже более странно дальше.

так, что я сделал, чтобы исправить это просто так:

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

Я изменил точку, чтобы просмотреть пространство и вычислил радиус выборки в пространстве вида, таким образом, принимая во внимание расстояние от камеры.

Это исправление.

enter image description here

Я играл немного с g_values, чтобы подогнать их для моих потребностей. Посмотрите, как это выглядит везде одинаково. Вот как это должно выглядеть.

 Смежные вопросы

  • Нет связанных вопросов^_^