在纹理而不是屏幕上使用着色器
Posted
技术标签:
【中文标题】在纹理而不是屏幕上使用着色器【英文标题】:Use shader on texture instead of screen 【发布时间】:2013-02-03 07:27:45 【问题描述】:我编写了一个简单的 GL 片段着色器,它对图像执行 RGB 伽玛调整:
uniform sampler2D tex;
uniform vec3 gamma;
void main()
vec3 texel = texture2D(tex, gl_TexCoord[0].st).rgb;
texel = pow(texel, gamma);
gl_FragColor.rgb = texel;
纹理绘制了大部分屏幕,我想到这是在屏幕上应用每个输出像素的调整,而不是纹理上的每个输入像素。虽然这不会改变它的外观,但这个纹理与屏幕相比是很小的。
为了提高效率,如何让着色器处理纹理像素而不是屏幕像素?如果有帮助,无论如何我都会在每一帧上更改/重新加载此纹理的数据,所以我不介意纹理是否被永久更改。
【问题讨论】:
"无论如何我都会在每一帧上更改/重新加载此纹理的数据" 为什么在重新加载时不应用伽玛? @NicolBolas 这是 Java。提取和重新合并整数的 RGB 分量所需的数组边界检查以及笨拙的移位和掩码使其变慢。 GPU 要好得多。 【参考方案1】:我突然想到这是在屏幕上应用每个输出像素的调整
几乎。每个输出fragment(因此得名)执行片段着色器。在写入像素之前,片段是光栅化的最小单位。被可见渲染几何体覆盖的每个像素都会变成一个或多个片段(是的,片段可能比被覆盖的像素更多,例如在绘制到抗锯齿帧缓冲区时)。
为了效率,
现代 GPU 甚至不会“注意到”略微降低的负载。这是一种微优化,处于不可测量的边缘。我的建议:不要担心。
如何让着色器处理纹理像素而不是屏幕像素?
您可以预处理纹理,首先通过纹理大小的非抗锯齿帧缓冲区对象将其渲染到中间纹理。但是,如果您的更改是非线性,并且伽马调整正是如此,那么您不应该这样做。您希望在线性色彩空间中处理图像并尽可能晚地应用非线性变换。
【讨论】:
谢谢!正如您所解释的,我尝试渲染到中间纹理。 (我不能在 OpenGL 2 上使用帧缓冲区,但我相信,我使用 glCopyTexImage2D 得到了或多或少相同的东西。)它使代码变得混乱,并且在使用普通着色器时增加了约 50% 的帧时间减慢,或者不,似乎对时代没有任何影响。我就不管它,让 GPU 继续处理。以上是关于在纹理而不是屏幕上使用着色器的主要内容,如果未能解决你的问题,请参考以下文章