absolute shit
authorhgn <hgodden00@gmail.com>
Wed, 12 Feb 2025 03:07:57 +0000 (03:07 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 12 Feb 2025 03:07:57 +0000 (03:07 +0000)
15 files changed:
build.c
content_skaterift/maps/dev_heaven/main.mdl
content_skaterift/models/rs_gate.mdl
content_skaterift/models/rs_skydome.mdl
shaders/model_sky.vs [new file with mode: 0644]
shaders/model_sky_cubemap.fs [new file with mode: 0644]
src/entity.h
src/world.h
src/world_entity.c
src/world_gate.c
src/world_gate.h
src/world_gen.c
src/world_load.c
src/world_render.c
src/world_render.h

diff --git a/build.c b/build.c
index c7e1a5dce7788e701a4dcc2bfd093ce627bddae2..e6797834ce5082b348c35d9eacafd55627ef0099 100644 (file)
--- a/build.c
+++ b/build.c
@@ -115,6 +115,7 @@ void build_shaders(void){
    /* Models */
    _S( "model_sky",            "model.vs",         "model_sky.fs" );
    _S( "model_sky_space",      "model.vs",         "model_sky_space.fs" );
+   _S( "model_sky_cubemap",    "model_sky.vs",     "model_sky_cubemap.fs" );
    _S( "model_menu",           "model.vs",         "model_menu.fs" );
    _S( "model_character_view", "model_skinned.vs", "model_character_view.fs" );
    _S( "model_board_view",     "model.vs",         "model_character_view.fs" );
index 2adad981918fe04d61a849b16bdfa286b61e54c8..113569b272a243acd85c8d7814d60419916dd741 100644 (file)
Binary files a/content_skaterift/maps/dev_heaven/main.mdl and b/content_skaterift/maps/dev_heaven/main.mdl differ
index 1cae7c174d2adcbdca5ce1aaa00211b0511bf6e3..597b12c801048494d4d0d63d56ddee8c2865eae1 100644 (file)
Binary files a/content_skaterift/models/rs_gate.mdl and b/content_skaterift/models/rs_gate.mdl differ
index 53980b142be1d98c70985d67d7cf05e730329c21..066a5232976d92d5f62828b434b5a4cb67e52053 100644 (file)
Binary files a/content_skaterift/models/rs_skydome.mdl and b/content_skaterift/models/rs_skydome.mdl differ
diff --git a/shaders/model_sky.vs b/shaders/model_sky.vs
new file mode 100644 (file)
index 0000000..baf4d77
--- /dev/null
@@ -0,0 +1,34 @@
+layout (location=0) in vec3 a_co;
+layout (location=1) in vec3 a_norm;
+layout (location=2) in vec2 a_uv;
+layout (location=3) in vec4 a_colour;
+layout (location=4) in vec4 a_weights;
+layout (location=5) in ivec4 a_groups;
+
+#include "motion_vectors_vs.glsl"
+
+uniform mat4x3 uMdl;
+uniform mat4 uPv;
+uniform mat4 uPvmPrev;
+
+out vec4 aColour;
+out vec2 aUv;
+out vec3 aNorm;
+out vec3 aCo;
+out vec3 aWorldCo;
+
+void main()
+{
+   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );
+   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );
+   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );
+
+   vs_motion_out( vproj0, vproj1 );
+
+   gl_Position = vproj0;
+   aWorldCo = world_pos0;
+   aColour = a_colour;
+   aUv = a_uv;
+   aNorm = a_norm;
+   aCo = a_co;
+}
diff --git a/shaders/model_sky_cubemap.fs b/shaders/model_sky_cubemap.fs
new file mode 100644 (file)
index 0000000..8385714
--- /dev/null
@@ -0,0 +1,19 @@
+uniform samplerCube uTexCubemap;
+
+in vec4 aColour;
+in vec2 aUv;
+in vec3 aNorm;
+in vec3 aCo;
+in vec3 aWorldCo;
+
+#include "motion_vectors_fs.glsl"
+
+layout (location = 0) out vec4 oColour;
+
+void main()
+{
+   compute_motion_vectors();
+
+   vec3 rd = -normalize(aNorm);
+   oColour = vec4(texture(uTexCubemap,rd).rgb, 1.0);
+}
index 1f2ada44185a1070ea5eb4e5a804ec0d3cf3c260..50e202dcd0afe7709c5747100f0bc6ffbf79bb14 100644 (file)
@@ -203,7 +203,12 @@ struct ent_gate{
       };
    };
 
