Diskussion:shader blur2: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „Da an dem anderen Blur Shader scheinbar seit Ewigkeiten nichtsmehr gemacht wird hab ich einfach mal diesen hier erstellt. Fragen, Anregungen, Verbesserungsvorschl…“)
 
(Excellent?)
 
(10 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
Da an dem anderen Blur Shader scheinbar seit Ewigkeiten nichtsmehr gemacht wird hab ich einfach mal diesen hier erstellt.
 
Da an dem anderen Blur Shader scheinbar seit Ewigkeiten nichtsmehr gemacht wird hab ich einfach mal diesen hier erstellt.
 
Fragen, Anregungen, Verbesserungsvorschläge? --[[Benutzer:Skeptiker|Skeptiker]] 22:25, 22. Dez. 2009 (CET)
 
Fragen, Anregungen, Verbesserungsvorschläge? --[[Benutzer:Skeptiker|Skeptiker]] 22:25, 22. Dez. 2009 (CET)
 +
:Der Shader ist sehr gut, bei meinem Vorschlag [http://www.delphigl.com/forum/viewtopic.php?f=20&p=76150 in diesem Thread] habe ich nämlich nicht berücksichtigt, dass die Convolution-Operation kommutativ und assoziativ ist. Der Gauss-Filter ist deshalb nämlich separierbar. Wenn man Rundungsfehler vernachlässigt spielt es beim Ergebnis keine Rolle, ob man einen 2D-Gauss anwendet oder die Operation zweimal mit einem horizontalen bzw. vertikalen 1D-Gauss durchführt. Die zweite Variante spart aber eine große Menge an Texturzugriffen. In diesem Fall 7*7=49 Zugriffe beim 2D-Gauss gegen 2*7=14 Texturzugriffe beim zweimaligen 1D-Gauss. Das macht um so mehr aus, je größer der Filter ist. Eigentlich sollte ich solche Dinge besser wissen.<br />Ok, was zu meckern habe ich natürlich auch ;)
 +
:* Du musst die Ränder der Textur in irgendeiner Form korrekt behandeln. Das kann beispielsweise dadurch geschehen das man <tt>GL_TEXTURE_WRAP_*</tt> auf <tt>GL_CLAMP_TO_EDGE</tt> oder <tt>GL_CLAMP_TO_BORDER</tt> setzt. Sollte man vielleicht erwähnen.
 +
:* Das Array gaussFilter sollte <tt>const</tt> sein, ich bin mir nicht sicher ob der Shader-Compiler so schlau ist selbst zu bemerken, dass er nur einmal Speicher reservieren muss.
 +
:* Ansonsten kann man, wie du schon selbst sagst, an der Fallunterscheidung natürlich noch etwas feilen, aber dann wäre der Shader wahrscheinlich nicht mehr so leicht zu lesen.
 +
:--[[Benutzer:Coolcat|Coolcat]] 11:06, 23. Dez. 2009 (CET)
 +
 +
 +
:Sollte es nicht <tt>float(i - 3)</tt> sein? Der Index i läuft von 0 bis 6, damit läuft i-4 von -4 bis 2. Oder habe ich gerade nen Knoten drin? --[[Benutzer:Coolcat|Coolcat]] 15:56, 23. Dez. 2009 (CET)
 +
 +
:Du hast mit allem recht ;-). Ich mach mich nachher ran und füge das noch mit in die Beschreibung ein. Und jau, es sollte durchaus i - 3 und nicht i - 4 heißen ;-). --[[Benutzer:Skeptiker|Skeptiker]] 16:40, 23. Dez. 2009 (CET)
 +
 +
 +
:Ok, meine optimierte Variante die ich für UC übernommen habe sieht nun wie folgt aus. Ich habe die Fallunterscheidung entfernt und durch die Uniform <tt>uShift</tt> ersetzt. Da die GPU Vektoraddition im Schlaf beherrscht sollte das die beste Lösung sein. Insbesondere ist die Texturgröße darin gleich integriert. Für einen horizontalen Filter setzt man also <tt>uShift</tt> auf <tt>vec2(1.0/textureWidth, 0.0)</tt>. Um bei gleicher Geschwindigkeit den Filter zu verstärken kann auch so etwas wie <tt>1.6/textureWidth</tt> versuchen. Auf diese Weise sind natürlich auch diagonale Filter möglich. Außerdem habe ich die Gauss-Funktion (im Array) vergrößert und stärker abgeschnitten. Texel die nur zu einem 64stel in die Berechnung eingehen lohnen den Aufwand nicht wirklich.
 +
