/* * Copyright (C) 2021 Christopher J. Howard * * This file is part of Antkeeper source code. * * Antkeeper source code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper source code. If not, see . */ #include "gl/rasterizer.hpp" #include "gl/framebuffer.hpp" #include "gl/shader-program.hpp" #include "gl/vertex-array.hpp" #include namespace gl { static constexpr GLenum drawing_mode_lut[] = { GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_LINE_STRIP_ADJACENCY, GL_LINES_ADJACENCY, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_TRIANGLE_STRIP_ADJACENCY, GL_TRIANGLES_ADJACENCY }; static constexpr GLenum element_array_type_lut[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT }; rasterizer::rasterizer(): bound_vao(nullptr), bound_shader_program(nullptr) { // Determine dimensions of default framebuffer GLint scissor_box[4] = {0, 0, 0, 0}; glGetIntegerv(GL_SCISSOR_BOX, scissor_box); // Setup default framebuffer default_framebuffer = new framebuffer(); default_framebuffer->gl_framebuffer_id = 0; default_framebuffer->dimensions = {scissor_box[2], scissor_box[3]}; // Bind default framebuffer bound_framebuffer = default_framebuffer; } rasterizer::~rasterizer() { delete default_framebuffer; } void rasterizer::context_resized(int width, int height) { default_framebuffer->dimensions = {width, height}; } void rasterizer::use_framebuffer(const gl::framebuffer& framebuffer) { if (bound_framebuffer != &framebuffer) { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.gl_framebuffer_id); bound_framebuffer = &framebuffer; } } void rasterizer::set_clear_color(float r, float g, float b, float a) { glClearColor(r, g, b, a); } void rasterizer::set_clear_depth(float depth) { glClearDepth(depth); } void rasterizer::set_clear_stencil(int s) { glClearStencil(s); } void rasterizer::clear_framebuffer(bool color, bool depth, bool stencil) { GLbitfield mask = 0; if (color) mask |= GL_COLOR_BUFFER_BIT; if (depth) mask |= GL_DEPTH_BUFFER_BIT; if (stencil) mask |= GL_STENCIL_BUFFER_BIT; glClear(mask); } void rasterizer::set_viewport(int x, int y, int width, int height) { glViewport(x, y, static_cast(width), static_cast(height)); } void rasterizer::use_program(const shader_program& program) { if (bound_shader_program != &program) { glUseProgram(program.gl_program_id); bound_shader_program = &program; } } void rasterizer::draw_arrays(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count) { GLenum gl_mode = drawing_mode_lut[static_cast(mode)]; if (bound_vao != &vao) { glBindVertexArray(vao.gl_array_id); bound_vao = &vao; } glDrawArrays(gl_mode, static_cast(offset), static_cast(count)); } void rasterizer::draw_arrays_instanced(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count, std::size_t instance_count) { GLenum gl_mode = drawing_mode_lut[static_cast(mode)]; if (bound_vao != &vao) { glBindVertexArray(vao.gl_array_id); bound_vao = &vao; } glDrawArraysInstanced(gl_mode, static_cast(offset), static_cast(count), static_cast(instance_count)); } void rasterizer::draw_elements(const vertex_array& vao, drawing_mode mode, std::size_t offset, std::size_t count, element_array_type type) { GLenum gl_mode = drawing_mode_lut[static_cast(mode)]; GLenum gl_type = element_array_type_lut[static_cast(type)]; if (bound_vao != &vao) { glBindVertexArray(vao.gl_array_id); bound_vao = &vao; } glDrawElements(gl_mode, static_cast(count), gl_type, (const GLvoid*)offset); } } // namespace gl