JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.phpMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Annäherung eines Kehrwerts im Pixelshader

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 09.06.2006, 20:07    Titel: Annäherung eines Kehrwerts im Pixelshader Antworten mit Zitat

Tach,

ich habe im Moment ein ziemlich kniffliges Problem. Ich überarbeite meinen Parallaxmapping und Bumpmapping Shader. Ich will die Abschwächung der Lichthelligkeit über die Distanz bei Punktlichtern jetzt nicht mehr auf Vertex sondern auf Pixelbasis berechnen. Ich kann allerdings nur Pixelshader Version 1.4 und Vertexshader Version 1.1 verwenden. Und ich möchte meinen Pixel Shader drei Lichtquellen berechnen lassen. Das berechnen des Parallax Effekts kommt natürlich noch dazu.

Ich habe mir jetzt eine Methode überlegt dies zu realisieren. Das Problem ist, dass ich dazu mit sieben Arithmetischen Rechenoperationen im Pixelshader, drei Vektoren berechnen muss die die gleiche Richtung aber die invertierte Länge der drei gegebenen Vektoren haben. Es muss also folgendes Verhältnis gelten:
|x|=1/|v| und x.v=1 (der Punkt soll hier für Skalarprodukt stehen)
Wobei x der gesuchte Vektor und v der gegebene ist.

Der letzte Baustein der mir noch fehlt um dies zu erreichnen ist ein Annäherungsverfahren zur Berechnung eines Kehrwerts, das ich in einen Pixelshaderbefehl quetschen kann. Und da komm ich mit meinem erweiterten Zehntklässler Mathewissen an meine Grenzen. Ich habe bereits eine ganze Weile nach so etwas gegooglet aber bis jetzt ohne Erfolg. Etwas was so ungefähr in diese Richtung geht ist das Newton-Raphson-Verfahren. Das berechnet allerdings den Kehrwert der Wurzel und daher nützt es mir nichts, da ich nicht genug Rechenoperationen zur Verfügung habe um das Ergebnis nochmal zu quadrieren.

Also für jeden Tipp wie ich das machen könnte wäre ich sehr dankbar. Es braucht nich präzise zu sein. Ich will bloß irgendetwas was keinen erkennbaren Unterschied macht wenn man es neben Objekten sieht die kein Bumpmapping verwenden. Ich hoffe es gibt da irgendeine Methode die mir weiterhelfen kann.

Im vorraus schonmal Danke,
mit freundlichen Grüßen
Dr. Best
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
Fallen
JLI MVP
JLI MVP


Alter: 41
Anmeldedatum: 08.03.2003
Beiträge: 2860
Wohnort: Münster
Medaillen: 1 (mehr...)

BeitragVerfasst am: 09.06.2006, 20:40    Titel: Antworten mit Zitat

Kannst du nicht die Abschwächung ausserhalb des Shaders berechnen und dem Shader die berechneten Werte als Konstanten übergeben?

Ansonsten habe ich dein Post nicht ganz verstanden beim flotten lesen.
_________________
"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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
PeaceKiller
JLI Master


Alter: 36
Anmeldedatum: 28.11.2002
Beiträge: 970

Medaillen: Keine

BeitragVerfasst am: 09.06.2006, 21:16    Titel: Re: Annäherung eines Kehrwerts im Pixelshader Antworten mit Zitat

Dr. Best hat Folgendes geschrieben:
Annäherungsverfahren zur Berechnung eines Kehrwerts


Was spricht gegen 1/x?
_________________
»If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Jonathan_Klein
Living Legend


Alter: 37
Anmeldedatum: 17.02.2003
Beiträge: 3433
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 09.06.2006, 21:33    Titel: Antworten mit Zitat

zu langsam für Schader, schätze ich.

http://germangamedev.de/index.php?site=faq&id=10

könnte helfen, falls dus in nen Shader kriegst.
_________________
https://jonathank.de/games/
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 09.06.2006, 21:38    Titel: Antworten mit Zitat

@ Fallen
Nein, kann ich nicht. Die Stärke des Lichts nimmt ja über die Distanz ab. Das Licht hat einen Reichweitefaktor. Ich verwende zur Berechnung der Abnahme die Formel A=1/(r/9) wobei A der Abnahmefaktor und r die maximale Reichweite ist. So ist bei der maximalen Reichweite die Helligkeit nur noch ein neuntel so dass es nicht auffällt wenn der Kram dahinter nicht mehr belichtet wird. Aber das ist hier eigentlich ziemlich egal. Entscheidend ist, dass man die Abschwächung weder auf Meshbasis noch auf Vertexbasis berechnen kann. Die Abschwächung ist für jeden Pixel anders.
Ich verdeutliche das mal an einem Beispiel:

Man hat ein gleichseitiges Dreieck mit einer Seitenlänge von 15 und genau in der Mitte davon ist in einer Entfernung von 1 eine Lichtquelle mit einer Reichweite von 2. Berechnet man die Abschwächung auf Vertexbasis würde das Dreieck überhaupt nicht beleuchtet werden denn alle Drei Eckpunkte sind deutlich weiter als 2 von der Lichtquelle entfernt. Aber in der Mitte müsste eigentlich ein Heller Fleck sein. Deswegen muss man die Lichtabschwächung auf Pixelbasis berechnen.

@ Peacekiller
Dann sag mir mal wie ich in einem Pixelshader Version 1.4 1/x schreiben soll.
Mir stehen da nur einfache Rechenoperationen wie Addition, Multiplikation und entsprechend auch Subtraktion zur Verfügung. Ich brauche also irgendeine Formel zur Berechnung eines Kehrwerts in der keine Division auftaucht. Und sie darf nicht zu kompliziert sein denn sonst kann ich sie nicht in einen Shaderbefehl packen.
Ein gutes Beispiel für soetwas ist wie gesagt das Newton-Raphson-Verfahren. Das geht nämlich folgendermaßen (zumindest wenn ich mich jetzt nicht vertue):
1/(x)^0.5=(0.5*(1-X))+1
Man berechnet eine Wurzel und einen Kehrwert und trotzdem steht da weder ein Exponent noch ein Bruchstrich. So etwas suche ich für die Berechnung des Kehrwerts.

Edit:
@ Jona
Würde ich es verstehen würde es mir vielleicht weiterhelfen Rolling Eyes . Aber es scheint wirklich bereits ein bisschen zu kompliziert für einen Pixelshader zu sein.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
Jonathan_Klein
Living Legend


Alter: 37
Anmeldedatum: 17.02.2003
Beiträge: 3433
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 09.06.2006, 23:06    Titel: Antworten mit Zitat

Tja, kannst ja mal bei Patrick im Forum fragne, ob der das hinkreigt das in nen Shader zu packen.
_________________
https://jonathank.de/games/
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 10.06.2006, 00:33    Titel: Antworten mit Zitat

Ja, ich werde Patrick vielleicht mal fragen wenn ich's garnicht mehr hinkriege.
Aber vorher noch was für euch Wink . Das hier verwirrt mich:
Das mit dem Newton-Raphson-Verfahren habe ich aus einem sehr lehrreichen Pixelhaderprogrammierungstutorial von Wolfgang Engel.
Da heißt es:
Code:
; Assuming v0 contains the unnormalized biased & scaled vector ( just
; like a normal map), r0 will end up with a very close to normalized
; result.
; This trick is also useful to do 'detail normal maps' by adding
; a vector to a normal map, and then renormalizing it.
dp3 r0, v0_bx2, v0_bx2 ; r0 = N . N
mad r0, v0_bias, 1-r0, v0_bx2 ; (v0_bias * (1-r0)) + v0_bx2
                              ; ((N - 0.5) * (1 - N.N)) + (N - 0.5) * 2

Wenn man v als (N-0.5)*2 (also v0_bx2) definiert dann ist die Formel die da steht folgende:
v*0.5*(1-|v|²)+v=n
Wobei n das normalisierte v ist.
Wenn ich das ganze ein bisschen umforme komme ich auf folgendes:
(-0.5*|v|²+1.5)*v=v/|v|
Und wenn ich dann noch v auf beiden Seiten wegdividiere und x als |v|² definiere bleibt das hier stehen:
-0.5*x+1.5=1/x^0.5
Aber das was da auf der linken Seite steht ist ja nichts weiter als eine lineare Funktion die den Graphen von 1/x^0.5 lediglich in einem Punkt tangiert. Sicherlich nichts was für eine ordentliche Approximation taugt (das wird ja sogar negativ). Habe ich beim umformen irgendetwas falsch gemacht oder stimmt in dieser Formel aus einem populären Tutorial tatsächlich etwas nicht Rolling Eyes ?

Ich hatte nämlich meine Hoffnung irgendeine Annäherung für den Kehrwert zu finden auf diese Formel gestützt Confused .
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
GreveN
JLI Master


