Photonmapping - Wie kann man gleichmäßig helle Wände erzeugen?
-
rapso schrieb:
ja, je kleiner der anteil den du rauswirfst, desto kleiner der bias. wenn du bei 0 ankommst bist du wieder unbiased. hat aber nicht mehr wirklich was damit du tun dass du etwas rauswerfen und trotzdem unbiased sein wolltest
Das habe ich genau wo geschrieben?
-
otze schrieb:
rapso schrieb:
ja, je kleiner der anteil den du rauswirfst, desto kleiner der bias. wenn du bei 0 ankommst bist du wieder unbiased. hat aber nicht mehr wirklich was damit du tun dass du etwas rauswerfen und trotzdem unbiased sein wolltest
Das habe ich genau wo geschrieben?
otze schrieb:
folgendes ist unbiased:
Für N gezogene strahlwerte wirfst du g(N) raus wobei
wenn du über die verbleibenden N-g(N) strahlen mittelst, erhälst du im limit einen unbiased estimator der für endliche N robust(im statistischen Sinne) ist.und das ist eben nicht korrekt da es biased ist solange g(N)> 0 pfade. also selbst wenn du gegen unendlich gehst, und auch wenn g(N) statistisch gesehen unbedeutend klein gegenueber dem eigentlichen N ist, ist es biased. wenn du so willst, ist die bias 'funktion' f(x) binaer, entweder ist x==0 -> unbiased oder x!=0 -> biased und N/g(N) ist dabei unbedeutend, was zaehlt ist einzig ob g(N)==0.
-
nein, bei N->inf ist es unbiased,zumindest solange du endliche Varianz annimmst. wir ziehen samples x_1,...x_N und entfernen die ersten x_1,...,x_g(N). Zur Vereinfachung nehme ich zusätzlich an, dass -C< x_i < C
nun zum limit.Der erste Term:
\lim_{N \rightarrow \infty }\frac N {N-g(N)} (\frac 1 N\sum_{i=1}^N x_i) = [\lim_{N \rightarrow \infty }\frac N {N-g(N)}] \lim_{N \rightarrow \infty }\frac 1 N\sum_{i=1}^N x\_i = [\lim\_{N \rightarrow \infty }\frac 1 {1-g(N)/N}] E_{p(x)}\{x\}=E_{p(x)}\{x\}der letzte Schritt gilt wegen g(N)/N->0
das der zweite Term gegen 0 geht braucht dann endliche Varianz oder ähnliches. Nach der zusätzlichen Annahme ist
-
ich glaube du vergisst dass N (bzw g(N), bzw die ganze gleichung) eine natuerliche zahl ist. entweder du hast alle strahlen oder, wenn 1 oder mehr entfernt wurden und du die restlichen nur mittelst, bist du biased.
deswegen sagte ich ja dass es eine binaer entscheidung ist.
entfernst du 0 strahlen ohne mit dem richtigen kriterium zu normalisieren (also mitteln) -> unbiased
entfernst du >0 strahlen ohne mit dem richtigen kriterium zu normalisieren (also mitteln) -> biasededit:
stell es dir als grundsatz vor, wie bei division, du kannst gerne n gegen 0 gehen und dagegen teilen, aber du kannst nicht durch 0 teilen.
-
rapso schrieb:
ich glaube du vergisst dass N (bzw g(N), bzw die ganze gleichung) eine natuerliche zahl ist. entweder du hast alle strahlen oder, wenn 1 oder mehr entfernt wurden und du die restlichen nur mittelst, bist du biased.
quatsch. Siehe konvergenz von Folgen sowie die Gesetze der großen Zahlen. Du kannst ja anfangen meinen Bweis zu widerlegen. Und nebenbei auch
http://en.wikipedia.org/wiki/Consistent_estimator
durchlesen(insbesondere den untersten abschnitt über konsistente Schätzer mit Bias). Das limitargument ist eigentlich ganz einfach zu verstehen: wenn der Schätzer biased ist, dann findest du ein epsilon > 0, sodass der Wert des Schätzers in Erwartung um mindestens epsilon abweicht. Der Beweis zeigt dass der Bias im limit gegen 0 geht und es deswegen dieses Epsilon nicht gibt. Dies verträgt sich aber nicht mit der Annahme, dass der Schätzer im limit biased ist.
-
otze schrieb:
rapso schrieb:
ich glaube du vergisst dass N (bzw g(N), bzw die ganze gleichung) eine natuerliche zahl ist. entweder du hast alle strahlen oder, wenn 1 oder mehr entfernt wurden und du die restlichen nur mittelst, bist du biased.
quatsch. Siehe konvergenz von Folgen sowie die Gesetze der großen Zahlen. Du kannst ja anfangen meinen Bweis zu widerlegen. Und nebenbei auch
http://en.wikipedia.org/wiki/Consistent_estimator
durchlesen(insbesondere den untersten abschnitt über konsistente Schätzer mit Bias). Das limitargument ist eigentlich ganz einfach zu verstehen: wenn der Schätzer biased ist, dann findest du ein epsilon > 0, sodass der Wert des Schätzers in Erwartung um mindestens epsilon abweicht. Der Beweis zeigt dass der Bias im limit gegen 0 geht und es deswegen dieses Epsilon nicht gibt. Dies verträgt sich aber nicht mit der Annahme, dass der Schätzer im limit biased ist.
achso, jetzt sehe ich dein versehen. consistence und bias sind verschiedene dinge. z.B. ist photonmapping consistent und liefert genau wie dein anstaz in der unendlichkeit das richtige resultat, dennoch ist es biased, genau wie deine idee solange du nicht mit dem attribut normalisierst mit dem du die paths verwirfst.
vielleicht verstehst du es mit formeln besser, es gilt dass
und
fuer
wenn S die sampling funktion ist, der parameter die path anzahl, statistisch
oder anders gesagt, wenn XNAMan jeden tag ein unbiased Bild mit X samples/Pixel rendert und sich das durschnittsbild bilded, kann er irgendwann aufhoeren wenn ihm die Bildqualitaet gefaellt ohne angst haben zu muessen, dass es einen fehler (ausgenommen des rauschens) gibt.
bei einem biased renderer muss er komplett X*N samples/Pixel rendern und kann dann das resultat betrachten und darf sich nicht gewiss sein, dass ein optisch ansprechendes Bild richtig ist, weil es sein kann dass bei X*(N+1) sich die bildinformation aendert (z.b. ein neuer stern am himmel zu sehen ist).
-
der unterschied ist mir bekannt. deswegen sagte ich ja "im limit unbiased" was eine notwendige, aber keine hinreichende Bedingung für Konsistenz ist.
Aber ich glaub, wir sind jetzt beim selben Punkt, also passt das.
-
otze schrieb:
der unterschied ist mir bekannt. deswegen sagte ich ja "im limit unbiased" was eine notwendige, aber keine hinreichende Bedingung für Konsistenz ist.
ja, deswegen antwortete ich, es ist im limit wohl consistent, aber bleibt biased, sonst waere jeder consistent algorithmus unbiased.
Aber ich glaub, wir sind jetzt beim selben Punkt, also passt das.
ok
-
rapso schrieb:
gut job
solide dass du dich da so verbissen hast bis es gute resultate gibt!
das radiosity bild schaut nicht ganz richtig aus, als ob irgendwas mit texture mapping falsch waere.
wir wollen hier jetzt natuerlich deinen raum sehen mit photonmapping (und den anderen versionen falls du die muesse hast )
So rapso, du sagst, dass mein Radiosity noch nicht ganz ok ist? Ich habe den Algorithmus nun korrigiert. Ich bin jetzt wieder voll drin im Raytracing-Fiber^^ Hier ist nun mein neues Radiosity-Bild:
http://s22.postimg.org/mj5e1yy6l/Radiosity1.png
-
schaut gut aus, aber ich werde wieder meckern dass ich da antialiasing sehen will
photonmapping hat einen leichten rot bias, radiosity hingegen leicht richtung blau. falls du floats benutzt, versuch mal doubles, vielleicht hast du ein precission problem weil du soviele werte accumulierst.
-
rapso schrieb:
schaut gut aus, aber ich werde wieder meckern dass ich da antialiasing sehen will
photonmapping hat einen leichten rot bias, radiosity hingegen leicht richtung blau. falls du floats benutzt, versuch mal doubles, vielleicht hast du ein precission problem weil du soviele werte accumulierst.
Das mit den Aliasing gebe ich dir recht. Das stört mich selber. Momentan hat meine Funktion zum Auslesen eines Texels lediglich die Möglichkeit, dass ich von genau einen Pixel aus der Bitmap lese, oder ich lese von 4 Pixeln mit 4 Wichungsfaktoren(Summe ist 1).
Leider bringt dieses 4-Pixel-Interpolieren voll wenig. Kann es sein, dass ich einfach ein anderen Filter noch nehmen muss? Was würdest du mir empfehlen?
-
XMAMan schrieb:
Leider bringt dieses 4-Pixel-Interpolieren voll wenig. Kann es sein, dass ich einfach ein anderen Filter noch nehmen muss? Was würdest du mir empfehlen?
ich denke du sprichst hier ueber textur filtering, oder? ich sprach eher vom bild.
ein pixel in deinem bild ist eine flaeche, du zeichnest jedoch immer nur die farbe eines speziellen unktes innerhalb dieser flaeche.
zumindestens beim path tracing (als referenz) solltest du versuchen bei jedem neuen strahl von einer anderen position innerhalb des pixels zu feuern. im simpelsten fall hast du sowasfor(int x=0;x<width;x++) { float3 Direction(float(x)/width,...); }
das solltest du in sowas aendern koennen
for(int x=0;x<width*AA;x++) { float3 Direction((float(x)+float(rand())/RAND_MAX)/(width*AA),...); }
damit hast du pro pixel einen zufaelligen wert innerhalb des pixels.
das geht natuerlich noch viel besser, aber fuer den anfang sollte das, gerade mit den tausenden von strahlen pro pixel die du abfeuerst, gut resultate liefern.
das filtern aus 4 punkten einer textur hilft dir beim hochskalieren. das macht aber nicht wirklich etwas besser, selbst wenn es aliasing loest, weil es dann matsch gibt (wobei das meine persoenliche meinung ist).
fuer gute qualitaet wuerdest du eigentlich mehr texel als pixel brauchen.der richtige filter ist dann ein wenig aufwendig. du musst nicht einfach einen punkt haben aus dem du interpolierst, du musst den pixel im screen auf die textur projezieren und dort jeden texel entsprechend der abdeckung einbeziehen. das wird aber noch aufwendiger wenn du reflektionen einbeziehen moechtest, ein pixel projeziert auf eine spiegelnde kugel kann dann eventuell eine ganze textur abdecken.
deswegen ist das supersampling mittels antialiasing, wie oben beschrieben, zu bevorzugen. denn zum antialiasing von geometrie und shading, bekommst du texture-antialiasing 'for free'.
-
rapso schrieb:
XMAMan schrieb:
Leider bringt dieses 4-Pixel-Interpolieren voll wenig. Kann es sein, dass ich einfach ein anderen Filter noch nehmen muss? Was würdest du mir empfehlen?
ich denke du sprichst hier ueber textur filtering, oder? ich sprach eher vom bild.
ein pixel in deinem bild ist eine flaeche, du zeichnest jedoch immer nur die farbe eines speziellen unktes innerhalb dieser flaeche.
zumindestens beim path tracing (als referenz) solltest du versuchen bei jedem neuen strahl von einer anderen position innerhalb des pixels zu feuern. im simpelsten fall hast du sowasfor(int x=0;x<width;x++) { float3 Direction(float(x)/width,...); }
das solltest du in sowas aendern koennen
for(int x=0;x<width*AA;x++) { float3 Direction((float(x)+float(rand())/RAND_MAX)/(width*AA),...); }
damit hast du pro pixel einen zufaelligen wert innerhalb des pixels.
das geht natuerlich noch viel besser, aber fuer den anfang sollte das, gerade mit den tausenden von strahlen pro pixel die du abfeuerst, gut resultate liefern.
das filtern aus 4 punkten einer textur hilft dir beim hochskalieren. das macht aber nicht wirklich etwas besser, selbst wenn es aliasing loest, weil es dann matsch gibt (wobei das meine persoenliche meinung ist).
fuer gute qualitaet wuerdest du eigentlich mehr texel als pixel brauchen.der richtige filter ist dann ein wenig aufwendig. du musst nicht einfach einen punkt haben aus dem du interpolierst, du musst den pixel im screen auf die textur projezieren und dort jeden texel entsprechend der abdeckung einbeziehen. das wird aber noch aufwendiger wenn du reflektionen einbeziehen moechtest, ein pixel projeziert auf eine spiegelnde kugel kann dann eventuell eine ganze textur abdecken.
deswegen ist das supersampling mittels antialiasing, wie oben beschrieben, zu bevorzugen. denn zum antialiasing von geometrie und shading, bekommst du texture-antialiasing 'for free'.
Meine Funktion zur Erzeugung eines Primärstrahls sieht bereits so aus:
public static Strahl GetPrimärStrahlForPixel(Kamera kamera, int screenWidth, int screenHight, int x, int y, Random rand) { float kameraAbstand = kamera.GetKameraAbstandFromBildebene(); float f = (float)screenWidth / (float)screenHight; float fx = 0, fy = 0; if (rand != null) { //Gleichverteilung (Sieht nicht so cool aus) //fx = (float)rand.NextDouble() * 2 - 1; //fy = (float)rand.NextDouble() * 2 - 1; //Tent-Filter (Erzeuge mit größerer Wahrscheinlichkeit in der Mitte des Pixels ein Strahl) (Die Verteilungsfunktion ist ein Dreieck/Zelt). Deswegen Tent-Filter float r1 = 2 * (float)rand.NextDouble(); float r2 = 2 * (float)rand.NextDouble(); fx = r1 < 1 ? (float)Math.Sqrt(r1) - 1 : 1 - (float)Math.Sqrt(2 - r1); //Erzeugt Zahl zwischen -1 und +1 fy = r2 < 1 ? (float)Math.Sqrt(r2) - 1 : 1 - (float)Math.Sqrt(2 - r2); //-1 + +1 } //Die Bildebene ist f Breit und 1 Hoch Vektor bildEbenenPunkt = new Vektor(+((x + fx + 0.5f) / (float)screenWidth * f - f / 2), -(((y + fy + 0.5f) / (float)screenHight) - 0.5f), 0); return new Strahl(new Vektor(0, 0, 0), Vektor.Normiere(bildEbenenPunkt - new Vektor(0, 0, kameraAbstand))); }
Die Zahlen fx und fy sind meine Zufallszahlen, welche den Strahl so versetzen, dass er nicht immer nur durch die Pixelmitte geschossen wird. Trotzdem habe ich das Gefühl das bringt kein sichtbaren Effekt. Woran kann das liegen?
-
versuch etwas sehr simples, tent glocke ist nicht wirklich sinnvoll. ein camera sensor hat auch keinen bias.
zudem samplest du immer ueber 2 pixel, 1pixel sollte reichen fuers erste (mehr pixel koennen in der realitaet passieren, aber in einer simplen, idealisierten welt reicht erstmal 1pixel).public static Strahl GetPrimärStrahlForPixel(Kamera kamera, int screenWidth, int screenHight, int x, int y, Random rand) { float kameraAbstand = kamera.GetKameraAbstandFromBildebene(); float f = (float)screenWidth / (float)screenHight; float fx = 0, fy = 0; assert(rand!=null); //Gleichverteilung (Sieht nicht so cool aus) fx = (float)rand.NextDouble(); fy = (float)rand.NextDouble(); //Die Bildebene ist f Breit und 1 Hoch Vektor bildEbenenPunkt = new Vektor(+((x + fx) / (float)screenWidth * f - f / 2), -(((y + fy) / (float)screenHight) - 0.5f), 0); return new Strahl(new Vektor(0, 0, 0), Vektor.Normiere(bildEbenenPunkt - new Vektor(0, 0, kameraAbstand))); }
poste mal ein bild davon.
wenn das holz auf dem fussboden immer noch aliast, nimmfx = (float)rand.NextDouble()*10-5; fy = (float)rand.NextDouble()*10-5;
dann sollte es sehr verschwommen aussehen.
zudem waere dein resolve der pixel interesant, vielleicht hast da ja noch ein bug. (also die stelle wo du alle samples zu einem pixel verrechnest.
-
So sieht Variante 1 von dein Vorschlag aus:
http://s3.postimg.org/hmbydgcbz/rapso1.png
So sieht Variante 2 aus:
http://s3.postimg.org/3rdnuzhwv/rapso2.png
Pro Pixel sende ich 100 Strahlen. Ich bilde einfach die Summe von diesen 3 Floatzahlen und teile das Ergebniss dann durch 100. Klingt erstmal nicht nach viel Möglichkeiten zum falschmachen.
-
der boden schaut doch schonmal sehr viel besser aus.
an den fenstern gibt es noch aliasing weil der kontrast zu gross ist. in spielen machen wir deswegen erst das tonemapping und dann den resolve. nicht ganz korrekt, aber bei wenig samples ist das resultat netter.
aber an sich richtig, oder hast du an irgendwas etwas auszusetzen?
-
Naja... Wenn ich Variante 1 von dir mit mein Radiosity-Bild vergleiche, dann finde ich, sieht der Boden relativ gleichverpixelt noch aus. Der Fußboden, der sehr Nah am Betrachter liegt, ändert sich nicht sichtbar für mich. Der Bereich, welcher weiter hinten liegt wird ein wenig weicher/weniger Pixelig. Dafür habe ich nun das Problem an den Fensterkanten. Die sehen bissel ausgefranst aus.
Ich glaube, wenn man wirklich eine pixelfreie Textur haben will, dann geht das nur über Prozedural erstellte Texturen.
Eine Idee hätte ich übrigens auch noch und will mal wissen was dazu sagst.
Was passiert, wenn ich über ein prozedurales Verfahren eine Bumpmap erstelle, welche die Oberfläche von Holz darstellen soll, welche aber so genau ist, dass ein einzelnes Pixel gleich mehrere Huckel/Löcher enthält. Über Aliasing werde ich alles bei jeden Bumpnormal-Auslesen aus diesen Pixel verschiedene Bumpnormalen erhalten. Wenn ich damit dann die Beleuchtungsformel/Photonmap-Erstellung anwende. Könnte es dann klappen, dass ich so realistisches Holz erhalte?
-
XMAMan schrieb:
Naja... Wenn ich Variante 1 von dir mit mein Radiosity-Bild vergleiche, dann finde ich, sieht der Boden relativ gleichverpixelt noch aus. Der Fußboden, der sehr Nah am Betrachter liegt, ändert sich nicht sichtbar für mich. Der Bereich, welcher weiter hinten liegt wird ein wenig weicher/weniger Pixelig. Dafür habe ich nun das Problem an den Fensterkanten. Die sehen bissel ausgefranst aus.
die pixel nah dran sind keine Aliasing pixel. aliasing hast du wenn du zuviele daten hast bzw daten nicht genau genug samplen kannst. ganz nah hast du jedoch viel zu wenig daten.
die fenster sind ein HDR problem. die bekommst du entweder mit
-mehr samples
-besseren samples
in den gruff. bei filmen variiert die sample anzahl manchmal zwischen 7x7 und 33x33.
besseres samplen waere z.B. stratified sampling. statt 100 zufaellige samples zu nehmen, nimmst du 10x10 auf einem grid, wobei du jedes einzelne dann mit der random funktion um 0.1 pro achse random versetzt (so wie du das jetzt mit 1.0 random gemacht hast).Ich glaube, wenn man wirklich eine pixelfreie Textur haben will, dann geht das nur über Prozedural erstellte Texturen.
nicht zwingend, eine einfache moeglichkeit ist dass du eine detail textur benutzt. im einfachsten fall erstellst du eine z.b. 128x128 textur die du im einfachsten fall pro texel der holz textur anwendest.
bei einer detail textur ist grau (128,128,128) die neutrale farbe, darueber oder darunter verdunkeln oder erhellen die eigentliche textur. sowas wiecolor = tex2d(holz,UV)*(tex2d(detail,UV*128)*2.f-1.f)
du kannst verschiedene skalierungen der intensitaet nehmen, statt 2.f
du kannst mit verschiedenen UV skalierungen probieren
du kannst mehrere male die detail texture mit untershiedlichen UV und intensitaetsskalierungen anwenden.Eine Idee hätte ich übrigens auch noch und will mal wissen was dazu sagst.
Was passiert, wenn ich über ein prozedurales Verfahren eine Bumpmap erstelle, welche die Oberfläche von Holz darstellen soll, welche aber so genau ist, dass ein einzelnes Pixel gleich mehrere Huckel/Löcher enthält. Über Aliasing werde ich alles bei jeden Bumpnormal-Auslesen aus diesen Pixel verschiedene Bumpnormalen erhalten. Wenn ich damit dann die Beleuchtungsformel/Photonmap-Erstellung anwende. Könnte es dann klappen, dass ich so realistisches Holz erhalte?
damit simulierst du micro facet lighting.
das ist dann eher schon ein shading improvement. ist nicht wirklich relevant dafuer dass du nicht genug holz-textur-aufloesung hast. du wirst dann dennoch die texel vom holz sehen.holz ist eines der einfachsten prozeduralen materialien, mit ein wenig tweaken kannst du sowas realistisches erreichen:
http://modo.docs.thefoundry.co.uk/modo/701/help/pages/shaderendering/ShaderItems/Wood.html
gibt einige paper dazu, z.b.
http://developer.amd.com/wordpress/media/2012/10/ShadingCourse_Mitchell.pdf ab seite 18
-
rapso schrieb:
nicht zwingend, eine einfache moeglichkeit ist dass du eine detail textur benutzt. im einfachsten fall erstellst du eine z.b. 128x128 textur die du im einfachsten fall pro texel der holz textur anwendest.
bei einer detail textur ist grau (128,128,128) die neutrale farbe, darueber oder darunter verdunkeln oder erhellen die eigentliche textur. sowas wiecolor = tex2d(holz,UV)*(tex2d(detail,UV*128)*2.f-1.f)
du kannst verschiedene skalierungen der intensitaet nehmen, statt 2.f
du kannst mit verschiedenen UV skalierungen probieren
du kannst mehrere male die detail texture mit untershiedlichen UV und intensitaetsskalierungen anwenden.Erhalte ich dadurch nicht ein Schachbrettmuster, wenn ich für jeden Texel die gleiche Detail-Textur nehme? Stell dir mal vor ich nehme das jetzt für mein Holzfußboden. Die Pixel ganz vorne bei der Kamera kann man ja deutlich sehen. Wenn nun jeder dieser Pixel über eine Detail-Textur aufgehellt/abgedunkelt wird, dann müsste man doch dieses Muster dann immer-wieder-kehrend erkennen oder?
-
Ich habe heute mal etwas mit prozeduralen Texturen rumgespielt. Hat jemand eine Idee, wie man die Hatch-Texture, welche auf Seite 40 gezeigt wird, erzeugen könnte?
http://developer.amd.com/wordpress/media/2012/10/ShadingCourse_Mitchell.pdf