Weiches Shadowmapping mittels Tiefenkegel-Projektion

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Schrompf »

Hallo Leute,

ich möchte euch hier eine Idee vorstellen, die ich seit geraumer Weile mit mir rumtrage. Es geht darum, die bekannte Technik Shadow Mapping so zu erweitern, dass mit wenig zusätzlicher Rechenzeit der optische Eindruck von mit zunehmendem Abstand aufweichenden Schattenkanten erreicht wird. Ich habe dazu eine Idee entwickelt und einen kleinen Prototypen gebaut, der die Stärken und Schwächen der Technik präsentiert. Dazu aber gleich mehr - wir arbeiten natürlich ordentlich wissenschaftlich strukturiert.

Das Problem
In den bekannten Techniken zur Schattenvisualisierung werden Lichtquellen üblicherweise als Punkt angenähert. Das sorgt abgesehen von den üblichen Aliasing-Problemen von z.B. Shadow Mapping für pixel-scharfe Schattenkanten. Physikalisch betrachtet ist das aber nicht haltbar - jede Lichtquelle hat eine gewisse Ausdehnung. Die Menge an Licht, die an einem bestimmten Punkt von einer Lichtquelle aus ankommt, ist also keine binäre Funktion. Und das menschliche Sehzentrum benutzt unbewusst die Licht-Schattenübergänge, um zusätzliche Tiefeninformationen zu der betrachteten Szene zu gewinnen. Es scheint also erstrebenswert, die durch die Lichtquellenausdehnung entstehenden weichen Licht-Schatten-Übergänge in der Computergrafik nachzubilden.

Für eine wirklich korrekte Bestimmung des an einem Punkt empfangenen Lichtes einer ausgedehnten Lichtquelle wäre ein Flächenintegral über den Teil des Halbkugel-Horizonts eines Punkts notwendig, den die Lichtquelle aus Sicht des Punktes einnimmt.

Bisherige Arbeiten
Es gibt bereits einige Methoden, Schattenkanten aufzuweichen. Für Shadow Mapping ist die einfachste Methode das Percentage Closer Filtering (PCF), das schlicht über die binären Ergebnisse mehrerer Shadow Mapping Samples mittelt. Eine erweiterte Version davon ist NVidias Percentage Closer Soft Shadows, welche in einer Standard-ShadowMap zuerst mit maximalem Weichzeichner-Radius eine Hinderniss-Suche ausführt, um anhand der gefundenen Hindernisse und ihres durchschnittlichen Abstands dann den Radius des eigentlichen PCF-Kernels zu bestimmen. Die Technik funktioniert auf einer Standard-ShadowMap ohne jede Vorverarbeitung, benötigt aber sehr viele Samples aus der SM pro Bildschirmpixel, was die Technik vor allem bei hohen Auflösungen und mehrfachem Overdraw sehr teuer macht.

Es gibt viele weitere Techniken, die ich aber mangels akkurater Kenntnisse gerade nicht aufzählen kann. Ein Thread auf GameDev.net hat mal demonstriert, wie man bei Variance Shadow Mapping aus den beiden Werten den Abstand des Blockers gewinnen kann und dann durch gezielte Auswahl der MipMap sehr weiche Schatten erreichen kann - allerdings mit den für VSM üblichen Fehlbeleuchtungen (Light Bleeding). Es gab auch Versuche, das Integral im Pixelshader live nachzubilden - ich habe auch eine Version davon da, die aber abartig teuer ist, und es gibt Beiträge von richtigen Wissenschaftlern, die sich aber gerade meiner Googlung entziehen.

