refactor specific rendering out of gba engine

This commit is contained in:
wgroeneveld 2020-07-11 12:06:40 +02:00
parent ede8465a9b
commit d3bd172d96
14 changed files with 120 additions and 67 deletions

View File

@ -1,11 +1,12 @@
#include <libgba-sprite-engine/scene.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
#include <libgba-sprite-engine/palette/palette_manager.h>
#include "wirescene.h"
int main() {
std::shared_ptr<GBAEngine> engine(new GBAEngine());
engine.get()->setRenderer(new WiredRenderer());
WireScene* startScene = new WireScene(engine);
engine->setScene(startScene);

View File

@ -3,7 +3,7 @@
//
#include <libgba-sprite-engine/gba/tonc_memdef.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
#include <libgba-sprite-engine/background/text_stream.h>
#include "wirescene.h"
@ -20,7 +20,6 @@ Camera WireScene::camera() {
return Camera(VectorFx::fromInt(0, 0, 10), VectorFx::fromInt(0, 0, 0));
}
int msecs = 1;
void WireScene::load() {
foregroundPalette = std::unique_ptr<ForegroundPaletteManager>(new ForegroundPaletteManager());
backgroundPalette = std::unique_ptr<BackgroundPaletteManager>(new BackgroundPaletteManager(pal, sizeof(pal)));
@ -48,26 +47,20 @@ void WireScene::load() {
cube->addFace({ 0, 4, 7});
cube->addFace({ 4, 5, 6});
cube->addFace({ 4, 6, 7});
engine->getTimer()->start();
}
bool wired = true;
void WireScene::tick(u16 keys) {
int curmsecs = engine->getTimer()->getMsecs();
int elapsed = curmsecs - msecs;
msecs = curmsecs;
TextStream::instance().setText(std::to_string(1000 / elapsed) + std::string(" FPS"), 1, 1);
cube->rotate(2, 2);
if(keys & KEY_A) {
cube->resetRotation();
} else if(keys & KEY_B) {
if(cube->isWired()) {
cube->unwire();
wired = !wired;
if(wired) {
engine->setRenderer(new WiredRenderer());
} else {
cube->wire();
engine->setRenderer(new PixelRenderer());
}
}
}

View File

@ -3,13 +3,14 @@
//
#include <libgba-sprite-engine/scene.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
#include <libgba-sprite-engine/palette/palette_manager.h>
#include "monkey.h"
int main() {
std::shared_ptr<GBAEngine> engine(new GBAEngine());
engine.get()->setRenderer(new WiredRenderer());
MonkeyScene* startScene = new MonkeyScene(engine);
engine->setScene(startScene);

View File

@ -17,23 +17,13 @@ Camera MonkeyScene::camera() {
return Camera(VectorFx::fromInt(0, 0, 10), VectorFx::fromInt(0, 0, 0));
}
int msecs = 1;
void MonkeyScene::load() {
foregroundPalette = std::unique_ptr<ForegroundPaletteManager>(new ForegroundPaletteManager());
backgroundPalette = std::unique_ptr<BackgroundPaletteManager>(new BackgroundPaletteManager(pal, sizeof(pal)));
monkey = std::unique_ptr<Mesh>(createMesh());
engine->getTimer()->start();
}
void MonkeyScene::tick(u16 keys) {
int curmsecs = engine->getTimer()->getMsecs();
int elapsed = curmsecs - msecs;
msecs = curmsecs;
int fps = 1000 / elapsed;
TextStream::instance().setText(std::to_string(fps < 0 ? 0 : fps) + std::string(" FPS"), 1, 1);
monkey->rotate(10, 10);
}

View File

@ -8,7 +8,7 @@
#include <libgba-sprite-engine/scene.h>
#include <libgba-sprite-engine/mesh.h>
#include <libgba-sprite-engine/camera.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
#include <memory>
// forward declaration of generated mesh.cpp file

View File

@ -19,7 +19,9 @@ add_library(${PROJECT_NAME}
src/gba/tonc_bios.s
src/gba/tonc_bmp8.cpp
src/background/tonc_font.s
src/gba_engine.cpp
src/renderer/gba_engine.cpp
src/renderer/pixelrenderer.cpp
src/renderer/wirerenderer.cpp
src/math.cpp
src/sound_control.cpp src/scene.cpp src/timer.cpp src/vectorfx.cpp src/mesh.cpp)

View File

@ -20,7 +20,6 @@ private:
VectorFx pos;
VectorFx rot;
u8 cIndex;
bool wired;
std::vector<std::unique_ptr<VectorFx>> verticesArr;
std::vector<Face> facesArr;
@ -41,9 +40,6 @@ public:
inline VectorFx &position() { return pos; }
inline VectorFx &rotation() { return rot; }
inline void wire() { wired = true; }
inline void unwire() { wired = false; }
inline bool isWired() const { return wired; }
inline u8 colorIndex() const { return cIndex; }
inline FIXED rotx() const { return rot.x(); }
inline FIXED roty() const { return rot.y(); }
@ -62,7 +58,7 @@ public:
rot.setY(rot.y() + y);
}
explicit Mesh() : pos(VectorFx()), rot(VectorFx()), cIndex(1), wired(true) {}
explicit Mesh() : pos(VectorFx()), rot(VectorFx()), cIndex(1) {}
Mesh(const Mesh&) = delete;
Mesh& operator=(const Mesh&) = delete;
};

View File

@ -11,9 +11,10 @@
#include <libgba-sprite-engine/vectorfx.h>
#include <libgba-sprite-engine/vectorpx.h>
#include <libgba-sprite-engine/matrixfx.h>
#include "scene.h"
#include "sound_control.h"
#include "timer.h"
#include <libgba-sprite-engine/renderer/renderer.h>
#include "libgba-sprite-engine/scene.h"
#include "libgba-sprite-engine/sound_control.h"
#include "libgba-sprite-engine/timer.h"
const unsigned int black[VRAM_PAGE_SIZE] = {};
@ -25,7 +26,10 @@ private:
Camera currentCamera;
Scene* sceneToTransitionTo;
bool showfps;
void showFPS();
MatrixFx projectionMatrix;
std::unique_ptr<Renderer> renderer;
static std::unique_ptr<Timer> timer;
static std::unique_ptr<SoundControl> activeChannelA;
@ -43,7 +47,6 @@ private:
void render();
void renderClear();
inline VectorPx project(const VectorFx &coord, const MatrixFx &transMat);
void flipPage();
public:
@ -66,9 +69,12 @@ public:
for(int i = 0; i < times; i++){}
}
inline void plotPixel(int x, int y, u8 clrId);
inline void plotPixel(const VectorPx &pixel, u8 clrId);
inline void plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId);
void setRenderer(Renderer* r) { renderer = std::unique_ptr<Renderer>(r); };
VectorPx project(const VectorFx &coord, const MatrixFx &transMat);
void plotPixel(int x, int y, u8 clrId);
void plotPixel(const VectorPx &pixel, u8 clrId);
void plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId);
};

