Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

17.12.2012, 16:15

Pointlight: Radius berechnen

Moin,

ich beschäftige mich momentan mit Deferred Lighting. Klappt auch alles wunderbar soweit, nun bin ich gerade aber am Userhandling dran. Aktuell ist es so, dass ich den Radius der Pointlight-Meshs dynamisch nach den Attenuation Angaben rendere. Meine Attenuation bestimmt sich durch f(x)=1/g(x) ; g(x)=ax²+bx+c. Logischerweise hat f(x) keine Nullstellen für x>0, bei sinnvoll gewählten a,b,c! Deshalb definiere ich mir eine Grenze bspw. threshold=25.6 (bedeutet für die Funktion f(x) die Grenze 1/25.6 = 0.04). Für diese Grenze sage ich, dass die Beleuchtung so nah an null ist, dass man an dieser Stelle "cutten" kann. Nochmal zusammengefasst;

Quellcode

1
2
3
ax²+bx+c = threshold
ax²+bx+c-threshold=0
//Nullstelle (x>0) (Mitternachtsformel)

Dann bekomme ich einen halbwegs optimeirten Radius auf den ich noch ein bisschen padding packe und damit dann ein Mesh erstelle. Soweit so gut. Allerdings möchte ich es für Anwender einfachen halten, Pointlights mit Attenuation zu erstellen. Ich setze zwar c=1 , da bei x=0 die Attenuation 1 sein soll, für a und b habe ich allerdings noch keine guten Default-Werte gefunden.
Ich habe nun gehört, dass man in den meisten 3d-Programmen (z.B. Blender) weder den Radius noch die Variablen a,b,c definiert, sondern das es fixe Werte gibt für Radius,a,b und c und das man das nur über die Light-Intensity ändern kann. Mir ist allerdings schleierhaft wie das funktionieren soll...

Ich sehe natürlich durchaus, dass es physikalisch mehr Sinn macht, wenn sich der Radius (also die Ausbreitungsdistanz) des Lichts mit seiner Intensität ändert, allerdings werden dafür erstmal sinnige Default-Werte gebraucht. Ebenso stelle ich mir bei größeren Radien eine starke Überbelichtung vor, denn die Lichtberechnung folgt ja dem simplen Muster: col = calculatedCol * intensity * attenuation. Wobei ich wie gesagt den physikalischen Zusammenhang sehe...

Habt ihr Ideen, wie man das sinnvoll handlen und berechnen kann?

Wo wir gerade bei pointlights sind, habt ihr gute Erfahrungen mit Dual-Parabolic Shadow Mapping gemacht?

Gruß Mark

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

2

17.12.2012, 17:09

Zum Lichtquellen-Radius: Du brauchst absurd niedrige Cutoff-Helligkeiten, wenn Du gammakorrekte Beleuchtung oder gar HDR benutzt. Ansonsten siehst Du permanent die Kanten von Lichtquellen, vor allem bei bewegten Lichtquellen sehr hässlich. Ich empfehle Dir stattdessen, die Attenuation anders zu berechnen. Nimm einen komplett linearen Falloff, oder ziehe die Cutoff-Helligkeit bereits in der Attenuation ab, so dass diese sauber bei 0 endet. Also Threshold statisch von c subtrahieren.

Zu Dual Paraboloid Shadow Mapping: habe ich noch nicht ausprobiert, aber die Fetzen, die ich im Internet aufgeschnappt haben, sind nicht sonderlich begeistert davon. Man braucht wohl sehr gut unterteilte Geometrie, damit es funktioniert, und die Übergangsbereiche sind bei jeder Art von Filter nicht wirklich schön zu kriegen. Ich nutze bei den Splitterwelten Standard-CubeMaps mit einem großzügigen Haufen PCF, was heutzutage keine Grafikkarte mehr sonderlich stört, aber sicherlich schöner geht. Ich bin aber auch am Überlegen, die CubeMap-Seite im Shader von Hand zu ermitteln, damit ich alle CubeMap-Seiten aller Lichtquellen auf einer Textur vereinen und mehrere Seiten auf einmal ausrendern kann. Zu Stoßzeiten habe ich bis zu 50 Renderpasses allein für Shadow CubeMaps, das killt jede Engine.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