Ansatz
Ich möchte hier eine Methode vorstellen, die auf einer symptomatischen Herangehensweise basiert. Die Lichtquelle wird dazu als kreisförmig mit räumlich begrenztem Umfang angenommen. Bei dieser Annahme projiziert ein einzelner Punkt also eine Art Schattenkegel hinter sich in die Szene, welcher mit zunehmender Tiefe linear im Radius wächst und dabei indirekt proportional an "Dunkelheit" verliert. Für eine beliebige Stelle im Raum ist der Gesamtwert der Helligkeit von der Lichtquelle also das Integral über die kegelförmigen "Impulsantworten" (ich nenn die jetzt mal so) aller schattenwerfenden Elemente davor. Ein Querschnitt durch die Szene sähe dann so aus:
Lichtskizze.jpg
Die Idee ist jetzt, eine Funktion zu finden, die mit möglichst wenig Parametern den typischen Helligkeitsverlauf mit der Tiefe an Schattenkanten beschreibt. Mit einer solchen Funktion kann man beim Zeichnen der Szene dann die Lichthelligkeit einfach rekonstruieren und das eingangs genannte Flächenintegral könnte man also in den Shadow Map Space verschieben. Als Funktion wurde hier gewählt:

Helligkeit = Seitlicher Abstand von Hinderniskante / Tiefenabstand zum Hindernis

Es reichen zur Beschreibung also zwei Parameter: der seitliche Abstand zum nächsten schattenwerfenden Hindernis und der Tiefenabstand zur Tiefe dieses Hindernisses. Diese Parameter haben außerdem den Vorteil, dass sie sehr leicht aus einer ShadowMap zu bestimmen sind und dass die Bestimmung wie z.b. ein Gausscher Weichzeichner achsen-separierbar ist. Besonders letztere Eigenschaft ermöglicht es, die algorithmische Komplexität der Nachbearbeitung von O(n^2) auf O(n) zu senken. Die beiden Parameter sind außerdem freundlich interpolierbar, was die Ausnutzung der gängigen Textur-Interpolationsmöglichkeiten moderner GPUs ermöglicht.

--- Hier klafft übrigens noch eine Lücke in meiner Idee: zum Einen hat die Bestimmung der Kegel-Parameter als reine Suche nach dem nahesten Hindernis den unschönen Nebeneffekt, dass Schattenkegel von vorderen Hindernissen die schmaleren und damit dunkleren Kegel hinterer Hindernisse zu überdecken. Eine bessere Kombinationsfunktion als "wähle das naheste Hinderniss" wäre hilfreich, aber ich habe bisher keine passende gefunden. Und zum Anderen erzeugt eben diese Interpolation der Parameter einen unschönen Rand am äußersten Ende der Schattenkegel, den ich noch beseitigen muss.

Implementation

Zuerst wird eine normale Shadow Map mit den Tiefenwerten der Szene aus Sicht der Lichtquelle gefüllt. Dann wird in einem Nachbearbeitungsschritt aus diesen Tiefenwerten die Kegelparameter pro ShadowMap-Texel bestimmt, indem für jeden Texel der Abstand zum nächsten Hinderniss bestimmt wird, das auf den Texel einen Schattenkegel projiziert. Das kann als einzelner Pass implementiert werden, aber wirkliche Vorteile bringt die Technik erst, wenn man die Bestimmung der Kegelparameter als zwei separate Durchgänge für horizontale und vertikale Suche implementiert. Danach zeichnet man die Szene normal wie bei Verwendung einer normalen Shadow Map, nur dass man für den "Punkt ist im Licht"-Fall zusätzlich die Kegelfunktion auswertet.

Die Implementation beschränkt sich hier auf die "äußeren" Seiten der Schattenkegel. Theoretisch würde sich ein Kegel auf beiden Seiten des Hindernisses erstrecken, die Hälfte des Kegels wäre also innerhalb des Schattens. Allerdings benötigt man dann noch einen bzw. zwei weitere Parameter, um auch diesen Verlauf zu beschreiben. Und zum Anderen bekommt man damit die prinzipielle Probleme des ShadowMappings (keine Informationen über weitere Hindernisse jenseits des vordersten, schattenwerfenden Hindernisses) in die Szene. Das äußert sich dann durch Fehlbeleuchtung an Tiefenwert-Kanten, sehr ähnlich dem Light Bleeding von Variance Shadow Mapping. Ich werde daher auf die beidseitige Kegelprojektion nicht weiter eingehen. In der Praxis halte ich die Verwendung nur der äußeren Kegelseiten für hinreichend, um den gewünschten optischen Eindruck zu erreichen.

