Skip to content

Commit

Permalink
renderer: primitive text renderer with support for colors
Browse files Browse the repository at this point in the history
  • Loading branch information
pjonnala-eab committed Aug 21, 2015
1 parent 856d006 commit 85843eb
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 1 deletion.
1 change: 1 addition & 0 deletions libopenage/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_subdirectory("testing")
add_subdirectory("unit")
add_subdirectory("util")
add_subdirectory("rng")
add_subdirectory("renderer")

# run codegen, add files to executable
codegen_run()
Expand Down
17 changes: 16 additions & 1 deletion libopenage/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
bind_player_switch(input::action_t::SWITCH_TO_PLAYER_6, 6);
bind_player_switch(input::action_t::SWITCH_TO_PLAYER_7, 7);
bind_player_switch(input::action_t::SWITCH_TO_PLAYER_8, 8);

this->text_renderer.reset(new renderer::TextRenderer());
}

Engine::~Engine() {
Expand Down Expand Up @@ -278,22 +280,28 @@ void Engine::end_game() {
bool Engine::draw_debug_overlay() {
util::col {255, 255, 255, 255}.use();

this->text_renderer->set_color(renderer::Color{255, 0, 0, 255});
// Draw FPS counter in the lower right corner
this->render_text(
{this->engine_coord_data->window_size.x - 100, 15}, 20,
"%.1f fps", this->fps_counter.fps
);

this->text_renderer->set_color(renderer::Color{0, 255, 0, 255});
// Draw version string in the lower left corner
this->render_text(
{5, 35}, 20,
"openage %s", config::version
);

this->text_renderer->set_color(renderer::Color{0, 0, 255, 255});
this->render_text(
{5, 15}, 12,
"%s", config::config_option_string
);

this->text_renderer->set_color(renderer::Color{255, 255, 255, 255});

this->profiler.show(true);

return true;
Expand Down Expand Up @@ -426,6 +434,8 @@ void Engine::loop() {
}
}
}

this->text_renderer->render();
}
glPopMatrix();

Expand Down Expand Up @@ -496,6 +506,10 @@ input::InputManager &Engine::get_input_manager() {
return this->input_manager;
}

renderer::TextRenderer *Engine::get_text_renderer() {
return this->text_renderer.get();
}

int64_t Engine::lastframe_duration_nsec() {
return this->fps_counter.nsec_lastframe;
}
Expand All @@ -514,7 +528,8 @@ void Engine::render_text(coord::window position, size_t size, const char *format
util::vsformat(format, vl, buf);
va_end(vl);

font->render_static(position.x, position.y, buf.c_str());
this->text_renderer->set_font(font);
this->text_renderer->draw(position.x, position.y, buf);
}

void Engine::move_phys_camera(float x, float y, float amount) {
Expand Down
8 changes: 8 additions & 0 deletions libopenage/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "util/fps.h"
#include "util/profiler.h"
#include "screenshot.h"
#include "renderer/text_renderer.h"

namespace openage {

Expand Down Expand Up @@ -213,6 +214,11 @@ class Engine : public ResizeHandler, public options::OptionNode {
*/
input::InputManager &get_input_manager();

/**
* return this engine's text renderer.
*/
renderer::TextRenderer *get_text_renderer();

/**
* return the number of nanoseconds that have passed
* for rendering the last frame.
Expand Down Expand Up @@ -358,6 +364,8 @@ class Engine : public ResizeHandler, public options::OptionNode {
* the engines profiler
*/
util::Profiler profiler;

std::unique_ptr<renderer::TextRenderer> text_renderer;
};

} // namespace openage
Expand Down
4 changes: 4 additions & 0 deletions libopenage/renderer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
add_sources(libopenage
color.cpp
text_renderer.cpp
)
54 changes: 54 additions & 0 deletions libopenage/renderer/color.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#include "color.h"

namespace openage {
namespace renderer {

Color::Color()
:
r{0},
g{0},
b{0},
a{255} {
// Empty
}

Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
:
r{r},
g{g},
b{b},
a{a} {
// Empty
}

Color::Color(const Color &other)
:
r{other.r},
g{other.g},
b{other.b},
a{other.a} {
// Empty
}

Color &Color::operator=(const Color &other) {
if (this != &other) {
this->r = other.r;
this->g = other.g;
this->b = other.b;
this->a = other.a;
}

return *this;
}

bool operator==(const Color &left, const Color &right) {
return left.r == right.r && left.g == right.g && left.b == right.b && left.a == right.a;
}

bool operator!=(const Color &left, const Color &right) {
return !(left == right);
}

}} // openage::renderer
33 changes: 33 additions & 0 deletions libopenage/renderer/color.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#ifndef OPENAGE_RENDERER_COLOR_H_
#define OPENAGE_RENDERER_COLOR_H_

#include <cstdint>

namespace openage {
namespace renderer {

class Color {
public:
Color();

Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);

Color(const Color &other);

Color &operator=(const Color &other);

uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;

};

bool operator==(const Color &left, const Color &right);
bool operator!=(const Color &left, const Color &right);

}} // openage::renderer

