SharpDX编译着色器

时间:2017-08-04 16:12:55

标签: c# directx shader sharpdx

如何在SharpDX中的构建时编译顶点和像素着色器?您可以在“Direct3D Rendering Cookbook”中阅读的方法是使用HLSLCompiler.CompileFromFile。这将在运行时编译着色器,这并不总是好的。

2 个答案:

答案 0 :(得分:2)

在最新的SharpDX 4中你可以在运行时编译像素和顶点着色器,问题是,大多数(未更新的)Windows 7都没有D3DCompiler_47.dll,它不允许你甚至运行SharpDX( SharpDX.D3DCompiler将无法使用)。最好使用DirectX SDK中的fxc在构建时编译着色器,如下所示:

ComplieShaders.bat(这个bat文件我作为项目的一部分,我在构建应用程序时调用它):

Echo Building shaders
Echo Launch dir: "%~dp0"
Echo Current dir: "%CD%"
cd "%~dp0"
PATH="c:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\bin\x86\"
fxc /T vs_5_0 /E VSMain "Laser.hlsl" /Fo "MyVS.cso"
fxc /T ps_5_0 /E PSMain "Laser.hlsl" /Fo "MyPS.cso"

奇怪的CD“%~dp0”将移动到正确的目录。我从预构建事件命令行调用此bat文件(在C#项目设置中 - >构建事件)。

这将生成二进制着色器数据,如MyVS.cso(用于顶点着色器)和MyPS.cso(用于像素着色器)。 这两个文件我再次作为内容插入到C#项目中。

然后你可以在C#中使用这两个文件:

    string shaderFile = @"SomeDirectoryInYourApp\Shaders\MyVS.cso";
    if (!Path.IsPathRooted(shaderFile))
    {
         shaderFile = Path.Combine(System.IO.Path.GetDirectoryName(
             System.Reflection.Assembly.GetEntryAssembly().Location),
        shaderFile);
    }

    using (var shaderCodeReader = new System.IO.StreamReader(shaderFile))
    {
        vertexShaderBytecode = ToDispose(ShaderBytecode.FromStream(
            shaderCodeReader.BaseStream));
    }

    vertexShader = ToDispose(new VertexShader(device, vertexShaderBytecode));

如果您在C#应用程序中找到MyVS.cso文件时遇到问题,可以使用assembly.GetManifestResourceNames()获取程序集中所有可用内容文件的列表(带完整路径)。

答案 1 :(得分:1)

我发现,上面的方式不适合部署。问题是,内容文件位于exe或dll之外,所以我宁愿将它们用作“嵌入式资源” - 这样cso文件就嵌入在程序集(dll或exe)中。要加载嵌入式资源的流,请使用:

protected SharpDX.D3DCompiler.ShaderBytecode LoadShaderFromManifestResourceFile(
            System.Reflection.Assembly assembly, string resourceName)
    {
        SharpDX.D3DCompiler.ShaderBytecode shaderBytecode = null;

        using (var shaderCodeReader = assembly.GetManifestResourceStream(resourceName))
        {
            shaderBytecode = ToDispose(ShaderBytecode.FromStream(shaderCodeReader));
        }

        return shaderBytecode;
    }

要获取资源路径/标识符(可能很长),您可以使用:

var assembly = Assembly.GetExecutingAssembly();
string[] resources = assembly.GetManifestResourceNames();