Transformed srender to a single header library, added srcmdbuf_add(cmd);
parent
40aec4a122
commit
0c77b3a230
578
src/srender.c
578
src/srender.c
|
@ -2,580 +2,8 @@
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
#define SRENDER_IMPLEMENTATION
|
||||||
|
|
||||||
#include "srender.h"
|
#include "srender.h"
|
||||||
|
#undef SRENDER_IMPLEMENTATION
|
||||||
|
|
||||||
#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 nbufsize;
|
|
||||||
int ncmds;
|
|
||||||
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;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Vertex Buffer Object for all debug objects (coord frame, grid, cube, ...)
|
|
||||||
//
|
|
||||||
const GLint DEBUG_VBO_SIZE = 1024;
|
|
||||||
GLuint gDebugShapesVBOId = 0;
|
|
||||||
GLuint gDebugShapesVAId = 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Simple Mesh Data
|
|
||||||
//
|
|
||||||
typedef struct srmeshdata {
|
|
||||||
int nvertices;
|
|
||||||
int nindices;
|
|
||||||
|
|
||||||
GLuint vao_id;
|
|
||||||
GLuint vb_id;
|
|
||||||
GLuint idb_id;
|
|
||||||
|
|
||||||
GLuint count;
|
|
||||||
GLenum mode;
|
|
||||||
} srmeshdata;
|
|
||||||
|
|
||||||
static srmeshdata gCoordFrameMesh = {0};
|
|
||||||
static srmeshdata gGridMesh = {0};
|
|
||||||
|
|
||||||
typedef struct srshader {
|
|
||||||
const char* vert_fname;
|
|
||||||
const char* frag_fname;
|
|
||||||
|
|
||||||
GLuint program_id;
|
|
||||||
GLuint vert_shader_id;
|
|
||||||
GLuint frag_shader_id;
|
|
||||||
} srshader;
|
|
||||||
|
|
||||||
static srshader gDefaultShader =
|
|
||||||
{"default_vert.glsl", "default_frag.glsl", 0, 0, 0};
|
|
||||||
|
|
||||||
bool srshader_compile(GLuint shader_id, const char* shader_src) {
|
|
||||||
glShaderSource(shader_id, 1, &shader_src, 0);
|
|
||||||
glCompileShader(shader_id);
|
|
||||||
|
|
||||||
// Check Vertex Shader
|
|
||||||
GLint result = GL_FALSE;
|
|
||||||
int log_length = 0;
|
|
||||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result);
|
|
||||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 0) {
|
|
||||||
char* err_msg = calloc(log_length, sizeof(char));
|
|
||||||
assert(err_msg);
|
|
||||||
glGetShaderInfoLog(shader_id, log_length, NULL, err_msg);
|
|
||||||
gLog("%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool srshader_load(
|
|
||||||
srshader* shader,
|
|
||||||
const char* vert_src,
|
|
||||||
const char* frag_src) {
|
|
||||||
shader->vert_shader_id = glCreateShader(GL_VERTEX_SHADER);
|
|
||||||
if (!srshader_compile(shader->vert_shader_id, vert_src)) {
|
|
||||||
gLog("Error compiling vertex shader!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
shader->frag_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
if (!srshader_compile(shader->frag_shader_id, frag_src)) {
|
|
||||||
gLog("Error compiling fragment shader!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
shader->program_id = glCreateProgram();
|
|
||||||
glAttachShader(shader->program_id, shader->vert_shader_id);
|
|
||||||
glAttachShader(shader->program_id, shader->frag_shader_id);
|
|
||||||
|
|
||||||
// Bind attribute locations
|
|
||||||
glBindAttribLocation(shader->program_id, 0, "inCoord");
|
|
||||||
glBindAttribLocation(shader->program_id, 1, "inNormal");
|
|
||||||
glBindAttribLocation(shader->program_id, 2, "inUV");
|
|
||||||
glBindAttribLocation(shader->program_id, 3, "inColor");
|
|
||||||
|
|
||||||
glLinkProgram(shader->program_id);
|
|
||||||
|
|
||||||
GLint result = GL_FALSE;
|
|
||||||
int log_length = 0;
|
|
||||||
glGetProgramiv(shader->program_id, GL_LINK_STATUS, &result);
|
|
||||||
glGetProgramiv(shader->program_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 0) {
|
|
||||||
char* err_msg = calloc(log_length, sizeof(char));
|
|
||||||
assert(err_msg);
|
|
||||||
glGetProgramInfoLog(shader->program_id, log_length, NULL, err_msg);
|
|
||||||
gLog("%s", err_msg);
|
|
||||||
free(err_msg);
|
|
||||||
gLog("Error linking shader program!");
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool try_read_file(const char* dir, const char* filename, char** buf) {
|
|
||||||
assert(*buf == NULL);
|
|
||||||
|
|
||||||
int path_len = strlen(dir) + strlen(filename) + 1;
|
|
||||||
char* path_buffer = calloc(path_len, sizeof(char));
|
|
||||||
snprintf(path_buffer, path_len, "%s%s", dir, filename);
|
|
||||||
long file_length = 0;
|
|
||||||
|
|
||||||
FILE* file = NULL;
|
|
||||||
file = fopen(path_buffer, "rb");
|
|
||||||
if (file) {
|
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
file_length = ftell(file);
|
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
*buf = calloc(file_length, sizeof(char));
|
|
||||||
assert(*buf);
|
|
||||||
fread(*buf, 1, file_length, file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_shaders() {
|
|
||||||
static const char* shader_search_paths[] = {
|
|
||||||
"./data/shaders/",
|
|
||||||
"../data/shaders/",
|
|
||||||
NULL};
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
int search_index = 0;
|
|
||||||
char* frag_buffer = NULL;
|
|
||||||
char* vert_buffer = NULL;
|
|
||||||
|
|
||||||
while (shader_search_paths[search_index] != NULL) {
|
|
||||||
const char* dir = shader_search_paths[search_index];
|
|
||||||
static char path_buf[1024];
|
|
||||||
long length;
|
|
||||||
|
|
||||||
if (vert_buffer == NULL) {
|
|
||||||
try_read_file(dir, gDefaultShader.vert_fname, &vert_buffer);
|
|
||||||
}
|
|
||||||
if (frag_buffer == NULL) {
|
|
||||||
try_read_file(dir, gDefaultShader.frag_fname, &frag_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((vert_buffer != NULL) && (frag_buffer != NULL)) {
|
|
||||||
srshader_load(&gDefaultShader, vert_buffer, frag_buffer);
|
|
||||||
|
|
||||||
free(vert_buffer);
|
|
||||||
vert_buffer = NULL;
|
|
||||||
free(frag_buffer);
|
|
||||||
frag_buffer = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
search_index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gDefaultShader.program_id == 0) {
|
|
||||||
gLog("Error: could not load default shader!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_debug_meshes() {
|
|
||||||
assert(gCoordFrameMesh.nvertices == 0);
|
|
||||||
|
|
||||||
glGenVertexArrays(1, &gDebugShapesVAId);
|
|
||||||
glBindVertexArray(gDebugShapesVAId);
|
|
||||||
|
|
||||||
glGenBuffers(1, &gDebugShapesVBOId);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, gDebugShapesVBOId);
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(union srvrtxdata) * DEBUG_VBO_SIZE, NULL, GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
GLintptr dbg_vbuf_offset = 0;
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glVertexAttribPointer(
|
|
||||||
0,
|
|
||||||
4,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof(srvrtxdata)),
|
|
||||||
(void*)0);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(1);
|
|
||||||
glVertexAttribPointer(
|
|
||||||
1,
|
|
||||||
3,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof(srvrtxdata)),
|
|
||||||
(void*)(sizeof(float) * 4));
|
|
||||||
|
|
||||||
// Attribute 2: texture coordinates
|
|
||||||
glEnableVertexAttribArray(2);
|
|
||||||
glVertexAttribPointer(
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
(sizeof(srvrtxdata)),
|
|
||||||
(void*)(sizeof(float) * 7));
|
|
||||||
// Attribute 3: color
|
|
||||||
glEnableVertexAttribArray(3);
|
|
||||||
glVertexAttribPointer(
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
GL_TRUE,
|
|
||||||
(sizeof(srvrtxdata)),
|
|
||||||
(void*)(sizeof(float) * 9));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Coordinate Frame
|
|
||||||
//
|
|
||||||
gCoordFrameMesh.vao_id = gDebugShapesVAId;
|
|
||||||
gCoordFrameMesh.vb_id = gDebugShapesVBOId;
|
|
||||||
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, 2, 3, 4, 5};
|
|
||||||
|
|
||||||
glBufferSubData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
dbg_vbuf_offset,
|
|
||||||
sizeof(coord_frame_vertices),
|
|
||||||
coord_frame_vertices);
|
|
||||||
dbg_vbuf_offset = sizeof (coord_frame_vertices);
|
|
||||||
|
|
||||||
glGenBuffers(1, &gCoordFrameMesh.idb_id);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.idb_id);
|
|
||||||
glBufferData(
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER,
|
|
||||||
sizeof(coord_frame_indices),
|
|
||||||
coord_frame_indices,
|
|
||||||
GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
gCoordFrameMesh.mode = GL_LINES;
|
|
||||||
gCoordFrameMesh.count = 6;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Coordinate Frame
|
|
||||||
//
|
|
||||||
gGridMesh.vao_id = gDebugShapesVAId;
|
|
||||||
gGridMesh.vb_id = gDebugShapesVBOId;
|
|
||||||
gGridMesh.nvertices = 44;
|
|
||||||
|
|
||||||
srvrtxdata* grid_vertices = calloc(44, sizeof(srvrtxdata));
|
|
||||||
srvrtxdata grid_def_vertex = {
|
|
||||||
0.f, 0.f, 0.f, 1.f,
|
|
||||||
0.f, 1.f, 0.f,
|
|
||||||
0.f, 0.f,
|
|
||||||
255, 255, 255, 255
|
|
||||||
};
|
|
||||||
// lines along parallel to x axis
|
|
||||||
for (int i = 0; i <= 10; i++) {
|
|
||||||
memcpy (&grid_vertices[2*i], &grid_def_vertex, sizeof(srvrtxdata));
|
|
||||||
memcpy (&grid_vertices[2*i + 1], &grid_def_vertex, sizeof(srvrtxdata));
|
|
||||||
grid_vertices[2 * i].pos[0] = -5.0f + i * 1.0f;
|
|
||||||
grid_vertices[2 * i].pos[2] = 5.0f;
|
|
||||||
grid_vertices[2 * i + 1].pos[0] = -5.0f + i * 1.0f;
|
|
||||||
grid_vertices[2 * i + 1].pos[2] = -5.0f;
|
|
||||||
}
|
|
||||||
// lines parallel to z axis
|
|
||||||
for (int i = 11; i <= 21; i++) {
|
|
||||||
memcpy (&grid_vertices[2*i], &grid_def_vertex, sizeof(srvrtxdata));
|
|
||||||
memcpy (&grid_vertices[2*i + 1], &grid_def_vertex, sizeof(srvrtxdata));
|
|
||||||
grid_vertices[2 * i].pos[0] = -5.0f;
|
|
||||||
grid_vertices[2 * i].pos[2] = -5.0f + (i - 11) * 1.0f;
|
|
||||||
grid_vertices[2 * i + 1].pos[0] = 5.0f;
|
|
||||||
grid_vertices[2 * i + 1].pos[2] = -5.0f + (i - 11) * 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, gDebugShapesVBOId);
|
|
||||||
glBufferSubData(
|
|
||||||
GL_ARRAY_BUFFER,
|
|
||||||
dbg_vbuf_offset,
|
|
||||||
sizeof(srvrtxdata) * 44,
|
|
||||||
grid_vertices);
|
|
||||||
dbg_vbuf_offset += sizeof (srvrtxdata) * 44;
|
|
||||||
|
|
||||||
free(grid_vertices);
|
|
||||||
|
|
||||||
GLuint grid_indices[44];
|
|
||||||
for (int i = 0; i < 22; i++) {
|
|
||||||
grid_indices[2 * i] = 2*i + 6;
|
|
||||||
grid_indices[2 * i + 1] = (2*i+1) + 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGenBuffers(1, &gGridMesh.idb_id);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gGridMesh.idb_id);
|
|
||||||
glBufferData(
|
|
||||||
GL_ELEMENT_ARRAY_BUFFER,
|
|
||||||
sizeof(grid_indices),
|
|
||||||
grid_indices,
|
|
||||||
GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
gGridMesh.mode = GL_LINES;
|
|
||||||
gGridMesh.count = 44;
|
|
||||||
|
|
||||||
glBindVertexArray(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Renderer
|
|
||||||
//
|
|
||||||
srndr* srndr_create() {
|
|
||||||
srndr* result = calloc(1, sizeof(srndr));
|
|
||||||
|
|
||||||
init_shaders();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
sv->width = width;
|
|
||||||
sv->height = height;
|
|
||||||
|
|
||||||
srview_cleanup_framebuffer(sv);
|
|
||||||
srview_update_framebuffer(sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
srview* srview_create() {
|
|
||||||
srview* result = calloc(1, sizeof(srview));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void srview_destroy(srview* sv) {
|
|
||||||
srview_cleanup_framebuffer(sv);
|
|
||||||
|
|
||||||
free(sv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void srndr_run_frame_command(const srcmd* cmd) {
|
|
||||||
glBindVertexArray(gCoordFrameMesh.vao_id);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.idb_id);
|
|
||||||
glDrawElements(gCoordFrameMesh.mode, gCoordFrameMesh.count, GL_UNSIGNED_INT, (void*)0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void srndr_run_grid_command(const srcmd* cmd) {
|
|
||||||
glBindVertexArray(gGridMesh.vao_id);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gGridMesh.idb_id);
|
|
||||||
glDrawElements(gGridMesh.mode, gGridMesh.count, GL_UNSIGNED_INT, (void*)0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) {
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId);
|
|
||||||
|
|
||||||
glViewport(0, 0, sview->width, sview->height);
|
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
glUseProgram(gDefaultShader.program_id);
|
|
||||||
GLint view_mat_loc =
|
|
||||||
glGetUniformLocation(gDefaultShader.program_id, "uViewMatrix");
|
|
||||||
assert(view_mat_loc != -1);
|
|
||||||
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, &sview->view);
|
|
||||||
|
|
||||||
GLint proj_mat_loc =
|
|
||||||
glGetUniformLocation(gDefaultShader.program_id, "uProjectionMatrix");
|
|
||||||
assert(proj_mat_loc != -1);
|
|
||||||
glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, &sview->proj);
|
|
||||||
|
|
||||||
GLint model_mat_loc =
|
|
||||||
glGetUniformLocation(gDefaultShader.program_id, "uModelMatrix");
|
|
||||||
assert(model_mat_loc != -1);
|
|
||||||
|
|
||||||
for (int i = 0; i < scmdbuf->ncmds; i++) {
|
|
||||||
const srcmd* cmd = &scmdbuf->cmds[i];
|
|
||||||
glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, &cmd->mat);
|
|
||||||
|
|
||||||
switch (cmd->type) {
|
|
||||||
case SRndrCmdTypeFrame:
|
|
||||||
srndr_run_frame_command(cmd);
|
|
||||||
break;
|
|
||||||
case SRndrCmdTypeGrid:
|
|
||||||
srndr_run_grid_command(cmd);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
gLog("Invalid command type %d at index %d", cmd->type, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render Commands
|
|
||||||
//
|
|
||||||
srcmdbuf* srcmdbuf_create(unsigned int size_max) {
|
|
||||||
srcmdbuf* result = malloc(sizeof(srcmdbuf));
|
|
||||||
result->nbufsize = size_max;
|
|
||||||
result->ncmds = 0;
|
|
||||||
result->cmds = calloc(sizeof(srcmd), size_max);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void srcmdbuf_clear(srcmdbuf* cmdbuf) { cmdbuf->ncmds = 0; }
|
|
||||||
|
|
||||||
srcmd* srcmd_create(srcmdbuf* cmdbuf) {
|
|
||||||
if (cmdbuf->ncmds == cmdbuf->nbufsize) {
|
|
||||||
gLog("Warning: number of render commands maxed out!");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &(cmdbuf->cmds[cmdbuf->ncmds++]);
|
|
||||||
}
|
|
||||||
|
|
606
src/srender.h
606
src/srender.h
|
@ -5,6 +5,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include "vectorial/simd4x4f.h"
|
#include "vectorial/simd4x4f.h"
|
||||||
|
|
||||||
typedef struct srndr srndr;
|
typedef struct srndr srndr;
|
||||||
|
@ -45,14 +46,617 @@ void srview_get_output_texture(srview* sv, GLuint* texture);
|
||||||
//
|
//
|
||||||
// Command Buffer and Commands
|
// Command Buffer and Commands
|
||||||
//
|
//
|
||||||
|
void srcmd_clear (srcmd *cmd);
|
||||||
|
|
||||||
srcmdbuf* srcmdbuf_create(unsigned int size_max);
|
srcmdbuf* srcmdbuf_create(unsigned int size_max);
|
||||||
void srcmdbuf_clear(srcmdbuf* cmdbuf);
|
void srcmdbuf_clear(srcmdbuf* cmdbuf);
|
||||||
|
bool srcmdbuf_add(srcmdbuf* cmdbuf, srcmd *cmd);
|
||||||
srcmd* srcmd_create(srcmdbuf* cmdbuf);
|
srcmd* srcmd_create(srcmdbuf* cmdbuf);
|
||||||
|
|
||||||
void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf);
|
void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf);
|
||||||
|
|
||||||
|
//
|
||||||
|
// srender Implementation
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef SRENDER_IMPLEMENTATION
|
||||||
|
|
||||||
|
#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 nbufsize;
|
||||||
|
int ncmds;
|
||||||
|
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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Vertex Buffer Object for all debug objects (coord frame, grid, cube, ...)
|
||||||
|
//
|
||||||
|
const GLint DEBUG_VBO_SIZE = 1024;
|
||||||
|
GLuint gDebugShapesVBOId = 0;
|
||||||
|
GLuint gDebugShapesVAId = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Simple Mesh Data
|
||||||
|
//
|
||||||
|
typedef struct srmeshdata {
|
||||||
|
int nvertices;
|
||||||
|
int nindices;
|
||||||
|
|
||||||
|
GLuint vao_id;
|
||||||
|
GLuint vb_id;
|
||||||
|
GLuint idb_id;
|
||||||
|
|
||||||
|
GLuint count;
|
||||||
|
GLenum mode;
|
||||||
|
} srmeshdata;
|
||||||
|
|
||||||
|
static srmeshdata gCoordFrameMesh = {0};
|
||||||
|
static srmeshdata gGridMesh = {0};
|
||||||
|
|
||||||
|
typedef struct srshader {
|
||||||
|
const char* vert_fname;
|
||||||
|
const char* frag_fname;
|
||||||
|
|
||||||
|
GLuint program_id;
|
||||||
|
GLuint vert_shader_id;
|
||||||
|
GLuint frag_shader_id;
|
||||||
|
} srshader;
|
||||||
|
|
||||||
|
static srshader gDefaultShader =
|
||||||
|
{"default_vert.glsl", "default_frag.glsl", 0, 0, 0};
|
||||||
|
|
||||||
|
bool srshader_compile(GLuint shader_id, const char* shader_src) {
|
||||||
|
glShaderSource(shader_id, 1, &shader_src, 0);
|
||||||
|
glCompileShader(shader_id);
|
||||||
|
|
||||||
|
// Check Vertex Shader
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
int log_length = 0;
|
||||||
|
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result);
|
||||||
|
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
if (log_length > 0) {
|
||||||
|
char* err_msg = calloc(log_length, sizeof(char));
|
||||||
|
assert(err_msg);
|
||||||
|
glGetShaderInfoLog(shader_id, log_length, NULL, err_msg);
|
||||||
|
gLog("%s", err_msg);
|
||||||
|
free(err_msg);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool srshader_load(
|
||||||
|
srshader* shader,
|
||||||
|
const char* vert_src,
|
||||||
|
const char* frag_src) {
|
||||||
|
shader->vert_shader_id = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
if (!srshader_compile(shader->vert_shader_id, vert_src)) {
|
||||||
|
gLog("Error compiling vertex shader!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->frag_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
if (!srshader_compile(shader->frag_shader_id, frag_src)) {
|
||||||
|
gLog("Error compiling fragment shader!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
shader->program_id = glCreateProgram();
|
||||||
|
glAttachShader(shader->program_id, shader->vert_shader_id);
|
||||||
|
glAttachShader(shader->program_id, shader->frag_shader_id);
|
||||||
|
|
||||||
|
// Bind attribute locations
|
||||||
|
glBindAttribLocation(shader->program_id, 0, "inCoord");
|
||||||
|
glBindAttribLocation(shader->program_id, 1, "inNormal");
|
||||||
|
glBindAttribLocation(shader->program_id, 2, "inUV");
|
||||||
|
glBindAttribLocation(shader->program_id, 3, "inColor");
|
||||||
|
|
||||||
|
glLinkProgram(shader->program_id);
|
||||||
|
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
int log_length = 0;
|
||||||
|
glGetProgramiv(shader->program_id, GL_LINK_STATUS, &result);
|
||||||
|
glGetProgramiv(shader->program_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
if (log_length > 0) {
|
||||||
|
char* err_msg = calloc(log_length, sizeof(char));
|
||||||
|
assert(err_msg);
|
||||||
|
glGetProgramInfoLog(shader->program_id, log_length, NULL, err_msg);
|
||||||
|
gLog("%s", err_msg);
|
||||||
|
free(err_msg);
|
||||||
|
gLog("Error linking shader program!");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_read_file(const char* dir, const char* filename, char** buf) {
|
||||||
|
assert(*buf == NULL);
|
||||||
|
|
||||||
|
int path_len = strlen(dir) + strlen(filename) + 1;
|
||||||
|
char* path_buffer = calloc(path_len, sizeof(char));
|
||||||
|
snprintf(path_buffer, path_len, "%s%s", dir, filename);
|
||||||
|
long file_length = 0;
|
||||||
|
|
||||||
|
FILE* file = NULL;
|
||||||
|
file = fopen(path_buffer, "rb");
|
||||||
|
if (file) {
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
file_length = ftell(file);
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
*buf = calloc(file_length, sizeof(char));
|
||||||
|
assert(*buf);
|
||||||
|
fread(*buf, 1, file_length, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_shaders() {
|
||||||
|
static const char* shader_search_paths[] = {
|
||||||
|
"./data/shaders/",
|
||||||
|
"../data/shaders/",
|
||||||
|
NULL};
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
int search_index = 0;
|
||||||
|
char* frag_buffer = NULL;
|
||||||
|
char* vert_buffer = NULL;
|
||||||
|
|
||||||
|
while (shader_search_paths[search_index] != NULL) {
|
||||||
|
const char* dir = shader_search_paths[search_index];
|
||||||
|
static char path_buf[1024];
|
||||||
|
long length;
|
||||||
|
|
||||||
|
if (vert_buffer == NULL) {
|
||||||
|
try_read_file(dir, gDefaultShader.vert_fname, &vert_buffer);
|
||||||
|
}
|
||||||
|
if (frag_buffer == NULL) {
|
||||||
|
try_read_file(dir, gDefaultShader.frag_fname, &frag_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vert_buffer != NULL) && (frag_buffer != NULL)) {
|
||||||
|
srshader_load(&gDefaultShader, vert_buffer, frag_buffer);
|
||||||
|
|
||||||
|
free(vert_buffer);
|
||||||
|
vert_buffer = NULL;
|
||||||
|
free(frag_buffer);
|
||||||
|
frag_buffer = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
search_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gDefaultShader.program_id == 0) {
|
||||||
|
gLog("Error: could not load default shader!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_debug_meshes() {
|
||||||
|
assert(gCoordFrameMesh.nvertices == 0);
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &gDebugShapesVAId);
|
||||||
|
glBindVertexArray(gDebugShapesVAId);
|
||||||
|
|
||||||
|
glGenBuffers(1, &gDebugShapesVBOId);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, gDebugShapesVBOId);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(union srvrtxdata) * DEBUG_VBO_SIZE, NULL, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
GLintptr dbg_vbuf_offset = 0;
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
0,
|
||||||
|
4,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof(srvrtxdata)),
|
||||||
|
(void*)0);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof(srvrtxdata)),
|
||||||
|
(void*)(sizeof(float) * 4));
|
||||||
|
|
||||||
|
// Attribute 2: texture coordinates
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
(sizeof(srvrtxdata)),
|
||||||
|
(void*)(sizeof(float) * 7));
|
||||||
|
// Attribute 3: color
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
GL_TRUE,
|
||||||
|
(sizeof(srvrtxdata)),
|
||||||
|
(void*)(sizeof(float) * 9));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Coordinate Frame
|
||||||
|
//
|
||||||
|
gCoordFrameMesh.vao_id = gDebugShapesVAId;
|
||||||
|
gCoordFrameMesh.vb_id = gDebugShapesVBOId;
|
||||||
|
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, 2, 3, 4, 5};
|
||||||
|
|
||||||
|
glBufferSubData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
dbg_vbuf_offset,
|
||||||
|
sizeof(coord_frame_vertices),
|
||||||
|
coord_frame_vertices);
|
||||||
|
dbg_vbuf_offset = sizeof (coord_frame_vertices);
|
||||||
|
|
||||||
|
glGenBuffers(1, &gCoordFrameMesh.idb_id);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.idb_id);
|
||||||
|
glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
sizeof(coord_frame_indices),
|
||||||
|
coord_frame_indices,
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
gCoordFrameMesh.mode = GL_LINES;
|
||||||
|
gCoordFrameMesh.count = 6;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Coordinate Frame
|
||||||
|
//
|
||||||
|
gGridMesh.vao_id = gDebugShapesVAId;
|
||||||
|
gGridMesh.vb_id = gDebugShapesVBOId;
|
||||||
|
gGridMesh.nvertices = 44;
|
||||||
|
|
||||||
|
srvrtxdata* grid_vertices = calloc(44, sizeof(srvrtxdata));
|
||||||
|
srvrtxdata grid_def_vertex = {
|
||||||
|
0.f, 0.f, 0.f, 1.f,
|
||||||
|
0.f, 1.f, 0.f,
|
||||||
|
0.f, 0.f,
|
||||||
|
255, 255, 255, 255
|
||||||
|
};
|
||||||
|
// lines along parallel to x axis
|
||||||
|
for (int i = 0; i <= 10; i++) {
|
||||||
|
memcpy (&grid_vertices[2*i], &grid_def_vertex, sizeof(srvrtxdata));
|
||||||
|
memcpy (&grid_vertices[2*i + 1], &grid_def_vertex, sizeof(srvrtxdata));
|
||||||
|
grid_vertices[2 * i].pos[0] = -5.0f + i * 1.0f;
|
||||||
|
grid_vertices[2 * i].pos[2] = 5.0f;
|
||||||
|
grid_vertices[2 * i + 1].pos[0] = -5.0f + i * 1.0f;
|
||||||
|
grid_vertices[2 * i + 1].pos[2] = -5.0f;
|
||||||
|
}
|
||||||
|
// lines parallel to z axis
|
||||||
|
for (int i = 11; i <= 21; i++) {
|
||||||
|
memcpy (&grid_vertices[2*i], &grid_def_vertex, sizeof(srvrtxdata));
|
||||||
|
memcpy (&grid_vertices[2*i + 1], &grid_def_vertex, sizeof(srvrtxdata));
|
||||||
|
grid_vertices[2 * i].pos[0] = -5.0f;
|
||||||
|
grid_vertices[2 * i].pos[2] = -5.0f + (i - 11) * 1.0f;
|
||||||
|
grid_vertices[2 * i + 1].pos[0] = 5.0f;
|
||||||
|
grid_vertices[2 * i + 1].pos[2] = -5.0f + (i - 11) * 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, gDebugShapesVBOId);
|
||||||
|
glBufferSubData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
dbg_vbuf_offset,
|
||||||
|
sizeof(srvrtxdata) * 44,
|
||||||
|
grid_vertices);
|
||||||
|
dbg_vbuf_offset += sizeof (srvrtxdata) * 44;
|
||||||
|
|
||||||
|
free(grid_vertices);
|
||||||
|
|
||||||
|
GLuint grid_indices[44];
|
||||||
|
for (int i = 0; i < 22; i++) {
|
||||||
|
grid_indices[2 * i] = 2*i + 6;
|
||||||
|
grid_indices[2 * i + 1] = (2*i+1) + 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &gGridMesh.idb_id);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gGridMesh.idb_id);
|
||||||
|
glBufferData(
|
||||||
|
GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
sizeof(grid_indices),
|
||||||
|
grid_indices,
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
gGridMesh.mode = GL_LINES;
|
||||||
|
gGridMesh.count = 44;
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Renderer
|
||||||
|
//
|
||||||
|
srndr* srndr_create() {
|
||||||
|
srndr* result = calloc(1, sizeof(srndr));
|
||||||
|
|
||||||
|
init_shaders();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
sv->width = width;
|
||||||
|
sv->height = height;
|
||||||
|
|
||||||
|
srview_cleanup_framebuffer(sv);
|
||||||
|
srview_update_framebuffer(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
srview* srview_create() {
|
||||||
|
srview* result = calloc(1, sizeof(srview));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srview_destroy(srview* sv) {
|
||||||
|
srview_cleanup_framebuffer(sv);
|
||||||
|
|
||||||
|
free(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void srndr_run_frame_command(const srcmd* cmd) {
|
||||||
|
glBindVertexArray(gCoordFrameMesh.vao_id);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gCoordFrameMesh.idb_id);
|
||||||
|
glDrawElements(gCoordFrameMesh.mode, gCoordFrameMesh.count, GL_UNSIGNED_INT, (void*)0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void srndr_run_grid_command(const srcmd* cmd) {
|
||||||
|
glBindVertexArray(gGridMesh.vao_id);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gGridMesh.idb_id);
|
||||||
|
glDrawElements(gGridMesh.mode, gGridMesh.count, GL_UNSIGNED_INT, (void*)0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void srndr_render(srndr* srndr, srview* sview, srcmdbuf* scmdbuf) {
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sview->mFrameBufferId);
|
||||||
|
|
||||||
|
glViewport(0, 0, sview->width, sview->height);
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 0.1f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glUseProgram(gDefaultShader.program_id);
|
||||||
|
GLint view_mat_loc =
|
||||||
|
glGetUniformLocation(gDefaultShader.program_id, "uViewMatrix");
|
||||||
|
assert(view_mat_loc != -1);
|
||||||
|
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, &sview->view);
|
||||||
|
|
||||||
|
GLint proj_mat_loc =
|
||||||
|
glGetUniformLocation(gDefaultShader.program_id, "uProjectionMatrix");
|
||||||
|
assert(proj_mat_loc != -1);
|
||||||
|
glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, &sview->proj);
|
||||||
|
|
||||||
|
GLint model_mat_loc =
|
||||||
|
glGetUniformLocation(gDefaultShader.program_id, "uModelMatrix");
|
||||||
|
assert(model_mat_loc != -1);
|
||||||
|
|
||||||
|
for (int i = 0; i < scmdbuf->ncmds; i++) {
|
||||||
|
const srcmd* cmd = &scmdbuf->cmds[i];
|
||||||
|
glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, &cmd->mat);
|
||||||
|
|
||||||
|
switch (cmd->type) {
|
||||||
|
case SRndrCmdTypeFrame:
|
||||||
|
srndr_run_frame_command(cmd);
|
||||||
|
break;
|
||||||
|
case SRndrCmdTypeGrid:
|
||||||
|
srndr_run_grid_command(cmd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gLog("Invalid command type %d at index %d", cmd->type, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Render Commands
|
||||||
|
//
|
||||||
|
void srcmd_clear (srcmd *cmd) {
|
||||||
|
cmd->color = simd4f_create(1.f, 1.f, 1.f, 1.f);
|
||||||
|
cmd->type = SRndrCmdTypeFrame;
|
||||||
|
simd4x4f_identity(&cmd->mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
srcmdbuf* srcmdbuf_create(unsigned int size_max) {
|
||||||
|
srcmdbuf* result = malloc(sizeof(srcmdbuf));
|
||||||
|
result->nbufsize = size_max;
|
||||||
|
result->ncmds = 0;
|
||||||
|
result->cmds = calloc(sizeof(srcmd), size_max);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srcmdbuf_clear(srcmdbuf* cmdbuf) { cmdbuf->ncmds = 0; }
|
||||||
|
|
||||||
|
bool srcmdbuf_add(srcmdbuf* cmdbuf, srcmd *cmd) {
|
||||||
|
srcmd *buf_cmd = srcmd_create(cmdbuf);
|
||||||
|
|
||||||
|
if (!buf_cmd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf_cmd = *cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
srcmd* srcmd_create(srcmdbuf* cmdbuf) {
|
||||||
|
if (cmdbuf->ncmds == cmdbuf->nbufsize) {
|
||||||
|
gLog("Warning: number of render commands maxed out!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &(cmdbuf->cmds[cmdbuf->ncmds++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SRENDER_IMPLEMENTATION
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif // SRENDER_H
|
||||||
|
|
|
@ -187,15 +187,15 @@ void DoRender() {
|
||||||
|
|
||||||
// Populate render commands
|
// Populate render commands
|
||||||
srcmdbuf_clear(gRndrCmds);
|
srcmdbuf_clear(gRndrCmds);
|
||||||
srcmd* cmd = srcmd_create(gRndrCmds);
|
|
||||||
cmd->type = SRndrCmdTypeFrame;
|
|
||||||
simd4x4f_identity(&cmd->mat);
|
|
||||||
cmd->color = simd4f_create(1.f, 1.f, 1.f, 1.f);
|
|
||||||
|
|
||||||
cmd = srcmd_create(gRndrCmds);
|
srcmd rcmd;
|
||||||
cmd->type = SRndrCmdTypeGrid;
|
srcmd_clear(&rcmd);
|
||||||
simd4x4f_identity(&cmd->mat);
|
|
||||||
cmd->color = simd4f_create(1.f, 1.f, 1.f, 1.f);
|
rcmd.type = SRndrCmdTypeFrame;
|
||||||
|
srcmdbuf_add(gRndrCmds, &rcmd);
|
||||||
|
|
||||||
|
rcmd.type = SRndrCmdTypeGrid;
|
||||||
|
srcmdbuf_add(gRndrCmds, &rcmd);
|
||||||
|
|
||||||
// Perform the actual render
|
// Perform the actual render
|
||||||
srndr_render(gRndr, gView, gRndrCmds);
|
srndr_render(gRndr, gView, gRndrCmds);
|
||||||
|
|
Loading…
Reference in New Issue