Hey,
I would like to create my own custom effects, but it’s all inside a black box. I cannot extend Effect or BasicEffect, which I was hoping to give me possibility to override the Render function. Any pointers how I could create my own effects?
Hey,
I would like to create my own custom effects, but it’s all inside a black box. I cannot extend Effect or BasicEffect, which I was hoping to give me possibility to override the Render function. Any pointers how I could create my own effects?
Why can’t you extend Effect
or BasicEffect
? It’s intended for this to work, and I’ve seen this done out in the wild…
Because lack of skills.
Error E3004: Base class Fuse.Effects.Effect does not have a default constructor
You need to pass EffectType
to the Effect
-constructor.
BasicEffect is a bit easier to get started with (no wrangling with render-bounds etc), here’s a very simple example of how to extend it:
public sealed class MyEffect : BasicEffect
{
public MyEffect() : base(EffectType.Composition)
{
}
protected override void OnRender(DrawContext dc, Rect elementRect)
{
var original = Element.CaptureRegion(dc, elementRect, int2(0));
if (original == null)
return;
// draw what you want within elementRect
FramebufferPool.Release(original);
}
}
Thanks a lot!
Could you give me an example how to draw the original?
using Uno;
using Uno.Graphics;
using Uno.UX;
using Fuse.Elements;
namespace Fuse.Effects
{
/** Applies a gaussian blur to an @Element.
@examples Docs/Blur/Examples.md
@remarks Docs/Blur/Remarks.md
*/
public sealed class Blur : BasicEffect
{
public Blur() :
base(EffectType.Composition)
{
Radius = 3;
}
float _radius;
/** The radius/size of the blur */
public float Radius
{
get { return _radius; }
set
{
if (_radius != value)
{
_radius = value;
OnRenderingChanged();
OnRenderBoundsChanged();
}
}
}
public override bool Active { get { return Radius > 0; } }
public override VisualBounds ModifyRenderBounds( VisualBounds inBounds )
{
return inBounds.InflateXY(Padding);
}
internal float Sigma { get { return Math.Max(Radius, 1e-5f); } }
internal float Padding { get { return Math.Ceil(Sigma * 3 * Element.AbsoluteZoom) / Element.AbsoluteZoom; } }
protected override void OnRender(DrawContext dc, Rect elementRect)
{
Rect paddedRect = Rect.Inflate(elementRect, Padding);
// capture stuff
var original = Element.CaptureRegion(dc, paddedRect, int2(0));
if (original == null)
return;
var blur = EffectHelpers.Instance.Blur(original.ColorBuffer, dc, Sigma * Element.AbsoluteZoom);
FramebufferPool.Release(original);
draw Fuse.Drawing.Planar.Image
{
DrawContext: dc;
Visual: Element;
Position: elementRect.Minimum - Padding;
Invert: true;
Size: paddedRect.Size;
Texture: blur.ColorBuffer;
apply Fuse.Drawing.PreMultipliedAlphaCompositing;
DepthTestEnabled: false;
};
FramebufferPool.Release(blur);
}
}
}
Here’s the source code of our Desaturate-effect, which does just that:
using Uno;
using Uno.Graphics;
using Uno.UX;
namespace Fuse.Effects
{
/** Desaturates an @Element.
@examples Docs/Desaturate/Examples.md
*/
public sealed class Desaturate : BasicEffect
{
public Desaturate() : base(EffectType.Composition)
{
}
float _amount = 1;
/**
The amount of desaturation to apply.
When `1`, the @Element will be completely grayscale.
*/
public float Amount
{
get { return _amount; }
set
{
if (_amount != value)
{
_amount = value;
OnRenderingChanged();
}
}
}
protected override void OnRender(DrawContext dc, Rect elementRect)
{
var original = Element.CaptureRegion(dc, elementRect, int2(0));
if (original == null)
return;
draw Fuse.Drawing.Planar.Image
{
DrawContext: dc;
Visual: Element;
Position: elementRect.Minimum;
Invert: true;
Size: elementRect.Size;
Texture: original.ColorBuffer;
TextureColor: float4(prev TextureColor.XYZ / Math.Max(prev TextureColor.W, 1e-5f), prev TextureColor.W);
float3 Primaries: float3(0.299f, 0.587f, 0.114f); // CCIR 601
float Luminance: Math.Sqrt(Vector.Dot(TextureColor.XYZ * TextureColor.XYZ, Primaries)); // HSP Color Model
PixelColor: float4(Math.Lerp(TextureColor.XYZ, float3(Luminance), Amount), TextureColor.W);
};
FramebufferPool.Release(original);
}
}
}