片段着色器 - 平均光度(Fragment Shader - Average Luminosity)

2019-06-27 12:17发布

是否有任何身体知道如何找到平均亮度在片段着色器的纹理? 我有机会获得RGB和YUV纹理YUV Y分量是一个数组,我想从这个数组的平均数。

Answer 1:

最近,我有这个输入图像和我的OpenGL ES的纹理视频帧做我自己。 我没有与产生这些的贴图由于这样的事实,我是与非幂的两个纹理工作去了,你无法为iOS上的OpenGL ES 2.0的NPOT纹理的贴图。

相反,我做了类似的纹理贴图生成多级减速,但也有一些细微的调整。 每一步向下通过四个在宽度和高度,而不是用于MIP贴图的两个正常因子的因子减小所述图像的大小。 我通过和已经在各在更高级别的图像由一个4x4的区域四个像素的四个正方形的中间四个纹理采样位置这样做。 这需要利用硬件纹理插值来平均的四个像素的四个组,然后我不得不平均那些四个像素,以产生在单个步骤中在像素的16X减少。

我使用RGB值的点积用的(0.2125,0.7154,0.0721)一个VEC3转换的图像的亮度在非常第一阶段。 这让我刚看完,其后每减少阶段,这确实有助于在iOS硬件的红色通道。 请注意,您并不需要这个,如果你已经开始用Y通道亮度质感了,但我正在处理RGB图像。

一旦图像已经减少到足够小的尺寸,我从回来到CPU读取像素,并做了最后的快速迭代在剩下的几个在最后的光度值到达。

对于640×480视频帧,该方法产生在iPhone 4〜6 ms的亮度值,并且我想可以挤出在该处理时间的1-2毫秒减少一点点调整。 根据我的经验,这似乎快于iOS设备通常以该尺寸周围产生幂的两张图片的贴图,但我没有坚实的数字来支持这件事。

如果你想看到这个动作,检查出的代码在我的开源GPUImageLuminosity类GPUImage框架(和GPUImageAverageColor超类)。 该FilterShowcase示例演示了动作中的亮度提取。



Answer 2:

你一般不这样做,只是用的着色器。

其中比较常见的方法是创建一个缓冲的质感全MIP-地图(下降到1x1的,这一点很重要)。 当你想找到光度,你的后备缓冲复制到此缓冲区,然后重新生成与近邻算法MIPS。 然后将底部像素具有整个表面的平均颜色,并且可以被用来找到通过类似平均LUM (cr * 0.6) + (cg * 0.3) + (cb * 0.1) 编辑 :如果你有一个YUV,然后做相似,使用Y;问题是把平均纹理到一个单一的价值,这是MIPS做)。

这不是一个精确的技术,但相当快,特别是在那些可以由内部产生的贴图硬件。



Answer 3:

我在这里提出的RGB纹理解决方案,我不知道纹理贴图代将与YUV纹理工作。

第一步是为纹理创建的贴图,如果不是已经存在:

glGenerateMipmapOES(GL_TEXTURE_2D);

现在,我们可以通过使用采样功能的可选的第三个参数访问来自片段着色器的最小纹理贴图水平的RGB值texture2D的“偏见”:

vec4 color = texture2D(sampler, vec2(0.5, 0.5), 8.0);

这将纹理贴图的水平上移八个级别,导致采样小得多水平。

如果你有一个256×256的质感与比例为1使它的8.0偏置将有效降低拾取纹理贴图到最小1x1的水平(二分之二百五十六^ 8 == 1)。 当然,你必须调整偏置为你的条件来样最小水平。

OK,现在我们拥有了整个图像的平均RGB值。 第三步是将RGB减少到光度:

float lum = dot(vec3(0.30, 0.59, 0.11), color.xyz);

点积是这样一种有趣的(和快速)计算加权和方式。



文章来源: Fragment Shader - Average Luminosity