GLSL fragment shader on different video cards
I am trying to convert a 12-bit YUV frame (YUV420P) to a 24-bit RGB frame using the GLSL shader. It works on Nvidia video cards, but it also works on ATI video cards, but does not work correctly. The image is not drawing correctly. The colors are different and the image is a quarter of its full size.
Here is the shader code:
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);
}
How can I change it (or create a new one)?
Here's some sample code:
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);
source to share
You are using textures incorrectly. Nowhere I see how you create texture objects ( glGenTextures
). First you need to create 3 texture objects and pass them inside glBindTexture
. Instead, you are using indices 0, 1 and 2, which is also incorrect, because 0 is the index of a texture that does not exist. I suspect OpenGL will give you error codes whenever you try to change the state of a texture. So add some check glError
() between calls. Technically your program is an example of undefined behavior in GL, so you should expect performance differences between different HWs / drivers (until you fix).
For your reference, the texture control should look like this:
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
Note that your calls to glUniform and glActiveTexture are still correct, so there is no need to fix them.
source to share