1

我正在尝试在我的 ATI 显卡上使用亮度纹理。

问题:我无法从我的 GPU 中正确检索数据。每当我尝试阅读它(使用 glReadPixels)时,它给我的只是一个“全一”数组(1.0、1.0、1.0...)。

您可以使用以下代码对其进行测试:

#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>

static int arraySize = 64;
static int textureSize = 8;
//static GLenum textureTarget = GL_TEXTURE_2D;
//static GLenum textureFormat = GL_RGBA;
//static GLenum textureInternalFormat = GL_RGBA_FLOAT32_ATI;
static GLenum textureTarget = GL_TEXTURE_RECTANGLE_ARB;
static GLenum textureFormat = GL_LUMINANCE;
static GLenum textureInternalFormat = GL_LUMINANCE_FLOAT32_ATI;

int main(int argc, char** argv)
{
    // create test data and fill arbitrarily
    float* data = new float[arraySize];
    float* result = new float[arraySize];

    for (int i = 0; i < arraySize; i++)
    {
        data[i] = i + 1.0;
    }

    // set up glut to get valid GL context and
    // get extension entry points
    glutInit (&argc, argv);
    glutCreateWindow("TEST1");
    glewInit();

    // viewport transform for 1:1 pixel=texel=data mapping
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, textureSize, 0.0, textureSize);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glViewport(0, 0, textureSize, textureSize);

    // create FBO and bind it (that is, use offscreen render target)
    GLuint fboId;
    glGenFramebuffersEXT(1, &fboId);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

    // create texture
    GLuint textureId;
    glGenTextures (1, &textureId);
    glBindTexture(textureTarget, textureId);

    // set texture parameters
    glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP);

    // define texture with floating point format
    glTexImage2D(textureTarget, 0, textureInternalFormat, textureSize, textureSize, 0, textureFormat, GL_FLOAT, 0);

    // attach texture
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, textureTarget, textureId, 0);

    // transfer data to texture
    //glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
    //glRasterPos2i(0, 0);
    //glDrawPixels(textureSize, textureSize, textureFormat, GL_FLOAT, data);
    glBindTexture(textureTarget, textureId);
    glTexSubImage2D(textureTarget, 0, 0, 0, textureSize, textureSize, textureFormat, GL_FLOAT, data);

    // and read back
    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
    glReadPixels(0, 0, textureSize, textureSize, textureFormat, GL_FLOAT, result);

    // print out results
    printf("**********************\n");
    printf("Data before roundtrip:\n");
    printf("**********************\n");

    for (int i = 0; i < arraySize; i++)
    {
        printf("%f, ", data[i]);
    }
    printf("\n\n\n");

    printf("**********************\n");
    printf("Data after roundtrip:\n");
    printf("**********************\n");

    for (int i = 0; i < arraySize; i++)
    {
        printf("%f, ", result[i]);
    }
    printf("\n");

    // clean up
    delete[] data;
    delete[] result;

    glDeleteFramebuffersEXT (1, &fboId);
    glDeleteTextures (1, &textureId);

    system("pause");

    return 0;
}

我还在互联网上的某个地方读到 ATI 卡还不支持亮度。有没有人知道这是不是真的?

4

2 回答 2

1

这与亮度值无关;问题在于您读取浮点值。

为了通过 glReadPixels 正确读取浮点数据,您首先需要设置颜色钳位模式。由于您显然没有使用 OpenGL 3.0+,因此您应该查看ARB_color_buffer_float 扩展。在那个扩展中是glClampColorARB,它的工作方式与核心 3.0 版本非常相似。

于 2012-11-18T20:53:59.000 回答
0

这是我发现的:

1) 如果您使用 GL_LUMINANCE 作为纹理格式(以及 GL_LUMINANCE_FLOAT32_ATI GL_LUMINANCE32F_ARB 或 GL_RGBA_FLOAT32_ATI 作为内部格式),则 glClampColor(..)(或 glClampColorARB(..))似乎根本不起作用。如果我将纹理格式设置为 GL_RGBA,我只能看到值被主动钳制/未钳制。我不明白为什么会发生这种情况,因为我听说的唯一 glClampColor(..) 限制是它只适用于浮点缓冲区,所有选择的内部格式似乎都是。

2)如果您使用 GL_LUMINANCE(同样,使用 GL_LUMINANCE_FLOAT32_ATI、GL_LUMINANCE32F_ARB 或 GL_RGBA_FLOAT32_ATI 作为内部格式),看起来您必须“更正”您的输出缓冲区将其每个元素除以 3。我猜这是因为当您使用 glTexImage2D(. .) 使用 GL_LUMINANCE它在内部将每个数组组件复制三次,当您使用 glReadPixel(..) 读取 GL_LUMINANCE 值时,它会根据 RGB 组件的总和计算其值(因此,是您作为输入给出的三倍)。但同样,它仍然为您提供钳位值。

3)最后,如果你使用 GL_RED 作为纹理格式(而不是 GL_LUMINANCE),你不需要打包你的输入缓冲区并且你可以正确地得到你的输出缓冲区。这些值没有被限制,您根本不需要调用 glClampColor(..)。

所以,我想我会坚持使用 GL_RED,因为最终我想要的是一种从“内核”发送和收集浮点值的简单方法,而不必担心偏移数组索引或类似的事情。

于 2012-11-19T16:56:26.100 回答