Lightweight Effects Framework

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Lightweight Effects Framework

Beitrag 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?
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 4884
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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 ...
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag von CodingCat »

OpenGl 4.3 hat Compute Shaders, aber im CgFX Toolkit von NVIDIA fehlt davon bisher jede Spur.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag von kimmi »

Ops, glatt durcheinandergebracht. Danke für die Info.

Gruß Kim
TDK
Beiträge: 54
Registriert: 06.04.2012, 11:15

Re: Lightweight Effects Framework

Beitrag von TDK »

So eine Library wäre auf jeden Fall praktisch. Von daher: Lass dich nicht abhalten!
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Lightweight Effects Framework

Beitrag 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. ;)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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. ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Lightweight Effects Framework

Beitrag 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. :)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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. :-/
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Lightweight Effects Framework

Beitrag 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. :)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag von CodingCat »

Hm, ich habe die Default Values der MSDN entnommen: http://msdn.microsoft.com/en-us/library ... s.85).aspx
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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:
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
eXile
Establishment
Beiträge: 1136
Registriert: 28.02.2009, 13:27

Re: Lightweight Effects Framework

Beitrag 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:
http://msdn.microsoft.com/en-us/library/windows/desktop/ff476087 hat geschrieben:IndependentBlendEnable: If set to FALSE, only the RenderTarget[0] members are used; RenderTarget[1..7] are ignored.
Dennoch initialisiert der CD3D11_BLEND_DESC-Konstruktor diese; das ist also auch noch eine Abweichung.
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
capslock
Beiträge: 8
Registriert: 11.04.2012, 12:17

Re: Lightweight Effects Framework

Beitrag 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
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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" };
> { }
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Lightweight Effects Framework

Beitrag 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.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Antworten