Browse Source

matrixes and stuff

feature/replace-renderer
Martin Dørum 3 years ago
parent
commit
7e12df96b3

+ 77
- 0
include/swan-common/Matrix3.h View File

@@ -0,0 +1,77 @@
#pragma once

#include <iostream>
#include <cmath>
#include <array>

namespace SwanCommon {

template<typename T>
struct Matrix3 {
static constexpr std::array<T, 9> identity = {1, 0, 0, 0, 1, 0, 0, 0, 1};
std::array<T, 9> vals;

constexpr Matrix3(): vals(identity) {}

constexpr T *data() {
return vals.data();
}

constexpr const T *data() const {
return vals.data();
}

constexpr T &at(int x, int y) {
return vals[y * 3 + x];
}

constexpr const T &at(int x, int y) const {
return vals[y * 3 + x];
}

constexpr Matrix3<T> &set(std::initializer_list<T> vals) {
this->vals = vals;
return *this;
}

constexpr Matrix3<T> &reset() {
vals = identity;
return *this;
}

constexpr Matrix3<T> &translate(T x, T y) {
at(2, 0) += x;
at(2, 1) += y;
return *this;
}

constexpr Matrix3<T> &scale(T x, T y) {
at(0, 0) *= x;
at(1, 1) *= y;
return *this;
}

constexpr Matrix3<T> &rotate(T rads) {
T s = std::sin(rads);
T c = std::cos(rads);
at(0, 0) += c;
at(1, 0) -= s;
at(0, 1) += s;
at(1, 1) += c;
return *this;
}

template<typename U>
friend std::ostream &operator<<(std::ostream &os, const Matrix3<U> &mat);
};

template<typename T>
std::ostream &operator<<(std::ostream &os, const Matrix3<T> &mat) {
os << '('
<< '(' << mat.at(0, 0) << ", " << mat.at(1, 0) << ", " << mat.at(2, 0) << "), "
<< '(' << mat.at(0, 1) << ", " << mat.at(1, 1) << ", " << mat.at(2, 1) << "), "
<< '(' << mat.at(0, 2) << ", " << mat.at(1, 2) << ", " << mat.at(2, 2) << "))";
return os;
}

}

+ 0
- 3
libcygnet/include/cygnet/shaders.h View File

@@ -2,10 +2,7 @@

namespace Cygnet::Shaders {

extern const char *basicVx;
extern const char *texturedVx;

extern const char *solidColorFr;
extern const char *texturedFr;

}

+ 5
- 1
libcygnet/include/cygnet/util.h View File

@@ -2,7 +2,8 @@

#include <stdexcept>
#include <stdint.h>
#include <SDL.h>

#include "swan-common/Matrix3.h"

