2017-08-04 96 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();