Ergebnisse
shtest_gross.jpg
Die vorgeschlagene Kegelprojektionstechnik wurde in einem Prototypen implementiert. Dieser Prototyp implementiert einfaches Shadow Mapping, NVidias Percentage Closer Soft Shadow Mapping und die beschriebene Technik Depth Cone Shadow Mapping. Auch die beidseitige Variante ist implementiert, aber nicht gepflegt - die Ergebnisse davon sind definitiv unbrauchbar. Ich werde diese Variante evtl. noch bis zur Benutzbarkeit bearbeiten, aber das ist unsicher - aufgrund der prinzipiellen Probleme von Shadow Mapping wird die beidseitige Variante definitiv immer Light Bleeding-Artefakte enthalten, weswegen ich sie für den praktischen Gebrauch für untauglich halte.

Die vorgeschlagene Methode erreicht in der Praxis meist eine deutlich bessere Performance als NVidias PCSS. Sie hat besonders dann einen Vorteil, wenn die Schattenauflösung geringer als die Bildschirmauflösung ist. Im Prototypen ist das ab mittleren Fenstergrößen der Fall. Bei uns auf den Splitterwelten mit dem Bodenbewuchs, der vielfachen Overdraw verursacht, dürfte die Technik ihre Stärken deutlicher zeigen. Die Kegelparameter sind zudem sauber interpolierbar, der Helligkeitsverlauf an den Schattenkanten ist also frei von Banding-Artefakten.

Nachteile sind vor allem der begrenzte Radius der Schattenübergänge, der vor allem durch die Breite der Filter bei der ShadowMap-Nachbearbeitung bestimmt wird. Zudem kann die Technik mehr Rechenzeit als rein sample-basierende Methoden kosten, falls die ShadowMap gleiche oder höhere Auflösung als die Bildschirmauflösung hat. Zudem ist die Kombination der Filter-Ergebisse über eine einfache Auswahl des nahesten Hindernisses hinaus bislang noch ein ungelöstes Problem.

Diskussion

Mich würde jetzt interessieren, was ihr davon haltet. Die Methode hat noch ihre Macken, aber ich denke, dass der Ansatz vielversprechend ist. Besonders die Verlagerung der Rechenzeit hin zur Shadow Map klingt für mich sehr reizvoll, da wir wie gesagt durch unseren dichten Bodenbewuchs mit vielfachem Overdraw zu kämpfen haben. Depth Cone Shadow Mapping leistet in diesem Szenario gute Dienste, da es beim Rendern der Szene gegenüber normalem Shadow Mapping kaum zusätzliche Rechenzeit frisst - ein zusätzlicher Texturzugriff und etwa 5 Mathe-Ops. Zudem halte ich die absolute Freiheit von Fehlbelichtungs-Artefakten für sehr wichtig - aus diesem Grund habe ich z.B. nie Variance Shadow Mapping benutzt.

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Stefan Zerbst
Moderator
Beiträge: 189
Registriert: 25.02.2009, 19:54

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Stefan Zerbst »

Hi,

also erstmal eines vorweg: Ich habe mit Shadow Maps bisher nur wenig gemacht, schon gar keine eigene Implementierung halbwegs zeitgemäßer Techniken. Aber lästern kann man ja trotzdem, gell? :mrgreen:

Vom Prinzip her klingt das erstmal nach einer guten Idee die so noch keiner berücksichtigt hat. In deiner Demo bietet deine gepflegte Variante auch meistens den schönsten Schatten. Aber man bekommt doch relativ schnell das folgende Bild hin, in dem die ersten beiden Techniken dir deutlich davonziehen:
Bild

Dafür ist aber sehr gut, dass du Qt verwendest. :lol:

Mich würde nun interessieren, woher diese Artefakte kommen. Zudem habe ich nicht ganz verstanden, wie das mit der Auswahl des Hindernisses funktioniert bzw. was genau so ein Hindernis ist. Ich bin auch zu faul mich da selbst reinzulesen und wäre daher für Ausklärungsarbeit dankbar.

