【问题标题】:How can a fragment shader use the color values of the previously rendered frame?片段着色器如何使用先前渲染帧的颜色值?
【发布时间】:2011-07-29 19:25:54
【问题描述】:

我正在学习在 OpenGL ES 中使用着色器。

举个例子:这是我的游乐场片段着色器,它获取当前视频帧并使其成为灰度:

varying highp vec2 textureCoordinate;

uniform sampler2D videoFrame;

void main() {
    highp vec4 theColor = texture2D(videoFrame, textureCoordinate);
    highp float avrg = (theColor[0] + theColor[1] + theColor[2]) / 3.0;
    theColor[0] = avrg; // r
    theColor[1] = avrg; // g
    theColor[2] = avrg; // b
    gl_FragColor = theColor;
}

theColor 表示当前像素。如果还可以访问同一坐标上的前一个像素,那就太酷了。

出于好奇,我想将当前像素的颜色与前一个渲染帧中像素的颜色相加或相乘。

我怎样才能保留以前的像素并将它们传递给我的片段着色器以便对它们做一些事情?

注意:它是 iPhone 上的 OpenGL ES 2.0。

【问题讨论】:

  • 正如 Matias Valdenegro 下面所述,您需要渲染到 FBO。但是当你这样做并使用你的着色器渲染时,它会很亮,你应该除以三而不是二以获得正确的平均值。转换为灰度时更常用的方法是使用颜色分量的加权和。请参阅mathworks.com/help/toolbox/images/ref/rgb2gray.html 了解哪些权重是好的。
  • 感谢您指出这一点。是我的代码中的错字。
  • 而且你一开始就不应该加和除。您应该使用dot instrinsic 函数,该函数映射到一个指令,该指令可以一步完成,而且速度要快得多。
  • 我的意思是dot(theColor.xyz, vec3(0.3333))。点积将两个向量相乘,然后将分量相加。这正是您正在做的事情,除了它是一个单一的 1 周期指令。见dot
  • @Damon:它可能是“单 1 周期指令”。它也可能是 3 条指令(一个向量乘法,两个从属相加)。但是,不管它是什么,它仍然会优于他的代码。或者在最坏的情况下,它不会慢,所以他仍然应该这样做。

标签: opengl-es glsl shader opengl-es-2.0 fragment-shader


【解决方案1】:

您需要使用帧缓冲区对象 (FBO) 将前一帧渲染为纹理,然后您可以在片段着色器中读取此纹理。

【讨论】:

  • 你能举一些例子或指出一些涵盖这个主题的好资源吗?
【解决方案2】:
Damon 所指的点内在函数是数学点积的代码实现。我对 OpenGL 不是非常熟悉,所以我不确定确切的函数调用是什么,但从数学上讲,点积是这样的:

给定一个vector a 和一个vector b'dot' product a 'dot' b 产生一个标量结果c

c = a.x * b.x + a.y * b.y + a.z * b.z

大多数现代图形硬件(以及 CPU,就此而言)都能够一次性执行此类操作。在您的特定情况下,您可以使用如下点积轻松计算平均值:

highp vec4 = (1/3, 1/3, 1/3, 0) //or zero

由于某种原因,我总是把齐次向量和矩阵中的第 4 个分量弄混。

highp float avg = theColor DOT vec4

这会将 theColor 的每个分量乘以1/3(第四个分量乘以 0),然后将它们加在一起

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2021-12-02
    • 2014-07-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    相关资源
    最近更新 更多