3

17.12.2012, 20:47

Ich habe bisher auch ausschliesslich Cubemaps benutzt.
Irgendwo habe ich mal aufgeschappt, dass man mit dem Geometrieshader die Polygone automatisch auf alle Cubeseiten in einem Pass rendern kann.
Ob es stimmt und wie es geht: Keine Ahnung, aber vielleicht ein interessanter Ansatz. ^^

EDIT:
So, auf dem DelphiGL-Wiki steht Folgendes:

Zitat von »http://wiki.delphigl.com/index.php/Shader#Beispiel_Cube-Maps_Environment-Mapping«

Beispiel: Cube-Maps / Environment-Mapping
Beispiel: Cube-Maps / Environment-Mapping
Der Geometryshader stellt ein neues Vertexattribut gl_Layer zur Verfügung. Dieses erlaubt es zu bestimmen in welchen Framebuffer ein Dreieck gerendert werden soll. Dies kann man nun benutzen um in 6 Framebuffer gleichzeitig zu rendern. Der Geometryshader arbeitet dabei als Geometrie-Duplizierer. Da wir volle Kontrolle über die erzeugte Geometrie haben, können wir für jeden Framebuffer eine andere ModelViewProjection-Matrix zur Transformation verwenden. Man muss natürlich beachten, dass in diesem Fall das Frustum-Culling zu einem großen Teil im Shader stattfinden muss. Aber, letztendlich kann man so in einem einzigen Durchgang alle 6 Seiten einer Environment-Cubemap rendern!

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Spiele Programmierer« (17.12.2012, 20:52)


Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

4

17.12.2012, 22:19

Technisch geht das. Praktisch soll es aufgrund der GeometrieShader-Details langsamer sein, als wenn man einfach die 6 Passes direkt rendert. Es fehlt mir da aber an Erfahrung.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

5

18.12.2012, 17:56

moin,

Zum Lichtquellen-Radius: Du brauchst absurd niedrige Cutoff-Helligkeiten, wenn Du gammakorrekte Beleuchtung oder gar HDR benutzt. Ansonsten siehst Du permanent die Kanten von Lichtquellen, vor allem bei bewegten Lichtquellen sehr hässlich. Ich empfehle Dir stattdessen, die Attenuation anders zu berechnen. Nimm einen komplett linearen Falloff, oder ziehe die Cutoff-Helligkeit bereits in der Attenuation ab, so dass diese sauber bei 0 endet. Also Threshold statisch von c subtrahieren.


Letzteres werde ich wohl nehmen, danke für den Hinweis !
Ebenso werde ich wohl vorerst auf CubeMaps gehen (entwickle noch für DX9) und dann mal schauen.

Ich möchte auch nochmal meine Ausgangsfrage hervorheben:

Allerdings möchte ich es für Anwender einfachen halten, Pointlights mit Attenuation zu erstellen. Ich setze zwar c=1 , da bei x=0 die Attenuation 1 [bzw. 1-threshold] sein soll, für a und b habe ich allerdings noch keine guten Default-Werte gefunden. Ich habe nun gehört, dass man in den meisten 3d-Programmen (z.B. Blender) weder den Radius noch die Variablen a,b,c definiert, sondern das es fixe Werte gibt für Radius,a,b und c und das man das nur über die Light-Intensity ändern kann. Mir ist allerdings schleierhaft wie das funktionieren soll...

Habt ihr Ideen, wie man das sinnvoll handlen und berechnen kann?


Gruß Mark

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

6

18.12.2012, 19:11

Physikalisch betrachtet sinkt die Lichtintensität mit dem Quadrat des Abstands. Demzufolge wären in Deiner Formal a=1 und b=c=0. Wenn Du jetzt eine Minimal-Wirkintensität der Lichtquelle e definierst, unterhalb derer die Lichtquelle als "unwirksam" gewertet wird, kannst Du nach dem Radius auflösen und bekommst eine Formel, die den Radius in Abhängigkeit von der Lichtintensität berechnet.

Diese (a,b,c)-Einstellerei habe ich das letzte Mal bei Fixed Function Grafikkarten gesehen... Geforce2 und Konsorten. DAS waren noch Zeiten.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

7

19.12.2012, 18:18

Ich glaube wir reden da aneinander vorbei.

Denn die Lichtberechnung folgt ja dem simplen Muster: col = calculatedCol * intensity * attenuation.

calculatedCol sei die berechnete Diffuse- und Specular- Farbe. Die Intensity gibt die Stärke des Lichts generell an. Bei einer Intensity von 2 sind die Farbwerte also doppelt so hoch wie bei einer Intensity von 1. Die Attenuation gibt ja einfach nru den Faktor an um den die Intensität dann abnimmt. Wenn ich nun aber a=1 b=c=0 wählen hätte ich die Attenuation Funktion1/x² und das will ich ja nicht, da die Werte für x->0 gegen unendlich gehen. Sondern ich will ja am Urpsrung der Lichtquelle dascol=calculatedCol*Intensity ist. Also c müsste konstant auf 1 gesetzt werden. Die Frage ist jetzt was ich dann für ein threshold udn für ein a nehmen soll, damit ich einen guten Default-Radius habe, der dann mit der Intensity vergrößert/verkleinert werden kann.

Zitat

Diese (a,b,c)-Einstellerei habe ich das letzte Mal bei Fixed Function Grafikkarten gesehen... Geforce2 und Konsorten. DAS waren noch Zeiten.


Zitat von »https://developer.valvesoftware.com/wiki/Constant-Linear-Quadratic_Falloff«

While this is typical real world attenuation (accordng to inverse-square law), this rate is often too fast for virtual environments, creating unnatural glares on nearby textures (like the ceiling). [...] A real-world point light will fall off following the inverse-square law(plus some linear attenuation due to atmospheric scattering).


Gruß Mark

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

8

19.12.2012, 21:19

Nein, wir reden nicht aneinander vorbei. Ich habe nur den Eindruck, dass Du nicht wahrhaben willst, was ich schreibe. Der quadratische Falloff ist PHYSIK. Das sind undiskutierbare Fakten. Die Falloff-Formel mit 1/(ax²+bx+c) ist reine Design-Entscheidung - die kannst Du benutzen, Du kannst es aber auch seinlassen. Und meine Empfehlung ist: lass es sein. Ich habe z.B. 1/x²-c empfohlen.

Mir ist ehrlich gesagt wurscht, was da ein User denkt, der bei Valve Schreibrechte im Wiki hat. Ich kann Dir nur aus Erfahrung sagen, dass bei gammakorrekter Beleuchtung und einem halbwegs sinnvollen Global Illumination-System quadratischer Falloff eine saubere Sache ist. Aber wenn Dir das nicht gefällt, dann ändere es doch. Tut doch keinem weh.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

9

19.12.2012, 21:54

Ich glaube schon, dass wir etwas aneiannder vorbei reden, ist ja nicht bös gemeint :) . Ich weiß nicht was richtig oder "physikalisch" korrekter ist. Ich stelle deine These auch gar nicht selbst in Frage. Ich habe nur festhalten wollen, dass es da durchaus andere Meinungen zu gibt. Wenn in der "Valve-Wiki" steht es gibt lineare Faktoren wegen "atmospheric scattering", dann ist das aus meiner Sicht genauso plausibel, wie wenn du schreibst, dass ist Quatsch. Ich weiß doch nicht was stimmt :). Ich weiß nur das es da auch unters. Meinungen dazu gibt, und dass diese "(a,b,c)-Einstellerei nach wie vor viel unter Dx9 angewendet wird, in wie weit das kompletter Quatsch ist, kann ich nichts zu sagen ;).

Es geht auch nicht darum, was mir gefällt oder nicht, sondern ich versuche zu verstehen, denn nur darum stell ich Fragen :). Das hat auch nichts mit wahrhaben zu tun, reine Verständnissache.

So wollte ich zum Beispiel in dem letzten Post auf das Problem aufmerksam machen, dass für mich aus deinem Vorschlag resultiert. Die Funktion 1/x² geht wie verlinkt für x->0 gegen unendlich. Dann habe ich doch ein großen Problem für kleine Distanzen (x=dist gegen Null), wenn ich col = calculatedCol * attenuation als Berechnung benutze. Denn dann bekomm ich ja riesige Summen raus, die absolut keinen Sinn machen oder wo ist der Denkfehler? Deswegen schrieb ich ja das ich die Maximum Attenuation auf "1" (das 'c') haben will, damit der Wert bei x=0 (Distanz gleich null) auf 1 steht. Somit wäre dann col = calculatedCol, was für mich Sinn ergibt. Mit steigenden Distanz bewegen sich die Werte dann von 1 gegen 0.

Das ist mein noch unvollständiges Verständnis der Sache und das möchte ich ausbauen. Deshalb suche ich Anregungen.

Gruß Mark

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

10

20.12.2012, 16:19

Nunja... "Quatsch" würde ich die (a,b,c)-Formel nicht nennen... es ist einfach eine Möglichkeit unter vielen, und noch dazu eine, die schon erfolgreich angewendet wurde. Es ist wirklich ernsthaft wahrlich echt jetzt völlig Dir überlassen, was Du nimmst. Meiner persönlichen Meinung nach solltest Du nur darauf achten, für alle Lichter die selbe Formel anzuwenden, damit das Endergebnis konsistent aussieht. Und ich würde mich nicht allzu weit vom 1/r² entfernen, damit Du später mit gamma-korrekter Beleuchtung die unbewusste Erwartungshaltung des Betrachters triffst. Das menschliche Sehorgan (Auge und Hirn dahinter) hat nämlich eine unglaubliche Menge Mechanismen, den wahrgenommenen Bildern Tiefe, Struktur und Bedeutung zu verleihen, die alle an der echten Physik trainiert wurden. Du solltest also, wenn Du davon abweichst, gute Gründe haben.

Und Du hast natürlich Recht: 1/r² geht gegen Unendlich für r -> 0. Die Formel 1/r² ist ja nur ein mathematisches Modell, das von einer Lichtquelle mit unendlich kleiner Ausdehnung ausgeht. Da aber reelle Lichtquellen nicht unendlich klein sind, weicht die Formel halt immer weiter von der Realität ab, je näher der Betrachtungspunkt an der Lichtquelle liegt.

Ich habe dafür bei mir im Shader ein banales max( r, 1.0f) eingebaut, so dass r nie kleiner als 1 wird und demzufolge die Attenuation-Formel nie mehr als 1 ergibt. Aber Du kannst es natürlich auch über eine Konstante 1/(r²+c) lösen, wo bei c == 1 die Formel für Radius 0 schon 1 ergibt. Oder Du nimmst ein kleines c von z.B. 0.1f, womit die Attenuation maximal das Zehnfache ergibt. Das ist wiederrum ganz nach Deinem Geschmack einstellbar.

Und auf die Gefahr hin, mich zu wiederholen: ich würde außerdem ein kleines Offset einbauen, so dass die Formel für eine von Dir definierte Grenzentfernung tatsächlich auf 0 kommt. Also ein 1/r²-k ... man beachte die hier fehlenden Klammern. Ich meine wirklich (1/r²) - k, nicht das vorhin genannte 1/(r²+c).

Und ziehe die Konstanten im Shader in irgendeine globale Definition raus, damit Du die später einfach ändern kannst. Aktuell kann Dir das noch egal sein, aber irgendwann später wirst Du unbedingt zu gamma-korrekter Berechnung wechseln wollen. Und damit ändert sich der Gesamt-Eindruck der Szene deutlich, dann geht das ganze Abschmecken der Konstanten von vorne los.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

Werbeanzeige