Zu guter Letzt:
[klugscheiss]
"projizieren" schreibt man auch nach Dutzenden von Orthographie-Reformen immer noch mit nur zwei "e", oder?
[/klugscheiss]

Gerade wenn man in großen Softwareprojekten nach bestimmten Begriffen sucht brechen einem solche Schnitzer das Genick. Ich erinnere mich nur zu gut daran, in unserer Software verzeifelt nach "BspLeaves" (BspLeafs) oder "Indices" (Indexes) gesucht zu haben :P

Ciao,
Stefan
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von CodingCat »

Ich scheitere leider auch daran, genauer nachzuvollziehen, wo jetzt die beschriebenen Abstände liegen. Prinzipiell hört sich die Technik durchaus sinnvoll an und funktioniert, wie in der Demo zu sehen, ja auch ganz gut, sofern du die von Stefan bereits angemerkten Artefakte noch in den Griff bekommst. Zum Punkt der Sample-Zahl kommt mir spontan in den Sinn, dass aus Gründen des Aliasings wohl am Ende trotzdem einige Samples erforderlich sein werden, auch wenn die Penumbra mittels deiner Überlegungen möglicherweise ohne berechenbar ist. Bringt die Technik in diesem Szenario dennoch Performance-Vorteile gegenüber Percentage Closer Soft Shadows?
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Schrompf »

Stefan Zerbst hat geschrieben:Aber lästern kann man ja trotzdem, gell? :mrgreen:
Ja, ich habe ja darum gebeten :-)

Zu den Rändern: ja, das ist bekannt. Den Fehler hatte ich im Ausgangspost als "unschöne Folgen der Interpolation" bezeichnet, habe aber so recht noch keine Idee, wie ich das beheben soll... vielleicht irgendwie den Kegel abschneiden, bevor es soweit kommt. Ohne bilineare Interpolation sieht's sauber aus, aber dann ist das ja kein Gewinn mehr.

@Sample-Anzahl: Das ist eine gute Frage. Die neue Methode betrifft ja erstmal nur die Penumbra. Der Kernschatten ist bewusst mit Standard-ShadowMapping umgesetzt, weil diese Technik absolut frei von Light Bleeding ist. Man kann also auf den Kernschatten jegliche Erweiterung anwenden, die man auch auf Standard-ShadowMapping anwenden kann. Und man sollte auch, aus offensichtlichen Gründen :-) Ich habe allerdings zu Demonstrationszwecken bewusst auf jede weiterführende Technik verzichtet und extra platte Texturen gewählt, damit die Stärken und Schwächen deutlich zu sehen sind. Mit realistischen Texturen und Lichtverhältnissen sieht auch NVidias PCSS nahezu perfekt aus... *hüstel*

Ich persönlich würde in den Splitterwelten wahrscheinlich ein halbtexel-weites Jittering einbauen, das sowohl auf Standard-SM als auch auf DepthCone-SM angewendet wird. Damit bekommt man etwas Gekriesel in die Penumbra, aber löst zumindest auch die harten Kanten des Schattenanfangs etwas auf. Hier wirklich noch 8xPCF oder sowas drauf zu tun, halte ich aber für Verschwendung, da der Schatten ja prima aussieht, sobald man zwei drei Texel Penumbra drumrum hat.

Ich werde aber auf jeden Fall noch daran rumprobieren und kann gerne hier von meinen Erfahrungen berichten. In Sachen Performance ist da noch einiger Raum, bis man auf Höhe von PCSS ist - die primäre Rechenzeit geht in das Filtern der ShadowMap, und ist damit mehr oder minder konstant. Der Szenen-Shader hat also noch Reserven für ein paar grundlegende Schatten-Verbesserungen, bevor der Performance-Gewinn aufgefressen ist. Hier muss man halt nur sehr genau schauen, ob sich das überhaupt lohnt.... Leute, die mittels scharf eingestelltem Cascaded SM im Nahbereich bereits nahezu Bildschirmauflösung in ihren Schatten haben, würden durch das Vorfiltern wahrscheinlich sogar an Performance verlieren.

@projizieren: Oh, Danke. Wieder was gelernt. Ich habe es editiert.

Und zum Schluss @Hindernissuche.

Das ist der Kern der vorgestellten Technik und damit etwas knifflig zu erklären. Ausgangspunkt ist, dass man für die Beschreibung des Helligkeitsverlauf in einem einfachen Schattenkegel zwei Parameter braucht: die Starttiefe des Kegels "an der Spitze" sozusagen, und der (aus Sicht des Lichts) seitliche Abstand zum Kegelmittelpunkt. Nennen wir den Tiefenabstand zur Kegelspitze mal "dd" wie Distance Depth und den seitlichen Abstand "do" wie Distance Offset. Wenn das seitliche Offset im ShadowMap-Space gegeben ist, also für einen Texel z.B. 1/1024, dann ist der Tiefenabstand in Tiefenschritten gegeben, also in Vielfachen der Distanz, die der Kegel pro Radiuserweiterung um ein Offset länger wird. Der Tiefenschritt ist also ein Maß dafür, wie schnell der Kegel mit der Entfernung breiter wird, leitet sich also indirekt aus der Ausdehnung der Lichtquelle ab. Ich versuche mich mal in einer Zeichnung.
shtest_skizze.JPG
Das schattenwerfende Hindernis liegt hier auf der Tiefe 0.2. Der Kegel der Penumbra fängt also bei Tiefe 0.2 an und wird mit jedem Texel seitlichem Abstands um 0.2 tiefer. Mit der Formel "licht = saturate((do + epsilon) / (dd + epsilon))" bekommt man also folgende Helligkeiten entlang der Tiefe:

Direkt auf der Kante, do == 0; 1.0 bis zum Hindernis, danach 0.0 - deswegen das Epsilon als kleiner Trick.
Einen Texel weiter rechts: do == 1; 1.0 bis zum Hindernis, 1.0 auch noch bis Hindernistiefe + einen Tiefenschritt, ab da dann absinkend 0.5, 0.33, 0.25, 0.2, usw.
Zwei Texel weiter rechts: do == 2; 1.0f bis zum Hindernis, 1.0 auch noch bis Hindernistiefe + zwei Tiefenschritte, ab da dann absinkend 0.66, 0.5, 0.4, 0.33, usw.

Auf die Art entsteht also ein solider Helligkeitsverlauf mit zunehmender Tiefe und Abstand von der Kante. Die Penumbra. Prima soweit, nur müssen wir dazu eine DepthCone-ShadowMap basteln, die pro Texel eben den seitlichen Abstand und die Starttiefe des dort wirksamen Kegels enthält. Und dazu filtern wir die ShadowMap wie folgt - vereinfacht für den 1D-Fall:

Wir sitzen auf einem Texel der ShadowMap, der eine EigenTiefe hat. Wir schauen jetzt alle ShadowMap-Texel in der Umgebung dieses Zieltexels an. Jeder benachbarte Texel hat eine FremdTiefe, wo ein Hindernis liegt und ab da alles hinter sich in Schatten taucht. Und dieser benachbarte Texel hat auch einen seitlichen Abstand zu uns, ein Offset. Wenn jetzt dieser Nachbar-Texel einen Penumbra-Kegel auf unseren Texel werfen würde, dann wäre dieser Kegel bei uns "KegelTiefe = FremdTiefe + SeitlichesOffset * Tiefenschritt" tief. Wenn diese KegelTiefe vor unserer EigenTiefe und auch vor dem bisherigen Kegelfavouriten liegt, dann behalten wir seine Kegelparameter - die FremdTiefe als Starttiefe des Kegels und den seitlichen Abstand. Mit dieser Methode bekommen wir als eine alternative ShadowMap, in der für jeden Texel steht, welcher Penumbrakegel an dieser Stelle vorherrscht.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Dirk Schulz »

