Skip to content

Commit

Permalink
Draw white triangle with game engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Cliche committed May 27, 2024
1 parent c1d3a5e commit d0b72e2
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 28 deletions.
2 changes: 1 addition & 1 deletion soc/src/examples/game/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS))

# The -MMD and -MP flags together generate Makefiles for us!
# These files will have .d instead of .o as the output.
CPPFLAGS := $(INC_FLAGS) -MMD -MP -g
CPPFLAGS := $(INC_FLAGS) -MMD -MP -g -DRV_FIXED_POINT_EXTENSION=1

all: $(BUILD_DIR)/program.hex

Expand Down
206 changes: 194 additions & 12 deletions soc/src/examples/game/src/GameEngine/GL.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include "GL.h"

#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define OP_SET_X0 0
#define OP_SET_Y0 1
Expand Down Expand Up @@ -42,6 +45,22 @@ struct Command {
uint32_t param : 24;
};

struct Buffer {
GLuint name;
void *data;
struct Buffer *next;
};

struct Context {
GLclampx clear_color_r, clear_color_g, clear_color_b, clear_color_a;
GLint viewport_x, viewport_y;
GLsizei viewport_width, viewport_height;
struct Buffer *buffers;
struct Buffer *current_buffer;
};

struct Context ctx = {0};

static void send_command(struct Command *cmd)
{
while (!MEM_READ(GRAPHITE));
Expand Down Expand Up @@ -208,25 +227,188 @@ void xd_draw_triangle(vec3d p[3], vec2d t[3], vec3d c[3], texture_t* tex, bool c
send_command(&cmd);
}

void GL_clear(unsigned int color)
void gglSwap(GLboolean vsync)
{
struct Command cmd;

// Clear framebuffer
cmd.opcode = OP_CLEAR;
cmd.param = color;
send_command(&cmd);
// Clear depth buffer
cmd.opcode = OP_CLEAR;
cmd.param = 0x010000;
cmd.opcode = OP_SWAP;
cmd.param = vsync ? 0x1 : 0x0;
send_command(&cmd);
}

void GL_swap(bool vsync)
void glBindBuffer(GLenum target, GLuint buffer)
{
bool found = false;
struct Buffer *b = ctx.buffers;
while (b != NULL) {
if (b->name == buffer) {
ctx.current_buffer = b;
found = true;
break;
}
b = b->next;
}
if (!found) {
fprintf(stderr, "glBindBuffer: buffer named %d not found\n", buffer);
} else {
//printf("glBindBuffer: buffer named %d bound\n", buffer);
}
}

void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
{
if (data != NULL) {
ctx.current_buffer->data = malloc(size);
memcpy(ctx.current_buffer->data, data, size);
} else {
ctx.current_buffer->data = NULL;
}
}

void glClear(GLbitfield mask)
{
struct Command cmd;

cmd.opcode = OP_SWAP;
cmd.param = vsync ? 0x1 : 0x0;
send_command(&cmd);
if (mask & GL_COLOR_BUFFER_BIT) {
// Clear framebuffer

unsigned int r = INT(MUL(ctx.clear_color_r, FX(15)));
unsigned int g = INT(MUL(ctx.clear_color_g, FX(15)));
unsigned int b = INT(MUL(ctx.clear_color_b, FX(15)));
unsigned int a = INT(MUL(ctx.clear_color_a, FX(15)));
uint32_t color = (a << 12) | (r << 8) | (g << 4) | b;

cmd.opcode = OP_CLEAR;
cmd.param = color;
send_command(&cmd);
}
if (mask & GL_DEPTH_BUFFER_BIT) {
// Clear depth buffer
cmd.opcode = OP_CLEAR;
cmd.param = 0x010000;
send_command(&cmd);
}
}

void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha)
{
ctx.clear_color_r = red;
ctx.clear_color_g = green;
ctx.clear_color_b = blue;
ctx.clear_color_a = alpha;
}

static void deleteBuffer(GLuint name)
{
struct Buffer *b = ctx.buffers, *pb = NULL;
while (b != NULL) {
if (b->name == name) {
if (pb != NULL) {
pb->next = b->next;
} else {
ctx.buffers = b->next;
}
if (b->data)
free(b->data);
free(b);
break;
}
pb = b;
b = b->next;
}
}

