Da bist Du völlig auf dem Holzweg. Irgendwas in Sachen Lichtberechnung auf der CPU zu machen ist eine Dumme Idee (tm). Da brauchst Du wirklich wirklich wirklich gute Gründe, bevor Du überhaupt daran denken darfst. Stattdessen solltest Du folgendes tun:
- Du berechnest bisher die TBN-Matrix im VertexShader.
- Das ist die Matrix, mit der Du einen Vektor VertexposZuLichtpos in den lokalen Tangentenraum transformierst
- Weil Du, wenn Du den in den PixelShader gibst, ihn dort mittels dot() gegen die Normal Map rechnen kannst.
- Damit brauchst Du aber pro Licht mindestens ein Interpolator-Register, und davon hast Du maximal 32.
- Also machst Du stattdessen alle Berechnungen im PixelShader.
- Du transponierst die oben genannte TBN-Matrix, so dass sie jetzt vom lokalen Tangentenraum in Objektkoordinaten transformiert
- Von da transformiert die World Matrix in Weltkoordinaten. Multipliziere die also im VertexShader hintendran an die inverse TBN-Matrix
- Du hast jetzt im VertexShader eine Matrix, die vom lokalen Tangentenraum in den globalen Welt-Koordinatenraum transformieren kann
- Gib also statt irgendwelcher Per-Licht-Daten die in den PixelShader rein
- Du kannst jetzt mit dieser Matrix im PixelShader die Position des Vertex und die Normale aus der Normal Map in Weltkoordinaten umrechnen
- Und damit alle Lichtberechnungen in Weltkoordinaten machen
- Jetzt brauchst Du nur noch ein Array aller Lichtdaten in Weltkoordinaten im PixelShader anstatt bisher im VertexShader
- Und kannst jetzt pro Pixel alle Berechnungen gegen alle Lichter machen
- Die Grenze der maximalen Anzahl Lichter hängt jetzt von den Konstantenregistern ab
- Und davon hast Du ab DX10 64000.
- Problem gelöst.
Probiere es aus. Und mach Dich fit in Sachen Matrizen, Koordinatenräumen und Transformationen zwischen diesen Räumen. Das ist hundewichtig und hier essentiell für die Problemlösung. Schreibe Dir für jeden einzelnen Variable in jedem einzelnen Shader-Abschnitt auf, in welchem Koordinatensystem dieser Wert vorliegt. Dann siehst Du schnell, welche Transformationen Du wo anwenden musst, um die Daten alle in den gleichen Koordinatenraum zu bekommen. Und alle Daten im gleichen Koordinatenraum zu haben ist die Grundvoraussetzung, um sie miteinander verrechnen zu können.