DGL
https://delphigl.com/forum/

Resolution independent rendering
https://delphigl.com/forum/viewtopic.php?f=20&t=9395
Seite 1 von 1

Autor:  Mountainking [ Di Aug 10, 2010 15:15 ]
Betreff des Beitrags:  Resolution independent rendering

Wie kann ich denn bei folgendem Fragmentshader noch "Antialiasing" z.B. mit smoothstep hinzufügen?
Code:
void main(void)
{
   vec2 center_point = vec2(200.0, 200.0);
   float mydistance = distance(center_point, gl_FragCoord.xy);

   if (mydistance <= 50.0)
   {
      gl_FragColor = gl_Color;
   }
   else
   {
      discard;
   }
}

Autor:  Lord Horazont [ Di Aug 10, 2010 18:45 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Verdeutliche bitte, worauf du hinaus willst…

greetings

Autor:  Schläfer [ Di Aug 10, 2010 22:05 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

MSAA wird ja dadurch erreicht, dass man für jeden Bildschirmpixel mehrere Subpixel errechnet und den Durchschnitt bildet. Oder anders: Man rendert das Bild in höherer Auflösung und verkleinert es dann.

Also gibt es mehrere Möglichkeiten:

1. Möglichkeit: für jeden Pixel mehrere berechnen und den Durchschnitt bilden. z.B. so:

Code:
void main(void)
{
   vec2 center_point = vec2(200.0, 200.0);
   float Alpha=0.0;
   for (float i=0.0; i<=0.5; i+=0.5)
   {
      for (float j=0.0; j<=0.5; j+=0.5)
      {
         float mydistance = distance(center_point+vec2(i,j), gl_FragCoord.xy);

         if (mydistance <= 50.0)
         {
            Alpha+=0.25;
         }
      }
   }
   gl_FragColor=vec4(vec3(gl_Color),gl_Color[3]*Alpha);
}

Dafür muss man natürlich Blending anstellen. Da die Farbe auch überall gleich ist reicht es den Alphawert zu bestimmen.
Bei meinem Beispielcode wird der Pixel in 4 Teile geteilt, weshalb beim Alpha auch immer 1/4 drauf addiert wird.
Die Lösung kommt dem richtigen AA wohl am nächsten.

2. Möglichkeit: Man fügt einen kleinen Rand um den Kreis ein.
Code:
void main(void)
{
   vec2 center_point = vec2(200.0, 200.0);
   float mydistance = distance(center_point+vec2(i,j), gl_FragCoord.xy);

   float Alpha=clamp(1.0*(50.0-mydistance),0.0,1.0);
   gl_FragColor=vec4(vec3(gl_Color),gl_Color[3]*Alpha);
}

Der Faktor vor "(50.0-mydistance)" ist 1 dividiert durch die Randbreite. Also wenn die Zahl kleiner wird, wird der Rand breiter.
Auch hierfür muss Blending angeschaltet sein.

Die Multiplikation "gl_Color[3]*Alpha" in beiden Beispielen ist dafür da falls die Farbe schon eine Transparenz besitzt. Wenn nicht kann man da auch nur "Alpha" hinschreiben.

Ich hoffe mal das kommt in etwa an das heran was du erreichen wolltest.

Autor:  TAK2004 [ Mi Aug 11, 2010 08:24 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Was du wohl brauchst ist folgende funktion.
* genType smoothstep (genType edge0, genType edge1, genType x)
* genType smoothstep (float edge0, float edge1, genType x)
Liefert 0.0 zurück, wenn x <= edge und 1.0 wenn x >= edge. Dabei wird eine weiche Hermite Interpolation zwischen 0 und 1 durchgeführt.
Ich benutze es bei meinem cubicbezier curve renderer, damit die kurven ein AA bekommen.
Code:
#version 130
out vec4 gl_FragColor;
void main(void)
{
   float v=pow(gl_TexCoord[0][0],3.0)-gl_TexCoord[0][1]*gl_TexCoord[0][2];
   float l=length(vec2(dFdx(v),dFdy(v)));
   float f=smoothstep(0.5-l,0.5+l,v);
   if (v<l*-0.5) discard;
   gl_FragColor=vec4(0.0,0.0,1.0,f);
}


Wenn du also mit smoothstep benutzt, dann musst du nur kurz vor geometryende anfangen und beim geometryende spätestens ausgefadet haben.
gl_FragColor = smoothstep(49.0,50.0,mydistance);

Autor:  Mountainking [ Mi Aug 11, 2010 13:05 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Danke euch
Code:
void main(void)
{
   vec2 center_point = vec2(325.0, 325.0);
   float mydistance = distance(center_point, gl_FragCoord.xy);

   float alpha = smoothstep(50.0, 49.0, mydistance);
        gl_FragColor=vec4(vec3(gl_Color), gl_Color[3] * alpha);
}


funktioniert prima. Ich habe allerdings nochein paar andere Probleme.

Nehmen wir mal eine Ellipse als Beispiel:
Code:
void main(void)
{
   vec2 center_point = vec2(200.0, 200.0);
   float radiusx = 100.0;
   float radiusy = 50.0;

   float sx = pow(gl_FragCoord.x - center_point.x, 2.0);
   float sy = pow(gl_FragCoord.y - center_point.y, 2.0);

   float equation = sx / pow(radiusx, 2.0) + sy / pow(radiusy, 2.0);

   if ((equation >= 0.9) && (equation <= 1.0))
   //if (equation == 1.0)
   {
      gl_FragColor = gl_Color;
   }
   else
   {
      discard;
   }
}


Der obige Code gibt mir eine schöne Ellipse die gefüllt ist. Wenn ich jetzt allerdings keine gefüllte Ellipse sondern nur den Umriss haben möchte habe ich das Problem das z.B. mit
Code:
if ((equation >= 0.9) && (equation <= 1.0))

Der Umriss der Ellipse nicht über all gleich dick ist. Und auch das Smoothstep funktioniert hier nicht mehr so einfach wie noch bei dem Kreis.

@TAK2004
Wie renderst du denn den cubic Bezier Shader? Bei mir kommen nur Dreiecke oder Quadrate raus?

Autor:  TAK2004 [ Mi Aug 11, 2010 16:06 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Dafür brauch es ein recht aufwändigen vorberechnung der UV Koordinaten, da diese die umgerechneten Stützpunkte wiederspiegeln.
Ich hatte auch mal Probiert Kubische Bezierkurven als linien dar zu stellen aber da hat mir die ungenauigkeit ein strich durch die rechnung gemacht und es kamen an einigen stellen verschwommende breitere streifen raus.
Ich würde aus dem stehgreif erstmal mit 2 schritten machen.
float alpha = smoothstep(50.0, 50.5, mydistance)*step(50.0,mydistance);//sollte von 50.5 nach 50.0 rein blenden und alles unter 50.0 und über 50.5 mit 0 setzen
alpha += (1.0-smoothstep(50.0, 49.5, mydistance))*step(49.5,mydistance);//1-smoothstep invertiert das blending(wird zum rand hin sichtbar),step wird 0 wenn kleiner 49.5 und 1 wenn >49.5 und multipliziert sollte es dann von 49.5 bis 50.0 ein einblenden hinzufügen sonnst sollte immer 0 drauf addiert werden
Nicht getestet aber wenn ich keine mathematischen fehler gemacht hab, dann sollte das so gehen.

Autor:  Mountainking [ Mi Aug 11, 2010 21:45 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Ist es überhaupt möglich die Outline/Stroke von z.B. Bezier/B-Splines mit Shadern vernünftig zu rendern? Ich suche schon seit Tagen im Internet und habe noch nichts gefunden. Die Kurve sollte auflösungsunanbhängig sein. Vielleicht kann mal jemand ein Beispiel Shader posten.

Autor:  TAK2004 [ Do Aug 12, 2010 10:24 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Wie ich bereits sagte ist die genauigkeit unzureichend, das liegt daran, das die genutzten Formeln eine annäherung sind, welche auf der Funktionslinie exakt ist und von dieser weg immer ungenauer wird. Hoppe von Microsoft Research hat das sehr genau beleuchtet und Lösungen entwickelt. Wenn ich mich recht entsinne ist die Outline ein extra Mesh.

Autor:  Mountainking [ Do Aug 12, 2010 11:25 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Bezog sich dein letzter Post jetzt nur auf die Bezier-Kurve oder generell auf das Rendern von Kurven? Was meinst du mit Funktionslinie. Sind Berechnungen auf der GPU (im Vergleich zur CPU) ungenau? Ist das also der Grund warum der Ellipsen-Shader weiter oben von mir unterschiedliche Liniendicken hat?

Hier hat jemand das gleiche Problem gehabt:
http://www.gamedev.net/community/forums/topic.asp?topic_id=505331

Du meinst wahrscheinlich diesen Artikel http://research.microsoft.com/en-us/um/people/hoppe/pm.pdf?

Autor:  TAK2004 [ Do Aug 12, 2010 13:16 ]
Betreff des Beitrags:  Re: Smoother Umriss eines Kreises

Ich meine den Link.
http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
Seite 5.

Bei Kubischen und Quadratischen Bezierkurven nutzt man Näherungsformeln, wegen Geschwindigkeit.
Die Rahmen sind keine Ränder, sondern ein neues Mesh.

Autor:  Mountainking [ Do Aug 12, 2010 19:27 ]
Betreff des Beitrags:  Re: Resolution independent rendering

Also, wenn ich das richtig sehe gehen die einfach hin ind berechnen für jeden Pixel eine Normale die Senkrecht auf der Kurve liegt und entscheiden dann anhand der Entfernung Punkt Kurve ob der Pixel gezeichnet werden soll.

Seite 1 von 1 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/