rbdlsim/src/srender.c

261 lines
5.5 KiB
C

// clang-format off
#include <glad/gl.h>
// clang-format on
#include "srender.h"
#include "utils.h"
#include <string.h>
#include <assert.h>
typedef struct srndr {
} srndr;
typedef struct srview {
GLuint width;
GLuint height;
GLuint mFrameBufferId;
GLuint mColorTexture;
GLuint mDepthTexture;
simd4x4f proj;
simd4x4f view;
} srview;
typedef struct srcmdbuf {
int ncmds;
int idx;
srcmd* cmds;
} srcmdbuf;
//
// Vertex Data
//
typedef union srvrtxdata {
struct {
float x, y, z, w;
float nx, ny, nz;
float s, t;
GLubyte r,g,b,a;
};
struct {
float pos[4];
float n[4];
float uv[2];
GLubyte color[4];
};
} srvrtxdata;
//
// Simple Mesh Data
//
typedef struct srmeshdata {
int nvertices;
int nindices;
srvrtxdata *vertices;
int *indices;
} srmeshdata;
static srmeshdata gCoordFrameMesh = {0};
void init_debug_meshes () {
assert (gCoordFrameMesh.nvertices == 0);
gCoordFrameMesh.nvertices = 6;
srvrtxdata coord_frame_vertices[] = {
{0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 },
{1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 255, 0, 0, 255 },
{0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255},
{0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 255, 0, 255},
{0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255},
{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 255, 255}
};
GLuint coord_frame_indices[] = {
0, 1,
1, 2,
3, 4
};
gCoordFrameMesh.vertices = malloc (sizeof(coord_frame_vertices));
memcpy (gCoordFrameMesh.vertices, coord_frame_vertices, sizeof(coord_frame_vertices));
gCoordFrameMesh.indices = malloc (sizeof(coord_frame_indices));
memcpy (gCoordFrameMesh.indices, coord_frame_indices, sizeof (coord_frame_indices));
};
//
// Renderer
//
srndr* srndr_create() {
srndr* result = calloc(1, sizeof(srndr));
init_debug_meshes();
return result;
}
void srndr_destroy(srndr* sr) { free(sr); }
//
// View
//
void srview_get_output_texture(srview* sv, GLuint* texture) {
*texture = sv->mColorTexture;
}
void srview_set_proj(srview* sv, simd4x4f proj) {
sv->proj = proj;
}
void srview_set_view(srview* sv, simd4x4f view) {
sv->view = view;
}
void srview_update_framebuffer(srview* sv) {
glGenFramebuffers(1, &sv->mFrameBufferId);
glBindFramebuffer(GL_FRAMEBUFFER, sv->mFrameBufferId);
// Color Texture
glGenTextures(1, &sv->mColorTexture);
glBindTexture(GL_TEXTURE_2D, sv->mColorTexture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_RGB,
sv->width,
sv->height,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
sv->mColorTexture,
0);
// Depth Texture
glGenTextures(1, &sv->mDepthTexture);
glBindTexture(GL_TEXTURE_2D, sv->mDepthTexture);
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_DEPTH_COMPONENT,
sv->width,
sv->height,
0,
GL_DEPTH_COMPONENT,
GL_FLOAT,
0);
// Set parameters so that we can set a shadow2DSampler
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float border_color[] = {1.0f, 1.0f, 1.0f, 1.0f};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
sv->mDepthTexture,
0);
}
void srview_cleanup_framebuffer(srview* sv) {
if (glIsFramebuffer(sv->mFrameBufferId)) {
glDeleteFramebuffers(1, &sv->mFrameBufferId);
}
if (sv->mColorTexture != -1) {
glDeleteTextures(1, &sv->mColorTexture);
sv->mColorTexture = -1;
}
if (sv->mDepthTexture != -1) {
glDeleteTextures(1, &sv->mDepthTexture);
sv->mDepthTexture = -1;
}
}
void srview_set_size(srview* sv, int width, int height) {
if (sv->width == width && sv->height == height) {
return;
}
gLog("Setting size to %d, %d", width, height);
sv->width = width;
sv->height = height;
srview_cleanup_framebuffer(sv);
srview_update_framebuffer(sv);
gLog("Color texture = %d", sv->mColorTexture);
}
srview* srview_create() {
srview* result = calloc(1, sizeof(srview));
return result;
}
void srview_destroy(srview* sv) {
srview_cleanup_framebuffer(sv);
free(sv);
}
void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId);
glViewport(0, 0, sview->width, sview->height);
glClearColor(1.f, 0.f, 1.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
//
// Render Commands
//
srcmdbuf* srcmdbuf_create (unsigned int size_max) {
srcmdbuf* result = malloc (sizeof (srcmdbuf));
result->ncmds = size_max;
result->idx = 0;
result->cmds = calloc (sizeof (srcmd), size_max);
return result;
}
void srcmdbuf_clear (srcmdbuf* cmdbuf) {
cmdbuf->idx = 0;
}
srcmd* srcmd_create (srcmdbuf* cmdbuf) {
if (cmdbuf->idx == cmdbuf->ncmds) {
gLog ("Warning: number of render commands maxed out!");
return NULL;
}
return &(cmdbuf->cmds[cmdbuf->idx++]);
}