namespace Cygnet {

@@ -11,6 +12,9 @@ using GLint = int32_t;
using GLuint = uint32_t;
using GLsizei = int32_t;
using GLenum = uint32_t;
using GLfloat = float;

using Mat3gf = SwanCommon::Matrix3<GLfloat>;

struct SDLError: public std::exception {
SDLError(std::string msg): message(std::move(msg)) {}

+ 47
- 10
libcygnet/src/Renderer.cc View File

@@ -1,6 +1,9 @@
#include "Renderer.h"

#include <iostream>
#include <stdio.h>
#include <SDL_opengles2.h>
#include <swan-common/constants.h>

#include "shaders.h"
#include "GlWrappers.h"
@@ -12,29 +15,22 @@ namespace Cygnet {
struct TexturedProg: public GlProgram {
using GlProgram::GlProgram;

GLint transform = uniformLoc("camera");
GLint position = attribLoc("position");
GLint texCoord = attribLoc("texCoord");
GLint tex = uniformLoc("tex");
};

struct SolidColorProg: public GlProgram {
using GlProgram::GlProgram;

GLint position = attribLoc("position");
GLint color = uniformLoc("color");
};

struct RendererState {
GlVxShader basicVx{Shaders::basicVx};
GlVxShader texturedVx{Shaders::texturedVx};
GlFrShader solidColorFr{Shaders::solidColorFr};
GlFrShader texturedFr{Shaders::texturedFr};

TexturedProg texturedProg{texturedVx, texturedFr};
SolidColorProg solidColorProg{basicVx, solidColorFr};

TileAtlas atlas;
GlTexture atlasTex;

Mat3gf camera;
};

Renderer::Renderer(): state_(std::make_unique<RendererState>()) {}
@@ -43,6 +39,42 @@ Renderer::~Renderer() = default;

void Renderer::draw() {
state_->texturedProg.use();

float tw = (6 * SwanCommon::TILE_SIZE) / (float)state_->atlasTex.width();
GLfloat vertexes[] = {
-0.5f, 0.5f, // pos 0: top left
0.0f, 0.0f, // tex 0: top left
-0.5f, -0.5f, // pos 1: bottom left
0.0f, 1.0f, // tex 1: bottom left
0.5f, -0.5f, // pos 2: bottom right
tw, 1.0f, // tex 2: bottom right
0.5f, 0.5f, // pos 3: top right
tw, 0.0f, // tex 3: top right
};

GLushort indexes[] = {
0, 1, 2, // top left -> bottom left -> bottom right
2, 3, 0, // bottom right -> top right -> top left
};

state_->camera.translate(0.01, 0);
glUniformMatrix3fv(state_->texturedProg.transform, 1, GL_TRUE, state_->camera.data());
glVertexAttribPointer(state_->texturedProg.position, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), vertexes);
glVertexAttribPointer(state_->texturedProg.texCoord, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), &vertexes[2]);
glCheck();

glEnableVertexAttribArray(state_->texturedProg.position);
glEnableVertexAttribArray(state_->texturedProg.texCoord);
glCheck();

state_->atlasTex.bind();
glUniform1i(state_->texturedProg.tex, 0);
glCheck();

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indexes);
glCheck();
}

void Renderer::registerTileTexture(size_t tileId, const void *data, size_t len) {
@@ -53,6 +85,11 @@ void Renderer::uploadTileTexture() {
size_t w, h;
const unsigned char *data = state_->atlas.getImage(&w, &h);
state_->atlasTex.upload(w, h, (void *)data, GL_RGBA, GL_UNSIGNED_BYTE);
std::cerr << "Uploaded image of size " << w << 'x' << h << '\n';

FILE *f = fopen("lol.rgb", "w");
fwrite(data, 1, w * h * 4, f);
fclose(f);
}

}

+ 9
- 7
libcygnet/src/TileAtlas.cc View File

@@ -2,6 +2,7 @@

