我正在评估SkiaSharp在允许在照片顶部渲染一些矢量元素的项目中使用的功能。SkiaSharp看起来非常适合渲染矢量元素,但是我还想对图像应用转换 - 例如色调曲线调整,如对比度或曝光。
理想的方案是在渲染包含图像的矩形时执行自定义 GLSL 片段着色器代码的方法(例如,仅包装 GLSL 代码的 SKColorFilter 子类,在调用 DrawBitmap 或类似时应用)。
让我现有的 GLSL 代码渲染到纹理,然后让 SkiaSharp 使用该纹理作为其内容绘制一个矩形,也可能有效。但是,如果没有 GPU 回读,我看不到一种方法可以做到这一点,这感觉它会非常慢。
最好的前进方向是什么?更准确地说:如何在 GPU 上、在 SkiaSharp 中将转换应用于图像的像素数据,或者,我还可以使用什么来提供类似 SkiaSharp 的矢量渲染基元,并允许类似 GLSL 片段着色器的像素转换?
你可以看看 v2.84 系列的一些非常早期的预览。他们有一个您可以使用的新SKRuntimeEffect
。
查看预览源:https://aka.ms/skiasharp-eap/index.json
您必须查看 https://github.com/mono/SkiaSharp/pull/1321 PR 的构建:
v2.84.0-pr.1321.*
请参阅此示例: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);