framebuffer.c (10493B)
1 2 ////////////////////////////////////////////////////////////////// 3 // framebuffer.c 4 5 #include "revolver_inc.h" 6 #include "revolver_inc.c" 7 8 ////////////////////////////////////////////////////////////////// 9 // triangle data 10 11 f32 triangle_v_data[] = { 12 0.0, 0.5, 1, 0, 0, 13 -0.5, -0.5, 0, 1, 0, 14 0.5, -0.5, 0, 0, 1, 15 }; 16 17 rv_str8 triangle_v_src = S("#version 330 core\n" rv_strify( 18 layout(location = 0) in vec2 a_pos; 19 layout(location = 1) in vec3 a_color; 20 precision mediump float; 21 out vec3 f_color; 22 void main() 23 { 24 gl_Position = vec4(a_pos, 0.0, 1.0); 25 f_color = a_color; 26 } 27 )); 28 29 rv_str8 triangle_f_src = S("#version 330 core\n" rv_strify( 30 precision mediump float; 31 in vec3 f_color; 32 out vec4 frag_color; 33 void main() 34 { 35 frag_color = vec4(f_color, 1.0); 36 } 37 )); 38 39 ////////////////////////////////////////////////////////////////// 40 // post processing data 41 42 // Vertex data for quad 43 f32 post_v_data[] = { 44 // Positions | UV 45 -1, -1, 0, 0, // Top Left 46 1, -1, 1, 0, // Top Right 47 -1, 1, 0, 1, // Bottom Left 48 1, 1, 1, 1, // Bottom Right 49 }; 50 51 // Index data for quad 52 uint32_t post_i_data[] = { 53 0, 3, 2, // First Triangle 54 0, 1, 3 // Second Triangle 55 }; 56 57 rv_str8 post_v_src = S("#version 330 core\n" rv_strify( 58 layout(location = 0) in vec2 a_pos; 59 layout(location = 1) in vec2 a_uv; 60 precision mediump float; 61 out vec2 uv; 62 void main() 63 { 64 gl_Position = vec4(a_pos, 0.0, 1.0); 65 uv = a_uv; 66 } 67 )); 68 69 rv_str8 post_f_src = S("#version 330 core\n" rv_strify( 70 precision mediump float; 71 in vec2 uv; 72 uniform sampler2D u_tex; 73 uniform float u_time; 74 out vec4 frag_color; 75 void main() 76 { 77 frag_color = texture(u_tex, uv); 78 float percent = (sin(u_time) + 1.0) * 0.5; 79 if (uv.x > percent) { 80 frag_color = vec4(vec3(1.0, 1.0, 1.0) - texture(u_tex, uv).xyz, 1.0); 81 } 82 } 83 )); 84 85 ////////////////////////////////////////////////////////////////// 86 87 int main(void) { 88 rv_window_desc_t desc = {.name = S("App"), .attach_render = true}; 89 rv_window_handle_t* window = rv_create_window(desc); 90 91 rv_arena* arena = rv_arena_alloc(); 92 rv_render_pass_list_t rpass_list = {0}; 93 94 rv_command_list_t create_instructions = {0}; 95 rv_command_list_t triangle_render_instructions = {0}; 96 rv_command_list_t post_render_instructions = {0}; 97 98 99 ////////////////////////////////////////////////////////////////// 100 // triangle 101 102 // make render objects 103 rv_vbo_t* triangle_vbo = rv_push_compound(arena, rv_vbo_t, {.data = triangle_v_data, .size = sizeof(triangle_v_data)}); 104 rv_shader_t* triangle_vertex = rv_push_compound(arena, rv_shader_t, {.source = triangle_v_src, .type = RV_SHADER_TYPE_VERTEX}); 105 rv_shader_t* triangle_fragment = rv_push_compound(arena, rv_shader_t, {.source = triangle_f_src, .type = RV_SHADER_TYPE_FRAGMENT}); 106 rv_pipeline_t* triangle_pip = rv_push(arena, rv_pipeline_t); 107 108 // construct pipeline 109 rv_pipeline_push_shader(arena, triangle_pip, triangle_vertex); 110 rv_pipeline_push_shader(arena, triangle_pip, triangle_fragment); 111 rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT2); 112 rv_pipeline_push_vattr(arena, triangle_pip, RV_VATTR_TYPE_FLOAT3); 113 114 // instructions to create render objects 115 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, triangle_vbo); 116 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_vertex); 117 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, triangle_fragment); 118 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, triangle_pip); 119 120 // instructions to render 121 rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, triangle_pip); 122 rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, triangle_vbo); 123 rv_cmd_push_type(arena, &triangle_render_instructions, RV_COMMAND_DRAW)->draw.count = 3; 124 rv_cmd_push_obj(arena, &triangle_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); 125 126 ////////////////////////////////////////////////////////////////// 127 // post processing 128 129 // make render objects 130 rv_vbo_t* post_vbo = rv_push_compound(arena, rv_vbo_t, {.data = post_v_data, .size = sizeof(post_v_data)}); 131 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])}); 132 rv_shader_t* post_vertex = rv_push_compound(arena, rv_shader_t, {.source = post_v_src, .type = RV_SHADER_TYPE_VERTEX}); 133 rv_shader_t* post_fragment = rv_push_compound(arena, rv_shader_t, {.source = post_f_src, .type = RV_SHADER_TYPE_FRAGMENT}); 134 rv_pipeline_t* post_pip = rv_push(arena, rv_pipeline_t); 135 136 // construct pipeline 137 rv_pipeline_push_shader(arena, post_pip, post_vertex); 138 rv_pipeline_push_shader(arena, post_pip, post_fragment); 139 rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2); 140 rv_pipeline_push_vattr(arena, post_pip, RV_VATTR_TYPE_FLOAT2); 141 rv_uniform_t* u_tex = rv_pipeline_push_uniform(arena, post_pip, S("u_tex"), RV_UNIFORM_TEX); 142 rv_uniform_t* u_time = rv_pipeline_push_uniform(arena, post_pip, S("u_time"), RV_UNIFORM_F32); 143 144 // instructions to create render objects 145 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, post_vbo); 146 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_CREATE, post_ibo); 147 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_vertex); 148 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, post_fragment); 149 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, post_pip); 150 151 // instructions to render 152 rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip); 153 rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, post_vbo); 154 rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_INDEX, RV_RENDER_OBJ_OP_BIND, post_ibo); 155 rv_cmd_push_type(arena, &post_render_instructions, RV_COMMAND_DRAW)->draw.count = 6; 156 rv_cmd_push_obj(arena, &post_render_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); 157 158 ////////////////////////////////////////////////////////////////// 159 // fbuf 160 161 rv_framebuffer_t* fbuf = rv_framebuffer_color_simple(arena, rv_v2(1920, 1080), &create_instructions); 162 // set uniform texture to fbuf 163 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, post_pip); 164 rv_cmd_push_uniform_update(arena, &create_instructions, u_tex, {.v_tex = fbuf->color_attachement_first->tex}); 165 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); 166 167 ////////////////////////////////////////////////////////////////// 168 169 // copy over create commands 170 rv_render_pass_t* create_rpass = rv_render_push_render_pass(arena, &rpass_list); 171 rv_render_copy_commands(arena, &create_rpass->commands, &create_instructions); 172 173 while(1) { 174 rv_temp_arena scratch = rv_scratch_begin(0, 0); 175 176 // process events 177 for (rv_event_t* e = rv_get_events(scratch.arena, 0); e; e = e->next) { 178 if (e->type == RV_EVENT_WINDOW_CLOSE) { 179 if (e->window_close == window) { 180 goto exit_program; 181 } 182 } 183 } 184 185 { // add off-screen rendering first 186 rv_render_pass_t* off_screen_rpass = rv_render_push_render_pass(scratch.arena, &rpass_list); 187 188 { // set viewport 189 rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_SET_VIEWPORT); 190 viewport->viewport = rv_v4(0, 0, 1920, 1080); 191 } 192 193 { // clear 194 rv_command_t* clear = rv_cmd_push_type(scratch.arena, &off_screen_rpass->commands, RV_COMMAND_CLEAR); 195 rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR); 196 clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0); 197 } 198 199 off_screen_rpass->framebuffer = fbuf; 200 rv_render_copy_commands(scratch.arena, &off_screen_rpass->commands, &triangle_render_instructions); 201 } 202 203 // main renderpass 204 rv_render_pass_t* rpass = rv_render_push_render_pass(scratch.arena, &rpass_list); 205 206 { // set viewport 207 rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_SET_VIEWPORT); 208 viewport->viewport = rv_v4(.xy = {0, 0}, .zw = rv_window_size(window)); 209 } 210 211 { // clear 212 rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR); 213 rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR); 214 clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0); 215 } 216 217 { // draw post processing 218 #if 1 219 rv_command_t* rcmd = rv_render_copy_commands(scratch.arena, &rpass->commands, &post_render_instructions); 220 221 // find the pipeline command 222 rv_command_t* pipeline_cmd = rcmd; 223 for (; pipeline_cmd; pipeline_cmd = pipeline_cmd->next) { 224 if (rv_command_has_pipeline(pipeline_cmd, post_pip)) break; 225 } 226 if (pipeline_cmd) { 227 rv_cmd_insert_uniform_update(scratch.arena, &rpass->commands, pipeline_cmd, u_time, {.v_f32 = (f32)rv_time()}); 228 } 229 #else 230 rv_render_copy_commands(scratch.arena, &rpass->commands, &triangle_render_instructions); 231 #endif 232 } 233 234 if (window) { // render screen 235 rv_window_render_commit(window, &rpass_list); 236 } 237 rv_scratch_end(scratch); 238 rpass_list = (rv_render_pass_list_t){0}; 239 } 240 exit_program: 241 242 return 0; 243 }