2017-08-04 4 views
2

Wie kompilieren Sie Vertex- und Pixelshader zum Zeitpunkt der Erstellung in SharpDX? Die Art, wie Sie in "Direct3D Rendering Cookbook" lesen können, besteht darin, HLSLCompiler.CompileFromFile zu verwenden. Dies wird Shader zur Laufzeit kompilieren, was nicht immer gut ist.SharpDX Kompilieren von Shadern

Antwort

2

In neuesten SharpDX 4 können Sie Pixel-und Vertex-Shader zur Laufzeit kompilieren, das Problem ist, haben die meisten der (nicht aktualisiert) Windows 7 nicht D3DCompiler_47.dll, die Sie nicht einmal die SharpDX ausführen können (SharpDX.D3DCompiler ist nicht verfügbar). Es ist besser, fxc von DirectX SDK verwenden Shadern zur Buildzeit zu kompilieren wie folgt:

ComplieShaders.bat (diese Fledermaus-Datei ich als Teil des Projekts haben und ich es nennen, wenn app Gebäude):

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" 

Die seltsame CD "% ~ dp0" wird in das richtige Verzeichnis verschoben. Diese Bat-Datei rufe ich von der Pre-Build-Ereignis-Befehlszeile auf (in C# -Projekteinstellungen -> Build-Ereignisse).

Dadurch werden binäre Shader-Daten wie MyVS.cso (für Vertex-Shader) und MyPS.cso (für Pixel-Shader) erzeugt. Diese beiden Dateien füge ich wieder als Inhalt in C# -Projekt ein.

Dann können Sie beide Dateien in C# verwenden:

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

Wenn Sie Problem haben, Ihre MyVS.cso Datei in Ihrem C# app haben, können Sie assembly.GetManifestResourceNames() verwenden, Liste aller verfügbaren Inhalte zu erhalten Dateien in Assembly (mit vollständigem Pfad).

1

Nun, ich fand heraus, der obige Weg ist nicht so gut für den Einsatz. Das Problem ist, dass Inhaltsdateien außerhalb von exe oder dll liegen, also verwende ich sie lieber als "Eingebettete Ressource" - auf diese Weise werden die cso-Dateien in Assembly (dll oder exe) eingebettet. Um den Stream für eingebettete Ressourcen Gebrauch zu laden:

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; 
    } 

Um den Ressourcenpfad/Kennung zu erhalten (es kann ziemlich lang sein) können Sie:

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