commit 1e57b726b635a7df096307ec28f381cf6af0ead3
parent ea52e2799ae8a1b1382f498d9a57d19443ff028f
Author: Samdal <samdal@protonmail.com>
Date: Sat, 22 Mar 2025 22:12:19 +0100
framebuffers
Diffstat:
13 files changed, 777 insertions(+), 327 deletions(-)
diff --git a/examples/framebuffer.c b/examples/framebuffer.c
@@ -0,0 +1,243 @@
+
+//////////////////////////////////////////////////////////////////
+// simple_texture.c
+
+#include "revolver_inc.h"
+#include "revolver_inc.c"
+
+//////////////////////////////////////////////////////////////////
+// triangle data
+
+f32 triangle_v_data[] = {
+ 0.0, 0.5, 1, 0, 0,
+ -0.5, -0.5, 0, 1, 0,
+ 0.5, -0.5, 0, 0, 1,
+};
+
+rv_str8 triangle_v_src = S("#version 330 core\n" rv_strify(
+ layout(location = 0) in vec2 a_pos;
+ layout(location = 1) in vec3 a_color;
+ precision mediump float;
+ out vec3 f_color;
+ void main()
+ {
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+ f_color = a_color;
+ }
+));
+
+rv_str8 triangle_f_src = S("#version 330 core\n" rv_strify(
+ precision mediump float;
+ in vec3 f_color;
+ out vec4 frag_color;
+ void main()
+ {
+ frag_color = vec4(f_color, 1.0);
+ }
+));
+
+//////////////////////////////////////////////////////////////////
+// post processing data
+
+// Vertex data for quad
+f32 post_v_data[] = {
+ // Positions | UV
+ -1, -1, 0, 0, // Top Left
+ 1, -1, 1, 0, // Top Right
+ -1, 1, 0, 1, // Bottom Left
+ 1, 1, 1, 1, // Bottom Right
+};
+
+// Index data for quad
+uint32_t post_i_data[] = {
+ 0, 3, 2, // First Triangle
+ 0, 1, 3 // Second Triangle
+};
+
+rv_str8 post_v_src = S("#version 330 core\n" rv_strify(
+ layout(location = 0) in vec2 a_pos;
+ layout(location = 1) in vec2 a_uv;
+ precision mediump float;
+ out vec2 uv;
+ void main()
+ {
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+ uv = a_uv;
+ }
+));
+
+rv_str8 post_f_src = S("#version 330 core\n" rv_strify(
+ precision mediump float;
+ in vec2 uv;
+ uniform sampler2D u_tex;
+ uniform float u_time;
+ out vec4 frag_color;
+ void main()
+ {
+ frag_color = texture(u_tex, uv);
+ float percent = (sin(u_time) + 1.0) * 0.5;
+ if (uv.x > percent) {
+ frag_color = vec4(vec3(1.0, 1.0, 1.0) - texture(u_tex, uv).xyz, 1.0);
+ }
+ }
+));
+
+//////////////////////////////////////////////////////////////////
+
+int main(void) {
+ rv_window_desc_t desc = {.name = S("App"), .attach_render = true};
+ rv_window_handle_t* window = rv_create_window(desc);
+
+ rv_arena* arena = rv_arena_alloc();
+ rv_render_pass_list_t rpass_list = {0};
+
+ rv_command_list_t create_instructions = {0};
+ rv_command_list_t triangle_render_instructions = {0};
+ rv_command_list_t post_render_instructions = {0};
+
+
+ //////////////////////////////////////////////////////////////////
+ // triangle
+
+ // make render objects
+ rv_vbo_t* triangle_vbo = rv_push_compound(arena, rv_vbo_t, {.data = triangle_v_data, .size = sizeof(triangle_v_data)});
+ rv_shader_t* triangle_vertex = rv_push_compound(arena, rv_shader_t, {.source = triangle_v_src, .type = RV_SHADER_TYPE_VERTEX});
+ rv_shader_t* triangle_fragment = rv_push_compound(arena, rv_shader_t, {.source = triangle_f_src, .type = RV_SHADER_TYPE_FRAGMENT});
+ rv_pipeline_t* triangle_pip = rv_push(arena, rv_pipeline_t);
+
+ // construct pipeline
+ rv_pipeline_push_shader(arena, triangle_pip, triangle_vertex);
+ rv_pipeline_push_shader(arena, triangle_pip, triangle_fragment);
+ rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT3);
+
+ // instructions to create render objects
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, triangle_vbo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_vertex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_fragment);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, triangle_pip);
+
+ // instructions to render
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, triangle_pip);
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, triangle_vbo);
+ rv_cmd_push_type(arena, &triangle_render_instructions, RV_COMMAND_DRAW)->draw.count = 3;
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
+ // post processing
+
+ // make render objects
+ rv_vbo_t* post_vbo = rv_push_compound(arena, rv_vbo_t, {.data = post_v_data, .size = sizeof(post_v_data)});
+ rv_vbo_t* post_ibo = rv_push_compound(arena, rv_ibo_t, {.data = post_i_data, .size = sizeof(post_i_data), .elem_size = sizeof(post_i_data[0])});
+ rv_shader_t* post_vertex = rv_push_compound(arena, rv_shader_t, {.source = post_v_src, .type = RV_SHADER_TYPE_VERTEX});
+ rv_shader_t* post_fragment = rv_push_compound(arena, rv_shader_t, {.source = post_f_src, .type = RV_SHADER_TYPE_FRAGMENT});
+ rv_pipeline_t* post_pip = rv_push(arena, rv_pipeline_t);
+
+ // construct pipeline
+ rv_pipeline_push_shader(arena, post_pip, post_vertex);
+ rv_pipeline_push_shader(arena, post_pip, post_fragment);
+ rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_uniform_t* u_tex = rv_pipeline_push_uniform(arena, post_pip, S("u_tex"), RV_UNIFORM_TEX);
+ rv_uniform_t* u_time = rv_pipeline_push_uniform(arena, post_pip, S("u_time"), RV_UNIFORM_F32);
+
+ // instructions to create render objects
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, post_vbo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, post_ibo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_vertex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_fragment);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, post_pip);
+
+ // instructions to render
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip);
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, post_vbo);
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_BIND, post_ibo);
+ rv_cmd_push_type(arena, &post_render_instructions, RV_COMMAND_DRAW)->draw.count = 6;
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
+ // fbuf
+
+ rv_framebuffer_t* fbuf = rv_framebuffer_color_simple(arena, rv_v2(1920, 1080), &create_instructions);
+ // set uniform texture to fbuf
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip);
+ rv_cmd_push_uniform_update(arena, &create_instructions, u_tex, {.v_tex = fbuf->color_attachement_first->tex});
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
+
+ // copy over create commands
+ rv_render_pass_t* create_rpass = rv_render_push_render_pass(arena, &rpass_list);
+ rv_render_copy_commands(arena, &create_rpass->commands, &create_instructions);
+
+ while(1) {
+ rv_temp_arena scratch = rv_scratch_begin(0, 0);
+
+ // process events
+ for (rv_event_t* e = rv_get_events(scratch.arena, 0); e; e = e->next) {
+ if (e->type == RV_EVENT_WINDOW_CLOSE) {
+ if (e->window_close == window) {
+ goto exit_program;
+ }
+ }
+ }
+
+ { // add off-screen rendering first
+ rv_render_pass_t* off_screen_rpass = rv_render_push_render_pass(scratch.arena, &rpass_list);
+
+ { // set viewport
+ rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_SET_VIEWPORT);
+ viewport->viewport = rv_v4(0, 0, 1920, 1080);
+ }
+
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
+
+ off_screen_rpass->framebuffer = fbuf;
+ rv_render_copy_commands(scratch.arena, &off_screen_rpass->commands, &triangle_render_instructions);
+ }
+
+ // main renderpass
+ rv_render_pass_t* rpass = rv_render_push_render_pass(scratch.arena, &rpass_list);
+
+ { // set viewport
+ rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_SET_VIEWPORT);
+ viewport->viewport = rv_v4(.xy = {0, 0}, .zw = rv_window_size(window));
+ }
+
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
+
+ { // draw post processing
+#if 1
+ rv_command_t* rcmd = rv_render_copy_commands(scratch.arena, &rpass->commands, &post_render_instructions);
+
+ // find the pipeline command
+ rv_command_t* pipeline_cmd = rcmd;
+ for (; pipeline_cmd; pipeline_cmd = pipeline_cmd->next) {
+ if (rv_command_has_pipeline(pipeline_cmd, post_pip)) break;
+ }
+ if (pipeline_cmd) {
+ rv_cmd_insert_uniform_update(scratch.arena, &rpass->commands, pipeline_cmd, u_time, {.v_f32 = (f32)rv_time()});
+ }
+#else
+ rv_render_copy_commands(scratch.arena, &rpass->commands, &triangle_render_instructions);
+#endif
+ }
+
+ if (window) { // render screen
+ rv_window_render_commit(window, &rpass_list);
+ }
+ rv_scratch_end(scratch);
+ rpass_list = (rv_render_pass_list_t){0};
+ }
+exit_program:
+
+ return 0;
+}
diff --git a/examples/simple_texture.c b/examples/simple_texture.c
@@ -72,7 +72,7 @@ int main(void) {
}
// make render objects
- rv_texture_t* tex = rv_push_compound(arena, rv_texture_t, {.data = pixels, .size = rv_v2s(ROW_COL_CT)});
+ rv_texture_t* tex = rv_push_compound(arena, rv_texture_t, {.data = pixels, .size = rv_v2s(ROW_COL_CT)});
rv_vbo_t* vbo = rv_push_compound(arena, rv_vbo_t, {.data = v_data, .size = sizeof(v_data)});
rv_vbo_t* ibo = rv_push_compound(arena, rv_ibo_t, {.data = i_data, .size = sizeof(i_data), .elem_size = sizeof(i_data[0])});
rv_shader_t* vertex = rv_push_compound(arena, rv_shader_t, {.source = v_src, .type = RV_SHADER_TYPE_VERTEX});
@@ -88,11 +88,11 @@ int main(void) {
// instructions to create render objects
rv_command_list_t create_instructions = {0};
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_TEXTURE, RV_RENDER_OBJ_OP_CREATE, tex);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, vbo);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, ibo);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, vertex);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, fragment);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_TEXTURE, RV_RENDER_OBJ_OP_CREATE, tex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, vbo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, ibo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, vertex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, fragment);
rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, pip);
rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, pip);
rv_cmd_push_uniform_update(arena, &create_instructions, u_tex, {.v_tex = tex});
@@ -131,19 +131,18 @@ int main(void) {
}
}
- if (window) { // render screen
-
- { // clear
- rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
- rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
- clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 0.1);
- }
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
- { // draw custom shader
- // copy render commands
- rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
- }
+ { // draw custom shader
+ // copy render commands
+ rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
+ }
+ if (window) { // render screen
rv_window_render_commit(window, &rpass_list);
}
rv_scratch_end(scratch);
diff --git a/examples/simple_triangle.c b/examples/simple_triangle.c
@@ -31,7 +31,7 @@ rv_str8 f_src = S("#version 330 core\n" rv_strify(
out vec4 frag_color;
void main()
{
- frag_color = vec4(f_color, 1.0);
+ frag_color = vec4(f_color, 1.0);
}
));
@@ -94,19 +94,19 @@ int main(void) {
}
}
- if (window) { // render screen
- { // clear
- rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
- rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
- clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 0.1);
- }
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
- { // draw custom shader
- // copy render commands
- rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
- }
+ { // draw custom shader
+ // copy render commands
+ rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
+ }
+ if (window) { // render screen
rv_window_render_commit(window, &rpass_list);
}
rv_scratch_end(scratch);
diff --git a/examples/test.c b/examples/test.c
@@ -5,27 +5,56 @@
#include "revolver_inc.h"
#include "revolver_inc.c"
-#define ROW_COL_CT 10
+//////////////////////////////////////////////////////////////////
+// triangle data
+
+f32 triangle_v_data[] = {
+ 0.0, 0.5, 1, 0, 0,
+ -0.5, -0.5, 0, 1, 0,
+ 0.5, -0.5, 0, 0, 1,
+};
+
+rv_str8 triangle_v_src = S("#version 330 core\n" rv_strify(
+ layout(location = 0) in vec2 a_pos;
+ layout(location = 1) in vec3 a_color;
+ precision mediump float;
+ out vec3 f_color;
+ void main()
+ {
+ gl_Position = vec4(a_pos, 0.0, 1.0);
+ f_color = a_color;
+ }
+));
+
+rv_str8 triangle_f_src = S("#version 330 core\n" rv_strify(
+ precision mediump float;
+ in vec3 f_color;
+ out vec4 frag_color;
+ void main()
+ {
+ frag_color = vec4(f_color, 1.0);
+ }
+));
//////////////////////////////////////////////////////////////////
-// data
+// post processing data
// Vertex data for quad
-f32 v_data[] = {
- // Positions UVs
- -0.5f, -0.5f, 0.0f, 0.0f, // Top Left
- 0.5f, -0.5f, 1.0f, 0.0f, // Top Right
- -0.5f, 0.5f, 0.0f, 1.0f, // Bottom Left
- 0.5f, 0.5f, 1.0f, 1.0f // Bottom Right
+f32 post_v_data[] = {
+ // Positions | UV
+ -1, -1, 0, 0, // Top Left
+ 1, -1, 1, 0, // Top Right
+ -1, 1, 0, 1, // Bottom Left
+ 1, 1, 1, 1, // Bottom Right
};
// Index data for quad
-uint32_t i_data[] = {
+uint32_t post_i_data[] = {
0, 3, 2, // First Triangle
0, 1, 3 // Second Triangle
};
-rv_str8 v_src = S("#version 330 core\n" rv_strify(
+rv_str8 post_v_src = S("#version 330 core\n" rv_strify(
layout(location = 0) in vec2 a_pos;
layout(location = 1) in vec2 a_uv;
precision mediump float;
@@ -37,20 +66,24 @@ rv_str8 v_src = S("#version 330 core\n" rv_strify(
}
));
-rv_str8 f_src = S("#version 330 core\n" rv_strify(
+rv_str8 post_f_src = S("#version 330 core\n" rv_strify(
precision mediump float;
- uniform sampler2D u_tex;
in vec2 uv;
+ uniform sampler2D u_tex;
+ uniform float u_time;
out vec4 frag_color;
void main()
{
frag_color = texture(u_tex, uv);
+ float percent = (sin(u_time) + 1.0) * 0.5;
+ if (uv.x > percent) {
+ frag_color = vec4(vec3(1.0, 1.0, 1.0) - texture(u_tex, uv).xyz, 1.0);
+ }
}
));
//////////////////////////////////////////////////////////////////
-
int main(void) {
rv_window_desc_t desc = {.name = S("App"), .attach_render = true};
rv_window_handle_t* window = rv_create_window(desc);
@@ -58,66 +91,88 @@ int main(void) {
rv_arena* arena = rv_arena_alloc();
rv_render_pass_list_t rpass_list = {0};
+ rv_command_list_t create_instructions = {0};
+ rv_command_list_t triangle_render_instructions = {0};
+ rv_command_list_t post_render_instructions = {0};
- // Generate procedural texture data (checkered texture)
- rv_color_t c0 = RV_COLOR_BLACK;
- rv_color_t c1 = RV_COLOR_PURPLE;
- rv_color_t pixels[ROW_COL_CT * ROW_COL_CT] = {0};
- for (uint32_t r = 0; r < ROW_COL_CT; ++r) {
- for (uint32_t c = 0; c < ROW_COL_CT; ++c) {
- const bool32 re = (r % 2) == 0;
- const bool32 ce = (c % 2) == 0;
- uint32_t idx = r * ROW_COL_CT + c;
- pixels[idx] = (re && ce) ? c0 : (re) ? c1 : (ce) ? c1 : c0;
- }
- }
+
+ //////////////////////////////////////////////////////////////////
+ // triangle
// make render objects
- rv_texture_t* tex = rv_push_compound(arena, rv_texture_t, {.data = pixels, .size = rv_v2s(ROW_COL_CT)});
- rv_vbo_t* vbo = rv_push_compound(arena, rv_vbo_t, {.data = v_data, .size = sizeof(v_data)});
- rv_vbo_t* ibo = rv_push_compound(arena, rv_ibo_t, {.data = i_data, .size = sizeof(i_data), .elem_size = sizeof(i_data[0])});
- rv_shader_t* vertex = rv_push_compound(arena, rv_shader_t, {.source = v_src, .type = RV_SHADER_TYPE_VERTEX});
- rv_shader_t* fragment = rv_push_compound(arena, rv_shader_t, {.source = f_src, .type = RV_SHADER_TYPE_FRAGMENT});
- rv_pipeline_t* pip = rv_push(arena, rv_pipeline_t);
+ rv_vbo_t* triangle_vbo = rv_push_compound(arena, rv_vbo_t, {.data = triangle_v_data, .size = sizeof(triangle_v_data)});
+ rv_shader_t* triangle_vertex = rv_push_compound(arena, rv_shader_t, {.source = triangle_v_src, .type = RV_SHADER_TYPE_VERTEX});
+ rv_shader_t* triangle_fragment = rv_push_compound(arena, rv_shader_t, {.source = triangle_f_src, .type = RV_SHADER_TYPE_FRAGMENT});
+ rv_pipeline_t* triangle_pip = rv_push(arena, rv_pipeline_t);
// construct pipeline
- rv_pipeline_push_shader(arena, pip, vertex);
- rv_pipeline_push_shader(arena, pip, fragment);
- rv_pipeline_push_vattr(arena, pip, RV_VATTR_TYPE_FLOAT2);
- rv_pipeline_push_vattr(arena, pip, RV_VATTR_TYPE_FLOAT2);
- rv_uniform_t* u_tex = rv_pipeline_push_uniform(arena, pip, S("u_tex"), RV_UNIFORM_TEX);
+ rv_pipeline_push_shader(arena, triangle_pip, triangle_vertex);
+ rv_pipeline_push_shader(arena, triangle_pip, triangle_fragment);
+ rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT3);
// instructions to create render objects
- rv_command_list_t create_instructions = {0};
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_TEXTURE, RV_RENDER_OBJ_OP_CREATE, tex);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, vbo);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, ibo);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, vertex);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, fragment);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, pip);
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, pip);
- rv_cmd_push_uniform_update(arena, &create_instructions, u_tex, {.v_tex = tex});
- rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, triangle_vbo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_vertex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_fragment);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, triangle_pip);
+
+ // instructions to render
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, triangle_pip);
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, triangle_vbo);
+ rv_cmd_push_type(arena, &triangle_render_instructions, RV_COMMAND_DRAW)->draw.count = 3;
+ rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
+ // post processing
+
+ // make render objects
+ rv_vbo_t* post_vbo = rv_push_compound(arena, rv_vbo_t, {.data = post_v_data, .size = sizeof(post_v_data)});
+ rv_vbo_t* post_ibo = rv_push_compound(arena, rv_ibo_t, {.data = post_i_data, .size = sizeof(post_i_data), .elem_size = sizeof(post_i_data[0])});
+ rv_shader_t* post_vertex = rv_push_compound(arena, rv_shader_t, {.source = post_v_src, .type = RV_SHADER_TYPE_VERTEX});
+ rv_shader_t* post_fragment = rv_push_compound(arena, rv_shader_t, {.source = post_f_src, .type = RV_SHADER_TYPE_FRAGMENT});
+ rv_pipeline_t* post_pip = rv_push(arena, rv_pipeline_t);
+
+ // construct pipeline
+ rv_pipeline_push_shader(arena, post_pip, post_vertex);
+ rv_pipeline_push_shader(arena, post_pip, post_fragment);
+ rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2);
+ rv_uniform_t* u_tex = rv_pipeline_push_uniform(arena, post_pip, S("u_tex"), RV_UNIFORM_TEX);
+ rv_uniform_t* u_time = rv_pipeline_push_uniform(arena, post_pip, S("u_time"), RV_UNIFORM_F32);
+
+ // instructions to create render objects
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, post_vbo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, post_ibo);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_vertex);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_fragment);
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, post_pip);
// instructions to render
- rv_command_list_t render_instructions = {0};
- rv_cmd_push_obj(arena, &render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, pip);
- rv_cmd_push_obj(arena, &render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, vbo);
- rv_cmd_push_obj(arena, &render_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_BIND, ibo);
- rv_cmd_push_type(arena, &render_instructions, RV_COMMAND_DRAW)->draw.count = 6;
- rv_cmd_push_obj(arena, &render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip);
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, post_vbo);
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_BIND, post_ibo);
+ rv_cmd_push_type(arena, &post_render_instructions, RV_COMMAND_DRAW)->draw.count = 6;
+ rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
+ // fbuf
+
+ rv_framebuffer_t* fbuf = rv_framebuffer_color_simple(arena, rv_v2(1920, 1080), &create_instructions);
+ // set uniform texture to fbuf
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip);
+ rv_cmd_push_uniform_update(arena, &create_instructions, u_tex, {.v_tex = fbuf->color_attachement_first->tex});
+ rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL);
+
+ //////////////////////////////////////////////////////////////////
// copy over create commands
rv_render_pass_t* create_rpass = rv_render_push_render_pass(arena, &rpass_list);
rv_render_copy_commands(arena, &create_rpass->commands, &create_instructions);
-
while(1) {
rv_temp_arena scratch = rv_scratch_begin(0, 0);
- // pick renderpass
- rv_render_pass_t* rpass = rv_render_push_render_pass(scratch.arena, &rpass_list);
-
// process events
for (rv_event_t* e = rv_get_events(scratch.arena, 0); e; e = e->next) {
if (e->type == RV_EVENT_WINDOW_CLOSE) {
@@ -125,26 +180,58 @@ int main(void) {
goto exit_program;
}
}
- if (e->type == RV_EVENT_WINDOW_RESIZE) {
- // set viewport
- rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_SET_VIEWPORT);
- viewport->viewport = rv_v4(.xy = {0, 0}, .zw = rv_window_size(window));
- }
}
- if (window) { // render screen
+ { // add off-screen rendering first
+ rv_render_pass_t* off_screen_rpass = rv_render_push_render_pass(scratch.arena, &rpass_list);
+
+ { // set viewport
+ rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_SET_VIEWPORT);
+ viewport->viewport = rv_v4(0, 0, 1920, 1080);
+ }
{ // clear
- rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_CLEAR);
rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
- clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 0.1);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
}
- { // draw custom shader
- // copy render commands
- rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
+ off_screen_rpass->framebuffer = fbuf;
+ rv_render_copy_commands(scratch.arena, &off_screen_rpass->commands, &triangle_render_instructions);
+ }
+
+ // main renderpass
+ rv_render_pass_t* rpass = rv_render_push_render_pass(scratch.arena, &rpass_list);
+
+ { // set viewport
+ rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_SET_VIEWPORT);
+ viewport->viewport = rv_v4(.xy = {0, 0}, .zw = rv_window_size(window));
+ }
+
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
+
+ { // draw post processing
+#if 1
+ rv_command_t* rcmd = rv_render_copy_commands(scratch.arena, &rpass->commands, &post_render_instructions);
+
+ // find the pipeline command
+ rv_command_t* pipeline_cmd = rcmd;
+ for (; pipeline_cmd; pipeline_cmd = pipeline_cmd->next) {
+ if (rv_command_has_pipeline(pipeline_cmd, post_pip)) break;
}
+ if (pipeline_cmd) {
+ rv_cmd_insert_uniform_update(scratch.arena, &rpass->commands, pipeline_cmd, u_time, {.v_f32 = (f32)rv_time()});
+ }
+#else
+ rv_render_copy_commands(scratch.arena, &rpass->commands, &triangle_render_instructions);
+#endif
+ }
+ if (window) { // render screen
rv_window_render_commit(window, &rpass_list);
}
rv_scratch_end(scratch);
diff --git a/examples/uniform.c b/examples/uniform.c
@@ -99,43 +99,43 @@ int main(void) {
}
}
- if (window) { // render screen
- { // clear
- rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
- rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
- clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 0.1);
- }
+ { // clear
+ rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR);
+ rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR);
+ clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0);
+ }
- { // draw custom shader
+ { // draw custom shader
- // copy render commands
- rv_command_t* rcmd = rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
+ // copy render commands
+ rv_command_t* rcmd = rv_render_copy_commands(scratch.arena, &rpass->commands, &render_instructions);
- // find the pipeline command
- rv_command_t* pipeline_cmd = rcmd;
- for (; pipeline_cmd; pipeline_cmd = pipeline_cmd->next) {
- if (rv_command_has_pipeline(pipeline_cmd, pip)) break;
- }
+ // find the pipeline command
+ rv_command_t* pipeline_cmd = rcmd;
+ for (; pipeline_cmd; pipeline_cmd = pipeline_cmd->next) {
+ if (rv_command_has_pipeline(pipeline_cmd, pip)) break;
+ }
- if (pipeline_cmd) {
- // add uniform updates
- const f64 t = rv_time();
- const f32 r = sinf(t) * 0.5f + 0.5f;
- const f32 g = cosf(t * 6.f) * 0.5f + 0.5f;
- const f32 b = sinf(t * 3.f) * 0.5f + 0.5f;
- rv_cmd_insert_uniform_update(scratch.arena, &rpass->commands, pipeline_cmd, u_color, {.v_vec3 = rv_v3(r, g, b)});
-
- const f32 st = sin(t);
- rv_mat4 rot = rv_mat4_rotatev(t, RV_ZAXIS);
- rv_mat4 scl = rv_mat4_scalev(rv_v3(st, st, st));
- rv_mat4 model = rv_mat4_mul_list(2, scl, rot);
- rv_command_t* update_u_model = rv_cmd_insert_type(scratch.arena, &rpass->commands, pipeline_cmd, RV_COMMAND_UNIFORM_UPDATE);
- update_u_model->uniform_update.desc = u_model;
- update_u_model->uniform_update.value.v_mat4 = model;
- }
+ if (pipeline_cmd) {
+ // add uniform updates
+ const f64 t = rv_time();
+ const f32 r = sinf(t) * 0.5f + 0.5f;
+ const f32 g = cosf(t * 6.f) * 0.5f + 0.5f;
+ const f32 b = sinf(t * 3.f) * 0.5f + 0.5f;
+ rv_cmd_insert_uniform_update(scratch.arena, &rpass->commands, pipeline_cmd, u_color, {.v_vec3 = rv_v3(r, g, b)});
+
+ const f32 st = sin(t);
+ rv_mat4 rot = rv_mat4_rotatev(t, RV_ZAXIS);
+ rv_mat4 scl = rv_mat4_scalev(rv_v3(st, st, st));
+ rv_mat4 model = rv_mat4_mul_list(2, scl, rot);
+ rv_command_t* update_u_model = rv_cmd_insert_type(scratch.arena, &rpass->commands, pipeline_cmd, RV_COMMAND_UNIFORM_UPDATE);
+ update_u_model->uniform_update.desc = u_model;
+ update_u_model->uniform_update.value.v_mat4 = model;
}
+ }
+ if (window) { // render screen
rv_window_render_commit(window, &rpass_list);
}
rv_scratch_end(scratch);
diff --git a/src/platform/gfx/xcb_impl.c b/src/platform/gfx/xcb_impl.c
@@ -188,18 +188,35 @@ RV_GLOBAL void* egl_attach(xcb_window_t window, xcb_connection_t* connection)
RV_GLOBAL void rv_window_render_begin(rv_window_handle_t* window)
{
- EGLSurface* surface = xcb_maybe_window(window)->render;
- eglMakeCurrent(egl_context.egl_display, surface, surface, egl_context.egl_context);
+ rv_window_handle_t* w = xcb_maybe_window(window);
+ if (w) {
+ EGLSurface* surface = w->render;
+ eglMakeCurrent(egl_context.egl_display, surface, surface, egl_context.egl_context);
+ }
}
RV_GLOBAL void rv_window_render_end(rv_window_handle_t* window)
{
- EGLSurface* surface = xcb_maybe_window(window)->render;
- eglSwapBuffers(egl_context.egl_display, surface);
+ rv_window_handle_t* w = xcb_maybe_window(window);
+ if (w) {
+ EGLSurface* surface = w->render;
+ eglSwapBuffers(egl_context.egl_display, surface);
+ }
+}
+
+#else // RV_RENDER_OPENGL
+
+RV_GLOBAL void rv_window_render_begin(rv_window_handle_t* window)
+{
+
}
+RV_GLOBAL void rv_window_render_end(rv_window_handle_t* window)
+{
+
+}
-#endif // RV_RENDER_OPENGL
+#endif // !RV_RENDER_OPENGL
//////////////////////////////////////////////////////////////////
@@ -506,7 +523,7 @@ RV_GLOBAL rv_window_handle_t* rv_create_window(rv_window_desc_t desc)
xcb_change_property(xcb_context.connection, XCB_PROP_MODE_REPLACE, res->window_id,
XCB_ATOM_WM_NAME, m_utf8_string_atom, 8,
- desc.name.size, desc.name.str);
+ desc.name.len, desc.name.str);
}
{ // setup close handler event
@@ -850,7 +867,7 @@ RV_GLOBAL rv_event_t* rv_get_events(rv_arena* arena, rv_event_flags_t flags)
if (len) {
new_ev.key_press.string = rv_str8_from_cstr(buf);
new_ev.key_press.string = rv_str8_copy(arena, new_ev.key_press.string);
- if (new_ev.key_press.string.size == 1) {
+ if (new_ev.key_press.string.len == 1) {
if (new_ev.key_press.string.str[0] == '\r') {
new_ev.key_press.string.str[0] = '\n';
}
@@ -859,7 +876,7 @@ RV_GLOBAL rv_event_t* rv_get_events(rv_arena* arena, rv_event_flags_t flags)
}
// invalidate event if nothing gave any results
- if (new_ev.key_press.keycode == RV_KEYCODE_INVALID && new_ev.key_press.string.size == 0) {
+ if (new_ev.key_press.keycode == RV_KEYCODE_INVALID && new_ev.key_press.string.len == 0) {
new_ev.type = RV_EVENT_INVALID;
}
} break;
diff --git a/src/platform/platform_core.c b/src/platform/platform_core.c
@@ -140,15 +140,15 @@ RV_GLOBAL s64 rv_mem_get_page_size(bool32 is_large)
rv_str8 proc_meminfo = rv_str8_from_cstr(buffer);
rv_str8 tag = S("Hugepagesize:");
- rv_str8 found = rv_str8_skip(proc_meminfo, rv_str8_find_needle(proc_meminfo, 0, tag, 0) + tag.size);
+ rv_str8 found = rv_str8_skip(proc_meminfo, rv_str8_find_needle(proc_meminfo, 0, tag, 0) + tag.len);
// chop around number + byte size
found = rv_str8_skip_chop_whitespace(found);
found = rv_str8_prefix(found, rv_str8_find_needle(found, 0, S("\n"), 0));
- bool32 kb = rv_str8_find_needle(found, 0, S("kb"), rv_str8_match_flag_case_insensetive) < found.size;
- bool32 mb = rv_str8_find_needle(found, 0, S("mb"), rv_str8_match_flag_case_insensetive) < found.size;
- bool32 gb = rv_str8_find_needle(found, 0, S("gb"), rv_str8_match_flag_case_insensetive) < found.size;
+ bool32 kb = rv_str8_find_needle(found, 0, S("kb"), rv_str8_match_flag_case_insensetive) < found.len;
+ bool32 mb = rv_str8_find_needle(found, 0, S("mb"), rv_str8_match_flag_case_insensetive) < found.len;
+ bool32 gb = rv_str8_find_needle(found, 0, S("gb"), rv_str8_match_flag_case_insensetive) < found.len;
// remove byte part
found = rv_str8_prefix(found, rv_str8_find_needle(found, 0, S(" "), 0));
diff --git a/src/platform/platform_string.c b/src/platform/platform_string.c
@@ -6,75 +6,75 @@
RV_READ_ONLY RV_INTERNAL u8 char_integer_symbol_reverse[128] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};
RV_GLOBAL bool32 rv_char_is_space(u8 c)
{
- return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v';
+ return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v';
}
RV_GLOBAL bool32 rv_char_is_upper(u8 c)
{
- return 'A' <= c && c <= 'Z';
+ return 'A' <= c && c <= 'Z';
}
RV_GLOBAL bool32 rv_char_is_lower(u8 c)
{
- return 'a' <= c && c <= 'z';
+ return 'a' <= c && c <= 'z';
}
RV_GLOBAL bool32 rv_char_is_alpha(u8 c)
{
- return rv_char_is_upper(c) || rv_char_is_lower(c);
+ return rv_char_is_upper(c) || rv_char_is_lower(c);
}
RV_GLOBAL bool32 rv_char_is_slash(u8 c)
{
- return c == '/' || c == '\\';
+ return c == '/' || c == '\\';
}
RV_GLOBAL bool32 rv_char_is_digit(u8 c, s32 base)
{
- bool32 result = 0;
- if (base >= 0 && base <= 16) {
- u8 val = char_integer_symbol_reverse[c];
- if (val < base) {
- result = 1;
- }
- }
- return result;
+ bool32 result = 0;
+ if (base >= 0 && base <= 16) {
+ u8 val = char_integer_symbol_reverse[c];
+ if (val < base) {
+ result = 1;
+ }
+ }
+ return result;
}
RV_GLOBAL u8 rv_char_to_lower(u8 c)
{
- if (rv_char_is_upper(c)) {
- c += ('a' - 'A');
- }
- return c;
+ if (rv_char_is_upper(c)) {
+ c += ('a' - 'A');
+ }
+ return c;
}
RV_GLOBAL u8 rv_char_to_upper(u8 c)
{
- if (rv_char_is_lower(c)) {
- c += ('A' - 'a');
- }
- return c;
+ if (rv_char_is_lower(c)) {
+ c += ('A' - 'a');
+ }
+ return c;
}
RV_GLOBAL u8 rv_char_to_correct_slash(u8 c)
{
- if(rv_char_is_slash(c)) {
- c = '/';
- }
- return c;
+ if(rv_char_is_slash(c)) {
+ c = '/';
+ }
+ return c;
}
//////////////////////////////////////////////////////////////////
@@ -82,9 +82,9 @@ RV_GLOBAL u8 rv_char_to_correct_slash(u8 c)
RV_GLOBAL s64 rv_cstrlen(const char* c_str)
{
- s64 res = 0;
- while (*c_str++) res++;
- return res;
+ s64 res = 0;
+ while (*c_str++) res++;
+ return res;
}
//////////////////////////////////////////////////////////////////
@@ -92,7 +92,7 @@ RV_GLOBAL s64 rv_cstrlen(const char* c_str)
RV_GLOBAL rv_str8 rv_str8_range(u8* first, u8* one_past_last)
{
- return rv_s8(first, (s64)(one_past_last - first));
+ return rv_s8(first, (s64)(one_past_last - first));
}
@@ -101,45 +101,45 @@ RV_GLOBAL rv_str8 rv_str8_range(u8* first, u8* one_past_last)
RV_GLOBAL s64 rv_sign_from_str8(rv_str8 string, rv_str8* string_tail)
{
- // count negative signs
- u64 neg_count = 0;
- u64 i = 0;
- for (; i < string.size; i += 1) {
- if (string.str[i] == '-') {
- neg_count += 1;
- }
- else if (string.str[i] != '+') {
- break;
- }
- }
-
- // output part of string after signs
- *string_tail = rv_str8_skip(string, i);
-
- // output integer sign
- s64 sign = (neg_count & 1) ? -1 : +1;
- return sign;
+ // count negative signs
+ u64 neg_count = 0;
+ u64 i = 0;
+ for (; i < string.len; i += 1) {
+ if (string.str[i] == '-') {
+ neg_count += 1;
+ }
+ else if (string.str[i] != '+') {
+ break;
+ }
+ }
+
+ // output part of string after signs
+ *string_tail = rv_str8_skip(string, i);
+
+ // output integer sign
+ s64 sign = (neg_count & 1) ? -1 : +1;
+ return sign;
}
RV_GLOBAL u64 rv_u64_from_str8(rv_str8 string, u32 radix)
{
- u64 x = 0;
- if (1 < radix && radix <= 16) {
- for (u64 i = 0; i < string.size; i += 1) {
- x *= radix;
- x += char_integer_symbol_reverse[string.str[i]&0x7F];
- }
- }
- return x;
+ u64 x = 0;
+ if (1 < radix && radix <= 16) {
+ for (u64 i = 0; i < string.len; i += 1) {
+ x *= radix;
+ x += char_integer_symbol_reverse[string.str[i]&0x7F];
+ }
+ }
+ return x;
}
RV_GLOBAL s64 rv_s64_from_str8(rv_str8 string, s32 radix)
{
- s64 sign = rv_sign_from_str8(string, &string);
- s64 x = (s64)rv_u64_from_str8(string, radix) * sign;
- return x;
+ s64 sign = rv_sign_from_str8(string, &string);
+ s64 x = (s64)rv_u64_from_str8(string, radix) * sign;
+ return x;
}
RV_GLOBAL rv_str8 str8_from_s64(rv_arena* arena, s64 integer, s32 radix, u8 min_digits, u8 digit_group_separator);
@@ -149,68 +149,68 @@ RV_GLOBAL rv_str8 str8_from_s64(rv_arena* arena, s64 integer, s32 radix, u8 min_
RV_GLOBAL bool32 rv_str8_match(rv_str8 a, rv_str8 b, rv_str8_match_flags flags)
{
- bool32 result = 0;
- if (a.size == b.size || (flags & rv_str8_match_flag_right_side_sloppy)){
- bool32 case_insensitive = (flags & rv_str8_match_flag_case_insensetive);
- bool32 slash_insensitive = (flags & rv_str8_match_flag_slash_insensetive);
- s64 size = rv_min(a.size, b.size);
- result = 1;
- for (s64 i = 0; i < size; i += 1){
- u8 at = a.str[i];
- u8 bt = b.str[i];
- if (case_insensitive){
- at = rv_char_to_upper(at);
- bt = rv_char_to_upper(bt);
- }
- if (slash_insensitive){
- at = rv_char_to_correct_slash(at);
- bt = rv_char_to_correct_slash(bt);
- }
- if (at != bt){
- result = 0;
- break;
- }
- }
- }
- return result;
+ bool32 result = 0;
+ if (a.len == b.len || (flags & rv_str8_match_flag_right_side_sloppy)){
+ bool32 case_insensitive = (flags & rv_str8_match_flag_case_insensetive);
+ bool32 slash_insensitive = (flags & rv_str8_match_flag_slash_insensetive);
+ s64 len = rv_min(a.len, b.len);
+ result = 1;
+ for (s64 i = 0; i < len; i += 1){
+ u8 at = a.str[i];
+ u8 bt = b.str[i];
+ if (case_insensitive){
+ at = rv_char_to_upper(at);
+ bt = rv_char_to_upper(bt);
+ }
+ if (slash_insensitive){
+ at = rv_char_to_correct_slash(at);
+ bt = rv_char_to_correct_slash(bt);
+ }
+ if (at != bt){
+ result = 0;
+ break;
+ }
+ }
+ }
+ return result;
}
RV_GLOBAL s64 rv_str8_find_needle(rv_str8 string, s64 start_pos, rv_str8 needle, rv_str8_match_flags flags)
{
- u8* p = string.str + start_pos;
- s64 stop_offset = rv_max(string.size + 1, needle.size) - needle.size;
- u8* stop_p = string.str + stop_offset;
-
- if (string.size > 0 && needle.size > 0) {
- u8* string_opl = string.str + string.size;
-
- rv_str8 needle_tail = rv_str8_skip(needle, 1);
- rv_str8_match_flags adjusted_flags = flags | rv_str8_match_flag_right_side_sloppy;
- u8 needle_first_rv_char_adjusted = needle.str[0];
-
- if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
- needle_first_rv_char_adjusted = rv_char_to_upper(needle_first_rv_char_adjusted);
- }
-
- for (;p < stop_p; p += 1) {
- u8 haystack_rv_char_adjusted = *p;
-
- if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
- haystack_rv_char_adjusted = rv_char_to_upper(haystack_rv_char_adjusted);
- }
-
- if (haystack_rv_char_adjusted == needle_first_rv_char_adjusted) {
- if (rv_str8_match(rv_str8_range(p + 1, string_opl), needle_tail, adjusted_flags)) {
- break;
- }
- }
- }
- }
- s64 result = string.size;
- if (p < stop_p) {
- result = (s64)(p - string.str);
- }
- return result;
+ u8* p = string.str + start_pos;
+ s64 stop_offset = rv_max(string.len + 1, needle.len) - needle.len;
+ u8* stop_p = string.str + stop_offset;
+
+ if (string.len > 0 && needle.len > 0) {
+ u8* string_opl = string.str + string.len;
+
+ rv_str8 needle_tail = rv_str8_skip(needle, 1);
+ rv_str8_match_flags adjusted_flags = flags | rv_str8_match_flag_right_side_sloppy;
+ u8 needle_first_rv_char_adjusted = needle.str[0];
+
+ if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
+ needle_first_rv_char_adjusted = rv_char_to_upper(needle_first_rv_char_adjusted);
+ }
+
+ for (;p < stop_p; p += 1) {
+ u8 haystack_rv_char_adjusted = *p;
+
+ if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
+ haystack_rv_char_adjusted = rv_char_to_upper(haystack_rv_char_adjusted);
+ }
+
+ if (haystack_rv_char_adjusted == needle_first_rv_char_adjusted) {
+ if (rv_str8_match(rv_str8_range(p + 1, string_opl), needle_tail, adjusted_flags)) {
+ break;
+ }
+ }
+ }
+ }
+ s64 result = string.len;
+ if (p < stop_p) {
+ result = (s64)(p - string.str);
+ }
+ return result;
}
//////////////////////////////////////////////////////////////////
@@ -218,60 +218,60 @@ RV_GLOBAL s64 rv_str8_find_needle(rv_str8 string, s64 start_pos, rv_str8 needle,
RV_GLOBAL rv_str8 rv_str8_substr(rv_str8 str, rv_range range)
{
- range.min = rv_min(range.min, str.size);
- range.max = rv_min(range.max, str.size);
- str.str += range.min;
- str.size = rv_range_diff(range);
- return str;
+ range.min = rv_min(range.min, str.len);
+ range.max = rv_min(range.max, str.len);
+ str.str += range.min;
+ str.len = rv_range_diff(range);
+ return str;
}
-RV_GLOBAL rv_str8 rv_str8_prefix(rv_str8 str, s64 size)
+RV_GLOBAL rv_str8 rv_str8_prefix(rv_str8 str, s64 len)
{
- str.size = rv_min(size, str.size);
- return str;
+ str.len = rv_min(len, str.len);
+ return str;
}
RV_GLOBAL rv_str8 rv_str8_skip(rv_str8 str, s64 amt)
{
- amt = rv_min(amt, str.size);
- str.str += amt;
- str.size -= amt;
- return str;
+ amt = rv_min(amt, str.len);
+ str.str += amt;
+ str.len -= amt;
+ return str;
}
-RV_GLOBAL rv_str8 rv_str8_postfix(rv_str8 str, s64 size)
+RV_GLOBAL rv_str8 rv_str8_postfix(rv_str8 str, s64 len)
{
- size = rv_min(size, str.size);
- str.str = (str.str + str.size) - size;
- str.size = size;
- return str;
+ len = rv_min(len, str.len);
+ str.str = (str.str + str.len) - len;
+ str.len = len;
+ return str;
}
RV_GLOBAL rv_str8 rv_str8_chop(rv_str8 str, s64 amt)
{
- amt = rv_min(amt, str.size);
- str.size -= amt;
- return str;
+ amt = rv_min(amt, str.len);
+ str.len -= amt;
+ return str;
}
RV_GLOBAL rv_str8 rv_str8_skip_chop_whitespace(rv_str8 string)
{
- u8* first = string.str;
- u8* opl = first + string.size;
- for (;first < opl; first += 1) {
- if (!rv_char_is_space(*first)) {
- break;
- }
- }
- for (;opl > first;) {
- opl -= 1;
- if (!rv_char_is_space(*opl)) {
- opl += 1;
- break;
- }
- }
- rv_str8 result = rv_str8_range(first, opl);
- return result;
+ u8* first = string.str;
+ u8* opl = first + string.len;
+ for (;first < opl; first += 1) {
+ if (!rv_char_is_space(*first)) {
+ break;
+ }
+ }
+ for (;opl > first;) {
+ opl -= 1;
+ if (!rv_char_is_space(*opl)) {
+ opl += 1;
+ break;
+ }
+ }
+ rv_str8 result = rv_str8_range(first, opl);
+ return result;
}
//////////////////////////////////////////////////////////////////
@@ -279,37 +279,37 @@ RV_GLOBAL rv_str8 rv_str8_skip_chop_whitespace(rv_str8 string)
RV_GLOBAL rv_str8 rv_str8_copy(rv_arena* arena, rv_str8 s)
{
- rv_str8 str;
- str.size = s.size;
- str.str = rv_push_array_no_zero(arena, u8, str.size + 1);
- rv_mem_copy(str.str, s.str, s.size);
- str.str[str.size] = 0;
- return str;
+ rv_str8 str;
+ str.len = s.len;
+ str.str = rv_push_array_no_zero(arena, u8, str.len + 1);
+ rv_mem_copy(str.str, s.str, s.len);
+ str.str[str.len] = 0;
+ return str;
}
RV_GLOBAL rv_str8 rv_read_file(rv_arena* arena, rv_str8 filename)
{
- u8* buffer = NULL;
- s64 size = 0;
+ u8* buffer = NULL;
+ s64 len = 0;
- FILE* fp = NULL;
- {
- rv_temp_arena scratch = rv_scratch_begin((rv_arena*[]){arena}, 1);
- rv_str8 filename_copy = rv_str8_copy(scratch.arena, filename);
- fp = fopen((char*)filename_copy.str, "rb");
- rv_scratch_end(scratch);
- }
+ FILE* fp = NULL;
+ {
+ rv_temp_arena scratch = rv_scratch_begin((rv_arena*[]){arena}, 1);
+ rv_str8 filename_copy = rv_str8_copy(scratch.arena, filename);
+ fp = fopen((char*)filename_copy.str, "rb");
+ rv_scratch_end(scratch);
+ }
- if (fp) {
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
+ if (fp) {
+ fseek(fp, 0, SEEK_END);
+ len = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
- buffer = rv_push_array_no_zero(arena, u8, size + 1);
- fread(buffer, 1, size, fp);
+ buffer = rv_push_array_no_zero(arena, u8, len + 1);
+ fread(buffer, 1, len, fp);
- fclose(fp);
- }
+ fclose(fp);
+ }
- return rv_s8(buffer, size);
+ return rv_s8(buffer, len);
}
diff --git a/src/platform/platform_string.h b/src/platform/platform_string.h
@@ -36,7 +36,7 @@ RV_GLOBAL rv_str8 rv_str8_copy(rv_arena* arena, rv_str8 s);
//////////////////////////////////////////////////////////////////
// conversions
-#define rv_s8v(S) (int)((S).size), ((S).str)
+#define rv_s8v(S) (int)((S).len), ((S).str)
RV_GLOBAL s64 rv_sign_from_str8(rv_str8 string, rv_str8* string_tail);
RV_GLOBAL u64 rv_u64_from_str8(rv_str8 string, u32 radix);
diff --git a/src/platform/platform_types.h b/src/platform/platform_types.h
@@ -150,7 +150,7 @@ typedef struct {
typedef struct {
u8* str;
- s64 size;
+ s64 len;
} rv_str8;
typedef struct rv_str8_node_t rv_str8_node_t;
diff --git a/src/render/impl/opengl.c b/src/render/impl/opengl.c
@@ -77,8 +77,24 @@ struct {
rv_ibo_t* bound_ibo;
rv_vbo_t* bound_vbo;
rv_pipeline_t* bound_pip;
+ rv_framebuffer_t* bound_fbuf;
} ogl_state;
+void ogl_bind_fbuf(rv_framebuffer_t* fbuf) {
+ ogl_state.bound_fbuf = fbuf;
+ glBindFramebuffer(GL_FRAMEBUFFER, ogl_safe_set(fbuf, handle));
+ if (fbuf) {
+ s32 r = 0;
+ for (rv_texture_node_t* c = fbuf->color_attachement_first; c; c = c->next, r++) {
+ if (c->tex) {
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + r, GL_TEXTURE_2D, c->tex->handle.u, 0);
+ } else {
+ rv_unreachable();
+ }
+ }
+ }
+}
+
RV_GLOBAL void rv_window_render_commit(rv_window_handle_t* window, rv_render_pass_list_t* passes)
{
@@ -91,7 +107,30 @@ RV_GLOBAL void rv_window_render_commit(rv_window_handle_t* window, rv_render_pas
glBindVertexArray(ogl_ctx.vao);
}
+
for (rv_render_pass_t* p = passes->first; p; p = p->next) {
+ { // unbind everything
+
+ if (ogl_state.bound_ibo) {
+ ogl_state.bound_ibo = NULL;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ if (ogl_state.bound_vbo) {
+ ogl_state.bound_vbo = NULL;
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
+ if (ogl_state.bound_pip) {
+ ogl_state.bound_pip = NULL;
+ glUseProgram(0);
+ }
+
+ if (ogl_state.bound_fbuf || p->framebuffer) {
+ ogl_bind_fbuf(p->framebuffer);
+ }
+ }
+
for (rv_command_t* c = p->commands.first; c; c = c->next) {
switch (c->type) {
case RV_COMMAND_INVALID: {
@@ -198,7 +237,7 @@ RV_GLOBAL void rv_window_render_commit(rv_window_handle_t* window, rv_render_pas
switch (c->obj.operation) {
case RV_RENDER_OBJ_OP_CREATE: {
shader->handle.u = glCreateShader(rv_shader_to_gl(shader->type));
- glShaderSource(shader->handle.u, 1, (const char* const*)&shader->source.str, (s32*)&shader->source.size);
+ glShaderSource(shader->handle.u, 1, (const char* const*)&shader->source.str, (s32*)&shader->source.len);
glCompileShader(shader->handle.u);
{ // check for errors
@@ -537,6 +576,30 @@ RV_GLOBAL void rv_window_render_commit(rv_window_handle_t* window, rv_render_pas
}
} break;
+ case RV_COMMAND_OBJ_FRAMEBUFFER: {
+ rv_framebuffer_t* fbuf = c->obj.framebuffer;
+ switch (c->obj.operation) {
+ case RV_RENDER_OBJ_OP_CREATE: {
+ glGenFramebuffers(1, &fbuf->handle.u);
+ } break;
+
+ case RV_RENDER_OBJ_OP_UPDATE: {
+ rv_unreachable();
+ } break;
+
+ case RV_RENDER_OBJ_OP_BIND: {
+ ogl_bind_fbuf(fbuf);
+ } break;
+
+ case RV_RENDER_OBJ_OP_DELETE: {
+ glDeleteFramebuffers(1, &fbuf->handle.u);
+ if (ogl_state.bound_fbuf == fbuf) {
+ ogl_state.bound_fbuf = NULL;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+ } break;
+ }
+ } break;
}
}
}
diff --git a/src/render/render.h b/src/render/render.h
@@ -34,6 +34,7 @@ typedef enum {
} rv_texture_filter_t;
typedef struct {
+ // creation data
rv_vec2 size;
rv_texture_format_t format;
rv_texture_wrap_t wrap_s;
@@ -47,9 +48,18 @@ typedef struct {
rv_render_handle_t handle;
} rv_texture_t;
+typedef struct rv_texture_node_t rv_texture_node_t;
+struct rv_texture_node_t {
+ rv_texture_node_t* next;
+ rv_texture_t* tex;
+};
+
typedef struct {
+ rv_texture_node_t* color_attachement_first;
+ // TODO(Samdal): depth buffer
+
rv_render_handle_t handle;
-} rv_render_framebuffer_t;
+} rv_framebuffer_t;
typedef enum {
RV_UNIFORM_INVALID,
@@ -200,6 +210,7 @@ typedef enum {
RV_COMMAND_OBJ_SHADER,
RV_COMMAND_OBJ_PIPELINE,
RV_COMMAND_OBJ_TEXTURE,
+ RV_COMMAND_OBJ_FRAMEBUFFER,
RV_COMMAND_UNIFORM_UPDATE, // only allowed during pipeline bind
@@ -256,6 +267,7 @@ struct rv_command_t {
rv_vbo_t* vbo;
rv_ibo_t* ibo;
rv_texture_t* tex;
+ rv_framebuffer_t* framebuffer;
void* generic;
};
} obj;
@@ -282,7 +294,7 @@ struct rv_render_pass_t {
rv_render_pass_t* next;
rv_command_list_t commands;
- rv_render_framebuffer_t* framebuffer;
+ rv_framebuffer_t* framebuffer; // auto bind framebuffer
};
typedef struct {
@@ -325,6 +337,10 @@ RV_GLOBAL rv_command_t rv_cmd_uniform_update(rv_uniform_t* uniform, rv_uniform_v
RV_GLOBAL rv_render_clear_desc_t* rv_render_push_clear_desc(rv_arena* arena, rv_command_t* clear, rv_graphics_clear_flag_t flags);
RV_GLOBAL bool32 rv_command_has_pipeline(rv_command_t* command, rv_pipeline_t* prog);
+// framebuffer modificatoin helpers
+RV_GLOBAL void rv_framebuffer_push_texture(rv_arena* arena, rv_framebuffer_t* fbuf, rv_texture_t* tex);
+RV_GLOBAL rv_framebuffer_t* rv_framebuffer_color_simple(rv_arena* arena, rv_vec2 color_size, rv_command_list_t* append_construction);
+
// pipeline modificatoin helpers
RV_GLOBAL rv_shader_node_t* rv_pipeline_push_shader(rv_arena* arena, rv_pipeline_t* pipeline, rv_shader_t* shader);
RV_GLOBAL rv_uniform_t* rv_pipeline_push_uniform(rv_arena* arena, rv_pipeline_t* pipeline, rv_str8 name, rv_uniform_type_t type);
diff --git a/src/render/render_helpers.c b/src/render/render_helpers.c
@@ -1,6 +1,7 @@
//////////////////////////////////////////////////////////////////
// render_helpers.c
+// render pass
RV_GLOBAL rv_render_pass_t* rv_render_push_render_pass(rv_arena* arena, rv_render_pass_list_t* rpass_list)
{
rv_render_pass_t* res = rv_push(arena, rv_render_pass_t);
@@ -8,6 +9,7 @@ RV_GLOBAL rv_render_pass_t* rv_render_push_render_pass(rv_arena* arena, rv_rende
return res;
}
+// command list
RV_GLOBAL rv_command_t* rv_cmd_copy(rv_command_t* dest, rv_command_t source) {
rv_command_t* next = dest->next;
rv_command_t* prev = dest->prev;
@@ -44,6 +46,7 @@ RV_GLOBAL rv_command_t* rv_render_copy_commands(rv_arena* arena, rv_command_list
return res;
}
+// ctors
RV_GLOBAL rv_command_t rv_cmd_type(rv_command_type_t type)
{
return (rv_command_t){.type = type};
@@ -51,7 +54,7 @@ RV_GLOBAL rv_command_t rv_cmd_type(rv_command_type_t type)
RV_GLOBAL rv_command_t rv_cmd_obj(rv_command_type_t type, rv_command_obj_operation_t operation, void* obj)
{
- rv_assert(type >= RV_COMMAND_OBJ_VERTEX && type <= RV_COMMAND_OBJ_TEXTURE);
+ rv_assert(type >= RV_COMMAND_OBJ_VERTEX && type <= RV_COMMAND_OBJ_FRAMEBUFFER);
return (rv_command_t) {
.type = type,
@@ -69,6 +72,7 @@ RV_GLOBAL rv_command_t rv_cmd_uniform_update(rv_uniform_t* uniform, rv_uniform_v
};
}
+// command modification helpers
RV_GLOBAL rv_render_clear_desc_t* rv_render_push_clear_desc(rv_arena* arena, rv_command_t* clear, rv_graphics_clear_flag_t flags)
{
rv_assert(clear->type == RV_COMMAND_CLEAR);
@@ -82,6 +86,27 @@ RV_GLOBAL bool32 rv_command_has_pipeline(rv_command_t* command, rv_pipeline_t* p
return command->type == RV_COMMAND_OBJ_PIPELINE && command->obj.pipeline == pipeline;
}
+// framebuffer modificatoin helpers
+RV_GLOBAL void rv_framebuffer_push_texture(rv_arena* arena, rv_framebuffer_t* fbuf, rv_texture_t* tex)
+{
+ rv_texture_node_t* tnode = rv_push_compound(arena, rv_texture_node_t, {.tex = tex});
+ rv_llist_stack_push(fbuf->color_attachement_first, tnode);
+}
+
+RV_GLOBAL rv_framebuffer_t* rv_framebuffer_color_simple(rv_arena* arena, rv_vec2 color_size, rv_command_list_t* append_construction)
+{
+ rv_framebuffer_t* fbuf = rv_push(arena, rv_framebuffer_t);
+
+ rv_texture_t* tex = rv_push_compound(arena, rv_texture_t, {.data = NULL, .size = color_size});
+ rv_framebuffer_push_texture(arena, fbuf, tex);
+
+ rv_cmd_push_obj(arena, append_construction, RV_COMMAND_OBJ_TEXTURE, RV_RENDER_OBJ_OP_CREATE, tex);
+ rv_cmd_push_obj(arena, append_construction, RV_COMMAND_OBJ_FRAMEBUFFER, RV_RENDER_OBJ_OP_CREATE, fbuf);
+
+ return fbuf;
+}
+
+// pipeline modificatoin helpers
RV_GLOBAL rv_shader_node_t* rv_pipeline_push_shader(rv_arena* arena, rv_pipeline_t* pipeline, rv_shader_t* shader)
{
rv_shader_node_t* res = rv_push_compound(arena, rv_shader_node_t, {.shader = shader});