GLSL — SSAO: получение нежелательных результатов при выборке глубины

Я пытаюсь реализовать SSAO на основе этого урока: http://john-chapman-graphics.blogspot.com/2013/01/ssao-tutorial.html. Кажется, я не понимаю, как этого добиться, и я продолжаю получать нежелательные результаты в своем фрагментном шейдере.

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

РЕДАКТИРОВАТЬ: Сначала я думал, что неправильно определяю позицию глубины, поэтому я добавил новую функцию positionFromDepth, но она все еще не работает …

Мой фрагмент шейдера:

uniform sampler2D uDepthBuffer;
uniform sampler2D uNoiseTexture;

uniform mat4 uProjection; // camera's projection matrix
uniform mat4 uInverseMatrix; // inverse of projection matrix
uniform vec2 uNoiseScale; // vec2(1024.0 / 4.0, 768.0 / 4.0)

const int MAX_KERNEL_SIZE = 128;

uniform int uSampleKernelSize;
uniform vec3 uSampleKernel[MAX_KERNEL_SIZE];

uniform float uRadius;

const float zNear = 0.1;
const float zFar = 2579.5671;

float linearizeDepth(float near, float far, float depth) {
return 2.0 * near / (far + near - depth * (far - near));
}

vec3 positionFromDepth(vec2 texcoords) {
float d = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords).r);
vec4 pos = uInverseMatrix * vec4(texcoords.x * 2.0 - 1.0,
texcoords.y * 2.0 - 1.0,
d * 2.0 - 1.0, 1.0);

pos.xyz /= pos.w;

return pos.xyz;
}

vec3 normal_from_depth(float depth, vec2 texcoords) {
const vec2 offset1 = vec2(0.0, 0.001);
const vec2 offset2 = vec2(0.001, 0.0);

float depth1 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset1).r);
float depth2 = linearizeDepth(zNear, zFar, texture2D(uDepthBuffer, texcoords + offset2).r);

vec3 p1 = vec3(offset1, depth1 - depth);
vec3 p2 = vec3(offset2, depth2 - depth);

vec3 normal = cross(p1, p2);
normal.z = -normal.z;

return normalize(normal);
}

void main() {
vec2 texcoord = gl_TexCoord[0].st;

vec3 origin = positionFromDepth(texcoord);

float d = texture2D(uDepthBuffer, texcoord).r;
vec3 normal = normal_from_depth(linearizeDepth(zNear, zFar, d), texcoord) * 2.0 - 1.0;
normal = normalize(normal);

vec3 rvec = texture2D(uNoiseTexture, texcoord * uNoiseScale).rgb * 2.0 - 1.0;
vec3 tangent = normalize(rvec - normal * dot(rvec, normal));
vec3 bitangent = cross(normal, tangent);
mat3 tbn = mat3(tangent, bitangent, normal);

float occlusion = 0.0;

for(int i = 0; i < uSampleKernelSize; i++) {
vec3 sample = tbn * uSampleKernel[i];
sample = sample * uRadius + origin.xyz;

vec4 offset = vec4(sample, 1.0);
offset = uProjection * offset;
offset.xy /= offset.w;
offset.xy = offset.xy * 0.5 + 0.5;

float sampleDepth = positionFromDepth(offset.xy).z;
occlusion += (sampleDepth <= sample.z ? 1.0 : 0.0);
}

occlusion = 1.0 - (occlusion / float(uSampleKernelSize));
gl_FragColor = vec4(pow(occlusion, 4.0));
}

Закупоренные образцы меняются, когда я перемещаю камеру. Результат выглядит примерно так:

Результат от шейдера SSAO

Я предполагаю, что я делаю что-то не так при выборке положения глубины, но, возможно, я делаю что-то не так с матрицей проекции. Должна ли матрица uProjection быть транспонирована или инвертирована? Кто-нибудь может определить проблему?

Также не обращайте внимания на тот факт, что я еще не прошел размытие.

2

Решение

Несколько вещей, чтобы рассмотреть здесь. Вы заменили оригинал linearizeDepth уравнение с чем-то другим. Оригинал linearizeDepth функция основана на этом формула.

Обратите внимание, что если вы попытаетесь вывести функцию на основе этой формулы, вы увидите, что на самом деле это инверсия Z, что linearizeDepth функция возвращает не только Z.

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

В частности, я считаю, что цель linearizeDepth в данном случае речь идет не о равномерном распределении света и темноты (я полагаю, это то, что вы здесь делаете) по оси z, а скорее о дешевой проекции координаты Z ‘.

0

Другие решения


По вопросам рекламы [email protected]