I
Hallo zusammen
Ich bin mit meinem neuen Beleuchtungsmodell ziemlich schnell an Grenzen gestossen und habe nun einige Fragen:
Frage 1:
--------
In der Doku: http://msdn.microsoft.com/en-us/library/bb147365(VS.85).aspx#Vertex_Shader_Model_3_Features steht klar, dass ab Version 3.0 sämtliche Input sowie auch Output Register mit Hilfe eines Schleifenzähler Registers indexiert (also indirekt adressiert) werden können. Wenn ich nun aber genau dies tue:
for(int i=0;i<cLight;++i) Out.aLight[i] = normalize(mul(mxTan,aLight[i].Dir));
kriege ich folgenden Fehler:
warning X3550: array reference cannot be used as an l-value; not natively addressable, forcing loop to unroll
Dieselbe Meldung kommt, wenn ich cLight durch einen numerischen Wert ersetze.
Frage 2:
--------
Ich verstehe nicht, wie er es unrollen will, da cLight zur Kompilezeit nicht bekannt ist und von Frame zu Frame ändern kann?
Frage 3:
--------
Ich habe zwar maximal 8 dynamische Lichtquellen, davon sind aber in einem Frame längstens nicht alle aktiv, denn die Lichter haben in meiner Engine ein Influenz Bounding Volume. Es könnte also sein, dass bei einem bestimmten Frame nur ein einziges Licht sichtbar sein würde. Ohne Schleife mit "dynamic branching" würde er aber dennoch sämtliche Lichter in den TangentSpace umrechnen, was nicht eben billig ist.
// transform all dynamic lights into tangent space
Out.Lg0 = normalize(mul(mxTan,aLgd[0].Dir));
Out.Lg1 = normalize(mul(mxTan,aLgd[1].Dir));
Out.Lg2 = normalize(mul(mxTan,aLgd[2].Dir));
Out.Lg3 = normalize(mul(mxTan,aLgd[3].Dir));
Out.Lg4 = normalize(mul(mxTan,aLgd[4].Dir));
Out.Lg5 = normalize(mul(mxTan,aLgd[5].Dir));
Out.Lg6 = normalize(mul(mxTan,aLgd[6].Dir));
Out.Lg7 = normalize(mul(mxTan,aLgd[7].Dir));
Frage 4:
--------
In einem Artikel auf Gamasutra "Messing with Tangent Space" habe ich auf Seite 2: http://www.gamasutra.com/view/feature/1515/messing_with_tangent_space.php?page=2 folgendes gelesen:
Instead of doing this, we declare the thousands of surface normals in the tangent space coordinate system. Then we just need to transform the other objects (mostly consisting of lights, the camera, etc) to the same tangent space coordinate system and do our calculations there. The count of these objects won’t exceed 10 in most cases.
So it’s 1000000s vs 10s of calculations. Hmmm… It’s going to take a while to decide which one would be better.
Also das ist doch IMHO völliger Schwachsinn, tatsächlich muss man nämlich alle 10 Lichter "FÜR JEDEN VERTEX" in den Tangentspace umrechnen. Also wenn schon, dann 10 mal ein paar Millionen Vertices, und schon sind wir bei 1000000 vs. 1000000. Zusätzlich werden Vertices IMHO erst NACH der Transformation (Vertex Shader) geclipped, während Fragmente bereits VOR dem Pixelshader geclipped (Z-Testing) werden.
Ich bin mit dem Author einer Meinung, dass es sich bei sehr wenigen Lichtern lohnen kann, im Tangentspace zu beleuchten, aber mit zunehmender Anzahl Lichter kann dass dan IMHO sehr schnell umkehren? Dies führt mich dann auch gleich zu Frage Nr. 5.
Frage 5:
--------
Eine moderne Grafikkarte hat IMHO zwischen 8 und 16 Interpolator Einheiten, die Grenze von Shader Version 3.0 liegt bei 12, zumindest kriege ich sehr schnell folgenden Fehler:
error X5629: Invalid register number: 12. Max allowed for o# register is 11
Beleuchte ich im Tangentspace, was ja ach so toll ist, dann kommt man schnell an diese Grenze, weil mind. der Direction Vector jeder Lichtquelle für jeden Pixel interpolliert werden muss, mehr als 8 dynamische Lichter, werden dann wohl kaum mehr zu schaffen sein? Meine Frage, ist Tangentspace Beleuchtung wirklich sooooo toll?
Frage 6:
--------
Ich habe mir überlegt, ob ich vielleicht für jede mögliche Anzahl Lichtquellen einen anderen Shader schreiben soll und schliesslich zur Laufzeit den korrekten zuweisen. Das würde sicherlich funktionieren, erscheint mir aber irgendwie nicht sehr elegant und gerade mit dem Shadermodell 3.x, welches ja hauptsächlich mit dynamic branching auftrumpfen soll, sollte dies doch wirklich nicht nötig sein, oder irre ich mich da?
Mfg Samuel