gor*_*dyr 4 shader webgl fragment-shader
我目前在 WebGL 中使用这个片段着色器来对照片纹理应用高光/阴影调整。
uniform sampler2D inputImageTexture;
varying highp vec2 textureCoordinate;
uniform lowp float shadows;
uniform lowp float highlights;
const mediump vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3);
void main()
{
lowp vec4 source = texture2D(inputImageTexture, textureCoordinate);
mediump float luminance = dot(source.rgb, luminanceWeighting);
mediump float shadow = clamp((pow(luminance, 1.0/(shadows+1.0)) + (-0.76)*pow(luminance, 2.0/(shadows+1.0))) - luminance, 0.0, 1.0);
mediump float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0);
lowp vec3 result = vec3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0))/(luminance - 0.0));
gl_FragColor = vec4(result.rgb, source.a);
}
Run Code Online (Sandbox Code Playgroud)
这个着色器目前只会减少0.0 - 1.0. 但是,我希望它也能在1.0-2.0.
目的是拥有一个完整的过滤器,当高光均匀小于 时减少图像高光,并在高于 时1.0增加高光强度1.0。黑暗阴影统一也是如此
强调:
0.0(duller) ---- 1.0 (default - original pixel values) ----- 2.0 (brighter)
Run Code Online (Sandbox Code Playgroud)
我曾尝试简单地将高光变量上的钳位更改为0.0,2.0,尽管这确实增加了当制服高于高光时的亮度,但1.0它也会严重弄乱颜色。
正如您所知,我对图像处理和构建片段着色器的理解充其量是非常薄弱的。
我只是希望有人能指出我正确的方向。
编辑:
以下是一些示例屏幕截图:-
1.00(基本上是源图像)的当前过滤器
0.00如您所见,高光被展平/移除。
clamp片段着色器中的 以允许上面的值1.00并将高光值设置为时会发生什么2.00
我只是希望能够增强亮点,使它们更亮/更清晰。即与设置值相反0.00
Ten*_*r04 10
我不太了解阴影和高光方程,但我可以看到它们的设置从不增强阴影和高光,而是将它们洗掉。所以我们需要一个辅助步骤来增强。
对于高光,我认为要处理更亮的颜色,您需要向白色混合而不是添加一些东西,这样您就不会出现色调偏移。我使用了一个基本的对比度方程来挑出高光,然后将其立方以剪掉中间调和阴影。的whiteTarget只是拉出顶部一半的0.0-2.0范围的作为乘数用来确定的增白效果的强度。
对于阴影,我们将范围从 0.0-1.0(其中 0 不变且 1 被淡化)更改为 0.0-2.0(其中 1 不变而 2 被淡化)。因此,shadow方程中的+1.0 应该被删除。然后对于 0.0-1.0 范围,我只是复制了我为高光所做的事情,除了向黑色混合。也许可以优化以避免mix函数(不确定)。
因此,这里是我的未优化版本的着色器,设置这样既shadows和highlights都在0.0-2.0秤,1.0是标称。您可能想要使用那些将亮度立方化的线条,以及我用于对比度的值(当前为 1.5),但对我来说现在的方式似乎很好——我调整了它以尽量避免当输入参数处于两个极端时,阴影和高光范围之间的任何难看的重叠。
uniform sampler2D inputImageTexture;
varying highp vec2 textureCoordinate;
uniform lowp float shadows;
uniform lowp float highlights;
const mediump vec3 luminanceWeighting = vec3(0.3, 0.3, 0.3);
void main()
{
lowp vec4 source = texture2D(inputImageTexture, textureCoordinate);
mediump float luminance = dot(source.rgb, luminanceWeighting);
//(shadows+1.0) changed to just shadows:
mediump float shadow = clamp((pow(luminance, 1.0/shadows) + (-0.76)*pow(luminance, 2.0/shadows)) - luminance, 0.0, 1.0);
mediump float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0);
lowp vec3 result = vec3(0.0, 0.0, 0.0) + ((luminance + shadow + highlight) - 0.0) * ((source.rgb - vec3(0.0, 0.0, 0.0))/(luminance - 0.0));
// blend toward white if highlights is more than 1
mediump float contrastedLuminance = ((luminance - 0.5) * 1.5) + 0.5;
mediump float whiteInterp = contrastedLuminance*contrastedLuminance*contrastedLuminance;
mediump float whiteTarget = clamp(highlights, 1.0, 2.0) - 1.0;
result = mix(result, vec3(1.0), whiteInterp*whiteTarget);
// blend toward black if shadows is less than 1
mediump float invContrastedLuminance = 1.0 - contrastedLuminance;
mediump float blackInterp = invContrastedLuminance*invContrastedLuminance*invContrastedLuminance;
mediump float blackTarget = 1.0 - clamp(shadows, 0.0, 1.0);
result = mix(result, vec3(0.0), blackInterp*blackTarget);
gl_FragColor = vec4(result, source.a);
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,知道为什么原始result行不断向所有内容添加 0 吗?好像可以简化为
vec3 result = (luminance + shadow + highlight) * source.rgb / luminance;
Run Code Online (Sandbox Code Playgroud)
但也许lowp在计算中而不是在计算之后转换是一个技巧。只是一个猜测。