2017-08-04 98 views
2

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

回答

2

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

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" 

奇怪的光盘“%〜dp0”将移动到正确的目录。这是我从Pre-build事件命令行调用的bat文件(在C#项目设置 - > Build Events中)。

这将生成二进制着色器数据,如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)); 

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

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();