Hi,

find ich echt klasse, was du dir immer für Sachen ausdenkst. Wenn man drüber nachdenkt eigentlich "simpel", aber vorher ist noch nie jemand drauf gekommen und immer leicht zu implementieren!

Die Artefakte kommen daher, dass die Entfernung zwischen Objekt und Receiver so groß ist, dass der Kegel ausserhalb deines maximalen Radius gelangt.
Wenn ich in deinem Shader CONEMAXRADIUS auf 10 setze, habe ich keine Artefakte mehr.

Falls du den Radius aber nicht vergrößern willst, sondern nur die auffälligen Artefakte wegbekommen willst, solltest du an der Zeile nochmal rumschnippeln:

scene.shader Zeile 159:

Code: Alles auswählen

float distToConeBase = min( saturate( receiverDepth - outerConeBase), MAXCONEDEPTH) / DEPTHSTEP;
wenn ich dort MAXCONEDEPTH mit CONEMAXRADIUS austausche, fallen die Artefakte schon geringer aus!

Vielleicht hilft dir ja meine Beobachtung!

Dirk Schulz

PS: Weiter so! :D
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Schrompf »

Moin Dirk,
Dirk Schulz hat geschrieben: find ich echt klasse, was du dir immer für Sachen ausdenkst. Wenn man drüber nachdenkt eigentlich "simpel", aber vorher ist noch nie jemand drauf gekommen und immer leicht zu implementieren!
Danke für die netten Worte! Ich habe bei so anscheinend simplen Sachen immer die Angst, dass es Gründe gibt, warum das niemand macht... quasi, als ob ich auf unüberwindbare Nachteile der Idee stoßen werde, die schon jeder andere kennt, und deswegen bisher niemand was dazu geschrieben hat. Aber genau weiß man das ja nie, bis man es ausprobiert hat....
Die Artefakte kommen daher, dass die Entfernung zwischen Objekt und Receiver so groß ist, dass der Kegel ausserhalb deines maximalen Radius gelangt.
Wenn ich in deinem Shader CONEMAXRADIUS auf 10 setze, habe ich keine Artefakte mehr.
"Keine Artefakte" dürfte nach meinem Verständnis nicht passieren, sie verschieben sich nur mit erhöhtem Radius weiter nach hinten.
Falls du den Radius aber nicht vergrößern willst, sondern nur die auffälligen Artefakte wegbekommen willst, solltest du an der Zeile nochmal rumschnippeln:
scene.shader Zeile 159:

Code: Alles auswählen

float distToConeBase = min( saturate( receiverDepth - outerConeBase), MAXCONEDEPTH) / DEPTHSTEP;
wenn ich dort MAXCONEDEPTH mit CONEMAXRADIUS austausche, fallen die Artefakte schon geringer aus!
Hmm... das verwirrt mich. MAXCONEDEPTH ist die ShadowMap-Tiefe, bis zu der der Kegel sich verbreitern darf, bevor er größer als die Vorfilter-Breite würde. Da ich die SM-Tiefe im Wertebereich 0.0 bis 1.0 halte, liegt die MAXCONEDEPTH so im Bereich 0.1f oder so... CONEMAXRADIUS ist aber die Filterbreite in Texeln, also momentan 7. Mit der Änderung hättest Du also die Tiefenbegrenzung praktisch aufgehoben.

Das müsste sich dann so äußern, dass innerhalb der filter-erzeugten Kegelbreite die Penumbra-Helligkeit sich weiter verdunkelt, wie als würde der Kegel auf den benachbarten Pixeln weiterwachsen, aber die benachbarten Pixel würden mangels Filterbreite gar keine Penumbra mehr abbekommen. Das müsste bei langen Schatten recht harte Abbruchkanten ergeben, aber die sichtbaren Ränder nicht beeinflussen. Die entstehen nämlich dadurch, dass die Graka an der Stelle zwischen einem validen Kegel-Parameter-Satz von recht weit außen und einem invaliden Parametersatz interpoliert, der sich wie "sehr nahe am Kegelzentrum" liest.

