summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/daw.c29
-rw-r--r--src/include/daw/rendering.h107
-rw-r--r--src/include/daw/window.h20
-rw-r--r--src/rendering.c63
-rw-r--r--src/window.c121
5 files changed, 315 insertions, 25 deletions
diff --git a/src/daw.c b/src/daw.c
index 163f484..fa607f0 100644
--- a/src/daw.c
+++ b/src/daw.c
@@ -171,9 +171,24 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) {
StateType state = initial_state;
+ Window* w = p->window;
+
{
u64 state_init_time = get_time();
State_init(state, mem, state_arg);
+ if (!w->render_targets) {
+ // 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[] = {
+ {.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;
+ }
INFO("Initializing state \"%s\" took %.1fns", StateTypeStr[state],
(get_time() - state_init_time));
}
@@ -222,12 +237,26 @@ i32 engine_run(Instance* p, StateType initial_state, void* state_arg) {
// Reset camera to default camera
p->cam = &default_camera;
+ free(w->render_targets);
state = next_state;
update_func = State_updateFunc(state);
{
u64 state_init_time = get_time();
State_init(state, mem, retval);
+ if (!w->render_targets) {
+ // 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[] = {
+ {.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;
+ }
INFO("Initializing state \"%s\" took %.1fns", StateTypeStr[state],
(get_time() - state_init_time));
}
diff --git a/src/include/daw/rendering.h b/src/include/daw/rendering.h
index 9c4b647..17d3728 100644
--- a/src/include/daw/rendering.h
+++ b/src/include/daw/rendering.h
@@ -204,15 +204,16 @@ u32 ShaderBuffer_get_gl_accesstype(u64 flags);
u32 ShaderBuffer_get_gl_datatype(u64 flags);
/* Misc */
-void r_perspective(f32 fov, Camera *c);
-void r_perspective_ortho(f32 sz, Camera *c);
+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);
+void r_reset_camera(Camera* c, ivec2 windowsize);
//void window_size_callback(GLFWwindow* window, i32 width, i32 height);
-void engine_draw_model(RenderObject* o, vec3 pos);
+// 3D positional coordinates and scale in last element of `pos`
+void engine_draw_model(RenderObject* o, vec4 pos);
typedef struct {
vec3 pos;
@@ -220,7 +221,89 @@ typedef struct {
RenderObject* model;
} RenderDrawCall;
-// TODO make all the shader buffers a list
+typedef enum {
+ BufferType_frame = 1,
+ BufferType_texture = 2,
+ BufferType_render = 3,
+ BufferType_buffer = 4,
+
+} BufferType;
+
+// Buffer parameter: Frame buffer
+// Buffer parameter: Texture buffer
+#define BUFFERPARAMETER_TEXTURE_1D 1
+#define BUFFERPARAMETER_TEXTURE_2D 2
+#define BUFFERPARAMETER_TEXTURE_3D 3
+#define BUFFERPARAMETER_TEXTURE_4D 4
+
+#define BUFFERPARAMETER_TEXTURE_FMT_RGBA8 (1 << 4)
+#define BUFFERPARAMETER_TEXTURE_FMT_SRGB8 (2 << 4)
+#define BUFFERPARAMETER_TEXTURE_FMT_SRGBA8 (3 << 4)
+
+//TODO: texture formats
+
+// Buffer parameter: Buffer buffer
+#define BUFFERPARAMETER_BUFFER_DEPTH 1
+#define BUFFERPARAMETER_BUFFER_STENCIL 2
+
+// `buffer_definition` has the first 4 bits for the type,
+#define BUFFERPARAMETER_MASK_TYPE ((1 << 4) - 1)
+// next 16 bits for the type-specific parameters
+#define BUFFERPARAMETER_MASK_PARAMETER (((1 << 16) - 1) << 4)
+
+#define BUFFERPARAMETER_GET_TYPE(bufferparam) \
+ (BufferType)(bufferparam & BUFFERPARAMETER_MASK_TYPE)
+#define BUFFERPARAMETER_GET_PARAMETER(bufferparam) \
+ ((bufferparam & BUFFERPARAMETER_MASK_TYPE) >> 4)
+
+#define BUFFERPARAMETER_SET_TYPE(bufferparam, type) \
+ (BufferType)((bufferparam & ~BUFFERPARAMETER_MASK_TYPE) | type)
+#define BUFFERPARAMETER_SET_PARAMETER(bufferparam, param) \
+ ((bufferparam & ~BUFFERPARAMETER_MASK_PARAMETER) | (param << 4))
+
+typedef struct {
+ i32 num_attached_buffers;
+ ivec4 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.
+// 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.
+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;
+
+ //// 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);
+
+ //// 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);
+} RenderTargets;
+
+void r_camera_reset_default(Camera* c, ivec2 windowsize);
RenderObject RenderObject_new(
Shader* shader,
@@ -242,6 +325,20 @@ ShaderType guess_shadertype_from_filename(const char *restrict fname);
Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 height, u8 components);
+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_destroy_textures(void *restrict ctx, u32* textures, usize num_textures);
+
+void r_init_renderstack(
+ usize num_fbuf, usize num_buf,
+ FramebufferParameters *restrict fb_params,
+ u32 *restrict buffer_params
+ );
+
+//static void r_create_renderbuffers(GladGLContext* restrict ctx, u32* restrict renderbuffer_array, u32* restrict renderbuffer_types, ivec2* restrict renderbuffer_sizes, usize num_targets);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/include/daw/window.h b/src/include/daw/window.h
index f445860..44ea1fa 100644
--- a/src/include/daw/window.h
+++ b/src/include/daw/window.h
@@ -12,6 +12,10 @@ extern "C" {
#include <daw/rendering.h>
+#define DAW_WINDOW_VSYNC (1 << 0)
+#define DAW_WINDOW_FULLSCREEN (1 << 1)
+#define DAW_WINDOW_RESIZEABLE (1 << 2)
+
typedef enum {
WINDOW_FRAMEWORK_NONE = 0,
WINDOW_FRAMEWORK_GLFW,
@@ -39,11 +43,13 @@ typedef struct {
usize bindings_sz;
usize bindings_len;
i_ctx** bindings;
-} Window;
-#define DAW_WINDOW_VSYNC (1 << 0)
-#define DAW_WINDOW_FULLSCREEN (1 << 1)
-#define DAW_WINDOW_RESIZEABLE (1 << 2)
+ /* The first element in the stack is the one presented to the screen. This is
+ * usually used for post-processing effects and can depend on previous
+ * RenderTextures. Use cases vary from shadowmapping, secondary in-game
+ * cameras, and UI. */
+ RenderTargets *render_targets;
+} Window;
// Whether or not it is clever to force API consistency using a struct like this
// can be debated, at the time of writing it seemed like a smart idea.
@@ -97,6 +103,12 @@ void render_present(Window* w);
void window_reset_drawing(void);
void render(Window* w);
+void window_init_renderstack(Window *restrict w,
+ usize num_fbuf, usize num_buf,
+ FramebufferParameters *restrict fb_params,
+ u32 *restrict buffer_params
+ );
+
void get_mousepos(double *x, double *y);
void window_get_size(ivec2* dst);
diff --git a/src/rendering.c b/src/rendering.c
index 25ee1fd..76df988 100644
--- a/src/rendering.c
+++ b/src/rendering.c
@@ -551,9 +551,8 @@ void window_reset_drawing(void) {
memset(drawcalls, 0, sizeof(RenderDrawCall) * drawcall_limit);
}
-void r_perspective(f32 fov, Camera *c) {
- const f32 ratio = (f32)GLOBAL_PLATFORM->window->windowsize[0]
- / (f32)GLOBAL_PLATFORM->window->windowsize[1];
+void r_perspective(Camera *c, f32 fov, ivec2 windowsize) {
+ const f32 ratio = (f32)windowsize[0] / (f32)windowsize[1];
c->type = Camera_Perspective;
c->parameters.perspective.fov = fov;
@@ -561,9 +560,8 @@ void r_perspective(f32 fov, Camera *c) {
glm_perspective(glm_rad(fov), ratio, 0.1f, 100.0f, c->per);
}
-void r_perspective_ortho(f32 sz, Camera *c) {
- const f32 ratio = (f32)GLOBAL_PLATFORM->window->windowsize[0]
- / (f32)GLOBAL_PLATFORM->window->windowsize[1];
+void r_perspective_ortho(Camera *c, f32 sz, ivec2 windowsize) {
+ const f32 ratio = (f32)windowsize[0] / (f32)windowsize[1];
c->type = Camera_Orthogonal;
c->parameters.orthogonal.sz = sz;
@@ -576,24 +574,24 @@ void r_set_camera(Camera* c) {
}
-void r_reset_camera(Camera* c) {
+void r_reset_camera(Camera* c, ivec2 windowsize) {
if (c->type == Camera_Perspective) {
- r_perspective(c->parameters.perspective.fov, c);
+ r_perspective(c, c->parameters.perspective.fov, windowsize);
}
else if (c->type == Camera_Orthogonal) {
- r_perspective_ortho(c->parameters.orthogonal.sz, c);
+ r_perspective_ortho(c, c->parameters.orthogonal.sz, windowsize);
}
}
-void engine_draw_model(RenderObject* o, vec3 pos) {
+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 = 1.f,
+ .scale = pos[3],
};
glm_vec3_copy(pos, dc.pos);
@@ -669,3 +667,46 @@ Texture createTextureFromImageData(unsigned char* image_data, i32 width, i32 hei
return t;
}
+
+void r_init_renderstack(
+ usize num_fbuf, usize num_buf,
+ FramebufferParameters *restrict fb_params,
+ u32 *restrict buffer_params
+ ) {
+ window_init_renderstack(GLOBAL_PLATFORM->window, num_fbuf, num_buf, fb_params, buffer_params);
+}
+
+void r_create_framebuffers(void* restrict ctx, u32* restrict framebuffer_array,
+ usize num_targets) {
+ const GladGLContext* gl = (GladGLContext*)ctx;
+
+ gl->CreateFramebuffers(num_targets, framebuffer_array);
+}
+
+void r_destroy_framebuffers(void* restrict ctx, u32* restrict framebuffer_array,
+ usize num_targets) {
+ const GladGLContext* gl = (GladGLContext*)ctx;
+
+ gl->DeleteFramebuffers(num_targets, framebuffer_array);
+}
+
+void r_create_textures(void* restrict ctx, u32* restrict texture_array,
+ u32* restrict texture_types,
+ ivec4* restrict texture_size, usize num_targets) {
+ const GladGLContext* gl = (GladGLContext*)ctx;
+
+ gl->CreateTextures(GL_TEXTURE_2D, num_targets, texture_array);
+
+ 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);
+ }
+}
+
+void r_destroy_textures(void *restrict ctx, u32* textures, usize num_textures) {
+ const GladGLContext* gl = (GladGLContext*)ctx;
+ gl->DeleteTextures(num_textures, textures);
+}
diff --git a/src/window.c b/src/window.c
index fc688b7..9702a7f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -10,8 +10,6 @@
#include <daw/window.h>
#undef ENGINE_RENDERING_WINDOW_H_EXCLUDE_EXTERNS
-#include <glad/gl.h>
-
#undef GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
@@ -50,14 +48,13 @@ Window* Window_new(const struct Platform* p, const char *restrict title, Window_
* out of struct Instance */
w = p->window_init(title, size, flags);
+ // Manually reset bindings et. al.
w->bindings = NULL;
w->bindings_sz = 0;
w->bindings_len = 0;
- /// TODO
- //w->cam = &default_camera;
+ w->render_targets = NULL;
return w;
- break;
default:
ERROR("Unsupported renderer.");
}
@@ -68,6 +65,38 @@ Window* Window_new(const struct Platform* p, const char *restrict title, Window_
return NULL;
}
+
+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?
+ for (usize i = 0; i < targets->framebuffer_len; i++) {
+ //if (targets->framebuffer_size_callback[i] == NULL) continue;
+
+ //ivec2 newsz;
+ //targets->framebuffer_size_callback[i](&newsz, w->windowsize);
+
+ // Destroy & Create framebuffers (and related buffers?)
+
+ if (targets->camera_reset_callback[i] == NULL) continue;
+ (*targets->camera_reset_callback)(&targets->cam[i], w->windowsize);
+ }
+}
+
+//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;
@@ -84,3 +113,85 @@ void get_mousepos(double *x, double *y) {
void window_get_size(ivec2* dst) {
glm_ivec2_copy(GLOBAL_PLATFORM->window->windowsize, *dst);
}
+
+
+// Assume framebuffer_len and texture_len is already set
+void window_init_renderstack(Window *restrict w,
+ usize num_fbuf, usize num_buf,
+ FramebufferParameters *restrict fb_params,
+ u32 *restrict buffer_params
+ ) {
+
+ ASSERT(w != NULL);
+ ASSERT(fb_params != NULL);
+ ASSERT(buffer_params != NULL);
+
+ RenderTargets *t = NULL;
+ 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
+ // TODO: callbacks
+ );
+
+#define ADVANCE_PTR(target, count)\
+ t->target = (void*)((u64)allocation + acc); \
+ acc += sizeof(*t->target) * count
+
+ t = allocation;
+
+ t->framebuffer_len = num_fbuf;
+ t->buffer_len = num_buf;
+
+ 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);
+ // 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);
+
+ // 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);
+ }
+ 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);
+ //if (BUFFERPARAMETER_GET_TYPE(buffer_params[i]) != BufferType_texture) continue;
+ //u32 texture_type = BUFFERPARAMETER_GET_PARAMETER(buffer_params[i]);
+
+ //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);
+ }
+ //r_create_renderbuffers(c, targets->renderbuffer, renderbuffertypes, renderbuffersizes, targets->renderbuffer_len);
+ // Skip `texture` (??)
+
+ w->render_targets = t;
+}
+
+
+void window_free_renderstack(RenderTargets *restrict t) {
+ // Everything is in the same buffer anyways
+ free(t->framebuffer);
+}