不同显卡上的GLSL片段着色器

3
我将尝试使用GLSL着色器将12位YUV帧(YUV420P)转换为24位RGB帧。在Nvidia显卡上它可以工作,但是在ATI显卡上工作不正确。图像绘制不正确,颜色不同,图像只有全尺寸的四分之一大小。
以下是着色器代码:
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);
}

我该如何修改它(或创建新的)?

以下是示例代码:

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);

2
请同时发布主机代码。也许你在那里使用了GL_TEXTURE_2D而不是GL_TEXTURE_RECTANGLE_ARB? - sschuberth
我已经发布了代码...还有在着色器中: 对于ATI显卡: y = texture2DRect(y_texture, vec2(sx / 2.0, sy / 2.0)).r; 对于nVidia显卡: y = texture2DRect(y_texture, vec2(sx, sy)).r; - Alexander
好的,但是你所说的“不正确”是什么意思? - Bart
你是否在输出编译器信息?如果没有,请输出。没有编译器消息是不可能编写着色器的。第二件事:所有转换都要显式(例如从float到int)。第三件事:将变量“1.0”替换为“1.0f”。ATI显卡总是抱怨这种东西。 ATI显卡是否支持纹理矩形?您也不应生成自己的纹理ID,而是使用glGenTextures生成它们。 - Tara
糟糕,忽略我的那行代码“将变量如“1.0”替换为“1.0f””。这只适用于OpenCL,而不是OpenGL。 - Tara
显示剩余3条评论
1个回答

0

您正在错误地使用纹理。我没有看到您创建纹理对象(glGenTextures)。您需要首先生成3个纹理对象,并将其传递到glBindTexture中。相反,您正在使用0、1和2索引,这也是不正确的,因为0是不存在的纹理的索引。我怀疑OpenGL会在任何尝试更改0纹理状态时给您错误代码。因此,在调用之间添加一些glError()检查。从技术上讲,您的程序是GL上“未定义行为”的示例,因此应该预期各种HW /驱动程序的执行差异(直到您修复它)。

供您参考,纹理管理应如下所示:

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

请注意,您对glUniform和glActiveTexture的调用仍然是正确的,因此无需修复它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接