shader overrides
[carveJwlIkooP6JGAAIwe30JlM.git] / render.h
1 /*
2 * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
3 */
4
5 #include "common.h"
6 #include "model.h"
7 #include "camera.h"
8 #include "world.h"
9
10 #include "shaders/blit.h"
11 #include "shaders/blitblur.h"
12 #include "shaders/blitcolour.h"
13 #include "shaders/blit_transition.h"
14
15 #define WORKSHOP_PREVIEW_WIDTH 504
16 #define WORKSHOP_PREVIEW_HEIGHT 336
17 #ifndef RENDER_H
18 #define RENDER_H
19
20 static f32 k_render_scale = 1.0f;
21 static i32 k_blur_effect = 1;
22 static f32 k_blur_strength = 0.3f;
23 static f32 k_fov = 0.86f;
24 static f32 k_cam_height = 0.8f;
25
26 typedef struct framebuffer framebuffer;
27
28 /*
29 * All standard buffers used in rendering
30 */
31 static struct pipeline{
32 glmesh fsquad;
33
34 framebuffer *fb_main,
35 *fb_water_reflection,
36 *fb_water_beneath,
37 *fb_workshop_preview;
38 int ready;
39 }
40 gpipeline;
41
42 struct framebuffer{
43 const char *display_name;
44 int resolution_div, /* definition */
45 fixed_w,
46 fixed_h,
47
48 render_w, /* runtime */
49 render_h;
50
51 struct framebuffer_attachment{
52 const char *display_name;
53
54 enum framebuffer_attachment_type{
55 k_framebuffer_attachment_type_none,
56 k_framebuffer_attachment_type_texture,
57 k_framebuffer_attachment_type_renderbuffer,
58 k_framebuffer_attachment_type_texture_depth
59 }
60 purpose;
61
62 enum framebuffer_quality_profile{
63 k_framebuffer_quality_all,
64 k_framebuffer_quality_high_only
65 }
66 quality;
67
68 GLenum internalformat,
69 format,
70 type,
71 attachment;
72
73 GLuint id;
74
75 /* Runtime */
76 int debug_view;
77 }
78 attachments[5];
79 GLuint fb;
80 framebuffer **link;
81 }
82 framebuffers[] =
83 {
84 {
85 /*
86 * The primary draw target
87 */
88 "main",
89 .link = &gpipeline.fb_main,
90 .resolution_div = 1,
91 .attachments =
92 {
93 {
94 "colour", k_framebuffer_attachment_type_texture,
95
96 .internalformat = GL_RGB,
97 .format = GL_RGB,
98 .type = GL_UNSIGNED_BYTE,
99 .attachment = GL_COLOR_ATTACHMENT0
100 },
101 {
102 "motion", k_framebuffer_attachment_type_texture,
103
104 .quality = k_framebuffer_quality_high_only,
105 .internalformat = GL_RG16F,
106 .format = GL_RG,
107 .type = GL_FLOAT,
108 .attachment = GL_COLOR_ATTACHMENT1
109 },
110 {
111 #if 0
112 "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
113
114 .internalformat = GL_DEPTH24_STENCIL8,
115 #else
116 "depth_stencil", k_framebuffer_attachment_type_texture_depth,
117 .internalformat = GL_DEPTH24_STENCIL8,
118 .format = GL_DEPTH_STENCIL,
119 .type = GL_UNSIGNED_INT_24_8,
120 #endif
121 .attachment = GL_DEPTH_STENCIL_ATTACHMENT
122 }
123 }
124 },
125 {
126 /*
127 * Second rendered view from the perspective of the water reflection
128 */
129 "water_reflection",
130 .link = &gpipeline.fb_water_reflection,
131 .resolution_div = 2,
132 .attachments =
133 {
134 {
135 "colour", k_framebuffer_attachment_type_texture,
136 .internalformat = GL_RGB,
137 .format = GL_RGB,
138 .type = GL_UNSIGNED_BYTE,
139 .attachment = GL_COLOR_ATTACHMENT0
140 },
141 {
142 "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
143
144 .internalformat = GL_DEPTH24_STENCIL8,
145 .attachment = GL_DEPTH_STENCIL_ATTACHMENT
146 }
147 }
148 },
149 {
150 /*
151 * Thid rendered view from the perspective of the camera, but just
152 * captures stuff thats under the water
153 */
154 "water_beneath",
155 .link = &gpipeline.fb_water_beneath,
156 .resolution_div = 2,
157 .attachments =
158 {
159 {
160 "colour", k_framebuffer_attachment_type_texture,
161 .internalformat = GL_RED,
162 .format = GL_RED,
163 .type = GL_UNSIGNED_BYTE,
164 .attachment = GL_COLOR_ATTACHMENT0
165 },
166 {
167 "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
168
169 .internalformat = GL_DEPTH24_STENCIL8,
170 .attachment = GL_DEPTH_STENCIL_ATTACHMENT
171 }
172 }
173 },
174 {
175 "workshop_preview",
176 .link = &gpipeline.fb_workshop_preview,
177 .resolution_div = 0,
178 .fixed_w = WORKSHOP_PREVIEW_WIDTH, .fixed_h = WORKSHOP_PREVIEW_HEIGHT,
179 .attachments =
180 {
181 {
182 "colour", k_framebuffer_attachment_type_texture,
183 .internalformat = GL_RGB,
184 .format = GL_RGB,
185 .type = GL_UNSIGNED_BYTE,
186 .attachment = GL_COLOR_ATTACHMENT0
187 },
188 {
189 "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
190 .internalformat = GL_DEPTH24_STENCIL8,
191 .attachment = GL_DEPTH_STENCIL_ATTACHMENT
192 }
193 }
194 }
195 };
196
197 /*
198 * Get the current (automatically scaled or fixed) resolution of framebuffer
199 */
200 static void render_fb_get_current_res( struct framebuffer *fb,
201 int *x, int *y )
202 {
203 if( fb->resolution_div ){
204 *x = vg.window_x / fb->resolution_div;
205 *y = vg.window_y / fb->resolution_div;
206 }
207 else{
208 *x = fb->fixed_w;
209 *y = fb->fixed_h;
210 }
211 }
212
213 static void render_fb_inverse_ratio( framebuffer *fb, v2f inverse )
214 {
215 if( fb ){
216 int x, y;
217 render_fb_get_current_res( fb, &x, &y );
218
219 v2f render = { fb->render_w, fb->render_h },
220 original = { x, y };
221
222 v2_div( render, original, inverse );
223 }
224 else{
225 v2_div( (v2f){1.0f,1.0f}, (v2f){ vg.window_x, vg.window_y }, inverse );
226 }
227 }
228
229 /*
230 * Bind framebuffer for drawing to
231 */
232 static void render_fb_bind( framebuffer *fb, int use_scaling )
233 {
234 int x, y;
235 render_fb_get_current_res( fb, &x, &y );
236
237 if( use_scaling ){
238 x = k_render_scale*(float)x;
239 y = k_render_scale*(float)y;
240
241 x = VG_MAX( 16, x );
242 y = VG_MAX( 16, y );
243
244 fb->render_w = x;
245 fb->render_h = y;
246 }
247
248 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
249 glViewport( 0, 0, x, y );
250 }
251
252 /*
253 * Bind framebuffer attachment's texture
254 */
255 static void render_fb_bind_texture( framebuffer *fb,
256 int attachment, int slot )
257 {
258 struct framebuffer_attachment *at = &fb->attachments[attachment];
259
260 if( (at->purpose != k_framebuffer_attachment_type_texture) &&
261 (at->purpose != k_framebuffer_attachment_type_texture_depth) )
262 {
263 vg_fatal_error( "illegal operation: bind non-texture framebuffer"
264 " attachment to texture slot" );
265 }
266
267 glActiveTexture( GL_TEXTURE0 + slot );
268 glBindTexture( GL_TEXTURE_2D, fb->attachments[attachment].id );
269 }
270
271
272 /*
273 * Shaders
274 */
275
276 #define FB_FORMAT_STR( E ) { E, #E },
277
278 /*
279 * Convert OpenGL attachment ID enum to string
280 */
281 static const char *render_fb_attachment_str( GLenum e )
282 {
283 struct { GLenum e; const char *str; }
284 formats[] =
285 {
286 FB_FORMAT_STR(GL_COLOR_ATTACHMENT0)
287 FB_FORMAT_STR(GL_COLOR_ATTACHMENT1)
288 FB_FORMAT_STR(GL_COLOR_ATTACHMENT2)
289 FB_FORMAT_STR(GL_COLOR_ATTACHMENT3)
290 FB_FORMAT_STR(GL_COLOR_ATTACHMENT4)
291 FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT)
292 };
293
294 for( int i=0; i<vg_list_size(formats); i++ )
295 if( formats[i].e == e )
296 return formats[i].str;
297
298 return "UNDEFINED";
299 }
300
301 /*
302 * Convert OpenGL texture format enums from TexImage2D table 1,2 &
303 * RenderBufferStorage Table 1, into strings
304 */
305 static const char *render_fb_format_str( GLenum format )
306 {
307 struct { GLenum e; const char *str; }
308 formats[] =
309 {
310 /* Table 1 */
311 FB_FORMAT_STR(GL_DEPTH_COMPONENT)
312 FB_FORMAT_STR(GL_DEPTH_STENCIL)
313 FB_FORMAT_STR(GL_RED)
314 FB_FORMAT_STR(GL_RG)
315 FB_FORMAT_STR(GL_RGB)
316 FB_FORMAT_STR(GL_RGBA)
317
318 /* Render buffer formats */
319 FB_FORMAT_STR(GL_DEPTH_COMPONENT16)
320 FB_FORMAT_STR(GL_DEPTH_COMPONENT24)
321 FB_FORMAT_STR(GL_DEPTH_COMPONENT32F)
322 FB_FORMAT_STR(GL_DEPTH24_STENCIL8)
323 FB_FORMAT_STR(GL_DEPTH32F_STENCIL8)
324 FB_FORMAT_STR(GL_STENCIL_INDEX8)
325
326 /* Table 2 */
327 FB_FORMAT_STR(GL_R8)
328 FB_FORMAT_STR(GL_R8_SNORM)
329 FB_FORMAT_STR(GL_R16)
330 FB_FORMAT_STR(GL_R16_SNORM)
331 FB_FORMAT_STR(GL_RG8)
332 FB_FORMAT_STR(GL_RG8_SNORM)
333 FB_FORMAT_STR(GL_RG16)
334 FB_FORMAT_STR(GL_RG16_SNORM)
335 FB_FORMAT_STR(GL_R3_G3_B2)
336 FB_FORMAT_STR(GL_RGB4)
337 FB_FORMAT_STR(GL_RGB5)
338 FB_FORMAT_STR(GL_RGB8)
339 FB_FORMAT_STR(GL_RGB8_SNORM)
340 FB_FORMAT_STR(GL_RGB10)
341 FB_FORMAT_STR(GL_RGB12)
342 FB_FORMAT_STR(GL_RGB16_SNORM)
343 FB_FORMAT_STR(GL_RGBA2)
344 FB_FORMAT_STR(GL_RGBA4)
345 FB_FORMAT_STR(GL_RGB5_A1)
346 FB_FORMAT_STR(GL_RGBA8)
347 FB_FORMAT_STR(GL_RGBA8_SNORM)
348 FB_FORMAT_STR(GL_RGB10_A2)
349 FB_FORMAT_STR(GL_RGB10_A2UI)
350 FB_FORMAT_STR(GL_RGBA12)
351 FB_FORMAT_STR(GL_RGBA16)
352 FB_FORMAT_STR(GL_SRGB8)
353 FB_FORMAT_STR(GL_SRGB8_ALPHA8)
354 FB_FORMAT_STR(GL_R16F)
355 FB_FORMAT_STR(GL_RG16F)
356 FB_FORMAT_STR(GL_RGB16F)
357 FB_FORMAT_STR(GL_RGBA16F)
358 FB_FORMAT_STR(GL_R32F)
359 FB_FORMAT_STR(GL_RG32F)
360 FB_FORMAT_STR(GL_RGB32F)
361 FB_FORMAT_STR(GL_RGBA32F)
362 FB_FORMAT_STR(GL_R11F_G11F_B10F)
363 FB_FORMAT_STR(GL_RGB9_E5)
364 FB_FORMAT_STR(GL_R8I)
365 FB_FORMAT_STR(GL_R8UI)
366 FB_FORMAT_STR(GL_R16I)
367 FB_FORMAT_STR(GL_R16UI)
368 FB_FORMAT_STR(GL_R32I)
369 FB_FORMAT_STR(GL_R32UI)
370 FB_FORMAT_STR(GL_RG8I)
371 FB_FORMAT_STR(GL_RG8UI)
372 FB_FORMAT_STR(GL_RG16I)
373 FB_FORMAT_STR(GL_RG16UI)
374 FB_FORMAT_STR(GL_RG32I)
375 FB_FORMAT_STR(GL_RG32UI)
376 FB_FORMAT_STR(GL_RGB8I)
377 FB_FORMAT_STR(GL_RGB8UI)
378 FB_FORMAT_STR(GL_RGB16I)
379 FB_FORMAT_STR(GL_RGB16UI)
380 FB_FORMAT_STR(GL_RGB32I)
381 FB_FORMAT_STR(GL_RGB32UI)
382 FB_FORMAT_STR(GL_RGBA8I)
383 FB_FORMAT_STR(GL_RGBA8UI)
384 FB_FORMAT_STR(GL_RGBA16I)
385 FB_FORMAT_STR(GL_RGBA16UI)
386 FB_FORMAT_STR(GL_RGBA32I)
387 FB_FORMAT_STR(GL_RGBA32UI)
388 };
389
390 for( int i=0; i<vg_list_size(formats); i++ )
391 if( formats[i].e == format )
392 return formats[i].str;
393
394 return "UNDEFINED";
395 }
396
397 /*
398 * Bind and allocate texture for framebuffer attachment
399 */
400 static void render_fb_allocate_texture( struct framebuffer *fb,
401 struct framebuffer_attachment *a )
402 {
403 int rx, ry;
404 render_fb_get_current_res( fb, &rx, &ry );
405
406 if( a->purpose == k_framebuffer_attachment_type_renderbuffer ){
407 glBindRenderbuffer( GL_RENDERBUFFER, a->id );
408 glRenderbufferStorage( GL_RENDERBUFFER, a->internalformat, rx, ry );
409 }
410 else if( a->purpose == k_framebuffer_attachment_type_texture ||
411 a->purpose == k_framebuffer_attachment_type_texture_depth )
412 {
413 glBindTexture( GL_TEXTURE_2D, a->id );
414 glTexImage2D( GL_TEXTURE_2D, 0, a->internalformat, rx, ry,
415 0, a->format, a->type, NULL );
416 }
417 }
418
419 /*
420 * Full allocation of a framebuffer
421 */
422 static void render_fb_allocate( struct framebuffer *fb )
423 {
424 glGenFramebuffers( 1, &fb->fb );
425 glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
426
427 int rx, ry;
428 render_fb_get_current_res( fb, &rx, &ry );
429
430 vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb->display_name, rx, ry );
431 vg_info( "{\n" );
432
433 GLenum colour_attachments[4];
434 u32 colour_count = 0;
435
436 for( int j=0; j<vg_list_size(fb->attachments); j++ ){
437 struct framebuffer_attachment *attachment = &fb->attachments[j];
438
439 if( attachment->purpose == k_framebuffer_attachment_type_none )
440 continue;
441
442 vg_info( " %s: %s\n",
443 render_fb_attachment_str( attachment->attachment ),
444 render_fb_format_str( attachment->internalformat ) );
445
446 if( attachment->purpose == k_framebuffer_attachment_type_renderbuffer ){
447 glGenRenderbuffers( 1, &attachment->id );
448 render_fb_allocate_texture( fb, attachment );
449 glFramebufferRenderbuffer( GL_FRAMEBUFFER,
450 GL_DEPTH_STENCIL_ATTACHMENT,
451 GL_RENDERBUFFER, attachment->id );
452 }
453 else if( attachment->purpose == k_framebuffer_attachment_type_texture ||
454 attachment->purpose == k_framebuffer_attachment_type_texture_depth )
455 {
456 glGenTextures( 1, &attachment->id );
457 render_fb_allocate_texture( fb, attachment );
458 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
459 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
460 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
461 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
462
463 glFramebufferTexture2D( GL_FRAMEBUFFER, attachment->attachment,
464 GL_TEXTURE_2D, attachment->id, 0 );
465
466 if( attachment->purpose == k_framebuffer_attachment_type_texture )
467 colour_attachments[ colour_count ++ ] = attachment->attachment;
468 }
469 }
470
471 glDrawBuffers( colour_count, colour_attachments );
472
473 /*
474 * Check result
475 */
476 GLenum result = glCheckFramebufferStatus( GL_FRAMEBUFFER );
477
478 if( result == GL_FRAMEBUFFER_COMPLETE ){
479 /*
480 * Attatch to gpipeline
481 */
482 if( fb->link )
483 *fb->link = fb;
484
485 vg_success( " status: complete\n" );
486 vg_info( "}\n" );
487 }
488 else{
489 if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT )
490 vg_error( " status: Incomplete attachment" );
491 else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT )
492 vg_error( " status: Missing attachment" );
493 else if( result == GL_FRAMEBUFFER_UNSUPPORTED )
494 vg_error( " status: Unsupported framebuffer format" );
495 else
496 vg_error( " status: Generic Error" );
497
498 vg_info( "}\n" );
499 vg_fatal_error( "Incomplete framebuffer (see logs)" );
500 }
501 }
502
503 /*
504 * Resize/Update all framebuffers(we know about)
505 */
506 static void render_fb_resize(void)
507 {
508 if( !gpipeline.ready ) return;
509
510 for( int i=0; i<vg_list_size(framebuffers); i++ ){
511 struct framebuffer *fb = &framebuffers[i];
512 for( int j=0; j<vg_list_size(fb->attachments); j++ ){
513 struct framebuffer_attachment *attachment = &fb->attachments[j];
514 render_fb_allocate_texture( fb, attachment );
515 }
516 }
517 }
518
519 static int render_framebuffer_control( int argc, char const *argv[] );
520 static void render_framebuffer_poll( int argc, char const *argv[] );
521
522 static void async_render_init( void *payload, u32 size )
523 {
524 /*
525 * Complete Framebuffers
526 */
527 for( int i=0; i<vg_list_size(framebuffers); i++ ){
528 struct framebuffer *fb = &framebuffers[i];
529 render_fb_allocate( fb );
530 }
531
532 f32 rh = 0x1p-4f, ih = 0.3f;
533
534 float quad[] = {
535 0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f, /* fsquad */
536 0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,
537
538 0.00f,0.00f, 1.00f,rh, 0.00f,rh, /* fsquad1 */
539 0.00f,0.00f, 1.00f,0.00f, 1.00f,rh,
540
541 /* 9x9 debug grid */
542 /* row0 */
543 0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
544 0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
545 0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
546 0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
547 0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
548 0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
549 /* row1 */
550 0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
551 0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
552 0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
553 0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
554 0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
555 0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
556 /* row2 */
557 0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
558 0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
559 0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
560 0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
561 0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
562 0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
563
564 0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh, /* fsquad2 */
565 0.00f,ih, 1.00f,ih, 1.00f,ih+rh,
566 };
567
568 vg_console_reg_cmd( "fb", render_framebuffer_control,
569 render_framebuffer_poll );
570 glGenVertexArrays( 1, &gpipeline.fsquad.vao );
571 glGenBuffers( 1, &gpipeline.fsquad.vbo );
572 glBindVertexArray( gpipeline.fsquad.vao );
573 glBindBuffer( GL_ARRAY_BUFFER, gpipeline.fsquad.vbo );
574 glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
575 glBindVertexArray( gpipeline.fsquad.vao );
576 glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE,
577 sizeof(float)*2, (void*)0 );
578 glEnableVertexAttribArray( 0 );
579
580 VG_CHECK_GL_ERR();
581
582 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
583 gpipeline.ready = 1;
584 }
585
586 static void render_init(void)
587 {
588 vg_console_reg_var( "blur_strength", &k_blur_strength, k_var_dtype_f32, 0 );
589 vg_console_reg_var( "render_scale", &k_render_scale,
590 k_var_dtype_f32, VG_VAR_PERSISTENT );
591 vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
592 vg_console_reg_var( "cam_height", &k_cam_height,
593 k_var_dtype_f32, VG_VAR_PERSISTENT );
594 vg_console_reg_var( "blur_effect", &k_blur_effect,
595 k_var_dtype_i32, VG_VAR_PERSISTENT );
596
597
598 shader_blit_register();
599 shader_blitblur_register();
600 shader_blitcolour_register();
601 shader_blit_transition_register();
602
603 vg_async_call( async_render_init, NULL, 0 );
604 }
605
606 /*
607 * Utility
608 */
609 static void render_fsquad(void)
610 {
611 glBindVertexArray( gpipeline.fsquad.vao );
612 glDrawArrays( GL_TRIANGLES, 0, 6 );
613 }
614
615 static void render_fsquad1(void)
616 {
617 glBindVertexArray( gpipeline.fsquad.vao );
618 glDrawArrays( GL_TRIANGLES, 6, 6 );
619 }
620
621 static void render_fsquad2(void)
622 {
623 glBindVertexArray( gpipeline.fsquad.vao );
624 glDrawArrays( GL_TRIANGLES, 66,6 );
625 }
626
627 /*
628 * Call this inside the UI function
629 */
630 static void render_view_framebuffer_ui(void)
631 {
632 #if 0
633 int viewing_count = 0;
634
635 glBindVertexArray( gpipeline.fsquad.vao );
636 shader_blit_use();
637 shader_blit_uTexMain( 0 );
638
639 v2f identity = { 1.0f, 1.0f };
640 shader_blit_uInverseRatio( identity );
641
642 for( int i=0; i<vg_list_size(framebuffers); i++ ){
643 struct framebuffer *fb = &framebuffers[i];
644
645 for( int j=0; j<vg_list_size(fb->attachments); j++ ){
646 struct framebuffer_attachment *at = &fb->attachments[j];
647
648 if( !at->debug_view )
649 continue;
650
651 v2f corner,
652 window = { vg.window_x, vg.window_y };
653
654 corner[0] = viewing_count % 3;
655 corner[1] = 1 + (viewing_count / 3);
656 v2_mul( corner, window, corner );
657 v2_muls( corner, 0.3f, corner );
658 corner[1] = vg.window_y - corner[1];
659
660 ui_text( (ui_rect){ corner[0], corner[1], 0.0f, 0.0f },
661 fb->display_name, 2, k_text_align_left );
662 ui_text( (ui_rect){ corner[0], corner[1] + 32, 0.0f, 0.0f, },
663 at->display_name, 1, k_text_align_left );
664
665 if( at->purpose == k_framebuffer_attachment_type_renderbuffer ){
666 v2f center;
667 v2_muladds( corner, window, 0.15f, center );
668
669 ui_text( (ui_rect){ center[0], center[1], 0.0f, 0.0f },
670 "<hardware texture>", 1, k_text_align_center );
671 }
672 else{
673 render_fb_bind_texture( fb, j, 0 );
674
675 int start = (viewing_count+2) * 6,
676 count = 6;
677 glDrawArrays( GL_TRIANGLES, start, count );
678 }
679
680 viewing_count ++;
681 }
682 }
683 #endif
684 }
685
686 static void render_framebuffer_show( struct framebuffer *fb,
687 struct framebuffer_attachment *at,
688 int operation )
689 {
690 at->debug_view = operation;
691 vg_info( "%s %s:%s\n", (operation?"shown": "hidden"),
692 fb->display_name, at->display_name );
693 }
694
695 /*
696 * arg0: command "show"/"hide"
697 * arg1: framebuffer name <name>/"all"
698 * arg2: subname <name>/none
699 */
700 static int render_framebuffer_control( int argc, char const *argv[] )
701 {
702 if( argc < 2 ){
703 vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
704 return 0;
705 }
706
707 int modify_all = 0,
708 operation = 0;
709
710 if( !strcmp( argv[0], "show" ) )
711 operation = 1;
712 else if( !strcmp( argv[0], "hide" ) )
713 operation = 0;
714 else{
715 vg_error( "Unknown framebuffer operation: '%s'\n", argv[0] );
716 return 0;
717 }
718
719 if( !strcmp( argv[1], "all" ) )
720 modify_all = 1;
721
722 for( int i=0; i<vg_list_size(framebuffers); i++ ){
723 struct framebuffer *fb = &framebuffers[i];
724
725 for( int j=0; j<vg_list_size(fb->attachments); j++ ){
726 struct framebuffer_attachment *at = &fb->attachments[j];
727
728 if( at->purpose == k_framebuffer_attachment_type_none )
729 continue;
730
731 if( modify_all ){
732 render_framebuffer_show( fb, at, operation );
733 }
734 else{
735 if( !strcmp( fb->display_name, argv[1] ) ){
736 if( argc == 2 )
737 render_framebuffer_show( fb, at, operation );
738 else if( !strcmp( at->display_name, argv[2] ) )
739 render_framebuffer_show( fb, at, operation );
740 }
741 }
742 }
743 }
744
745 return 0;
746 }
747
748 static void render_framebuffer_poll( int argc, char const *argv[] )
749 {
750 const char *term = argv[argc-1];
751
752 if( argc == 1 ){
753 console_suggest_score_text( "show", term, 0 );
754 console_suggest_score_text( "hide", term, 0 );
755 }
756 else if( argc == 2 ){
757 console_suggest_score_text( "all", term, 0 );
758
759 for( int i=0; i<vg_list_size(framebuffers); i++ ){
760 struct framebuffer *fb = &framebuffers[i];
761 console_suggest_score_text( fb->display_name, term, 0 );
762 }
763 }
764 else if( argc == 3 ){
765 int modify_all = 0;
766
767 if( !strcmp( argv[1], "all" ) )
768 modify_all = 1;
769
770 for( int i=0; i<vg_list_size(framebuffers); i++ ){
771 struct framebuffer *fb = &framebuffers[i];
772
773 for( int j=0; j<vg_list_size(fb->attachments); j++ ){
774 struct framebuffer_attachment *at = &fb->attachments[j];
775
776 if( at->purpose == k_framebuffer_attachment_type_none )
777 continue;
778
779 if( modify_all ){
780 console_suggest_score_text( at->display_name, term, 0 );
781 }
782 else if( !strcmp( fb->display_name, argv[1] ) ){
783 console_suggest_score_text( at->display_name, term, 0 );
784 }
785 }
786 }
787 }
788 }
789
790 #endif /* RENDER_H */