OpenGL - 渲染到纹理 - 总是黑屏
OpenGL - Render to texture - always blackscreen
我是 OpenGL 的新手,我正在研究 Voxelengine。我想将当前场景渲染为纹理,然后在四边形上渲染该纹理。问题是我总是黑屏。当我将碎片颜色输出乘以 5 时,我的屏幕变成灰色。因此我认为问题是,纹理没有得到我的渲染器的输出。直接渲染到默认渲染器工作正常,所以我认为这是我的 fbo 的问题。
Renderer.h:
public ref class DefaultRenderer : RendererBase, IRenderer
{
public:
internal:
protected:
private:
EngineCore::Graphics::GraphicController* GraphicControl_;
Controllers::CameraControl^ CameraControl_;
Controllers::ColorPaletteControl^ ColorPaletteControl_;
Controllers::LightControl^ LightControl_;
unsigned int texture_;
unsigned int FBO_;
unsigned int RBO_;
unsigned int quadVAO_;
unsigned int quadVBO_;
array<float>^ quadVertices_;
EngineCore::Graphics::Shaders::ShaderProgram* screenShader_;
bool IsShadowsEnabled_ = false; // At the moment not used / not implemented
bool IsSkyBoxEnabled_ = true; // At the moment not used / not implemented
bool IsBloomEnabled_ = false; // At the moment not used / not implemented
bool IsToneMappingEnabled_ = false; // At the moment not used / not implemented
bool IsFxaaEnabled_ = false; // At the moment not used / not implemented
public:
DefaultRenderer() {};
~DefaultRenderer() {
this->!DefaultRenderer();
};
!DefaultRenderer() {};
internal:
protected:
private:
public:
/// <summary>
/// Enables Shadows
/// </summary>
virtual void EnableShadows();
/// <summary>
/// Disables Shadows
/// </summary>
virtual void DisableShadows();
/// <summary>
/// Enables Skybox
/// </summary>
virtual void EnableSkyBox();
/// <summary>
/// Disables Skyboy
/// </summary>
virtual void DisableSkyBox();
/// <summary>
/// Enables Bloom
/// </summary>
virtual void EnableBloom();
/// <summary>
/// Disables Bloom
/// </summary>
virtual void DisableBloom();
/// <summary>
/// Enables ToneMapping
/// </summary>
virtual void EnableToneMapping();
/// <summary>
/// Disables ToneMapping
/// </summary>
virtual void DisableToneMapping();
/// <summary>
/// Enables Fxaa
/// </summary>
virtual void EnableIsFxaa();
/// <summary>
/// Disables Fxaa
/// </summary>
virtual void DisableIsFxaa();
/// <summary>
/// This function enable the use of ColorPalette in the PBR-Rendering
/// and disables the use of Texturing for World-Elements.
/// World-Elements are the Voxels.
/// </summary>
virtual void EnableRenderingWithColorPalette();
/// <summary>
/// This function disable the use of ColorPalette in the PBR-Rendering
/// and enables the use of Texturing for World-Elements.
/// World-Elements are the Voxels.
/// </summary>
virtual void DisableRenderingWithColorPalette();
/// <summary>
/// Enables color palette transparency
/// </summary>
virtual void EnableColorTransparency();
/// <summary>
/// Disables color palette transparency
/// </summary>
virtual void DisableColorTransparency();
internal:
void Init(VoxelEngine::IEngine^ engine, EngineCore::Graphics::GraphicController* graphicControl, Controllers::CameraControl^ cameraControl, Controllers::ColorPaletteControl^ colorPalette, EngineCore::Input::InputSystem* input) override;
void Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime) override;
protected:
private:
/// <summary>
/// This function adds all of our shaders and create an Open GL shader
/// program from them.
/// </summary>
void AddShadersAndCreateGLProgram(VoxelEngine::IEngine^ engine);
/// <summary>
/// In this function all needed uniform buffers are created.
/// </summary>
void CreateUniformBuffers();
/// <summary>
/// In this function all needed voxel buffers are created.
/// </summary>
void CreateVoxelBuffers();
/// <summary>
/// In this function the uniform gets their values.
/// </summary>
void AddUniforms();
/// <summary>
/// In this function the buffers got rendered.
/// </summary>
void RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram);
/// <summary>
/// This function creates the framebuffer.
/// </summary>
void CreateFrameBuffer();
};
Renderer.cpp CreateFrameBuffer:
void DefaultRenderer::CreateFrameBuffer()
{
quadVertices_ = gcnew array<float>
{ // positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
float quadVertices[24];
for (size_t i = 0; i < 24; i++)
{
quadVertices[i] = quadVertices_[i];
}
// screen quad VAO
unsigned int quadVAO;
unsigned int quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
quadVAO_ = quadVAO;
quadVBO_ = quadVBO;
glBindVertexArray(quadVAO_);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO_);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
screenShader_ = &GraphicControl_->GetShaderProgram("framebuffer_screen_Program");
screenShader_->Use();
glUniform1i(screenShader_->GetUniform("screenTexture"), 0);
unsigned int framebuffer;
glGenFramebuffers(1,&framebuffer);
FBO_ = framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, FBO_);
// generate texture
unsigned int texColorBuffer;
glGenTextures(1, &texColorBuffer);
texture_ = texColorBuffer;
glBindTexture(GL_TEXTURE_2D, texture_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1920, 1080, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// attach it to currently bound framebuffer object
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
RBO_ = rbo;
glBindRenderbuffer(GL_RENDERBUFFER, RBO_);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1920, 1080);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO_);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
}
FBO_ = framebuffer;
texture_ = texColorBuffer;
RBO_ = rbo;
quadVBO_ = quadVBO;
quadVAO_ = quadVAO;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Renderer.cpp 渲染循环:
void DefaultRenderer::Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime)
{
//bind to framebuffer and draw scene to color texture
glBindFramebuffer(GL_FRAMEBUFFER, FBO_ );
//clear framebuffer
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
auto tmp = GraphicControl_->GetVoxelBuffer("test");
tmp.ClearVoxelRenderList();
tmp.VoxelBufferData(chunksForRendering);
AddUniforms();
RenderVoxelBuffer(tmp, GraphicControl_->GetShaderProgram("testProgram"));
// bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//// clear all relevant buffers
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GraphicControl_->GetShaderProgram("framebuffer_screen_Program").Use();
glBindVertexArray(quadVAO_);
glDisable(GL_DEPTH_TEST); // disable depth test
glBindTexture(GL_TEXTURE_2D, texture_); // use the color attachment texture as the texture of the quad plane
glDrawArrays(GL_TRIANGLES, 0, 6);
}
Renderer.cpp渲染体素缓冲区:
void DefaultRenderer::RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram)
{
shaderProgram.Use();
for (auto const& singleChunk : tmp.List_)
{
glBindVertexArray(singleChunk->Id);
glBindBuffer(GL_ARRAY_BUFFER, singleChunk->VoxelBuffer);
glBufferData(GL_ARRAY_BUFFER, singleChunk->VoxelCount * sizeof(EngineCore::Graphics::Data::VoxelData), singleChunk->List.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, sizeof(EngineCore::Graphics::Data::VoxelData), 0);
glUniform3f(shaderProgram.GetUniform("u_chunk_location"), (float)singleChunk->OffsetX, (float)singleChunk->OffsetY, (float)singleChunk->OffsetZ);
glDrawArrays(GL_POINTS, 0, singleChunk->VoxelCount);
}
glBindVertexArray(0);
}
framebuffer_screen.fs:
#version 450 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
vec3 col = texture(screenTexture, TexCoords).rgb;
FragColor = vec4(col, 1.0);
}
framebuffer_screen.vs:
#version 450 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}
我忘记在设置我的着色器属性之前激活我的着色器。现在一切正常
我是 OpenGL 的新手,我正在研究 Voxelengine。我想将当前场景渲染为纹理,然后在四边形上渲染该纹理。问题是我总是黑屏。当我将碎片颜色输出乘以 5 时,我的屏幕变成灰色。因此我认为问题是,纹理没有得到我的渲染器的输出。直接渲染到默认渲染器工作正常,所以我认为这是我的 fbo 的问题。
Renderer.h:
public ref class DefaultRenderer : RendererBase, IRenderer
{
public:
internal:
protected:
private:
EngineCore::Graphics::GraphicController* GraphicControl_;
Controllers::CameraControl^ CameraControl_;
Controllers::ColorPaletteControl^ ColorPaletteControl_;
Controllers::LightControl^ LightControl_;
unsigned int texture_;
unsigned int FBO_;
unsigned int RBO_;
unsigned int quadVAO_;
unsigned int quadVBO_;
array<float>^ quadVertices_;
EngineCore::Graphics::Shaders::ShaderProgram* screenShader_;
bool IsShadowsEnabled_ = false; // At the moment not used / not implemented
bool IsSkyBoxEnabled_ = true; // At the moment not used / not implemented
bool IsBloomEnabled_ = false; // At the moment not used / not implemented
bool IsToneMappingEnabled_ = false; // At the moment not used / not implemented
bool IsFxaaEnabled_ = false; // At the moment not used / not implemented
public:
DefaultRenderer() {};
~DefaultRenderer() {
this->!DefaultRenderer();
};
!DefaultRenderer() {};
internal:
protected:
private:
public:
/// <summary>
/// Enables Shadows
/// </summary>
virtual void EnableShadows();
/// <summary>
/// Disables Shadows
/// </summary>
virtual void DisableShadows();
/// <summary>
/// Enables Skybox
/// </summary>
virtual void EnableSkyBox();
/// <summary>
/// Disables Skyboy
/// </summary>
virtual void DisableSkyBox();
/// <summary>
/// Enables Bloom
/// </summary>
virtual void EnableBloom();
/// <summary>
/// Disables Bloom
/// </summary>
virtual void DisableBloom();
/// <summary>
/// Enables ToneMapping
/// </summary>
virtual void EnableToneMapping();
/// <summary>
/// Disables ToneMapping
/// </summary>
virtual void DisableToneMapping();
/// <summary>
/// Enables Fxaa
/// </summary>
virtual void EnableIsFxaa();
/// <summary>
/// Disables Fxaa
/// </summary>
virtual void DisableIsFxaa();
/// <summary>
/// This function enable the use of ColorPalette in the PBR-Rendering
/// and disables the use of Texturing for World-Elements.
/// World-Elements are the Voxels.
/// </summary>
virtual void EnableRenderingWithColorPalette();
/// <summary>
/// This function disable the use of ColorPalette in the PBR-Rendering
/// and enables the use of Texturing for World-Elements.
/// World-Elements are the Voxels.
/// </summary>
virtual void DisableRenderingWithColorPalette();
/// <summary>
/// Enables color palette transparency
/// </summary>
virtual void EnableColorTransparency();
/// <summary>
/// Disables color palette transparency
/// </summary>
virtual void DisableColorTransparency();
internal:
void Init(VoxelEngine::IEngine^ engine, EngineCore::Graphics::GraphicController* graphicControl, Controllers::CameraControl^ cameraControl, Controllers::ColorPaletteControl^ colorPalette, EngineCore::Input::InputSystem* input) override;
void Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime) override;
protected:
private:
/// <summary>
/// This function adds all of our shaders and create an Open GL shader
/// program from them.
/// </summary>
void AddShadersAndCreateGLProgram(VoxelEngine::IEngine^ engine);
/// <summary>
/// In this function all needed uniform buffers are created.
/// </summary>
void CreateUniformBuffers();
/// <summary>
/// In this function all needed voxel buffers are created.
/// </summary>
void CreateVoxelBuffers();
/// <summary>
/// In this function the uniform gets their values.
/// </summary>
void AddUniforms();
/// <summary>
/// In this function the buffers got rendered.
/// </summary>
void RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram);
/// <summary>
/// This function creates the framebuffer.
/// </summary>
void CreateFrameBuffer();
};
Renderer.cpp CreateFrameBuffer:
void DefaultRenderer::CreateFrameBuffer()
{
quadVertices_ = gcnew array<float>
{ // positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
float quadVertices[24];
for (size_t i = 0; i < 24; i++)
{
quadVertices[i] = quadVertices_[i];
}
// screen quad VAO
unsigned int quadVAO;
unsigned int quadVBO;
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
quadVAO_ = quadVAO;
quadVBO_ = quadVBO;
glBindVertexArray(quadVAO_);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO_);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
screenShader_ = &GraphicControl_->GetShaderProgram("framebuffer_screen_Program");
screenShader_->Use();
glUniform1i(screenShader_->GetUniform("screenTexture"), 0);
unsigned int framebuffer;
glGenFramebuffers(1,&framebuffer);
FBO_ = framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, FBO_);
// generate texture
unsigned int texColorBuffer;
glGenTextures(1, &texColorBuffer);
texture_ = texColorBuffer;
glBindTexture(GL_TEXTURE_2D, texture_);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1920, 1080, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// attach it to currently bound framebuffer object
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
RBO_ = rbo;
glBindRenderbuffer(GL_RENDERBUFFER, RBO_);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 1920, 1080);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, RBO_);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;
}
FBO_ = framebuffer;
texture_ = texColorBuffer;
RBO_ = rbo;
quadVBO_ = quadVBO;
quadVAO_ = quadVAO;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Renderer.cpp 渲染循环:
void DefaultRenderer::Render(std::vector<std::shared_ptr<EngineCore::Culling::Data::ChunkData>> chunksForRendering, frameTimeOffset offsetTime)
{
//bind to framebuffer and draw scene to color texture
glBindFramebuffer(GL_FRAMEBUFFER, FBO_ );
//clear framebuffer
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
auto tmp = GraphicControl_->GetVoxelBuffer("test");
tmp.ClearVoxelRenderList();
tmp.VoxelBufferData(chunksForRendering);
AddUniforms();
RenderVoxelBuffer(tmp, GraphicControl_->GetShaderProgram("testProgram"));
// bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//// clear all relevant buffers
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
GraphicControl_->GetShaderProgram("framebuffer_screen_Program").Use();
glBindVertexArray(quadVAO_);
glDisable(GL_DEPTH_TEST); // disable depth test
glBindTexture(GL_TEXTURE_2D, texture_); // use the color attachment texture as the texture of the quad plane
glDrawArrays(GL_TRIANGLES, 0, 6);
}
Renderer.cpp渲染体素缓冲区:
void DefaultRenderer::RenderVoxelBuffer(EngineCore::Graphics::Buffer::VoxelBuffer tmp, const EngineCore::Graphics::Shaders::ShaderProgram& shaderProgram)
{
shaderProgram.Use();
for (auto const& singleChunk : tmp.List_)
{
glBindVertexArray(singleChunk->Id);
glBindBuffer(GL_ARRAY_BUFFER, singleChunk->VoxelBuffer);
glBufferData(GL_ARRAY_BUFFER, singleChunk->VoxelCount * sizeof(EngineCore::Graphics::Data::VoxelData), singleChunk->List.data(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, sizeof(EngineCore::Graphics::Data::VoxelData), 0);
glUniform3f(shaderProgram.GetUniform("u_chunk_location"), (float)singleChunk->OffsetX, (float)singleChunk->OffsetY, (float)singleChunk->OffsetZ);
glDrawArrays(GL_POINTS, 0, singleChunk->VoxelCount);
}
glBindVertexArray(0);
}
framebuffer_screen.fs:
#version 450 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
vec3 col = texture(screenTexture, TexCoords).rgb;
FragColor = vec4(col, 1.0);
}
framebuffer_screen.vs:
#version 450 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}
我忘记在设置我的着色器属性之前激活我的着色器。现在一切正常