void glDeleteBuffers(GLsizei n, const GLuint *buffers)
{
for (GLsizei i = 0; i < n; ++i)
deleteBuffer(buffers[i]);
}

static void drawTriangle(fx32 v[9])
{
vec3d vertices[3];
vertices[0] = (vec3d){v[0], v[1], v[2], FX(1.0f)};
vertices[1] = (vec3d){v[3], v[4], v[5], FX(1.0f)};
vertices[2] = (vec3d){v[6], v[7], v[8], FX(1.0f)};

vec3d vec_camera = {
FX(0.0f), FX(0.0f), FX(0.0f), FX(1.0f)
};

face_t face = {0};
face.indices[0] = 0;
face.indices[1] = 1;
face.indices[2] = 2;

triangle_t triangles_to_raster[2];

model_t model = {0};
model.mesh.nb_vertices = 9;
model.mesh.nb_faces = 1;
model.mesh.vertices = vertices;
model.mesh.faces = &face;
model.triangles_to_raster = triangles_to_raster;

//mat4x4 mat_proj = matrix_make_projection(ctx.viewport_width, ctx.viewport_height, 60.0f);
mat4x4 mat_proj = matrix_make_identity();
mat4x4 mat_world = matrix_make_identity();
mat4x4 mat_view = matrix_make_identity();

draw_model(ctx.viewport_width, ctx.viewport_height, &vec_camera, &model, &mat_world, NULL, &mat_proj, &mat_view, NULL, 0, false, NULL, false, false, 0, 0, false);
}

void glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
struct Buffer *b = ctx.current_buffer;
if (b != NULL) {
if (b->data != NULL) {
GLfixed *d = b->data;
d += first;
for (GLsizei i = 0; i < count / 3; ++i) {
//printf("glDrawArrays: draw triangle (%x,%x,%x), (%x,%x,%x), (%x,%x,%x)\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]);
drawTriangle((fx32 *)d);
d += 9;
}
} else {
printf("glDrawArrays: no data\n");
}
} else {
fprintf(stderr, "glDrawArrays: no bound buffer\n");
}
}

static GLuint genBuffer()
{
struct Buffer *b = ctx.buffers, *pb = NULL;
GLuint name = 1;
while (b != NULL) {
if (b->name > name)
name = b->name + 1;
pb = b;
b = b->next;
}
struct Buffer *nb = malloc(sizeof(struct Buffer));
nb->name = name;
nb->data = NULL;
nb->next = NULL;
if (pb == NULL) {
ctx.buffers = nb;
} else {
pb->next = nb;
}
return name;
}

void glGenBuffers(GLsizei n, GLuint *buffers)
{
for (GLsizei i = 0; i < n; ++i)
buffers[i] = genBuffer();
}

void glViewport(int left, int top, int width, int height)
{
ctx.viewport_x = left;
ctx.viewport_y = top;
ctx.viewport_width = width;
ctx.viewport_height = height;
}
31 changes: 29 additions & 2 deletions soc/src/examples/game/src/GameEngine/GL.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,39 @@

#include <graphite.h>

typedef unsigned int GLenum;
typedef int GLfixed;
typedef unsigned int GLuint;
typedef size_t GLsizeiptr;
typedef unsigned int GLbitfield;
typedef int GLint;
typedef unsigned char GLboolean;
typedef int GLsizei;
typedef int GLclampx;

#define GL_DEPTH_BUFFER_BIT 0x00000100
#define GL_COLOR_BUFFER_BIT 0x00004000
#define GL_FALSE 0
#define GL_TRUE 1
#define GL_TRIANGLES 0x0004
#define GL_ARRAY_BUFFER 0x8892
#define GL_STATIC_DRAW 0x88E4

#ifdef __cplusplus
extern "C" {
#endif

void GL_clear(unsigned int color);
void GL_swap(bool vsync);
// Graphite extension
void gglSwap(GLboolean vsync);

void glBindBuffer(GLenum target, GLuint buffer);
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
void glClear(GLbitfield mask);
void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha);
void glDeleteBuffers(GLsizei n, const GLuint *buffers);
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
void glGenBuffers(GLsizei n, GLuint *buffers);
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

