QGlWidget die Farbe Weiß als Rot zeichnen

Alles rund um die Programmierung mit Qt
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Mal eine kurze Frage, wie aktiviere ich den Fragmentshader denn? Die Funktion gl_FragColor ist bei mir nicht vorhanden.

Gruß

Treehouse
N¤X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N¤X »

Aktivieren musst du das Programmobjekt an das du deine Shader angehängt hast, und zwar mit glUseProgramObjectARB(programObject);

gl_FragColor ist keine Funktion, sondern eine Variable in der GLSL vom Typ vec4, die es im Fragment Shader gibt.
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Also ich habe folgendes gemacht

ich habe ein Array angelegt wie du gesagt hast für die RGB komponenten:

GLfloat color_table[256][3];

dann habe ich eine Texture erstellt.

glGenTextures(1, &m_lookupTable);
glBindTexture(GL_TEXTURE_1D, m_lookupTable);

jetzt wollte ich das Farb array als fragment shader setzten und da scheiter ich gerade.

Gruß

Treehouse
N¤X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N¤X »

Treehouse hat geschrieben:jetzt wollte ich das Farb array als fragment shader setzten und da scheiter ich gerade.
Ein Shader ist ein kleines Programm, das direkt auf der Grafikkarte ausgeführt wird und Teile der Grafikpipeline ersetzt, du kannst also nicht einfach ein Array als Shader benutzen...

Schau dir am besten mal das Example das dir Solarix empfohlen hat an, da benutzen die auch Shader, da kannst du dir vllt was rausstibitzen.

PS: ist jetzt mehr so aus dem Kopf und daher vllt nicht ganz so richtig, aber an meinen Code komm ich wohl nicht so schnell, und so ungefähr sollte der Shader aussehen:

Code: Alles auswählen

uniform sampler2D texSampler;
uniform sampler1D transferTexSampler;

void main(void)
{
  gl_FragColor = texture1D(transferTexSampler, texture2D(texSampler, gl_TexCoord[0].st).r);
}
Ist jetzt halt nur ne schnelle Lösung. Ich geh z.B. davon aus, dass die Textur wirklich nur Graustufen enthält und nehm einfach den Rotkanal für die Intensität anstatt mir die extra auszurechnen...
Edit: OK, deine Textur machst du ja wahrscheinlich eh als GL_INTENSITY, wenns schon ne Graue ist. In dem Fall bin ich mir nicht sicher, ob man das .r weglassen kann oder ob mans braucht, das musst du ausprobieren...
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hallo,

ich bin dir super dankbar für deine tollen Antworten und das du dir die Zeit und Geduld dafür nimmst.

Code: Alles auswählen

  gl_FragColor = texture1D(transferTexSampler, texture2D(texSampler, gl_TexCoord[0].st).r); 
Dieser Code den du gepostet hast ist genau eines der Probleme bei mir. Der funktioniert nicht weil "gl_FragColor" unbekannt obwohl ich alle nötigen header eingebunden habe. Gibt es da noch irgendwas was ich beachten oder einbinden muss?

Gruß

Treehouse.

PS: Diese Tutorial ist für QT 4.6 meine Vorgabe ist zur Zeit 4.5.3. Dabei ist diese Shader Funktionalität noch nicht implementiert.
N¤X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N¤X »

Dann informier dich mal ein bisschen über Shader. Die Shader sind nicht in C++ geschrieben und da steht auch nix in headern, das ist alles in GLSL (openGL Shader Language).
Ein guten Ansatzpunkt dafür is das DGL-Wiki. Ist zwar primär für openGL mit Delphi, aber hauptsächlich gehts ja um openGL und in deinem fall noch GLSL, und das ist immer gleich.
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hallo,

ich habe die Header Datei glext.h und wglext.h eingebunden.

Wenn ich nun versuche mit

Code: Alles auswählen

m_FragShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
ein shader Objekt zu erstellen dann bekomme ich einen Speicherzugriffsfehler.

Kann mir vielleicht jemand sagen woran das liegen könnte?

Gruß

Treehouse
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hallo,

So ich habe jetzt folgendes im groben gemacht:

1. Ein Lookup Color array erstellt

Code: Alles auswählen

for(int i=0; i < 256; i++) {
		if ( i != 255 ) 
			m_lookupTable[i][0] = m_lookupTable[i][1] = m_lookupTable[i][2] = (double)i/256.0;
		else {
			m_lookupTable[i][0] = 1.0;
			m_lookupTable[i][1] = 0.0;
			m_lookupTable[i][2] = 0.0;
		}
	}
Dann habe ich das Shader Programm geladen hier die Shader SRC:

Fragment:

Code: Alles auswählen

uniform sampler2D m_OriginalTexture;  
uniform sampler1D m_lookUpTexture;  
  
void main(void)   
{  
    float i = texture2D(m_OriginalTexture, gl_TexCoord[0].xy).r;  
    gl_FragColor = texture1D(m_lookUpTexture, i);  
}
Vorher habe ich noch den look up table hochgeladen:

Code: Alles auswählen

glTexImage1D (GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_RGB , GL_FLOAT, m_lookupTable);
dann habe ich meine m_OriginalTexture gebunden und in diese lade ich jetzt immer die bilddaten.

Das Bild sieht aber wenn ich dies jetzt auf die 2D Fläche klebe, furchtbar aus. Völlig verrauscht und die Farben stimmen gar nicht mehr.

