#include "player_remote.h"
#include "ent_skateshop.h"
#include "shaders/model_entity.h"
+#include "shaders/model_sky_cubemap.h"
struct world_render world_render;
-static int ccmd_set_time( int argc, const char *argv[] ){
+static int ccmd_render_portals( int argc, const char *argv[] );
+
+static int ccmd_set_time( int argc, const char *argv[] )
+{
world_instance *world = &_world.main;
if( argc == 1 )
world->time = atof( argv[0] );
VG_VAR_I32( k_light_preview );
VG_VAR_I32( k_light_editor );
vg_console_reg_cmd( "set_time", ccmd_set_time, NULL );
+ vg_console_reg_cmd( "render_portals", ccmd_render_portals, NULL );
world_render.sky_rate = 1.0;
world_render.sky_target_rate = 1.0;
mdl_open( &msky, "models/rs_skydome.mdl", vg_mem.scratch );
mdl_load_metadata_block( &msky, vg_mem.scratch );
mdl_async_load_glmesh( &msky, &world_render.skydome, NULL );
+ world_render.skydome_complete_mesh = *mdl_find_submesh( &msky, "dome_complete" );
+ world_render.skydome_squanched_mesh = *mdl_find_submesh( &msky, "dome_squanched" );
mdl_close( &msky );
vg_info( "Loading default world textures\n" );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
}
+ else if( world->skybox == k_skybox_cubemap )
+ {
+ /* TODO */
+ }
else {
vg_fatal_error( "Programming error\n" );
}
glDisable( GL_DEPTH_TEST );
mesh_bind( &world_render.skydome );
- mesh_draw( &world_render.skydome );
+ mdl_draw_submesh( &world_render.skydome_complete_mesh );
glEnable( GL_DEPTH_TEST );
glDepthMask( GL_TRUE );
if( gate->flags & k_ent_gate_linked )
{
+ render_gate( world, NULL, gate, cam );
+
+ m4x3f mmdl;
+ m4x4f pvm;
+
+ m4x3_copy( gate->to_world, mmdl );
+ mmdl[3][1] += 2.0f;
+
+ if( gate->flags & k_ent_gate_flip )
+ {
+ m3x3f rotation = {{-1,0,0},{0,1,0},{0,0,-1}};
+ m3x3_mul( mmdl, rotation, mmdl );
+ }
+
+ m4x3_expand( mmdl, pvm );
+ m4x4_mul( cam->mtx_prev.pv, pvm, pvm );
+
+ shader_model_sky_cubemap_use();
+ shader_model_sky_cubemap_uMdl( mmdl );
+ shader_model_sky_cubemap_uPv( cam->mtx.pv );
+ shader_model_sky_cubemap_uPvmPrev( pvm );
+ shader_model_sky_cubemap_uTexCubemap(10);
+
+ glActiveTexture( GL_TEXTURE10 );
+ glBindTexture( GL_TEXTURE_CUBE_MAP, world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+ glClear( GL_DEPTH_BUFFER_BIT );
+ glStencilFunc( GL_EQUAL, 1, 0xFF );
+ glStencilMask( 0x00 );
+ glEnable( GL_CULL_FACE );
+ glEnable( GL_STENCIL_TEST );
+
+ mesh_bind( &world_render.skydome );
+ mdl_draw_submesh( &world_render.skydome_squanched_mesh );
+
+ glStencilMask( 0xFF );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glDisable( GL_STENCIL_TEST );
}
else
{
render_world_fxglow( world, world, cam, mmdl, 0, 0, 1 );
}
-static void render_cubemap_side( world_instance *world, ent_cubemap *cm,
- u32 side ){
+static void render_cubemap_side( world_instance *world, v3f co, m3x3f rotation, u32 side )
+{
vg_camera cam;
- glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_CUBE_MAP_POSITIVE_X + side, cm->texture_id, 0 );
- glClear( GL_DEPTH_BUFFER_BIT );
-
v3f forward[6] = {
{ -1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f }
};
+ v3f vz, vy;
+ m3x3_mulv( rotation, forward[side], vz );
+ m3x3_mulv( rotation, up[side], vy );
+
v3_zero( cam.angles );
- v3_copy( cm->co, cam.pos );
+ v3_copy( co, cam.pos );
- v3_copy( forward[side], cam.transform[2] );
- v3_copy( up[side], cam.transform[1] );
- v3_cross( up[side], forward[side], cam.transform[0] );
- v3_copy( cm->co, cam.transform[3] );
+ v3_copy( vz, cam.transform[2] );
+ v3_copy( vy, cam.transform[1] );
+ v3_cross( vy, vz, cam.transform[0] );
+ v3_copy( co, cam.transform[3] );
m4x3_invert_affine( cam.transform, cam.transform_inverse );
vg_camera_update_view( &cam );
vg_camera_finalize( &cam );
vg_camera_finalize( &cam );
- render_world( world, &cam, 0, 1, 1, 0 );
+ /* TODO: CANT RENDER CUBEMAPS BECAUSE RENDER_WORLD FUCKS WITH GLVIEWPORT AND STUFF */
+ render_world( world, &cam, 0, 1, 0, 0 );
}
void render_world_cubemaps( world_instance *world )
{
+ m3x3f identity;
+ m3x3_identity( identity );
+
if( world->cubemap_cooldown )
world->cubemap_cooldown --;
else{
world->cubemap_cooldown = 60;
glViewport( 0, 0, WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES );
- for( u32 i=0; i<af_arrcount( &world->ent_cubemap ); i++ ){
+ for( u32 i=0; i<af_arrcount( &world->ent_cubemap ); i++ )
+ {
ent_cubemap *cm = af_arritm( &world->ent_cubemap, i );
glBindFramebuffer( GL_FRAMEBUFFER, cm->framebuffer_id );
if( world->cubemap_side >= 6 )
world->cubemap_side = 0;
- render_cubemap_side( world, cm, world->cubemap_side );
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_CUBE_MAP_POSITIVE_X + world->cubemap_side,
+ cm->texture_id, 0 );
+ glClear( GL_DEPTH_BUFFER_BIT );
+
+ render_cubemap_side( world, cm->co, identity, world->cubemap_side );
}
}
}
+void render_world_portal_cubemaps(void)
+{
+ if( vg_loader_availible() )
+ {
+ qoi_desc desc =
+ {
+ .width = 512,
+ .height = 512*6,
+ .channels = 3,
+ .colorspace = 0
+ };
+
+ vg_linear_clear( vg_async.buffer );
+ u8 *src_image = vg_linear_alloc( vg_async.buffer, 512*512*3*6 );
+ u8 *compressed_image = vg_linear_alloc( vg_async.buffer, vg_query_qoi_storage_size( &desc ) );
+
+ GLuint temp_tex, temp_fb, temp_rb;
+
+ glGenFramebuffers( 1, &temp_fb );
+ glBindFramebuffer( GL_FRAMEBUFFER, temp_fb );
+
+ glGenRenderbuffers( 1, &temp_rb );
+ glBindRenderbuffer( GL_RENDERBUFFER, temp_rb );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 512, 512 );
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, temp_rb );
+
+ glGenTextures( 1, &temp_tex );
+ glBindTexture( GL_TEXTURE_2D, temp_tex );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL );
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_tex, 0 );
+
+ if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE )
+ {
+ vg_error( "Cubemap framebuffer incomplete.\n" );
+ return;
+ }
+
+ glViewport( 0, 0, 512, 512 );
+
+ world_instance *world = &_world.main;
+
+ for( u32 j=0; j<af_arrcount(&world->ent_gate); j ++ )
+ {
+ ent_gate *gate = af_arritm( &world->ent_gate, j );
+ if( gate->flags & k_ent_gate_nonlocal )
+ {
+ v3f co;
+ v3_add( gate->co[0], (v3f){0,2,0}, co );
+
+ m3x3f rotation;
+ m3x3f correction = {{0,0,1},{0,1,0},{-1,0,0}};
+ m3x3_mul( correction, gate->to_world, rotation );
+
+ for( u32 i=0; i<6; i ++ )
+ {
+ glClear( GL_DEPTH_BUFFER_BIT );
+ render_cubemap_side( &_world.main, co, gate->to_world, i );
+
+ u8 *dest_side = src_image + i*512*512*3;
+ glReadBuffer( GL_COLOR_ATTACHMENT0 );
+ glReadPixels( 0,0, 512,512, GL_RGB, GL_UNSIGNED_BYTE, dest_side );
+ }
+
+ char path[256];
+ nonlocal_gate_cubemap_path( world->addon, af_str( &world->meta.af, gate->key ), path );
+
+ int file_size;
+ if( vg_encode_qoi2( src_image, &desc, compressed_image, &file_size ) )
+ {
+ vg_asset_write( path, compressed_image, file_size );
+ }
+ }
+ }
+
+ glDeleteTextures( 1, &temp_tex );
+ glDeleteFramebuffers( 1, &temp_fb );
+ glDeleteRenderbuffers( 1, &temp_rb );
+ }
+}
+
+static int ccmd_render_portals( int argc, const char *argv[] )
+{
+ render_world_portal_cubemaps();
+ return 1;
+}
+
/*
* Geo shaders
* ---------------------------------------------