Start work on figuring out interface between graphics and engine subsystems. I did this by creating a 'board_gfx' class that became a member of the 'board' class. This gfx member does all the graphics legwork for the type.

I also put all the tic-tac-toe specific files into 'ttt' subdirectories to make it easier to see what's specifically for this game and what's just a wip idea
This commit is contained in:
rexy712 2022-01-17 13:35:29 -08:00
parent 5857c442aa
commit 21137971ca
26 changed files with 525 additions and 294 deletions

View File

@ -54,27 +54,6 @@ namespace egn{
unsigned char* data();
};
class deferred_image
{
private:
std::string m_filename;
bool m_flip = false;
int m_req_chan = 0;
public:
deferred_image(const char* file, bool flip = false, int req_chan = 0);
deferred_image(const std::string& file, bool flip = false, int req_chan = 0);
deferred_image(const deferred_image&) = default;
deferred_image(deferred_image&&) = default;
~deferred_image(void) = default;
deferred_image& operator=(const deferred_image&) = default;
deferred_image& operator=(deferred_image&&) = default;
operator image(void)const;
image get_image(void)const;
};
}
#endif

View File

@ -34,6 +34,7 @@ namespace egn{
class resource_manager
{
private:
std::map<std::string,gfx::texture_array> m_array_textures;
std::map<std::string,gfx::material> m_textures;
std::map<std::string,gfx::model> m_models;
std::map<std::string,gfx::shader_program> m_shaders;
@ -48,6 +49,12 @@ namespace egn{
resource_manager& operator=(const resource_manager&) = default;
resource_manager& operator=(resource_manager&&) = default;
bool has_array_texture(const char* key)const;
template<class... Args>
std::pair<gfx::texture_array*,bool> emplace_array_texture(const char* key, Args&&... args);
gfx::texture_array* get_array_texture(const char* file);
bool erase_array_texture(const char* key);
bool has_material(const char* key)const;
template<class... Args>
std::pair<gfx::material*,bool> emplace_material(const char* key, Args&&... args);
@ -68,6 +75,13 @@ namespace egn{
};
template<class... Args>
std::pair<gfx::texture_array*,bool> resource_manager::emplace_array_texture(const char* key, Args&&... args){
if(auto it = m_array_textures.find(key);it != m_array_textures.end())
return {&(*it).second, false};
auto ret = m_array_textures.emplace(std::piecewise_construct, std::tuple(key), std::tuple(std::forward<Args>(args)...));
return {&(*(ret.first)).second, true};
}
template<class... Args>
std::pair<gfx::material*,bool> resource_manager::emplace_material(const char* key, Args&&... args){
if(auto it = m_textures.find(key);it != m_textures.end())

View File

@ -87,7 +87,7 @@ namespace gfx{
texture_base(GLenum format, GLsizei w, GLsizei h, GLenum type, bool mipmap);
texture_base(const texture_base&);
texture_base(texture_base&&);
~texture_base(void) = default;
~texture_base(void);
texture_base& operator=(const texture_base&);
texture_base& operator=(texture_base&&);
@ -132,10 +132,9 @@ namespace gfx{
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, bool mipmap = true);
texture(const egn::deferred_image& i, bool mipmap = true);
texture(const texture&);
texture(texture&&);
~texture(void);
~texture(void) = default;
texture& operator=(const texture&);
texture& operator=(texture&&);
@ -143,12 +142,10 @@ namespace gfx{
//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);
//bind to target
void bind(GLuint target = GL_TEXTURE_2D)const;
@ -161,40 +158,76 @@ namespace gfx{
bool create_texture_storage_(void);
};
class texture_array;
class texture_slice
{
private:
texture_array* m_owner;
size_t m_level;
public:
texture_slice(texture_array* tex, int level);
texture_slice(const texture_slice&) = default;
texture_slice(texture_slice&&) = default;
~texture_slice(void) = default;
texture_slice& operator=(const texture_slice&) = default;
texture_slice& operator=(texture_slice&&) = default;
bool valid(void)const;
GLuint raw(void)const;
int get_level(void)const;
GLsizei get_width(void)const;
GLsizei get_height(void)const;
bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type);
bool set_image(const egn::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);
};
class texture_array : public texture_base
{
private:
int m_levels = 0;
size_t m_levels = 0;
public:
texture_array(void);
texture_array(const egn::image& i, int layers, bool mipmap = true);
texture_array(GLenum format, GLsizei w, GLsizei h, GLenum type, int layers, bool mipmap = true);
texture_array(size_t layers);
texture_array(const egn::image& i, size_t layers, bool mipmap = true);
texture_array(GLenum format, GLsizei w, GLsizei h, GLenum type, size_t layers, bool mipmap = true);
texture_array(const texture_array&);
texture_array(texture_array&&);
~texture_array(void);
~texture_array(void) = default;
texture_array& operator=(const texture_array&);
texture_array& operator=(texture_array&&);
//overwrite the current image data with 'i'
bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, int layer);
bool set_image(const egn::image& i, int layer);
bool set_image(const egn::deferred_image& i, int layer);
bool set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, size_t layer);
bool set_image(const egn::image& i, size_t layer);
bool set_subimage(const unsigned char* data, GLenum format, GLenum type,
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h, int layer);
bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset, int layer);
bool set_subimage(const egn::deferred_image& i, GLsizei xoffset, GLsizei yoffset, int layer);
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h, size_t layer);
bool set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset, size_t layer);
//bind to target
void bind(GLuint target = GL_TEXTURE_2D_ARRAY)const;
//bind to given texture unit and load into given program uniform location
void bind_unit(GLuint tunit)const;
texture_slice operator[](size_t layer);
private:
bool create_texture_storage_(void);
};
class texture_view
{
//TODO
//lookup glTextureView to remind yourself
};
}
#endif

