我在WPF中有一个ShaderEffect
,其中有两个SamplerProperty
。一个是采样器寄存器0中的隐式输入,另一个(在采样器寄存器1中)我传递了一个ImageBrush
,其中有一个简单的PNG作为它的源。
此效果会套用至Rectangle
,而其Fill
设定为ImageBrush
,且来源为不同的PNG。
我还将两个常量ViewportWidth
和ViewportHeight
传递给着色器,这两个常量分别绑定到矩形的ActualWidth
和ActualHeight
,中间有一个IValueConverter
,它舍入到整数像素(因为出于某种原因,矩形总是比整数像素高0.04个像素)。
以下是XAML:
<TextBlock Grid.Row="0">
Texture: 1009 x 753, Control: <Run Text="{Binding Path=ActualWidth, ElementName=TheRectangle, Mode=OneWay, Converter={StaticResource ResourceKey=Rounder}}"
/> x <Run Text="{Binding Path=ActualHeight, ElementName=TheRectangle, Mode=OneWay, Converter={StaticResource ResourceKey=Rounder}}"/>
</TextBlock>all textures passed to MyEffect1. -->
<Rectangle x:Name="TheRectangle" Grid.Row="1" Margin="20" RenderOptions.BitmapScalingMode="NearestNeighbor" >
<Rectangle.Fill>
<ImageBrush ImageSource="D:\NoEffect.png"/>
</Rectangle.Fill>
<Rectangle.Effect>
<l:MyEffect1
x:Name="MyEffect"
ViewportWidth="{Binding Path=ActualWidth, ElementName=TheRectangle, Mode=OneWay, Converter={StaticResource ResourceKey=Rounder}}"
ViewportHeight="{Binding Path=ActualHeight, ElementName=TheRectangle, Mode=OneWay, Converter={StaticResource ResourceKey=Rounder}}"
>
<l:MyEffect1.TestTexture>
<ImageBrush x:Name="Texture" ImageSource="D:\MinecraftSkeletonTexture.png"/>
</l:MyEffect1.TestTexture>
</l:MyEffect1>
</Rectangle.Effect>
</Rectangle>
字符串
下面是HLSL着色器代码:
sampler2D ImplicitTexture : register(S0);
sampler2D TestTexture : register(S1);
float ViewportWidth : register(C0);
float ViewportHeight : register(C1);
float4 main(float2 UV : TEXCOORD) : SV_Target
{
// These two tests work as expected.
// return tex2D(ImplicitTexture, UV);
// return tex2D(TestTexture, UV);
// Convert UV-space to pixels
float2 ScreenPixel = UV * float2(ViewportWidth, ViewportHeight);
// Hard-coded size (in pixels) of TestTexture, for easy testing
float2 TestTextureSourceSize = float2(1009, 753);
// Where (in pixels) we want to sample the TestTexture
// We could also e.g. zoom in by a factor of 5 by dividing ScreenPixel by 5, or shift to the left by 100 pixels by adding float2(100, 0)
float2 SamplePositionInPixels = ScreenPixel;
// Convert pixels to UV-space
float2 TestTextureRelativeUv = SamplePositionInPixels / TestTextureSourceSize;
// Sample the texture at that position
return tex2D(TestTexture, TestTextureRelativeUv);
}
型
这在原则上是可行的,但问题是我实际上无法从着色器访问整个TestTexture。当我减小窗口大小(因此也减小了Rectangle
大小)时,我开始丢失像素数据。
下面是一个现象的视频:https://imgur.com/a/4hbebMS
结果不应扭曲,也不应像那样变成块状。
WPF似乎会调整纹理的大小,以符合套用此效果的矩形大小。
有什么办法可以防止这种情况发生吗?
这对我来说是个问题,因为在实际的程序中,我使用纹理将大量的任意数据传递给着色器,这些数据被插值完全打乱了。
注意事项:RenderOptions.BitmapScalingMode="NearestNeighbor"
的存在并不会改变这个行为。它只是改变了纹理在传递到着色器之前缩小的方式。另请注意:WPF会在将所有纹理传送到着色器之前,先将它们转换为(p)BGRA32。重新调整比例可能是该过程的一部分。
1条答案
按热度按时间mpgws1up1#
请看blogs.ugidotnet.org/leonardo,0.04像素的问题可以是PNG文件,因为无法在元数据中存储96 DPI。尝试使用PNGGauntlet删除元数据,以便WPF默认为96 DPI,并且您不会调整纹理大小。为了解决第二个问题(固定TestTexture大小),您应该避免将Brush重命名(不要将其放在重命名的元素中)。