Add subimage to texture
This commit is contained in:
parent
913285e57a
commit
1c4d5cd304
@ -23,13 +23,18 @@
|
||||
|
||||
namespace egn{
|
||||
|
||||
//Represent a 3D point
|
||||
using point = math::vec3<float>;
|
||||
|
||||
//Represent a line segment in 3D space given the end points
|
||||
class line_segment
|
||||
{
|
||||
public:
|
||||
point point1;
|
||||
point point2;
|
||||
};
|
||||
|
||||
//Represent a 2D rectangle in 3D space given the four corners
|
||||
class rectangle
|
||||
{
|
||||
public:
|
||||
@ -38,6 +43,8 @@ namespace egn{
|
||||
point point3;
|
||||
point point4;
|
||||
};
|
||||
|
||||
//Axis aligned bounding box. Given the 2 opposite corners.
|
||||
class aabb
|
||||
{
|
||||
public:
|
||||
@ -52,6 +59,8 @@ namespace egn{
|
||||
aabb& operator=(const aabb&) = default;
|
||||
aabb& operator=(aabb&&) = default;
|
||||
};
|
||||
|
||||
//3D sphere represented using a point and radius
|
||||
class sphere
|
||||
{
|
||||
public:
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
namespace egn{
|
||||
|
||||
//Virtual base for camera types
|
||||
//Provides general object functionality as well as projection and view matrices.
|
||||
//Derived classes must provide method of recalculating the projection matrix.
|
||||
class camera_iface : public object_base
|
||||
{
|
||||
protected:
|
||||
@ -41,16 +44,19 @@ namespace egn{
|
||||
GLfloat m_far = 100; //far clipping plane in camera space
|
||||
|
||||
public:
|
||||
camera_iface() = default;
|
||||
camera_iface(void) = default;
|
||||
//Initialize with given projection matrix and clipping planes
|
||||
camera_iface(const math::mat4<GLfloat>& proj, GLfloat n, GLfloat f);
|
||||
camera_iface(const camera_iface&) = default;
|
||||
camera_iface(camera_iface&&) = default;
|
||||
virtual ~camera_iface() = default;
|
||||
virtual ~camera_iface(void) = default;
|
||||
|
||||
camera_iface& operator=(const camera_iface&) = default;
|
||||
camera_iface& operator=(camera_iface&&) = default;
|
||||
|
||||
//Set the camera's location and update relevant data structures
|
||||
void set_position(const math::vec3<GLfloat>& pos)override;
|
||||
//Set the camera's facing angle and update relevant data structures
|
||||
void set_orientation(const math::quaternion<GLfloat>& distance)override;
|
||||
|
||||
//getters
|
||||
@ -62,18 +68,21 @@ namespace egn{
|
||||
//setters
|
||||
void set_near_plane(GLfloat n);
|
||||
void set_far_plane(GLfloat f);
|
||||
//No control over matrices directly is done purposefully
|
||||
|
||||
protected:
|
||||
void recalc_view_matrix()const;
|
||||
virtual void recalc_projection_matrix()const = 0;
|
||||
};
|
||||
|
||||
//Camera which performs an orthographic projection. Essentially camera will have no depth perspective
|
||||
class ortho_camera : public camera_iface
|
||||
{
|
||||
protected:
|
||||
GLfloat m_width, m_height; //width and height of the camera space box
|
||||
|
||||
public:
|
||||
//Build camera with width, height, near, and far planes
|
||||
ortho_camera(GLfloat w, GLfloat h, GLfloat n, GLfloat f);
|
||||
ortho_camera(const ortho_camera&) = default;
|
||||
ortho_camera(ortho_camera&&) = default;
|
||||
@ -82,9 +91,11 @@ namespace egn{
|
||||
ortho_camera& operator=(const ortho_camera&) = default;
|
||||
ortho_camera& operator=(ortho_camera&&) = default;
|
||||
|
||||
//Getters
|
||||
GLfloat get_projection_width()const;
|
||||
GLfloat get_projection_height()const;
|
||||
|
||||
//Setters
|
||||
void set_projection_width(GLfloat w);
|
||||
void set_projection_height(GLfloat h);
|
||||
void set_projection_box(GLfloat w, GLfloat h);
|
||||
|
||||
@ -23,17 +23,21 @@
|
||||
|
||||
namespace egn{
|
||||
|
||||
//How far away before a collision is considered to have occurred
|
||||
static constexpr float default_collision_epsilon = 1.0e-10f;
|
||||
|
||||
class collidable_visitor;
|
||||
|
||||
//Anything which derives from this is considered collidable and must be comparible to any other collidable
|
||||
class collidable_iface
|
||||
{
|
||||
public:
|
||||
//Check if this and the other collidable have collided
|
||||
virtual bool check_collision(const collidable_iface& c, float epsilon)const = 0;
|
||||
virtual void accept_visitor(collidable_visitor& v)const = 0;
|
||||
};
|
||||
|
||||
//CRTP collidable to allow the collision checks to determine the concrete type of the collidable
|
||||
template<typename Derived>
|
||||
class collidable : public collidable_iface
|
||||
{
|
||||
@ -46,14 +50,23 @@ namespace egn{
|
||||
|
||||
namespace collision{
|
||||
|
||||
//Basic collidable objects
|
||||
|
||||
//A 1D point
|
||||
class point : public egn::point, public collidable<point>
|
||||
{
|
||||
public:
|
||||
using egn::point::point;
|
||||
using egn::point::operator=;
|
||||
};
|
||||
|
||||
//A 2D line
|
||||
class line_segment : public egn::line_segment, public collidable<line_segment>{};
|
||||
|
||||
//A 2D rectangle
|
||||
class rectangle : public egn::rectangle, public collidable<rectangle>{};
|
||||
|
||||
//A 3D bounding box
|
||||
class aabb : public egn::aabb, public collidable<aabb>
|
||||
{
|
||||
public:
|
||||
@ -62,6 +75,8 @@ namespace egn{
|
||||
aabb(const egn::aabb& b);
|
||||
aabb& operator=(const egn::aabb& b);
|
||||
};
|
||||
|
||||
//A 3D sphere
|
||||
class sphere : public egn::sphere, public collidable<sphere>
|
||||
{
|
||||
public:
|
||||
@ -73,6 +88,7 @@ namespace egn{
|
||||
|
||||
}
|
||||
|
||||
//base class for collision visitor to provide polymorphic access to visitation functions
|
||||
class collidable_visitor
|
||||
{
|
||||
public:
|
||||
@ -83,6 +99,7 @@ namespace egn{
|
||||
virtual void visit(const collision::point& p) = 0;
|
||||
};
|
||||
|
||||
//Templated visitor to allow checking collision from polymorphic types
|
||||
template<typename T>
|
||||
class collision_visitor : public collidable_visitor
|
||||
{
|
||||
@ -100,6 +117,7 @@ namespace egn{
|
||||
constexpr bool result()const;
|
||||
};
|
||||
|
||||
//Concrete collision detection that is eventually called
|
||||
//bool check_collision(const collidable_iface& l, const collidable_iface& r, float epsilon = default_collision_epsilon);
|
||||
bool check_collision(const aabb& l, const aabb& r, float epsilon = default_collision_epsilon);
|
||||
bool check_collision(const aabb& l, const sphere& r, float epsilon = default_collision_epsilon);
|
||||
@ -128,21 +146,23 @@ namespace egn{
|
||||
bool check_collision(const point& l, const rectangle& r, float epsilon = default_collision_epsilon);
|
||||
|
||||
|
||||
//Check collision between this and c via a visitor
|
||||
template<typename Derived>
|
||||
bool collidable<Derived>::check_collision(const collidable_iface& c, float epsilon)const{
|
||||
collision_visitor<Derived> vis(static_cast<const Derived&>(*this), epsilon);
|
||||
c.accept_visitor(vis);
|
||||
collision_visitor<Derived> vis(static_cast<const Derived&>(*this), epsilon); //Determine our true type for visitor
|
||||
c.accept_visitor(vis); //have c give its true type to our visitor and check for collision
|
||||
return vis.result();
|
||||
}
|
||||
template<typename Derived>
|
||||
void collidable<Derived>::accept_visitor(collidable_visitor& v)const{
|
||||
v.visit(static_cast<const Derived&>(*this));
|
||||
v.visit(static_cast<const Derived&>(*this)); //Give the visitor our true type to allow calling correct collision check function
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr collision_visitor<T>::collision_visitor(const T& l, float epsilon):
|
||||
m_l(l),
|
||||
m_epsilon(epsilon){}
|
||||
//Call correct concrete function for given collision
|
||||
template<typename T>
|
||||
void collision_visitor<T>::visit(const collision::aabb& a){
|
||||
m_result = check_collision(m_l, a, m_epsilon);
|
||||
|
||||
77
include/engine/font.hpp
Normal file
77
include/engine/font.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2022 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OUR_DICK_ENGINE_FONT_HPP
|
||||
#define OUR_DICK_ENGINE_FONT_HPP
|
||||
|
||||
#include <freetype2/ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <map>
|
||||
#include <optional>
|
||||
|
||||
#include "graphics/texture.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
namespace egn{
|
||||
|
||||
class font
|
||||
{
|
||||
private:
|
||||
//ascii texture atlas
|
||||
const char* m_bitmap_handle;
|
||||
//When rendering unicode, load up new textures per code page to create many atlases
|
||||
std::map<int, const char*> m_extra_codepages;
|
||||
//stb or freetype font handle
|
||||
|
||||
public:
|
||||
//load the font file and process it with stb/freetype lib
|
||||
//render out basic ascii characters to bitmap texture atlas
|
||||
//maybe do signed distance fonts? example: https://github.com/ShoYamanishi/SDFont
|
||||
//dynamically add new codepage textures for rendering non-ascii
|
||||
};
|
||||
|
||||
class font_generator
|
||||
{
|
||||
private:
|
||||
static inline bool s_initialized = false;
|
||||
static inline FT_Library s_ft;
|
||||
|
||||
private:
|
||||
FT_Face m_face = nullptr;
|
||||
|
||||
public:
|
||||
font_generator(const char* file);
|
||||
~font_generator(void);
|
||||
|
||||
//params:
|
||||
// start_codepoint: unicode character at which the atlas starts
|
||||
// count: number of characters to make in the atlas
|
||||
// glyph_width: requested pixel width of glyph
|
||||
// glyph_height: requested pixel height of glyph
|
||||
// atlas_width: requested pixel width of atlas
|
||||
// atlas_height: requested pixel height of atlas
|
||||
std::optional<gfx::texture> generate_atlas(int start_codepoint, int count, int glyph_width, int glyph_height, int atlas_width, int atlas_height);
|
||||
std::optional<gfx::texture> generate_glyph(char character, int width, int height);
|
||||
|
||||
private:
|
||||
static bool initialize_freetype_(void);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2020 rexy712
|
||||
Copyright (C) 2020-2022 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -29,6 +29,9 @@ namespace gfx{
|
||||
public:
|
||||
using texture::texture;
|
||||
using texture::operator=;
|
||||
|
||||
//tmp
|
||||
material(texture&&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -36,16 +36,16 @@ namespace gfx{
|
||||
weak_texture_handle(const texture& tex);
|
||||
weak_texture_handle(const weak_texture_handle&) = default;
|
||||
weak_texture_handle(weak_texture_handle&&) = default;
|
||||
~weak_texture_handle() = default;
|
||||
~weak_texture_handle(void) = default;
|
||||
|
||||
weak_texture_handle& operator=(const weak_texture_handle&) = default;
|
||||
weak_texture_handle& operator=(weak_texture_handle&&) = default;
|
||||
|
||||
GLuint raw()const;
|
||||
GLsizei get_width()const;
|
||||
GLsizei get_height()const;
|
||||
GLuint raw(void)const;
|
||||
GLsizei get_width(void)const;
|
||||
GLsizei get_height(void)const;
|
||||
|
||||
void bind()const;
|
||||
void bind(void)const;
|
||||
void bind_unit(GLuint tunit)const;
|
||||
};
|
||||
|
||||
@ -81,29 +81,35 @@ namespace gfx{
|
||||
GLsizei m_height = 0;
|
||||
GLenum m_format = 0;
|
||||
GLenum m_type = GL_UNSIGNED_BYTE;
|
||||
bool m_mipmapped = true;
|
||||
|
||||
public:
|
||||
//create the texture with no image data
|
||||
texture();
|
||||
texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
texture(GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
texture(void);
|
||||
texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap = true);
|
||||
texture(GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap = true);
|
||||
//create the texture with image data from 'i'
|
||||
texture(const egn::image& i);
|
||||
texture(const egn::deferred_image& i);
|
||||
texture(const texture&) = delete;
|
||||
texture(const egn::image& i, bool mipmap = true);
|
||||
texture(const egn::deferred_image& i, bool mipmap = true);
|
||||
texture(const texture&);
|
||||
texture(texture&&);
|
||||
~texture();
|
||||
~texture(void);
|
||||
|
||||
texture& operator=(const texture&) = delete;
|
||||
texture& operator=(const texture&);
|
||||
texture& operator=(texture&&);
|
||||
|
||||
GLuint raw()const;
|
||||
GLuint raw(void)const;
|
||||
|
||||
//overwrite the current image data with 'i'
|
||||
bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type);
|
||||
bool set_image(const egn::image& i);
|
||||
bool set_image(const egn::deferred_image& i);
|
||||
|
||||
bool set_subimage(const unsigned char* data, GLenum format, GLenum type,
|
||||
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h);
|
||||
bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset);
|
||||
bool set_subimage(const egn::deferred_image& i, GLsizei xoffset, GLsizei yoffset);
|
||||
|
||||
//change wrap mode for both x and y
|
||||
void set_wrap_mode(wrap w);
|
||||
void set_wrap_mode(wrap w, wrap h);
|
||||
@ -116,25 +122,31 @@ namespace gfx{
|
||||
void set_mag_filter(magfilter m);
|
||||
void set_min_filter(minfilter m);
|
||||
|
||||
magfilter get_mag_filter()const;
|
||||
minfilter get_min_filter()const;
|
||||
math::vec4<GLfloat> get_border_color()const;
|
||||
magfilter get_mag_filter(void)const;
|
||||
minfilter get_min_filter(void)const;
|
||||
math::vec4<GLfloat> get_border_color(void)const;
|
||||
|
||||
wrap get_wrap_x()const;
|
||||
wrap get_wrap_y()const;
|
||||
wrap get_wrap_x(void)const;
|
||||
wrap get_wrap_y(void)const;
|
||||
|
||||
GLsizei get_width()const;
|
||||
GLsizei get_height()const;
|
||||
GLsizei get_width(void)const;
|
||||
GLsizei get_height(void)const;
|
||||
|
||||
void enable_auto_mipmap(bool enable);
|
||||
void generate_mipmap(void);
|
||||
|
||||
//release ownership of this texture object
|
||||
GLuint release();
|
||||
GLuint release(void);
|
||||
|
||||
//bind to GL_TEXTURE_2D
|
||||
void bind()const;
|
||||
void bind(void)const;
|
||||
//bind to given texture unit and load into given program uniform location
|
||||
void bind_unit(GLuint tunit)const;
|
||||
|
||||
weak_texture_handle create_handle()const;
|
||||
weak_texture_handle create_handle(void)const;
|
||||
|
||||
private:
|
||||
bool create_texture_storage_(void);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ private:
|
||||
};
|
||||
private:
|
||||
basic_framebuffer m_fb;
|
||||
gfx::fbo m_primary_fb;
|
||||
gfx::shader_program* m_sprite_shader;
|
||||
gfx::shader_program* m_screen_shader;
|
||||
gfx::vbo m_vbo;
|
||||
|
||||
4
makefile
4
makefile
@ -26,7 +26,7 @@ DEPDIR::=$(OBJDIR)/dep
|
||||
LIBDIRS::=lib
|
||||
INCLUDE_DIRS::=include
|
||||
CFLAGS::=-std=c18 -Wall -pedantic -Wextra
|
||||
CXXFLAGS::=-std=c++20 -Wall -pedantic -Wextra -fno-rtti -fno-exceptions
|
||||
CXXFLAGS::=-std=c++20 -Wall -pedantic -Wextra -fno-rtti -fno-exceptions $(shell pkg-config --cflags freetype2)
|
||||
DEBUG_CFLAGS::=
|
||||
DEBUG_CXXFLAGS::=-DOUR_DICK_DEBUG=2
|
||||
EXT::=cpp
|
||||
@ -41,7 +41,7 @@ ifneq ($(WINDOWS),1)
|
||||
#*nix settings
|
||||
CC::=gcc
|
||||
CXX::=g++
|
||||
LDLIBS::=-lglfw -lglad -ldl -lm -lportaudio -lsndfile -lpthread -lrexy
|
||||
LDLIBS::=-lglfw -lglad -ldl -lm -lportaudio -lsndfile -lpthread -lrexy $(shell pkg-config --libs freetype2)
|
||||
ifeq ($(shell uname -s),Linux)
|
||||
LDLIBS+=-lasound
|
||||
endif
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
#include "math/mat.hpp"
|
||||
|
||||
#include "graphics/gl_include.hpp" //GLfloat
|
||||
|
||||
#include "engine/font.hpp"
|
||||
|
||||
gfx::unified_mesh square_mesh(const gfx::material& blank, const gfx::material& o, const gfx::material& x){
|
||||
static constexpr gfx::vertex s_vertices[] = {
|
||||
@ -64,7 +64,6 @@ board::board(egn::resource_manager& resman):
|
||||
blank = resman.emplace_material("assets/images/blank.jpg", egn::deferred_image("assets/images/blank.jpg", true)).first;
|
||||
o = resman.emplace_material("assets/images/o.jpg", egn::deferred_image("assets/images/o.jpg", true)).first;
|
||||
x = resman.emplace_material("assets/images/x.jpg", egn::deferred_image("assets/images/x.jpg", true)).first;
|
||||
x = resman.emplace_material("assets/images/x.jpg", egn::deferred_image("assets/images/x.jpg", true)).first;
|
||||
|
||||
if(!resman.has_model("square")){
|
||||
sq = resman.emplace_model("square", square_mesh(*blank, *o, *x)).first;
|
||||
|
||||
55
src/engine/font.cpp
Normal file
55
src/engine/font.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2022 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "engine/font.hpp"
|
||||
|
||||
namespace egn{
|
||||
|
||||
font_generator::font_generator(const char* file){
|
||||
initialize_freetype_();
|
||||
if(FT_New_Face(s_ft, file, 0, &m_face)){
|
||||
debug_print_error("Failed to initialize font '%s'\n", file);
|
||||
}
|
||||
}
|
||||
font_generator::~font_generator(void){
|
||||
FT_Done_Face(m_face);
|
||||
}
|
||||
|
||||
std::optional<gfx::texture> font_generator::generate_glyph(char character, int width, int height){
|
||||
FT_Set_Pixel_Sizes(m_face, width, height);
|
||||
if(FT_Load_Char(m_face, character, FT_LOAD_RENDER)){
|
||||
debug_print_error("Failed to load character '%c', from font '%s'\n", character, m_face->family_name);
|
||||
return {};
|
||||
}
|
||||
auto& bitmap = m_face->glyph->bitmap;
|
||||
return {gfx::texture(bitmap.buffer, GL_RED, bitmap.width, bitmap.rows, GL_UNSIGNED_BYTE)};
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool font_generator::initialize_freetype_(void){
|
||||
if(!s_initialized){
|
||||
if(FT_Init_FreeType(&s_ft)){
|
||||
return false;
|
||||
}
|
||||
return (s_initialized = true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
28
src/graphics/material.cpp
Normal file
28
src/graphics/material.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
This file is a part of our_dick
|
||||
Copyright (C) 2022 rexy712
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "graphics/material.hpp"
|
||||
|
||||
#include <utility> //move
|
||||
|
||||
namespace gfx{
|
||||
|
||||
material::material(texture&& t):
|
||||
texture(std::move(t)){}
|
||||
|
||||
}
|
||||
@ -20,6 +20,7 @@
|
||||
#include "config.hpp"
|
||||
|
||||
#include <utility> //exchange, swap
|
||||
#include <rexy/utility.hpp>
|
||||
|
||||
namespace gfx{
|
||||
|
||||
@ -65,62 +66,88 @@ namespace gfx{
|
||||
};
|
||||
return 1;
|
||||
}
|
||||
[[maybe_unused]]
|
||||
static GLint save_unpack_alignment_(void){
|
||||
int old_alignment;
|
||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &old_alignment);
|
||||
return old_alignment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
texture::texture(){
|
||||
texture::texture(void){
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_tex_id);
|
||||
}
|
||||
texture::texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type):
|
||||
texture::texture(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap):
|
||||
m_width(w), m_height(h),
|
||||
m_format(format), m_type(type)
|
||||
m_format(format), m_type(type),
|
||||
m_mipmapped(mipmap)
|
||||
{
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_tex_id);
|
||||
switch(m_format){
|
||||
case GL_RED:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_R8, m_width, m_height);
|
||||
break;
|
||||
case GL_RG:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RG8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGB:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGB8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGBA:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGBA8, m_width, m_height);
|
||||
break;
|
||||
default:
|
||||
debug_print_error("Unsupported format passed to texture constructor\n");
|
||||
glDeleteTextures(1, &m_tex_id);
|
||||
m_tex_id = 0;
|
||||
return;
|
||||
};
|
||||
GLint old_alignment = save_unpack_alignment_();
|
||||
|
||||
if(!create_texture_storage_()){
|
||||
debug_print_error("Failed to create texture storage\n");
|
||||
return;
|
||||
}
|
||||
glTextureSubImage2D(m_tex_id, 0, 0, 0, m_width, m_height, m_format, m_type, data);
|
||||
glGenerateTextureMipmap(m_tex_id);
|
||||
if(m_mipmapped)
|
||||
generate_mipmap();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
|
||||
}
|
||||
texture::texture(GLenum format, GLsizei w, GLsizei h, GLenum type):
|
||||
texture(nullptr, format, w, h, type){}
|
||||
texture::texture(const egn::image& i):
|
||||
texture::texture(GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap):
|
||||
texture(nullptr, format, w, h, type, mipmap){}
|
||||
texture::texture(const egn::image& i, bool mipmap):
|
||||
texture()
|
||||
{
|
||||
m_mipmapped = mipmap;
|
||||
set_image(i);
|
||||
}
|
||||
texture::texture(const egn::deferred_image& i):
|
||||
texture::texture(const egn::deferred_image& i, bool mipmap):
|
||||
texture()
|
||||
{
|
||||
m_mipmapped = mipmap;
|
||||
set_image(i);
|
||||
}
|
||||
texture::texture(const texture& t):
|
||||
m_width(t.m_width), m_height(t.m_height),
|
||||
m_format(t.m_format), m_type(t.m_type),
|
||||
m_mipmapped(t.m_mipmapped)
|
||||
{
|
||||
//Copying textures is not preferable so generate a debug warning
|
||||
debug_print_warn("Copy constructing texture!\n");
|
||||
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &m_tex_id);
|
||||
GLint old_alignment = save_unpack_alignment_();
|
||||
|
||||
if(!create_texture_storage_()){
|
||||
debug_print_error("Failed to create texture storage\n");
|
||||
return;
|
||||
}
|
||||
glCopyImageSubData(t.m_tex_id, GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||
m_tex_id, GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||
m_width, m_height, 1);
|
||||
if(m_mipmapped)
|
||||
generate_mipmap();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
|
||||
}
|
||||
texture::texture(texture&& t):
|
||||
m_tex_id(std::exchange(t.m_tex_id, 0)){}
|
||||
texture::~texture(){
|
||||
m_tex_id(std::exchange(t.m_tex_id, 0)),
|
||||
m_width(t.m_width), m_height(t.m_height),
|
||||
m_format(t.m_format), m_type(t.m_type){}
|
||||
texture::~texture(void){
|
||||
glDeleteTextures(1, &m_tex_id);
|
||||
}
|
||||
|
||||
texture& texture::operator=(const texture& t){
|
||||
debug_print_warn("Copy assigning texture!\n");
|
||||
return (*this = texture(t));
|
||||
}
|
||||
texture& texture::operator=(texture&& t){
|
||||
std::swap(m_tex_id, t.m_tex_id);
|
||||
return *this;
|
||||
}
|
||||
GLuint texture::raw()const{
|
||||
GLuint texture::raw(void)const{
|
||||
return m_tex_id;
|
||||
}
|
||||
|
||||
@ -129,6 +156,8 @@ namespace gfx{
|
||||
debug_print_error("Image is invalid\n");
|
||||
return false;
|
||||
}
|
||||
GLint old_alignment = save_unpack_alignment_();
|
||||
|
||||
if(m_width != w || m_height != h || m_format != format){
|
||||
if(m_format != 0){
|
||||
debug_print_warn("Regenerating texture\n");
|
||||
@ -137,27 +166,17 @@ namespace gfx{
|
||||
}
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
switch(format){
|
||||
case GL_RED:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_R8, m_width, m_height);
|
||||
break;
|
||||
case GL_RG:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RG8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGB:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGB8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGBA:
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGBA8, m_width, m_height);
|
||||
break;
|
||||
default:
|
||||
debug_print_error("Invalid format for texture\n");
|
||||
return false;
|
||||
};
|
||||
m_format = format;
|
||||
if(!create_texture_storage_()){
|
||||
debug_print_error("Invalid format for texture\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
glTextureSubImage2D(m_tex_id, 0, 0, 0, m_width, m_height, m_format, type, data);
|
||||
glGenerateTextureMipmap(m_tex_id);
|
||||
if(m_mipmapped)
|
||||
generate_mipmap();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
|
||||
return true;
|
||||
}
|
||||
bool texture::set_image(const egn::image& i){
|
||||
@ -167,6 +186,37 @@ namespace gfx{
|
||||
return set_image(i.get_image());
|
||||
}
|
||||
|
||||
bool texture::set_subimage(const unsigned char* data, GLenum format, GLenum type,
|
||||
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h)
|
||||
{
|
||||
if(!data){
|
||||
debug_print_error("Image is invalid\n");
|
||||
return false;
|
||||
}
|
||||
if(yoffset >= m_height || xoffset >= m_width){
|
||||
debug_print_error("Texture is smaller than requested offsets: (%d, %d)\n", xoffset, yoffset);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint old_alignment = save_unpack_alignment_();
|
||||
|
||||
h = rexy::min(h, m_height - yoffset);
|
||||
w = rexy::min(w, m_width - xoffset);
|
||||
|
||||
glTextureSubImage2D(m_tex_id, 0, xoffset, yoffset, w, h, format, type, data);
|
||||
generate_mipmap();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
|
||||
return true;
|
||||
}
|
||||
bool texture::set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset){
|
||||
return set_subimage(i.data(), convert_channel_to_format(i.get_channels()), GL_UNSIGNED_BYTE, xoffset, yoffset, i.get_width(), i.get_height());
|
||||
}
|
||||
bool texture::set_subimage(const egn::deferred_image& i, GLsizei xoffset, GLsizei yoffset){
|
||||
return set_subimage(i.get_image(), xoffset, yoffset);
|
||||
}
|
||||
|
||||
|
||||
void texture::set_wrap_mode(wrap w){
|
||||
glTextureParameteri(m_tex_id, GL_TEXTURE_WRAP_S, static_cast<GLint>(w));
|
||||
glTextureParameteri(m_tex_id, GL_TEXTURE_WRAP_T, static_cast<GLint>(w));
|
||||
@ -196,67 +246,99 @@ namespace gfx{
|
||||
void texture::set_min_filter(minfilter m){
|
||||
glTextureParameteri(m_tex_id, GL_TEXTURE_MIN_FILTER, static_cast<GLint>(m));
|
||||
}
|
||||
auto texture::get_mag_filter()const -> magfilter{
|
||||
auto texture::get_mag_filter(void)const -> magfilter{
|
||||
GLint filter;
|
||||
glGetTextureParameteriv(m_tex_id, GL_TEXTURE_MAG_FILTER, &filter);
|
||||
return static_cast<magfilter>(filter);
|
||||
}
|
||||
auto texture::get_min_filter()const -> minfilter{
|
||||
auto texture::get_min_filter(void)const -> minfilter{
|
||||
GLint filter;
|
||||
glGetTextureParameteriv(m_tex_id, GL_TEXTURE_MIN_FILTER, &filter);
|
||||
return static_cast<minfilter>(filter);
|
||||
}
|
||||
math::vec4<GLfloat> texture::get_border_color()const{
|
||||
math::vec4<GLfloat> texture::get_border_color(void)const{
|
||||
math::vec4<GLfloat> color;
|
||||
glGetTextureParameterfv(m_tex_id, GL_TEXTURE_BORDER_COLOR, color);
|
||||
return color;
|
||||
}
|
||||
auto texture::get_wrap_x()const -> wrap{
|
||||
auto texture::get_wrap_x(void)const -> wrap{
|
||||
GLint w;
|
||||
glGetTextureParameteriv(m_tex_id, GL_TEXTURE_WRAP_S, &w);
|
||||
return static_cast<wrap>(w);
|
||||
}
|
||||
auto texture::get_wrap_y()const -> wrap{
|
||||
auto texture::get_wrap_y(void)const -> wrap{
|
||||
GLint w;
|
||||
glGetTextureParameteriv(m_tex_id, GL_TEXTURE_WRAP_T, &w);
|
||||
return static_cast<wrap>(w);
|
||||
}
|
||||
GLsizei texture::get_width()const{
|
||||
GLsizei texture::get_width(void)const{
|
||||
return m_width;
|
||||
}
|
||||
GLsizei texture::get_height()const{
|
||||
GLsizei texture::get_height(void)const{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
GLuint texture::release(){
|
||||
void texture::enable_auto_mipmap(bool enable){
|
||||
m_mipmapped = enable;
|
||||
}
|
||||
void texture::generate_mipmap(void){
|
||||
glGenerateTextureMipmap(m_tex_id);
|
||||
}
|
||||
|
||||
GLuint texture::release(void){
|
||||
return std::exchange(m_tex_id, 0);
|
||||
}
|
||||
|
||||
void texture::bind()const{
|
||||
void texture::bind(void)const{
|
||||
glBindTexture(GL_TEXTURE_2D, m_tex_id);
|
||||
}
|
||||
void texture::bind_unit(GLuint tunit)const{
|
||||
glBindTextureUnit(tunit, m_tex_id);
|
||||
}
|
||||
weak_texture_handle texture::create_handle()const{
|
||||
weak_texture_handle texture::create_handle(void)const{
|
||||
return weak_texture_handle(*this);
|
||||
}
|
||||
|
||||
bool texture::create_texture_storage_(void){
|
||||
switch(m_format){
|
||||
case GL_RED:
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTextureStorage2D(m_tex_id, 1, GL_R8, m_width, m_height);
|
||||
break;
|
||||
case GL_RG:
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RG8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGB:
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGB8, m_width, m_height);
|
||||
break;
|
||||
case GL_RGBA:
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glTextureStorage2D(m_tex_id, 1, GL_RGBA8, m_width, m_height);
|
||||
break;
|
||||
default:
|
||||
glDeleteTextures(1, &m_tex_id);
|
||||
m_tex_id = 0;
|
||||
return false;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
weak_texture_handle::weak_texture_handle(const texture& tex):
|
||||
m_texture(&tex){}
|
||||
|
||||
GLuint weak_texture_handle::raw()const{
|
||||
GLuint weak_texture_handle::raw(void)const{
|
||||
return m_texture->raw();
|
||||
}
|
||||
GLsizei weak_texture_handle::get_width()const{
|
||||
GLsizei weak_texture_handle::get_width(void)const{
|
||||
return m_texture->get_width();
|
||||
}
|
||||
GLsizei weak_texture_handle::get_height()const{
|
||||
GLsizei weak_texture_handle::get_height(void)const{
|
||||
return m_texture->get_height();
|
||||
}
|
||||
|
||||
void weak_texture_handle::bind()const{
|
||||
void weak_texture_handle::bind(void)const{
|
||||
m_texture->bind();
|
||||
}
|
||||
void weak_texture_handle::bind_unit(GLuint tunit)const{
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
#include "config.hpp"
|
||||
#include "tic_tac_toe.hpp"
|
||||
#include "engine/font.hpp"
|
||||
|
||||
int main(){
|
||||
srand(time(NULL));
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
|
||||
main_renderer::main_renderer(egn::resource_manager& res, int width, int height):
|
||||
m_fb(MAX_WIDTH, MAX_HEIGHT),
|
||||
m_primary_fb(util::no_initialize),
|
||||
m_vbo(s_vertices, sizeof(s_vertices), gfx::vbo::usage::DYNAMIC_DRAW)
|
||||
{
|
||||
if(res.has_shader("sprite_shader"))
|
||||
@ -61,7 +62,6 @@ void main_renderer::set_vp_matrix(const math::mat4<GLfloat>& vp){
|
||||
m_sprite_shader->set_uniform("vp_mat", vp);
|
||||
}
|
||||
void main_renderer::render(scene& s){
|
||||
const auto& vp = m_fb.get_viewport();
|
||||
m_fb.bind();
|
||||
m_fb.clear_color_buffer();
|
||||
m_fb.clear_depth_buffer();
|
||||
@ -73,10 +73,9 @@ void main_renderer::render(scene& s){
|
||||
(*it)->render(*m_sprite_shader);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
m_primary_fb.bind();
|
||||
m_primary_fb.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glViewport(0, 0, vp.z(), vp.w());
|
||||
|
||||
m_screen_shader->use();
|
||||
m_screen_shader->set_uniform("texture1", m_fb.colorbuffer(), 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user