Implement Multi-Sample Anti Aliasing (MSAA)

This commit is contained in:
Abdelrahman Said 2024-12-30 21:00:10 +00:00
parent e9a9b8a2cf
commit 71f6d03635

View File

@ -50,8 +50,13 @@
#define WIREFRAME 0 #define WIREFRAME 0
#define NORMALS 0 #define NORMALS 0
#define MSAA 1
#define POINT_LIGHTS 1 #define POINT_LIGHTS 1
#if MSAA
#define MSAA_SAMPLE_COUNT 4
#endif
enum exit_codes : int { enum exit_codes : int {
EXIT_CODE_SUCCESS, EXIT_CODE_SUCCESS,
EXIT_CODE_SDL_INIT_FAILED, EXIT_CODE_SDL_INIT_FAILED,
@ -149,9 +154,15 @@ struct FrameBuffer {
GLuint fbo; GLuint fbo;
GLuint color; GLuint color;
GLuint depth_stencil; GLuint depth_stencil;
GLuint width;
GLuint height;
}; };
FrameBuffer create_frame_buffer(unsigned int width, unsigned int height); FrameBuffer create_normal_frame_buffer(unsigned int width, unsigned int height);
#if MSAA
FrameBuffer create_multisample_frame_buffer(unsigned int width, unsigned int height);
void blit_multisample_frame_buffer(const FrameBuffer &multisample_buffer, const FrameBuffer &normal_buffer);
#endif
void delete_frame_buffer(FrameBuffer &buffer); void delete_frame_buffer(FrameBuffer &buffer);
GLuint load_cubemap(std::vector<std::string> textures); GLuint load_cubemap(std::vector<std::string> textures);
@ -166,6 +177,11 @@ int main() {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#if MSAA
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, MSAA_SAMPLE_COUNT);
#endif
SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
if (!window) { if (!window) {
@ -181,12 +197,21 @@ int main() {
return EXIT_CODE_GLAD_LOADER_FAILED; return EXIT_CODE_GLAD_LOADER_FAILED;
} }
#if MSAA
glEnable(GL_MULTISAMPLE);
#endif
SDL_SetRelativeMouseMode(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE);
SDL_WarpMouseInWindow(window, WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT); SDL_WarpMouseInWindow(window, WINDOW_HALF_WIDTH, WINDOW_HALF_HEIGHT);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
FrameBuffer offscreen_buffer = create_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT); #if MSAA
FrameBuffer multisample_buffer = create_multisample_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
FrameBuffer offscreen_buffer = create_normal_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
#else
FrameBuffer offscreen_buffer = create_normal_frame_buffer(WINDOW_WIDTH, WINDOW_HEIGHT);
#endif
std::vector<Vertex> vertices = { std::vector<Vertex> vertices = {
// positions // normals // texture coords // positions // normals // texture coords
@ -497,7 +522,11 @@ int main() {
// Recreate offscreen frame buffer // Recreate offscreen frame buffer
delete_frame_buffer(offscreen_buffer); delete_frame_buffer(offscreen_buffer);
offscreen_buffer = create_frame_buffer(w, h); offscreen_buffer = create_normal_frame_buffer(w, h);
#if MSAA
delete_frame_buffer(multisample_buffer);
multisample_buffer = create_multisample_frame_buffer(w, h);
#endif
} }
break; break;
} }
@ -523,7 +552,11 @@ int main() {
skybox_shader.set_mat4("sb_view", glm::mat4(glm::mat3(view))); skybox_shader.set_mat4("sb_view", glm::mat4(glm::mat3(view)));
// Main render pass // Main render pass
#if MSAA
glBindFramebuffer(GL_FRAMEBUFFER, multisample_buffer.fbo);
#else
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo); glBindFramebuffer(GL_FRAMEBUFFER, offscreen_buffer.fbo);
#endif
glClearColor(0.04f, 0.08f, 0.08f, 1.0f); glClearColor(0.04f, 0.08f, 0.08f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@ -578,6 +611,10 @@ int main() {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif #endif
#if MSAA
blit_multisample_frame_buffer(multisample_buffer, offscreen_buffer);
#endif
// Post processing pass // Post processing pass
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -959,7 +996,7 @@ std::vector<Texture2D> Model::load_material_textures(aiMaterial *material, aiTex
return textures; return textures;
} }
FrameBuffer create_frame_buffer(unsigned int width, unsigned int height) { FrameBuffer create_normal_frame_buffer(unsigned int width, unsigned int height) {
FrameBuffer buffer = {}; FrameBuffer buffer = {};
glGenFramebuffers(1, &buffer.fbo); glGenFramebuffers(1, &buffer.fbo);
@ -990,9 +1027,61 @@ FrameBuffer create_frame_buffer(unsigned int width, unsigned int height) {
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
buffer.width = width;
buffer.height = height;
return buffer; return buffer;
} }
#if MSAA
FrameBuffer create_multisample_frame_buffer(unsigned int width, unsigned int height) {
FrameBuffer buffer = {};
glGenFramebuffers(1, &buffer.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, buffer.fbo);
// Create color texture
glGenTextures(1, &buffer.color);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, buffer.color);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, MSAA_SAMPLE_COUNT, GL_RGB, width, height, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, buffer.color, 0);
// Create depth and stencil buffers
glGenRenderbuffers(1, &buffer.depth_stencil);
glBindRenderbuffer(GL_RENDERBUFFER, buffer.depth_stencil);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_SAMPLE_COUNT, GL_DEPTH24_STENCIL8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer.depth_stencil);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
printf("Incomplete frame buffer\n");
exit(EXIT_CODE_INCOMPLETE_FRAME_BUFFER);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
buffer.width = width;
buffer.height = height;
return buffer;
}
void blit_multisample_frame_buffer(const FrameBuffer &multisample_buffer, const FrameBuffer &normal_buffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, multisample_buffer.fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, normal_buffer.fbo);
glBlitFramebuffer(
0, 0, multisample_buffer.width, multisample_buffer.height,
0, 0, normal_buffer.width, normal_buffer.height,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
}
#endif
void delete_frame_buffer(FrameBuffer &buffer) { void delete_frame_buffer(FrameBuffer &buffer) {
glDeleteFramebuffers(1, &buffer.fbo); glDeleteFramebuffers(1, &buffer.fbo);
glDeleteTextures(1, &buffer.color); glDeleteTextures(1, &buffer.color);