#include "common.h"
#include "model.h"
+#include "shaders/blit.h"
+#include "shaders/standard.h"
+#include "shaders/vblend.h"
+#include "shaders/unlit.h"
+
static void render_water_texture( m4x3f camera );
static void render_water_surface( m4x4f pv, m4x3f camera );
static void render_world( m4x4f projection, m4x3f camera );
#ifndef RENDER_H
#define RENDER_H
+struct framebuffer
+{
+ GLuint fb, colour, rb;
+ int div;
+ GLuint format;
+
+ int allocated;
+};
+
static struct pipeline
{
float fov;
GLuint fb_depthmap, rgb_depthmap;
GLuint ubo_world_lighting,
ubo_world;
+
+ int ready;
}
gpipeline =
{
&gpipeline.ub_world_lighting );
}
-static void render_alloc_ub(void)
-{
- glGenBuffers( 1, &gpipeline.ubo_world_lighting );
- glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
- glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
- NULL, GL_DYNAMIC_DRAW );
-
- render_update_lighting_ub();
- glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting );
-}
-
/*
* Framebuffers
*/
-struct framebuffer
-{
- GLuint fb, colour, rb;
- int div;
- GLuint format;
-};
static void fb_use( struct framebuffer *fb )
{
}
}
-static void fb_init( struct framebuffer *fb )
+__attribute__((warn_unused_result))
+static int fb_init( struct framebuffer *fb )
{
i32 ix = vg_window_x / fb->div,
iy = vg_window_y / fb->div;
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, fb->rb );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+ if( VG_CHECK_GL_ERR() )
+ {
+ fb->allocated = 0;
+ vg_error( "Error while creating standard framebuffer\n" );
+ return 0;
+ }
+
+ fb->allocated = 1;
+ return 1;
+}
+
+static void fb_free( struct framebuffer *fb )
+{
+ glDeleteTextures( 1, &fb->colour );
+ glDeleteFramebuffers( 1, &fb->fb );
}
static void fb_bindtex( struct framebuffer *fb, int texture )
static void fb_resize( struct framebuffer *fb )
{
+ if( !fb->allocated )
+ return;
+
i32 ix = vg_window_x / fb->div,
iy = vg_window_y / fb->div;
static void render_fb_resize(void)
{
- glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 0,
- GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ if( gpipeline.ready )
+ {
+ glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ }
}
/*
* Vg
*/
-static void render_init(void)
+static int render_init(void)
{
- glGenFramebuffers( 1, &gpipeline.fb_background );
- glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
+ shader_blit_register();
+ shader_standard_register();
+ shader_vblend_register();
+ shader_unlit_register();
- glGenTextures( 1, &gpipeline.rgb_background );
- glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y,
- 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ if( vg_acquire_thread_sync(1) )
+ {
+ vg_info( "Allocating framebuffers\n" );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- gpipeline.rgb_background, 0);
+ glGenFramebuffers( 1, &gpipeline.fb_background );
+ glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
- /*
- * World depth map, maybe this should be moved to world.h
- * TODO: review
- */
- glGenFramebuffers( 1, &gpipeline.fb_depthmap );
- glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
+ glGenTextures( 1, &gpipeline.rgb_background );
+ glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y,
+ 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
- glGenTextures( 1, &gpipeline.rgb_depthmap );
- glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024, 0,
- GL_RED, GL_FLOAT, NULL );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
- vg_tex2d_clamp();
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ gpipeline.rgb_background, 0);
- glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- gpipeline.rgb_depthmap, 0);
+ if( VG_CHECK_GL_ERR() )
+ {
+ vg_error( "Error while creating back buffer\n" );
+ vg_release_thread_sync(1);
+ return 0;
+ }
- 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 };
+ /*
+ * World depth map, maybe this should be moved to world.h
+ * TODO: review
+ */
+ glGenFramebuffers( 1, &gpipeline.fb_depthmap );
+ glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap );
+
+ glGenTextures( 1, &gpipeline.rgb_depthmap );
+ glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024, 0,
+ GL_RED, GL_FLOAT, NULL );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ vg_tex2d_clamp();
+
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ gpipeline.rgb_depthmap, 0);
+
+ if( VG_CHECK_GL_ERR() )
+ {
+ vg_error( "Error while creating world depth buffer\n" );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ vg_release_thread_sync(1);
+ return 0;
+ }
- glGenVertexArrays( 1, &gpipeline.fsquad.vao );
- glGenBuffers( 1, &gpipeline.fsquad.vbo );
- glBindVertexArray( gpipeline.fsquad.vao );
- glBindBuffer( GL_ARRAY_BUFFER, 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 );
- glEnableVertexAttribArray( 0 );
- VG_CHECK_GL();
+ 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 };
- render_alloc_ub();
+ glGenVertexArrays( 1, &gpipeline.fsquad.vao );
+ glGenBuffers( 1, &gpipeline.fsquad.vbo );
+ glBindVertexArray( gpipeline.fsquad.vao );
+ glBindBuffer( GL_ARRAY_BUFFER, 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 );
+ glEnableVertexAttribArray( 0 );
+
+ if( VG_CHECK_GL_ERR() )
+ {
+ vg_error( "Error while creating fsquad\n" );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ vg_release_thread_sync(1);
+ return 0;
+ }
+
+ glGenBuffers( 1, &gpipeline.ubo_world_lighting );
+ glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
+ glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting),
+ NULL, GL_DYNAMIC_DRAW );
+
+ render_update_lighting_ub();
+ glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting );
+
+ if( VG_CHECK_GL_ERR() )
+ {
+ vg_error( "Error while creating world uniform buffers\n" );
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ vg_release_thread_sync(1);
+ return 0;
+ }
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ vg_success( "Done\n" );
+
+ gpipeline.ready = 1;
+ vg_release_thread_sync(1);
+ return 1;
+ }
+ else
+ return 0;
}
-static void render_free(void)
+static void render_free(void *_)
{
- /* TODO: ... */
+ glDeleteVertexArrays( 1, &gpipeline.fsquad.vao );
+ glDeleteBuffers( 1, &gpipeline.fsquad.vbo );
+
+ glDeleteFramebuffers( 1, &gpipeline.fb_background );
+ glDeleteFramebuffers( 1, &gpipeline.fb_depthmap );
+
+ glDeleteTextures( 1, &gpipeline.rgb_background );
+ glDeleteTextures( 1, &gpipeline.rgb_depthmap );
}
/*