Seite 1 von 1
Lightweight Effects Framework
Verfasst: 25.09.2012, 17:29
von CodingCat
Ich denke darüber nach, einen leichtgewichtigen Loader für das D3D11 Effect Format zu schreiben. Das originale Effects11 scheint mir nicht mehr weiterentwickelt zu werden und hat mir auch zu viele Schwächen. Dennoch habe ich meine States gerne direkt in den Shader Sources, genau wie die Zusammenschaltung von Shaders in Techniques/Passes. Außerdem bin ich, wie inzwischen vermutlich bekannt, intensiver Nutzer von Annotations, auf welche die Standard-D3D11-Reflections-API leider ebenfalls keinen Zugriff gibt. Die Idee ist also, eine minimale Reflection-API zu schreiben, die die Standard-D3D11-Reflection-API um Dinge wie Annotations, Techniques und Passes ergänzt und die Erzeugung von Shader- und State-Gruppen anhand deren Gruppierung in Passes erlaubt. Im Gegensatz zum Effects11-Framework soll es dagegen keine aufgeblasene Laufzeitkomponente geben, die einen zustandsbehafteten Benutzungsmodus vorschreibt, wie z.B. das lästige Überschreiben bereits gebundener Ressourcen mit anderen veralteten Ressourcen in Effects etc.
Wie verwaltet ihr eure Shader- und State-Gruppen? Bestünde bei anderen ebenfalls Interesse an so einer Bibliothek?
Re: Lightweight Effects Framework
Verfasst: 26.09.2012, 15:45
von Schrompf
Meine Erkenntnisse dazu sind leider noch auf dem Niveau von DX9, daher kann ich hier nix beitragen. Ich habe in der Engine aber die verschiedenen Passes eines Effekts auseinandergerissen, um sie für bessere Performance zusammen mit allen anderen DrawCalls sortieren zu können. Ein Effect Framework jeder beliebigen Art müsste das meiner Meinung nach unterstützen.
Re: Lightweight Effects Framework
Verfasst: 26.09.2012, 15:57
von CodingCat
Ja, die Idee ist genau, überhaupt nichts vorzuschreiben, sondern einfach nur alles strukturiert in den Speicher zu bekommen. Quasi wie Assimp, nur für Effect Files. Weil zur Laufzeit eh jeder sein eigenes System hat, halte ich das originale Effects9/11 Framework im professionellen Einsatz für absolut ungeeignet. Nicht nur kommt man nur an einen Bruchteil der vorhandenen Informationen ran, die Laufzeitkomponente schreibt einem auch noch absolut abstruse Benutzungsmuster vor und hält haufenweise nutzlosen Speicher im Hintergrund.
Ob ich selbst eine minimale Laufzeitkomponente anbieten werde, weiß ich noch nicht. Der wichtigste Teil ist für mich erstmal die vollständige Kontrolle zur Ladezeit.
DirectX 9 Effects haben wie es aussieht ein vollkommen anderes Format, weshalb ich mich leider auf DX10 aufwärts beschränke.
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 10:18
von kimmi
Provokante Frage, ich weiß, aber: Wenn du dich auf eine API und dementsprechend eine Plattform beschränkst: wo liegt der Vorteil deines Tools für einen Anwender wie zum Beispiel mich? Ich erfoffe mir vn einem Tool ja gerade, dass es diese Fragestellungen, die du ausklammern möchtest, umschifft und trotzdem eine gute Anwendbarkeit anbietet.
Gruß Kimmi
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 10:35
von CodingCat
kimmi hat geschrieben:Provokante Frage, ich weiß, aber: Wenn du dich auf eine API und dementsprechend eine Plattform beschränkst: wo liegt der Vorteil deines Tools für einen Anwender wie zum Beispiel mich? Ich erfoffe mir vn einem Tool ja gerade, dass es diese Fragestellungen, die du ausklammern möchtest, umschifft und trotzdem eine gute Anwendbarkeit anbietet.
Gruß Kimmi
Ich nutze D3D11, und viele andere auch. Diese können damit Effects ohne den ganzen Overhead und Affentanz nutzen, der mit den originalen Effects11 einhergeht. Außerdem fügt sich meine Bibliothek mangels Abhängigkeiten zu D3DX problemlos in Direct3D 11.1 ein. Für alle anderen hat die Bibliothek logischerweise keinen Nutzen. Natürlich könnte man eine ähnliche Bibliothek für CgFX schreiben. Ich habe mir CgFX nicht näher angesehen, aber ich befürchte, es funktioniert erschreckend ähnlich zu den Effects11. Mein erster Gedanke war tatsächlich, diese Bibliothek nicht für D3D Effects, sondern für Cg Effects zu schreiben. Leider sieht es jedoch so aus, als seien die Cg Effects gnadenlos veraltet, keine Compute Shaders ...
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 11:14
von kimmi
Vielleicht gibt es eine Möglichkeit, so etwas für OpenGL4.0 mit einzubringen. Dann hätte Man Compute-Shader. Allerdings ist das nicht ohne, ich weiß.
Gruß Kimmi
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 11:47
von CodingCat
OpenGl 4.3 hat Compute Shaders, aber im CgFX Toolkit von NVIDIA fehlt davon bisher jede Spur.
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 12:01
von kimmi
Ops, glatt durcheinandergebracht. Danke für die Info.
Gruß Kim
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 19:24
von TDK
So eine Library wäre auf jeden Fall praktisch. Von daher: Lass dich nicht abhalten!
Re: Lightweight Effects Framework
Verfasst: 28.09.2012, 20:00
von CodingCat
OK, erste Alpha-Version ist online:
http://code.google.com/p/d3d-effects-lite/
Keine Abhängigkeit von D3DX, voll Windows SDK 8.0-kompatibel. Auch sonst möglichst wenige Abhängigkeiten, D3D11, WinAPI und ganz ganz wenig STL.
Unterstützt noch kein Geometry Shader Stream Out, das kommt aber noch. Dynamic Shader Linkage bleibt erstmal außen vor. Wie am
Quelltext unschwer zu erkennen, war es ein riesen Spaß. Der Wahnsinn, was in so einem Effekt alles gespeichert wird (und absolute Irrsinn,
wie es gespeichert wird).
Das Datenlayout findet sich hier. Alles unmittelbar lesbar und vollständig typisiert. Nicht von der COM-Style-Namensgebung abschrecken lassen,
am Ende des Headers findet sch ein schöneres C++-Interface.
Der gesamte Ladevorgang kommt meinerseits mit zwei Allokationen aus, von denen nur eine behalten wird. Die Direct3D-Shader-Reflection versaut diese Statistik vermutlich mit einigen zusätzlichen Allokationen, aber wen kümmert das auf dem PC schon. ;) Die Speicherfragmentierung sollte jedenfalls noch geringer sein als ohnehin schon in der originalen Effects11-Bibliothek.
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 02:47
von eXile
Kurze Frage: Machen UAVs im Vertex Shader irgendwelche Probleme in Verbindung mit dem Effect-Framework? Ich konnte diese Frage mir leider (noch) nicht mit dem Code wirklich beantworten, weil der wie Spaghetti-Code aussieht; das ist aber den zu Grunde liegenden Datenstrukturen geschuldet, nicht deinen Programmierfertigkeiten. ;)
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 02:52
von CodingCat
Sollten nicht. Interessanterweise wurde mit DirectX 11.1 kein Shader Model 5.1 eingeführt. Damit sieht DirectX 11.1 noch mehr wie ein hässlicher Hack aus, Byte Code der von DirectX 11.1 Gebrauch macht wird zur Laufzeit einfach akzeptiert sobald eine DirectX 11.1-Runtime darunterliegt. Da sowohl ich wie auch das originale Effects11 Framework einfach direkt diesen Byte Code laden, sollte alles von alleine gehen.
eXile hat geschrieben:Ich konnte diese Frage mir leider (noch) nicht mit dem Code wirklich beantworten, weil der wie Spaghetti-Code aussieht; das ist aber den zu Grunde liegenden Datenstrukturen geschuldet, nicht deinen Programmierfertigkeiten. ;)
Gegen die Effects11 Referenzimplementierung ist das alles absolut aufgeräumt und hochgradig lesbar. ;)
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 03:16
von eXile
Ja, die Antwort geht in die Richtung, wie ich es mir vorgestellt habe. Ich habe nur die Befürchtung, dass das Effect-Framework gar nicht mehr gepflegt wird, und man das dann mit Direct3D 12 wegschmeißen kann.
Ganz ehrlich gesagt,
riecht es förmlich danach: Keine Integration mehr in Direct3D;
alle Direct3D-Samples verzichten auf Effects; und, natürlich, die Bezeichnung als
Legacy Effects mitsamt Fußnoten (die auch nicht bei den übrigen Shader Targets angegeben sind).
Ich finde es voll knorke, dass du das runterimplementiert hast. Aber irgendwie sieht mir das nach einem sinkenden Schiff aus. Ich bleibe erstmal bei meinen reinen HLSL-Shadern mit Abermilliarden
#defines. :|
CodingCat hat geschrieben:Gegen die Effects11 Referenzimplementierung ist das alles absolut aufgeräumt und hochgradig lesbar. ;)
Gegenüber Effect11 ist auch Assembler hochgradig lesbar. :)
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 11:38
von CodingCat
Naja, ich sitze ja praktisch schon seit Jahren auf diesem Schiff. Aber selbst wenn Effects verschwinden, habe ich mit dieser Bibliothek jetzt reine Datenstrukturen, die ich notfalls auch mit meinem eigenen Effekt-Format füllen kann. Mit losen Shaders will ich mich heute wie zukünftig nicht rumärgern, insofern ist die Bibliothek für mich jetzt relativ zukunftssicher, sofern sich mit DirectX 12 nicht ALLES ändert (à la keine Shaders mehr ;)). Davon abgesehen sind wir noch nicht mal bei DirectX 11.1. Einige Jahre dürfte die Bibliothek also mindestens halten. Sollte sich in Zukunft tatsächlich alles ändern, dann sind lose Shader auch nicht rückwärtskompatibler. :)
Die Bezeichnung Legacy Effects ist dennoch bedrückend. Wäre schade, wenn sie Annotationen und Passes irgendwann aus dem Compiler nehmen, nur weil sie ihre eigene Implementierung so verkackt haben. Wenn es ganz schlimm kommt, muss ich wohl mit einem eigenen Parser ran. :-/
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 15:56
von CodingCat
So, habe mal einige meiner real-world Effect Files geladen und dabei noch etliche Bugs gefixt. Stream Out und Bind Points gehen nun auch. Außerdem gibt es eine
Mini-"Doku", die etwas lesbarer als der große API-Header sein sollte. Der nächste große Schritt wird jetzt, damit in meinen eigenen Projekten endlich das Effects11-Framework zu ersetzen.
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 18:52
von eXile
CodingCat hat geschrieben:Mit losen Shaders will ich mich heute wie zukünftig nicht rumärgern
Bei mir sieht es genau umgekehrt aus: Ich hatte nie Lust auf die Effects-Runtime, und jetzt, wo man das dank dir benutzen könnte, schaut mal einmal in die MSDN und sieht, dass plötzlich das Deprecation-Schwert über dem Zeugs schwebt. Ich weiß nicht, ob das ein kosmischer Witz sein soll, oder ob mich die Welt nur hasst. :(
Frage: Glaubst du, dass die Default-Initialisierungen richtig sind? Wenn ich beispielsweise mir den
CD3D11_SAMPLER_DESC( CD3D11_DEFAULT )-Konstruktor hier anschaue, dann steht da
MaxAnisotropy = 1, bei dir
MaxAnisotropy = 16. Allgemein ist die Suche nach
D3D11_NO_HELPERS in der D3D11.h diesbezüglich sehr aufschlussreich. :)
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 19:06
von CodingCat
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 19:15
von CodingCat
D3D11_DEFAULT_MAX_ANISOTROPY und D3D11_DEFAULT_BORDER_COLOR_COMPONENT stimmen mit der MSDN überein, nicht aber mit den Helper-Konstruktoren. Großartig! Wieso definieren die Headers überhaupt Konstanten für jeden Default-Wert, wenn die Konstruktoren in demselben Header diese nicht mal nutzen? :twisted:
Re: Lightweight Effects Framework
Verfasst: 29.09.2012, 19:19
von eXile
What the?! Dann ist das ein Fehler im D3D11.h-Header. Ich habe mal alle CD3D11_DEFAULTs überflogen: In der CD3D11_SAMPLER_DESC gibts die einzigen Unterschiede, und ich habe sie irgendwie zielsicher angesteuert. Der Wert aus der MSDN ergibt mehr Sinn: Er entspricht genau D3D11_REQ_MAXANISOTROPY. Der Konstruktor von CD3D11_SAMPLER_DESC ist damit einfach falsch, sie haben eine 6 vergessen hinzuschreiben.
Du bist mir eine Minute zuvorgekommen. ;)
Nachtrag: Was der „Texture: N/A“-Eintrag auf der Seite von
D3D11_SAMPLER_DESC überhaupt bedeuten soll, bleibt wohl auf ewig im Dunkeln.
Außerdem kann man die Seite von
D3D11_BLEND_DESC so verstehen, als ob nur
RenderTarget[0] initialisiert worden wäre, und
RenderTarget[1] bis
RenderTarget[7] genullt bleiben. Was auch Sinn ergäbe:
Dennoch initialisiert der
CD3D11_BLEND_DESC-Konstruktor diese; das ist also auch noch eine Abweichung.
Re: Lightweight Effects Framework
Verfasst: 30.09.2012, 10:10
von Krishty
eXile hat geschrieben:Nachtrag: Was der „Texture: N/A“-Eintrag […] überhaupt bedeuten soll, bleibt wohl auf ewig im Dunkeln.
I lol'd :D
Re: Lightweight Effects Framework
Verfasst: 30.09.2012, 11:57
von CodingCat
Früher (DirectX 9) mussten Texturen direkt an Sampler gebunden werden, daher dieser Eintrag. Echte Textur-Objekte kamen erst mit DirectX 10, zuvor waren Texturen und Sampler in HLSL dasselbe.
Re: Lightweight Effects Framework
Verfasst: 30.09.2012, 17:36
von capslock
CodingCat hat geschrieben:Wie verwaltet ihr eure Shader- und State-Gruppen?
Ich bin vor einiger Zeit von den D3DX11Effects auf ein eigenes System umgestiegen und habe es nicht bereut. Die Techniques und Definitionen im Shader-Code hört sich auf den ersten Blick gut an, haben bei mir aber ständig zu hässlichen und überladenen Effect Files geführt :mrgreen:. Die Wartung war dann eine Katastrophe.
Mein eigenes System wollte ich daher möglichst schlank halten. Ein Effect wird bei mir über eine Konfigurationsdatei (z.B. Json oder XML) definiert, die Shader und States für jeweils einen Pass definieren. Das hat die Vorteile, dass es API neutral ist und man es sauber auf höhere Ebene implementieren kann. Die low level Shader-Implementierung liefert dann die Buffers und Samplers eines Shaders per Reflection / program_query. Wenn man sowas wie Techniques mal bräuchte, könnte man einfach mehrere Passes verknüpfen.
Beispielsweise sieht ein Effect so aus:
Code: Alles auswählen
{
"Name" : "RenderTexture",
"Shaders" : {
"Pixel" : "RenderTexturePS",
"Vertex" : "RenderTextureVS"
},
"Samplers" : [
{
"Name" : "pointSampler",
"Filter" : "Point"
}
]
}
Gruß capslock
Re: Lightweight Effects Framework
Verfasst: 03.12.2012, 00:51
von CodingCat
Da es sich momentan ja etwas abzeichnet, dass die vorgefertigte Effects-Funktionalität im MS HLSL Compiler über kurz oder lang verschwinden wird, habe ich heute mal meinen funpl Parser-Prototypen von letztem Jahr ausgegraben und in mein Effects Lite Framework eingebaut. Momentan nutze ich zwar noch immer das MS Effects Framework, aber ich brauche dringend einen mächtigeren Präprozessor, der mir Effects ordentlich zusammenlinken kann. Mit reinen Includes kam ich zwar recht weit (das ganze Ray Tracing war nicht-destruktiv nur über Includes an die bestehende Engine-Funktionalität drangehängt), aber jetzt wo ich Instancing, prozedurale Animation etc. nutze, lässt sich mit dem Standardpräprozessor nicht mehr viel ausrichten.
Der Präprozessor, den ich heute implementiert habe, ist an Scala Traits angelehnt. Im Wesentlichen baut er eine linearisierte Vererbungshierarchie auf. Effect Files können (virtuelle) Hook-Funktionen definieren, die einerseits von abgeleiteten Effects überschrieben werden können, und andererseits selbst die Hook-Funktionen der Basis-Effects aufrufen dürfen. Weiterhin können Effect Files unsichtbare benannte Geltungsbereiche definieren, die erst anschließend per Namen in abgeleiteten Effect Files eingefügt werden, dort landen dann alle gleichnamigen Bereiche aller eingebundenen Effect Files, konkateniert in der Einbindungsreihenfolge. Zudem können Effect Files die globale Konfiguration klassisch durch Makros beeinflussen, auch hier werden die Konfigurationsbereiche aneinandergehängt und landen am Ende als Preambel vor dem fertig gelinkten Effect.
Ein Transformations-Hook lässt sich zum Beispiel so realisieren:
Code: Alles auswählen
// Basiseffekt Transform.fx, definiert einfache Transformation
struct TransformHookState
{
float4 WorldPos;
float3 WorldNormal;
float4 WVPPos;
};
float4 GetWorldPosition(TransformHookState s) { return s.WorldPos; }
float4 GetWVPPosition(TransformHookState s) { return s.WVPPos; }
float3 GetWorldNormal(TransformHookState s) { return s.WorldNormal; }
// _HOOKED ist gesetzt, wenn dieser Effect als Hook eingebunden wurde (im Gegensatz zu Standard-#include)
#ifdef _HOOKED
// Konfiguriere Headers zum Einbinden der richtigen Matrizen (World, WorldInverse, WorldViewProj)
#hookconfig
{
#redefine BE_RENDERABLE_INCLUDE_WORLD
#redefine BE_RENDERABLE_INCLUDE_PROJ
}
#include <Engine/Perspective.fx>
#include <Engine/Renderable.fx>
TransformHookState DefaultTransformHook(float4 pos, float3 normal)
{
TransformHookState state;
state.WorldPos = mul(pos, World);
state.WorldNormal = normalize( mul((float3x3) WorldInverse, normal) );
state.WVPPos = mul(pos, WorldViewProj);
return state;
}
// Definiere virtuelle Hook-Funktion "Transform" mit Zustandstyp TransformHookState,
// kann in abgeleitetem Effekt per '#hookcall Transform(vertex)' aufgerufen werden
#hookfun Transform(vertex) -> TransformHookState = DefaultTransformHook(vertex.Position, vertex.Normal)
#endif
Code: Alles auswählen
// Prozedurale Windanimation
// Definiert zusätzliche Konstanten zur Steuerung der Windanimation,
// können in abgeleitetem Effekt per '#hookinsert SetupConstants' eingebunden werden
#hookdef SetupConstants
{
float AnchorHeight
<
String UIName = "Anchor Height";
> = 10.0f;
float FreeHeight
<
String UIName = "Free Height";
> = 0.0f;
float3 Amplitude
<
String UIName = "Amplitude";
> = 0.0f;
}
// Konfiguriere Headers zum Einbinden der richtigen Matrizen (World, WorldInverse, WorldViewProj)
#hookconfig
{
#redefine BE_RENDERABLE_INCLUDE_WORLD
#redefine BE_RENDERABLE_INCLUDE_PROJ
}
#include <Engine/Perspective.fx>
#include <Engine/Renderable.fx>
// Bindet nur den nicht-_HOOKED-Teil ein, um die dort definierten Strukturen/Funktionen wiederzuverwenden
#include <Hooks/Transform.fx>
[...]
// '#hookstate Transform' liefert dynamisch gebundenen Zustandstyp der Transform-Hook-Implementierung des Basis-Effects
TransformHookState WindTransform(#hookstate Transform baseState)
{
TransformHookState state;
float4 basePos = GetWorldPosition(baseState);
float3 baseNormal = GetWorldNormal(baseState);
state.WorldPos = float4(WindPerturbWorldPosition(basePos.xyz), basePos.w);
state.WorldNormal = normalize( WindPerturbWorldNormal(baseNormal, basePos.y) );
state.WVPPos = mul(state.WorldPos, Perspective.ViewProj);
return state;
}
// Überschreibt virtuelle Hook-Funktion "Transform" mit Zustandstyp TransformHookState,
// ruft Basis-Effect mit #hookcall Transform(vertex) auf,
// kann in abgeleitetem Effekt per '#hookcall Transform(vertex)' aufgerufen werden
#hookfun Transform(vertex) -> TransformHookState = WindTransform(#hookcall Transform(vertex))
Man beachte, dass auch der Zustandstyp der Hook-Funktionen virtuell ist, also überschrieben werden kann. Damit funktioniert die restliche polymorphie ganz ohne hässliche Präprozessormagie mit Standard-Überladungsauflösung.
Code: Alles auswählen
// Normaler Material-Effect, der nun mit beliebigen Hooks manipuliert werden kann
#include <Engine/Perspective.fx>
#include <Engine/Renderable.fx>
#include <Pipelines/LPR/Geometry.fx>
// Bindet IMMER "Transform.fx" als Basiseffekt ein, um auch ohne zusätzliche Hooks Standard-Funktionalität zu haben
#hookincl "Hooks/Transform.fx"
// Bindet beliebig viele weitere, zur Compile-Zeit gegebene Hook-Effect-Files ein, in unserem Beispiel "Wind.fx"
#hookincl ...
cbuffer SetupConstants
{
float4 DiffuseColor
<
String UIName = "Diffuse";
String UIWidget = "Color";
> = float4(1.0f, 1.0f, 1.0f, 0.0f);
float4 SpecularColor
<
String UIName = "Specular";
String UIWidget = "Color";
> = float4(0.0f, 0.0f, 0.0f, 0.1f);
float2 TextureRepeat
<
String UIName = "Texture Repeat";
> = float2(1.0f, 1.0f);
// Fügt nacheinander alle per '#hookdef SetupConstants' definierten Bereiche ein, in diesem Beispiel den aus "Wind.fx",
// so landen in diesem Constant Buffer auch alle Wind-Konstanten
#hookinsert SetupConstants
}
[...]
Pixel VSMain(Vertex v)
{
// Ruft zuletzt definierte Hook-Funktion auf, in diesem Beispiel die aus "Wind.fx", und speichert deren
// Zustand in 'transformState' (Kurzschreibweise für: '#hookstate Transform transformState = #hookcall Transform(v)')
// Transform() in "Wind.fx" gibt dann teilweise weiter an überschriebenen Hook aus "Transform.fx", siehe oben
#hookcall transformState = Transform(v);
Pixel o;
o.Position = GetWVPPosition(transformState);
[...]
return o;
}
[...]
// Teile Standardfunktionalität mit anderen Effects (= binde vorkompilierte Effects ein)
technique11 <
string IncludeEffect = "Prototypes/Shadow.fx";
// Präprozessor liefert Array mit zur Compilezeit angegebenen Hook Files, i.d.Bsp. { "Wind.fx" }
string IncludeHooks[] = #hookarray;
> { }
Entstehender Quelltext:
Code: Alles auswählen
#define _HOOKED
#ifndef BE_RENDERABLE_INCLUDE_WORLD
#define BE_RENDERABLE_INCLUDE_WORLD
#endif
#ifndef BE_RENDERABLE_INCLUDE_PROJ
#define BE_RENDERABLE_INCLUDE_PROJ
#endif
#undef _HOOKED
#include <Engine/Perspective.fx>
#define _HOOKED
#undef _HOOKED
#include <Engine/Renderable.fx>
#define _HOOKED
#undef _HOOKED
#include <Pipelines/LPR/Geometry.fx>
#define _HOOKED
#ifndef BE_HOOK_TRANSFORM
#define BE_HOOK_TRANSFORM
struct TransformHookState
{
float4 WorldPos;
float3 WorldNormal;
float4 WVPPos;
};
float4 GetWorldPosition(TransformHookState s) { return s.WorldPos; }
float4 GetWVPPosition(TransformHookState s) { return s.WVPPos; }
float3 GetWorldNormal(TransformHookState s) { return s.WorldNormal; }
#ifdef _HOOKED
#undef _HOOKED
#include <Engine/Perspective.fx>
#define _HOOKED
#undef _HOOKED
#include <Engine/Renderable.fx>
#define _HOOKED
TransformHookState DefaultTransformHook(float4 pos, float3 normal)
{
TransformHookState state;
state.WorldPos = mul(pos, World);
state.WorldNormal = normalize( mul((float3x3) WorldInverse, normal) );
state.WVPPos = mul(pos, WorldViewProj);
return state;
}
#define Transform__HOOKFUN1(vertex) DefaultTransformHook(vertex.Position, vertex.Normal)
#endif
#endif
#undef _HOOKED
#include <Engine/Perspective.fx>
#define _HOOKED
#undef _HOOKED
#include <Engine/Renderable.fx>
#define _HOOKED
#undef _HOOKED
#include <Hooks/Transform.fx>
#define _HOOKED
[...]
TransformHookState WindTransform(TransformHookState baseState)
{
TransformHookState state;
float4 basePos = GetWorldPosition(baseState);
float3 baseNormal = GetWorldNormal(baseState);
state.WorldPos = float4(WindPerturbWorldPosition(basePos.xyz), basePos.w);
state.WorldNormal = normalize( WindPerturbWorldNormal(baseNormal, basePos.y) );
state.WVPPos = mul(state.WorldPos, Perspective.ViewProj);
return state;
}
#define Transform__HOOKFUN2(vertex) WindTransform(Transform__HOOKFUN1(vertex))
cbuffer SetupConstants
{
float4 DiffuseColor
<
String UIName = "Diffuse";
String UIWidget = "Color";
> = float4(1.0f, 1.0f, 1.0f, 0.0f);
float4 SpecularColor
<
String UIName = "Specular";
String UIWidget = "Color";
> = float4(0.0f, 0.0f, 0.0f, 0.1f);
float2 TextureRepeat
<
String UIName = "Texture Repeat";
> = float2(1.0f, 1.0f);
float AnchorHeight
<
String UIName = "Anchor Height";
> = 10.0f;
float FreeHeight
<
String UIName = "Free Height";
> = 0.0f;
float3 Amplitude
<
String UIName = "Amplitude";
> = 0.0f;
}
[...]
Pixel VSMain(Vertex v)
{
Pixel o;
TransformHookState transformState = Transform__HOOKFUN2(v);
o.Position = GetWVPPosition(transformState);
o.NormalDepth.xyz = GetWorldNormal(transformState);
o.NormalDepth.w = o.Position.w;
o.TexCoord = v.TexCoord * TextureRepeat;
IF_NORMALMAP(
o.Tangent.xyz = mul(v.Tangent, (float3x3) World);
// Extract handedness
o.Tangent.w = sign(dot(v.Tangent, v.Tangent) - 0.5f);
)
IF_OBJECTNORMAL(
o.ObjectNormal = normalize( mul((float3x3) WorldInverse, v.ObjectNormal) );
)
return o;
}
[...]
technique11 Geometry <
string PipelineStage = "GeometryPipelineStage";
string RenderQueue = "DefaultRenderQueue";
>
{
pass
{
SetVertexShader( CompileShader(vs_4_0, VSMain()) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader(ps_4_0, PSGeometry()) );
}
}
technique11 <
string IncludeEffect = "Prototypes/Shadow.fx";
string IncludeHooks[] = { "Modifiers/Wind.fx" };
> { }
technique11 <
string IncludeEffect = "Prototypes/Feedback.fx";
string IncludeHooks[] = { "Modifiers/Wind.fx" };
> { }
Re: Lightweight Effects Framework
Verfasst: 03.12.2012, 00:54
von CodingCat
Code ist wie immer
online, insbesondere ist der Code unabhängig von irgendeinem Shader-/Effects-Format, es handelt sich vielmehr um einen praktisch sprachunabhängigen Präprozessor vor dem Präprozessor.