この同様の質問を確認しましたが、提案は私の問題を解決しませんでした:浮動小数点 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;
}