繁体   English   中英

OpenGL屏幕外渲染返回清晰的颜色

[英]OpenGL Offscreen Rendering Returning Clear Color

我有一个简单的函数,该函数应该接收OpenGL中存在的现有纹理并将其调整大小/缩小到给定的宽度和高度,并返回新纹理ID的ID。

第一次,它运行良好,代码可以在相同的源纹理甚至结果纹理上多次运行(循环)。 但是,一旦帧通过,该代码将不再起作用。 一旦函数损坏,结果将是具有正确宽度和高度输入的纹理,但是它根本不使用输入纹理,并且输出像素是使用glClearColor(0, 1, 1, 1);像素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;
}

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

只需在返回之前添加glFinish()并创建互斥锁方案就可以了。 然后,当访问纹理时,将在互斥锁上尝试锁,以确定是否正在使用该纹理。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM