简体   繁体   English

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

[英]OpenGL - FBO black screen when rendering to texture on NVIDIA card

I've followed some tutorials on how to setup and render an FBO.我已经学习了一些关于如何设置和渲染 FBO 的教程。 At first it worked and the scene rendered fine, but it turns out the program was using the integrated GPU.起初它可以工作并且场景渲染得很好,但事实证明该程序使用的是集成 GPU。 (I'm using my laptop) (我正在使用我的笔记本电脑)

Then, out of curiosity, I ran it with the "higher-performance" GPU (an Nvidia GeForce GT540M ) and the screen was all black.然后,出于好奇,我用“更高性能”的 GPU( Nvidia GeForce GT540M )运行它,屏幕全黑。 At this point I tried saving the FBO's color texture into a file and the scene was actually being drawn there.在这一点上,我尝试将 FBO 的颜色纹理保存到一个文件中,并且场景实际上是在那里绘制的。

But eventually I found a solution.但最终我找到了解决方案。 Previously I would only clear the FBO (color and depth buffers), but now I clear both the FBO and the default framebuffer and the scene is rendered again.以前我只会清除 FBO(颜色和深度缓冲区),但现在我清除 FBO 和默认帧缓冲区并再次渲染场景。

So the question is , is it bad that I have to call glClear twice?所以问题是,我必须两次调用 glClear 是不是很糟糕? Do I really have to call glClear twice?我真的必须两次调用 glClear 吗? Why would the one clear work on the integrated card?为什么一个 clear 会在集成卡上工作?


I can show some code if it helps.如果有帮助,我可以显示一些代码。

Framebuffer initialization帧缓冲区初始化

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;
}

Color Texture颜色纹理

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;
}

The Depth Texture is the same, except it uses the GL_DEPTH_COMPONENT format,深度纹理是相同的,除了它使用 GL_DEPTH_COMPONENT 格式,

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

Post Processing Shader后处理着色器

Vertex shader顶点着色器

#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 );
}

Fragment shader片段着色器

#version 330 core

in vec2 texCoords;

uniform sampler2D texture0;

layout(location = 0) out vec4 outColor;

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

The rendering code looks like this,渲染代码如下所示,

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 );

Where the post processing shader simply renders the texture on a screen-sized quad.后处理着色器只是在屏幕大小的四边形上渲染纹理。 The scene uses 3 shaders: one for 3D objects, the second for the skybox and last one for fonts.该场景使用 3 个着色器:一个用于 3D 对象,第二个用于天空盒,最后一个用于字体。

I'm using C++, SDL2 and (of course) OpenGL/Glew in VS 2015.我在 VS 2015 中使用 C++、SDL2 和(当然)OpenGL/Glew。


Edit:编辑:

Depth Test initialization深度测试初始化

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

I got a similar problem when I went from Intel HUD to Nvidia.当我从 Intel HUD 转到 Nvidia 时,我遇到了类似的问题。 However my solution was simple.但是我的解决方案很简单。 I had to ensure I called glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) before rendering to the new framebuffer (on Nvidia) otherwise I would see nothing rendered.我必须确保在渲染到新的帧缓冲区(在 Nvidia 上glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)之前调用glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) ) 否则我看不到任何渲染。 I suspect that on Nvidia the depth buffer is not set to the same defaults as on Intel so clearing it sets it to the opengl default clear value.我怀疑在 Nvidia 上,深度缓冲区没有设置为与 Intel 相同的默认值,因此清除它会将其设置为 opengl 默认清除值。

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

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