【问题标题】:GLSL Motion Blur JitteringGLSL 运动模糊抖动
【发布时间】:2014-10-18 21:29:26
【问题描述】:

我尝试实现 GPU 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);
}

制服matrixVPmatrix是ModelView和Projection矩阵,得到如下:

float matrix[16];
float VPmatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
glGetFloatv(GL_PROJECTION_MATRIX, VPmatrix);

制服matrixPrevVPmatrixPrev是之前渲染后得到的ModelView和Projection矩阵如下:(在下面的代码中matrixPrevVPmatrixPrev是全局变量)

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.xyzpreviousPos.xyz,而在渲染H.xyz 产生彩色屏幕时,previousPos.xyz 产生相同的彩色屏幕,除了当相机旋转时颜色似乎反转,所以我怀疑从深度中提取世界位置有问题。

我在这里遗漏了什么吗?任何帮助将不胜感激。

【问题讨论】:

  • 在您的代码中,您进行了 16 次模糊采样。请注意,这意味着您需要每像素采样 16 倍。好多啊。您是否尝试将其减少到例如4次?效果好吗?你还看到抖动吗?仅凭代码很难说什么,也许一些实验会表明什么是错误的。

标签: glsl motion-blur


【解决方案1】:

忘记我之前的回答,是矩阵错误:

矩阵乘法的顺序错误,否则您必须发送转置矩阵(解释为什么只计算旋转,平移/缩放组件搞砸了):

glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrix"), 16, GL_FALSE, matrix);

变成

glUniformMatrix4fvARB(glGetUniformLocationARB(postShader, "matrix"), 1, GL_TRUE, matrix);

(注16不是矩阵大小而是矩阵个数,所以这里应该只有一个)

另一个注意事项:您应该在主应用程序中计算逆矩阵和 project*view 结果矩阵,而不是像素着色器:它每像素执行一次,但每帧只执行一次!)

过去的帖子说明:谷歌“RuinIsland_GLSL_Demo.zip”:它包含许多很好的 glsl 示例,帮助我解决了这个问题

【讨论】:

  • 你应该编辑你以前的答案,而不是像这样发布另一个
  • 我最终放弃了那个项目,但是在编写另一个项目时,我成功地实现了运动模糊。在这个新项目上实现自定义矩阵堆栈时我注意到的一件事是我应该将 1 作为参数而不是 16 作为参数传递,否则它会发送一个充满零的矩阵。我认为这是我旧项目中唯一的错误,所以我接受了。谢谢!
【解决方案2】:

对不起,我没有答案,只有一个线索: 我和你的问题完全一样。 我想我使用了谷歌指出的相同材料,和你一样,模糊只在相机旋转时存在。

但是我有一个线索(实际上和你的一样):我认为这是因为网络周围的 glsl 着色器假设我们的深度纹理包含 z/w 但是,像我一样,你使用了一个真正的深度纹理,使用固定填充管道。 因此,您只有 z 并且在第一步中缺少 w 。 由于 "texture2D(zTexture, texCoord).r" 确实只包含 z :我们错过了获得 zOverW 的计算。 最后,我们被卡在了从窗口 spce 到剪辑空间的中途。

我发现了这个:https://www.opengl.org/wiki/Compute_eye_space_from_window_space#From_NDC_to_clip 但是我的透视投影矩阵不符合要求,也许对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2012-08-14
    • 2018-12-28
    • 2012-05-27
    相关资源
    最近更新 更多