Framebuffer-Objekt mit Float-Textur klemmt Werte
Ich habe diese ähnliche Frage geprüft, aber die Vorschläge haben mein Problem nicht gelöst:Geringe Präzision und Klemmung beim Schreiben auf Fließkomma-FBO.
Ich rendere ein Float-Bild mit einem Framebuffer-Objekt als Render-Ziel. Die von glReadPixels gelesenen Werte werden jedoch zwischen 0 und 1 geklemmt. Wenn ich versuche, mein Bild mit normalisierten Werten in diesem Bereich zu rendern, funktioniert dies, aber Werte außerhalb dieses Bereichs werden auf 1 oder 0 geklemmt. Folgt einigen Teilen des Codes.
So habe ich die Textur erstellt, die ich dem FBO hinzugefügt habe:
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);
Wie ich es nach dem Malen gelesen habe:
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(0, 0, ResX, ResY, GL_RGB, GL_FLOAT, data);
Ich habe mit ein Dreieck im Bild gezeichnet
glColor3f(0.5f, 2.0f, -0.5f);
Und die Pixelwerte erscheinen als(0,5f, 1,0f, 0,0f) im Lesepuffer.
Wie kann ich Werte außerhalb dieses Bereichs zurückgeben?
Es folgt eine vereinfachte Version meines Codes (ich habe den Tiefenpuffer beibehalten, weil ich ihn im Original verwende):
Ps. Ich habe den folgenden Code basierend auf der Antwort korrigiert. Es funktioniert jetzt.
#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;
}