2014-10-27 93 views
0

我有一个简单的函数,它应该在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; 
} 

回答

0

找到答案(按照我提出问题后的通常10分钟)。我正在运行OpenGL的多上下文实现。因此,在函数返回后立即使用输入纹理ID,但GPU尚未完成处理。

在返回和创建互斥锁之前,只需添加glFinish()就能发挥魅力。然后,当纹理被访问时,互斥体上的try-lock被用来确定它是否被使用。

例如。 Mutex.Instance.lock(); TextureID_Internal = Downsample(128,128, TextureID_Internal); Mutex.Instance.unlock();