<source lang="glsl">uniform sampler2D uScene;
 +
uniform vec2 uShift;
 +
 +
varying vec2 vTexCoord;
 +
 +
const int gaussRadius = 11;
 +
const float gaussFilter[gaussRadius] = float[gaussRadius](
 +
0.0402,0.0623,0.0877,0.1120,0.1297,0.1362,0.1297,0.1120,0.0877,0.0623,0.0402
 +
);
 +
 +
void main() {
 +
vec2 texCoord = vTexCoord - float(int(gaussRadius/2)) * uShift;
 +
vec3 color = vec3(0.0, 0.0, 0.0);
 +
for (int i=0; i<gaussRadius; ++i) {
 +
color += gaussFilter[i] * texture2D(uScene, texCoord).xyz;
 +
texCoord += uShift;
 +
}
 +
gl_FragColor = vec4(color,1.0);
 +
}</source>
 +
: --[[Benutzer:Coolcat|Coolcat]] 19:18, 23. Dez. 2009 (CET)
 +
 +
:Sieht gut aus, habs für mich auch direkt mal so übernommen. Wäre vermutlich auch Sinnvoll, wenn du die Version mit in den Artikel schreibst, damit es nicht auf der Diskussionsseite untergeht (oder den alten Shader gleich komplett ersetzt - wie auch immer es sinnvoller ist). --[[Benutzer:Skeptiker|Skeptiker]] 00:43, 24. Dez. 2009 (CET)
 +
::Habe den Artikel komplett überarbeitet und auch in die Shadersammlung eingefügt. Ein bisschen Erklärung von welchem Himmel die Zahlen fallen kommt immer gut :) --[[Benutzer:Coolcat|Coolcat]] 16:11, 24. Dez. 2009 (CET)
 +
 +
== Excellent? ==
 +
 +
Ist der Shader Performance-Optimiert (soll heißen, gibt es keine Sachen im Shader die man ohne Hexenwerk noch performanter machen kann)?
 +
: Also mir fällt nichts ein was man da noch sinnvoll Optimieren könnte. Höchstens die Größe des Filters gegenüber der Anzahl der Anwendungen des Shaders. Dafür bräuchte man eine größere Testreihe mit verschiedener Grafikhardware. Ich denke mal das ist übertrieben ;) --[[Benutzer:Coolcat|Coolcat]] 19:40, 25. Dez. 2009 (CET)
 +
 +
Falls ja würde ich den Artikel zum Excellenten Artikel vorschlagen. Er erklärt die Theorie ausreichend fundiert, er enthält Bilder und einen vollständig nutzbaren Code. --[[Benutzer:Flash|Flash]] 19:15, 25. Dez. 2009 (CET)
 +
: Darfst du gerne machen :) --[[Benutzer:Coolcat|Coolcat]] 19:40, 25. Dez. 2009 (CET)
 +
 +
Braucht man irgendeine besondere GLSL Version für den Shader? Falls ja, bitte in den Vorraussetzungen ergänzen. Hab den Artikel nominiert.  --[[Benutzer:Flash|Flash]] 21:18, 25. Dez. 2009 (CET)

Aktuelle Version vom 25. Dezember 2009, 21:18 Uhr

Da an dem anderen Blur Shader scheinbar seit Ewigkeiten nichtsmehr gemacht wird hab ich einfach mal diesen hier erstellt. Fragen, Anregungen, Verbesserungsvorschläge? --Skeptiker 22:25, 22. Dez. 2009 (CET)

Der Shader ist sehr gut, bei meinem Vorschlag in diesem Thread habe ich nämlich nicht berücksichtigt, dass die Convolution-Operation kommutativ und assoziativ ist. Der Gauss-Filter ist deshalb nämlich separierbar. Wenn man Rundungsfehler vernachlässigt spielt es beim Ergebnis keine Rolle, ob man einen 2D-Gauss anwendet oder die Operation zweimal mit einem horizontalen bzw. vertikalen 1D-Gauss durchführt. Die zweite Variante spart aber eine große Menge an Texturzugriffen. In diesem Fall 7*7=49 Zugriffe beim 2D-Gauss gegen 2*7=14 Texturzugriffe beim zweimaligen 1D-Gauss. Das macht um so mehr aus, je größer der Filter ist. Eigentlich sollte ich solche Dinge besser wissen.
Ok, was zu meckern habe ich natürlich auch ;)
  • Du musst die Ränder der Textur in irgendeiner Form korrekt behandeln. Das kann beispielsweise dadurch geschehen das man GL_TEXTURE_WRAP_* auf GL_CLAMP_TO_EDGE oder GL_CLAMP_TO_BORDER setzt. Sollte man vielleicht erwähnen.
  • Das Array gaussFilter sollte const sein, ich bin mir nicht sicher ob der Shader-Compiler so schlau ist selbst zu bemerken, dass er nur einmal Speicher reservieren muss.
  • Ansonsten kann man, wie du schon selbst sagst, an der Fallunterscheidung natürlich noch etwas feilen, aber dann wäre der Shader wahrscheinlich nicht mehr so leicht zu lesen.
--Coolcat 11:06, 23. Dez. 2009 (CET)


Sollte es nicht float(i - 3) sein? Der Index i läuft von 0 bis 6, damit läuft i-4 von -4 bis 2. Oder habe ich gerade nen Knoten drin? --Coolcat 15:56, 23. Dez. 2009 (CET)
Du hast mit allem recht ;-). Ich mach mich nachher ran und füge das noch mit in die Beschreibung ein. Und jau, es sollte durchaus i - 3 und nicht i - 4 heißen ;-). --Skeptiker 16:40, 23. Dez. 2009 (CET)


Ok, meine optimierte Variante die ich für UC übernommen habe sieht nun wie folgt aus. Ich habe die Fallunterscheidung entfernt und durch die Uniform uShift ersetzt. Da die GPU Vektoraddition im Schlaf beherrscht sollte das die beste Lösung sein. Insbesondere ist die Texturgröße darin gleich integriert. Für einen horizontalen Filter setzt man also uShift auf vec2(1.0/textureWidth, 0.0). Um bei gleicher Geschwindigkeit den Filter zu verstärken kann auch so etwas wie 1.6/textureWidth versuchen. Auf diese Weise sind natürlich auch diagonale Filter möglich. Außerdem habe ich die Gauss-Funktion (im Array) vergrößert und stärker abgeschnitten. Texel die nur zu einem 64stel in die Berechnung eingehen lohnen den Aufwand nicht wirklich.
uniform sampler2D uScene;
uniform vec2 uShift;

varying vec2 vTexCoord;

const int gaussRadius = 11;
const float gaussFilter[gaussRadius] = float[gaussRadius](
	0.0402,0.0623,0.0877,0.1120,0.1297,0.1362,0.1297,0.1120,0.0877,0.0623,0.0402
);
 
void main() {
	vec2 texCoord = vTexCoord - float(int(gaussRadius/2)) * uShift;
	vec3 color = vec3(0.0, 0.0, 0.0); 
	for (int i=0; i<gaussRadius; ++i) { 
		color += gaussFilter[i] * texture2D(uScene, texCoord).xyz;
		texCoord += uShift;
	}
	gl_FragColor = vec4(color,1.0);
}
--Coolcat 19:18, 23. Dez. 2009 (CET)
Sieht gut aus, habs für mich auch direkt mal so übernommen. Wäre vermutlich auch Sinnvoll, wenn du die Version mit in den Artikel schreibst, damit es nicht auf der Diskussionsseite untergeht (oder den alten Shader gleich komplett ersetzt - wie auch immer es sinnvoller ist). --Skeptiker 00:43, 24. Dez. 2009 (CET)
Habe den Artikel komplett überarbeitet und auch in die Shadersammlung eingefügt. Ein bisschen Erklärung von welchem Himmel die Zahlen fallen kommt immer gut :) --Coolcat 16:11, 24. Dez. 2009 (CET)

Excellent?

Ist der Shader Performance-Optimiert (soll heißen, gibt es keine Sachen im Shader die man ohne Hexenwerk noch performanter machen kann)?

Also mir fällt nichts ein was man da noch sinnvoll Optimieren könnte. Höchstens die Größe des Filters gegenüber der Anzahl der Anwendungen des Shaders. Dafür bräuchte man eine größere Testreihe mit verschiedener Grafikhardware. Ich denke mal das ist übertrieben ;) --Coolcat 19:40, 25. Dez. 2009 (CET)

Falls ja würde ich den Artikel zum Excellenten Artikel vorschlagen. Er erklärt die Theorie ausreichend fundiert, er enthält Bilder und einen vollständig nutzbaren Code. --Flash 19:15, 25. Dez. 2009 (CET)

Darfst du gerne machen :) --Coolcat 19:40, 25. Dez. 2009 (CET)

Braucht man irgendeine besondere GLSL Version für den Shader? Falls ja, bitte in den Vorraussetzungen ergänzen. Hab den Artikel nominiert. --Flash 21:18, 25. Dez. 2009 (CET)