Posts by 2#4u

    Ok. Der Ansatz schaut in Ordnung aus für mich.
    Stimmt diese Zeile jetzt so?:

    Code
    1. [COLOR=blue]float[/COLOR] sampleDepth = [COLOR=maroon][B]texture[/B][/COLOR](scenePosViewSpace, offset.xy).z;


    Oder benutzt du hier scenePosWorldSpace?


    Oder anders gefragt. Wenn du "scenePosViewSpace" eh verfügbar hast, funktioniert SSAO dann wenn du

    Code
    1. originVS = vec4([COLOR=maroon][B]texture[/B][/COLOR](scenePosViewSpace, fragUV).xyz,1.0)

    setzt? Wenn es funktioniert, dann ist deine Textur "scenePosWorldSpace" falsch. Wenn es nicht funktioniert hat es was anderes am Algorithmus.


    Und die 1.0 als w-Komponente der homogenen Koordinaten passt. Du willst ja eine Position im World-Space zu einer Position im View-Spae umrechnen (mit Translation).

    Der Code ist einfach irgendwas. Was soll denn jetzt origin.z sein? Hast du jetzt zwei texturen? Eine mit view space positions und eine mit world space positions? scenePosWorldSpace ist aber nicht mal definiert. Dass du die Kamera-Position abgezogen hast, mag ja sein - wennst mir den Code dazu nicht zeigst, kann ich wenig dazu sagen. Ich hoffe mal, dass du danach nicht einfach wieder die Z-Komponente vom Resultat genommen hast.


    Also so nicht...

    Aha?


    Ich seh mal kein offensichtliches Problem mit dem if. Aber kann es sein, dass "currentDepth" einfach ein Topfen ist? Vielleicht ist das uniform für die light position nicht gesetzt oder sowas?


    Sobald dieser verwendet wird, rendert der Shader keine Objekte mehr, die ihm zugewiesen worden sind.


    Was genau heißt denn das? Sind dann Objekte schwarz, gibt es vielleicht einen Compile-Fehler beim Shader, der nicht ausgegeben wird?
    Was passiert, wenn ihr die Werte in der if Abfrage umdreht? Ist dann alles weiß?


    Funktioniert folgender Code?:

    Code
    1. result = 1.0 - [COLOR=maroon][B]step[/B][/COLOR](currentDepth - bias, closestDepth);


    Edit: Das mit CodeXL kann schon sein. Ich verlass mich bei Cubemaps nicht auf den Debugger. Das ist gefährliches Terrain :)

    Naja wenn du statt scenePosViewSpace jetzt eine Textur mit world space Koordinaten hast, dann wird das folgende nicht viel Sinn machen:


    texture(scenePosViewSpace, offset.xy).z;


    Denn das ist kein Tiefenwert mehr aus Sicht der Kamera.
    Um die Tiefe zu berechnen musst du die Koordinate aus der Textur holen und die Kamera-Position abziehen oder eben mit der View-Matrix multiplizieren...
    Wennst einen vollständigen Code postest, tu ich mir leichter zu erkennen was du verändert hast. Aber bitte mit [ code ] tags umhüllen...

    Hmm. Ok. Ja, schaut besser aus.


    Für's Konvertieren von Normalen einer Normal-Map in den View-Space geht man ungefähr so vor:
    - Normale (N_o), Tangente (T_o), Bitangente (B_o) sind gegeben im Object Space
    - Konvertieren mit Normalmatrix (N) und ViewMatrix (V) für view-space: N_v = V * N * N_o. Analog für T_v, B_v
    - Normalisieren der Vektoren
    - Erstellen von TBN Matrix. TBN = mat3(T_v, B_v, N_v)
    - Laden von Normalen aus Normal-Map-Textur im Tangent-space (N_ts)
    - Konvertieren von Normalen von Range [0,1] -> [-1,1]
    - Konvertierte Normale im view space ist dann: TBN * N_ts
    - Diese Normale noch normalisieren, fertig


    Wichtig wäre statt der Model-Matrix die Normal-Matrix zu benutzen, falls non-uniform scaling eines Objektes geschieht.


    Ich bin mir nicht sicher ob es sinnvoll ist die Normalen anhand einer Normal-Map für SSAO anzupassen. Denn für SSAO richtet man die Hemisphere für's Sampling anhand der gegebenen Normalen aus und prüft wie viele Samples in der Geometrie stecken. Die Geometrie ist aber die selbe, nur die Normale ist verdreht.


    Man kann das schon machen (Normal-Maps benutzen vor SSAO - hab ich auch schon gemacht), ich bin mir nur nicht sicher ob es richtig ist. Ich würde empfehlen die Normalen vom Objekt zu nehmen - also lass es lieber so :)

    Ja, für finale Abgabe wäre eine automatische Steuerung gewünscht (nicht nur für das Video). Die LVA Leitung versteht unter Demonstration eine eigenständig laufende Applikation - Ich hab das grad eben noch einmal bestätigen lassen. Es muss aber nicht komplex sein, im einfachsten Fall ist es eine geskriptete Rotation / Translation der Kamera durch die Szene. Falls ihr bereits animierte Objekte in eure Engine importieren könnt, dann könnt ihr auch die Kamera als animiertes Objekt behandeln - das wär eine andere Möglichkeit.


    Falls ihr mehr Anregungen braucht oder Probleme habt, meldet euch.

    [strike]Ich hab euch übrigens nicht vergessen - Ich warte noch auf Rückmeldung zu dem Thema von der LVA Leitung..[/strike]


    EDIT:
    Also. Tangenten könnt ich auch von Assimp berechnen lassen.
    Unabhängig davon muss man trotzdem verstehen wie Tangentenberechnung funktioniert für die Prüfung, da es Stoff der Vorlesung ist.

    Annahmen:


    scenePosViewSpace - enthält korrekte view position und der textur typ ist korrekt. D.h. eine float textur.
    sceneNormalSampler - enthält korrekte normalen und textur typ ist korrekt. Werte zwischen [-1,1]?
    noise texture - keine konvertierung von [0,1] nach [-1,1], daher auch hier: Textur typ sollte korrekt sein.


    Wenn ich mir euren Code ansehe, dann ist der eh fast gleich mit dem Chapman Tutorial.
    Das einzige was unterschiedlich ist, und dort sehe ich auch den Fehler, ist nach dem Samplen, die Occlusion Bestimmung.
    Das 1000.0f minus ... macht meines Erachtens überhaupt keinen Unterschied, außer, dass ihr alle Tiefenwerte invertiert (Annahme: Far-Plane <= 1000) und der Code unlesbar wird.
    Ich hab versucht mir das durchzudenken und eure step Funktion macht soweit ich das sehe, genau dann eine Occlusion wenn die gespeicherte Tiefe (texture(scenePosViewSpace, offset.xy).z) größer/gleich der Sampletiefe (screenSample.z) ist. Das ist aber genau falsch herum, weil das heißt, dass das gespeicherte Fragment hinter dem Sample liegt.


    Prüft mal meine Annahmen, ob das denn alles richtig konfiguriert ist und nehmt testweise den Code von Chapman und tested es noch einmal...

    Im Wesentlichen ist es egal, da ihr bei der Endabgabe sowieso eine eigenständige Kamerafahrt haben werdet (nehm ich an).


    Aber was damit gemeint ist, ist folgendes:
    Wenn man sich bei euch durch die Szene mit den Pfeiltasten bewegt und zB vorwärts drückt. Dann gibt es das Standard Keyboard-Input-Delay bis die Taste als gedrückt erkannt wird. Das delay ist im OS einstellbar. Anyway - 3D Engines, Spiele, etc. haben typischerweise dieses delay nicht - macht ja auch wenig Sinn, wenn man zB einen Character steuert und der zurerst einmal nach vorn hüpft, dann wartet und dann "normal" nach vorne geht...


    Der Unterschied zwischen beiden Varianten ist:
    1. Eventbasiert - Das Betriebssystem sagt euch mit Events wann eine Taste gedrückt ist - Da ist diese Delay inkludiert
    2. Polling - Ihr fragt direkt ab was der aktuelle Status (gedrückt/nicht gedrückt) einer Taste ist


    Mit GLFW zB wäre das:
    1. Eventbasiert - glfwSetKeyCallback(...)
    2. Polling - glfwGetKey(...)


    Ich hab mit SDL noch nicht gearbeitet, aber ich nehme an, dass SDL_GetKeyState oder SDL_GetKeyboardState das "Polling" realisiert worauf wir euch hinweisen wollten...

    Vielen Wenn so wohl Tangente als auch Bitangente verkehrt sind, hilft dieser Ansatz aber auch nicht weiter, oder verstehe ich da was falsch?


    Ja, ich würd sagen da hast du recht. Wenn es nur eine Rotation der beiden Vektoren in der Ebene um den Normalvektor ist, wird sich nix ändern. Es hilft beim Umwandeln von einem links- in ein rechtshändiges Koordinatensystem...




    Zum Berechnen der Tangenten mit Assimp: Wenn ich mich recht erinnere hat Professor Wimmer in der VO gesagt, dass wir die Tangenten selbst berechnen sollen, und nicht die Funktion von Assimp verwenden?


    Aha. Ich klär das mal mit der LVA Leitung ab..

    Ich nehme jetzt auch mal an, dass es an den Texturkoordinaten liegt. Du könntest ja mal die Texturkoordinaten visualisieren, dann sieht man theoretisch in welche Richtung die ansteigen und ob sie sich anders im Mittelteil verhalten. Wenn es an den Texturkoordinaten liegt, ist es am einfachsten diese im Modellierungsprogram für den Mittelteil umzudrehen, denn de-facto ist das Modell dann falsch modelliert. Wenn es nicht an den Texturkoordinaten liegt, dann sind höchstwahrscheinlich die Normalen invertiert.


    Zu deinem Ansatz mit dot(cross(normal, tangent), bitangent). Das kann nur funktionieren, wenn du die Tangente nicht aus der Normale und Bitangente herleitest. Das heißt im Shader wird das nicht mehr funktionieren. Ich kann deinem Text nicht entnehmen ob du das auf C++ oder GLSL Seite gemacht hast...


    Übrigens: Falls ihr Assimp zum Modell-Laden benutzt... Assimp kann Tangenten und Bitangenten für euch berechnen, muss man also nicht selbst machen...

    Zweiter Anlauf:


    Ich hab das jetzt mal ausprobiert und es liegt tatsächlich daran, dass ihr nicht-lineare Tiefenwerte benutzt. Wenn man eine linearisierte Tiefe benutzt - In meinem Fall: Der z-Wert im View-Space von [near,far] auf [0,1] umgerechnet, dann funktioniert es zumindest ohne diese Artefakte wie ihr sie gepostet habt. Es gibt aber noch immer ein Problem, dass die Schatten nicht ganz korrekt platziert sind, ich denke das kann mit einem Bias gelöst werden.


    Übrigens würde ich euch auch empfehlen, dass ihr eure SAT vertical/horizontal shader mit texelfetch arbeiten lasst, aber nicht so wie euer auskommentierter Code aussieht. Es geht genauer:



    Das empfehle ich deshalb, weil ihr derzeit mit relativen ungenauen float Koordinaten arbeitet und einen linearen sampler habt, der ständig zwischen SAT Werten interpoliert. Das ist nicht unbedingt präzise..

    Ok - Erster Anlauf:


    1. Zwei Compilefehler in Shader "default_f2.glsl" auf meinem System (NVidia Karte):


    Error: "OpenGL does not allow C style initializers":
    Ersetzen von: vec2 poissonDisk[16] = { ... };
    mit: vec2 poissonDisk[16] = vec2[](...);


    Error: "Cannot call a non-function":
    Ersetzen der Variablen 'min'/'max' mit 'minv'/'maxv':
    float minv = 0.2;
    float maxv = 1.0;
    p_max = clamp((p_max - minv) / (maxv - minv), 0, 1);
    return max(p, p_max);


    2. Normales VSM schaut falsch aus (siehe Anhang), wenn ich im Shader die Zeile "float shadow = calcShadowVSM(shadowCoord, shadowMap3);" einkommentiere.


    vsm.jpg
    Edit: Sorry, Hab übersehen, dass ihr das Verteilen der floating-point precision nicht bei der normalen Variance Shadow Variante benutzt. Schatten funktionieren eh auch bei der normalen Variante - Bild ist zu ignoreren.



    Grundsätzlich habe ich einen Fehler bei der Erstellung eurer SVM entdeckt.
    Laut dieses Blogs, müssen die Tiefenwerte linear im Bereich [0,1] sein (Abbildung von [near-plane, far-plane]), ihr benutzt aber gl_FragCoord.z als Tiefenwerte, die sind aber nicht linear.
    Das muss jetzt nicht das Problem wie im Bild sein, vielleicht mach ich auch was falsches einkommentiert. Aber ich denk das passt so, da shadowMap3 bei euch die "normale" Variance Shadow Map sein sollte.


    Benutzt doch mal lineare Tiefenwerte bzw. falls ich was falsch gemacht hab mit Rendern des Schattens, gebt Bescheid..

    Ich sehe jetzt kein offensichtliches Problem mit dem Code. Außer vielleicht dein Zugriff auf die Textur mit texture2D, das kommt aber darauf an wie du bzw. ob du filtering für die Textur aktiviert hast und ob filtering auf der SAT ein Problem darstellt. Ich nehme mal an, dass du eigentlich direkt auf die texel zugreifen möchtest - überleg dir dann ob du nicht lieber "texelFetch" benutzen willst statt "texture2D" mit genauen Pixelkoordinaten.


    Es ist schwierig zu sagen, ob deine SAT korrekt ist - die Attachments kann ich leider nicht öffnen. Summierst du vielleicht auf und benutzt einen anderen Origin als "links/oben"?


    Die Variance Shadow Maps selber haben bereits funktioniert ohne SAT, richtig?


    Wenn euer Code im git repository up-to-date ist, kann ich mal einen Blick reinwerfen (aber eher erst morgen). Dafür brauch ich aber euren Gruppennamen.

    Wenn ich konkret auf das Youtube Video Bezug nehme, dann sehe ich nicht viel Ähnlichkeit..
    Beispiel:


    rtr2.jpgrtr1.jpg



    Euer Effekt ist interessant, wirkt auf mich aber nicht wie ein lens-flare. Ja, ihr zeigt ein bzw. mehrere Sprites entlang der Linie zwischen Lichtquelle und Mittelpunkt des Screens an. Aber authentisch wirkt das nicht. Ihr dürft nicht vergessen was hier in der Theorie passiert: Das Licht fällt in die Linse ein und wird zumeist aufgrund von mehreren Linsen gebrochen, gestreut und verzerrt... Das von euch verlinkte Video zeigt den Effekt besser, vor allem spiegelt es nicht einfach ein Sprite auf die entgegengesetzte Position der Lichtquelle im Screen.


    Es würde mir helfen, wenn ihr angebt nach welchen Resourcen ihr vorgegangen seid. In eurem ersten Dokument habt ihr lediglich auf https://www.opengl.org/archive…gardTechniques/LensFlare/ verwiesen (der erste hit auf google), aber das benutzt die fixed-function pipeline, ist > 16 Jahre alt und erklärt nichts bzw. sehr wenig. Also gehe ich davon aus, dass ihr etwas anderes benutzt habt. Das Chapman Tutorial hat sehr schöne Ergebnisse, ist aber, wenn man alles implementiert, einfach schon viel zu viel..


    Als letzte Anmerkung sei gesagt, dass es an eurer Umsetzung des Lens-Flares nicht scheitern soll... Ihr habt andere interessante Effekte angegeben, also konzentriert euch auf diese (Atmosphere effect, displacement mapping) und wenn dann noch Zeit ist, könnt ihr den Lens-Flare authentischer machen...

    Smart Projection löst sicher nicht einfach alles. Je nach Modell werdet ihr Sphere oder Cube Mapping mit teilweise besseren Resultaten haben. Es kommt darauf an, ob ihr Seams gesetzt habt und wenn ja, wo diese sind. UV Mapping ist leider kein einfaches Thema. Als Alternative könnt ihr auch in Maya modellieren, das gibt's gratis für Studenten. Aber auch dort ist der Einarbeitungsaufwand enorm. Ich würde euch empfehlen vorerst bei Blender zu bleiben und euch Tutorials zu UV Mapping/Unwrapping anzusehen...

    Was du auch machen kannst, ist dir die shadow map in CodeXL ansehen. Dort gibt es die Möglichkeit den Wertebereich zur Visualisierung einzuschränken. Damit schließt du immerhin Fehler bei deiner Visualisierung aus. Dennoch, near plane so nah wie möglich vor das Objekt legen und far plane kurz nach dem Objekt sollte schon Unterschiede zeigen. Weiters, falls du das noch nicht gemacht hast, kannst du die Präzision der Textur auf 32bit float erhöhen.

    Naja, kommt darauf an wie du deine Shadowmap visualisierst...
    Es sieht so aus, als ob du mit der Kamera der Lichtquelle sehr weit von der Szene entfernt bist und daher die beiden Objekte im Tiefenbereich sehr nah beinander sind. Z.B. Im Bereich 0.2 bis 0.25 von einem Gesamtbereich [0,1].


    Nachdem du eine orthographische Kamera hast, musst du halt den Bildausschnitt (near,far,left,right,top,bottom) anpassen, statt die Position der Kamera zu verändern.


    Wenn du jetzt einfach nur die Tiefenwerte auf den Bildschirm ausgibst, ohne praktisch eine Histogram-Normalisierung zu machen, dann werden alle Tiefenwerte, weil sie im gleichen Bereich sind, ähnliche Grauwerte haben und optisch nicht zu unterscheiden sein.