#endif
114 changes: 114 additions & 0 deletions libopenage/renderer/text_renderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#include "text_renderer.h"

#include <algorithm>
#include <epoxy/gl.h>

#include "../log/log.h"
#include "../util/strings.h"
#include "../font.h"

namespace openage {
namespace renderer {

TextRenderer::TextRenderer()
:
current_font{nullptr},
current_color{255, 255, 255, 255},
is_dirty{true} {
// Empty
}

TextRenderer::~TextRenderer() {
// Empty
}

void TextRenderer::set_font(openage::Font *font) {
if (this->current_font == font) {
return;
}

this->current_font = font;
this->is_dirty = true;
}

void TextRenderer::set_color(const Color &color) {
if (this->current_color == color) {
return;
}

this->current_color = color;
this->is_dirty = true;
}

void TextRenderer::draw(coord::window position, const char *format, ...) {
std::string text;
va_list vl;
va_start(vl, format);
util::vsformat(format, vl, text);
va_end(vl);

this->draw(position.x, position.y, text);
}

void TextRenderer::draw(coord::window position, const std::string &text) {
this->draw(position.x, position.y, text);
}

void TextRenderer::draw(int x, int y, const std::string &text) {
if (this->is_dirty) {
TextRenderBatch batch;
batch.font = this->current_font;
batch.color = this->current_color;
render_batches.push_back(batch);
this->is_dirty = false;
}

TextRenderBatchPass batch_pass;
batch_pass.x = x;
batch_pass.y = y;
batch_pass.text = text;
render_batches.back().passes.push_back(batch_pass);
}

void TextRenderer::render() {
// Sort the batches by font
std::sort(std::begin(this->render_batches), std::end(this->render_batches),
[](const TextRenderBatch &a, const TextRenderBatch &b) -> bool {
return a.font < b.font;
});

// Merge consecutive batches if font and color values are same
for (auto current_batch = std::begin(this->render_batches); current_batch != std::end(this->render_batches); ) {
auto next_batch = current_batch;
next_batch++;
if (next_batch != std::end(this->render_batches) &&
current_batch->font == next_batch->font &&
current_batch->color == next_batch->color) {
// Merge the render passes of current and next batches and remove the next batch
std::move(std::begin(next_batch->passes),
std::end(next_batch->passes),
std::back_inserter(current_batch->passes));
this->render_batches.erase(next_batch);
} else {
current_batch++;
}
}

// Render all the batches
for (auto &batch : this->render_batches) {
glColor4f(batch.color.r / 255.f,
batch.color.g / 255.f,
batch.color.b / 255.f,
batch.color.a / 255.f);
for (auto &pass : batch.passes) {
batch.font->render_static(pass.x, pass.y, pass.text.c_str());
}
}

// Clear the render batches for next frame
this->render_batches.clear();
}

}} // openage::renderer
56 changes: 56 additions & 0 deletions libopenage/renderer/text_renderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#ifndef OPENAGE_RENDERER_TEXT_RENDERER_H_
#define OPENAGE_RENDERER_TEXT_RENDERER_H_

#include <vector>
#include <string>

#include "../coord/window.h"
#include "color.h"

namespace openage {

class Font;

namespace renderer {

class TextRenderer {

public:
TextRenderer();

virtual ~TextRenderer();

void set_font(Font *font);
void set_color(const Color &color);

void draw(coord::window position, const char *format, ...);
void draw(coord::window position, const std::string &text);
void draw(int x, int y, const std::string &text);

void render();

private:
struct TextRenderBatchPass {
int x;
int y;
std::string text;
};

struct TextRenderBatch {
openage::Font *font;
Color color;
std::vector<TextRenderBatchPass> passes;
};

Font *current_font;
Color current_color;
bool is_dirty;
std::vector<TextRenderBatch> render_batches;

};

}} // openage::renderer

#endif

0 comments on commit 85843eb

Please sign in to comment.