From 07116cd28845c3e589ab7e99f32d0ab96dd5cf4d Mon Sep 17 00:00:00 2001 From: onelin Date: Sat, 29 Nov 2025 23:04:52 +0100 Subject: TMP Rework rendering --- src/api/daw.h | 13 +- src/daw.c | 124 ++++++++++++++-- src/gl.c | 1 + src/include/daw/rendering.h | 74 +++++----- src/include/daw/window.h | 3 +- src/platform_glfw.c | 3 + src/rendering.c | 350 ++++++++++++++++++++++++++++---------------- src/window.c | 27 +++- 8 files changed, 405 insertions(+), 190 deletions(-) diff --git a/src/api/daw.h b/src/api/daw.h index 2676170..259c743 100644 --- a/src/api/daw.h +++ b/src/api/daw.h @@ -6,8 +6,9 @@ extern "C" { #endif #include -#include +#include +typedef struct Instance Instance; /* Essential functions */ Instance* engine_init(const char* windowtitle, i32 windowWidth, i32 windowHeight, @@ -21,16 +22,6 @@ void engine_stop(Instance* p); /* Utility functions */ void engine_fps_max(Instance* p, u16 cap); -void render_set_zoom(f32 new_zoom); -void render_adjust_zoom(f32 diff); -void render_add_unit(RenderUnit* u); - -/* move this */ -void delay(uint64_t ms); - -// file operations -usize f_get_sz(FILE* f); - #ifdef __cplusplus } diff --git a/src/daw.c b/src/daw.c index 284bfc7..2d6a764 100644 --- a/src/daw.c +++ b/src/daw.c @@ -41,10 +41,8 @@ Instance* GLOBAL_PLATFORM = NULL; -static Camera default_camera = { - .pos = {3, 0, 0}, - .dir = {1, 1, 1}, -}; +#define DEFAULT_CAMERA { .pos = {3, 0, 0}, .dir = {1, 1, 1}, } +static Camera default_camera = DEFAULT_CAMERA; input_callback_t* callbacks[128]; usize callbacks_len; @@ -159,8 +157,74 @@ Instance* engine_init(const char* windowtitle, i32 windowWidth, i32 windowHeight return p; } +// TODO: MOVE TO RENDERING +static f32 default_quad[8] = { + -1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f, +}; + +static f32 default_quad_uv[8] = { + 0.f, 0.f, + 1.f, 0.f, + 1.f, 1.f, + 0.f, 1.f, +}; + +static u8 default_quad_ibo[6] = { + 0, 1, 2, + 2, 3, 0, +}; + +// TODO: CREATE DEFAULT SHADERBUFF +#define COUNT(a) sizeof(a) / sizeof(a[0]) +static ShaderBuffer shaderbuf[3] = { + SHADERBUFFER_NEW(f32, COUNT(default_quad), 2, default_quad, ShaderBuffer_AccessFrequency_static | ShaderBuffer_AccessType_draw | ShaderBuffer_Type_vertexPosition), + SHADERBUFFER_NEW(f32, COUNT(default_quad_uv), 2, default_quad_uv, ShaderBuffer_AccessFrequency_static | ShaderBuffer_AccessType_draw), + SHADERBUFFER_NEW(u8, COUNT(default_quad_ibo), 3, default_quad_ibo, ShaderBuffer_AccessFrequency_static | ShaderBuffer_AccessType_draw | ShaderBuffer_Type_vertexIndex), +}; +#undef COUNT + +static const char* default_quad_shader_vertex_src = +"#version 330 core" +"" +"layout(location = 0) in vec3 vertexPosition_modelspace;" +"layout(location = 1) in vec2 vertexUV;" +"" +"out vec2 UV;" +"" +"void main() {" +" gl_Position = vec4(vertexPosition_modelspace, 0, 0);" +"" +" UV = vertexUV;" +"}"; + +static const char* default_quad_shader_fragment_src = +"#version 330 core" +"" +"// Ouput data" +"in vec2 UV;" +"out vec3 color;" +"" +"uniform sampler2D textureSampler;" +"" +"void main() {" +" color = texture(textureSampler, UV).rgb;" +"}"; + + i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { + // TODO: MOVE TO INIT + Shader default_quad_shaders[] = { + compile_shader(default_quad_shader_vertex_src, Shader_Vertex), + compile_shader(default_quad_shader_fragment_src, Shader_Fragment), + (Shader){0}, + }; + default_quad_shaders[2] = compose_shader(default_quad_shaders, 2); + RenderObject default_quad_renderobject; + if (p == NULL) { ERROR("Platform is uninitialized.\n"); INFO("initialize with `engine_init`"); @@ -172,6 +236,7 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { StateType state = initial_state; Window* w = p->window; + Camera default_renderbuffer_camera = default_camera; { u64 state_init_time = get_time(); @@ -187,8 +252,28 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_TEXTURE_2D) }; window_init_renderstack(w, 1, 1, p, t); - w->render_targets->cam[0] = default_camera; + //w->render_targets->cam[0] = &default_renderbuffer_camera; } + + u32 first_texture = 0; + + for (usize i = 0; i < w->render_targets->buffer_len; i++) { + if (BUFFERPARAMETER_GET_TYPE(w->render_targets->buffer_parameters[i]) == BufferType_texture) { + first_texture = w->render_targets->buffer[i]; + break; + } + } + + default_quad_renderobject = RenderObject_new( + // Shader + &default_quad_shaders[2], + // Texture + first_texture, + // Vertices + shaderbuf, + sizeof(shaderbuf) / sizeof(ShaderBuffer) + ); + INFO("Initializing state \"%s\" took %.1fns", StateTypeStr[state], (get_time() - state_init_time)); } @@ -248,15 +333,36 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { // Create only 1 additional framebuffer, in addition to the default // one. This is used to render a texture that is represented as a quad // on the default framebuffer. - FramebufferParameters p[] = { + FramebufferParameters fb_params[] = { {.num_attached_buffers = 1, {200,200}}, }; u32 t[] = { BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_TEXTURE_2D) }; - window_init_renderstack(w, 1, 1, p, t); - w->render_targets->cam[0] = default_camera; + window_init_renderstack(w, 1, 1, fb_params, t); + + //w->render_targets->cam[0] = &default_camera; } + + u32 first_texture = 0; + + for (usize i = 0; i < w->render_targets->buffer_len; i++) { + if (BUFFERPARAMETER_GET_TYPE(w->render_targets->buffer_parameters[i]) == BufferType_texture) { + first_texture = w->render_targets->buffer[i]; + break; + } + } + + default_quad_renderobject = RenderObject_new( + // Shader + &default_quad_shaders[2], + // Texture + first_texture, /*TODO*/ + // Vertices + shaderbuf, + sizeof(shaderbuf) / sizeof(ShaderBuffer) + ); + INFO("Initializing state \"%s\" took %.1fns", StateTypeStr[state], (get_time() - state_init_time)); } @@ -265,7 +371,7 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) { /* Render */ const u64 rendertime_begin = get_time(); render_begin(p->window); - render_present(p->window); + render_present(p->window, &default_quad_renderobject); const u64 rendertime_dt = get_time() - rendertime_begin; /* Regulate FPS */ diff --git a/src/gl.c b/src/gl.c index e84b33d..a512b46 100644 --- a/src/gl.c +++ b/src/gl.c @@ -248,6 +248,7 @@ RenderObject RenderObject_new( o.shader = *shader; o.texture = texture; + o.texture_len = 1; o.buffer = buffers; o.buffer_len = num_buffers; o.mvp = gl->GetUniformLocation(o.shader.program, "MVP"); diff --git a/src/include/daw/rendering.h b/src/include/daw/rendering.h index 590bcb6..a26310e 100644 --- a/src/include/daw/rendering.h +++ b/src/include/daw/rendering.h @@ -124,6 +124,7 @@ typedef struct { // The texture ID, glBindTextures(target, &this->texture) u32 texture; + u32 texture_len; // Number of buffers usize buffer_len; @@ -191,30 +192,6 @@ typedef struct { } Camera; -usize ShaderBufferDataType_size(u16 flags); - -ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags); -ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags); -ShaderBufferFlag ShaderBuffer_get_type(u64 flags); -ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags); - -/* Conversion to GL types */ -u32 ShaderBuffer_get_gl_type(u64 flags); -u32 ShaderBuffer_get_gl_accesstype(u64 flags); -u32 ShaderBuffer_get_gl_datatype(u64 flags); - -/* Misc */ -void r_perspective(Camera *c, f32 fov, ivec2 windowsize); -void r_perspective_ortho(Camera *c, f32 sz, ivec2 windowsize); - -void r_set_camera(Camera* c); -void r_reset_camera(Camera* c, ivec2 windowsize); - -//void window_size_callback(GLFWwindow* window, i32 width, i32 height); - -// 3D positional coordinates and scale in last element of `pos` -void engine_draw_model(RenderObject* o, vec4 pos); - typedef struct { vec3 pos; f32 scale; @@ -231,11 +208,14 @@ typedef enum { // Buffer parameter: Frame buffer // Buffer parameter: Texture buffer +#define BUFFERPARAMETER_TEXTURE_GET_DIMENSION(bufferparam) (BUFFERPARAMETER_GET_PARAMETER(bufferparam) & 7) #define BUFFERPARAMETER_TEXTURE_1D 1 #define BUFFERPARAMETER_TEXTURE_2D 2 #define BUFFERPARAMETER_TEXTURE_3D 3 #define BUFFERPARAMETER_TEXTURE_4D 4 +// TODO: Change `2` once we add support for more formats +#define BUFFERPARAMETER_TEXTURE_GET_FORMAT(bufferparam) (BUFFERPARAMETER_GET_PARAMETER(bufferparam) >> 3 & 2) #define BUFFERPARAMETER_TEXTURE_FMT_RGBA8 (1 << 4) #define BUFFERPARAMETER_TEXTURE_FMT_SRGB8 (2 << 4) #define BUFFERPARAMETER_TEXTURE_FMT_SRGBA8 (3 << 4) @@ -263,7 +243,7 @@ typedef enum { typedef struct { i32 num_attached_buffers; - ivec4 dimensions; // All objects attached to a framebuffer (in OpenGL) must have same size + ivec3 dimensions; // All objects attached to a framebuffer (in OpenGL) must have same size } FramebufferParameters; // A render target takes a bunch of drawcalls, and renders it to a texture. @@ -273,22 +253,15 @@ typedef struct { // glFrameBuffer usize framebuffer_len; - // glTexture / glRenderBuffer / glBuffer / glWhatever - usize buffer_len; - u32 *framebuffer; - u32 *buffer; // Number of buffers attached to each of the framebuffers. Used to iteratively // get all buffers by summing the previous sizes to get the first buffer // associated with the current. FramebufferParameters *framebuffer_parameters; - // Stores per-buffer type, and type-specific parameters. - u32 *buffer_parameters; - - // One cam per framebuffer - Camera *cam; + // One cam per framebuffer, is usually a pointer to user-allocated camera + Camera **cam; //// Called when window is resized with new width and height. Set to NULL to //// skip changing texture_size. Comparable to glViewport. @@ -301,8 +274,38 @@ typedef struct { //// called with the new dimensions of the texture. //// Set to NULL to skip changing the camera size/perspective. void (**camera_reset_callback)(Camera*,ivec2); + + // glTexture / glRenderBuffer / glBuffer / glWhatever + usize buffer_len; + u32 *buffer; + // Stores per-buffer type, and type-specific parameters. + u32 *buffer_parameters; } RenderTargets; +usize ShaderBufferDataType_size(u16 flags); + +ShaderBufferFlag ShaderBuffer_get_access_frequency(u64 flags); +ShaderBufferFlag ShaderBuffer_get_access_type(u64 flags); +ShaderBufferFlag ShaderBuffer_get_type(u64 flags); +ShaderBufferFlag ShaderBuffer_get_data_type(u64 flags); + +/* Conversion to GL types */ +u32 ShaderBuffer_get_gl_type(u64 flags); +u32 ShaderBuffer_get_gl_accesstype(u64 flags); +u32 ShaderBuffer_get_gl_datatype(u64 flags); + +/* Misc */ +void r_perspective(Camera *c, f32 fov, ivec2 windowsize); +void r_perspective_ortho(Camera *c, f32 sz, ivec2 windowsize); + +void r_set_camera(RenderTargets *restrict t, i32 framebuffer_idx, Camera *restrict c); +void r_reset_camera(Camera* c, ivec2 windowsize); + +//void window_size_callback(GLFWwindow* window, i32 width, i32 height); + +// 3D positional coordinates and scale in last element of `pos` +void r_draw_model(void *restrict context, RenderTargets *restrict t, u32 framebuffer_idx, RenderObject* o, vec4 pos); + void r_camera_reset_default(Camera* c, ivec2 windowsize); RenderObject RenderObject_new( @@ -328,8 +331,9 @@ Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 hei void r_create_framebuffers(void* restrict ctx, u32* restrict framebuffer_array, usize num_targets); void r_destroy_framebuffers(void* restrict ctx, u32* restrict framebuffer_array, usize num_targets); -void r_create_textures(void *restrict ctx, u32* restrict texture_array, u32* restrict texture_types, ivec4* restrict texture_sizes, usize num_targets); +void r_create_textures(void *restrict ctx, u32* restrict texture_array, u32* restrict texture_types, ivec3* restrict texture_sizes, usize num_targets); void r_destroy_textures(void *restrict ctx, u32* textures, usize num_textures); +void r_attach_buffers(void *restrict ctx, u32 fbo, u32* buffers, u32* buffer_parameters, i32 num_buffers); void r_init_renderstack( usize num_fbuf, usize num_buf, diff --git a/src/include/daw/window.h b/src/include/daw/window.h index 44ea1fa..4e00774 100644 --- a/src/include/daw/window.h +++ b/src/include/daw/window.h @@ -99,9 +99,10 @@ Window* Window_new(const struct Platform *p, const char *restrict title, Window_ /* Rendering functions */ void render_begin(Window* w); -void render_present(Window* w); +void render_present(Window* w, RenderObject *restrict default_quad); void window_reset_drawing(void); void render(Window* w); +void draw_model(Window *restrict w, u32 framebuffer_idx, RenderObject* o, vec4 pos); void window_init_renderstack(Window *restrict w, usize num_fbuf, usize num_buf, diff --git a/src/platform_glfw.c b/src/platform_glfw.c index 5453258..92e29a2 100644 --- a/src/platform_glfw.c +++ b/src/platform_glfw.c @@ -133,6 +133,7 @@ void window_destroy_glfw(Window *restrict w) { void window_resize_glfw(Window *restrict window, int width, int height) { window_resize_callback(window->window, width, height); framebuffer_resize_callback(window->window, width, height); + DEBUG("Resizing to <%d,%d>\n", width, height); } bool window_should_close_glfw(Window *restrict window) { @@ -152,6 +153,7 @@ static void window_resize_callback(GLFWwindow* window, int width, int height) { const GladGLContext* gl = w->context; gl->Finish(); } + DEBUG("WINDOW RESIZE <%d,%d>\n", width, height); } static void framebuffer_resize_callback(GLFWwindow* window, int width, int height) { @@ -167,6 +169,7 @@ static void framebuffer_resize_callback(GLFWwindow* window, int width, int heigh //r_reset_camera(c); } + DEBUG("FRAMEBUFFER RESIZE <%d,%d>\n", width, height); } static void glfw_err_callback(int code, const char* description) { diff --git a/src/rendering.c b/src/rendering.c index 76df988..8f7104e 100644 --- a/src/rendering.c +++ b/src/rendering.c @@ -1,4 +1,3 @@ -#include #include #include @@ -11,16 +10,12 @@ #include #include #include +#include /* Extern globals */ extern Instance* GLOBAL_PLATFORM; -/* Globals */ -#define drawcall_limit (64 * 1024) -RenderDrawCall drawcalls[drawcall_limit]; -i32 drawcall_len = 0; - usize ShaderBufferDataType_size(u16 flags) { const ShaderBufferFlag t = ShaderBuffer_get_data_type(flags); @@ -441,114 +436,62 @@ void render_begin(Window* w) { ((GladGLContext*)(w->context))->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void render_present(Window* w) { - /* This is GL specific, TODO: move the GL-specific code elsewhere. Maybe make - * this whole present GL specific? assign it as a fn ptr in the Window struct? */ - GladGLContext *restrict gl = w->context; - Camera c = *GLOBAL_PLATFORM->cam; - - mat4 view; // view - vec3 angle; // viewing angle / direction of the camera - mat4 camera_matrix; - - glm_vec3_sub(c.pos, c.dir, angle); - glm_lookat(c.pos, angle, GLM_YUP, view); - glm_mat4_mul(c.per, view, camera_matrix); - - for (i32 drawcall_idx = 0; drawcall_idx < drawcall_len; drawcall_idx++) { - RenderDrawCall dc = drawcalls[drawcall_idx]; - - // bind shader program - // - set uniforms - // bind vertex array - // bind index buffer - - - const RenderObject* const restrict o = dc.model; - vec3 pos; - glm_vec3_copy(dc.pos, pos); - - gl->UseProgram(o->shader.program); - // TODO: Use texture atlas - gl->BindTextureUnit(0, o->texture); - - { - mat4 model = GLM_MAT4_IDENTITY_INIT; - mat4 modelviewprojection; - - model[3][0] = pos[0]; - model[3][1] = pos[1]; - model[3][2] = pos[2]; - - // modelviewprojection = p * view * model - glm_mat4_mul(model, camera_matrix, modelviewprojection); - - // TODO: Do this only once during initialization - gl->UniformMatrix4fv(o->mvp, 1, GL_FALSE, &modelviewprojection[0][0]); - gl->UniformMatrix4fv(o->model_position, 1, GL_FALSE, &model[0][0]); - } - - // TODO the buffers need to be abstracted a bit more - gl->BindVertexArray(o->vao); - - ShaderBuffer* ibo = NULL; - for (usize i = 0; i < o->buffer_len; i++) { - const u32 b_gl_type = ShaderBuffer_get_gl_type(o->buffer[i].buffertype); - if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) { - ibo = &o->buffer[i]; - } - - gl->EnableVertexAttribArray((u32)i); - gl->BindBuffer(b_gl_type, o->buffer[i].buffername); - gl->VertexAttribPointer( - // index of the attribute - (u32)i, - // number of component - (i32)o->buffer[i].components, - // type - ShaderBuffer_get_gl_datatype(o->buffer[i].buffertype), - // normalized? - GL_FALSE, - // stride - 0, - // array buffer offset - (void*)0 - ); - } - - // Draw the model ! - const i32 sz = (i32)(o->buffer->count * o->buffer->size_elem); - if (ibo) { - gl->DrawElements( - GL_TRIANGLES, - (i32)ibo->count, - ShaderBuffer_get_gl_datatype(ibo->buffertype), - (void*)0 - ); - } else { - // Starting from vertex 0; 3 vertices total -> 1 triangle - gl->DrawArrays(GL_TRIANGLES, 0, sz); +void render_present(Window* w, RenderObject *restrict default_quad) { + const GladGLContext *restrict gl = w->context; + gl->UseProgram(default_quad->shader.program); + gl->BindTextureUnit(0, default_quad->texture); + gl->BindVertexArray(default_quad->vao); + + ShaderBuffer* ibo = NULL; + for (usize i = 0; i < default_quad->buffer_len; i++) { + const u32 b_gl_type = ShaderBuffer_get_gl_type(default_quad->buffer[i].buffertype); + if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) { + ibo = &default_quad->buffer[i]; } - for (u32 i = 0; i < o->buffer_len; i++) { - gl->DisableVertexAttribArray(i); - } - - gl->BindVertexArray(0); - - //if (i == 8) { - // printf("\r obj: %.3f", (double)(get_time() - t) * 1000.); - //} - } - - drawcall_len = 0; + gl->EnableVertexAttribArray((u32)i); + gl->BindBuffer(b_gl_type, default_quad->buffer[i].buffername); + gl->VertexAttribPointer( + // index of the attribute + (u32)i, + // number of component + (i32)default_quad->buffer[i].components, + // type + ShaderBuffer_get_gl_datatype(default_quad->buffer[i].buffertype), + // normalized? + GL_FALSE, + // stride + 0, + // array buffer offset + (void*)0 + ); + } + + // Draw the model ! + const i32 sz = (i32)(default_quad->buffer->count * default_quad->buffer->size_elem); + if (ibo) { + gl->DrawElements( + GL_TRIANGLES, + (i32)ibo->count, + ShaderBuffer_get_gl_datatype(ibo->buffertype), + (void*)0 + ); + } else { + // Starting from vertex 0; 3 vertices total -> 1 triangle + gl->DrawArrays(GL_TRIANGLES, 0, sz); + } + + for (u32 i = 0; i < default_quad->buffer_len; i++) { + gl->DisableVertexAttribArray(i); + } + + gl->BindVertexArray(0); glfwSwapBuffers(w->window); } void window_reset_drawing(void) { - drawcall_len = 0; - memset(drawcalls, 0, sizeof(RenderDrawCall) * drawcall_limit); + // Clear } void r_perspective(Camera *c, f32 fov, ivec2 windowsize) { @@ -569,10 +512,12 @@ void r_perspective_ortho(Camera *c, f32 sz, ivec2 windowsize) { glm_ortho(-sz * ratio, sz * ratio, -sz, sz, -sz * 10.f, sz * 10.f, c->per); } -void r_set_camera(Camera* c) { - GLOBAL_PLATFORM->cam = c; -} +void r_set_camera(RenderTargets *restrict t, i32 framebuffer_idx, Camera *restrict c) { + ASSERT(t != NULL); + ASSERT(framebuffer_idx == -1 || framebuffer_idx < (i32)t->framebuffer_len); + t->cam[framebuffer_idx] = c; +} void r_reset_camera(Camera* c, ivec2 windowsize) { if (c->type == Camera_Perspective) { @@ -584,19 +529,92 @@ void r_reset_camera(Camera* c, ivec2 windowsize) { } -void engine_draw_model(RenderObject* o, vec4 pos) { - if (drawcall_len + 1 >= drawcall_limit) return; -#ifdef _DEBUG - if (o == NULL) __asm__("int3;"); -#endif - RenderDrawCall dc = { - .model = o, - .scale = pos[3], - }; +void r_draw_model(void *restrict context, RenderTargets *restrict t, u32 framebuffer_idx, RenderObject* o, vec4 pos) { + ASSERT(context != NULL); + ASSERT(t != NULL); + ASSERT(t->framebuffer != NULL); + ASSERT(t->cam != NULL); + ASSERT(t->cam[framebuffer_idx] != NULL); + + const GladGLContext *restrict gl = context; + Camera c = *t->cam[framebuffer_idx]; + //const f32 s = pos[3]; + + mat4 view; // view + vec3 angle; // viewing angle / direction of the camera + mat4 camera_matrix; + + glm_vec3_sub(c.pos, c.dir, angle); + glm_lookat(c.pos, angle, GLM_YUP, view); + glm_mat4_mul(c.per, view, camera_matrix); + + gl->UseProgram(o->shader.program); + // ENUMERATE FRAMEBUFFER TEXTURES + gl->BindTextureUnit(0, o->texture); - glm_vec3_copy(pos, dc.pos); + { + mat4 model = GLM_MAT4_IDENTITY_INIT; + mat4 modelviewprojection; - drawcalls[drawcall_len++] = dc; + model[3][0] = pos[0]; + model[3][1] = pos[1]; + model[3][2] = pos[2]; + + // modelviewprojection = p * view * model + glm_mat4_mul(model, camera_matrix, modelviewprojection); + + // TODO: Do this only once during initialization + gl->UniformMatrix4fv(o->mvp, 1, GL_FALSE, &modelviewprojection[0][0]); + gl->UniformMatrix4fv(o->model_position, 1, GL_FALSE, &model[0][0]); + } + + // TODO the buffers need to be abstracted a bit more + gl->BindVertexArray(o->vao); + + ShaderBuffer* ibo = NULL; + for (usize i = 0; i < o->buffer_len; i++) { + const u32 b_gl_type = ShaderBuffer_get_gl_type(o->buffer[i].buffertype); + if (b_gl_type == GL_ELEMENT_ARRAY_BUFFER) { + ibo = &o->buffer[i]; + } + + gl->EnableVertexAttribArray((u32)i); + gl->BindBuffer(b_gl_type, o->buffer[i].buffername); + gl->VertexAttribPointer( + // index of the attribute + (u32)i, + // number of component + (i32)o->buffer[i].components, + // type + ShaderBuffer_get_gl_datatype(o->buffer[i].buffertype), + // normalized? + GL_FALSE, + // stride + 0, + // array buffer offset + (void*)0 + ); + } + + // Draw the model ! + const i32 sz = (i32)(o->buffer->count * o->buffer->size_elem); + if (ibo) { + gl->DrawElements( + GL_TRIANGLES, + (i32)ibo->count, + ShaderBuffer_get_gl_datatype(ibo->buffertype), + (void*)0 + ); + } else { + // Starting from vertex 0; 3 vertices total -> 1 triangle + gl->DrawArrays(GL_TRIANGLES, 0, sz); + } + + for (u32 i = 0; i < o->buffer_len; i++) { + gl->DisableVertexAttribArray(i); + } + + gl->BindVertexArray(0); } @@ -691,22 +709,100 @@ void r_destroy_framebuffers(void* restrict ctx, u32* restrict framebuffer_array, } void r_create_textures(void* restrict ctx, u32* restrict texture_array, - u32* restrict texture_types, - ivec4* restrict texture_size, usize num_targets) { + u32* restrict texture_parameters, + ivec3* restrict texture_size, usize num_targets) { const GladGLContext* gl = (GladGLContext*)ctx; - gl->CreateTextures(GL_TEXTURE_2D, num_targets, texture_array); + u32 texture_dim = BUFFERPARAMETER_TEXTURE_GET_DIMENSION(texture_parameters[0]); + u32 texture_format = BUFFERPARAMETER_TEXTURE_GET_DIMENSION(texture_parameters[0]); + u32 gl_texture_format; + u32 err; + + for (usize i = 1; i < num_targets; i++) { + ASSERT(texture_dim == BUFFERPARAMETER_TEXTURE_GET_DIMENSION(texture_parameters[i])); + ASSERT(texture_format == BUFFERPARAMETER_TEXTURE_GET_FORMAT(texture_parameters[i])); + } + + switch (texture_format) { + case BUFFERPARAMETER_TEXTURE_FMT_RGBA8: gl_texture_format = GL_RGBA8; break; + case BUFFERPARAMETER_TEXTURE_FMT_SRGB8: gl_texture_format = GL_SRGB; break; + case BUFFERPARAMETER_TEXTURE_FMT_SRGBA8: gl_texture_format = GL_SRGB8_ALPHA8; break; + default: + ERROR("Failed to convert format to GL internal format!"); + exit(EXIT_FAILURE); + } + + // Convert the texturetype to GL texturetype + switch (texture_dim) { + case BUFFERPARAMETER_TEXTURE_1D: + gl->CreateTextures(GL_TEXTURE_1D, num_targets, texture_array); + for (usize i = 0; i < num_targets; i++) { + gl->TextureStorage1D(texture_array[i], 1, gl_texture_format, *texture_size[0]); + } + break; + + case BUFFERPARAMETER_TEXTURE_2D: + gl->CreateTextures(GL_TEXTURE_2D, num_targets, texture_array); + for (usize i = 0; i < num_targets; i++) { + gl->TextureStorage2D(texture_array[i], 1, gl_texture_format, *texture_size[0], *texture_size[1]); + } + break; + + case BUFFERPARAMETER_TEXTURE_3D: + gl->CreateTextures(GL_TEXTURE_3D, num_targets, texture_array); + for (usize i = 0; i < num_targets; i++) { + gl->TextureStorage3D(texture_array[i], 1, gl_texture_format, *texture_size[0], *texture_size[1], *texture_size[2]); + } + break; + + case BUFFERPARAMETER_TEXTURE_4D: + ERROR("4D textures are unsupported!"); + exit(EXIT_FAILURE); + default: + ERROR("Failed to convert dimensionality to GL_TEXTURE_XD"); + exit(EXIT_FAILURE); + } + err = gl->GetError(); + + if (err) { + ERROR("Failed to create textures!"); + } + + // This should probably be changed in the future for (usize i = 0; i < num_targets; i++) { - ASSERT("SWITCH CASE ON BUFFER DIMENSIONALITY"); - ASSERT("SWITCH CASE ON TEXTURE DATA TYPE"); - gl->TextureStorage2D(texture_array[i], 1, texture_types[i], *texture_size[0], *texture_size[1]); gl->TextureParameteri(texture_array[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->TextureParameteri(texture_array[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST); } + + err = gl->GetError(); + + if (err) { + ERROR("Failed to set texture parameters!"); + } } void r_destroy_textures(void *restrict ctx, u32* textures, usize num_textures) { const GladGLContext* gl = (GladGLContext*)ctx; gl->DeleteTextures(num_textures, textures); } + +void r_attach_buffers(void *restrict ctx, u32 fbo, u32* buffers, u32* buffer_parameters, i32 num_buffers) { + const GladGLContext *restrict gl = (GladGLContext*)ctx; + + u32 err; + + for (i32 i = 0; i < num_buffers; i++) { + BufferType t = BUFFERPARAMETER_GET_TYPE(buffer_parameters[i]); + + if (t != BufferType_texture) UNIMPLEMENTED; + + // TODO: FINISH ME + gl->NamedFramebufferTexture(fbo, GL_COLOR_ATTACHMENT0 + i, buffers[i], 0); + + err = gl->GetError(); + if (err) { + ERROR("Failed to attach buffer!"); + } + } +} diff --git a/src/window.c b/src/window.c index 9702a7f..72717ab 100644 --- a/src/window.c +++ b/src/window.c @@ -78,7 +78,7 @@ void window_reset_cameras(Window* w, RenderTargets* restrict targets) { // Destroy & Create framebuffers (and related buffers?) if (targets->camera_reset_callback[i] == NULL) continue; - (*targets->camera_reset_callback)(&targets->cam[i], w->windowsize); + targets->camera_reset_callback[i](targets->cam[i], w->windowsize); } } @@ -130,10 +130,11 @@ void window_init_renderstack(Window *restrict w, void* allocation = malloc( sizeof(RenderTargets) + sizeof(*t->framebuffer) * num_fbuf + - sizeof(*t->buffer) * num_buf + sizeof(*t->framebuffer_parameters) * num_fbuf + - sizeof(*t->buffer_parameters) * num_buf + - sizeof(*t->cam) * num_fbuf + sizeof(*t->cam) * num_fbuf + + sizeof(*t->camera_reset_callback) * num_fbuf + + sizeof(*t->buffer) * num_buf + + sizeof(*t->buffer_parameters) * num_buf // TODO: callbacks ); @@ -148,28 +149,36 @@ void window_init_renderstack(Window *restrict w, u64 acc = sizeof(RenderTargets); ADVANCE_PTR(framebuffer, num_fbuf); - ADVANCE_PTR(buffer, num_buf); ADVANCE_PTR(framebuffer_parameters, num_fbuf); - ADVANCE_PTR(buffer_parameters, num_buf); ADVANCE_PTR(cam, num_fbuf); + ADVANCE_PTR(camera_reset_callback, num_fbuf); + ADVANCE_PTR(buffer, num_buf); + ADVANCE_PTR(buffer_parameters, num_buf); // TODO: callbacks #undef ADVANCE_PTR memcpy(t->framebuffer_parameters, fb_params, sizeof(*t->framebuffer_parameters) * num_fbuf); memcpy(t->buffer_parameters, buffer_params, sizeof(*t->buffer_parameters) * num_buf); + r_create_framebuffers(w->context, &t->framebuffer[0], num_fbuf); + // Iteratively set up each framebuffer and framebuffer-attached objects usize buffer_offset = 0; for (usize fb_idx = 0; fb_idx < num_fbuf; fb_idx++) { FramebufferParameters *p = &t->framebuffer_parameters[fb_idx]; // Check everything is a texture, cuz rn. we don't support anything else for (isize buffer_idx = 0; buffer_idx < p->num_attached_buffers; buffer_idx++) { - ASSERT(BUFFERPARAMETER_GET_TYPE(t->buffer_parameters[buffer_idx + buffer_offset]) == BufferType_texture); + ASSERT(BUFFERPARAMETER_GET_TYPE(t->buffer_parameters[buffer_offset + buffer_idx]) == BufferType_texture); } + + // Create `num_attached_buffers` identical buffers r_create_textures(w->context, &t->buffer[buffer_offset], &t->buffer_parameters[buffer_offset], &t->framebuffer_parameters[fb_idx].dimensions, t->framebuffer_parameters[fb_idx].num_attached_buffers); + + r_attach_buffers(w->context, t->framebuffer[fb_idx], &t->buffer[buffer_offset], &t->buffer_parameters[buffer_offset], t->framebuffer_parameters[fb_idx].num_attached_buffers); + //if (BUFFERPARAMETER_GET_TYPE(buffer_params[i]) != BufferType_texture) continue; //u32 texture_type = BUFFERPARAMETER_GET_PARAMETER(buffer_params[i]); @@ -195,3 +204,7 @@ void window_free_renderstack(RenderTargets *restrict t) { // Everything is in the same buffer anyways free(t->framebuffer); } + +void draw_model(Window *restrict w, u32 framebuffer_idx, RenderObject* o, vec4 pos) { + r_draw_model(w->context, w->render_targets, framebuffer_idx, o, pos); +} -- cgit v1.3