-   double timing_time;
+   union
+   {
+      double timing_time;
+      u32 cubemap_id;
+   };
+
    u16 routes[4];       /* routes that pass through this gate */
    u8 route_count;
 
index 662a3dd7da10bf4415fc07fe3174ecf10ccee204..7cd280f86dfff19f70c8945fe91910c487d26691 100644 (file)
@@ -183,10 +183,14 @@ struct world_instance
       struct script_info *story_script;
    }
    * events;
+   
+   GLuint *nonlocal_gates_cubemaps;
+   u32 nonlocal_gate_count;
 
    enum skybox {
       k_skybox_default,
-      k_skybox_space
+      k_skybox_space,
+      k_skybox_cubemap
    } skybox;
 
    ent_gate *rendering_gate;
index c4b745fbfaddfc7aec29c98a8f3171c24eb7803b..025126a167eaac869efa3afe69691f11f84a3b86 100644 (file)
@@ -183,8 +183,46 @@ void world_gen_entities_init( world_instance *world )
       light->angle_sin_cos[1] = cosf( light->angle * 0.5f );
    }
 
-   vg_async_call( world_link_gates_async, world, 0 );
-   vg_async_stall();
+   world->nonlocal_gate_count = 0;
+   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 )
+      {
+         gate->cubemap_id = world->nonlocal_gate_count;
+         world->nonlocal_gate_count ++;
+      }
+   }
+
+   if( world->nonlocal_gate_count )
+   {
+      world->nonlocal_gates_cubemaps = vg_linear_alloc( world->heap, 
+                                                        vg_align8(world->nonlocal_gate_count*sizeof(GLuint)) );
+      for( u32 i=0; i<world->nonlocal_gate_count; i ++ )
+         world->nonlocal_gates_cubemaps[i] = 0;
+
+      vg_async_call( world_link_gates_async, world, 0 );
+      vg_async_stall();
+
+      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) && (gate->flags & k_ent_gate_linked) )
+         {
+            if( gate->addon_reg != 0xffffffff )
+            {
+               addon_reg *reg = get_addon_from_index( k_addon_type_world, gate->addon_reg, 0 );
+               
+               char cubemap_path[256];
+               nonlocal_gate_cubemap_path( reg, af_str( &world->meta.af, gate->key ), cubemap_path );
+               vg_tex2d_load_qoi_async_file( cubemap_path, VG_TEX2D_CUBEMAP, 
+                                             &world->nonlocal_gates_cubemaps[ gate->cubemap_id ] );
+            }
+         }
+      }
+   }
+   else
+      world->nonlocal_gates_cubemaps = NULL;
 
    /* water */
    for( u32 j=0; j<af_arrcount(&world->ent_water); j++ )
index 6ab4c7b0b4dd8ab58877cf1a989dd09f491551a1..adf0bd2b3145a6cccd38a95ba94f49f6974a7b5d 100644 (file)
@@ -185,8 +185,11 @@ int render_gate( world_instance *world, world_instance *world_inside,
    shader_model_gate_uMdl( mmdl );
    render_gate_mesh( world, gate );
 
-   render_world( world_inside, &world_gates.cam, 
-                 1, !localplayer.gate_waiting, 1, 1 );
+   if( world_inside )
+   {
+      render_world( world_inside, &world_gates.cam, 
+                    1, !localplayer.gate_waiting, 1, 1 );
+   }
 
    return 1;
 }
@@ -316,6 +319,19 @@ entity_call_result ent_gate_call( world_instance *world, ent_call *call )
    }
 }
 
