OpenGL - 在NVIDIA卡上渲染纹理时出现FBO黑屏

时间:2015-09-27 01:02:29

标签: c++ opengl fbo

我已经关注了如何设置和渲染FBO的一些教程。起初它工作,场景渲染得很好,但事实证明该程序使用的是集成GPU。 (我用我的笔记本电脑)

然后,出于好奇,我用了更高性能的#34; GPU(Nvidia GeForce GT540M),屏幕全黑。此时我尝试将FBO的颜色纹理保存到文件中,实际上是在那里绘制了场景。

但最终我找到了解决方案。以前我只清除FBO(颜色和深度缓冲区),但现在我清除了FBO和默认的帧缓冲区,并再次渲染场景。

所以问题是,我必须两次调用glClear是不是很糟糕?我真的要两次打电话给glClear吗?为什么一个人清楚地在集成卡上工作?

如果有帮助,我可以展示一些代码。

帧缓冲初始化

bool FrameBufferObject::initializeFBO( int width, int height ) {
    glActiveTexture( GL_TEXTURE0 );

    if ( !_colorTexture.createEmptyTexture( width, height ) ) {
        return false;
    }
    _textureId = _colorTexture.getTextureId();

    if ( !_depthTexture.createDepthTexture( width, height ) ) {
        return false;
    }
    _depthTextureId = _depthTexture.getTextureId();

    glGenFramebuffers( 1, &_frameBufferID );
    glBindFramebuffer( GL_FRAMEBUFFER, _frameBufferID );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureId, 0 );
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTextureId, 0 );

    if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE ) {
        return false;
    }

    glBindFramebuffer( GL_FRAMEBUFFER, 0 );

    _width = width;
    _height = height;

    _isInitialized = true;

    return true;
}

颜色纹理

bool Texture::createEmptyTexture( int width, int height ) {
    if ( isLoaded() ) {
        closeTexture();
    }

    GLuint textureId = 0;

    glGenTextures( 1, &textureId );

    if ( getOpenGLError( "Unable to generate TextureID." ) ) {
        return false;
    }

    glBindTexture( GL_TEXTURE_2D, textureId );
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glBindTexture( GL_TEXTURE_2D, 0 );

    if ( getOpenGLError( "Error creating empty texture." ) ) {
        glDeleteTextures( 1, &textureId );
        return false;
    }

    _isLoaded = true;
    _textureWidth = _imageWidth = width;
    _textureHeight = _imageHeight = height;
    _textureId = textureId;

    return true;
}

深度纹理是相同的,除了它使用GL_DEPTH_COMPONENT格式,

glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );

后处理着色器

顶点着色器

#version 330 core

in vec2 inVertex;
in vec2 inTexture;

out vec2 texCoords;

void main() {
    texCoords = inTexture;
    gl_Position = vec4( inVertex.x, inVertex.y, 0, 1 );
}

片段着色器

#version 330 core

in vec2 texCoords;

uniform sampler2D texture0;

layout(location = 0) out vec4 outColor;

void main() {
    vec4 color = texture( texture0, texCoords );
    outColor = color;
}

渲染代码如下所示,

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

fbo.bindFBO();
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

// .. render scene ..

fbo.unbindFBO();

// This is a namespace
PostProcShader::shader.useShader();
PostProcShader::render( fbo.getColorTexture() );
PostProcShader::shader.disableShader();

SDL_GL_SwapWindow( window );

后处理着色器只是在屏幕大小的四边形上渲染纹理。场景使用3个着色器:一个用于3D对象,第二个用于天空盒,最后一个用于字体。

我在VS 2015中使用C ++,SDL2和(当然)OpenGL / Glew。

编辑:

深度测试初始化​​

glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
glDepthFunc( GL_LEQUAL );
glDepthRange( 0.0f, 1.0f );
glClearDepth( 1.0f );

1 个答案:

答案 0 :(得分:-1)

从英特尔HUD转到Nvidia时,我遇到了类似的问题。但是我的解决方案很简单。我必须确保在渲染到新的帧缓冲区(在Nvidia上)之前调用glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT),否则我将看不到任何渲染。我怀疑在Nvidia上深度缓冲区的设置没有与Intel上的默认设置相同,因此清除它会将其设置为opengl默认清除值。