• 在WPF中使用着色器


    概念类比

    范畴 CPU GPU
    二进制文件 .exe .cso / .ps
    二进制指令 机器码 CSO(shader指令)
    助记符 汇编 SL
    高级语言 C# HLSL
    高级语言文件 .cs .hlsl / .fx
    高级语言编译器 csc.exe fxc.exe
    API .NET API DirectX API
    运行时环境 CLR DirectX
    调试工具 Visual Studio Debugger RenderDoc
    • 着色器类型
    着色器简称 着色器名 解释
    cs_4_0 Compute Shader model 4.0 计算着色器,用于处理非图形计算任务
    ds_5_0 Domain Shader model 5.0 域着色器,用于曲面细分技术中,生成顶点后处理顶点数据
    fx_2_0 Effect model 2.0 效果文件,用于组合多个渲染状态和着色器程序,方便管理和使用
    gs_4_0 Geometry Shader model 4.0 几何着色器,能接收一些图形形状作为输入,并输出其他形状,用于生成新顶点和图形
    hs_5_0 Hull Shader model 5.0 曲面控制着色器,用于图形的曲面细分
    ps_2_0 Pixel Shader model 2.0 像素着色器,用于计算像素颜色
    tx_1_0 Texture Shader model 1.0 (software) 纹理着色器,主要用于处理纹理映射
    vs_1_1 Vertex Shader model 1.1 顶点着色器,用于处理每个顶点数据

    3DS Max HLSL编写与预览

    • 首先,为了避免折腾和跟上b站的视频教程,下载3DS Max,接着添加一个茶壶
      只是教程用的是Direct9,我们现在用的是Direct11,语法有点差异
      image
      打开3DS Max,按下快捷键M,或者点击材质编辑器
      image
      然后切换模式,换成精简材质编辑器
      image
      点击物理材质切换自己写的shader
      image
      选择DirectX Shader材质
      image
      点击确定
      image
      点击路径,可选择自定义材质
      image

    可以事先在桌面上新建一个txt文件,然后把扩展名改为.fx,可以使用vscode或者visualStudio下载HLSL扩展进行编辑
    这列我提供一个Direct11的最简单的纯色着色器效果文件solidColor.fx

    // solidColor.fx
    
    
    //世界投影矩阵
    //用来将顶点从模型空间转换到最终的裁剪空间
    float4x4 WorldViewProjection : WorldViewProjection < string UIWidget="None"; >;
    
    //UI面板项目
    float4 SolidColor
    <
        string UIWidget = "Color";
        string UIName="Solid Color";
    > = float4(1.0f, 1.0f, 1.0f, 1.0f);
    
    struct VertexShaderInput
    {
        //顶点着色器输入用这个语义
        //表示顶点的位置信息
        //模型空间(或世界空间)中定义的
        float4 Position : POSITION;
    };
    
    struct VertexShaderOutput
    {
        //顶点着色器输出用这个语义
        //表示顶点在裁剪空间(Clip Space)中的位置
        //用来决定顶点在屏幕上位置的空间
        float4 Position : SV_Position;
    };
    
    struct PixelShaderOutput
    {
        float4 Color : SV_TARGET;
    };
    
    //================== 简单的顶点着色器函数
    VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
    {
        VertexShaderOutput output;
    
        // 计算最终的顶点位置
        output.Position = mul(input.Position, WorldViewProjection);
    
        return output;
    }
    
    
    //=============== 基本像素着色器函数
    PixelShaderOutput PixelShaderFunction()
    {
        PixelShaderOutput output;
    
        // 设置像素颜色为 SolidColor 定义的颜色
        output.Color = SolidColor;
    
        return output;
    }
    
    // 定义渲染效果
    //Direct9写technique
    //Direct10写technique10
    //Direct11写technique11
    technique11 SolidColorTechnique
    {
        pass P0
        {
            // 基本顶点着色器
            VertexShader = compile vs_5_0 VertexShaderFunction();
    
            // 基本像素着色器
            PixelShader = compile ps_5_0 PixelShaderFunction();
        }
    }
    

    然后把这个材质拖到模型上
    image
    参数Solid Color是我们在代码中定义的组件,用来选材质颜色

    float4 SolidColor
    <
        string UIWidget = "Color";
        string UIName="Solid Color";
    > = float4(1.0f, 1.0f, 1.0f, 1.0f);
    

    image

    WPF着色器编写与使用

    看了下,似乎wpf只支持像素着色器,不支持顶点着色器。那代码就简化许多了。
    第二个问题是wpf中没有通过HLSL生成UI控件,怎么调整SolidColor?
    我看了下HLSL变量声明语法,原来是批注语法效果框架能识别,但会被hlsl忽略
    https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-syntax

    [Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset] [: Register]; [Annotations] [= Initial_Value]
    

    wpf中使用的则是Register可选部分,从寄存器读取输入

    wpfSolidColor.fx
    
    struct PixelShaderOutput
    {
        float4 Color : SV_TARGET;
    };
    float4 SolidColor : register(c0) = float4(1.0f, 1.0f, 1.0f, 1.0f);
    
    //=============== 基本像素着色器函数
    PixelShaderOutput PixelShaderFunction()
    {
        PixelShaderOutput output;
    
        // 设置像素颜色为 SolidColor 定义的颜色
        output.Color = SolidColor;
    
        return output;
    }
    
    namespace 你的命名空间
    {
        public class SolidShader:ShaderEffect
        {
            public static readonly DependencyProperty SolidColorProperty = DependencyProperty.Register("SolidColor", typeof(Color), typeof(SolidShader), new UIPropertyMetadata(Color.FromArgb(255, 0, 0, 0), PixelShaderConstantCallback(1)));
            public SolidShader()
            {
                PixelShader pixelShader = new PixelShader();
                pixelShader.UriSource = new Uri("pack://application:,,,/程序集命名空间;component/路径/TextEffect2.ps", UriKind.Absolute);
                this.PixelShader = pixelShader;
    
                this.UpdateShaderValue(SolidColorProperty);
            }
            public Color SolidColor
            {
                get
                {
                    return ((Color)(this.GetValue(SolidColorProperty)));
                }
                set
                {
                    this.SetValue(SolidColorProperty, value);
                }
            }
        }
    }
    

    最后看到像素着色器正常运行
    image

    总结

    • 自定义
      着色器类型很多,3ds max中能自定义完整的渲染管线,包括顶点着色器和像素着色器。但是wpf只支持像素着色器的自定义。
    • 着色器编译入口
      使用fxc.exe我们可以自及指定入口函数,但是使用Shazzam Shader Editor 看起来已经在代码中固定了入口函数。
      Shazzam Shader Editor使用Shazzam Shader Editor 的好处是编译和预览方便
    • 版本
      Direct已经更新到11了,但wpf只支持Direct9
  • 相关阅读:
    ubuntu 23.04安装中文输入法
    Hadoop(五)C#操作Hive
    Bootstrap table 表格创建
    【RP2物联网实战(一)】C/C++&FreeRTOS版
    YoloV5/YoloV7独家改进:Multi-Dconv Head Transposed Attention注意力,效果优于MHSA| CVPR2022
    性能测试、负载测试、压力测试、稳定性测试简单区分【超详细】
    [附源码]JAVA毕业设计教学辅助系统(系统+LW)
    【vue】Vue项目中如何在父组件中直接调用子组件的方法
    【工作中用到的功能-windows篇】自用备忘
    [山东科技大学OJ]1382 Problem A: 编写函数:三个数的最大最小值 (Append Code)
  • 原文地址:https://www.cnblogs.com/ggtc/p/18273658