DGL https://delphigl.com/forum/ |
|
Convolution-Filter https://delphigl.com/forum/viewtopic.php?f=20&t=9255 |
Seite 1 von 1 |
Autor: | SunBlack [ So Jun 13, 2010 09:54 ] |
Betreff des Beitrags: | Convolution-Filter |
Hallo ihr, wir sollen in der Uni jetzt u.a. ein Convolution-Filter implementieren. Allerdings komm ich irgendwie mit den Datentypen im Shader noch nicht ganz klar, wes wegen ich mich im Netz mal ein bisschen umgeschaut habe. Dabei bin ich auf folgenden Code gestoßen: Code: // maximum size supported by this shader const int MaxKernelSize = 25; // array of offsets for accessing the base image uniform vec2 Offset[MaxKernelSize]; // size of kernel (width * height) for this execution uniform int KernelSize; // value for each location in the convolution kernel uniform vec4 KernelValue[MaxKernelSize]; // image to be convolved uniform sampler2D BaseImage; void main() { int i; vec4 sum = vec4(0.0); for (i = 0; i < KernelSize; i++) { vec4 tmp = texture2D(BaseImage, gl_TexCoord[0].st + Offset[i]); sum += tmp * KernelValue[i]; } gl_FragColor = sum; } Was mein Problem an dem Code ist:
Das Tutorial im Wiki gibt dazu leider nicht wirklich eine richtige Auskunft ![]() besten Dank im Voraus SunBlack |
Autor: | mrtrain [ So Jun 13, 2010 11:34 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Hallo! Von Convolution-Filter lese ich das erste Mal etwas, bin da also auch kein Pro. Zu deinen Fragen:
Übrigens, hast du auch schon das Tutorial GLSL gelesen? Gruß mrtrain ps: Wie hast du eigentlich die Aufzählungspunkte gemacht? Mit [*] will es bei nicht funktionieren. edit: Danke Lord, jetzt geht's. |
Autor: | Lord Horazont [ So Jun 13, 2010 11:37 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Hi SunBlack, Bevor ich deine Fragen beantworte, hier vielleicht ein andere interessanter Hinweis für dich: Für Convolution-Filter *ohne* Shader gibt es auch: glConvolutionFilter2D. Wie man damit umgeht und was das genau ist, wird hier erklärt: Convolution-Filter. Ohne Shader wird wahrscheinlich schneller funktionieren, da du sonst sehr schnell an das Limit der Texturzugriffe kommst. Dann wechselt OpenGL in den Softwaremodus und es wird richtig langsam. Der ConvolutionFilter2D muss aktiviert werden, bevor du dein Bild an OpenGL hochlädst. Wenn du die fertigen Daten dann auslesen und weiterverarbeiten möchtest, könnte sich glGetTexImage2D lohnen. Eventuell wird dieses sogar auch vom ConvolutionFilter beeinflusst. Dann lohnt es sich, erst das Bild *ohne* aktivierten Filter hochzuladen, dann den Filter aktivieren und das Bild wieder von OpenGL mit genanntem Befehl zurückholen. So kannst du unterschiedliche Filter anwenden, ohne das Bild immer wieder zur Grafikkarte übertragen zu müssen. Das ist aber, wie gesagt, nur dann interessant, wenn du die Daten später weiterverarbeiten oder in eine Datei schreiben willst. SunBlack hat geschrieben:
SunBlack hat geschrieben:
Generell greifst du in OpenGL auf Texturen (also "Bilder") immer nur mit Koordinaten zwischen 0 und 1 zu. Ein vec2 (0.5, 0.5) würde also genau die Mitte der Textur treffen, egal, wie groß diese ist. Das ist meistens vorteilhaft (man kann einfach hochauflösende Texturen gegen niedriger auflösende austauschen und umgekehrt), in deinem Fall aber nachteilhaft. Die Größe der Textur kannst du im Shader selbst nicht rausbekommen und um anhand der Pixelkoordinaten auf einzelne Bildpunkte zuzugreifen brauchst du irgendein hohes Shadermodel (4 oder so), wird also nicht von jeder Grafikkarte unterstützt. Wie du die Größe der Textur in C nach dem Hochladen zu OpenGL rausbekommst weiß ich gerade leider nicht. Wenn ich pixelgenaue Zugriffe brauchte, habe ich das immer so gelöst, dass ich die Originalgröße der Textur beim Laden in einer Datenstruktur zusammen mit der TexturID (der GLUInt, den du meinst), gespeichert habe. SunBlack hat geschrieben:
greetings ps: mrtrain war bei ein paar sachen schneller ![]() |
Autor: | SunBlack [ So Jun 13, 2010 12:32 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Hiho, ersteinmal Danke für die Antworten ![]() mrtrain hat geschrieben: [*] Ein vec2 ist ein Vektor mit zwei Komponenten, also x und y, s und t oder auch u und v. Für jede Komponente gibt es quasi einen float. Vec4 hat vier Komponenten (z.B. xyzw). Dass der vec4-Konstruktor mit nur einem Parameter aufgerufen wird, entspricht glaube ich nicht den GLSL-Regeln. Gemeint ist jedenfalls vec4(0.0, 0.0, 0.0, 0.0). Ok, gut. War mir da nicht ganz sicher ob er das so einfach abkam, vor allem da es mich gewundert hat, warum texture2D einen vec4 zurückgibt. Aber man sollte nicht nur an Koordinaten denken, sondern auch mal an Farbwerte (RGBA) die nicht in einer einzelnen Zahl stehen (wie bei Delphi weiß z.B. 16777215 ist ![]() mrtrain hat geschrieben: Übrigens, hast du auch schon das Tutorial GLSL gelesen? Japp, mein letzter Satz sollte das Andeuten. Lord Horazont hat geschrieben: Bevor ich deine Fragen beantworte, hier vielleicht ein andere interessanter Hinweis für dich: Für Convolution-Filter *ohne* Shader gibt es auch: glConvolutionFilter2D. Leider bringt es mir in der Übung nichts - da sollen wir leider den Shader dazu verwenden - ist halt eine Shaderübung ![]() Lord Horazont hat geschrieben: Es greifen die normalen Texturbehandlungen von OpenGL soweit ich weiß. Außerhalb des gültigen Texturbereiches wird der äußerste Pixel des Bildes bis in die Unendlichkeit wiederholt (vgl. glTexParameter - Vergleich zwischen verschiedenen Texturwraptypen). Hab eben nachgeschaut GL_CLAMP_TO_EDGE ist eingestellt, also das passende. Lord Horazont hat geschrieben: Wenn ich pixelgenaue Zugriffe brauchte, habe ich das immer so gelöst, dass ich die Originalgröße der Textur beim Laden in einer Datenstruktur zusammen mit der TexturID (der GLUInt, den du meinst), gespeichert habe. Ok schade. Hatte gehofft das Texturgrößenunabhängig machen zu können. Lord Horazont hat geschrieben: Nein, es geht nicht über glUniformMatrix4fv. Ich sehe bei dem Shader gerade garkeinen Filterkernel, nur Offsets. Die Pixel werden also ungewichtet aufaddiert, es scheint sich nicht wirklich um einen Convolution-Shader zu handeln. Über was dann? Achja, hatte den flaschen Code vorhin vond er Quelle kopiert. Habe es mal korrigiert. |
Autor: | Lord Horazont [ So Jun 13, 2010 12:49 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Na das sieht doch besser aus. Dann musst du deine Daten über glUniform4fv übergeben. Und zwar legst du dir dafür ein Array an, indem du die Vektoren mit den Faltungskernwerten speicherst. Auch hier handelt es sich wieder um vec4, sodass du jede Farbkomponente und Alpha mit einem anderen Wert belegen kannst. Dann übergibst du an glUniform4fv einen Pointer auf den ersten Wert des Arrays. Ähnlich machst du's mit Offset. Da brauchst du dann ein Array aus vec2-Vektoren, in das du dann den Versatz reinsetzt. Für einen 3x3-Filter würdest du also z.B. die Vektoren (-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0), (1, 1) übergeben, wobei die noch mit einem Faktor multipliziert werden müssen, damit du die Pixel auch triffst. Dieser Faktor ist der Kehrwert der Texturgröße in der jeweiligen Dimension, ist also für X und Y unterschiedlich. Für X ist er 1/Width, für Y 1/Height. Irgendwie müsstest du ja beim Laden an die Höhe und Breite der Textur rankommen, oder? Ich hoffe, das war verständlich ![]() greetings |
Autor: | SunBlack [ So Jun 13, 2010 13:17 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Hey danke, jetzt ist alles klar. Mein Problem war wohl, dass ich die Farbe die ganze Zeit gedanklich als eine einzige Zahl interpretiert hatte (statt als Vector) und nach dem Fixen das nicht mehr darüber nachgedacht habe, was es bringt 4D-Vectoren zu übergeben (in der Übung davor haben wir alle Farbkompos gleich behandelt, wes wegen ich hier auch die Trennung vergaß ![]() Eine Randfrage aber noch: Wann verwendet man denn glUniformMatrix4fv, wenn glUniform4fv reicht? Denn wenn ich mir das hier ansehe, sehe ich da keinen bedeutenden Unterschied. |
Autor: | Lord Horazont [ So Jun 13, 2010 13:38 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Der bedeutende Unterschied liegt einfach darin, dass die Uniform-Variable im Shader bei dir als vecX deklariert ist, in verlinkten Beispiel als matX. Bei vecX musst du immer glUniformX[fd][v] verwenden, bei matX entsprechend glUniformMatrixX[fd][v]. greetings |
Autor: | SunBlack [ So Jun 13, 2010 21:37 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
So, ich habe eben versucht das ganze zu Implementieren. Aber irgendwie erkenne ich keinen Unterschied zw. dem pass through filter und dem mean filter. Shader: Code: #version 110 const int KernelSize = 9; uniform sampler2D samplerTexture; uniform vec4 KernelValues[KernelSize]; uniform vec2 Offset[KernelSize]; vec4 convolution(void) { // // Todo Convolution Filter // vec4 col = vec4(0.0, 0.0, 0.0, 0.0); for (int i = 0; i < KernelSize; i++) { col += texture2D(samplerTexture, gl_TexCoord[0].st + Offset[i]) * KernelValues[i]; } return col; } void main(void) { gl_FragColor = convolution(); return; } Und im C-Code: Code: //assume 2500px*1250px pictures, because we can't read size of picture in shader void loadShaderOffset() { float offsets[18]; for (int y=-1; y<=1; y++){ for (int x=-1; x<=1; x++){ int idx = (y+1)*3 + (x+1); offsets[2*idx] = x/2500.0; offsets[2*idx+1] = y/1250.0; } } glUseProgramObjectARB(g_filterProgram); int offsetFBO = glGetUniformLocationARB(g_filterProgram, "Offset"); glUniform4fvARB(offsetFBO, sizeof(offsets), &offsets[0]); glUseProgramObjectARB(0); } void loadFilter(float filter[9]) { float offsets[36]; for (int y=-1; y<=1; y++){ for (int x=-1; x<=1; x++){ int idx = (y+1)*3 + (x+1); offsets[4*idx] = offsets[4*idx+1] = offsets[4*idx+2] = offsets[4*idx+3] = filter[idx]; } } glUseProgramObjectARB(g_filterProgram); int kernelFBO = glGetUniformLocationARB(g_filterProgram, "KernelValues"); glUniform4fvARB(kernelFBO, sizeof(offsets), &offsets[0]); glUseProgramObjectARB(0); } ... float kernel[9] = {0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}; loadFilter(&kernel[0]); Seht ihr den Fehler? |
Autor: | SunBlack [ Mo Jun 14, 2010 11:23 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Fehler gefunden (Copy&Paste-Fehler): Die offsets sollten ja nicht mit glUniform4fvARB sondenr mit glUniform2fvARB hochgeladen werden ![]() |
Autor: | dj3hut1 [ Mi Jun 23, 2010 07:57 ] |
Betreff des Beitrags: | Re: Convolution-Filter |
Hallo, glConvolutionFilter2D ist deutlich langsamer als ein Shader, zumal dafür die Erweiterung ARB_Imaging benötigt wird, die nicht immer verfügbar ist und ab OpenGL 3.0 als deprecated gilt. Viele Grüße dj3hut1 |
Seite 1 von 1 | Alle Zeiten sind UTC + 1 Stunde |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |