3

この同様の質問を確認しましたが、提案は私の問題を解決しませんでした:浮動小数点 FBO への書き込み時の精度とクランプが低い

フレームバッファ オブジェクトをレンダー ターゲットとして使用してフロート イメージをレンダリングしています。ただし、glReadPixels によって読み取られる値は 0 から 1 の間にクランプされます。この範囲内の正規化された値を使用して画像をレンダリングしようとすると機能しますが、この範囲外の値は 1 または 0 にクランプされます。コードの一部に従います。

FBO にアタッチしたテクスチャの作成方法は次のとおりです。

    glGenTextures(1, &color_tex); 
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
        GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
        GL_NEAREST);
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB, ResX, ResY, 0,
        GL_RGB, GL_FLOAT, NULL);

塗装後の読み方:

    glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
    glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);

を使用して画像に三角形を描きました

    glColor3f(0.5f, 2.0f, -0.5f);

また、ピクセル値は、読み取りバッファーに(0.5f, 1.0f, 0.0f)として表示されます。

この範囲外の値を返すにはどうすればよいですか?

私のコードの簡略化されたバージョンに従います(元のバッファーで使用しているため、深度バッファーを保持しました):

Ps。回答に基づいて以下のコードを修正しました。それは今動作します。

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

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#define WINDOW_WIDTH                    800
#define WINDOW_HEIGHT                   600

bool initGL(int argc, char *argv[])
{
    // initialize GLUT and glexts
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("FBO");

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed. */
        printf("Error: %s\n", glewGetErrorString(err));
        return 0;
    }

    if (!GLEW_EXT_framebuffer_object)
    {
        printf("Error: no extension GL_EXT_framebuffer_object.");
        return 0;
    }

    if (!GLEW_ARB_color_buffer_float)
    {
        printf("Error: no extension ARB_color_buffer_float.");
        return 0;
    }

    glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
    glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
    glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);

    return 1;
}

void glErrorCheck()
{
    int errCode;
    if ((errCode = glGetError()) != GL_NO_ERROR)
    {
        printf("Failure in OpenGL %d", errCode);
        exit(0);
    }
}

bool renderFBO()
{

    GLenum status;
    GLuint color_tex, depth_rb, fb;

    int ResX, ResY;

    ResY = 4;
    ResX = 4;

    float *data;

    //gen renderbuffer
    glGenRenderbuffers(1, &depth_rb);
    glErrorCheck();
    // initialize depth renderbuffer
    glBindRenderbuffer(GL_RENDERBUFFER, depth_rb);
    glErrorCheck();
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, ResX,
            ResY);

    glErrorCheck();

    // make a texture
    glGenTextures(1, &color_tex);
    // initialize texture that will store the framebuffer image (BGRA type)
    glBindTexture(GL_TEXTURE_RECTANGLE_ARB, color_tex);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
            GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
            GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB, ResX, ResY, 0,
            GL_RGB, GL_FLOAT, NULL);
    glErrorCheck();

    // gen the framebuffer object
    glGenFramebuffers(1, &fb);
    // bind the framebuffer, fb, so operations will now occur on it
    glBindFramebuffer(GL_FRAMEBUFFER, fb);

    // bind this texture to the current framebuffer obj. as color_attachment_0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
            GL_TEXTURE_RECTANGLE_ARB, color_tex, 0);
    glErrorCheck();

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
            GL_RENDERBUFFER, depth_rb);
    glErrorCheck();

    //check framebuffer status
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (status != GL_FRAMEBUFFER_COMPLETE)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        {
            printf("Failure in OpenGL Framebuffer %d", status);
            return 0;
        }
    }
    glErrorCheck();

    //render to GL_TEXTURE_2D
    glBindFramebuffer(GL_FRAMEBUFFER, fb);
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, ResX, ResY);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0.0, (float) ResX, 0.0, (float) ResY, -1.0, 1.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glBegin(GL_TRIANGLES);

    printf("Original color: %f %f %f\n", 0.5f, 2.0f, -0.5f);

    glColor3f(0.5f, 2.0f, -0.5f);

    glVertex3f(0.0f, 0.0f, 0.0f);
    glVertex3f((float) ResX, 0.0f, 0.0f);
    glVertex3f((float) ResX, (float) ResY, 0.0f);

    glEnd();

    // read framebuffer
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glErrorCheck();

    // allocate memory for texture data
    data = new float[ResX * ResY * 3];
    if (data == NULL)
    {
        printf("Out of memory\n");
        return false;
    }

    //glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
    glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);

    glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);
    glErrorCheck();

    //print the last pixel of the buffer
    int i = ResX * ResY - 1;
    printf("Buffer color: %f %f %f\n", data[i], data[i + 1], data[i + 2]);

    // Re-enable rendering to the window
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glErrorCheck();

    //deallocate data
    delete[] data;

    //delete buffers
    glDeleteTextures(1, &color_tex);
    glDeleteRenderbuffers(1, &depth_rb);
    glDeleteFramebuffers(1, &fb);
    glErrorCheck();

    return true;
}

int main(int argc, char **argv)
{

    if (!initGL(argc, argv))
    {
        printf("Failure during GLUT/GLEXT initialization.");
        return 0;
    }

    if (!renderFBO())
        printf("Fail!\n");

    printf("End!\n");
    return 0;

}
4

2 に答える 2

3

関数で一連のglClampColor()操作を実行します。initGL()

glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE);
glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);

私のシステムでは、GL_CLAMP_VERTEX_COLOR.

于 2012-07-02T14:56:35.560 に答える
1

glClampColor使用する色glReadPixelsがクランプされるかどうかを示すために使用する必要があります。

これは色を読み取るためだけのものであることに注意してください。フラグメントシェーダーによって書き込まれるものは、常にアンクランプされます。

于 2012-06-26T16:28:11.027 に答える