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, но моя матрица перспективной проекции не соответствует требованиям, возможно, она поможет вам.

Другие вопросы по тегам