#include <iostream>
#include <vector>
#include <algorithm>
#include <SDL_opengles2.h>
#include <stdio.h>
#include <string.h>
@@ -20,7 +21,7 @@ struct AtlasState {
TileAtlas::TileAtlas(): state_(std::make_unique<AtlasState>()) {
GLint size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
state_->tilesPerLine = size / SwanCommon::TILE_SIZE;
state_->tilesPerLine = std::min(size / SwanCommon::TILE_SIZE, 1024);
}

TileAtlas::~TileAtlas() = default;
@@ -30,6 +31,7 @@ void TileAtlas::addTile(size_t tileId, const void *data, size_t len) {
const unsigned char *bytes = (const unsigned char *)data;
size_t x = tileId % state_->tilesPerLine;
size_t y = tileId / state_->tilesPerLine;
std::cerr << "Adding tile " << x << ", " << y << '\n';
if (y >= state_->tilesPerLine) {
std::cerr << "Cygnet: Warning: Tile ID " << tileId << " too big for texture atlas\n";
return;
@@ -43,21 +45,21 @@ void TileAtlas::addTile(size_t tileId, const void *data, size_t len) {
state_->height = y + 1;
}

size_t tileImgSize = SwanCommon::TILE_SIZE * SwanCommon::TILE_SIZE * 4;
size_t requiredSize = (x + 1) * (y + 1) * tileImgSize;
state_->data.resize(requiredSize);
size_t requiredSize = state_->tilesPerLine * SwanCommon::TILE_SIZE *
state_->height * SwanCommon::TILE_SIZE * 4;
state_->data.reserve(requiredSize);

for (size_t ty = 0; ty < rows; ++ty) {
const unsigned char *src = bytes + ty * SwanCommon::TILE_SIZE * 4;
unsigned char *dest = state_->data.data() +
((y + ty) * state_->width * SwanCommon::TILE_SIZE * 4) +
(y * SwanCommon::TILE_SIZE + ty) * state_->tilesPerLine * SwanCommon::TILE_SIZE * 4 +
(x * SwanCommon::TILE_SIZE * 4);
const unsigned char *src = bytes + ty * SwanCommon::TILE_SIZE * 4;
memcpy(dest, src, SwanCommon::TILE_SIZE * 4);
}
}

const unsigned char *TileAtlas::getImage(size_t *w, size_t *h) {
*w = state_->width * SwanCommon::TILE_SIZE;
*w = state_->tilesPerLine * SwanCommon::TILE_SIZE;
*h = state_->height * SwanCommon::TILE_SIZE;
return state_->data.data();
}

+ 2
- 19
libcygnet/src/shaders.cc View File

@@ -2,35 +2,18 @@

namespace Cygnet::Shaders {

const char *basicVx = R"glsl(
uniform mat3 transform;
attribute vec2 position;
void main() {
vec3 pos = transform * vec3(position, 0);
gl_Position = vec4(pos.x, pos.y, 0, 1);
}
)glsl";

const char *texturedVx = R"glsl(
uniform mat3 transform;
uniform mat3 camera;
attribute vec2 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
void main() {
vec3 pos = transform * vec3(position, 0);
vec3 pos = camera * vec3(position, 1);
gl_Position = vec4(pos.x, pos.y, 0, 1);
v_texCoord = texCoord;
}
)glsl";

const char *solidColorFr = R"glsl(
precision mediump float;
uniform vec4 color;
void main() {
gl_FragColor = color;
}
)glsl";

const char *texturedFr = R"glsl(
precision mediump float;
varying vec2 v_texCoord;

+ 1
- 0
libcygnet/src/util.cc View File

@@ -1,5 +1,6 @@
#include "util.h"

#include <SDL.h>
#include <SDL_opengles2.h>

namespace Cygnet {

+ 20
- 7
src/cygnet-test.cc View File

@@ -4,18 +4,31 @@
#include <swan-common/constants.h>

#include <stdint.h>
#include <SDL_image.h>
#include <SDL.h>

void addTile(Cygnet::Renderer &rnd, const char *path) {
static size_t id = 0;
SDL_Surface *surf = IMG_Load(path);
rnd.registerTileTexture(id++, surf->pixels, surf->pitch * surf->h * 4);
SDL_FreeSurface(surf);
}

int main() {
Cygnet::Context ctx;
Cygnet::Window win("Cygnet Test", 640, 480);
IMG_Init(IMG_INIT_PNG);
//Cygnet::Window win("Cygnet Test", 640, 480);
Cygnet::Window win("Cygnet Test", 1280, 256);
Cygnet::Renderer rnd;

uint32_t img[SwanCommon::TILE_SIZE * SwanCommon::TILE_SIZE];
for (size_t i = 0; i < sizeof(img) / sizeof(*img); ++i) {
img[i] = 0xff00aaff;
}
rnd.registerTileTexture(0, img, sizeof(img));
for (auto path: {
"core.mod/assets/tile/dirt.png",
"core.mod/assets/tile/grass.png",
"core.mod/assets/tile/leaves.png",
"core.mod/assets/tile/stone.png",
"core.mod/assets/tile/torch.png",
"core.mod/assets/tile/tree-trunk.png",
}) addTile(rnd, path);
rnd.uploadTileTexture();

while (true) {
@@ -33,5 +46,5 @@ int main() {
}

exit:
;
IMG_Quit();
}

Loading…
Cancel
Save