Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 17.02.2008, 22:30 Titel: Beliebig viele Lichtquellen über Shader implementieren |
|
|
Ich möchte ein Shaderprogramm schreiben, dass eine beliebige Menge an Lichtquellen verarbeiten kann (im Rahmen der Gesamtzahl der Instruktionen der jeweiligen Shaderversion )
Zunächst suche eine Möglichkeit eine Anzahl der Lichtquellen zu übergeben. Die Anzahl möchte ich u.a. als Arraygröße von 3 verschiedenen Attributen der Lichtquellen übergeben:
Code: | //Punktlichtquelle
const int LightNumber = 3;
float3 LightPosition[LightNumber];
float4 LightColor[LightNumber];
float LightRange[LightNumber]; |
Hinterher sollen im Vertexshader die diffusen und specularen Lichtanteile der Lichtquellen addiert werden:
Code: | //int index = 0;
for(int index = 0; index < LightNumber; index++)
{
...
Out.AmbDiff += Diffuse;
Out.Specular += Specular;
} |
Leider nimmt ein Shaderprogramm anscheinend nur Zahlen und keine variablen oder Konstanten an, wenn ich diese an Arrayinitialisierungen übergeben möchte.
Wie kann man dieses Problem lösen? _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 18.02.2008, 06:52 Titel: |
|
|
Ich erledige das so das ich mit Callbacks arbeite, per Standard nutze ich keine Callbacks so ds jeder pass nur ein einziges mal gerendert wird. Mit Callbacks erweitere ich das ganze so das ich als Returnvalue des Callbacks 3 Möglichkeiten habe:
- Renderer nur ein einziges mal
- Rendere, aber rufe den Callback danach nochmal auf
- Rendere den Pass überhaupt nicht
Ein Callback könnte dann zB so aussehen:
CPP: | ReturnValue Callback(Shader* myShader, Scene* myScene, Object* myObject)
{
static int currentLight = -1;
currentLight++;
if (currentLight < myScene->get_VisibleLightsForObject(myObject).size())
{
myShader->SetUpLightData(myScene->get_VisibleLightsForObject(myObject)[currentLight]);
if (currentLight+1 == myScene->get_VisibleLightsForObject(myObject).size())
{
currentLight = -1;
return RenderOnce;
}
return RenderAgain
}
return DontRender;
}
|
Ob ein Pass ein Callback nutzten soll bzw welchen kannst du per Annotations festlegen (siehe Doku) _________________ "I have a Core2Quad at 3.2GHz, 4GB of RAM at 1066 and an Nvidia 8800 GTS 512 on Vista64 and this game runs like ass whereas everything else I own runs like melted butter over a smokin' hot 18 year old catholic schoolgirl's arse." |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 18.02.2008, 16:43 Titel: |
|
|
Kannst du dein Konstrukt etwas näher erläutern? Ich weiß gerade mal so ungefähr, was ein Callback ist, habe aber vorher noch nicht damit gearbeitet.
Ist deine Beispielfunktion jetzt die Funktion, die als Callback aufgerufen werden soll oder eine, die einen Callback benutzt?
Diese Lichtquellen-Iteration versteh ich auch nicht, weil mir nicht klar ist, was die einzelnen Zeilen für Aufgaben haben. _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 18.02.2008, 21:18 Titel: |
|
|
Ahh ich sehe das ich wirklich eineMenge unerwähnt habe lassen. nagut.
Unter diesen Callbacks [siehe oben] verstehe ich eine Funktion die vor dem rendern eines Shader Passes aufgerufen wird. Diese Callbacks können mir 2 Dinge:
1. Mir sagen ob der Pass gerendert werden soll und ob der Pass sogar mehr als einmal gerendert werden soll (RenderOnce - nur 1x rendern oder RenderAgain - 1x rendern und danach den Callback nochmal aufrufen)
2. Wichtige Parameter setzen die für den ShaderPass wichtig sind. Im Falle eines PhongShaders der grade den Pass für die Diffuse Beleuchtung abarbeitet dürften die Parameter wie Position des Liches, Richtung, Leuchtfarbe, etc wichtig sein, dies sollte der Callback setzen wenn denn der Pass gerendert werden soll.
Der Callback kann also durch Punkt1 mehrfach aufgerufen werden wodurch man zum Beispiel alle relevanten Lichter abarbeiten kann.
Zu den Annotations:
Annotations sind nur zusätzliche Beschreibungen für ein Wert im Shader, diese Beschreibung werden nicht vom Shader selbst gebaucht, aber die Anwendung selbst ann diese auslesen und so den Shader zusätzlich erweitern. Im Callback Fall von eben könnte zB die Annotation so aussehen:
Code: | pass DiffusePass
<
string CallbackName = "DiffusePassCallback";
>
{
VertexShader = ...;
PixelShader = ...;
} |
in deiner Anwendung selber müsstest du dann einen Callback unter dem Namen "DiffusePassCallback" irgendwo handhaben. Das auslesen der Annotations musst du dir aber selbst erarbeiten wenn du es denn so machen wolltest. |
|
Nach oben |
|
|
LeeDiGer Super JLI'ler
Anmeldedatum: 31.08.2003 Beiträge: 366 Wohnort: Duisburg Medaillen: Keine
|
Verfasst am: 18.02.2008, 22:20 Titel: |
|
|
Ok, ich glaub versteh deinen Ansatz jetzt einigermaßen. Aber ist das Render über mehrere Passes nicht aufwändiger?
Man hat zwar den Vorteil, dass man nicht mehr so die Probleme mit der Einschränkung der maximalen Anzahl der Instruktionen, aber es wird doch bei jedem Pass wieder jeder Vertex bzw. Pixel neu aufgewühlt....würde doch heißen, dass man Pro Lichtquelle quasi die Rechenzeit für einen kompletten Rendervorgang des ganzen Objektes hätte, oder seh ich das falsch?
Was für ein Rechner hast du und wieviele Lichtquellen kannst du denn in etwa in deine Engine einbauen und dabei noch genug Frames pro Sekunde gewährleisten? _________________ Kein Rückzug! Kein Aufgeben! |
|
Nach oben |
|
|
Fallen JLI MVP
Alter: 40 Anmeldedatum: 08.03.2003 Beiträge: 2860 Wohnort: Münster Medaillen: 1 (mehr...)
|
Verfasst am: 19.02.2008, 06:41 Titel: |
|
|
Klar kostet das jedes mal ordentlich Rechenleistung, wenn möglich sollte man auch versuchen für jede Situation einen Shader parat zu haben, also 1 PointLight+1SpotLight, nur 1 Spotlight, 2 PointLights, etc. Diese sollten dann in so wenig Passes wie möglich abgearbeitet werden.
Dieser Ansatz ist allerdings etwas stoisch und erfordert das man eben für die Situation einen Shader hat, sowas kann man allerdings vorgenerieren und schränkt die mögliche Anzahl an Lichtquellen drastisch ein da man sehr stark am Instruktioncount eines Passes gebunden wird.
Interessant dürfte d auch Deffered Shading sein, hier kann man sehr viele Lichtquellen benutzten und pro lichtquelle muss nur 1 Screen Quad gerendert werden anstatt jedes mal alle beleuchteten Objekte komplett zu rendern. |
|
Nach oben |
|
|
|