View File

@ -30,4 +30,6 @@ public:
virtual void render(gfx::shader_program&) = 0;
};
class renderable_object : public renderable_iface, public egn::object_base{};
#endif

View File

@ -19,14 +19,8 @@
#ifndef OUR_DICK_BOARD_HPP
#define OUR_DICK_BOARD_HPP
#include "graphics/mesh.hpp"
#include "graphics/model.hpp"
#include "graphics/shader_program.hpp"
#include "graphics/material.hpp"
#include "graphics/vbo.hpp"
#include "graphics/vao.hpp"
#include "engine/object.hpp"
#include "renderable.hpp"
#include "engine/resource_manager.hpp"
#include "math/vec.hpp"
@ -34,6 +28,8 @@
#include <memory> //unique_ptr
class board_gfx;
class tile : public egn::object_base
{
public:
@ -56,26 +52,23 @@ public:
void set_color(const math::vec4<float>& color);
const math::vec4<float>& get_color(void)const;
};
class board : public renderable_iface, public egn::object_base
class board : public renderable_object
{
private:
std::unique_ptr<tile[]> m_tiles;
gfx::texture_array m_textures;
gfx::vao m_vao;
gfx::vbo m_vbo;
std::unique_ptr<board_gfx> m_gfx;
public:
board(egn::resource_manager& r);
~board(void) = default;
~board(void)override = default;
tile::value check_winner(void)const;
bool is_full(void)const;
void render(gfx::shader_program& shader);
int click_collision_cheat(const math::vec3<GLfloat>&)const;
void set_tile(int index, tile::value value);
@ -84,6 +77,8 @@ public:
void reset(void);
void render(gfx::shader_program& sh)override;
private:
tile::value check_rows_(void)const;
tile::value check_columns_(void)const;

51
include/ttt/board_gfx.hpp Normal file
View File

@ -0,0 +1,51 @@
/**
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_BOARD_GFX_HPP
#define OUR_DICK_BOARD_GFX_HPP
#include "graphics/material.hpp"
#include "graphics/vbo.hpp"
#include "graphics/vao.hpp"
#include "graphics/shader_program.hpp"
#include <utility> //pair
class tile;
class board_gfx
{
private:
gfx::texture_array* m_textures;
gfx::vao m_vao;
gfx::vbo m_vbo;
public:
board_gfx(std::pair<gfx::texture_array*,bool> resman_result);
~board_gfx(void) = default;
void set_uniforms(gfx::shader_program& sh);
void bind_buffers(void);
void bind_attributes(void);
void buffer_tiles(const tile* t);
void render(gfx::shader_program& shader);
};
#endif

79
include/util/deferred.hpp Normal file
View File

@ -0,0 +1,79 @@
/**
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_UTIL_DEFERRED_HPP
#define OUR_DICK_UTIL_DEFERRED_HPP
#include <tuple>
#include <utility> //forward, index_sequence
namespace util{
template<class T, class... Args>
class deferred
{
public:
using value_type = T;
private:
std::tuple<Args...> m_args;
public:
template<class... FArgs>
constexpr deferred(FArgs&&... args);
deferred(const deferred&) = default;
deferred(deferred&&) = default;
~deferred(void) = default;
deferred& operator=(const deferred&) = default;
deferred& operator=(deferred&&) = default;
constexpr value_type value(void);
constexpr operator value_type(void);
private:
template<size_t... Is>
constexpr value_type get_value_(std::index_sequence<Is...>);
};
template<class T, class... Args>
template<class... FArgs>
constexpr deferred<T,Args...>::deferred(FArgs&&... args):
m_args{std::forward<FArgs>(args)...}{}
template<class T, class... Args>
constexpr auto deferred<T,Args...>::value(void) -> deferred<T,Args...>::value_type{
return get_value_(std::make_index_sequence<sizeof...(Args)>());
}
template<class T, class... Args>
constexpr deferred<T,Args...>::operator value_type(void){
return get_value_(std::make_index_sequence<sizeof...(Args)>());
}
template<class T, class... Args>
template<size_t... Is>
constexpr auto deferred<T,Args...>::get_value_(std::index_sequence<Is...>) -> deferred<T,Args...>::value_type{
return T{std::get<Is>(m_args)...};
}
template<class T, class... Args>
deferred<T,Args...> make_deferred(Args&&... args){
return deferred<T,Args...>(std::forward<Args>(args)...);
}
}
#endif

View File

@ -79,20 +79,4 @@ namespace egn{
return m_data;
}
deferred_image::deferred_image(const char* file, bool flip, int req_chan):
m_filename(file),
m_flip(flip),
m_req_chan(req_chan){}
deferred_image::deferred_image(const std::string& file, bool flip, int req_chan):
m_filename(file),
m_flip(flip),
m_req_chan(req_chan){}
deferred_image::operator image(void)const{
return get_image();
}
image deferred_image::get_image(void)const{
return image(m_filename.c_str(), m_flip, m_req_chan);
}
}

View File

@ -20,12 +20,25 @@
namespace egn{
bool resource_manager::has_array_texture(const char* key)const{
if(auto it = m_array_textures.find(key);it != m_array_textures.end())
return true;
return false;
}
gfx::texture_array* resource_manager::get_array_texture(const char* file){
if(auto it = m_array_textures.find(file);it != m_array_textures.end())
return &(*it).second;
return nullptr;
}
bool resource_manager::erase_array_texture(const char* key){
return m_array_textures.erase(key) == 1;
}
bool resource_manager::has_material(const char* key)const{
if(auto it = m_textures.find(key);it != m_textures.end())
return true;
return false;
}
gfx::material* resource_manager::get_material(const char* file){
if(auto it = m_textures.find(file);it != m_textures.end())
return &(*it).second;

View File

@ -87,6 +87,9 @@ namespace gfx{
m_format(t.m_format), m_type(t.m_type),
m_mipmapped(t.m_mipmapped){}
texture_base::~texture_base(void){
glDeleteTextures(1, &m_tex_id);
}
texture_base& texture_base::operator=(const texture_base& t){
m_width = t.m_width;
m_height = t.m_height;
@ -179,119 +182,6 @@ namespace gfx{
return std::exchange(m_tex_id, 0);
}
texture_array::texture_array(void){
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
}
texture_array::texture_array(const egn::image& i, int layers, bool mipmap):
texture_array(convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE, layers, mipmap)
{
m_mipmapped = mipmap;
set_image(i, 0);
}
texture_array::texture_array(GLenum format, GLsizei w, GLsizei h, GLenum type, int levels, bool mipmap):
texture_base(format, w, h, type, mipmap),
m_levels(levels)
{
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
if(!create_texture_storage_()){
debug_print_error("Failed to create texture array storage\n");
return;
}
}
texture_array::texture_array(const texture_array& t):
texture_base(t),
m_levels(t.m_levels)
{
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
GLint old_alignment = save_unpack_alignment_();
if(!create_texture_storage_()){
}
//TODO
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
}
texture_array::texture_array(texture_array&& t):
texture_base(std::move(t)),
m_levels(t.m_levels){}
texture_array::~texture_array(void){
glDeleteTextures(1, &m_tex_id);
}
texture_array& texture_array::operator=(const texture_array& t){
return (*this = texture_array(t));
}
texture_array& texture_array::operator=(texture_array&& t){
texture_base::operator=(std::move(t));
m_levels = t.m_levels;
return *this;
}
bool texture_array::set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, int layer){
if(!data){
return false;
}
if(layer > m_levels){
return false;
}
GLint old_alignment = save_unpack_alignment_();
if(m_width != w || m_height != h || m_format != format){
return false;
}
glTextureSubImage3D(m_tex_id, 0, 0, 0, layer, m_width, m_height, 1, m_format, type, data);
if(m_mipmapped){
generate_mipmap();
}
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
return true;
}
bool texture_array::set_image(const egn::image& i, int layer){
return set_image(i.data(), convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE, layer);
}
bool texture_array::set_image(const egn::deferred_image& i, int layer){
return set_image(i.get_image(), layer);
}
bool texture_array::set_subimage(const unsigned char* data, GLenum format, GLenum type,
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h, int layer)
{
if(!data){
return false;
}
if(yoffset >= m_height || xoffset >= m_width){
debug_print_error("Texture array is smaller than requested offsets: (%d, %d)\n", xoffset, yoffset);
return false;
}
if(layer > m_levels || m_format != format){
return false;
}
GLint old_alignment = save_unpack_alignment_();
h = rexy::min(h, m_height - yoffset);
w = rexy::min(w, m_width - xoffset);
glTextureSubImage3D(m_tex_id, 0, xoffset, yoffset, layer, w, h, 1, m_format, type, data);
if(m_mipmapped)
generate_mipmap();
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
return true;
}
bool texture_array::set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset, int layer){
return set_subimage(i.data(), convert_channel_to_format(i.get_channels()), GL_UNSIGNED_BYTE, xoffset, yoffset, i.get_width(), i.get_height(), layer);
}
bool texture_array::set_subimage(const egn::deferred_image& i, GLsizei xoffset, GLsizei yoffset, int layer){
return set_subimage(i.get_image(), xoffset, yoffset, layer);
}
void texture_array::bind(GLuint target)const{
glBindTexture(target, m_tex_id);
}
void texture_array::bind_unit(GLuint tunit)const{
glBindTextureUnit(tunit, m_tex_id);
}
texture::texture(void){
glCreateTextures(GL_TEXTURE_2D, 1, &m_tex_id);
}
@ -313,12 +203,6 @@ namespace gfx{
m_mipmapped = mipmap;
set_image(i);
}
texture::texture(const egn::deferred_image& i, bool mipmap):
texture()
{
m_mipmapped = mipmap;
set_image(i);
}
texture::texture(const texture& t):
texture_base(t)
{
@ -342,9 +226,6 @@ namespace gfx{
}
texture::texture(texture&& t):
texture_base(std::move(t)){}
texture::~texture(void){
glDeleteTextures(1, &m_tex_id);
}
texture& texture::operator=(const texture& t){
debug_print_warn("Copy assigning texture!\n");
@ -385,9 +266,6 @@ namespace gfx{
bool texture::set_image(const egn::image& i){
return set_image(i.data(), convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE);
}
bool texture::set_image(const egn::deferred_image& i){
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)
@ -416,10 +294,6 @@ namespace gfx{
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::bind(GLuint target)const{
glBindTexture(target, m_tex_id);
@ -431,30 +305,6 @@ namespace gfx{
return weak_texture_handle(*this);
}
bool texture_array::create_texture_storage_(void){
switch(m_format){
case GL_RED:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTextureStorage3D(m_tex_id, 1, GL_R8, m_width, m_height, m_levels);
break;
case GL_RG:
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glTextureStorage3D(m_tex_id, 1, GL_RG8, m_width, m_height, m_levels);
break;
case GL_RGB:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTextureStorage3D(m_tex_id, 1, GL_RGB8, m_width, m_height, m_levels);
break;
case GL_RGBA:
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTextureStorage3D(m_tex_id, 1, GL_RGBA8, m_width, m_height, m_levels);
break;
default:
glDeleteTextures(1, &m_tex_id);
return false;
};
return true;
}
bool texture::create_texture_storage_(void){
switch(m_format){
case GL_RED:
@ -481,6 +331,201 @@ namespace gfx{
return true;
}
texture_slice::texture_slice(texture_array* tex, int level):
m_owner(tex),
m_level(level){}
bool texture_slice::valid(void)const{
return m_owner;
}
GLuint texture_slice::raw(void)const{
return m_owner->raw();
}
int texture_slice::get_level(void)const{
return m_level;
}
GLsizei texture_slice::get_width(void)const{
return m_owner->get_width();
}
GLsizei texture_slice::get_height(void)const{
return m_owner->get_height();
}
bool texture_slice::set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type){
return m_owner->set_image(data, format, w, h, type, m_level);
}
bool texture_slice::set_image(const egn::image& i){
return m_owner->set_image(i, m_level);
}
bool texture_slice::set_subimage(const unsigned char* data, GLenum format, GLenum type, GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h){
return m_owner->set_subimage(data, format, type, xoffset, yoffset, w, h, m_level);
}
bool texture_slice::set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset){
return m_owner->set_subimage(i, xoffset, yoffset, m_level);
}
texture_array::texture_array(void){
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
}
texture_array::texture_array(size_t layers):
m_levels(layers)
{
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
}
texture_array::texture_array(const egn::image& i, size_t layers, bool mipmap):
texture_array(convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE, layers, mipmap)
{
m_mipmapped = mipmap;
set_image(i, 0);
}
texture_array::texture_array(GLenum format, GLsizei w, GLsizei h, GLenum type, size_t levels, bool mipmap):
texture_base(format, w, h, type, mipmap),
m_levels(levels)
{
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
if(!create_texture_storage_()){
debug_print_error("Failed to create texture array storage\n");
return;
}
}
texture_array::texture_array(const texture_array& t):
texture_base(t),
m_levels(t.m_levels)
{
debug_print_warn("Copy constructing texture array!\n");
glCreateTextures(GL_TEXTURE_2D_ARRAY, 1, &m_tex_id);
GLint old_alignment = save_unpack_alignment_();
if(!create_texture_storage_()){
debug_print_error("Failed to create texture array storage\n");
return;
}
glCopyImageSubData(t.m_tex_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0,
m_tex_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0,
m_width, m_height, m_levels);
if(m_mipmapped)
generate_mipmap();
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
}
texture_array::texture_array(texture_array&& t):
texture_base(std::move(t)),
m_levels(t.m_levels){}
texture_array& texture_array::operator=(const texture_array& t){
return (*this = texture_array(t));
}
texture_array& texture_array::operator=(texture_array&& t){
texture_base::operator=(std::move(t));
m_levels = t.m_levels;
return *this;
}
bool texture_array::set_image(const unsigned char* data, GLenum format, GLsizei w, GLsizei h, GLenum type, size_t layer){
if(!data){
return false;
}
GLint old_alignment = save_unpack_alignment_();
if(!m_width || !m_height){
m_width = w;
m_height = h;
m_format = format;
m_type = type;
if(!m_levels){
m_levels = layer + 1;
}
create_texture_storage_();
}else if(m_width != w || m_height != h || m_format != format){
return false;
}
if(layer > m_levels){
return false;
}
glTextureSubImage3D(m_tex_id, 0, 0, 0, layer, m_width, m_height, 1, m_format, type, data);
if(m_mipmapped){
generate_mipmap();
}
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
return true;
}
bool texture_array::set_image(const egn::image& i, size_t layer){
return set_image(i.data(), convert_channel_to_format(i.get_channels()), i.get_width(), i.get_height(), GL_UNSIGNED_BYTE, layer);
}
bool texture_array::set_subimage(const unsigned char* data, GLenum format, GLenum type,
GLsizei xoffset, GLsizei yoffset, GLsizei w, GLsizei h, size_t layer)
{
if(!data){
return false;
}
if(yoffset >= m_height || xoffset >= m_width){
debug_print_error("Texture array is smaller than requested offsets: (%d, %d)\n", xoffset, yoffset);
return false;
}
if(layer > m_levels || m_format != format){
return false;
}
GLint old_alignment = save_unpack_alignment_();
h = rexy::min(h, m_height - yoffset);
w = rexy::min(w, m_width - xoffset);
glTextureSubImage3D(m_tex_id, 0, xoffset, yoffset, layer, w, h, 1, m_format, type, data);
if(m_mipmapped)
generate_mipmap();
glPixelStorei(GL_UNPACK_ALIGNMENT, old_alignment);
return true;
}
bool texture_array::set_subimage(const egn::image& i, GLsizei xoffset, GLsizei yoffset, size_t layer){
return set_subimage(i.data(), convert_channel_to_format(i.get_channels()), GL_UNSIGNED_BYTE, xoffset, yoffset, i.get_width(), i.get_height(), layer);
}
void texture_array::bind(GLuint target)const{
glBindTexture(target, m_tex_id);
}
void texture_array::bind_unit(GLuint tunit)const{
glBindTextureUnit(tunit, m_tex_id);
}
texture_slice texture_array::operator[](size_t layer){
if(layer < m_levels)
return texture_slice(this, layer);
return texture_slice(nullptr, 0);
}
bool texture_array::create_texture_storage_(void){
switch(m_format){
case GL_RED:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTextureStorage3D(m_tex_id, 1, GL_R8, m_width, m_height, m_levels);
break;
case GL_RG:
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glTextureStorage3D(m_tex_id, 1, GL_RG8, m_width, m_height, m_levels);
break;
case GL_RGB:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTextureStorage3D(m_tex_id, 1, GL_RGB8, m_width, m_height, m_levels);
break;
case GL_RGBA:
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTextureStorage3D(m_tex_id, 1, GL_RGBA8, m_width, m_height, m_levels);
break;
default:
glDeleteTextures(1, &m_tex_id);
return false;
};
return true;
}
weak_texture_handle::weak_texture_handle(const texture& tex):
m_texture(&tex){}

View File

@ -24,7 +24,7 @@
#include <ctime> //time
#include "config.hpp"
#include "tic_tac_toe.hpp"
#include "ttt/tic_tac_toe.hpp"
#include "engine/font.hpp"
int main(){

View File

@ -16,11 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "board.hpp"
#include "math/mat.hpp"
#include "ttt/board.hpp"
#include "ttt/board_gfx.hpp"
#include "graphics/gl_include.hpp" //GLfloat
#include "engine/font.hpp"
void tile::set_value(value t){
m_active_value = t;
@ -36,18 +35,9 @@ const math::vec4<float>& tile::get_color(void)const{
}
board::board(egn::resource_manager& resman):
m_tiles(nullptr),
m_textures(egn::image("assets/images/blank.jpg", true), 3),
m_vbo((16 * sizeof(GLfloat) + 4 * sizeof(GLfloat) + 1 * sizeof(GLint)) * 9, gfx::vbo::usage::DYNAMIC_DRAW)
m_tiles(new tile[9]),
m_gfx(new board_gfx(resman.emplace_array_texture("board_textures", 3)))
{
//m_textures[0] = resman.emplace_material("assets/images/blank.jpg", egn::deferred_image("assets/images/blank.jpg", true)).first;
//m_textures[1] = resman.emplace_material("assets/images/o.jpg", egn::deferred_image("assets/images/o.jpg", true)).first;
//m_textures[2] = resman.emplace_material("assets/images/x.jpg", egn::deferred_image("assets/images/x.jpg", true)).first;
m_textures.set_image(egn::image("assets/images/o.jpg", true), 1);
m_textures.set_image(egn::image("assets/images/x.jpg", true), 2);
m_tiles.reset(new tile[9]);
m_tiles[0].set_position({-2.125, 2.125, -1});
m_tiles[1].set_position({-2.125, 0, -1});
m_tiles[2].set_position({-2.125, -2.125, -1});
@ -58,51 +48,10 @@ board::board(egn::resource_manager& resman):
m_tiles[7].set_position({ 2.125, 0, -1});
m_tiles[8].set_position({ 2.125, -2.125, -1});
m_vao.bind_buffer(m_vbo, 0, 0, sizeof(GLfloat)*16 + sizeof(GLfloat)*4 + sizeof(GLint));
auto attrib = m_vao.get_attribute(2);
attrib.set_float_array(4, 0);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(3);
attrib.set_float_array(4, sizeof(GLfloat)*4);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(4);
attrib.set_float_array(4, sizeof(GLfloat)*8);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(5);
attrib.set_float_array(4, sizeof(GLfloat)*12);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(0);
attrib.set_int_array(1, sizeof(GLfloat)*16);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(1);
attrib.set_float_array(4, sizeof(GLfloat)*16 + sizeof(GLint));
attrib.associate_with(0);
attrib.enable();
}
void board::render(gfx::shader_program& shader){
m_vbo.clear();
shader.set_uniform("textures", m_textures, 0);
for(int i = 0;i < 9;++i){
GLint tex_id = (GLint)m_tiles[i].get_value();
m_vbo.buffer(m_tiles[i].model_matrix().raw(), sizeof(GLfloat)*16);
m_vbo.buffer(&tex_id, sizeof(GLint));
m_vbo.buffer(m_tiles[i].get_color().raw(), sizeof(GLfloat)*4);
}
m_vao.bind();
glDrawArrays(GL_POINTS, 0, 9);
void board::render(gfx::shader_program& sh){
m_gfx->buffer_tiles(m_tiles.get());
m_gfx->render(sh);
}
bool board::is_full(void)const{
@ -224,4 +173,3 @@ tile::value board::check_diagonals_(void)const{
}
return tile::value::BLANK;
}

87
src/ttt/board_gfx.cpp Normal file
View File

@ -0,0 +1,87 @@
/**
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 "ttt/board_gfx.hpp"
#include "ttt/board.hpp"
board_gfx::board_gfx(std::pair<gfx::texture_array*,bool> resman_result):
m_vbo((16 * sizeof(GLfloat) + 4 * sizeof(GLfloat) + 1 * sizeof(GLint)) * 9, gfx::vbo::usage::DYNAMIC_DRAW)
{
m_textures = resman_result.first;
if(resman_result.second){
(*m_textures)[0].set_image(egn::image("assets/images/blank.jpg", true));
(*m_textures)[1].set_image(egn::image("assets/images/o.jpg", true));
(*m_textures)[2].set_image(egn::image("assets/images/x.jpg", true));
}
m_vao.bind_buffer(m_vbo, 0, 0, sizeof(GLfloat)*16 + sizeof(GLfloat)*4 + sizeof(GLint));
auto attrib = m_vao.get_attribute(2);
attrib.set_float_array(4, 0);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(3);
attrib.set_float_array(4, sizeof(GLfloat)*4);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(4);
attrib.set_float_array(4, sizeof(GLfloat)*8);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(5);
attrib.set_float_array(4, sizeof(GLfloat)*12);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(0);
attrib.set_int_array(1, sizeof(GLfloat)*16);
attrib.associate_with(0);
attrib.enable();
attrib = m_vao.get_attribute(1);
attrib.set_float_array(4, sizeof(GLfloat)*16 + sizeof(GLint));
attrib.associate_with(0);
attrib.enable();
}
void board_gfx::set_uniforms(gfx::shader_program& sh){
sh.set_uniform("textures", *m_textures, 0);
}
void board_gfx::bind_buffers(void){
m_vao.bind();
}
void board_gfx::buffer_tiles(const tile* t){
m_vbo.clear();
for(int i = 0;i < 9;++i){
GLint tex_id = (GLint)t[i].get_value();
m_vbo.buffer(t[i].model_matrix().raw(), sizeof(GLfloat)*16);
m_vbo.buffer(&tex_id, sizeof(GLint));
m_vbo.buffer(t[i].get_color().raw(), sizeof(GLfloat)*4);
}
}
void board_gfx::render(gfx::shader_program& shader){
set_uniforms(shader);
bind_buffers();
glDrawArrays(GL_POINTS, 0, 9);
}

View File

@ -16,10 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main_renderer.hpp"
#include "ttt/main_renderer.hpp"
#include "graphics/shader.hpp"
#include "square_shader.hpp"
#include "screen_shader.hpp"
#include "ttt/square_shader.hpp"
#include "ttt/screen_shader.hpp"
#include "config.hpp"
#include <cstdlib> //size_t
@ -40,7 +40,7 @@ main_renderer::main_renderer(egn::resource_manager& res, int width, int height):
gfx::shader(square_shader::geometry_shader_text, gfx::shader::type::GEOMETRY),
gfx::shader(square_shader::vertex_shader_text, gfx::shader::type::VERTEX)).first;
if(m_square_shader->has_link_error()){
debug_print_error(m_square_shader->get_error().c_str());
debug_print_error("%s\n", m_square_shader->get_error().c_str());
}
m_square_shader->set_uniform("vp_mat", math::mat4<GLfloat>{});

View File

@ -16,8 +16,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pause_state.hpp"
#include "ttt/pause_state.hpp"
#include "engine/game.hpp"
#include "util/deferred.hpp"
#include "graphics/gl_include.hpp" //TODO
@ -26,7 +27,7 @@
pause_state::pause_state(egn::game& owner, egn::game_state_iface* under):
game_state_iface(&owner),
m_under_state(under),
m_screen_renderer(owner.resource_man(), owner.get_width(), owner.get_height(), *owner.resource_man().emplace_material("pause_screen", egn::deferred_image("assets/images/pause.png", true)).first){}
m_screen_renderer(owner.resource_man(), owner.get_width(), owner.get_height(), *owner.resource_man().emplace_material("pause_screen", util::make_deferred<egn::image>("assets/images/pause.png", true)).first){}
void pause_state::enter(){
m_screen_renderer.resize_viewport(m_owner->get_width(), m_owner->get_height());

View File

@ -16,16 +16,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "play_state.hpp"
#include "ttt/play_state.hpp"
#include <queue>
#include "pause_state.hpp"
#include "ttt/pause_state.hpp"
#include "graphics/gl_include.hpp" //TODO: separate key definitions from GLFW
#include "engine/image.hpp" //TODO: move image to engine namespace
#include "math/math.hpp"
#include "config.hpp"
#include "engine/game.hpp"
#include "board.hpp"
#include "ttt/board.hpp"
play_state::play_state(egn::game& owner, int width, int height):
game_state_iface(&owner),

View File

@ -16,10 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "screen_renderer.hpp"
#include "ttt/screen_renderer.hpp"
#include "graphics/shader.hpp"
#include "screen_shader.hpp"
#include "ttt/screen_shader.hpp"
#include <tuple>
#include <utility> //piecewise_construct

View File

@ -16,9 +16,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tic_tac_toe.hpp"
#include "ttt/tic_tac_toe.hpp"
#include "engine/game_state.hpp"
#include "play_state.hpp"
#include "ttt/play_state.hpp"
#include "config.hpp"
tic_tac_toe::tic_tac_toe(int width, int height):