aboutsummaryrefslogtreecommitdiff
path: root/src/renderer/Renderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/Renderer.cpp')
-rw-r--r--src/renderer/Renderer.cpp233
1 files changed, 224 insertions, 9 deletions
diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp
index 13f5feb..9217f5c 100644
--- a/src/renderer/Renderer.cpp
+++ b/src/renderer/Renderer.cpp
@@ -1,18 +1,233 @@
#include <renderer/Renderer.hpp>
-#include <renderer/opengl/GlRenderer.hpp>
+#include <GL/glew.h>
+#include <cstdio>
+#include <cstdlib>
-std::unique_ptr<Renderer>
-Renderer::Select(Api api, SDL_Window *window) {
- switch (api) {
- case API_OPENGL: {
- return std::make_unique<GlRenderer>(window);
+
+Renderer::Renderer(SDL_Window *window) : m_Window(window), m_Canvas{}
+{
+}
+
+
+bool
+Renderer::Init()
+{
+ GLenum err = glewInit();
+ if (err) {
+ printf("glewInit() error\n");
+ return false;
+ }
+
+ int32_t window_width;
+ int32_t window_height;
+ if (!SDL_GetWindowSize(m_Window, &window_width, &window_height)) {
+ printf("Error: SDL_GetWindowSize: %s\n", SDL_GetError());
+ return false;
+ }
+
+
+ m_Canvas.rshift = 0;
+ m_Canvas.gshift = 8;
+ m_Canvas.bshift = 16;
+ m_Canvas.ashift = 24;
+ ResizeCanvas(window_width, window_height);
+
+
+ glEnable(GL_TEXTURE_2D);
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenTextures(1, &m_GlTexId);
+ glBindTexture(GL_TEXTURE_2D, m_GlTexId);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+
+ return true;
+}
+
+
+void
+Renderer::ResizeCanvas(int32_t w, int32_t h)
+{
+ size_t realloc_size = (size_t)(w * h) * sizeof(m_Canvas.pixels[0]);
+ void *realloc_data = realloc(m_Canvas.pixels, realloc_size);
+ if (!realloc_data) {
+ printf("could not resize offscreen buffer\n");
+ return;
+ }
+
+ m_Canvas.w = w;
+ m_Canvas.h = h;
+ m_Canvas.pixels = (uint32_t*)realloc_data;
+}
+
+
+void
+Renderer::Draw(RenderGroup& rgroup)
+{
+ rgroup.Sort();
+ REntity_Rectangle clear_rect = {
+ REntityType_Rectangle,
+ 0, 0,
+ (float)(m_Canvas.w-1), (float)(m_Canvas.h-1),
+ 0.0f,
+ rgroup.m_ClearColor
+ };
+ DrawRectangle(rgroup, clear_rect);
+
+
+ float z = -1;
+ for (RSortEntry sort_entry : rgroup.m_RSortEntries) {
+ if (sort_entry.z >= z) {
+ z = sort_entry.z;
+ }
+
+ REntity& entity = rgroup.m_REntities[sort_entry.entity_index];
+ switch (entity.type) {
+ case REntityType_Rectangle: {
+ DrawRectangle(rgroup, entity.rect);
+ } break;
+
+ case REntityType_Bitmap: {
+ Color color = {0.0f, 0.0f, 0.0f, 1.0f};
+ DrawMonoBitmap(entity.bitmap, color);
+ } break;
+
+ default:;
}
- InvalidDefaultCase;
}
- return nullptr;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, m_GlTexId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_Canvas.w, m_Canvas.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Canvas.pixels);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}
-Renderer::~Renderer() {}
+void
+Renderer::DrawRectangle(RenderGroup& rgroup, REntity_Rectangle& rect)
+{
+ int32_t xmin = WorldXToScreenX(rgroup, rect.x0);
+ int32_t ymin = WorldYToScreenY(rgroup, rect.y0);
+ int32_t xmax = WorldXToScreenX(rgroup, rect.x1);
+ int32_t ymax = WorldYToScreenY(rgroup, rect.y1);
+
+ if (xmin < 0) {
+ xmin = 0;
+ }
+ if (ymin < 0) {
+ ymin = 0;
+ }
+ if (xmax >= m_Canvas.w) {
+ xmax = m_Canvas.w - 1;
+ }
+ if (ymax >= m_Canvas.h) {
+ ymax = m_Canvas.h - 1;
+ }
+
+ uint32_t rshift = m_Canvas.rshift;
+ uint32_t gshift = m_Canvas.gshift;
+ uint32_t bshift = m_Canvas.bshift;
+ for (int32_t y = ymin; y <= ymax; ++y) {
+ uint32_t *pixel = m_Canvas.pixels + y * m_Canvas.w + xmin;
+ for (int32_t x = xmin; x <= xmax; ++x) {
+ uint32_t r = (uint32_t)(rect.color.r * 255.0f);
+ uint32_t g = (uint32_t)(rect.color.g * 255.0f);
+ uint32_t b = (uint32_t)(rect.color.b * 255.0f);
+ uint32_t val = r << rshift | g << gshift | b << bshift;
+ *pixel++ = val;
+ }
+ }
+}
+
+
+void
+Renderer::DrawMonoBitmap(REntity_Bitmap& bitmap, Color color)
+{
+ int32_t x0 = (int32_t)bitmap.x;
+ int32_t y0 = (int32_t)bitmap.y;
+ int32_t x1 = (int32_t)bitmap.x + bitmap.w - 1;
+ int32_t y1 = (int32_t)bitmap.y + bitmap.h - 1;
+
+ int32_t cut_left = 0;
+ int32_t cut_bot = 0;
+
+ if (x0 < 0) {
+ cut_left = x0;
+ x0 = 0;
+ }
+ if (y0 < 0) {
+ cut_bot = y0;
+ y0 = 0;
+ }
+ if (x1 >= m_Canvas.w) {
+ x1 = m_Canvas.w - 1;
+ }
+ if (y1 >= m_Canvas.h) {
+ y1 = m_Canvas.h - 1;
+ }
+
+
+ uint32_t rshift = m_Canvas.rshift;
+ uint32_t gshift = m_Canvas.gshift;
+ uint32_t bshift = m_Canvas.bshift;
+
+ uint8_t* grayscale = (uint8_t*)bitmap.data + (-cut_bot * bitmap.w) + (-cut_left);
+ uint32_t* rgba = m_Canvas.pixels + y0 * m_Canvas.w + x0;
+ for (int32_t y = y0; y <= y1; y++) {
+ uint8_t *grayscale_pixels = grayscale;
+ uint32_t *rgba_pixels = rgba;
+ for (int32_t x = x0; x <= x1; x++) {
+ float alpha = *grayscale_pixels / 255.0f;
+
+ // Todo: we do not want to blend with existing color!
+
+ uint32_t rgba_result = *rgba_pixels;
+ float r0 = (rgba_result >> rshift) & 0xff;
+ float g0 = (rgba_result >> gshift) & 0xff;
+ float b0 = (rgba_result >> bshift) & 0xff;
+
+ float r1 = r0 + (color.r - r0)*alpha;
+ float g1 = g0 + (color.g - g0)*alpha;
+ float b1 = b0 + (color.b - b0)*alpha;
+
+ rgba_result = (uint32_t)r1 << rshift | (uint32_t)g1 << gshift | (uint32_t)b1 << bshift;
+ *rgba_pixels = rgba_result;
+
+ grayscale_pixels++;
+ rgba_pixels++;
+ }
+
+ grayscale += bitmap.w;
+ rgba += m_Canvas.w;
+ }
+}
+
+
+int32_t
+Renderer::WorldXToScreenX(RenderGroup& rgroup, float x)
+{
+ float xscreen = (x / rgroup.m_CameraWidth) * (float)rgroup.m_ScreenWidth;
+ return (int32_t)xscreen;
+}
+
+int32_t
+Renderer::WorldYToScreenY(RenderGroup& rgroup, float y)
+{
+ float yscreen = (y / rgroup.m_CameraHeight) * (float)rgroup.m_ScreenHeight;
+ return (int32_t)yscreen;
+}
+