Alter: 38
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 10.06.2006, 13:55    Titel: Antworten mit Zitat

Was Parick verwendet ist im Grunde dieses Snippet, welches im Internet umhergeistert:
CPP:
#define FP_ONE_BITS 0x3F800000

// r = 1/p
#define FP_INV(r,p) \
{ \
    int _i = 2 * FP_ONE_BITS - *(int *)&(p); \
    r = *(float *)&_i; \
    r = r * (2.0f - (p) * r); \
}

"2 * FP_ONE_BITS" lässt sich noch zusammenfassen und ist: 0x7F000000
Vielleicht etwas verständlicher für dich der Algo in dieser Form... ;)


Und das hier ist die gepimpte Version von Vincent Van Eeckhout (genau die, die Patrick auch verwendet, ist halt als Makro definiert nur Käse ;)):
CPP:
/////////////////////////////////////////////////
// The following comes from Vincent Van Eeckhout
// Thanks for sending us the code!
// It's the same thing in assembly but without this C-needed line:
//    r = *(float *)&_i;

float   __two = 2.0f;

#define FP_INV2(r,p) \
{ \
    __asm { mov     eax,0x7F000000    }; \
    __asm { sub     eax,dword ptr [p] }; \
    __asm { mov     dword ptr [r],eax }; \
    __asm { fld     dword ptr [p]     }; \
    __asm { fmul    dword ptr [r]     }; \
    __asm { fsubr   [__two]      }; \
    __asm { fmul    dword ptr [r]     }; \
    __asm { fstp    dword ptr [r]     }; \
}


p.s.: Wie wär's denn mit einem Mathe-Subforum für solche Fragen?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 10.06.2006, 16:21    Titel: Antworten mit Zitat

Ok, ich hab mich bei Wikipedia mal ein bisschen über den Aufbau von float-Variablen schlau gemacht und jetzt zumindest so ne ungefähre Ahnung davon wie dieser Algorithmus funktioniert. Leider muss ich aus diesen Erkenntnissen schließen, dass ich das in meinem Shader mit Sicherheit nicht verwenden kann Confused . Dem GPU kann man nicht beibringen irgendetwas plötzlich nicht mehr als Fließkommazahl sondern als Integer zu interpretieren. Außerdem werden da ja komplett andere Datenformate verwendet.

Mir ist gerade noch eingefallen, dass die Möglichkeit besteht dafür zu sorgen, dass die gegebenen Vektoren, deren Länge ich umkehren will, immer eine Länge zwischen 0 und 1 haben. Das heißt die Annäherung müsste bloß in diesem Bereich ordentlich funktionieren. Ich werde mal ausprobieren wie gut folgende Annäherung funktioniert:
1/x ~= (x-1)²*4+1
Diese Formel müsste ich eigentlich im Shader umsetzen können. Vergleicht man die Graphen sieht es eigentlich auch so halbwegs ähnlich aus:
BILD
BTW, praktische Freeware.
Die Stellen die eigentlich extrem hell sein sollten werden bei dieser Annäherung dann halt nicht ganz so hell werden. Aber die Farbwerte werden hinterher ja sowieso wieder geclampt (also zwischen 0 und 1 gebracht) also fällt das mit etwas Glück nicht groß auf.
Ich lass euch dann wissen, ob und wenn ja wie gut das funktioniert.

Ein Mathe Subforum fände ich auch mal angebracht. Ist ja schließlich nicht gerade selten, dass man beim Programmieren mal auf mathematische Probleme stößt.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 11.06.2006, 03:16    Titel: Antworten mit Zitat

Ich habe jetzt erfolgreich folgende Formel implementiert:
(x-1)²*8 = 8x²-16x+8
Anders ging es nicht. Das funktioniert ganz ordentlich aber es weicht doch ziemlich weit von dem korrekten Ergebnis ab. Also bleibt die Frage dieses Topics im Prinzip bestehen. Also wenn irgendwer vielleicht mal zufällig über so etwas stolpert dann wäre ich dankbar wenn er's hier reinposten könnte.

Hier mal ein Screenshot. Das ganze besteht halt wirklich nur aus 24 Vertices und 12 Dreiecken. Und die Abschwächung der Lichthelligkeit über die Distanz wird auf Pixelbasis berechnet. Genau das ist es halt wozu ich irgendeine Annäherung brauchte bzw. immernoch eine bessere brauche.

Danke für eure Hilfe.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
GreveN
JLI Master