+void nonlocal_gate_cubemap_path( addon_reg *world_addon, const char *gate_key, char path[256] )
+{
+   char id[76];
+   addon_alias_uid( &world_addon->alias, id );
+
+   vg_str path_str;
+   vg_strnull( &path_str, path, 256 );
+   vg_strcat( &path_str, id );
+   vg_strcat( &path_str, "-cm-" );
+   vg_strcat( &path_str, gate_key );
+   vg_strcat( &path_str, ".qoi" );
+}
+
 /*
  * This has to be synchronous because main thread looks at gate data for 
  * rendering, and we modify gates that the main thread has ownership of.
index a071e4bb20ee575e59c5f1722ade8b4da0ac0dab..6bdfe91dfc221c9f0b109fbcc142d05068a4e0bd 100644 (file)
@@ -34,3 +34,4 @@ void world_link_gates_async( void *payload, u32 size );
 void world_unlink_nonlocal( world_instance *world );
 void render_gate_unlinked( world_instance *world,
                            ent_gate *gate, vg_camera *cam );
+void nonlocal_gate_cubemap_path( addon_reg *world_addon, const char *gate_key, char path[256] );
index 6c1b8ee1dd49949b15e20146e6d5b87fa8075e7a..30ee158992bc0fb2c965e1c0cc4e17f99e06ea47 100644 (file)
@@ -701,9 +701,6 @@ void async_world_postprocess( void *payload, u32 _size )
                glBindRenderbuffer( GL_RENDERBUFFER, cm->renderbuffer_id );
                glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 
                               WORLD_CUBEMAP_RES, WORLD_CUBEMAP_RES );
-
-               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                       GL_TEXTURE_CUBE_MAP_POSITIVE_X, cm->texture_id, 0 );
                glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
                                  GL_RENDERBUFFER, cm->renderbuffer_id );
 
index 2cb84198ce18d8243e940c48e1c820ade32f78bf..b75a80db620afe3c838db9ee8d1ed0842467ecd9 100644 (file)
@@ -530,6 +530,8 @@ void world_instance_free_graphics_data( world_instance *world )
       glDeleteFramebuffers( 1, &cm->framebuffer_id );
       glDeleteRenderbuffers( 1, &cm->renderbuffer_id );
    }
+
+   glDeleteTextures( world->nonlocal_gate_count, world->nonlocal_gates_cubemaps );
 }
 
 /* 
index bf71a7c241b86cd728ac32d5b76169dfca782d7d..12b94fa1f9d5167bc38c8f0652feb582cc742503 100644 (file)
 #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] );
@@ -46,6 +50,7 @@ void world_render_init(void)
    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;
@@ -57,6 +62,8 @@ void world_render_init(void)
    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" );
@@ -850,6 +857,10 @@ static void render_sky( world_instance *world, vg_camera *cam )
       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" );
    }
@@ -858,7 +869,7 @@ static void render_sky( world_instance *world, vg_camera *cam )
    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 );
@@ -904,7 +915,44 @@ void render_world_gates( world_instance *world, vg_camera *cam )
 
          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
          {
@@ -1229,13 +1277,9 @@ void render_world_override( world_instance *world,
    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 },
@@ -1253,13 +1297,17 @@ static void render_cubemap_side( world_instance *world, ent_cubemap *cm,
       { 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 );
@@ -1272,18 +1320,23 @@ static void render_cubemap_side( world_instance *world, ent_cubemap *cm,
    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 );
 
@@ -1291,11 +1344,102 @@ void render_world_cubemaps( world_instance *world )
          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
  * ---------------------------------------------
index 1eb5ab15d23d314608c9b7ebadb9c7dd1c3d3079..8d512cbe67d4d692c3accada90bc57e6d44eef25 100644 (file)
@@ -30,6 +30,8 @@ struct world_render
 
    /* rendering */
    glmesh skydome;
+   mdl_submesh skydome_complete_mesh,
+               skydome_squanched_mesh;
 
    double sky_time, sky_rate, sky_target_rate;