2012-03-26 12 views
3

Ich versuche, einen 12-Bit-YUV-Frame (YUV420P) in einen 24-Bit-RGB-Frame mit einem GLSL-Shader zu konvertieren. Auf Nvidia-Grafikkarten funktioniert es, aber auf ATI-Grafikkarten funktioniert es auch, funktioniert aber nicht korrekt. Das Bild wird nicht korrekt gezeichnet. Die Farben sind unterschiedlich und das Bild ist ein Viertel der vollen Größe.GLSL-Fragment-Shader auf verschiedenen Grafikkarten

Hier ist der Code von Shader:

uniform sampler2DRect y_texture, u_texture, v_texture; 
uniform float imageHeight; 

void main(void) { 
    float sx, sy, r, g, b, y, u, v; 
    sx = gl_TexCoord[0].x; 
    sy = imageHeight - gl_TexCoord[0].y; 
    y = texture2DRect(y_texture, vec2(sx/2.0, sy/2.0)).r; 
    u = texture2DRect(u_texture, vec2(sx/2.0, sy/2.0)).r; 
    v = texture2DRect(v_texture, vec2(sx/2.0, sy/2.0)).r; 
    y = 1.1643 * (y - 0.0625); 
    u = u - 0.5; 
    v = v - 0.5; 
    r = y + 1.5958 * v; 
    g = y - 0.39173 * u - 0.8129 * v; 
    b = y + 2.017 * u; 
    gl_FragColor = vec4(r, g, b, 1.0); 
} 

Wie kann ich es ändern (oder neu erstellen)?

Hier ist Beispielcode:

glEnable(GL_TEXTURE_RECTANGLE_ARB); 

//FrameHeight 
int i_imageHeight = glGetUniformLocation(handleProgram, "imageHeight"); 
glUniform1f(i_imageHeight, (float)frameHeight); 

//U 
glActiveTexture(GL_TEXTURE1); 
int i_u = glGetUniformLocationARB(handleProgram, "u_texture"); 
glUniform1iARB(i_u, 1); 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 1); 

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, frameWidth/2, frameHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, uFrameData); 

//V 
glActiveTexture(GL_TEXTURE2); 
int i_v = glGetUniformLocationARB(handleProgram, "v_texture"); 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 2); 
glUniform1iARB(i_v, 2); 

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, frameWidth/2, frameHeight/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, vFrameData); 

//Y 
glActiveTexture(GL_TEXTURE0); 
int i_y = glGetUniformLocationARB(handleProgram, "y_texture"); 
glUniform1iARB(i_y, 3); 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, frameWidth, frameHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yFrameData); 

//Draw 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glBegin(GL_QUADS); 
    glTexCoord2i(0, 0); glVertex2i(0, 0); 
    glTexCoord2i(frameWidth, 0); glVertex2i(this->width, 0); 
    glTexCoord2i(frameWidth, frameHeight); glVertex2i(this->width, this->height); 
    glTexCoord2i(0, frameHeight); glVertex2i(0, this->height); 
glEnd(); 

glFlush(); 
SwapBuffers(hDC); 
+3

Definieren Sie "nicht korrekt". – Bart

+2

Bitte geben Sie auch den Host-Code ein. Vielleicht verwenden Sie GL_TEXTURE_2D anstelle von GL_TEXTURE_RECTANGLE_ARB dort? – sschuberth

+0

Ich habe Code geschrieben ... Auch im Shader: y = texture2Dect (y_texture, vec2 (sx/2.0, sy/2.0)). Diese Zeile für ATI-Karten. In nVidiakarten: y = texture2Dect (y_texture, vec2 (sx, sy)) .r; – Alexander

Antwort

0

Sie sind falsch Texturen. Nirgendwo kann ich sehen, wie Sie die Texturobjekte erstellen (glGenTextures). Sie müssen zuerst 3 Texturobjekte generieren und diese innerhalb von glBindTexture übergeben. Stattdessen verwenden Sie die Indizes 0, 1 und 2, was ebenfalls falsch ist, da 0 ein Index für eine nicht vorhandene Textur ist. Ich vermute, dass OpenGL Ihnen bei jedem Versuch, den Texturzustand zu ändern, Fehlercodes gibt. Fügen Sie also einige glError() Prüfungen zwischen den Anrufen hinzu. Technisch gesehen ist Ihr Programm ein Beispiel für "undefiniertes Verhalten" im GL, daher sollte der Unterschied in der Ausführung durch verschiedene HW/Treiber erwartet werden (bis Sie es beheben).

Für Ihre Referenz sollte die Textur-Management wie folgt aussehen:

GLuint textures[3]; 
glGenTextures(3,textures); 
... 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures[1]); 
//initialize state of t1 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures[2]); 
//initialize state of t2 
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textures[0]); 
//initialize state of t0 

Beachten Sie, dass Ihr Anruf glUniform und glActiveTexture noch korrekt sind, so dass keine Notwendigkeit, sie zu beheben.

Verwandte Themen