Kann es sein das der Shader nicht richtig funktioniert oder die Lookup table nicht stimmt ?

Gruß,

Treehouse
N&#164;X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N&#164;X »

schön, das du soweit gekommen bist :)

was mir an deinem shader erstmal auffällt: x und y sind für vertexdaten gedacht, texturkoordinaten sind s, t, p und q, also sollte die zeile eher so aussehen:
float i = texture2D(m_OriginalTexture, gl_TexCoord[0].st).r;

ich bin mir momentan ncihtmal sicher, ob das wirklich nen unterschied macht, aber probiers mal so, ist immer besser sich an sowas zu halten...

wenns dann immernoch nicht geht musst du langsam ausprobieren, bis wohin es noch funzt. meld dich einfach wieder, da kann ich dir dann helfen.
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Hallo N¤X,

leider muss ich feststellen das der Inhalt des LUT gar keinen Einfluss auf das Verhalten des Bildes hat. Auch wenn ich das so abändere wie du das beschrieben hast ändert sich nichts.

Aufgefallen ist mir das weil ich mal alle Farben auf 1.0 gesetzt habe und keinen Effekt dadurch erzielt habe.


Tja jetzt muss ich erst mal ein bisschen testen, woran es liegen könnte.

Gruß

Treehouse
N&#164;X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N&#164;X »

OK, das kann ein wenig tricky sein alle Texturen richtig in den shader zu bekommen, aber am besten erstmal klein anfangen beim testen.

Probier mal folgendes als Shader:

Code: Alles auswählen

gl_FragColor = vec3(gl_TexCoord[0].st, 0.0);
Damit kannst du erstmal überprüfen, ob die Texturkoordinaten auch stimmen. Dein Bild sollte damit nen mehr oder weniger schön anzuschauenden Übergang zeigen: Links oben Schwarz, rechts oben rot, links unten grün, rechts unten gelb (s wird auf r und t auf g gemappt. b bleibt konstant 0).

Wenn das tut kannst du einen Schritt weiter gehen: Tut deine eigentliche Textur?

Code: Alles auswählen

gl_FragColor =  texture2D(m_OriginalTexture, gl_TexCoord[0].st);
Damit sollte dein Bild unbearbeitet ausgegeben werden.

Wenn auch das tut muss es an der LUT liegen. um zu überprüfen ob da auch was sinnvolles im Shader ankommt einfach mal Folgendes probieren:

Code: Alles auswählen

gl_FragColor = texture1D(m_lookUpTexture, gl_TexCoord[0].s);  
Das Resultat sollte deine LUT darstellen, also ein Übergang von links schwarz nach rechts weiß, wobei ganz rechts etwas rot sein sollte. (Allerdings solltest du rechts nur reines rot sehen, wenn das Rot ins Weiß ausblutet hast du doch lineare Filterung statt nearest neighbour eingestellt ;) )

Meld mal bei welchem Schritt was schief geht und wenn möglich auch was ^^
mfg N¤X
Treehouse
Beiträge: 100
Registriert: 18. Juni 2007 10:21

Beitrag von Treehouse »

Code: Alles auswählen

gl_FragColor = vec3(gl_TexCoord[0].st, 0.0);
Danke dir vielmals für deine schnelle Antwort. Wenn ich das oben genannte als Fragement Shader nehme passiert gar nichts. Das bild wird ganz normal angezeigt ohne irgend eine Änderung.

Dies ist die Fehlermeldung vom Shader Compiler:

Code: Alles auswählen

0(5) : error C1035: assignment of incompatible types
Beim zweiten kommt das raus was du beschrieben hast.

Und beim dritten ist das bild schwarz.

Aber wenn ich folgendes mache:

Code: Alles auswählen

uniform sampler2D cTexture;
uniform sampler1D lutTexture;

void main (void) {
    gl_FragColor = texture1D(lutTexture, texture2D(cTexture, gl_TexCoord[0].st).r);
}
Dann wird die lut texture angezeigt mit den grau werten von links nach rechts (links schwarz und rechts ist rot).

Ich kann dir leider nicht mehr sagen weil ich es auch gerade nicht ganz verstehe was da falsch läuft

Gruß

Treehouse

PS: Hier sind die Filter:

Code: Alles auswählen

glEnable(GL_TEXTURE_1D);
	glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	
	glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
N&#164;X
Beiträge: 77
Registriert: 21. September 2009 12:24

Beitrag von N&#164;X »

Hm, ja, das macht irgendwie keinen Sinn so... Oo
Da der dritt Shader nur schwarz gebracht hat hätt ich eigentlich gesagt, deine LUT kommt nicht im Shader an, aber da der "fertige" shader plötzlich das von Shader 3 anzeigt scheint sie ja doch irgendwo da zu sein, auch wenn der Shader sowas niemals anzeigen sollte, sondern halt dein Fertiges Bild oO

Was passiert denn bei dem Shader?

Code: Alles auswählen

gl_FragColor = texture1D(m_lookUpTexture, 0.0);
bzw.

Code: Alles auswählen

gl_FragColor = texture1D(m_lookUpTexture, 1.0);
Da sollte das Bild dann wirklich ganz schwarz (oder ganz rot) sein.

Versuch auch mal vor dem aktivieren vom Shader erst die LUT-Texture und direkt darauf die eigentliche Textur zu binden, und dann den Shader aktivieren. Klingt komisch, hat bei mir aber auch schonmal seltsame Shader-Probleme beseitigt ^^
mfg N¤X
Antworten