std::array<T, 9> vals; | std::array<T, 9> vals; | ||||
constexpr Matrix3(): vals(identity) {} | constexpr Matrix3(): vals(identity) {} | ||||
constexpr Matrix3(const Matrix3 &mat): vals(mat.vals) {} | |||||
constexpr Matrix3 &operator=(const Matrix3 &mat) { vals = mat.vals; } | |||||
constexpr T *data() { | constexpr T *data() { | ||||
return vals.data(); | return vals.data(); |
struct RendererState; | struct RendererState; | ||||
struct RenderSprite { | |||||
GLuint tex; | |||||
}; | |||||
struct RenderChunk { | struct RenderChunk { | ||||
GLuint tex; | GLuint tex; | ||||
}; | }; | ||||
Renderer(); | Renderer(); | ||||
~Renderer(); | ~Renderer(); | ||||
void drawChunk(SwanCommon::Vec2 pos, RenderChunk chunk); | |||||
void drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos); | |||||
void drawSprite(RenderSprite sprite, Mat3gf mat); | |||||
void drawSprite(RenderSprite sprite, SwanCommon::Vec2 pos); | |||||
void drawSpriteFlipped(RenderSprite chunk, SwanCommon::Vec2 pos); | |||||
void draw(const RenderCamera &cam); | void draw(const RenderCamera &cam); | ||||
void modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id); | void modifyChunk(RenderChunk chunk, SwanCommon::Vec2i pos, TileID id); | ||||
void destroyChunk(RenderChunk chunk); | void destroyChunk(RenderChunk chunk); | ||||
RenderSprite createSprite(uint8_t *rgb, int width, int height); | |||||
void destroySprite(RenderSprite sprite); | |||||
private: | private: | ||||
std::unique_ptr<RendererState> state_; | std::unique_ptr<RendererState> state_; | ||||
std::vector<std::pair<SwanCommon::Vec2, RenderChunk>> draw_chunks_; | std::vector<std::pair<SwanCommon::Vec2, RenderChunk>> draw_chunks_; | ||||
std::vector<std::pair<Mat3gf, RenderSprite>> draw_sprites_; | |||||
}; | }; | ||||
inline void Renderer::drawChunk(SwanCommon::Vec2 pos, RenderChunk chunk) { | |||||
inline void Renderer::drawChunk(RenderChunk chunk, SwanCommon::Vec2 pos) { | |||||
draw_chunks_.emplace_back(pos, chunk); | draw_chunks_.emplace_back(pos, chunk); | ||||
} | } | ||||
inline void Renderer::drawSprite(RenderSprite sprite, Mat3gf mat) { | |||||
draw_sprites_.emplace_back(mat, sprite); | |||||
} | |||||
inline void Renderer::drawSprite(RenderSprite sprite, SwanCommon::Vec2 pos) { | |||||
draw_sprites_.emplace_back(Mat3gf{}.translate(pos), sprite); | |||||
} | |||||
inline void Renderer::drawSpriteFlipped(RenderSprite sprite, SwanCommon::Vec2 pos) { | |||||
draw_sprites_.emplace_back(Mat3gf{}.translate(pos).scale({ -1, 1 }), sprite); | |||||
} | |||||
} | } |
void Renderer::draw(const RenderCamera &cam) { | void Renderer::draw(const RenderCamera &cam) { | ||||
Mat3gf camMat; | Mat3gf camMat; | ||||
camMat.translate(cam.pos.scale(-1, 1) * cam.zoom); // TODO: Change something to make this -cam.pos | |||||
camMat.scale({ cam.zoom * ((float)cam.size.y / (float)cam.size.x), cam.zoom }); | |||||
float ratio = (float)cam.size.y / (float)cam.size.x; | |||||
camMat.translate(cam.pos.scale(-ratio, 1) * cam.zoom); // TODO: Change something to make this -cam.pos | |||||
camMat.scale({ cam.zoom * ratio, cam.zoom }); | |||||
auto &chunkProg = state_->chunkProg; | auto &chunkProg = state_->chunkProg; | ||||
chunkProg.enable(); | chunkProg.enable(); | ||||
RenderChunk chunk; | RenderChunk chunk; | ||||
glGenTextures(1, &chunk.tex); | glGenTextures(1, &chunk.tex); | ||||
glCheck(); | glCheck(); | ||||
glActiveTexture(GL_TEXTURE0); | glActiveTexture(GL_TEXTURE0); | ||||
glBindTexture(GL_TEXTURE_2D, chunk.tex); | glBindTexture(GL_TEXTURE_2D, chunk.tex); | ||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | ||||
glDeleteTextures(1, &chunk.tex); | glDeleteTextures(1, &chunk.tex); | ||||
} | } | ||||
RenderSprite createSprite(uint8_t *rgb, int width, int height) { | |||||
RenderSprite sprite; | |||||
glGenTextures(1, &sprite.tex); | |||||
glCheck(); | |||||
glActiveTexture(GL_TEXTURE0); | |||||
glBindTexture(GL_TEXTURE_2D, sprite.tex); | |||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |||||
glCheck(); | |||||
glTexImage2D( | |||||
GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, | |||||
width, height, | |||||
0, GL_RGBA, GL_UNSIGNED_BYTE, rgb); | |||||
return sprite; | |||||
} | |||||
void Renderer::destroySprite(RenderSprite sprite) { | |||||
glDeleteTextures(1, &sprite.tex); | |||||
} | |||||
} | } |
} | } | ||||
lol += 1 * dt; | lol += 1 * dt; | ||||
rnd.modifyChunk(chunk, {0, 0}, (int)lol % 6); | |||||
rnd.modifyChunk(chunk, {4, 4}, ((int)(lol / 2) + 3) % 6); | |||||
rnd.modifyChunk(chunk, {3, 2}, ((int)(lol * 1.5) + 7) % 6); | |||||
rnd.modifyChunk(chunk, { 0, 0 }, (int)lol % 6); | |||||
rnd.modifyChunk(chunk, { 4, 4 }, ((int)(lol / 2) + 3) % 6); | |||||
rnd.modifyChunk(chunk, { 3, 2 }, ((int)(lol * 1.5) + 7) % 6); | |||||
rnd.drawChunk({0, 0}, chunk); | |||||
rnd.drawChunk(chunk, { 0, 0 }); | |||||
win.clear(); | win.clear(); | ||||
rnd.draw(cam); | rnd.draw(cam); |