C# SharpDX编译着色器

C# SharpDX编译着色器,c#,directx,shader,sharpdx,C#,Directx,Shader,Sharpdx,如何在构建时在SharpDX中编译顶点和像素着色器?在“Direct3D渲染食谱”中可以阅读的方法是使用HLSLCompiler.CompileFromFile。这将在运行时编译着色器,这并不总是好的。在最新的SharpDX 4中,您可以在运行时编译像素和顶点着色器,问题是,大多数(未更新)Windows 7没有D3DCompiler_47.dll,这甚至不允许您运行SharpDX(SharpDX.D3DCompiler将不可用)。最好在构建时使用DirectX SDK中的fxc编译着色器,如下

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

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

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

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

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

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


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

我发现,上述方法不适合部署。问题是,内容文件位于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();
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();