GLSL Motion Blur Дрожание
Я попытался реализовать эффект постобработки размытия в движении, как описано в разделе "Графические процессоры Gems 3", глава 27, но у меня возникли проблемы, поскольку размытие дрожит, когда я перемещаю камеру, и работает не так, как ожидалось. Это мой фрагментный шейдер:
varying vec3 pos;
varying vec3 normal;
varying vec2 tex;
varying vec3 tangent;
uniform mat4 matrix;
uniform mat4 VPmatrix;
uniform mat4 matrixPrev;
uniform mat4 VPmatrixPrev;
uniform sampler2D diffuseTexture;
uniform sampler2D zTexture;
void main() {
vec2 texCoord = tex;
float zOverW = texture2D(zTexture, texCoord).r;
vec4 H = vec4(texCoord.x * 2.0 - 1.0, (1 - texCoord.y) * 2.0 - 1.0, zOverW, 1.0);
mat4 inv1 = inverse(matrix);
mat4 inv2 = inverse(VPmatrix);
vec4 D = H*(inv2*inv1);
vec4 worldPos = D/D.w;
mat4 prev = matrixPrev*VPmatrixPrev;
vec4 previousPos = worldPos*prev;
previousPos /= previousPos.w;
vec2 velocity = vec2((H.x-previousPos.x)/2.0, (H.y-previousPos.y)/2.0);
vec3 color = vec3(texture2D(diffuseTexture, texCoord));
for(int i = 0; i < 16; i++) {
texCoord += velocity;
vec3 color2 = vec3(texture2D(diffuseTexture, texCoord));
color += color2;
}
color /= 16;
gl_FragColor = vec4(color, 1.0);
}
Униформа matrix
а также VPmatrix
являются матрицы ModelView и проекции, которые были получены следующим образом:
float matrix[16];
float VPmatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
glGetFloatv(GL_PROJECTION_MATRIX, VPmatrix);
Униформа matrixPrev
а также VPmatrixPrev
предыдущие матрицы ModelView и проекции, полученные после рендеринга, выглядят следующим образом: (в приведенном ниже коде matrixPrev
а также VPmatrixPrev
являются глобальными переменными)
for(int i = 0; i < 16; i++) {
matrixPrev[i] = matrix[i];
VPmatrixPrev[i] = VPmatrix[i];
}
Все четыре матрицы передаются в шейдер следующим образом:
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrix"), 16, GL_FALSE, matrix);
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "VPmatrix"), 16, GL_FALSE, VPmatrix);
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrixPrev"), 16, GL_FALSE, matrixPrev);
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "VPmatrixPrev"), 16, GL_FALSE, VPmatrixPrev);
В шейдере равномерная zTexture представляет собой текстуру, содержащую значения глубины буфера кадра. (Не уверен, что они делятся на W)
Я надеялся, что шейдер будет работать, но вместо этого я получаю то, что, когда я поворачиваю камеру вокруг дрожания размытия очень быстро с тонкими поворотами. Я попытался визуализировать zTexture, и в результате я получил изображение в градациях серого, так что все в порядке. Я также попытался установить цвет фрагмента H.xyz
а также previousPos.xyz
и во время рендеринга H.xyz
производит цветной экран, previousPos.xyz
производит тот же цветной экран, за исключением того, что когда камера вращается, цвета, кажется, инвертируются, поэтому я подозреваю, что что-то не так с извлечением позиции мира из глубины.
Я что-то здесь упускаю? Любая помощь будет принята с благодарностью.
2 ответа
Забудь мой предыдущий ответ, это ошибка матрицы:
умножения матриц расположены в неправильном порядке, иначе вы должны отправить транспонированную матрицу (объясняя, почему только поворот был учтен, компоненты перевода / масштабирования там, где испортились):
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrix"), 16, GL_FALSE, matrix);
становится
glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrix"), 1, GL_TRUE, matrix);
(примечание 16 - это не размер матрицы, а количество матриц, поэтому здесь он должен быть только один)
Еще одно замечание: вы должны вычислить обратную матрицу и матрицу результатов просмотра проекта * в своем основном приложении, а не в пиксельном шейдере: это делается один раз для пикселей, но должно выполняться только один раз для каждого кадра!)
Предыдущая заметка: Google "RuinIsland_GLSL_Demo.zip": содержит много хороших примеров glsl, помогло мне решить эту проблему
Извините, у меня нет ответа, но есть подсказка: у меня точно такая же проблема, как и у вас. Я думаю, что я использовал тот же материал, указанный Google, и, как и вы, размытие существует только при вращении камеры.
Однако у меня есть подсказка (такая же, как у вас): я думаю, это потому, что шейдер glsl вокруг сети предполагает, что наша текстура глубины содержит z/w, но, как и я, вы использовали настоящую текстуру глубины, заполненную фиксированным конвейером. Таким образом, у вас есть только z, и вам не хватает w в самом первом шаге. Поскольку "texture2D(zTexture, texCoord).r" содержит только z: мы пропускаем вычисления, чтобы получить zOverW. В конце концов мы застряли на полпути от окна spce к месту клипа.
Я нашел это: https://www.opengl.org/wiki/Compute_eye_space_from_window_space, но моя матрица перспективной проекции не соответствует требованиям, возможно, она поможет вам.