#ifdef __cplusplus
}
Expand Down
28 changes: 26 additions & 2 deletions soc/src/examples/game/src/GameEngine/Game.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Game.h"
#include "GraphicsEngine.h"
#include "Window.h"
#include "VertexArrayObject.h"

#include "SDL2/SDL.h"

Expand All @@ -9,17 +10,40 @@ Game::Game() {
m_display = std::make_unique<Window>();

m_display->makeCurrentContext();

m_graphicsEngine->setViewport(m_display->getInnerSize());
}

Game::~Game() {
}

void Game::onCreate() {
/*
const fx32 triangleVertices[] = {
FX(-0.5f), FX(-0.5f), FX(0.0f),
FX(0.5f), FX(-0.5f), FX(0.0f),
FX(0.0f), FX(0.5f), FX(0.0f)
};
*/

const fx32 triangleVertices[] = {
FX(-0.5f), FX(-0.5f), FX(15.0f),
FX(0.0f), FX(0.5f), FX(15.0f),
FX(0.5f), FX(-0.5f), FX(15.0f)
};

m_trianglesVAO = m_graphicsEngine->createVertexArrayObject({
(void*)triangleVertices,
sizeof(fx32)*3,
3
});
}

void Game::onUpdate() {
m_graphicsEngine->clear({FX(1.0f), FX(0.0f), FX(0.0f), FX(1.0f)});
m_display->present(false);
m_graphicsEngine->clear(Vec4(FX(1.0f), FX(0.0f), FX(0.0f), FX(1.0f)));
m_graphicsEngine->setVertexArrayObject(m_trianglesVAO);
m_graphicsEngine->drawTriangles(m_trianglesVAO->getVertexBufferSize(), 0);
m_display->present(true);
}

void Game::onQuit() {
Expand Down
4 changes: 4 additions & 0 deletions soc/src/examples/game/src/GameEngine/Game.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once
#include <memory>

#include "VertexArrayObject.h"

class GraphicsEngine;
class Window;
class Game {
Expand All @@ -19,4 +21,6 @@ class Game {
bool m_isRunning = true;
std::unique_ptr<GraphicsEngine> m_graphicsEngine;
std::unique_ptr<Window> m_display;

VertexArrayObjectPtr m_trianglesVAO;
};
29 changes: 23 additions & 6 deletions soc/src/examples/game/src/GameEngine/GraphicsEngine.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "GraphicsEngine.h"
#include "VertexArrayObject.h"

#include "GL.h"
#include <stdexcept>

GraphicsEngine::GraphicsEngine() {
Expand All @@ -8,10 +10,25 @@ GraphicsEngine::GraphicsEngine() {
GraphicsEngine::~GraphicsEngine() {
}

void GraphicsEngine::clear(const vec3d& color) {
unsigned int r = INT(MUL(color.x, FX(15)));
unsigned int g = INT(MUL(color.y, FX(15)));
unsigned int b = INT(MUL(color.z, FX(15)));
unsigned int a = INT(MUL(color.w, FX(15)));
GL_clear((a << 12) | (r << 8) | (g << 4) | b);
VertexArrayObjectPtr GraphicsEngine::createVertexArrayObject(const VertexBufferData& data) {
return std::make_shared<VertexArrayObject>(data);
}

void GraphicsEngine::clear(const Vec4& color) {
glClearColorx(color.x(), color.y(), color.z(), color.w());
//glClear(GL_COLOR_BUFFER_BIT);
// TODO: Remove this hack
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void GraphicsEngine::setViewport(const Rect& size) {
glViewport(size.left, size.top, size.width, size.height);
}

void GraphicsEngine::setVertexArrayObject(const VertexArrayObjectPtr& vao) {
glBindBuffer(GL_ARRAY_BUFFER, vao->getId());
}

void GraphicsEngine::drawTriangles(ui32 vertexCount, ui32 offset) {
glDrawArrays(GL_TRIANGLES, offset, vertexCount);
}
Loading

0 comments on commit d0b72e2

Please sign in to comment.