Пытаюсь сделать ССАО на примере тех шейдеров, что выкладывал товарищ _arwya. (так что не сочтите за плагиат, если увидите что-то знакомое :) ).
Позиции, нормали, цвет и глубина сохраняются в текстуры GL_RGBA32F через MRT.
Вот код шейдеров:
// // writeGBuffer Vertex shader // varying vec4 p; varying vec3 n; varying float z; void main(void) { vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = pos; z = pos.z / pos.w * 0.5 + 0.5; // правильно ли я сохраняю z ???? p = gl_ModelViewMatrix * gl_Vertex; n = gl_Normal; } // // writeGBuffer Fragment shader // varying vec4 p; varying vec3 n; varying float z; void main(void) { vec3 nn = normalize(n); gl_FragData[0] = vec4(1.0, 1.0, 1.0, 1.0); gl_FragData[1] = p; gl_FragData[2] = vec4( nn, z); }
Сам код ССАО:
// // Fragment Shader SSAO // uniform sampler2DRect albedoMap; uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform sampler2DRect depthMap; uniform mat4 matModelView; uniform mat4 matProj; uniform float width, height; void main(void) { vec4 clr = texture2DRect( albedoMap, gl_FragCoord.xy ); vec4 worldPos = texture2DRect( positionMap, gl_FragCoord.xy ); vec4 normal = texture2DRect( normalMap, gl_FragCoord.xy ); float depth = texture2DRect( depthMap, gl_FragCoord.xy ).r; float z = texture2DRect( normalMap, gl_FragCoord.xy ).a; const float num_jitters = 14.0; vec3 jitters[14] = { vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0), vec3(0.57735, 0.57735, 0.57735), vec3(0.57735, 0.57735, -0.57735), vec3(0.57735, -0.57735, 0.57735), vec3(0.57735, -0.57735, -0.57735), vec3(-0.57735, 0.57735, 0.57735), vec3(-0.57735, 0.57735, -0.57735), vec3(-0.57735, -0.57735, 0.57735), vec3(-0.57735, -0.57735, -0.57735) }; float ssao_radius = 0.1; float passedRays = 0.0, i; for(i = 0; i < num_jitters; i++ ) { vec3 p = jitters[i]*ssao_radius; vec4 sample3d = worldPos + vec4(p, 1.0); vec4 sample2d = sample3d * matProj; // умножаем только на GL_PROJECTION матрицу sample2d /= sample2d.w; // перспективное деление sample2d.xy = sample2d.xy * 0.5 + 0.5; // переводим в [0; 1] sample2d.xy *= vec2(width, height); sample2d.z = sample2d.z * 0.5 + 0.5; float d1 = sample2d.z; float d2 = texture2DRect( normalMap, sample2d.xy).a; // здесь лежит z = pos.z / pos.w * 0.5 + 0.5 if ( d1 > d2 ) passedRays += 1.0; } float shadeFactor = passedRays / num_jitters; gl_FragColor = vec4( vec3(clr.rgb) * shadeFactor, 1.0 ); }
Так вот, результатом работы этих шейдеров является белый экран :). Думаю, что ошибка где-то в проецировании точек или в zbuffer - е
(но не могу найти где). Пробовал также делать линейную глубину, но ситуация не изменилась.
Вообщем, I need help.
Заранее спасибо.
Тут про SSAO не любят распространяться :)
Я вот сейчас тоже его мучаю. Давай разберемся вместе!
Можешь поподробней рассказать ЧТО и КАК надо делать, я попробую и отпишу, если получиться (или не получиться)??
Думаю, что ошибка все таки где-то в проецировании точек (если бы ошибка была в zbuffer-е то на картинке было бы хоть ЧТО-ТО).
Проецирую так:
vec4 sample2d = sample3d * matProj; // умножаем только на GL_PROJECTION матрицу sample2d /= sample2d.w; // перспективное деление sample2d.xy = sample2d.xy * 0.5 + 0.5; // переводим в [0; 1] sample2d.z = sample2d.z * 0.5 + 0.5; sample2d.xy *= vec2(width, height); // получаем xy в диапозоне 0..width, 0..height
Кроме этого никаких других вычислений делать не надо?
Sergio666
ОК, давай вместе. Стучи завтра вечером в аську, я сегодня еще подумаю, может что-нибудь придумаю :)
незнаю ОГЛ, но набрасыватется сразу:
1. Заменить sample2d.xy = sample2d.xy * 0.5 + 0.5; // переводим в [0; 1] на
sample2d=sample2d*0.5;
sample2d.x=sample2d.x+0.5;
sample2d.y=0.5-sample2d.y; // изза этого картинка может рисоваться выше экрана (ЗЕРКАЛЬНО)
2. Незнаю зачем там координата z оО
3. sample2d.xy *= vec2(width, height); // получаем xy в диапозоне 0..width, 0..height ------ с точки зрения математики это получение нового вектора, перпендикулярного к sample2d.xy и vec2(width, height). Нужно умножать компоненты отдельно
3,5. А разве в ОГЛ нужно переводить в 0..width, 0..height???
Che@ter
>2. Незнаю зачем там координата z оО
Там еще кое-что не используется
>3,5. А разве в ОГЛ нужно переводить в 0..width, 0..height???
В шейдере используються текстурные координаты по размеру текстуры (т.е не 0..1, а допустим 0..255)
Che@ter
Попробовал, как ты написал, но это особо не на что не повлияло ((
>sample2d.y=0.5-sample2d.y
в ОГЛ картинку переворачивать не надо )
> А разве в ОГЛ нужно переводить в 0..width, 0..height???
я перевожу, потому что у меня все текстуры NPOTD
А вообще, чтобы проверить правильно ли работает проекция, я спроецировал все точки, которые были сохранены в uniform sampler2DRect positionMap. Картинка рисуется на полэкрана в центре и при этом ее края вытянуты в стороны о__О.
Если проекция правильная, то может быть я не правильно передаю матрицу в шейдер?? делаю так glUniformMatrix4fv(uni_matProj, 1, false, pr);
RaZOR
float d2 = texture2DRect( normalMap, sample2d.xy).
sample2d.xy - у тебя тут точно (w.h ) ?
ну да, глубину сохраняю в альфа-компоненту текстуры normalMap, расчитываю так
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; z = pos.z / pos.w * 0.5 + 0.5;
а в samle2d.xy получаем текст.координаты, по которым берем глубину.
Сейчас пробую писать линейную глубину, но результат тот же ((
innuendo
или ты имел ввиду правильно ли у меня рассчитываеться sample2d.xy ? если это, то хз. Делаю вроде правильно, но может нужно еще что-то сделать ( например засунуть в clip space ) ?
RaZOR
sample2d.xy *= vec2(width, height);
не заметил :)
RaZOR
varying vec4 p;
varying vec3 n;
varying float z;
void main(void)
{
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = pos;
z = pos.z / pos.w * 0.5 + 0.5; // правильно ли я сохраняю z ????
p = gl_ModelViewMatrix * gl_Vertex;
n = gl_Normal;
}
хитро :)
p - в eyeSpace, n - просто так? в objspace
> z = pos.z / pos.w * 0.5 + 0.5; // правильно ли я сохраняю z ????
так ведь в FragCoord.z уже будет глубина
innuendo
бывает :)
еще возникла проблемка - не могу вывести на экран глубину(ни обычную, ни линейную).
vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
float z = pos.z / pos.w * 0.5 + 0.5; // нелинейная
float z_linear = (z - znear)/(zfar - znear); // линейная
в чем может быть проблема? к MRT прицеплена текстура gl_depth_component, в нее глубина пишется вроде нормально ( во всяком случае можно разглядеть едва заметные силуэты)
>хитро :)
p - в eyeSpace, n - просто так? в objspace
издержки производства :)
RaZOR
>еще возникла проблемка - не могу вывести на экран глубину(ни обычную, ни линейную).
попробуй через pow( )
> попробуй через pow( )
попробовал, gl_FragCoor.z выводиться выводится нормально, а та глубина, что считаю вручную - нет.
а как тогда посчитать глубину точки в ручную? через distance( cameraPos, sample3d) ??
Тема в архиве.