Schrompf hat geschrieben: ↑30.07.2020, 22:03Sehr cool, dass Du Deinen Shader geteilt hast.
Das freut mich :D
Schrompf hat geschrieben: ↑30.07.2020, 22:03Ich verstehe leider nicht,...
Das nicht so... aber ich pack noch ein paar Kommentare dran, und versuche es nochmal besser zu erklären.
Bin halt nur kein Freund von langen Variablennamen...
a, b, c = Vertices
t = 2D Screenkoordinate
s = Seite
e = Kanten
ee = Winkelhalbierende (glaube ich)
et = Transponierte Kanten
v = a | b je nach Dreieckswinding
vv = Matrix aus den 3 Dreieckspunkten
tt = Abstandswerte zu den 3 Kanten
tt2 = Abstandwerte zu den 3 Winkelhalbierenden (also den Eckpunkten, die an diesen liegen)
ss = Hilfsvariable
bo2 | bo1 = Hilfsvariablen für den Saum
Zudomon hat geschrieben: ↑23.07.2020, 22:42
bo1 und bo2 sind vorberechnete Variablen die angeben wie groß der Übergang sein muss.
bo = 0.03;
bo2 = 0.5/bo;
bo1 = bo*bo2;
Hier habe ich bo 0.03 gewählt... bei 64 x 64 Pixeln. Das ist dann aber abhängig von der Auflösung, die letztendlich verwendet wird.
Nochmal kurz den Gesamtalgo zusammengefasst:
Zu jeder Dreieckskante wird der Abstand ermittelt. Da jede Kante ein Übergang bekommt, können Artefakte bei sehr schmalen Dreiecken entstehen. Das sieht dann in etwa aus, wie der relativistische Jet bei einem schwarzen Loch. Nach einigem rumprobieren ist mir dann die Idee gekommen, vielleicht einfach das gleiche nochmal zu machen. Nun statt für die Kanten des Dreiecks für die Eckpunkte. Also die Eckpunkte werden auch einfach als Kanten berechnet, dessen Ausrichtung Senkrecht zur Winkelhalbierenden (?) steht.
Eventuell könnte man, wenn das Dreieck erst Bounding Box geprüft würde, das einfach raus lassen, dann fällt da nochmal die Hälfte aus der Funktion raus.
Code: Alles auswählen
float ed(vec2 t, vec2 a, vec2 b, vec2 c)
{
// Welche Seite? s = 0 (die eine) oder 1 (die andere) :D try&error bis es passt ;)
float s = sign(dot((b-a).yx*vec2(-1, 1), a-c))*0.5+0.5;
// Je nachdem wird dann a und b vertauscht
vec4 v = mix(vec4(a, b), vec4(b, a), s);
// Kantenmatrix aus Eckpunkte basteln
// Leider muss hier alles normalisiert werden, weil sonst die Abstände nicht richtig sind.
// Wenn diese nicht exakt sein müssen, kann man sich eventuell sämtliche normalisierungen sparen.
mat3x2 e = mat3x2(normalize(v.zw-v.xy),
normalize(c-v.zw),
normalize(v.xy-c));
// Kantenmatrix der Senkrecht zur Winkelhalbierend stehenden Eckpunkte
mat2x3 ee= transpose(mat3x2(normalize(e[2]+e[0]),
normalize(e[0]+e[1]),
normalize(e[1]+e[2])));
// Ein bisschen transposen, damit man schön die Vektoroperationen nutzen kann
mat2x3 et = transpose(e);
// Hier auch, allerdings mit einer Matrix aus den Eckpunkten des Dreiecks
mat2x3 vv = transpose(mat3x2(v.xy, v.zw, c));
// Noch schnell alles in den Worldspace bringen...
vv[0]-=t.x;
vv[1]-=t.y;
// Nun können wir die Abstandswerte für alle 6 Kanten errechnen.
vec3 tt = et[1]*vv[0] - et[0] * vv[1];
vec3 tt2 = ee[1]*vv[0] - ee[0] * vv[1];
// Nun noch den Minimalwert aller 6 Kanten finden... noch mit den bo's verrechnen,
// damit wir den Übergang noch wie gewünscht steuern können
// und letztendlich noch mit 0 maxen, um negativwerte zu vermeiden.
vec3 ss = min(tt, tt2);
return max(min(min(ss.x, ss.y), ss.z)*bo2+bo1, 0);
// Wobei ich mich gerade frage, ob es wirklich überflüssig war auch die Obergrenze
// zu prüfen. Ansonsten also noch ein "min" mit 1 drum packen, was man dann auch mit
// der clamp funktion hätte
}
Der Code Schnipsel hat mich auch einige Stunden gekostet, auch wenn einem so kurzer Code was anderes suggeriert.
Ich hatte damals mal auch so einen "Unlimited Detail"-Ansatz auf CPU ausprobiert... mit einem großen Octree der da geraycast wurde. Weiß gar nicht ob ich das Projekt hier gepostet hatte.
Jedenfalls fand ich es da ziemlich cool, dass man relativ schnell ganze Octreeäste auslassen konnte, wenn diese verdeckt waren und man konnte bei beliebiger Leafgröße abbrechen. Dadurch war dann quasi automatisches LOD bzw. auch Mipmaps für Geometrie mit drin. Ich glaube, das hatte ich von dir auch die Tage gelesen, dass du da ähnliches vor hattest.
Wie schon oben geschrieben, ich verfolge das mal gespannt mit und vielleicht ergibt sich da für mich ja auch noch etwas.
Hab bei mir da jetzt diese Vektortextur umgesetzt für die Reprojektion, zwar erstmal nur für den Gegenstand in der Hand, aber das hat schon viel ausgemacht.
Ich hatte mir nochmal angeschaut wie das bei Doom 2016 gemacht wurde, da gabs ja einen schönen Artikel zu. Da hab ich dann gecheckt, dass man ja nicht ALLES in die Vektortextur packen muss. Die statische Geometrie bleibt außen vor. Ich hatte ja Bedenken wegen dem G-Buffer und dem zusätzlichen Overhead. Aber wenn ich am Ende nur nochmal ein paar Objekte nachrendern muss, ist das super in Ordnung!
Also seit dem bin ich jetzt mit dem TAA mehr als zufrieden. Ist zwar kein Ultrasupersampling... aber ein bisschen mehr Supersampling als gar keins.