#include "common.h"
#include "model.h"
+#include "camera.h"
#include "shaders/blit.h"
+#include "shaders/blitblur.h"
#include "shaders/standard.h"
#include "shaders/vblend.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 );
-static void shader_link_standard_ub( GLuint shader, int texture_id );
-static void render_world_depth( m4x4f projection, m4x3f camera );
+VG_STATIC void render_water_texture( camera *cam );
+VG_STATIC void render_water_surface( camera *cam );
+VG_STATIC void render_world( camera *cam );
+VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id );
+VG_STATIC void render_world_depth( camera *cam );
#ifndef RENDER_H
#define RENDER_H
int allocated;
};
-static struct pipeline
+/*
+ * All standard buffers used in rendering
+ */
+VG_STATIC struct pipeline
{
+#if 0
float fov;
+#endif
glmesh fsquad;
GLuint fb_background,
- rgb_background;
+ rgb_background,
+ mv_background,
+ rb_background;
/* STD140 */
struct ub_world_lighting
float g_water_fog;
int g_light_count;
int g_light_preview;
+ int g_shadow_samples;
}
ub_world_lighting;
}
};
-/*
- * Matrix Projections
- */
-/*
- * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
- */
-static void plane_clip_projection( m4x4f mat, v4f plane )
-{
- v4f c =
- {
- (vg_signf(plane[0]) + mat[2][0]) / mat[0][0],
- (vg_signf(plane[1]) + mat[2][1]) / mat[1][1],
- -1.0f,
- (1.0f + mat[2][2]) / mat[3][2]
- };
-
- v4_muls( plane, 2.0f / v4_dot(plane,c), c );
-
- mat[0][2] = c[0];
- mat[1][2] = c[1];
- mat[2][2] = c[2] + 1.0f;
- mat[3][2] = c[3];
-}
-
-static void pipeline_projection( m4x4f mat, float nearz, float farz )
-{
- m4x4_projection( mat,
- gpipeline.fov,
- (float)vg.window_x / (float)vg.window_y,
- nearz, farz );
-}
-
/*
* Shaders
*/
-static void shader_link_standard_ub( GLuint shader, int texture_id )
+VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id )
{
GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );
glUniformBlockBinding( shader, idx, 0 );
glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id );
}
-static void render_update_lighting_ub(void)
+VG_STATIC void render_update_lighting_ub(void)
{
struct ub_world_lighting *winf = &gpipeline.ub_world_lighting;
int c = 0;
winf->g_light_directions[0][3] = gpipeline.shadow_length;
winf->g_light_colours[0][3] = gpipeline.shadow_spread;
+ if( vg.quality_profile == k_quality_profile_low )
+ winf->g_shadow_samples = 0;
+ else
+ winf->g_shadow_samples = 8;
+
glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting );
glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting),
&gpipeline.ub_world_lighting );
* Framebuffers
*/
-static void fb_use( struct framebuffer *fb )
+VG_STATIC void fb_use( struct framebuffer *fb )
{
if( !fb )
{
- glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
glViewport( 0, 0, vg.window_x, vg.window_y );
}
else
}
}
-static void fb_init( struct framebuffer *fb )
+VG_STATIC void fb_init( struct framebuffer *fb )
{
i32 ix = vg.window_x / fb->div,
iy = vg.window_y / fb->div;
fb->allocated = 1;
}
-static void fb_free( struct framebuffer *fb )
+VG_STATIC void fb_free( struct framebuffer *fb )
{
glDeleteTextures( 1, &fb->colour );
glDeleteFramebuffers( 1, &fb->fb );
}
-static void fb_bindtex( struct framebuffer *fb, int texture )
+VG_STATIC void fb_bindtex( struct framebuffer *fb, int texture )
{
glActiveTexture( GL_TEXTURE0 + texture );
glBindTexture( GL_TEXTURE_2D, fb->colour );
}
-static void fb_resize( struct framebuffer *fb )
+VG_STATIC void fb_resize( struct framebuffer *fb )
{
if( !fb->allocated )
return;
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy );
}
-static void render_fb_resize(void)
+VG_STATIC void render_fb_resize(void)
{
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 );
+
+ /* FIXME: Resizeother textures and rb */
}
}
-/* used for drawing player onto */
-static void render_init_temp_buffer(void)
+VG_STATIC void render_init_temp_buffer(void)
{
- vg_info( "[render] Allocate temporary framebuffer\n" );
+ vg_info( "[render] Allocate framebuffer\n" );
glGenFramebuffers( 1, &gpipeline.fb_background );
glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background );
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);
-
+ 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
- gpipeline.rgb_background, 0);
+ gpipeline.rgb_background, 0 );
+
+ glGenTextures( 1, &gpipeline.mv_background );
+ glBindTexture( GL_TEXTURE_2D, gpipeline.mv_background );
+#if 0
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RG, vg.window_x, vg.window_y,
+ 0, GL_RG, GL_FLOAT, NULL);
+#endif
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F, vg.window_x, vg.window_y,
+ 0, GL_RGBA, GL_FLOAT, NULL);
+
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1,
+ GL_TEXTURE_2D,
+ gpipeline.mv_background, 0 );
+
+ /* render buffer */
+ glGenRenderbuffers( 1, &gpipeline.rb_background );
+ glBindRenderbuffer( GL_RENDERBUFFER, gpipeline.rb_background );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
+ vg.window_x, vg.window_y );
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, gpipeline.rb_background );
+
+ GLuint attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
+ glDrawBuffers( 2, attachments );
+
+ GLenum result = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+ if( result != GL_FRAMEBUFFER_COMPLETE )
+ {
+ if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT )
+ vg_fatal_exit_loop( "Main RT: Incomplete attachment" );
+ else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT )
+ vg_fatal_exit_loop( "Main RT: Missing attachment" );
+ else if( result == GL_FRAMEBUFFER_UNSUPPORTED )
+ vg_fatal_exit_loop( "Main RT: Unsupported framebuffer format" );
+ else
+ vg_fatal_exit_loop( "Main RT: Generic Error" );
+ }
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
VG_CHECK_GL_ERR();
}
/* used for drawing world depth from the top view, used in our water and
* lighting calculations */
-static void render_init_depthmap_buffer(void)
+VG_STATIC void render_init_depthmap_buffer(void)
{
vg_info( "[render] Allocate depth map buffer\n" );
VG_CHECK_GL_ERR();
}
-static void render_init_fs_quad(void)
+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 };
+ 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+
+ 0.2f, 0.0f, 0.8f, 1.0f, 0.2f, 1.0f,
+ 0.2f, 0.0f, 0.8f, 0.0f, 0.8f, 1.0f};
glGenVertexArrays( 1, &gpipeline.fsquad.vao );
glGenBuffers( 1, &gpipeline.fsquad.vbo );
VG_CHECK_GL_ERR();
}
-static void render_init_uniform_buffers(void)
+VG_STATIC void render_init_uniform_buffers(void)
{
vg_info( "[render] Allocate uniform buffer\n" );
VG_CHECK_GL_ERR();
}
-static void render_init(void)
+VG_STATIC void render_init(void)
{
shader_blit_register();
+ shader_blitblur_register();
shader_standard_register();
shader_vblend_register();
vg_release_thread_sync();
}
-static void render_free(void *_)
-{
- glDeleteBuffers( 1, &gpipeline.ubo_world_lighting );
-
- glDeleteVertexArrays( 1, &gpipeline.fsquad.vao );
- glDeleteBuffers( 1, &gpipeline.fsquad.vbo );
-
- glDeleteFramebuffers( 1, &gpipeline.fb_depthmap );
- glDeleteTextures( 1, &gpipeline.rgb_depthmap );
-
- glDeleteFramebuffers( 1, &gpipeline.fb_background );
- glDeleteTextures( 1, &gpipeline.rgb_background );
-}
-
/*
* Utility
*/
-static void render_fsquad(void)
+VG_STATIC void render_fsquad(void)
{
glBindVertexArray( gpipeline.fsquad.vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
}
+VG_STATIC void render_fsquad1(void)
+{
+ glBindVertexArray( gpipeline.fsquad.vao );
+ glDrawArrays( GL_TRIANGLES, 6, 6 );
+}
+
#endif /* RENDER_H */