summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoronelin <oscar@nelin.dk>2025-12-17 12:48:51 +0000
committeronelin <oscar@nelin.dk>2025-12-18 21:14:22 +0000
commit99d49b59e99cc94d18efd3ff0e33a25d7356bae9 (patch)
treed60fdcdf59c7f75307b6f57c3ac8734999425971 /src
parent261d33c72095a2abd98177f88ebb24fe205a042f (diff)
Add framebuffer resizing
Diffstat (limited to 'src')
-rw-r--r--src/daw.c27
-rw-r--r--src/include/daw/rendering.h55
-rw-r--r--src/rendering.c27
-rw-r--r--src/window.c126
4 files changed, 132 insertions, 103 deletions
diff --git a/src/daw.c b/src/daw.c
index 79b230c..2659f3b 100644
--- a/src/daw.c
+++ b/src/daw.c
@@ -248,17 +248,17 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) {
ivec2 wsz;
window_get_size(&wsz);
u32 t[] = {
- BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_TEXTURE_2D | BUFFERPARAMETER_FMT_RGB8),
+ BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_FMT_RGB8),
// The depth buffer could also be a texture like so:
// BUFFERPARAMETER_SET_PARAMETER(
// BUFFERPARAMETER_SET_TYPE(0, BufferType_texture),
- // BUFFERPARAMETER_TEXTURE_2D | BUFFERPARAMETER_FMT_DEPTH32
+ // BUFFERPARAMETER_FMT_DEPTH32
// ),
- BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_render), BUFFERPARAMETER_RENDERBUFFER_DEPTH | BUFFERPARAMETER_FMT_DEPTH32F),
+ BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_render), BUFFERPARAMETER_FMT_DEPTH32F),
};
FramebufferParameters p[] = {
- {.num_attached_buffers = sizeof(t) / sizeof(t[0]), .dimensions = {wsz[0], wsz[1], 0}},
+ {.num_textures = 1, .num_renderbuffers = 1, .dimensions = {wsz[0], wsz[1], 0}},
};
window_init_renderstack(w, 1, sizeof(t) / sizeof(t[0]), p, t);
//w->render_targets->cam[0] = &default_renderbuffer_camera;
@@ -342,13 +342,22 @@ 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 fb_params[] = {
- {.num_attached_buffers = 1, {200,200}},
- };
+ ivec2 wsz;
+ window_get_size(&wsz);
u32 t[] = {
- BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_TEXTURE_2D)
+ BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_texture), BUFFERPARAMETER_FMT_RGB8),
+
+ // The depth buffer could also be a texture like so:
+ // BUFFERPARAMETER_SET_PARAMETER(
+ // BUFFERPARAMETER_SET_TYPE(0, BufferType_texture),
+ // BUFFERPARAMETER_FMT_DEPTH32
+ // ),
+ BUFFERPARAMETER_SET_PARAMETER(BUFFERPARAMETER_SET_TYPE(0, BufferType_render), BUFFERPARAMETER_FMT_DEPTH32F),
+ };
+ FramebufferParameters p[] = {
+ {.num_textures = 1, .num_renderbuffers = 1, .dimensions = {wsz[0], wsz[1], 0}},
};
- window_init_renderstack(w, 1, 1, fb_params, t);
+ window_init_renderstack(w, 1, sizeof(t) / sizeof(t[0]), p, t);
//w->render_targets->cam[0] = &default_camera;
}
diff --git a/src/include/daw/rendering.h b/src/include/daw/rendering.h
index 530a8e0..70b1566 100644
--- a/src/include/daw/rendering.h
+++ b/src/include/daw/rendering.h
@@ -264,26 +264,39 @@ typedef enum {
// TODO: Change `2` once we add support for more formats
-#define BUFFERPARAMETER_FMT_GET(bufferparam) (BUFFERPARAMETER_GET_PARAMETER(bufferparam) & (((1 << 8) - 1) << 2))
-
#define BUFFERPARAMETER_FMT_IS_COLOR(bufferparam) \
((BUFFERPARAMETER_GET_PARAMETER(bufferparam) & BUFFERPARAMETER_FMT_COLOR_MASK) != 0)
#define BUFFERPARAMETER_FMT_IS_DEPTH_OR_STENCIL(bufferparam) \
((BUFFERPARAMETER_GET_PARAMETER(bufferparam) & BUFFERPARAMETER_FMT_DEPTH_STENCIL_MASK) != 0)
+// The textures and renderbuffers must be contigous in the rendertargets
+// `buffer` and `buffer_parameters` members
typedef struct {
- i32 num_attached_buffers;
- ivec3 dimensions; // All objects attached to a framebuffer (in OpenGL) must have same size
+ // Number of attached textures
+ i8 num_textures;
+ // Number of attached renderbuffers
+ i8 num_renderbuffers;
+ // All objects attached to a framebuffer (at least in OpenGL) must have same
+ // size. Set the remainding dimensions to zero to indicate they're unused
+ // even though, mathematically speaking, they should be one.
+ ivec3 dimensions;
} FramebufferParameters;
-// A render target takes a bunch of drawcalls, and renders it to a texture.
+// A render target takes a bunch of drawcalls, and renders it to either a
+// texture or buffer.
// TODO: user runs "init" for their rendertarget(s) "stack", possibly using some
-// predefined macro "DEFAULT_RENDERTARGETS". Requires user to specify number of lights et. al.
+// predefined macro "DEFAULT_RENDERTARGETS". Requires user to specify number of
+// lights et. al.
+// The RenderTargets is technically two SOAs:
+// * framebuffers, holding the OpenGL "framebuffer name", buffer parameters,
+// camera, and resize callbacks,
+// * and "buffers" (generalized name for "textures" and "renderbuffers")
typedef struct {
- // glFrameBuffer
+ // Number of framebuffers.
usize framebuffer_len;
+ // OpenGL "names"
u32 *framebuffer;
// Number of buffers attached to each of the framebuffers. Used to iteratively
@@ -294,22 +307,25 @@ typedef struct {
// 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.
- //// This function can be heavy due to it destroying and re-creating framebuffers.
- //// Which requires me to store the parameters that they we're created with.
- //void (**framebuffer_size_callback)(ivec2*,ivec2);
+ // Indirectly called when window is resized with new width and height. Set to
+ // NULL to skip changing framebuffer_size. Comparable to glViewport.
+ // This function can be heavy due to it destroying and re-creating buffers,
+ // textures and framebuffers.
+ void (**framebuffer_size_callback)(ivec3* dst,ivec2 src);
- //// Called when window is resized. Calls the respective texture_size_callback function at
- //// the same index if not null. The camera resize callback function is then
- //// called with the new dimensions of the texture.
- //// Set to NULL to skip changing the camera size/perspective.
- void (**camera_reset_callback)(Camera*,ivec2);
+ // Called when window is resized. Calls the respective framebuffer_size_callback function at
+ // the same index if not null. The camera resize callback function is then
+ // called with the new dimensions of the framebuffer if
+ // framebuffer_size_callback is not null, otherwise called with
+ // the new window size.
+ // Set to NULL to skip changing the camera size/perspective.
+ void (**camera_reset_callback)(Camera*,ivec2 src);
- // glTexture / glRenderBuffer / glBuffer / glWhatever.
+ // glTexture and glRenderBuffer
// Currently, each buffer must be either a texture or a (depth and/or stencil)
// buffer.
usize buffer_len;
+ // OpenGL buffer names
u32 *buffer;
// Stores per-buffer type, and type-specific parameters.
u32 *buffer_parameters;
@@ -362,6 +378,9 @@ ShaderType guess_shadertype_from_filename(const char *restrict fname);
Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 height, u8 components);
+// Creates and initializes buffers for the framebuffer
+void r_setup_framebuffer(void *restrict ctx, u32 framebuffer_id, FramebufferParameters param, u32 *restrict buffer_array, u32 *restrict buffer_parameters);
+
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, ivec3* restrict texture_sizes, usize num_targets);
diff --git a/src/rendering.c b/src/rendering.c
index 0643c70..8c3846d 100644
--- a/src/rendering.c
+++ b/src/rendering.c
@@ -4,6 +4,7 @@
#include <GLFW/glfw3.h>
#include <cglm/cam.h>
#include <cglm/vec2.h>
+#include <cglm/ivec3.h>
#include <cglm/mat4.h>
@@ -707,6 +708,24 @@ void r_init_renderstack(
window_init_renderstack(GLOBAL_PLATFORM->window, num_fbuf, num_buf, fb_params, buffer_params);
}
+void r_setup_framebuffer(void *restrict ctx, u32 framebuffer_id, FramebufferParameters param, u32 *restrict buffer_array, u32 *restrict buffer_parameters) {
+ r_create_textures(ctx, buffer_array,
+ buffer_parameters,
+ &param.dimensions,
+ param.num_textures);
+
+ r_create_renderbuffers(ctx, &buffer_array[param.num_textures],
+ &buffer_parameters[param.num_textures],
+ &param.dimensions,
+ param.num_renderbuffers);
+
+ r_attach_buffers(ctx,
+ framebuffer_id,
+ buffer_array,
+ buffer_parameters,
+ param.num_textures + param.num_renderbuffers);
+}
+
void r_create_framebuffers(void* restrict ctx, u32* restrict framebuffer_array,
usize num_targets) {
const GladGLContext* gl = (GladGLContext*)ctx;
@@ -764,7 +783,7 @@ void r_create_textures(void* restrict ctx, u32* restrict texture_array,
gl->CreateTextures(GL_TEXTURE_1D, num_targets, texture_array);
ASSERT(!gl->GetError());
for (usize i = 0; i < num_targets; i++) {
- gl->TextureStorage1D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_FMT_GET(texture_parameters[i])), texture_sz[0]);
+ gl->TextureStorage1D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_GET_PARAMETER(texture_parameters[i])), texture_sz[0]);
}
break;
@@ -772,7 +791,7 @@ void r_create_textures(void* restrict ctx, u32* restrict texture_array,
gl->CreateTextures(GL_TEXTURE_2D, num_targets, texture_array);
ASSERT(!gl->GetError());
for (usize i = 0; i < num_targets; i++) {
- gl->TextureStorage2D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_FMT_GET(texture_parameters[i])), texture_sz[0], texture_sz[1]);
+ gl->TextureStorage2D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_GET_PARAMETER(texture_parameters[i])), texture_sz[0], texture_sz[1]);
}
break;
@@ -780,7 +799,7 @@ void r_create_textures(void* restrict ctx, u32* restrict texture_array,
gl->CreateTextures(GL_TEXTURE_3D, num_targets, texture_array);
ASSERT(!gl->GetError());
for (usize i = 0; i < num_targets; i++) {
- gl->TextureStorage3D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_FMT_GET(texture_parameters[i])), texture_sz[0], texture_sz[1], texture_sz[2]);
+ gl->TextureStorage3D(texture_array[i], 1, gl_texture_format(BUFFERPARAMETER_GET_PARAMETER(texture_parameters[i])), texture_sz[0], texture_sz[1], texture_sz[2]);
}
break;
@@ -834,7 +853,7 @@ void r_create_renderbuffers(void *restrict ctx, u32* restrict buffer_array, u32*
for (usize i = 0; i < num_buffers; i++) {
gl->NamedRenderbufferStorage(
buffer_array[i],
- gl_texture_format(BUFFERPARAMETER_FMT_GET(buffer_types[i])),
+ gl_texture_format(BUFFERPARAMETER_GET_PARAMETER(buffer_types[i])),
buffer_sizes[i][0],
buffer_sizes[i][1]
);
diff --git a/src/window.c b/src/window.c
index 36c1612..142e8bd 100644
--- a/src/window.c
+++ b/src/window.c
@@ -15,6 +15,7 @@
#include <GLFW/glfw3.h>
#include <cglm/ivec2.h>
+#include <cglm/ivec3.h>
extern Instance* GLOBAL_PLATFORM;
@@ -68,35 +69,58 @@ Window* Window_new(const struct Platform* p, const char *restrict title, Window_
void window_reset_cameras(Window* w, RenderTargets* restrict targets) {
- // Question, would it be better to check both callbacks and continue early,
- // instead of resizing the texture first, then check the camera callback?
+ usize b_ofst = 0;
for (usize i = 0; i < targets->framebuffer_len; i++) {
- //if (targets->framebuffer_size_callback[i] == NULL) continue;
+ ivec3 newsz;
+ // Set last dimension to 0 to ensure 2d
+ newsz[2] = 0;
+ // Well aware that we copy a smaller sized vec into a larger one, thank you.
+ glm_ivec2_copy(w->windowsize, newsz);
- //ivec2 newsz;
- //targets->framebuffer_size_callback[i](&newsz, w->windowsize);
+ const i8 num_textures = targets->framebuffer_parameters[i].num_textures;
+ const i8 num_renderbuffers = targets->framebuffer_parameters[i].num_renderbuffers;
- // Destroy & Create framebuffers (and related buffers?)
+ // Change framebuffer & attached buffers dimensions, if framebuffer resize callback exists
+ if (targets->framebuffer_size_callback[i] != NULL) {
+ targets->framebuffer_size_callback[i](&newsz, w->windowsize);
- if (targets->camera_reset_callback[i] == NULL) continue;
- targets->camera_reset_callback[i](targets->cam[i], w->windowsize);
+ // as far as I can tell from the OpenGL docs, it should be safe to just
+ // delete framebuffers and attached buffers
+ u32 *buffer = &targets->buffer[b_ofst];
+ if (num_textures != 0) {
+ r_destroy_textures(w->context, buffer, targets->framebuffer_parameters[i].num_textures);
+ // Move buf ptr
+ }
+
+ if (num_renderbuffers != 0) {
+ // renderbuffer(s) should be located after "textures", so their index
+ // starts at num_textures.
+ r_destroy_renderbuffers(w->context, &buffer[num_textures], targets->framebuffer_parameters[i].num_renderbuffers);
+ }
+
+ r_destroy_framebuffers(w->context, &targets->framebuffer[i], 1);
+
+
+ // TODO: Re-Create framebuffers and related buffers with new sizes.
+ glm_ivec3_copy(newsz, targets->framebuffer_parameters[i].dimensions);
+
+ r_create_framebuffers(w->context, &targets->framebuffer[i], 1);
+
+ r_setup_framebuffer(w->context, targets->framebuffer[i],
+ targets->framebuffer_parameters[i],
+ buffer,
+ &targets->buffer_parameters[b_ofst]);
+ }
+
+ // Reset camera using callback (if any)
+ if (targets->camera_reset_callback[i] != NULL) {
+ targets->camera_reset_callback[i](targets->cam[i], newsz);
+ }
+
+ b_ofst += num_textures + num_renderbuffers;
}
}
-//void window_reset_texture_sizes(Window* w, RenderTargets* restrict targets) {
-// // Question, would it be more efficient to just wipe all of them at once
-// // instead of doing this? Not all are necessarily deleted.
-// for (usize i = 0; i < targets->texture_len; i++) {
-// if (targets->framebuffer_size_callback[i] == NULL) continue;
-//
-// ivec2 newsz;
-// targets->framebuffer_size_callback[i](&newsz, w->windowsize);
-//
-// r_destroy_framebuffers(w->context, targets->framebuffer, 1);
-// r_create_framebuffers(w->context, &targets->framebuffer[i], &targets->framebuffer_parameters[i].framebuffer_type, &newsz, 1);
-// }
-//}
-
void get_mousepos(double *x, double *y) {
Window* w = GLOBAL_PLATFORM->window;
@@ -133,6 +157,7 @@ void window_init_renderstack(Window *restrict w,
sizeof(*t->framebuffer) * num_fbuf +
sizeof(*t->framebuffer_parameters) * num_fbuf +
sizeof(*t->cam) * num_fbuf +
+ sizeof(*t->framebuffer_size_callback) * num_fbuf +
sizeof(*t->camera_reset_callback) * num_fbuf +
sizeof(*t->buffer) * num_buf +
sizeof(*t->buffer_parameters) * num_buf
@@ -152,6 +177,7 @@ void window_init_renderstack(Window *restrict w,
ADVANCE_PTR(framebuffer, num_fbuf);
ADVANCE_PTR(framebuffer_parameters, num_fbuf);
ADVANCE_PTR(cam, num_fbuf);
+ ADVANCE_PTR(framebuffer_size_callback, num_fbuf);
ADVANCE_PTR(camera_reset_callback, num_fbuf);
ADVANCE_PTR(buffer, num_buf);
ADVANCE_PTR(buffer_parameters, num_buf);
@@ -167,59 +193,15 @@ void window_init_renderstack(Window *restrict w,
usize buffer_offset = 0;
for (usize fb_idx = 0; fb_idx < num_fbuf; fb_idx++) {
- // Count textures & renderbuffers
- u32 num_textures = 0;
- u32 num_renderbuffers = 0;
- for (i32 i = 0; i < t->framebuffer_parameters[fb_idx].num_attached_buffers; i++) {
- switch (BUFFERPARAMETER_GET_TYPE(t->buffer_parameters[buffer_offset + i])) {
- case BufferType_frame:
- UNIMPLEMENTED;
- case BufferType_texture:
- num_textures++;
- break;
- case BufferType_render:
- num_renderbuffers++;
- break;
- case BufferType_buffer:
- UNIMPLEMENTED;
- default:
- UNIMPLEMENTED;
- }
- }
-
- // 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,
- num_textures);
-
- r_create_renderbuffers(w->context, &t->buffer[buffer_offset + num_textures],
- &t->buffer_parameters[buffer_offset + num_textures],
- &t->framebuffer_parameters[fb_idx].dimensions,
- num_renderbuffers);
-
- r_attach_buffers(w->context,
- t->framebuffer[fb_idx],
+ r_setup_framebuffer(w->context, t->framebuffer[fb_idx],
+ t->framebuffer_parameters[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]);
+ &t->buffer_parameters[buffer_offset]);
- //usize span = 0;
- //while (
- // (i + span < targets->buffer_len) &&
- // (BUFFERPARAMETER_GET_TYPE(buffer_params[i + span]) == BufferType_texture) &&
- // (buffer_params[i + span].buffer_param & 3) == textureType
- //) {
- // span++;
- //}
- //if (span == 0) continue;
- //r_create_textures(w->context, &targets->buffer[i], texture_type, texturesizes, span);
+ buffer_offset +=
+ t->framebuffer_parameters[fb_idx].num_textures
+ + t->framebuffer_parameters[fb_idx].num_renderbuffers;
}
- //r_create_renderbuffers(c, targets->renderbuffer, renderbuffertypes, renderbuffersizes, targets->renderbuffer_len);
- // Skip `texture` (??)
w->render_targets = t;
}