Compare commits
2 Commits
5fec2c0045
...
cd0d7bfea0
Author | SHA1 | Date |
---|---|---|
bog | cd0d7bfea0 | |
bog | 21ca282619 |
|
@ -0,0 +1,8 @@
|
|||
#version 130
|
||||
|
||||
in vec4 frag_icolor;
|
||||
out vec4 frag_ocolor;
|
||||
|
||||
void main() {
|
||||
frag_ocolor = frag_icolor;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#version 130
|
||||
|
||||
in vec3 pos;
|
||||
in vec4 color;
|
||||
|
||||
out vec4 frag_icolor;
|
||||
|
||||
uniform mat4 mvp;
|
||||
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(pos, 1.0f);
|
||||
frag_icolor = color;
|
||||
}
|
22
meson.build
22
meson.build
|
@ -7,8 +7,11 @@ project('duck2d',
|
|||
'cpp_std=c++17',
|
||||
])
|
||||
|
||||
assets_dir = get_option('prefix') / get_option('datadir') / 'duck2d'
|
||||
|
||||
conf = configuration_data()
|
||||
conf.set('version', meson.project_version())
|
||||
conf.set('assets_dir', assets_dir / 'assets')
|
||||
|
||||
|
||||
configure_file(
|
||||
|
@ -20,7 +23,26 @@ configure_file(
|
|||
executable('d2d',
|
||||
sources: [
|
||||
'src/main.cpp',
|
||||
'src/Script.cpp',
|
||||
|
||||
# game
|
||||
'src/Game.cpp',
|
||||
'src/Scene.cpp',
|
||||
|
||||
# graphics
|
||||
'src/Shader.cpp',
|
||||
'src/Shape.cpp',
|
||||
'src/Material.cpp',
|
||||
'src/Object.cpp',
|
||||
'src/Renderer.cpp',
|
||||
|
||||
],
|
||||
dependencies: [
|
||||
dependency('sdl2'),
|
||||
dependency('glew'),
|
||||
dependency('glm'),
|
||||
dependency('guile-3.0'),
|
||||
],
|
||||
install: true)
|
||||
|
||||
install_subdir('assets', install_dir: assets_dir)
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
#include <GL/glew.h>
|
||||
#include "Game.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Game::Game(std::string const& title,
|
||||
unsigned width,
|
||||
unsigned height)
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
m_window = SDL_CreateWindow(title.c_str(),
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
width, height,
|
||||
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
|
||||
if (!m_window)
|
||||
{
|
||||
throw game_error {"Cannot open a new window."};
|
||||
}
|
||||
|
||||
m_context = SDL_GL_CreateContext(m_window);
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
throw game_error {"Cannot initialize opengl context."};
|
||||
}
|
||||
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
throw game_error {"Cannot initialize GLEW."};
|
||||
}
|
||||
|
||||
m_renderer = std::make_unique<Renderer>(width, height);
|
||||
}
|
||||
|
||||
/*virtual*/ Game::~Game()
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_GL_DeleteContext(m_context);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
void Game::run()
|
||||
{
|
||||
SDL_Event event;
|
||||
bool m_running = true;
|
||||
float dt = 0.0f;
|
||||
|
||||
while (m_running)
|
||||
{
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
if (event.type == SDL_QUIT)
|
||||
{
|
||||
m_running = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_running == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (m_scenes.size() > 0)
|
||||
{
|
||||
m_scenes.back()->update(dt);
|
||||
}
|
||||
|
||||
for (auto const& obj: m_draw_queue)
|
||||
{
|
||||
m_renderer->draw(*obj);
|
||||
}
|
||||
|
||||
m_draw_queue.clear();
|
||||
|
||||
if (m_scenes.size() > 0)
|
||||
{
|
||||
m_scenes.back()->draw();
|
||||
}
|
||||
|
||||
SDL_GL_SwapWindow(m_window);
|
||||
|
||||
dt = std::chrono::duration_cast<std::chrono::microseconds>
|
||||
(std::chrono::steady_clock::now() - now).count()/1000000.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void Game::queue_draw(std::unique_ptr<Object> obj)
|
||||
{
|
||||
m_draw_queue.push_back(std::move(obj));
|
||||
}
|
||||
|
||||
void Game::pop()
|
||||
{
|
||||
if (m_scenes.size() > 0)
|
||||
{
|
||||
m_scenes.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef d2_GAME_HPP
|
||||
#define d2_GAME_HPP
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include "commons.hpp"
|
||||
#include "Renderer.hpp"
|
||||
#include "Scene.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
D2_ERROR(game_error);
|
||||
|
||||
class Game
|
||||
{
|
||||
public:
|
||||
explicit Game(std::string const& title,
|
||||
unsigned width,
|
||||
unsigned height);
|
||||
virtual ~Game();
|
||||
|
||||
void run();
|
||||
void queue_draw(std::unique_ptr<Object> obj);
|
||||
|
||||
template <typename T, typename... Args>
|
||||
void push(Args... args);
|
||||
void pop();
|
||||
|
||||
private:
|
||||
SDL_Window* m_window = nullptr;
|
||||
SDL_GLContext m_context;
|
||||
std::unique_ptr<Renderer> m_renderer;
|
||||
std::vector<std::unique_ptr<Object>> m_draw_queue;
|
||||
std::vector<std::unique_ptr<Scene>> m_scenes;
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
void Game::push(Args... args)
|
||||
{
|
||||
auto scene = std::make_unique<T>(args...);
|
||||
m_scenes.push_back(std::move(scene));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
#include "Material.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Material::Material()
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Material::~Material()
|
||||
{
|
||||
}
|
||||
|
||||
void Material::set_color(unsigned r, unsigned g, unsigned b, unsigned a)
|
||||
{
|
||||
m_r = r;
|
||||
m_g = g;
|
||||
m_b = b;
|
||||
m_a = a;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef d2_MATERIAL_HPP
|
||||
#define d2_MATERIAL_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
class Material
|
||||
{
|
||||
public:
|
||||
explicit Material();
|
||||
virtual ~Material();
|
||||
|
||||
void set_color(unsigned r, unsigned g, unsigned b, unsigned a);
|
||||
|
||||
unsigned r() const { return m_r; }
|
||||
unsigned g() const { return m_g; }
|
||||
unsigned b() const { return m_b; }
|
||||
unsigned a() const { return m_a; }
|
||||
|
||||
private:
|
||||
unsigned m_r = 0;
|
||||
unsigned m_g = 0;
|
||||
unsigned m_b = 0;
|
||||
unsigned m_a = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,108 @@
|
|||
#include "Object.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Object::Object(std::shared_ptr<Shape> shape,
|
||||
std::shared_ptr<Material> material,
|
||||
std::shared_ptr<Shader> shader)
|
||||
: m_shape { shape }
|
||||
, m_material { material }
|
||||
, m_shader { shader }
|
||||
{
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
use();
|
||||
glGenBuffers(BUFFER_COUNT, m_vbos);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
/*virtual*/ Object::~Object()
|
||||
{
|
||||
glDeleteBuffers(BUFFER_COUNT, m_vbos);
|
||||
glDeleteVertexArrays(1, &m_vao);
|
||||
}
|
||||
|
||||
void Object::set_position(glm::vec3 position)
|
||||
{
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
void Object::set_size(glm::vec3 size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void Object::use() const
|
||||
{
|
||||
m_shader->use();
|
||||
glBindVertexArray(m_vao);
|
||||
}
|
||||
|
||||
void Object::update() const
|
||||
{
|
||||
update_pos();
|
||||
update_color();
|
||||
}
|
||||
|
||||
size_t Object::point_count() const
|
||||
{
|
||||
return m_shape->points().size();
|
||||
}
|
||||
|
||||
void Object::update_pos() const
|
||||
{
|
||||
use();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbos[POS_BUFFER]);
|
||||
auto const& vertices = m_shape->points();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
vertices.size() * sizeof(glm::vec3),
|
||||
vertices.data(),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
GLint location = m_shader->attr("pos");
|
||||
assert(location >= 0);
|
||||
|
||||
glEnableVertexAttribArray(location);
|
||||
glVertexAttribPointer(location,
|
||||
3,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(glm::vec3),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void Object::update_color() const
|
||||
{
|
||||
use();
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbos[COLOR_BUFFER]);
|
||||
std::vector<glm::vec4> colors;
|
||||
|
||||
for (size_t i=0; i<m_shape->points().size(); i++)
|
||||
{
|
||||
colors.push_back(glm::vec4
|
||||
{static_cast<float>(m_material->r())/255.0f,
|
||||
static_cast<float>(m_material->g()/255.0f),
|
||||
static_cast<float>(m_material->b()/255.0f),
|
||||
static_cast<float>(m_material->a())/255.0f});
|
||||
}
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
colors.size() * sizeof(glm::vec4),
|
||||
colors.data(),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
GLint location = m_shader->attr("color");
|
||||
assert(location >= 0);
|
||||
|
||||
glEnableVertexAttribArray(location);
|
||||
glVertexAttribPointer(location,
|
||||
4,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(glm::vec4),
|
||||
nullptr);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef d2_OBJECT_HPP
|
||||
#define d2_OBJECT_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <GL/glew.h>
|
||||
#include "commons.hpp"
|
||||
|
||||
#include "Shader.hpp"
|
||||
#include "Material.hpp"
|
||||
#include "Shape.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
enum BufferType {
|
||||
POS_BUFFER,
|
||||
COLOR_BUFFER,
|
||||
BUFFER_COUNT
|
||||
};
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
explicit Object(std::shared_ptr<Shape> shape,
|
||||
std::shared_ptr<Material> material,
|
||||
std::shared_ptr<Shader> shader);
|
||||
|
||||
virtual ~Object();
|
||||
|
||||
glm::mat4 transform() const { return m_transform; }
|
||||
std::shared_ptr<Shader> shader() const { return m_shader; }
|
||||
|
||||
glm::vec3 position() const { return m_position; }
|
||||
glm::vec3 size() const { return m_size; }
|
||||
|
||||
void set_position(glm::vec3 position);
|
||||
void set_size(glm::vec3 size);
|
||||
|
||||
void use() const;
|
||||
void update() const;
|
||||
size_t point_count() const;
|
||||
|
||||
private:
|
||||
GLuint m_vao;
|
||||
GLuint m_vbos[BUFFER_COUNT];
|
||||
glm::vec3 m_position;
|
||||
glm::vec3 m_size;
|
||||
|
||||
glm::mat4 m_transform;
|
||||
std::shared_ptr<Shape> m_shape;
|
||||
std::shared_ptr<Material> m_material;
|
||||
std::shared_ptr<Shader> m_shader;
|
||||
|
||||
void update_pos() const;
|
||||
void update_color() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,34 @@
|
|||
#include "Renderer.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Renderer::Renderer(unsigned width, unsigned height)
|
||||
: m_width { width }
|
||||
, m_height { height }
|
||||
{
|
||||
m_projection = glm::ortho(0.0f,
|
||||
static_cast<float>(m_width),
|
||||
static_cast<float>(height),
|
||||
0.0f);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
/*virtual*/ Renderer::~Renderer()
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::draw(Object const& object) const
|
||||
{
|
||||
glm::mat4 mvp {1.0f};
|
||||
|
||||
mvp = glm::translate(mvp, object.position());
|
||||
mvp = glm::scale(mvp, object.size());
|
||||
mvp = m_projection * mvp;
|
||||
|
||||
object.use();
|
||||
object.shader()->set_matrix("mvp", mvp);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, object.point_count());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef d2_RENDERER_HPP
|
||||
#define d2_RENDERER_HPP
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "commons.hpp"
|
||||
#include "Object.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
class Renderer
|
||||
{
|
||||
public:
|
||||
explicit Renderer(unsigned width, unsigned height);
|
||||
virtual ~Renderer();
|
||||
|
||||
void draw(Object const& object) const;
|
||||
|
||||
private:
|
||||
unsigned m_width;
|
||||
unsigned m_height;
|
||||
glm::mat4 m_projection;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
#include "Scene.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Scene::Scene()
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Scene::~Scene()
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef d2_SCENE_HPP
|
||||
#define d2_SCENE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
explicit Scene();
|
||||
virtual ~Scene();
|
||||
|
||||
virtual void update(float dt) = 0;
|
||||
virtual void draw() = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,119 @@
|
|||
#include "Script.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*static*/ std::unique_ptr<Game> Script::game = nullptr;
|
||||
/*static*/ glm::vec4 Script::color = {0.0f, 0.0f, 0.0f, 255.0f};
|
||||
|
||||
/*static*/ void Script::init()
|
||||
{
|
||||
scm_init_guile();
|
||||
scm_c_define_gsubr("winconf", 3, 0, 0,
|
||||
reinterpret_cast<void*>(&fn_winconf));
|
||||
|
||||
// Scenes
|
||||
// ------
|
||||
scm_c_define_gsubr("scene:push", 1, 1, 0,
|
||||
reinterpret_cast<void*>(&fn_scene__push));
|
||||
|
||||
scm_c_define_gsubr("scene:pop", 0, 0, 0,
|
||||
reinterpret_cast<void*>(&fn_scene__pop));
|
||||
|
||||
// Drawing
|
||||
// -------
|
||||
scm_c_define_gsubr("rect", 4, 0, 0, reinterpret_cast<void*>(&fn_rect));
|
||||
scm_c_define_gsubr("color!", 4, 0, 0,
|
||||
reinterpret_cast<void*>(&fn_set_color));
|
||||
}
|
||||
|
||||
/*static*/ void Script::terminate()
|
||||
{
|
||||
Script::game.reset();
|
||||
}
|
||||
|
||||
/*static*/ void Script::run(std::filesystem::path conf_file)
|
||||
{
|
||||
scm_c_primitive_load(conf_file.c_str());
|
||||
|
||||
if (Script::game == nullptr)
|
||||
{
|
||||
Script::game = std::make_unique<Game>("Duck2D", 640, 480);
|
||||
}
|
||||
|
||||
Script::game->run();
|
||||
}
|
||||
|
||||
/*static*/ SCM Script::fn_winconf(SCM scm_title,
|
||||
SCM scm_width,
|
||||
SCM scm_height)
|
||||
{
|
||||
std::string title = scm_to_locale_string(scm_title);
|
||||
unsigned width = scm_to_uint32(scm_width);
|
||||
unsigned height = scm_to_uint32(scm_height);
|
||||
|
||||
Script::game = std::make_unique<Game>(title, width, height);
|
||||
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
|
||||
/*static*/ SCM Script::fn_scene__push(SCM scm_function, SCM scm_ctx)
|
||||
{
|
||||
if (scm_is_null(scm_ctx))
|
||||
{
|
||||
Script::game->push<ScriptScene>(scm_function);
|
||||
}
|
||||
else
|
||||
{
|
||||
Script::game->push<ScriptScene>(scm_function, scm_ctx);
|
||||
}
|
||||
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
|
||||
/*static*/ SCM Script::fn_scene__pop()
|
||||
{
|
||||
Script::game->pop();
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
|
||||
/*static*/ SCM Script::fn_rect(SCM scm_x, SCM scm_y, SCM scm_w, SCM scm_h)
|
||||
{
|
||||
float x = scm_to_double(scm_x);
|
||||
float y = scm_to_double(scm_y);
|
||||
float w = scm_to_double(scm_w);
|
||||
float h = scm_to_double(scm_h);
|
||||
|
||||
auto shape = std::make_shared<Shape>();
|
||||
shape->set_rect();
|
||||
|
||||
auto material = std::make_shared<Material>();
|
||||
|
||||
material->set_color(Script::color.x,
|
||||
Script::color.y,
|
||||
Script::color.z,
|
||||
Script::color.w);
|
||||
|
||||
auto shader = std::make_shared<Shader>();
|
||||
|
||||
auto obj = std::make_unique<Object>(shape, material, shader);
|
||||
obj->set_position(glm::vec3 {x, y, 0.0f});
|
||||
obj->set_size(glm::vec3 {w, h, 0.0f});
|
||||
|
||||
Script::game->queue_draw(std::move(obj));
|
||||
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
SCM Script::fn_set_color(SCM scm_r, SCM scm_g, SCM scm_b, SCM scm_a)
|
||||
{
|
||||
float r = scm_to_double(scm_r);
|
||||
float g = scm_to_double(scm_g);
|
||||
float b = scm_to_double(scm_b);
|
||||
float a = scm_to_double(scm_a);
|
||||
|
||||
Script::color = glm::vec4 {r, g, b, a};
|
||||
|
||||
return SCM_BOOL_T;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef d2_SCRIPT_HPP
|
||||
#define d2_SCRIPT_HPP
|
||||
#include <guile/3.0/libguile.h>
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Game.hpp"
|
||||
#include "libguile/numbers.h"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
struct Script
|
||||
{
|
||||
static void init();
|
||||
static void terminate();
|
||||
static void run(std::filesystem::path conf_file);
|
||||
|
||||
static SCM fn_winconf(SCM scm_title, SCM scm_width, SCM scm_height);
|
||||
static SCM fn_rect(SCM scm_x, SCM scm_y, SCM scm_w, SCM scm_h);
|
||||
static SCM fn_set_color(SCM scm_r, SCM scm_g, SCM scm_b, SCM scm_a);
|
||||
|
||||
static SCM fn_scene__push(SCM scm_function, SCM scm_ctx);
|
||||
static SCM fn_scene__pop();
|
||||
|
||||
private:
|
||||
static std::unique_ptr<Game> game;
|
||||
static glm::vec4 color;
|
||||
};
|
||||
|
||||
struct ScriptScene: public Scene
|
||||
{
|
||||
SCM function;
|
||||
SCM ctx;
|
||||
|
||||
explicit ScriptScene(SCM p_function, SCM p_ctx = 0)
|
||||
: function { p_function }
|
||||
, ctx { p_ctx }
|
||||
{
|
||||
}
|
||||
|
||||
void update(float dt) override
|
||||
{
|
||||
ctx = scm_call_2(function, scm_from_double(dt), ctx);
|
||||
}
|
||||
|
||||
void draw() override
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
#include "Shader.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Shader::Shader()
|
||||
{
|
||||
load_shader(GL_VERTEX_SHADER,
|
||||
DUCK_ASSETS / "shaders" / "vertex.glsl");
|
||||
|
||||
load_shader(GL_FRAGMENT_SHADER,
|
||||
DUCK_ASSETS / "shaders" / "fragment.glsl");
|
||||
|
||||
glLinkProgram(m_program);
|
||||
|
||||
GLint status = GL_FALSE;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
|
||||
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
size_t const SZ = 1024;
|
||||
char msg[SZ];
|
||||
glGetProgramInfoLog(m_program, SZ, nullptr, msg);
|
||||
throw shader_error {"Cannot link program."};
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ Shader::~Shader()
|
||||
{
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
void Shader::use() const
|
||||
{
|
||||
glUseProgram(m_program);
|
||||
}
|
||||
|
||||
GLint Shader::attr(std::string const& name) const
|
||||
{
|
||||
use();
|
||||
return glGetAttribLocation(m_program, name.c_str());
|
||||
}
|
||||
|
||||
GLint Shader::uniform(std::string const& name) const
|
||||
{
|
||||
use();
|
||||
return glGetUniformLocation(m_program, name.c_str());
|
||||
}
|
||||
|
||||
void Shader::set_matrix(std::string const& name, glm::mat4 matrix) const
|
||||
{
|
||||
use();
|
||||
glUniformMatrix4fv(uniform(name), 1, false, glm::value_ptr(matrix));
|
||||
}
|
||||
|
||||
GLuint Shader::load_shader(GLenum type,
|
||||
std::filesystem::path source_path)
|
||||
{
|
||||
// Load source
|
||||
// -----------
|
||||
if (!std::filesystem::is_regular_file(source_path))
|
||||
{
|
||||
throw shader_error {"Cannot find shader '"
|
||||
+ source_path.string() + "'."};
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
std::ifstream file { source_path };
|
||||
|
||||
if (!file)
|
||||
{
|
||||
throw shader_error {"Cannot open shader '"
|
||||
+ source_path.string()
|
||||
+ "'"};
|
||||
}
|
||||
|
||||
ss << file.rdbuf();
|
||||
|
||||
// Compile source
|
||||
// --------------
|
||||
std::string source = ss.str();
|
||||
char const* c_source[] = {source.c_str()};
|
||||
|
||||
GLuint shader = glCreateShader(type);
|
||||
glShaderSource(shader, 1, c_source, nullptr);
|
||||
|
||||
glCompileShader(shader);
|
||||
|
||||
// check compilation status
|
||||
// ------------------------
|
||||
GLint status = GL_FALSE;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
size_t const SZ = 1024;
|
||||
char msg[SZ];
|
||||
glGetShaderInfoLog(shader, SZ, nullptr, msg);
|
||||
|
||||
std::stringstream ss2;
|
||||
ss2 << "Cannot compile shader '"
|
||||
<< source_path.string() << "'" << std::endl;
|
||||
|
||||
ss2 << msg << std::endl;
|
||||
|
||||
throw shader_error {ss2.str()};
|
||||
}
|
||||
|
||||
glAttachShader(m_program, shader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef d2_SHADER_HPP
|
||||
#define d2_SHADER_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <GL/glew.h>
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
D2_ERROR(shader_error);
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
explicit Shader();
|
||||
virtual ~Shader();
|
||||
|
||||
void use() const;
|
||||
GLint attr(std::string const& name) const;
|
||||
GLint uniform(std::string const& name) const;
|
||||
void set_matrix(std::string const& name, glm::mat4 matrix) const;
|
||||
|
||||
private:
|
||||
GLuint m_program = glCreateProgram();
|
||||
|
||||
GLuint load_shader(GLenum type, std::filesystem::path source_path);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
#include "Shape.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
/*explicit*/ Shape::Shape()
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/ Shape::~Shape()
|
||||
{
|
||||
}
|
||||
|
||||
void Shape::set_rect()
|
||||
{
|
||||
auto const a = glm::vec3 {-0.5f, -0.5f, +0.0f};
|
||||
auto const b = glm::vec3 {+0.5f, -0.5f, +0.0f};
|
||||
auto const c = glm::vec3 {+0.5f, +0.5f, +0.0f};
|
||||
auto const d = glm::vec3 {-0.5f, +0.5f, +0.0f};
|
||||
// a -- b
|
||||
// | |
|
||||
// d -- c
|
||||
m_points = {a, b, c, a, c, d};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef d2_SHAPE_HPP
|
||||
#define d2_SHAPE_HPP
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include "commons.hpp"
|
||||
|
||||
namespace d2
|
||||
{
|
||||
class Shape
|
||||
{
|
||||
public:
|
||||
explicit Shape();
|
||||
virtual ~Shape();
|
||||
|
||||
std::vector<glm::vec3> const& points() const { return m_points; }
|
||||
|
||||
void set_rect();
|
||||
|
||||
private:
|
||||
std::vector<glm::vec3> m_points;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef d2_COMMONS_HPP
|
||||
#define d2_COMMONS_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "conf.hpp"
|
||||
|
||||
#define D2_ERROR(NAME) \
|
||||
struct NAME : public std::runtime_error { \
|
||||
explicit NAME(std::string const& what): \
|
||||
std::runtime_error { what } \
|
||||
{ \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
|
@ -2,5 +2,5 @@
|
|||
#define d2_CONF_HPP
|
||||
|
||||
#define DUCK_VERSION std::string("@version@")
|
||||
|
||||
#define DUCK_ASSETS std::filesystem::path("@assets_dir@")
|
||||
#endif
|
||||
|
|
20
src/main.cpp
20
src/main.cpp
|
@ -1,8 +1,22 @@
|
|||
#include <iostream>
|
||||
#include "conf.hpp"
|
||||
#include "commons.hpp"
|
||||
#include "Game.hpp"
|
||||
#include "Script.hpp"
|
||||
|
||||
int main(int, char**)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::cout << "Duck2D " << DUCK_VERSION << std::endl;
|
||||
d2::Script::init();
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
d2::Script::run(argv[1]);
|
||||
}
|
||||
else if (std::filesystem::exists(std::filesystem::path("main.scm")))
|
||||
{
|
||||
d2::Script::run("main.scm");
|
||||
}
|
||||
|
||||
d2::Script::terminate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue