防止 WPF ShaderEffect SamplerProperty 调整纹理大小以控制大小

问题描述 投票:0回答:0

我在 WPF 中有一个

ShaderEffect
,有两个
SamplerProperty
。第一个是采样器寄存器 0 中的隐式输入,第二个(在采样器寄存器 1 中)我传递一个
ImageBrush
,并以简单的 PNG 作为其源。
该效果应用于
Rectangle
,其
Fill
设置为以不同 PNG 作为源的
ImageBrush

我还将两个常量传递给着色器,
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。重新调整可能是该过程的一部分。

wpf vb.net xaml shader fragment-shader
© www.soinside.com 2019 - 2024. All rights reserved.