Alter: 38
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 11.06.2006, 12:17    Titel: Antworten mit Zitat

Also, wenn du das irgendwie implementieren kannst:
Zitat:
y = 4,5(x-1,2)^6+1

...liefert bei mir eine ziemlich brauchbare Annäherung, wenn die 6 Multiplikation bei dem Exponenten schon zu lahm sein sollten, könntest du auch mal den Exponenten 4 testen, liefert auch schon recht brauchbare Ergebnisse. Aber "nur" 2 scheint mir zuwenig zusein.

Achja: Die Konstanten waren da auch eher grobe "Schätzwerte", etwas Feintuning wirkt da vielleicht noch Wunder.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
Dr. Best
Senior JLI'ler


Alter: 35
Anmeldedatum: 17.06.2004
Beiträge: 269
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 11.06.2006, 21:17    Titel: Antworten mit Zitat

Also der Shadercode den ich jetzt verwende nutzt eigentlich schon so ziemlich alle Möglichkeiten irgendeine Rechenoperation durchzuführen, die ein Pixelshader 1.4 zu bieten hat:
Code:
// Scale each difference vector to it's approximate inverse lenth using this formula:
// 1/x ~= (x-1)²*8 = 8x²-16x+8 = ((x*x-2x)*2+2)*4
// Calculate the squared length of the first difference vector
dp3_sat r0.rgb, r3, r3
// Begin approximating the reciprocal of the first light's squared length
mad_x2 r3.a, r0.r, r0.r, -r0_x2.r
// Invert the length of the first difference vector
mad_x4 r3.rgb, r3, r3.a, r3_x2

Bei mehr als einer Lichtquelle verwende ich dann auch noch Instruction Pairing damit das alles passt. So etwas wie du vorgeschlagen hast ist also eindeutig zu kompliziert.

Allgeimein kann ich auf diese Weise Formeln folgender Form basteln:
m und n müssen Element der ganzen Zahlen und betragsmäßig kleiner gleich 3 sein.
p, o, q und r müssen Element der ganzen Zahlen und betragsmäßig kleiner gleich 2 sein.
( (px*ox + qx) * 2^m + r )*2^n

Versuche ich irgendwo noch Platz für weitere Rechenoperationen zu finden scheitert das daran, dass es nicht genug Register gibt um alle benötigten Werte zu speichern.

Ich habe heute nochmal den ganzen Tag versucht mit den vorhandenen Mitteln irgendeine bessere Annäherung hinzubiegen, aber bin dabei zu keinem wirklich brauchbaren Ergebnis gekommen. Also werde ich jetzt wahrscheinlich bei der Formel die ich jetzt habe bleiben. Im Moment checke ich sie noch ein bisschen auf verschiedene mögliche Probleme.

Ein Problem ist auf jeden Fall, dass die Lichtstärke wenn das Licht sehr nah kommt irgendwann wieder abnimmt. Bei x=0.2 also einem Fünftel der definierten Reichweite hat die Lichtstärke ihr Maximum erreicht. Kommt das Licht noch näher geht sie wieder gegen null wobei sie allerdings erst bei 0.016 unter eins fällt Confused . Das ist wirklich nicht gerade optimal aber eine bessere Lösung fällt mir einfach nicht ein. Und es ist immernoch besser als Vertexbasierte Beleuchtung. Ich werde die Nutzer meiner Engine halt in der Hilfedatei darauf hinweisen müssen bei Verwendung des Per Pixel Lightings keine zu hohen Lichtreichweiten anzugeben.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen AIM-Name MSN Messenger
PeaceKiller
JLI Master


Alter: 36
Anmeldedatum: 28.11.2002
Beiträge: 970

Medaillen: Keine

BeitragVerfasst am: 11.06.2006, 21:23    Titel: Antworten mit Zitat

Mit gnuplot kannst du für beliebige Punkte und Formel Näherungswerte berechnen.
_________________
»If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Fallen
JLI MVP
JLI MVP


Alter: 41
Anmeldedatum: 08.03.2003
Beiträge: 2860
Wohnort: Münster
Medaillen: 1 (mehr...)

BeitragVerfasst am: 11.06.2006, 21:53    Titel: Antworten mit Zitat

Schau dir doch hier mal die verschiedenen Verfahren an zur Berechnung der Abschwächung des Lichtes:

http://www.zanir.szm.sk/dx/016_Per_Pixel_Lighting.zip
_________________
"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
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum