使用SkiaSharp自定义片段着色器

时间:2018-01-02 23:25:52

标签: glsl fragment-shader vector-graphics skiasharp

我正在评估SkiaSharp,以便在允许在照片顶部渲染一些矢量元素的项目中使用。 SkiaSharp看起来非常适合渲染矢量元素,但我也想对图像应用变换 - 例如对比度或曝光等色调曲线调整。

理想情况是在渲染包含图像的矩形时执行自定义GLSL片段着色器代码的方法(例如,包含GLSL代码的SKColorFilter子类,在调用DrawBitmap时应用,或类似)。

将我现有的GLSL代码渲染到纹理可能也有效,然后让SkiaSharp使用该纹理作为其内容绘制一个矩形。但是,如果没有GPU回读,我无法看到这样做的方法,感觉它会非常慢。

这里最好的方法是什么?更确切地说:或者,如何在GPU上,SkiaSharp中将变换应用于图像的像素数据,或者,我还可以使用什么来提供类似矢量渲染基元的SkiaSharp,还允许GLSL片段着色器像素转换?

1 个答案:

答案 0 :(得分:0)

您可以看一下v2.84系列的一些早期预览。他们有一个新的SKRuntimeEffect,您可以使用。

查看预览供稿:https://aka.ms/skiasharp-eap/index.json

您必须查看https://github.com/mono/SkiaSharp/pull/1321 PR的构建:

v2.84.0-pr.1321 ** p

请参见以下示例:https://github.com/mono/SkiaSharp/issues/1319#issuecomment-640529824

// input values
SKCanvas canvas = ...;
float threshold = 1.05f;
float exponent = 1.5f;

// shader
var src = @"
in fragmentProcessor color_map;

uniform float scale;
uniform half exp;
uniform float3 in_colors0;

void main(float2 p, inout half4 color) {
    half4 texColor = sample(color_map, p);
    if (length(abs(in_colors0 - pow(texColor.rgb, half3(exp)))) < scale)
        discard;
    color = texColor;
}";
using var effect = SKRuntimeEffect.Create(src, out var errorText);

// input values
var inputs = new SKRuntimeEffectInputs(effect);
inputs.Set("scale", threshold);
inputs.Set("exp", exponent);
inputs.Set("in_colors0", new[] { 1f, 1f, 1f });

// shader values
using var blueShirt = SKImage.FromEncodedData(Path.Combine(PathToImages, "blue-shirt.jpg"));
using var textureShader = blueShirt.ToShader();
var children = new SKRuntimeEffectChildren(effect);
children.Set("color_map", textureShader);

// create actual shader
using var shader = effect.ToShader(inputs, children, true);

// draw as normal
canvas.Clear(SKColors.Black);
using var paint = new SKPaint { Shader = shader };
canvas.DrawRect(SKRect.Create(400, 400), paint);