【问题标题】:Why am I not able to attach this texture uniform to my GLSL fragment shader?为什么我无法将此纹理统一附加到我的 GLSL 片段着色器?
【发布时间】:2011-05-09 08:56:33
【问题描述】:

在我的 Mac 应用程序中,我根据来自附加相机的 YUV 4:2:2 数据定义了一个矩形纹理。使用标准的顶点和纹理坐标,我可以毫无问题地将其绘制到屏幕上的矩形区域。

但是,我想使用 GLSL 片段着色器在 GPU 上处理这些图像帧,并且在将矩形视频纹理作为制服传递给片段着色器时遇到了麻烦。当我尝试这样做时,纹理只是显示为黑色。

着色器程序编译、链接并通过验证。我从着色器程序中收到了制服的正确地址。其他uniforms,例如浮点值,正确传入,片段着色器响应这些值的变化。片段着色器接收正确的纹理坐标。我还用 glGetError() 随意地洒了我的代码,并且在任何地方都没有看到任何错误。

顶点着色器如下:

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}

片段着色器如下:

uniform sampler2D videoFrame;

void main()
{
    gl_FragColor = texture2D(videoFrame, gl_TexCoord[0].st);
}

这应该只是在我的矩形几何体上显示纹理。

相关绘图代码如下:

static const GLfloat squareVertices[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    -1.0f,  1.0f,
    1.0f,  1.0f,
};

const GLfloat textureVertices[] = {
    0.0, videoImageSize.height,
    videoImageSize.width, videoImageSize.height,
    0.0, 0.0,
    videoImageSize.width, 0.0
};

CGLSetCurrentContext(glContext);

if(!readyToDraw)
{
    [self initGL];
    readyToDraw = YES;
}


glViewport(0, 0, (GLfloat)self.bounds.size.width, (GLfloat)self.bounds.size.height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); 

glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);

glGenTextures(1, &textureName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, textureName);

glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageSize.width, videoImageSize.height, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);  

glUseProgram(filterProgram);    

glUniform1i(uniforms[UNIFORM_VIDEOFRAME], 0);   

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, squareVertices);
glTexCoordPointer(2, GL_FLOAT, 0, textureVertices);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

[super drawInCGLContext:glContext pixelFormat:pixelFormat forLayerTime:interval displayTime:timeStamp];

glDeleteTextures(1, &textureName);

此代码位于 CAOpenGLLayer 中,其中超类的 -drawInCGLContext:pixelFormat:forLayerTime: displayTime: 仅运行 glFlush()

使用如下代码读取统一地址:

uniforms[UNIFORM_VIDEOFRAME] = glGetUniformLocation(filterProgram, "videoFrame");

正如我所说,如果我注释掉 glUseProgram()glUniform1i() 行,这个带纹理的矩形就会正确绘制。将它们留在里面会导致绘制一个黑色矩形。

什么会阻止我的纹理统一被传递到我的片段着色器?

【问题讨论】:

  • 如果不立即 glDeleteTextures 是否有效? glDrawArrays 不是同步的...
  • @Ben - 我已经试过了,有没有立即删除纹理。这似乎没有什么区别。事实上,它的原始版本使用 glTextureRangeAPPLE 只是为纹理映射一些内存,并且只在应用程序开始时创建一次。正如我上面所说,当注释掉激活着色器程序的行时,这渲染得很好,所以我不相信这是原因。

标签: macos opengl glsl


【解决方案1】:

不确定您正在使用的 GLSL 版本,但从 1.40 开始,sampler2DRect 类型专门用于访问非二次幂纹理。 可能是你要找的东西,但我不知道在 glsl 1.40 之前如何处理矩形纹理。

【讨论】:

  • 科斯是对的。片段着色器表示 sampler2d,因此着色器系统将查看 GL_TEXTURE_2D 绑定点以查找纹理,而不是 GL_TEXTURE_RECTANGLE_EXT。这些是不同的。所以系统永远不会看到正确的纹理对象。正如 Kos 提到的,使用 sampler2DRect(如果目标设备支持 texture_rectangle 扩展)或 GL_TEXTURE_2D 绑定点(如果设备支持 texture_non_power_of_two)。如果硬件都不支持,那么您需要以二次幂纹理上传帧...
  • 宾果游戏。就是这样。通过将我的制服更改为sampler2DRect 类型,一切都将按原样显示。我在 OpenGL ES 2.0 的 pre-1.4 GLSL 上花费了太多时间。
  • 为了后代,我还应该补充一点,我需要在上面的着色器中将 texture2D() 更改为 texture2DRect()
猜你喜欢
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多