bump_cache.c (8560B)
1 ////////////////////////////////////////////////////////////////// 2 // bump_cache.c 3 4 #include "revolver_inc.h" 5 #include "revolver_inc.c" 6 7 ////////////////////////////////////////////////////////////////// 8 // data 9 10 f32 v_data[] = { 11 0.00, 0.05, 1, 0, 0, 12 -0.05, -0.05, 0, 1, 0, 13 0.05, -0.05, 0, 0, 1, 14 }; 15 16 rv_str8 v_src = S("#version 330 core\n" rv_strify( 17 layout(location = 0) in vec2 a_pos; 18 layout(location = 1) in vec3 a_color; 19 layout(location = 2) in vec2 a_offset; 20 precision mediump float; 21 out vec3 f_color; 22 void main() 23 { 24 gl_Position = vec4(a_pos + a_offset, 0.0, 1.0); 25 f_color = a_color; 26 } 27 )); 28 29 rv_str8 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 41 int main(void) { 42 rv_window_desc_t desc = {.name = S("App"), .attach_render = true}; 43 rv_window_handle_t* window = rv_create_window(desc); 44 45 rv_arena* arena = rv_arena_alloc(); 46 rv_render_pass_list_t rpass_list = {0}; 47 48 // make render objects 49 rv_vbo_t* vbo = rv_push_compound(arena, rv_vbo_t, {.data = v_data, .size = sizeof(v_data)}); 50 rv_vbo_t* vboi = rv_push_compound(arena, rv_vbo_t, {.usage = RV_BUFFER_USAGE_DYNAMIC}); 51 rv_shader_t* vertex = rv_push_compound(arena, rv_shader_t, {.source = v_src, .type = RV_SHADER_TYPE_VERTEX}); 52 rv_shader_t* fragment = rv_push_compound(arena, rv_shader_t, {.source = f_src, .type = RV_SHADER_TYPE_FRAGMENT}); 53 rv_pipeline_t* pip = rv_push(arena, rv_pipeline_t); 54 55 // construct pipeline 56 rv_pipeline_push_shader(arena, pip, vertex); 57 rv_pipeline_push_shader(arena, pip, fragment); 58 rv_pipeline_push_vattr(arena, pip, RV_VATTR_TYPE_FLOAT2, 0, 0); 59 rv_pipeline_push_vattr(arena, pip, RV_VATTR_TYPE_FLOAT3, 0, 0); 60 rv_pipeline_push_vattr(arena, pip, RV_VATTR_TYPE_FLOAT2, 1, 1); 61 62 // instructions to create render objects 63 rv_command_list_t create_instructions = {0}; 64 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, vbo); 65 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_CREATE, vboi); 66 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, vertex); 67 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_SHADER, RV_RENDER_OBJ_OP_CREATE, fragment); 68 rv_cmd_push_obj(arena, &create_instructions, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_CREATE, pip); 69 70 // copy over create commands 71 rv_render_pass_t* create_rpass = rv_render_push_render_pass(arena, &rpass_list); 72 rv_render_copy_commands(arena, &create_rpass->commands, &create_instructions); 73 74 // create vertex cache 75 rv_bump_cache_ctx_t bc = {0}; 76 rv_bump_cache_create(&bc, sizeof(rv_vec2)); 77 78 while(1) { 79 rv_temp_arena scratch = rv_scratch_begin(0, 0); 80 81 // pick renderpass 82 rv_render_pass_t* rpass = rv_render_push_render_pass(scratch.arena, &rpass_list); 83 84 // process events 85 for (rv_event_t* e = rv_get_events(scratch.arena, 0); e; e = e->next) { 86 if (e->type == RV_EVENT_WINDOW_CLOSE) { 87 if (e->window_close == window) { 88 goto exit_program; 89 } 90 } 91 if (e->type == RV_EVENT_WINDOW_RESIZE) { 92 // set viewport 93 rv_command_t* viewport = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_SET_VIEWPORT); 94 viewport->viewport = rv_v4(.xy = {0, 0}, .zw = rv_window_size(window)); 95 } 96 } 97 98 99 { // clear 100 rv_command_t* clear = rv_cmd_push_type(scratch.arena, &rpass->commands, RV_COMMAND_CLEAR); 101 rv_render_clear_desc_t* clear_desc = rv_render_push_clear_desc(scratch.arena, clear, RV_RENDER_CLEAR_FLAG_COLOR); 102 clear_desc->color_v = rv_v4(0.1, 0.1, 0.1, 1.0); 103 } 104 105 { // draw using vertex cache 106 // bind pipeline 107 rv_cmd_push_obj(arena, &rpass->commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, pip); 108 rv_cmd_push_obj(arena, &rpass->commands, RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, vbo); 109 110 { // draw custom shader first time 111 { // Translation data 112 int32_t index = 0; 113 float offset = 0.1f; 114 s32 peak_to_peak = 10.0; 115 for (int32_t y = -peak_to_peak; y < peak_to_peak; y += 2) { 116 if (sinf(rv_time()*5) * 9.0f < y) 117 break; 118 for (int32_t x = -peak_to_peak; x < peak_to_peak; x += 2) { 119 if (cosf(rv_time()*5) * 9.0f < x) 120 break; 121 rv_vec2 vertex = {0}; 122 vertex.x = (float)x / 10.0f + offset; 123 vertex.y = (float)y / 10.0f + offset; 124 rv_bump_cache_push(&bc, &vertex); 125 index++; 126 } 127 } 128 } 129 130 // insert break, push draw command 131 s64 offset, instances; 132 rv_bump_cache_break(&bc, &offset, &instances); 133 134 rv_command_t bind_command = rv_cmd_obj(RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, vboi); 135 bind_command.obj.vbo_bind.bind_index = 1; 136 bind_command.obj.vbo_bind.base_offset = offset * bc.element_size; 137 rv_command_t draw_command = rv_cmd(RV_COMMAND_DRAW, {.draw.count = 3, .draw.instances = instances}); 138 139 if (instances) { 140 rv_cmd_push_copy(scratch.arena, &rpass->commands, bind_command); 141 rv_cmd_push_copy(scratch.arena, &rpass->commands, draw_command); 142 } 143 } 144 145 { // draw custom shader second time 146 { // Translation data 147 rv_vec2 extra_offset = rv_v2(sinf(rv_time()*10) * 0.05, cosf(rv_time()*10) * 0.05); 148 int32_t index = 0; 149 float offset = 0.1f; 150 s32 peak_to_peak = 10; 151 for (int32_t y = -peak_to_peak; y < peak_to_peak; y += 2) { 152 for (int32_t x = -peak_to_peak; x < peak_to_peak; x += 2) { 153 rv_vec2 vertex = {0}; 154 vertex.x = (float)x / 10.0f + offset + extra_offset.x; 155 vertex.y = (float)y / 10.0f + offset + extra_offset.y; 156 rv_bump_cache_push(&bc, &vertex); 157 index++; 158 } 159 } 160 } 161 162 // insert break, push draw command 163 s64 offset, instances; 164 rv_bump_cache_break(&bc, &offset, &instances); 165 166 rv_command_t bind_command = rv_cmd_obj(RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_BIND, vboi); 167 bind_command.obj.vbo_bind.bind_index = 1; 168 bind_command.obj.vbo_bind.base_offset = offset * bc.element_size; 169 rv_command_t draw_command = rv_cmd(RV_COMMAND_DRAW, {.draw.count = 3, .draw.instances = instances}); 170 171 if (instances) { 172 rv_cmd_push_copy(scratch.arena, &rpass->commands, bind_command); 173 rv_cmd_push_copy(scratch.arena, &rpass->commands, draw_command); 174 } 175 } 176 177 // unbind pipeline 178 rv_cmd_push_obj(arena, &rpass->commands, RV_COMMAND_OBJ_PIPELINE, RV_RENDER_OBJ_OP_BIND, NULL); 179 180 { 181 // when done, upload all the data 182 // must be done before render commands of course 183 rv_command_t change_command = rv_cmd_obj(RV_COMMAND_OBJ_VERTEX, RV_RENDER_OBJ_OP_UPDATE, vboi); 184 rv_bump_cache_upload_and_reset(&bc, scratch.arena, &change_command.obj.vbo_update.data, &change_command.obj.vbo_update.size); 185 rv_cmd_insert_copy(scratch.arena, &rpass->commands, rpass->commands.first, change_command); 186 } 187 } 188 189 if (window) { // render screen 190 rv_window_render_commit(window, &rpass_list); 191 } 192 rv_scratch_end(scratch); 193 rpass_list = (rv_render_pass_list_t){0}; 194 } 195 exit_program: 196 197 return 0; 198 }