简体   繁体   English

将自定义和复杂的 2d 渐变应用于 WPF 3d 对象

[英]Apply custom and complex 2d gradient to WPF 3d Objects

What I would like to do is simple to describe:我想做的很容易描述:

I want to map an UV map like in this question on a cube: WPF Texture mapping of a cube .我想 map 和 UV map 就像在立方体上的这个问题一样: WPF Texture mapping of a cube

But with an higher level of complety: I want to generate the 2d gradient on the fly (from N points coloured in N different ways).但是具有更高的完整性:我想动态生成 2d 渐变(从以 N 种不同方式着色的 N 个点)。

I've read somewhere that wpf cannot create 2d gradient: is it still true?我在某处读到 wpf 无法创建 2d 渐变:它仍然是真的吗? Is there any way to create this gradient, avoiding complex solution such as mixing N linear gradients?有没有办法创建这个梯度,避免复杂的解决方案,比如混合 N 个线性梯度?

Maybe using something like a 2d mesh or some external library?也许使用二维网格或一些外部库之类的东西?

Thank you.谢谢你。

2D gradients aren't supported, but if you can deconstruct it down to some alpha-blended or additive combination of two 1d gradients then it can still be done.不支持 2D 渐变,但如果您可以将其解构为两个 1d 渐变的一些 alpha 混合或相加组合,那么它仍然可以完成。 Check out my answer to this question for an example.我对这个问题的回答为例。

Anything more complex and you'll have to generate the shading yourself.任何更复杂的东西,您都必须自己生成阴影。 The easiest way to do this is to create a 2D texture manually and apply that to your geometry.最简单的方法是手动创建 2D 纹理并将其应用于几何体。 Plenty of examples on the net showing how to do that.网上有很多例子展示了如何做到这一点。

If you don't want to generate a texture then your only remaining option is to use a custom shader.如果您不想生成纹理,那么您唯一剩下的选择就是使用自定义着色器。 This is not a trivial topic, but I'll give you the general idea.这不是一个微不足道的话题,但我会给你一个大致的想法。 You start with your shader fx code, which you then compile to a ps file:您从着色器 fx 代码开始,然后将其编译为 ps 文件:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    return float4(uv.x, uv.y, 0, 1);
}

Obviously this is just a very simple shader that sets red along the x axis and green along y, in your example you'd probably want to pass both axis in as 1D textures containing your gradient stops.显然,这只是一个非常简单的着色器,它沿 x 轴设置红色,沿 y 轴设置绿色,在您的示例中,您可能希望将两个轴作为包含渐变色标的 1D 纹理传入。 Either way, you compile it down, add it as a resource and load it with a class based on ShaderEffect:无论哪种方式,您都可以编译它,将其添加为资源并使用基于 ShaderEffect 的 class 加载它:

public class MyShader : ShaderEffect
{
    public MyShader() => this.PixelShader = new PixelShader { UriSource = new Uri("/MyApp;component/MyShader.ps", UriKind.Relative) };
}

With that out of the way, you now need to apply it to geometry.有了它,您现在需要将其应用于几何体。 WPF doesn't directly support 3d texture shaders, but since you've loaded your shader as an effect you can create a 2d VisualBrush and apply it like that instead: WPF 不直接支持 3d 纹理着色器,但由于您已将着色器作为效果加载,您可以创建 2d VisualBrush 并像这样应用它:

<Viewport3D>
    <Viewport3D.Camera>
        <PerspectiveCamera Position="0 0 10" LookDirection="0 0 -1"/>
    </Viewport3D.Camera>
    <ModelVisual3D>
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <AmbientLight Color="White" />
            </ModelVisual3D.Content>
        </ModelVisual3D>
    </ModelVisual3D>
    <ModelVisual3D>
        <ModelVisual3D.Content>
            <GeometryModel3D>
                <GeometryModel3D.Geometry>
                    <MeshGeometry3D 
                        Positions="-1 -1 0  1 -1 0  -1 1 0  1 1 0"
                        TextureCoordinates="0 1  1 1  0 0  1 0"
                        TriangleIndices="0 1 2  1 3 2" />
                </GeometryModel3D.Geometry>
                <GeometryModel3D.Material>
                    <DiffuseMaterial>
                        <DiffuseMaterial.Brush>
                            <VisualBrush>
                                <VisualBrush.Visual>
                                    <Image Source="texture.png"> <!-- placeholder texture -->
                                        <Image.Effect>
                                            <local:MyShader />
                                        </Image.Effect>
                                    </Image>
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </DiffuseMaterial.Brush>
                    </DiffuseMaterial>
                </GeometryModel3D.Material>
            </GeometryModel3D>
        </ModelVisual3D.Content>
    </ModelVisual3D>
</Viewport3D>

The result is 3D geometry mapped with your custom shader output:结果是使用自定义着色器 output 映射的 3D 几何图形:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM