我想创建一个效果,我使用一个非常大的图像通过WPF效果生成一个带有HLSL的较小图像。但似乎WPF由于某种原因将所有输入图像调整为渲染大小,这不是我想要的,因为它将裁剪我的一个图像并使我的最终图像看起来不那么好。
这就是我设置它的方式。 我有一个在MediaElement中播放的大小为2592x1944的图像(视频)。 我将我的效果应用于大小为800x600的边框(或其他元素),并将MediaElement绑定到效果,以便能够将要渲染的曲面(边框)和要渲染的源(MediaElement)发送到像素着色器。
但是由于光源的严重裁剪,所得到的图像非常像素化。
有没有人知道是否有办法让WPF不裁剪像素着色器样本?
我发现Greg Schecter的这篇博文有点做我想做的事,但反过来说: http://blogs.msdn.com/b/greg_schechter/archive/2008/09/27/a-more-useful-multi-input-effect.aspx 他缩小了一个图像,但我想让它更大。问题是他使用的是ImageBrush,因为我使用的是UIElements而不是图像,所以我得到了一个VisualBrush。不知道是否有办法在VisualBrush上做他做的事情。
答案 0 :(得分:1)
在WPF Visual
中,您无能为力,因为如果图像源的尺寸大于渲染尺寸,则WPF PixelShader
会失去质量。如果图像源的大小小于渲染大小,则可以使用PaddingTop
,PaddingBottom
,PaddingLeft
和PaddingRight
。只有一个小路,可以帮助您节省全质量:
使用Image
或ImageBrush
并将Stretch
设置为None
。通过这种方式,您可以将完整图像(Textura)发送到PixelShader
。您必须在自定义DependencyPRoperty
中拥有ShaderEffect
:
public static readonly DependencyProperty ViewAspectProperty = DependencyProperty.Register(nameof(ViewAspect), typeof(Point), typeof(CustomEffect), new UIPropertyMetadata(new Point(1D, 1D), PixelShaderConstantCallback(0)));
public Point ViewAspect
{
get => (Point)GetValue(ViewAspectProperty);
set => SetValue(ViewAspectProperty, value);
}
和在Shader.fs中:
float2 ViewAspect : register(C0) = float2(1, 1);
sampler2D Input : register(s0);
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COlOR;
float2 UV : TEXCOORD;
};
float4 main(VS_OUTPUT input) : COlOR
{
float2 uv = input.UV;
uv.x *= ViewAspect.x;
uv.y *= ViewAspect.y;
return tex2D(Input, uv);
}
当渲染控件将更改大小时,您需要:
ViewAspectX = ViewWidth > 0 ? FrameWidth / ViewWidth : 1;
ViewAspectY = ViewHeight > 0 ? FrameHeight / ViewHeight : 1;
其中ViewWidth
和ViewHeight
是渲染FrameworkElement的大小,而FrameWidth
和FrameHeight
是源图像的大小。这样,您可以在不损失质量的情况下调整输入图像的大小>