我有一个简单的函数,它应该在OpenGL中存在的纹理中进行处理,并将其大小/大小缩减为给定的宽度和高度,并返回新纹理ID的ID。OpenGL离屏渲染返回清晰颜色
它在第一次完美地工作并且代码可以在相同的源纹理甚至最终的纹理上运行多次(在循环中)。但是,一旦帧通过,代码就不再有效。一旦功能被破坏的结果是具有正确宽度和高度输入的纹理,但是其根本不使用输入纹理,并且输出像素是使用的清晰颜色glClearColor(0, 1, 1, 1);
的纹理。使用传统的OpenGL代码来显示一个彩色的四边形也可以工作一次,然后停止工作,让我建议问题不在于输入纹理,但几何不在FBO中绘制。
GLuint Texture::Downsample(int width, int height, GLuint source)
{
// Use the largest values
width = Max(16, width);
height = Max(16, height);
// Create a frame buffer object
GLuint fbo, rbo, target_texture;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &target_texture); // Create the target texture
GLenum status;
// : Target Texture :
glBindTexture(GL_TEXTURE_2D, target_texture); // Bind the texture position unit to be used as a buffer
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target_texture, 0); // Setup the Framebuffer
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) throw;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) throw;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// Use the FBO to draw to the color attachment
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glPushAttrib(GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT);
glViewport(0, 0, width, height);
glClearColor(0, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// : Draw the original texture
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//this->Bind(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, source);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glDisable(GL_DEPTH_TEST); // Disable Depth Testing
glDisable(GL_CULL_FACE);
// Geometry Data
const float uvdata[] = { 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f };
const float geometrydata[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f };
const unsigned char indices[] = { 0, 1, 2, 2, 3, 0 };
glEnableClientState(GL_VERTEX_ARRAY); // Enable Client Vertex Arrays
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable Client Texture Coordinate Arrays
glVertexPointer(3, GL_FLOAT, 0, &geometrydata[0]); // Pass the geometry data into the Vertex Array
glTexCoordPointer(2, GL_FLOAT, 0, &uvdata[0]); // Pass the UV data into the Texture Coordinate Array
// Draw the geometry using the indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable Client Texture Coordinate Arrays
glDisableClientState(GL_VERTEX_ARRAY); // Disable Client Vertex Arrays
glPopAttrib();
glDeleteTextures(1, &source); // Delete the old texture
glDrawBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDeleteFramebuffers(1, &fbo);
glDeleteRenderbuffers(1, &rbo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, target_texture);
int w, h;
int miplevel = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, miplevel, GL_TEXTURE_HEIGHT, &h);
return target_texture;
}