k_framebuffer_quality_high_only
}
quality;
-
+
GLenum internalformat,
format,
type,
attachment;
GLuint id;
+
+ /* Runtime */
+ int debug_view;
}
attachments[5];
GLuint fb;
/*
* The primary draw target
*/
- "Main",
+ "main",
.link = &gpipeline.fb_main,
.resolution_div = 1,
.attachments =
{
{
- "Colour", k_framebuffer_attachment_type_colour,
+ "colour", k_framebuffer_attachment_type_colour,
.internalformat = GL_RGB,
.format = GL_RGB,
.attachment = GL_COLOR_ATTACHMENT0
},
{
- "Motion Vectors", k_framebuffer_attachment_type_colour,
+ "motion", k_framebuffer_attachment_type_colour,
.quality = k_framebuffer_quality_high_only,
.internalformat = GL_RG16F,
.attachment = GL_COLOR_ATTACHMENT1
},
{
- "Depth/Stencil", k_framebuffer_attachment_type_renderbuffer,
+ "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
.internalformat = GL_DEPTH24_STENCIL8,
.attachment = GL_DEPTH_STENCIL_ATTACHMENT
* Note: it does not have a render buffer attachement because it's
* intended to be drawn to in a MAX blending mode
*/
- "Heightmap",
+ "heightmap",
.link = &gpipeline.fb_heightmap,
.fixed_w = 1024,
.fixed_h = 1024,
.attachments =
{
{
- "Depth", k_framebuffer_attachment_type_colour,
+ "depth", k_framebuffer_attachment_type_colour,
.internalformat = GL_R32F,
.format = GL_RED,
/*
* Second rendered view from the perspective of the water reflection
*/
- "Water reflection",
+ "water_reflection",
.link = &gpipeline.fb_water_reflection,
.resolution_div = 3,
.attachments =
{
{
- "Colour", k_framebuffer_attachment_type_colour,
+ "colour", k_framebuffer_attachment_type_colour,
.internalformat = GL_RGB,
.format = GL_RGB,
.type = GL_UNSIGNED_BYTE,
.attachment = GL_COLOR_ATTACHMENT0
},
{
- "Depth/Stencil", k_framebuffer_attachment_type_renderbuffer,
+ "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
.internalformat = GL_DEPTH24_STENCIL8,
.attachment = GL_DEPTH_STENCIL_ATTACHMENT
* Thid rendered view from the perspective of the camera, but just
* captures stuff thats under the water
*/
- "Water Beneath",
+ "water_beneath",
.link = &gpipeline.fb_water_beneath,
.resolution_div = 4,
.attachments =
{
{
- "Colour", k_framebuffer_attachment_type_colour,
+ "colour", k_framebuffer_attachment_type_colour,
.internalformat = GL_RGBA,
.format = GL_RGBA,
.type = GL_UNSIGNED_BYTE,
.attachment = GL_COLOR_ATTACHMENT0
},
{
- "Depth/Stencil", k_framebuffer_attachment_type_renderbuffer,
+ "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
.internalformat = GL_DEPTH24_STENCIL8,
.attachment = GL_DEPTH_STENCIL_ATTACHMENT
}
}
+VG_STATIC int render_framebuffer_control( int argc, char const *argv[] );
+VG_STATIC void render_framebuffer_poll( int argc, char const *argv[] );
VG_STATIC void render_init_fs_quad(void)
{
vg_info( "[render] Allocate quad\n" );
- float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+ float quad[] =
+ {
+ 0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,
+ 0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,
+
+ 0.20f,0.00f, 0.80f,1.00f, 0.20f,1.00f,
+ 0.20f,0.00f, 0.80f,0.00f, 0.80f,1.00f,
+
+ /* 9x9 debug grid */
+ /* row0 */
+ 0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
+ 0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
+ 0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
+ 0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
+ 0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
+ 0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
+ /* row1 */
+ 0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
+ 0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
+ 0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
+ 0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
+ 0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
+ 0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
+ /* row2 */
+ 0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
+ 0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
+ 0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
+ 0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
+ 0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
+ 0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
+ };
- 0.2f, 0.0f, 0.8f, 1.0f, 0.2f, 1.0f,
- 0.2f, 0.0f, 0.8f, 0.0f, 0.8f, 1.0f};
+ vg_function_push( (struct vg_cmd)
+ {
+ .name = "fb",
+ .function = render_framebuffer_control,
+ .poll_suggest = render_framebuffer_poll
+ });
glGenVertexArrays( 1, &gpipeline.fsquad.vao );
glGenBuffers( 1, &gpipeline.fsquad.vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
glBindVertexArray( gpipeline.fsquad.vao );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE,
- sizeof(float)*2, (void*)0 );
+ sizeof(float)*2, (void*)0 );
glEnableVertexAttribArray( 0 );
VG_CHECK_GL_ERR();
glDrawArrays( GL_TRIANGLES, 6, 6 );
}
+/*
+ * Call this inside the UI function
+ */
+VG_STATIC void render_view_framebuffer_ui(void)
+{
+ int viewing_count = 0;
+
+ glBindVertexArray( gpipeline.fsquad.vao );
+ shader_blit_use();
+ shader_blit_uTexMain( 0 );
+
+ for( int i=0; i<vg_list_size(framebuffers); i++ )
+ {
+ struct framebuffer *fb = &framebuffers[i];
+
+ for( int j=0; j<vg_list_size(fb->attachments); j++ )
+ {
+ struct framebuffer_attachment *at = &fb->attachments[j];
+
+ if( !at->debug_view )
+ continue;
+
+ v2f corner,
+ window = { vg.window_x, vg.window_y };
+
+ corner[0] = viewing_count % 3;
+ corner[1] = 1 + (viewing_count / 3);
+ v2_mul( corner, window, corner );
+ v2_muls( corner, 0.3f, corner );
+ corner[1] = vg.window_y - corner[1];
+
+ ui_text( (ui_rect){ corner[0], corner[1], 0.0f, 0.0f },
+ fb->display_name, 2, k_text_align_left );
+ ui_text( (ui_rect){ corner[0], corner[1] + 32, 0.0f, 0.0f, },
+ at->display_name, 1, k_text_align_left );
+
+ if( at->purpose == k_framebuffer_attachment_type_renderbuffer )
+ {
+ v2f center;
+ v2_muladds( corner, window, 0.15f, center );
+
+ ui_text( (ui_rect){ center[0], center[1], 0.0f, 0.0f },
+ "<hardware texture>", 1, k_text_align_center );
+ }
+ else
+ {
+ render_fb_bind_texture( fb, j, 0 );
+
+ int start = (viewing_count+2) * 6,
+ count = 6;
+ glDrawArrays( GL_TRIANGLES, start, count );
+ }
+
+ viewing_count ++;
+ }
+ }
+}
+
+VG_STATIC void render_framebuffer_show( struct framebuffer *fb,
+ struct framebuffer_attachment *at,
+ int operation )
+{
+ at->debug_view = operation;
+ vg_info( "%s %s:%s\n", (operation?"shown": "hidden"),
+ fb->display_name, at->display_name );
+}
+
+/*
+ * arg0: command "show"/"hide"
+ * arg1: framebuffer name <name>/"all"
+ * arg2: subname <name>/none
+ */
+VG_STATIC int render_framebuffer_control( int argc, char const *argv[] )
+{
+ if( argc < 2 )
+ {
+ vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
+ return 0;
+ }
+
+ int modify_all = 0,
+ operation = 0;
+
+ if( !strcmp( argv[0], "show" ) )
+ operation = 1;
+ else if( !strcmp( argv[0], "hide" ) )
+ operation = 0;
+ else
+ {
+ vg_error( "Unknown framebuffer operation: '%s'\n", argv[0] );
+ return 0;
+ }
+
+ if( !strcmp( argv[1], "all" ) )
+ modify_all = 1;
+
+ for( int i=0; i<vg_list_size(framebuffers); i++ )
+ {
+ struct framebuffer *fb = &framebuffers[i];
+
+ for( int j=0; j<vg_list_size(fb->attachments); j++ )
+ {
+ struct framebuffer_attachment *at = &fb->attachments[j];
+
+ if( at->purpose == k_framebuffer_attachment_type_none )
+ continue;
+
+ if( modify_all )
+ {
+ render_framebuffer_show( fb, at, operation );
+ }
+ else
+ {
+ if( !strcmp( fb->display_name, argv[1] ) )
+ {
+ if( argc == 2 )
+ render_framebuffer_show( fb, at, operation );
+ else if( !strcmp( at->display_name, argv[2] ) )
+ render_framebuffer_show( fb, at, operation );
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+VG_STATIC void render_framebuffer_poll( int argc, char const *argv[] )
+{
+ const char *term = argv[argc-1];
+
+ if( argc == 1 )
+ {
+ console_suggest_score_text( "show", term, 0 );
+ console_suggest_score_text( "hide", term, 0 );
+ }
+ else if( argc == 2 )
+ {
+ console_suggest_score_text( "all", term, 0 );
+
+ for( int i=0; i<vg_list_size(framebuffers); i++ )
+ {
+ struct framebuffer *fb = &framebuffers[i];
+ console_suggest_score_text( fb->display_name, term, 0 );
+ }
+ }
+ else if( argc == 3 )
+ {
+ int modify_all = 0;
+
+ if( !strcmp( argv[1], "all" ) )
+ modify_all = 1;
+
+ for( int i=0; i<vg_list_size(framebuffers); i++ )
+ {
+ struct framebuffer *fb = &framebuffers[i];
+
+ for( int j=0; j<vg_list_size(fb->attachments); j++ )
+ {
+ struct framebuffer_attachment *at = &fb->attachments[j];
+
+ if( at->purpose == k_framebuffer_attachment_type_none )
+ continue;
+
+ if( modify_all )
+ {
+ console_suggest_score_text( at->display_name, term, 0 );
+ }
+ else if( !strcmp( fb->display_name, argv[1] ) )
+ {
+ console_suggest_score_text( at->display_name, term, 0 );
+ }
+ }
+ }
+ }
+}
+
#endif /* RENDER_H */