View File

@ -0,0 +1,33 @@
//
// Created by Wouter Groeneveld on 11/07/20.
//
#ifndef GBA_BITMAP_ENGINE_PROJECT_RENDERER_H
#define GBA_BITMAP_ENGINE_PROJECT_RENDERER_H
#include <libgba-sprite-engine/matrixfx.h>
#include <libgba-sprite-engine/mesh.h>
class GBAEngine;
class Renderer {
protected:
std::shared_ptr<GBAEngine> engine;
public:
virtual void render(const MatrixFx &transformationMatrix, const Mesh* mesh) = 0;
};
class PixelRenderer : public Renderer {
public:
void render(const MatrixFx &transformationMatrix, const Mesh* mesh) override;
};
class WiredRenderer : public Renderer {
public:
void render(const MatrixFx &transformationMatrix, const Mesh* mesh) override;
};
#endif //GBA_BITMAP_ENGINE_PROJECT_RENDERER_H

View File

@ -4,7 +4,7 @@
#include <libgba-sprite-engine/gba/tonc_memdef.h>
#include <libgba-sprite-engine/gba/tonc_video.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
#include <cstring>
#include <libgba-sprite-engine/gba/tonc_core.h>
#include <libgba-sprite-engine/matrixfx.h>
@ -16,6 +16,7 @@ std::unique_ptr<SoundControl> GBAEngine::activeChannelB;
std::unique_ptr<Timer> GBAEngine::timer;
u16 *vid_page;
int msecs = 1;
void GBAEngine::vsync() {
while (REG_VCOUNT >= 160);
@ -124,6 +125,7 @@ GBAEngine::GBAEngine() {
REG_SNDDSCNT = 0;
vid_page = vid_mem_back;
projectionMatrix = MatrixFx::perspectiveFovLH(float2fx(0.78), fxdiv(GBA_SCREEN_WIDTH_FX, GBA_SCREEN_HEIGHT_FX), float2fx(0.01), ONE);
showfps = true;
}
void GBAEngine::update() {
@ -135,27 +137,41 @@ void GBAEngine::update() {
// TODO use software interrupt Vsyncing instead of 2 wasteful whiles
vsync();
renderClear();
if(showfps) {
showFPS();
}
currentScene->tick(keys);
render();
flipPage();
}
void GBAEngine::showFPS() {
int curmsecs = getTimer()->getMsecs();
int elapsed = curmsecs - msecs;
int fps = 1000 / elapsed;
msecs = curmsecs;
TextStream::instance().setText(std::to_string(fps > 0 ? fps : 0) + std::string(" FPS"), 1, 1);
}
void GBAEngine::flipPage() {
// toggle the write_buffer's page
vid_page= (COLOR*)((u32)vid_page ^ VRAM_PAGE_SIZE);
REG_DISPCNT ^= DCNT_PAGE;
}
inline void GBAEngine::plotPixel(const VectorPx &pixel, u8 clrId) {
void GBAEngine::plotPixel(const VectorPx &pixel, u8 clrId) {
m4_plot(pixel.x(), pixel.y(), clrId);
}
inline void GBAEngine::plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId) {
void GBAEngine::plotLine(const VectorPx &point0, const VectorPx &point1, u8 clrId) {
// uses tonc's optimalization tricks to get 10 FPS extra compared to standard bline algorithms
m4_line(point0.x(), point0.y(), point1.x(), point1.y(), clrId);
}
inline VectorPx GBAEngine::project(const VectorFx &coord, const MatrixFx &transMat) {
VectorPx GBAEngine::project(const VectorFx &coord, const MatrixFx &transMat) {
auto point = MatrixFx::transformCoordinates(coord, transMat);
auto x = fxmul(point.x(), GBA_SCREEN_WIDTH_FX) + fxdiv(GBA_SCREEN_WIDTH_FX, TWO);
@ -171,28 +187,7 @@ void GBAEngine::render() {
auto worldMatrix = MatrixFx::rotationYawPitchRoll(mesh->roty(), mesh->rotx(), mesh->rotz()) * MatrixFx::translation(mesh->position());
auto transformMatrix = worldMatrix * viewMatrix * projectionMatrix;
if(mesh->isWired()) {
// triangular faces wireframes
for(auto& face : mesh->faces()) {
auto& vertexA = mesh->vertices()[face.a];
auto& vertexB = mesh->vertices()[face.b];
auto& vertexC = mesh->vertices()[face.c];
auto pixelA = project(*vertexA.get(), transformMatrix);
auto pixelB = project(*vertexB.get(), transformMatrix);
auto pixelC = project(*vertexC.get(), transformMatrix);
plotLine(pixelA, pixelB, mesh->colorIndex());
plotLine(pixelB, pixelC, mesh->colorIndex());
plotLine(pixelC, pixelA, mesh->colorIndex());
}
} else {
// pixel-only
for (auto &vertex : mesh->vertices()) {
auto projectedPoint = project(*vertex.get(), transformMatrix);
plotPixel(projectedPoint, mesh->colorIndex());
}
}
renderer->render(transformMatrix, mesh);
}
}
@ -212,6 +207,7 @@ void GBAEngine::setScene(Scene* scene) {
cleanupPreviousScene();
}
scene->load();
getTimer()->start();
auto fgPalette = scene->getForegroundPalette();
fgPalette->persist();

View File

@ -0,0 +1,13 @@
//
// Created by Wouter Groeneveld on 11/07/20.
//
#include <libgba-sprite-engine/renderer/renderer.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
void PixelRenderer::render(const MatrixFx &transformationMatrix, const Mesh* mesh) {
for (auto &vertex : mesh->vertices()) {
auto projectedPoint = engine->project(*vertex.get(), transformationMatrix);
engine->plotPixel(projectedPoint, mesh->colorIndex());
}
}

View File

@ -0,0 +1,22 @@
//
// Created by Wouter Groeneveld on 11/07/20.
//
#include <libgba-sprite-engine/renderer/renderer.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
void WiredRenderer::render(const MatrixFx &transformationMatrix, const Mesh* mesh) {
for (auto &face : mesh->faces()) {
auto &vertexA = mesh->vertices()[face.a];
auto &vertexB = mesh->vertices()[face.b];
auto &vertexC = mesh->vertices()[face.c];
auto pixelA = engine->project(*vertexA.get(), transformationMatrix);
auto pixelB = engine->project(*vertexB.get(), transformationMatrix);
auto pixelC = engine->project(*vertexC.get(), transformationMatrix);
engine->plotLine(pixelA, pixelB, mesh->colorIndex());
engine->plotLine(pixelB, pixelC, mesh->colorIndex());
engine->plotLine(pixelC, pixelA, mesh->colorIndex());
}
}

View File

@ -3,5 +3,5 @@
//
#include <libgba-sprite-engine/scene.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>

View File

@ -8,7 +8,7 @@
#include <libgba-sprite-engine/math.h>
#include <libgba-sprite-engine/mesh.h>
#include <libgba-sprite-engine/camera.h>
#include <libgba-sprite-engine/gba_engine.h>
#include <libgba-sprite-engine/renderer/gba_engine.h>
class MatrixFxSuite : public ::testing::Test {
protected: