Применение настраиваемого и сложного 2D-градиента к 3D-объектам WPF - PullRequest
0 голосов
/ 14 июля 2020

То, что я хотел бы сделать, просто описать:

Я хочу сопоставить UV-карту, как в этом вопросе, на кубе: Отображение текстур WPF куба .

Но с более высоким уровнем завершенности: я хочу сгенерировать 2d градиент на лету (из N точек, раскрашенных N разными способами).

Я где-то читал, что wpf не может создать 2d градиент : это все еще правда? Есть ли способ создать этот градиент, избегая сложных решений, таких как смешивание N линейных градиентов?

Может быть, используя что-то вроде 2d me sh или какую-то внешнюю библиотеку?

Спасибо.

1 Ответ

1 голос
/ 14 июля 2020

2D-градиенты не поддерживаются, но если вы можете деконструировать его до некоторой альфа-смешанной или аддитивной комбинации двух 1d градиентов, то это все равно можно сделать. Посмотрите, например, мой ответ на этот вопрос .

Что-нибудь более сложное, и вам придется создавать затенение самостоятельно. Самый простой способ сделать это - создать 2D текстуру вручную и применить ее к своей геометрии. Множество примеров на net, показывающих, как это сделать.

Если вы не хотите генерировать текстуру, вам остается только использовать собственный шейдер. Это не банальный топи c, но общее представление я вам дам. Вы начинаете с вашего fx-кода шейдера, который затем компилируете в файл ps:

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

Очевидно, это просто очень простой шейдер, который устанавливает красный цвет по оси x и зеленый по оси y, в вашем примере вы Возможно, я хотел бы передать обе оси как одномерные текстуры, содержащие ваши градиентные остановки. В любом случае, вы компилируете его, добавляете в качестве ресурса и загружаете с классом, основанным на ShaderEffect:

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

Теперь вам нужно применить его к геометрии. WPF напрямую не поддерживает шейдеры трехмерных текстур, но поскольку вы загрузили свой шейдер в качестве эффекта, вы можете создать 2d VisualBru sh и применить его следующим образом:

<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>

Результат - 3D геометрия, сопоставленная с вашим пользовательским выводом шейдера:

введите описание изображения здесь

...