aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/YAGE/camera2d.hpp10
-rw-r--r--include/YAGE/inputmanager.hpp23
-rw-r--r--include/YAGE/spritebatch.hpp67
-rw-r--r--include/YAGE/window.hpp2
-rw-r--r--src/camera2d.cpp6
-rw-r--r--src/inputmanager.cpp24
-rw-r--r--src/sprite.cpp6
-rw-r--r--src/spritebatch.cpp165
-rw-r--r--src/window.cpp13
10 files changed, 267 insertions, 51 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8a7cd709..bbe8a259 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,10 +7,12 @@ set(YAGE_SOURCES
${PROJECT_SOURCE_DIR}/src/camera2d.cpp
${PROJECT_SOURCE_DIR}/src/glslprogram.cpp
${PROJECT_SOURCE_DIR}/src/imageloader.cpp
+ ${PROJECT_SOURCE_DIR}/src/inputmanager.cpp
${PROJECT_SOURCE_DIR}/src/iomanager.cpp
${PROJECT_SOURCE_DIR}/src/picopng.cpp
${PROJECT_SOURCE_DIR}/src/resourcemanager.cpp
${PROJECT_SOURCE_DIR}/src/sprite.cpp
+ ${PROJECT_SOURCE_DIR}/src/spritebatch.cpp
${PROJECT_SOURCE_DIR}/src/texturecache.cpp
${PROJECT_SOURCE_DIR}/src/window.cpp)
diff --git a/include/YAGE/camera2d.hpp b/include/YAGE/camera2d.hpp
index 030b0a37..0c86fc31 100644
--- a/include/YAGE/camera2d.hpp
+++ b/include/YAGE/camera2d.hpp
@@ -9,21 +9,23 @@ namespace yage
class Camera2D
{
+ // member variables
private:
bool matrix_needs_update_=true;
float scale_=1.f;
glm::vec2 position_;
glm::mat4 camera_matrix_;
glm::mat4 ortho_matrix_;
+
+ // member functions
public:
Camera2D(int screen_width=1280, int screen_height=720);
virtual ~Camera2D();
+ // update camera location
void update();
-
- // setters
- void setPosition(const glm::vec2 &new_position) { position_=new_position; matrix_needs_update_=true; }
- void setScale(float new_scale) {scale_=new_scale; matrix_needs_update_=true; }
+ // camera movement
+ void move(const glm::vec2 &direction);
// getters
float getScale() { return scale_; }
diff --git a/include/YAGE/inputmanager.hpp b/include/YAGE/inputmanager.hpp
new file mode 100644
index 00000000..7f49c3b3
--- /dev/null
+++ b/include/YAGE/inputmanager.hpp
@@ -0,0 +1,23 @@
+#ifndef INPUT_MANAGER_HPP
+#define INPUT_MANAGER_HPP
+
+#include <unordered_map>
+
+namespace yage
+{
+
+class InputManager
+{
+ // member variables
+private:
+ std::unordered_map<unsigned, bool> key_map_;
+
+ // member functions
+public:
+ void keyPressed(unsigned key);
+ void keyReleased(unsigned key);
+ bool isKeyPressed(unsigned key) const;
+};
+
+}
+#endif
diff --git a/include/YAGE/spritebatch.hpp b/include/YAGE/spritebatch.hpp
index fcc6faec..3f40a009 100644
--- a/include/YAGE/spritebatch.hpp
+++ b/include/YAGE/spritebatch.hpp
@@ -11,39 +11,76 @@
namespace yage
{
-struct Glyph
+class Glyph
{
- GLuint texture;
- float depth;
-
- Vertex top_left;
- Vertex top_right;
- Vertex bottom_right;
- Vertex bottom_left;
+ // member variables
+private:
+ GLuint texture_;
+ float depth_;
+ Vertex top_left_;
+ Vertex top_right_;
+ Vertex bottom_right_;
+ Vertex bottom_left_;
+
+ // member functions
+public:
+ Glyph(GLuint texture, float depth, const Vertex &top_left, const Vertex &top_right, const Vertex &bottom_right, const Vertex &bottom_left);
+
+ inline GLuint texture() const { return texture_; }
+ inline float depth() const { return depth_; }
+ inline Vertex top_left() const { return top_left_; }
+ inline Vertex top_right() const { return top_right_; }
+ inline Vertex bottom_right() const { return bottom_right_; }
+ inline Vertex bottom_left() const { return bottom_left_; }
+};
+
+class RenderBatch
+{
+ // member variables
+public:
+ GLint offset_;
+private:
+ GLsizei num_vertices_;
+ GLuint texture_;
+
+ // member functions
+public:
+ RenderBatch(GLint offset, GLsizei num_vertices, GLuint texture);
+
+ // getters
+ inline GLint offset() const { return offset_; }
+ inline GLsizei num_vertices() const { return num_vertices_; }
+ inline GLuint texture() const { return texture_; }
};
class SpriteBatch
{
-public: // member variables
+ // member variables
+public:
+ static const int NUM_VERTICES=6;
private:
GLuint vbo_=0;
GLuint vao_=0;
-
std::vector<Glyph> glyphs_;
std::vector<Glyph *> glyph_ptrs_;
-
-public: // member functions
+ std::vector<RenderBatch> render_batches_;
+
+ // member functions
+public:
SpriteBatch();
~SpriteBatch();
+ // initialize vaos and vbos
+ void init();
void begin();
void end();
-
+ // adds a sprite to the sprite batch to be rendered later
void draw(const glm::vec4 &destination_rect, const glm::vec4 &uv_rect, GLuint texture, const Color &color, float depth);
-
- void renderBatch();
+ // render the batch
+ void render();
private:
void createVertexArray();
+ void createRenderBatches();
void sortGlyphs();
};
diff --git a/include/YAGE/window.hpp b/include/YAGE/window.hpp
index 5f104912..d86c00ac 100644
--- a/include/YAGE/window.hpp
+++ b/include/YAGE/window.hpp
@@ -34,6 +34,8 @@ public: // member functions
void create(const std::string &window_name, int width, int height, unsigned flags=WindowFlags::SHOWN);
// swap the buffer
void swapBuffer();
+ // clear buffer
+ void clearBuffer();
private:
};
diff --git a/src/camera2d.cpp b/src/camera2d.cpp
index 5dd25bb3..75bbe9c6 100644
--- a/src/camera2d.cpp
+++ b/src/camera2d.cpp
@@ -26,4 +26,10 @@ void Camera2D::update()
}
}
+void Camera2D::move(const glm::vec2 &direction)
+{
+ position_+=direction;
+ matrix_needs_update_=true;
+}
+
} // yage
diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp
new file mode 100644
index 00000000..0bcb35f8
--- /dev/null
+++ b/src/inputmanager.cpp
@@ -0,0 +1,24 @@
+#include "inputmanager.hpp"
+
+namespace yage
+{
+
+void InputManager::keyPressed(unsigned key)
+{
+ key_map_[key]=true;
+}
+
+void InputManager::keyReleased(unsigned key)
+{
+ key_map_[key]=false;
+}
+
+bool InputManager::isKeyPressed(unsigned key) const
+{
+ auto key_index=key_map_.find(key);
+ if(key_index!=key_map_.end())
+ return key_index->second;
+ return false;
+}
+
+}
diff --git a/src/sprite.cpp b/src/sprite.cpp
index 941a680d..010b43a7 100644
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -62,14 +62,20 @@ void Sprite::draw()
{
glBindTexture(GL_TEXTURE_2D, texture_.id);
glBindBuffer(GL_ARRAY_BUFFER, vbo_id_);
+
glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, position));
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, color));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, uv));
glDrawArrays(GL_TRIANGLES, 0, 6);
+ glDisableVertexAttribArray(2);
+ glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
+
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
diff --git a/src/spritebatch.cpp b/src/spritebatch.cpp
index 1abcc567..8a08ea86 100644
--- a/src/spritebatch.cpp
+++ b/src/spritebatch.cpp
@@ -1,14 +1,30 @@
#include "spritebatch.hpp"
#include <algorithm>
+#include <stdexcept>
namespace yage
{
+const int SpriteBatch::NUM_VERTICES;
+
+Glyph::Glyph(GLuint texture, float depth, const Vertex &top_left, const Vertex &top_right, const Vertex &bottom_right, const Vertex &bottom_left) :
+ texture_(texture),
+ depth_(depth),
+ top_left_(top_left),
+ top_right_(top_right),
+ bottom_right_(bottom_right),
+ bottom_left_(bottom_left)
+{}
+
+RenderBatch::RenderBatch(GLint offset, GLsizei num_vertices, GLuint texture) :
+ offset_(offset),
+ num_vertices_(num_vertices),
+ texture_(texture)
+{}
+
SpriteBatch::SpriteBatch()
-{
- createVertexArray();
-}
+{}
SpriteBatch::~SpriteBatch()
{
@@ -19,48 +35,135 @@ SpriteBatch::~SpriteBatch()
glDeleteVertexArrays(1, &vbo_);
}
+void SpriteBatch::init()
+{
+ createVertexArray();
+}
+
void SpriteBatch::begin()
-{}
+{
+ glyphs_.clear();
+ glyph_ptrs_.clear();
+ render_batches_.clear();
+}
void SpriteBatch::end()
-{}
+{
+ sortGlyphs();
+ createRenderBatches();
+}
void SpriteBatch::draw(const glm::vec4 &destination_rect, const glm::vec4 &uv_rect, GLuint texture, const Color &color, float depth)
{
- Glyph new_glyph;
- new_glyph.texture=texture;
- new_glyph.depth=depth;
-
- new_glyph.top_left.color=color;
- new_glyph.top_left.setPosition(destination_rect.x, destination_rect.y+destination_rect.w);
- new_glyph.top_left.setUv(uv_rect.x, uv_rect.y+uv_rect.w);
-
- new_glyph.top_right.color=color;
- new_glyph.top_right.setPosition(destination_rect.x+destination_rect.z, destination_rect.y+destination_rect.w);
- new_glyph.top_right.setUv(uv_rect.x+uv_rect.z, uv_rect.y+uv_rect.w);
-
- new_glyph.bottom_right.color=color;
- new_glyph.bottom_right.setPosition(destination_rect.x+destination_rect.z, destination_rect.y);
- new_glyph.bottom_right.setUv(uv_rect.x+uv_rect.z, uv_rect.y);
+ Vertex top_left, top_right, bottom_right, bottom_left;
+
+ top_left.color=color;
+ top_left.setPosition(destination_rect.x, destination_rect.y+destination_rect.w);
+ top_left.setUv(uv_rect.x, uv_rect.y+uv_rect.w);
+
+ top_right.color=color;
+ top_right.setPosition(destination_rect.x+destination_rect.z, destination_rect.y+destination_rect.w);
+ top_right.setUv(uv_rect.x+uv_rect.z, uv_rect.y+uv_rect.w);
+
+ bottom_right.color=color;
+ bottom_right.setPosition(destination_rect.x+destination_rect.z, destination_rect.y);
+ bottom_right.setUv(uv_rect.x+uv_rect.z, uv_rect.y);
+
+ bottom_left.color=color;
+ bottom_left.setPosition(destination_rect.x, destination_rect.y);
+ bottom_left.setUv(uv_rect.x, uv_rect.y);
+
+ // deal with fragmenting by creating vector of pointers
+ glyphs_.emplace_back(texture, depth, top_left, top_right, bottom_right, bottom_left);
+ glyph_ptrs_.push_back(&glyphs_.back());
+}
- new_glyph.bottom_right.color=color;
- new_glyph.bottom_right.setPosition(destination_rect.x, destination_rect.y);
- new_glyph.bottom_right.setUv(uv_rect.x, uv_rect.y);
+void SpriteBatch::render()
+{
+ glBindVertexArray(vao_);
+ for(auto &&batch : render_batches_)
+ {
+ glBindTexture(GL_TEXTURE_2D, batch.texture());
+ glDrawArrays(GL_TRIANGLES, batch.offset(), batch.num_vertices());
+ }
+ glBindVertexArray(0);
+}
- // deal with fragmenting
- glyphs_.push_back(new_glyph);
- glyph_ptrs_.push_back(&glyphs_.back());
+void SpriteBatch::createVertexArray()
+{
+ if(vao_==0)
+ {
+ glGenVertexArrays(1, &vao_);
+ if(vao_==0)
+ throw std::runtime_error("glGenVertexArrays failed");
+ }
+ // bind vertex array object
+ glBindVertexArray(vao_);
+
+ if(vbo_==0)
+ {
+ glGenBuffers(1, &vbo_);
+ if(vbo_==0)
+ throw std::runtime_error("glGenBuffers failed");
+ }
+ // bind vertex buffer object
+ glBindBuffer(GL_ARRAY_BUFFER, vbo_);
+
+ // enable vertex attribute arrays
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glEnableVertexAttribArray(2);
+
+ // set the vertex attribute pointers
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, position));
+ glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void *)offsetof(Vertex, color));
+ glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)offsetof(Vertex, uv));
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+
+ // unbind vertex array object
+ glBindVertexArray(0);
}
-void SpriteBatch::renderBatch()
-{}
+void SpriteBatch::createRenderBatches()
+{
+ std::vector<Vertex> vertices;
+ if(glyph_ptrs_.empty())
+ return;
+
+ render_batches_.reserve(glyph_ptrs_.size()*NUM_VERTICES);
+
+ for(int i=0; i<(int)glyph_ptrs_.size(); ++i)
+ {
+ if(i==0 || (i>0 && (glyph_ptrs_[i]->texture()!=glyph_ptrs_[i-1]->texture())))
+ render_batches_.emplace_back(i*NUM_VERTICES, NUM_VERTICES, glyph_ptrs_[i]->texture());
+ else
+ render_batches_.back().offset_+=NUM_VERTICES;
+
+ vertices.push_back(glyph_ptrs_[i]->bottom_left());
+ vertices.push_back(glyph_ptrs_[i]->top_left());
+ vertices.push_back(glyph_ptrs_[i]->top_right());
+ vertices.push_back(glyph_ptrs_[i]->bottom_left());
+ vertices.push_back(glyph_ptrs_[i]->bottom_right());
+ vertices.push_back(glyph_ptrs_[i]->top_right());
+
+ // bind vbo
+ glBindBuffer(GL_ARRAY_BUFFER, vbo_);
+ // orphan the buffer
+ glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), nullptr, GL_DYNAMIC_DRAW);
+ // upload the data
+ glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vertex), vertices.data());
+ // unbind buffer
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+}
void SpriteBatch::sortGlyphs()
{
+ // sort using introsort or quicksort
std::sort(glyph_ptrs_.begin(), glyph_ptrs_.end(), [] (Glyph *a, Glyph *b)->bool {
- if(a->depth==b->depth)
- return a->texture<b->texture;
- return a->depth<b->depth;
+ if(a->depth()==b->depth())
+ return a->texture()<b->texture();
+ return a->depth()<b->depth();
});
}
diff --git a/src/window.cpp b/src/window.cpp
index ac2304c9..dc2a743a 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -58,7 +58,10 @@ void Window::create(const std::string &window_name, int width, int height, unsig
// set vsync on instead of custom fps limiting
SDL_GL_SetSwapInterval(1);
// set the clear color to black
- glClearColor(0.f, 0.f, 0.f, 1.f);
+ glClearColor(0.f, 0.5f, 0.f, 1.f);
+ // set alpha blending
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Window::swapBuffer()
@@ -66,5 +69,13 @@ void Window::swapBuffer()
// swap the window buffer
SDL_GL_SwapWindow(window_);
}
+
+void Window::clearBuffer()
+{
+ // set the clear depth
+ glClearDepth(1.f);
+ // clears buffer with clear color
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
} // yage