my project is at RocketArticle. When not using framebuffer, the scene will show as normal, but with framebuffer enabled, there will be only clear color in the bind framebuffer. Also, Renderdoc shows that, vertex output is fine, but fragment shader has no output. Below is render result
No Framebuffer Output
Render To Default Frame
RenderDoc Mesh View
And the main render loop is as follow:
Render Main Loop
#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <vector>
#include <iostream>
struct PerFrameConstants
{
glm::mat4 viewMatrix; // 64 bytes
glm::mat4 projectionMatrix; // 64 bytes
glm::vec4 camPos; // 16 bytes
};
struct PerBatchConstants
{
glm::mat4 modelMatrix; // 64 bytes
};
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
int main()
{
float orthoLeft = -10 * 1.7 * 0.5f;
float orthoRight = 10 * 1.7 * 0.5f;
float orthoBottom = -10 * 0.5f;
float orthoTop = 10 * 0.5f;
PerFrameConstants frame_data { glm::mat4(1.0f), glm::ortho(orthoLeft, orthoRight,orthoBottom, orthoTop, -1.0, 1.0), glm::vec4(0.0) };
PerBatchConstants batch_data { glm::mat4(1.0f) };
uint32_t shader_id = glCreateProgram();
AttachShader( shader_id, GL_VERTEX_SHADER, vert );
AttachShader( shader_id, GL_FRAGMENT_SHADER, frag );
glLinkProgram( shader_id );
CheckStatus( shader_id, false );
glUseProgram( shader_id );
struct Vertex
{
glm::vec4 mPosition;
glm::vec4 mColor;
glm::vec2 mTexCoord;
float index;
float tiling;
};
const std::vector< Vertex > vert =
{
{ glm::vec4( -0.5f, -0.5f, 0, 0), glm::vec4( 1.0f, 0.0f, 0.0f,1), glm::vec2(0, 0), 0, 1},
{ glm::vec4( 0.5f, -0.5f, 0, 0), glm::vec4( 0.0f, 1.0f, 0.0f,1), glm::vec2(0, 1), 0, 1},
{ glm::vec4( 0.0f, 0.5f, 0, 0), glm::vec4( 0.0f, 0.0f, 1.0f,1), glm::vec2(1, 0), 0, 1},
};
glBufferData( GL_ARRAY_BUFFER, sizeof( Vertex ) * verts.size(), verts.data(), GL_STATIC_DRAW );
GLuint vao = 0;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0 , 4, GL_FLOAT, GL_FALSE, sizeof( Vertex ), (GLvoid*)offsetof( Vertex, mPosition ) );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 1 , 4, GL_FLOAT, GL_FALSE, sizeof( Vertex ), (GLvoid*)offsetof( Vertex, mColor ) );
glEnableVertexAttribArray( 2 );
glVertexAttribPointer( 1 , 2, GL_FLOAT, GL_FALSE, sizeof( Vertex ), (GLvoid*)offsetof( Vertex, mTexCoord ) );
glEnableVertexAttribArray( 3 );
glVertexAttribPointer( 1 , 1, GL_FLOAT, GL_FALSE, sizeof( Vertex ), (GLvoid*)offsetof( Vertex, index ) );
glEnableVertexAttribArray( 4 );
glVertexAttribPointer( 1 , 1, GL_FLOAT, GL_FALSE, sizeof( Vertex ), (GLvoid*)offsetof( Vertex, tiling ) );
uint32_t texture_id;
uint32_t white_tex = 0xffffffff;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &white_tex);
glGenerateMipmap(GL_TEXTURE_2D);
uint32_t m_Framebuffer;
// Gen Frame Buffer
glGenFramebuffers(1, &m_Framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_Framebuffer);
// Bind Color
uint32_t m_ColorAttachments;
uint32_t m_ColorSpecifications[1];
glBindTexture(GL_TEXTURE_2D, m_ColorAttachments);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1280, 720, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ColorAttachments, 0);
glBindTexture(GL_TEXTURE_2D, 0);
m_ColorSpecifications[0] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, m_ColorSpecifications);
// Bind Depth Texture
glGenTextures(1, &m_DepthAttachment);
glBindTexture(GL_TEXTURE_2D, m_DepthAttachment);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1280, 720, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_DepthAttachment, 0);
glBindTexture(GL_TEXTURE_2D, 0);
ASSERT(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Framebuffer is incomplete!");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Generate UBO
uint32_t m_uboFrame, m_uboBatch;
auto BufferSize = sizeof(PerFrameConstants);
glGenBuffers(1, &m_RendererID);
glBindBuffer(GL_UNIFORM_BUFFER, m_uboFrame);
glBufferData(GL_UNIFORM_BUFFER, m_BufferSize, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
BufferSize = sizeof(PerBatchConstants);
glGenBuffers(1, &m_RendererID);
glBindBuffer(GL_UNIFORM_BUFFER, m_uboBatch);
glBufferData(GL_UNIFORM_BUFFER, m_BufferSize, NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
while(!glfwWindowShouldClose( window ) )
{
// Generate VAO, VBO, IBO for render
// Get Camera Matrix
// Set the color to clear the screen to.
glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
// Clear the screen and depth buffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set UBO view projection matrix data
glBindBuffer(GL_UNIFORM_BUFFER, m_uboFrame);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(PerFrameConstants), frame_data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
// Bind Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_Framebuffer);
glViewport(0, 0, 1280, 720);
// Set OpenGL State
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
// Set Blender Mode
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Set Cullface Mode
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Clear Framebuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind Shader
glUseProgram(shader_id);
// Bind UBO to shader
auto frame_block_index = glGetUniformBlockIndex(shader_id, "PerFrameConstants");
if (frame_block_index != GL_INVALID_INDEX)
{
int32_t blockSize;
glGetActiveUniformBlockiv(shader_id, frame_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
RK_GRAPHICS_ASSERT(blockSize >= sizeof(PerFrameConstants), "PerBatchConstants Size Error");
glUniformBlockBinding(shader_id, frame_block_index, 0);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_uboFrame);
}
frame_block_index = glGetUniformBlockIndex(shader_id, "PerBatchConstants");
if (frame_block_index != GL_INVALID_INDEX)
{
int32_t blockSize;
glGetActiveUniformBlockiv(shader_id, frame_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
RK_GRAPHICS_ASSERT(blockSize >= sizeof(PerBatchConstants), "PerBatchConstants Size Error");
glUniformBlockBinding(shader_id, frame_block_index, 1);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, m_uboBatch);
}
// Set Texture Ids
int32_t samplers[16];
for (uint32_t i = 0; i < 16; i++)
samplers[i] = i;
GLint location = GetLocation("u_Textures");
glUniform1iv(location, 16, samplers);
// Set Model Matrix
glBindBuffer(GL_UNIFORM_BUFFER, m_uboBatch);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(PerFrameConstants), batch_data);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
// Bind VAO
glBindVertexArray(vao);
// Bind Textures at different slot
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glDrawElements(GL_TRIANGLES, index_count, GL_STATIC_DRAW, nullptr);
// Unbind Framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glfwSwapBuffer();
}
}
Below is shader program used in render
shaders
vertex shader
#version 410
layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec4 a_Color;
layout(location = 2) in vec2 a_TexCoord;
layout(location = 3) in float a_TexIndex;
layout(location = 4) in float a_TilingFactor;
layout(std140) uniform PerFrameConstants
{
mat4 viewMatrix; // 64 bytes
mat4 projectionMatrix; // 64 bytes
vec4 camPos; // 16 bytes
ivec4 numLights; // 16 bytes
} PerFrame; // total 160 bytes
layout(std140) uniform PerBatchConstants
{
mat4 modelMatrix;
} PerBatch;
out vec4 v_Color;
out vec2 v_TexCoord;
out float v_TexIndex;
out float v_TilingFactor;
void main()
{
v_Color = a_Color;
v_TexCoord = a_TexCoord;
v_TexIndex = a_TexIndex;
v_TilingFactor = a_TilingFactor;
gl_Position = PerFrame.projectionMatrix * PerFrame.viewMatrix * PerBatch.modelMatrix * vec4(a_Position.xyz, 1.0f);
}
fragment shader
#version 410
layout(location = 0) out vec4 color;
uniform sampler2D u_Textures[16];
layout(location = 0) in vec4 v_Color;
layout(location = 1) in vec2 v_TexCoord;
layout(location = 2) in float v_TexIndex;
layout(location = 3) in float v_TilingFactor;
void main()
{
vec4 texColor = v_Color;
switch(int(v_TexIndex))
{
case 0: texColor *= texture(u_Textures[ 0], v_TexCoord * v_TilingFactor); break;
case 1: texColor *= texture(u_Textures[ 1], v_TexCoord * v_TilingFactor); break;
}
color = texColor;
}
User contributions licensed under CC BY-SA 3.0