#define in GLSL möglich?
-
Hi Leute!
Ich plane gerade an einem Material-Generator. Dem werden Parameter übergeben, anhand dessen er dann einen Shader (Material) erstellt. Soweit bin ich mit der Planung durch, es fehlt nurnoch eine Sache. Ich hatte erst geplant, das ich mehrere Teile des GLSL Codes in verschiedenen Dateien ablege, und diese dann vom Framework, jenachdem welche Parameter übergeben werden, zusammen schustert. Jedoch finde ich dies nun ein wenig inefizient, da dies sehr schnell in 100then von Dateien enden würde. Nun habe ich bei jemanden gesehen, das er #define im GLSL Code benutzt, die man wohl zur Laufzeit vom c++ Programm um-definenen kann.
Nun Frage ich mich jedoch wie ich das mit opengl machen kann?
-
Code-Walker schrieb:
Jedoch finde ich dies nun ein wenig inefizient, da dies sehr schnell in 100then von Dateien enden würde. Nun habe ich bei jemanden gesehen, das er #define im GLSL Code benutzt, die man wohl zur Laufzeit vom c++ Programm um-definenen kann.
Du scheinst ein generelles Design-Problem zu haben
#define und "zur Laufzeit" wiedersprechen sich ein wenig. Bevor du einen Shader erstellst, musst du diesen ja compilieren. Dies ist z.B. möglich, indem du die entsprechende Methode von OpenGL mit einem String aufrufst. Der String beinhaltet den Quellcode des Shaders. Jetzt kannst du zur Laufzeit den String aus mehreren Teilstücken zusammen schustern. Fertig.
Oder du erstellst eine Quelldatei, in der du "define" benutzt und beim compilieren des Shaders entsprechende Konstanten angibst.
Siehe http://www.opengl.org/documentation/glsl/ Seite 14
Die Spezifikation kannst du selbst lesen.Thomas
-
Auf die Sache mit dem zusammen schustern aus mehreren Strings bin ich auch inzwischen gekommen, aber nun stelle ich mir die Frage, ob es denn überhaupt sin macht, eine Art Shader Generator zu basteln?
Ich hatte mir das im moment etwa so gedacht, das ich ein Model lade, beispielsweise 3DS oder ähnliches, und dann anhand des Materials aus der Datei ein passenden Shader dazu generieren lasse. Dabei gebe ich dann einfach ein paar Parameter an den Generator:
// Setting the lightmodel for this entrie. RenderEntrie.Material.Lightmodel.Type = AveMaterialLightmodelType.Phong; RenderEntrie.Material.Lightmodel.Diffuse = true; RenderEntrie.Material.Lightmodel.Ambient = true; RenderEntrie.Material.Lightmodel.Specular = true; // Setting the used textures for this entrie. RenderEntrie.Material.Normalmap = false; RenderEntrie.Material.Lightmap = true; RenderEntrie.Material.Layermap = true; RenderEntrie.Material.Layer[0] = true; RenderEntrie.Material.Layer[1] = true; RenderEntrie.Material.Layer[2] = false; RenderEntrie.Material.Layer[3] = false;
-
du machst dir zuviel arbeit.
wenn du ein material laedst und parameter sind 0, z.b. fuer ambient und specular, und irgendwo in deinem shader steht danncolor=ambient+diffuse*intensity+specular*pow(intensity,specularpower);
wird das resultat das selbe sein wie nur diffuse*intensity und wenn der compiler smart ist (wovon du ausgehen darfst), wird er auch alle mathematisch wertlosen dinge rausoptimieren.
das selbe gilt fuer ifs, statt also defines zu nutzen (wieso fragst du hier eigentlich, dauert es nicht nur 1min das selbst zu testen? :P), kannst du einfach richtige ifs und statische globale constants/variables nutzen, das resultat ist sogar noch besser als mit defines, da der compiler den ganzen code evaluiert und fehler meldet die defines verstecken wuerden.
-
Die Frage wäre dann aber wohl die, ob man sich darauf verlassen kann, dass der compiler diese raus optimiert.
-
wenn der compiler smart ist, wird er auch alle mathematisch wertlosen dinge rausoptimieren.
Oft ergeben sich "mathematisch wertlosen dinge" aus dynamischen Parametern.
Dann ist es sinnvoll einen "Header" zu erzeugen um Shaderteile zur Compilezeit zu disablen, zB:#define USEAMBIENT 1 #define USESPECULAR 1 #define USEBUMP 0
void main() { if (USEAMBIENT) { ... } if (USESPECULAR) { ... } if (USEBUMP) { ... } gl_FragColor = ... }