Was ich dagegen mache, weiß ich noch nicht. Aber auf jeden Fall Danke für den Denkanstoß!

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Dirk Schulz
Establishment
Beiträge: 130
Registriert: 01.03.2009, 14:21
Alter Benutzername: frittentuete

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Dirk Schulz »

Hi,

ja, ich habe damit unabsichtlich die Tiefenbegrenzung ausgeschaltet. :D

Da dadurch aber der Radius über die Filterbreite hinaus gestreckt wird, fällt es nicht so auf. Optimal ist es natürlich trotzdem nicht.

Wo liegt denn der Unterschied zwischem "validen" und "invalidem" Parametersatz? Es wird doch die gesamte Coneshadowmap mit Standardeinstellungen initialisiert.

Wenn man im SceneShader Point-Sampled, dann gibt es die Artefakte auch. :(
Hast du mal versucht die ConeShadowmap mit 128Bit auszustatten?

Dirk Schulz
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Weiches Shadowmapping mittels Tiefenkegel-Projektion

Beitrag von Schrompf »

Moin Dirk,
Dirk Schulz hat geschrieben: Wo liegt denn der Unterschied zwischem "validen" und "invalidem" Parametersatz? Es wird doch die gesamte Coneshadowmap mit Standardeinstellungen initialisiert.
Ok, "invalid" war ein unpassendes Wort. Der Standardwert für einen ConeSM-Texel ist (Texeltiefe, 0) - also Abstand 0 zum Zentrum eines Kegels mit der Starttiefe des ShadowMap-Texels da. Das passt zu Texeln, die als Hindernisse einen Kegel auf benachbarte Texel werfen - die Interpolation der GPU interpoliert dann korrekt von innen nach außen zu aufsteigenden Cone-Parametern. Am Rand des Kegels aber, wo der letzte Kegelrand-Texel noch (Kegeltiefe, MAXRADIUS) hat und der Nachbarpixel wieder (AndereTiefe, 0) hat, ergibt die Interpolation halt Mist - der Shader liest dort einen Wert, der wie irgendwo auf dem Kegel aussieht, und dunkelt die Stelle entsprechend ab.

Ich habe bereits probiert, den Default auf (Kegeltiefe, MAXRADIUS) zu ändern - wenn man die Quer- und Längsfilter ordentlich anpasst, verschwinden damit wie erwartet die Kegelränder. Allerdings sieht jetzt das Innere der Kegel Scheiße aus... wenn man vom Kernschatten nach außen hin schaut, hat man da nochmal eine dünne schattenfreie Kante, bevor der Kegel anfängt. Das ist also auch Mist.

Ich glaube, die Lösung liegt darin, einen pixelbreiten Saum um den Standard-Kegelverlauf zu generieren, der die Kegelschattierung irgendwie deaktiviert. Wie die Zahlen aussehen müssten, weiß ich aber noch nicht. Mal gucken, ob ich am Wochenende mal wieder Zeit dafür finde.
Wenn man im SceneShader Point-Sampled, dann gibt es die Artefakte auch. :(
Hast du mal versucht die ConeShadowmap mit 128Bit auszustatten?
Wenn ich die bilinearen Filter für die ConeSM abschalte (QD3DWidget.cpp, Zeile 464ff), verschwinden bei mir die Artefakte:
shtest_pointfilter.JPG
Könnte man dann evtl. mit etwas Jittering ausgleichen, um ein Dithern der Übergänge zu erreichen. Wär aber meiner Meinung nach schon ein Verlust, die Interpolierbarkeit der Kegelparameter hielt ich für einen der Vorteile dieser Technik.

Präzisionsprobleme können wir dagegen ausschließen, denke ich. Wenn ich die Formate auf A32B32G32R32F erweitere (QD3DWidget.cpp, Z118 und Z123), ändert das gar nix... außer dass die Framerate auf der NVidia Quadro meines Arbeitsrechners fast auf die Hälfte einbricht :)

Bye, Thomas
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten