有人能解释一下这个片段着色器吗?它是一个色度键过滤器(绿屏特效)。

8

我想了解这个色度键滤镜的工作原理。如果您不知道什么是色度键,它是一种绿屏效果。有没有人能够解释一下这些功能是如何工作的,以及它们到底在做什么?

float maskY = 0.2989 * colorToReplace.r + 0.5866 * colorToReplace.g + 0.1145 * colorToReplace.b;
 float maskCr = 0.7132 * (colorToReplace.r - maskY);
 float maskCb = 0.5647 * (colorToReplace.b - maskY);

 float Y = 0.2989 * textureColor.r + 0.5866 * textureColor.g + 0.1145 * textureColor.b;
 float Cr = 0.7132 * (textureColor.r - Y);
 float Cb = 0.5647 * (textureColor.b - Y);

 float blendValue = smoothstep(thresholdSensitivity, thresholdSensitivity + smoothing, distance(vec2(Cr, Cb), vec2(maskCr, maskCb)));


 gl_FragColor = vec4(textureColor.rgb * blendValue, 1.0 * blendValue);

我理解前6行是将颜色转换为替换颜色(可能为绿色),并将纹理颜色转换为YCrCb颜色系统。
这个片段着色器有两个输入浮点值:thresholdSensitivity和Smoothing。
  • Threshold Sensitivity 控制需要多相似的像素才能被取代。
  • Smoothing 控制图像中相似颜色逐渐被替换的程度。
我不理解这些值如何在blendValue行中使用。blendValue计算什么? blendValue行和gl_FragColor行实际上如何创建绿屏效果?

1
我觉得这段代码看起来很熟悉:https://github.com/BradLarson/GPUImage/blob/master/framework/Source/GPUImageChromaKeyFilter.m - Brad Larson
是的,我正在尝试理解它的工作原理。 - kilakev
1
radical7对smoothstep()部分有很好的分解,这是一个内置的GLSL函数。它基本上呈现了一个具有模糊而不是锐利边界的阈值函数。我使用它来减少在匹配颜色时通常会看到的一些噪声。其余部分是将其转换为YUV颜色空间,以便从颜色匹配计算中去除亮度(使用基于类似于几年前苹果演示的类图像核心滤镜的代码)。这只是匹配颜色的一种方式,然后根据匹配程度使输入透明或半透明。 - Brad Larson
@BradLarson 我试图为Webgl实现这个着色器,但是我有些卡住了。如果您愿意,您可以看一下这个问题:http://stackoverflow.com/questions/44043782/chroma-key-fragment-shader-fails-to-find-the-color? - Ibe Vanmeenen
就此而言 - 看起来这对于任意颜色都不起作用...例如从图像中删除白色([1.0, 1.0, 1.0])。这正确吗? - davidkomer
1个回答

4
GLSL中的smoothstep函数在一个区间内(由前两个参数指定)评估一个平滑的三次曲线。与GLSL的mix函数相比,后者会线性混合其参数,如下所示: GLSL的<code>mix</code>函数 smoothstep使用Hermite三次多项式确定值。 GLSL的<code>smoothstep</code>函数 在您的shader中,blendValue是基于红色和蓝色色度值之间的距离平滑插值的smoothing值。
最后,gl_FragColor指定最终片段颜色(在片段着色器完成后发生混合)。在您的情况下,它是从输入图像中读取的调制值和透明度的调制alpha值。

我认为这不太对:所涉及的距离是在YCrCb空间中(忽略Y),纹理像素颜色和掩码颜色之间的距离,而不是红色和蓝色色度值之间的距离。 - GuyRT
实际上,我认为你的答案并没有错,只是可能可以用不同的方式解析它。 - GuyRT
另外,我认为第一段不正确。smoothstep 不是在第一和第二个参数之间进行插值 - 最好将其与 step 函数而非 mix 函数进行比较。 - GuyRT
编辑以澄清。我们可以选择就插值的使用进行争论(这在man页面中有描述),但您的观点已经被接受。 - radical7
很久以前我就知道了,但是我有点困惑 - 你所说的“使用Hermite三次多项式”是什么意思?这是否意味着它使用了Hermite三次样条的所有基函数,还是只使用了你图片中的一个(据我所知,那只是其中一个)? - Robin F.
@RobinF。图像中的方程式是Hermite三次多项式在区间[0,1]上的简化形式。由于插值的起点为0,且区间两端的切线也为零,因此完整的Hermite形式简化为仅有的简化形式。 - radical7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接