surface props
authorhgn <hgodden00@gmail.com>
Sat, 29 Oct 2022 15:23:38 +0000 (16:23 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 29 Oct 2022 15:23:38 +0000 (16:23 +0100)
31 files changed:
audio.h
blender_export.py
main.c
menu.h
model.h
models_src/ch_jordan.mdl
models_src/ch_new.mdl
models_src/ch_outlaw.mdl
models_src/mp_dev.mdl
models_src/mp_test.mdl
models_src/rs_cars.mdl
models_src/rs_chicken.mdl
models_src/rs_foliage.mdl
models_src/rs_gate.mdl
models_src/rs_menu.mdl
models_src/rs_scoretext.mdl
models_src/rs_skydome.mdl
models_src/rs_vig.mdl
player.h
player_audio.h
player_physics.h
shaders/standard.fs
shaders/standard.h
textures_src/menu.png [new file with mode: 0644]
textures_src/scoretext.png
world.h
world_gen.h
world_render.h
world_routes.h
world_sfd.h
world_water.h

diff --git a/audio.h b/audio.h
index 26c1a35ca3b69152c2a0b2f99c556e63567c7247..9622c50a81eee572bb52a082339f45668d4e15b0 100644 (file)
--- a/audio.h
+++ b/audio.h
@@ -37,6 +37,24 @@ audio_clip audio_footsteps[] = {
  {.path = "sound/step_concrete3.ogg" }
 };
 
+audio_clip audio_footsteps_grass[] = {
+ {.path = "sound/step_bush0.ogg" },
+ {.path = "sound/step_bush1.ogg" },
+ {.path = "sound/step_bush2.ogg" },
+ {.path = "sound/step_bush3.ogg" },
+ {.path = "sound/step_bush4.ogg" },
+ {.path = "sound/step_bush5.ogg" }
+};
+
+audio_clip audio_footsteps_wood[] = {
+ {.path = "sound/step_wood0.ogg" },
+ {.path = "sound/step_wood1.ogg" },
+ {.path = "sound/step_wood2.ogg" },
+ {.path = "sound/step_wood3.ogg" },
+ {.path = "sound/step_wood4.ogg" },
+ {.path = "sound/step_wood5.ogg" }
+};
+
 audio_clip audio_lands[] = {
    { .path = "sound/land0.ogg" },
    { .path = "sound/land1.ogg" },
@@ -167,6 +185,10 @@ VG_STATIC void audio_init(void)
    audio_clip_loadn( audio_water, vg_list_size(audio_water), NULL );
    audio_clip_loadn( audio_grass, vg_list_size(audio_grass), NULL );
    audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps), NULL );
+   audio_clip_loadn( audio_footsteps_grass, 
+                     vg_list_size(audio_footsteps_grass), NULL );
+   audio_clip_loadn( audio_footsteps_wood, 
+                     vg_list_size(audio_footsteps_wood), NULL );
    audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind), NULL );
    audio_clip_loadn( audio_ui, vg_list_size(audio_ui), NULL );
 
@@ -281,7 +303,7 @@ enum audio_sprite_type
  * Trace out a random point, near the player to try and determine water areas
  */
 VG_STATIC enum audio_sprite_type audio_sample_sprite_random( v3f origin, 
-                                                          v3f output )
+                                                             v3f output )
 {
    v3f chance = { (vg_randf()-0.5f) * 30.0f, 
                   8.0f,
@@ -296,22 +318,29 @@ VG_STATIC enum audio_sprite_type audio_sample_sprite_random( v3f origin,
    
    if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &contact ) )
    {
-      if( ray_hit_is_ramp( &contact ) )
+      struct world_material *mat = ray_hit_material( &contact );
+
+      if( mat->info.surface_prop == k_surface_prop_grass) 
+      {
+         v3_copy( contact.pos, output );
+         return k_audio_sprite_type_grass;
+      }
+      else
       {
          vg_line( pos, contact.pos, 0xff0000ff );
          vg_line_pt3( contact.pos, 0.3f, 0xff0000ff );
          return k_audio_sprite_type_none;
       }
-
-      v3_copy( contact.pos, output );
-      return k_audio_sprite_type_grass;
    }
 
    output[0] = pos[0];
    output[1] = 0.0f;
    output[2] = pos[2];
-
-   return k_audio_sprite_type_water;
+   
+   if( world.water.enabled )
+      return k_audio_sprite_type_water;
+   else
+      return k_audio_sprite_type_none;
 }
 
 VG_STATIC void audio_debug_soundscapes(void)
index 4508bca48d8f0f53b3c759ce61bcda421f8297dd..81951235c49258de1574e7faa2ec73aebba24fef 100644 (file)
@@ -71,6 +71,7 @@ class mdl_material(Structure):
    _fields_ = [("pstr_name",c_uint32),
                ("shader",c_uint32),
                ("flags",c_uint32),
+               ("surface_prop",c_uint32),
                ("colour",c_float*4),
                ("colour1",c_float*4),
                ("tex_diffuse",c_uint32),
@@ -1080,8 +1081,13 @@ def encoder_process_material( mat ):
    flags = 0x00
    if mat.cv_data.skate_surface: flags |= 0x1
    if mat.cv_data.collision: flags |= 0x2
+   if mat.cv_data.grow_grass: flags |= 0x4
    dest.flags = flags
 
+   if mat.cv_data.surface_prop == 'concrete': dest.surface_prop = 0
+   if mat.cv_data.surface_prop == 'wood': dest.surface_prop = 1
+   if mat.cv_data.surface_prop == 'grass': dest.surface_prop = 2
+
    if mat.cv_data.shader == 'standard': dest.shader = 0
    if mat.cv_data.shader == 'standard_cutout': dest.shader = 1
    if mat.cv_data.shader == 'terrain_blend': 
@@ -1101,8 +1107,8 @@ def encoder_process_material( mat ):
    #{
       dest.shader = 3
 
-      dest.colour1[0] = mat.cv_data.uv_offset[0]
-      dest.colour1[1] = mat.cv_data.uv_offset[1]
+      dest.colour1[0] = mat.cv_data.blend_offset[0]
+      dest.colour1[1] = mat.cv_data.blend_offset[1]
    #}
 
    if mat.cv_data.shader == 'water':
@@ -2405,6 +2411,14 @@ class CV_MATERIAL_SETTINGS(bpy.types.PropertyGroup):
       ('vertex_blend', "vertex_blend", "", 3),
       ('water',"water","",4),
       ])
+
+   surface_prop: bpy.props.EnumProperty(
+      name="Surface Property",
+      items = [
+      ('concrete','concrete','',0),
+      ('wood','wood','',1),
+      ('grass','grass','',2)
+      ])
    
    collision: bpy.props.BoolProperty( \
          name="Collisions Enabled",\
@@ -2416,6 +2430,11 @@ class CV_MATERIAL_SETTINGS(bpy.types.PropertyGroup):
          default=True,\
          description = "Should the game try to target this surface?" \
    )
+   grow_grass: bpy.props.BoolProperty( \
+         name="Grow Grass", \
+         default=False,\
+         description = "Spawn grass sprites on this surface?" \
+   )
    blend_offset: bpy.props.FloatVectorProperty( \
          name="Blend Offset", \
          size=2, \
@@ -2464,10 +2483,12 @@ class CV_MATERIAL_PANEL(bpy.types.Panel):
       info = material_info( active_mat )
 
       _.layout.prop( active_mat.cv_data, "shader" )
+      _.layout.prop( active_mat.cv_data, "surface_prop" )
       _.layout.prop( active_mat.cv_data, "collision" )
 
       if active_mat.cv_data.collision:
          _.layout.prop( active_mat.cv_data, "skate_surface" )
+         _.layout.prop( active_mat.cv_data, "grow_grass" )
 
       if active_mat.cv_data.shader == "terrain_blend":
       #{
diff --git a/main.c b/main.c
index 0e5a2fc66f850c513afb3feed100633e06b647c1..22052fa40b58a2c3def75e8ccd7c683ceeb8fb39 100644 (file)
--- a/main.c
+++ b/main.c
@@ -94,7 +94,7 @@ VG_STATIC void vg_load(void)
    world_audio_init();
 
    /* 'systems' are completely loaded now */
-   strcpy( world.world_name, "models/mp_test.mdl" );
+   strcpy( world.world_name, "models/mp_dev.mdl" );
    world_load();
    vg_console_load_autos();
 }
diff --git a/menu.h b/menu.h
index 02ab25242a74c75837f862f20eb51fb6a230bf7b..21fa313e5edc9e6613c23ca64ad39c595969bd80 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -17,14 +17,16 @@ VG_STATIC float       menu_fov_target = 97.0f;
 VG_STATIC v2f         menu_extra_angles;
 
 VG_STATIC int         menu_loc = 1,
-                   menu_loc_last = 1;
+                      menu_loc_last = 1;
 VG_STATIC u32         menu_page     = 0;
 
 VG_STATIC int         cl_menu         = 0,
-                   cl_menu_go_away = 0;
+                      cl_menu_go_away = 0;
 
 VG_STATIC const char *playermodels[] = { "ch_new", "ch_jordan", "ch_outlaw" };
 
+vg_tex2d tex_menu = { .path = "textures/menu.qoi",.flags = VG_TEXTURE_NEAREST };
+
 VG_STATIC void menu_btn_paused( int event );
 VG_STATIC void menu_btn_quit( int event );
 VG_STATIC void menu_btn_skater( int event );
@@ -104,7 +106,10 @@ VG_STATIC void menu_init(void)
    mdl_close( &menu_model );
 
    vg_acquire_thread_sync();
-   mdl_unpack_glmesh( &menu_model, &menu_glmesh );
+   {
+      mdl_unpack_glmesh( &menu_model, &menu_glmesh );
+      vg_tex2d_init( (vg_tex2d *[]){ &tex_menu }, 1 );
+   }
    vg_release_thread_sync();
 
    for( int i=0; i<vg_list_size(menu_buttons); i++ )
@@ -386,7 +391,7 @@ VG_STATIC void menu_render( m4x4f projection )
    shader_menu_use();
    shader_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} );
    shader_menu_uTexMain( 1 );
-   vg_tex2d_bind( &tex_graffiti, 1 );
+   vg_tex2d_bind( &tex_menu, 1 );
 
    shader_menu_uPv( projection );
    mesh_bind( &menu_glmesh );
diff --git a/model.h b/model.h
index ea34a6ddf974f5769f1482a2672e4d0975d21581..ca7c0b1d5f73d95c1a913fd5857fa552b9eb368e 100644 (file)
--- a/model.h
+++ b/model.h
@@ -29,19 +29,19 @@ typedef struct mdl_context mdl_context;
 
 enum classtype
 {
-   k_classtype_none = 0,
-   k_classtype_gate = 1,
-   k_classtype_spawn = 3,
-   k_classtype_water = 4,
-   k_classtype_route_node = 8,
-   k_classtype_route = 9,
-   k_classtype_bone = 10,
-   k_classtype_skeleton = 11,
-   k_classtype_skin = 12,
-   k_classtype_audio = 14,
-   k_classtype_trigger = 100,
-   k_classtype_logic_achievement = 101,
-   k_classtype_logic_relay = 102
+   k_classtype_none                 = 0,
+   k_classtype_gate                 = 1,
+   k_classtype_spawn                = 3,
+   k_classtype_water                = 4,
+   k_classtype_route_node           = 8,
+   k_classtype_route                = 9,
+   k_classtype_bone                 = 10,
+   k_classtype_skeleton             = 11,
+   k_classtype_skin                 = 12,
+   k_classtype_audio                = 14,
+   k_classtype_trigger              = 100,
+   k_classtype_logic_achievement    = 101,
+   k_classtype_logic_relay          = 102
 };
 
 enum mdl_shader
@@ -53,6 +53,20 @@ enum mdl_shader
    k_shader_water                   = 4
 };
 
+enum mdl_surface_prop
+{
+   k_surface_prop_concrete          = 0,
+   k_surface_prop_wood              = 1,
+   k_surface_prop_grass             = 2
+};
+
+enum material_flag
+{
+   k_material_flag_skate_surface    = 0x1,
+   k_material_flag_collision        = 0x2,
+   k_material_flag_grow_grass       = 0x4
+};
+
 #pragma pack(push,1)
 
 struct mdl_vert
@@ -87,7 +101,8 @@ struct mdl_material
 {
    u32 pstr_name,
        shader,
-       flags;
+       flags,
+       surface_prop;
 
    v4f colour,
        colour1;
index 360bf00b36a1a7ff96928d3f4755a6c49e34690b..7130ad03ced7e5e1d94fa4a54bb69b31e0d9ae4a 100644 (file)
Binary files a/models_src/ch_jordan.mdl and b/models_src/ch_jordan.mdl differ
index 464a1277f692ba2b12a8f8b408bacdc3fdedbc70..c11c27fe27b6de02d41644d971244b9027753b48 100644 (file)
Binary files a/models_src/ch_new.mdl and b/models_src/ch_new.mdl differ
index 84d494daa6feb3796f568391014f2ffa916496f2..6ff28b6a3ce579422419db1b76e9dabe7ea8de84 100644 (file)
Binary files a/models_src/ch_outlaw.mdl and b/models_src/ch_outlaw.mdl differ
index 15d83fa535a31e233a5d8105f3ad4a0ce8e4a043..a1771a6886786b7c75a495740dd2e9e31bb211fd 100644 (file)
Binary files a/models_src/mp_dev.mdl and b/models_src/mp_dev.mdl differ
index c5a891cc77a218086e5bc5837504f581e598afda..443babc24fc06027598de46b90b5186743ed2b41 100644 (file)
Binary files a/models_src/mp_test.mdl and b/models_src/mp_test.mdl differ
index 3395b82776a81301b4639a11a6321215c0b8194e..7ea1025c3a635af31586f781003cdacd5b275b4f 100644 (file)
Binary files a/models_src/rs_cars.mdl and b/models_src/rs_cars.mdl differ
index c74de54e35b021afe32bb8dc8264ee15543ed17f..19e1b591ec9cbe038cc6313e9346109dab3463ef 100644 (file)
Binary files a/models_src/rs_chicken.mdl and b/models_src/rs_chicken.mdl differ
index 4a119d1473a362392224ec10085a02f5ca6a2d8b..5f1b81c1d8f76ce068cddd92af2d3b29748ef03d 100644 (file)
Binary files a/models_src/rs_foliage.mdl and b/models_src/rs_foliage.mdl differ
index 7a912d61ec23d534e82a7e8d19caa596426b396c..c554abe87fb8f593c51155a682f58ea680b371f8 100644 (file)
Binary files a/models_src/rs_gate.mdl and b/models_src/rs_gate.mdl differ
index 272d5375cf479aaf74650bd2bb4b3e49630aa072..9c77133f4514d7987a765930e3dfcba43030f1c2 100644 (file)
Binary files a/models_src/rs_menu.mdl and b/models_src/rs_menu.mdl differ
index c781533b4f583347945b8901cf53cb289797ad33..113b53a02d1de2eea4484d866aaa88445e762773 100644 (file)
Binary files a/models_src/rs_scoretext.mdl and b/models_src/rs_scoretext.mdl differ
index 62ceac4d275de301622d4a20645995493a20b07e..75288f23f12901b521dd80af39df11c798916193 100644 (file)
Binary files a/models_src/rs_skydome.mdl and b/models_src/rs_skydome.mdl differ
index e498f34dcd2f94dd64c8cc27e34516164bffe81d..c9ebbc23047c009467adc0041fa5af3f8cc4dd76 100644 (file)
Binary files a/models_src/rs_vig.mdl and b/models_src/rs_vig.mdl differ
index e119ffcffaac33ee553f5e3f99076324f8bf6dbf..840858371c204165e0beea0c9834a50b06a05fd9 100644 (file)
--- a/player.h
+++ b/player.h
@@ -124,6 +124,7 @@ VG_STATIC struct gplayer
 
    float walk;
    int step_phase;
+   enum mdl_surface_prop surface_prop;
 
    /* player model */
    struct player_model
index 50616048156b1e71978ca657c25a62c0a328b178..727080cea20c36bc5cf93d996d2aa94436cdeeaa 100644 (file)
@@ -127,8 +127,28 @@ VG_STATIC void player_audio(void)
          audio_player_set_flags( &audio_player_extra, AUDIO_FLAG_SPACIAL_3D );
          audio_player_set_position( &audio_player_extra, phys->rb.co );
          audio_player_set_vol( &audio_player_extra, 6.0f );
-         audio_player_playclip( &audio_player_extra, 
-                                          &audio_footsteps[rand()%4] );
+
+         if( player.surface_prop == k_surface_prop_concrete )
+         {
+            audio_player_playclip( 
+              &audio_player_extra, 
+              &audio_footsteps[rand()%vg_list_size(audio_footsteps)] 
+            );
+         }
+         else if( player.surface_prop == k_surface_prop_grass )
+         {
+            audio_player_playclip( 
+              &audio_player_extra, 
+              &audio_footsteps_grass[rand()%vg_list_size(audio_footsteps_grass)]
+            );
+         }
+         else if( player.surface_prop == k_surface_prop_wood )
+         {
+            audio_player_playclip( 
+              &audio_player_extra, 
+              &audio_footsteps_wood[rand()%vg_list_size(audio_footsteps_wood)]
+            );
+         }
       }
 
       player.step_phase = walk_phase;
index ff8d1f7a25a921848254f2a6d1725d39713a316a..438441ec1aa264bb680c9935968c89c977496daf 100644 (file)
@@ -81,7 +81,8 @@ VG_STATIC void player_start_air(void)
             u32 scolour = (u8)(vg_minf(-land_delta * 2.0f, 255.0f));
 
             /* Bias prediction towords ramps */
-            if( ray_hit_is_ramp( &contact ) )
+            if( ray_hit_material( &contact )->info.flags 
+                  & k_material_flag_skate_surface )
             {
                land_delta *= 0.1f;
                scolour |= 0x0000a000;
@@ -359,7 +360,14 @@ VG_STATIC void player_walk_physics(void)
       }
    }
 
-   phys->in_air = len==0?1:0;
+   if( len == 0 )
+      phys->in_air = 1;
+   else
+   {
+      phys->in_air = 0;
+      struct world_material *surface_mat = world_contact_material( manifold );
+      player.surface_prop = surface_mat->info.surface_prop;
+   }
 
    if( !phys->in_air )
    {
index e3f05c8d72a042046450f13af9e3413cc7e10144..d3a6842926edc966466f1dfe774c11f7aff297c9 100644 (file)
@@ -1,20 +1,40 @@
 out vec4 FragColor;
 
+uniform sampler2D uTexGarbage;
 uniform sampler2D uTexMain;
-uniform vec4 uColour;
+uniform vec3 uCamera;
+uniform vec4 uPlane;
 
 in vec4 aColour;
 in vec2 aUv;
 in vec3 aNorm;
 in vec3 aCo;
+in vec3 aWorldCo;
+
+#include "common_world.glsl"
 
 void main()
 {
-   vec3 diffuse = texture( uTexMain, aUv ).rgb;
-   float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));
-   float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));
-   diffuse += vec3(0.2,0.2,0.2) +
-             vec3(1.0,1.0,0.9)*light1 + 
-             vec3(0.1,0.3,0.4)*light2;
-   FragColor = vec4(diffuse*uColour.rgb, aColour.a*uColour.a);
+   vec3 vfrag = vec3(0.5,0.5,0.5);
+   vec4 vsamplemain = texture( uTexMain, aUv );
+   vec3 qnorm = normalize(aNorm);
+
+   vfrag = vsamplemain.rgb;
+
+   if( g_light_preview == 1 )
+   {
+      vfrag = vec3(0.5);
+   }
+
+   // Lighting
+   vec3 halfview = uCamera - aWorldCo;
+   float fdist = length( halfview );
+   halfview /= fdist;
+
+   vfrag = do_light_diffuse( vfrag, qnorm );
+   vfrag = do_light_spec( vfrag, qnorm, halfview, 0.1 );
+   vfrag = do_light_shadowing( vfrag );
+   vfrag = apply_fog( vfrag, fdist );
+
+   FragColor = vec4(vfrag, 1.0);
 }
index cf98fb0765d652ea5be57e6b44efb6bf386fe7ab..ac052b0d935f5e4042e1dff2b5be57a8162e7c71 100644 (file)
@@ -44,42 +44,172 @@ static struct vg_shader _shader_standard = {
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
+"uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexMain;\n"
-"uniform vec4 uColour;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
 "\n"
 "in vec4 aColour;\n"
 "in vec2 aUv;\n"
 "in vec3 aNorm;\n"
 "in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_light_colours[3];\n"
+"   vec4 g_light_directions[3];\n"
+"   vec4 g_ambient_colour;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"   float g_water_fog;\n"
+"   int g_light_count;\n"
+"   int g_light_preview;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"\n"
+"// Standard diffuse + spec models\n"
+"// ==============================\n"
+"\n"
+"vec3 do_light_diffuse( vec3 vfrag, vec3 wnormal )\n"
+"{\n"
+"   vec3 vtotal = g_ambient_colour.rgb;\n"
+"\n"
+"   for( int i=0; i<g_light_count; i++ )\n"
+"   {\n"
+"      vec3 vcolour = g_light_colours[i].rgb;\n"
+"      vec3 vdir = g_light_directions[i].xyz;\n"
+"\n"
+"      float flight = max(dot( vdir, wnormal )*0.75+0.25,0.0);\n"
+"      vtotal += vcolour*flight;\n"
+"   }\n"
+"\n"
+"   return vfrag * vtotal;\n"
+"}\n"
+"\n"
+"vec3 do_light_spec( vec3 vfrag, vec3 wnormal, vec3 halfview, float fintensity )\n"
+"{\n"
+"   vec3 vcolour = g_light_colours[0].rgb;\n"
+"   vec3 vdir = g_light_directions[0].xyz;\n"
+"\n"
+"   vec3 specdir = reflect( -vdir, wnormal );\n"
+"   float spec = pow(max(dot( halfview, specdir ), 0.0), 10.0);\n"
+"   return vfrag + vcolour*spec*fintensity;\n"
+"}\n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 vdir )\n"
+"{\n"
+"   vec3 sample_pos = aWorldCo + vdir;\n"
+"   float height_sample = world_depth_sample( sample_pos );\n"
+"\n"
+"   float fdelta = height_sample - sample_pos.y;\n"
+"   return clamp( fdelta, 0.1, 0.2 )-0.1;\n"
+"}\n"
+"\n"
+"vec3 do_light_shadowing_old( vec3 vfrag )\n"
+"{\n"
+"   float faccum = 0.0;\n"
+"   faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 ));\n"
+"   faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 ));\n"
+"   faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 ));\n"
+"   faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 ));\n"
+"   faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )*1.5);\n"
+"   faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )*1.5);\n"
+"   faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )*1.5);\n"
+"   faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )*1.5);\n"
+"   return mix( vfrag, g_ambient_colour.rgb, faccum );\n"
+"}\n"
+"\n"
+"vec3 do_light_shadowing( vec3 vfrag )\n"
+"{\n"
+"   float fspread = g_light_colours[0].w;\n"
+"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   float flength = g_light_directions[0].w;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt+=shadow_sample((vdir+vec3(-0.563, 0.550, 0.307)*fspread)*flength*0.1);\n"
+"   famt+=shadow_sample((vdir+vec3( 0.808, 0.686, 0.346)*fspread)*flength*0.2);\n"
+"   famt+=shadow_sample((vdir+vec3( 0.787, 0.074,-0.065)*fspread)*flength*0.3);\n"
+"   famt+=shadow_sample((vdir+vec3(-0.593, 0.071,-0.425)*fspread)*flength*0.4);\n"
+"   famt+=shadow_sample((vdir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   famt+=shadow_sample((vdir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   famt+=shadow_sample((vdir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   famt+=shadow_sample((vdir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"   return mix( vfrag, g_ambient_colour.rgb, famt );\n"
+"}\n"
+"\n"
+"vec3 apply_fog( vec3 vfrag, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0008,1.2);\n"
+"   return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"#line     15        0 \n"
 "\n"
 "void main()\n"
 "{\n"
-"   vec3 diffuse = texture( uTexMain, aUv ).rgb;\n"
-"   float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));\n"
-"   float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));\n"
-"   diffuse += vec3(0.2,0.2,0.2) +\n"
-"             vec3(1.0,1.0,0.9)*light1 + \n"
-"             vec3(0.1,0.3,0.4)*light2;\n"
-"   FragColor = vec4(diffuse*uColour.rgb, aColour.a*uColour.a);\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = normalize(aNorm);\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - aWorldCo;\n"
+"   float fdist = length( halfview );\n"
+"   halfview /= fdist;\n"
+"\n"
+"   vfrag = do_light_diffuse( vfrag, qnorm );\n"
+"   vfrag = do_light_spec( vfrag, qnorm, halfview, 0.1 );\n"
+"   vfrag = do_light_shadowing( vfrag );\n"
+"   vfrag = apply_fog( vfrag, fdist );\n"
+"\n"
+"   FragColor = vec4(vfrag, 1.0);\n"
 "}\n"
 ""},
 };
 
 static GLuint _uniform_standard_uMdl;
 static GLuint _uniform_standard_uPv;
+static GLuint _uniform_standard_uTexGarbage;
 static GLuint _uniform_standard_uTexMain;
-static GLuint _uniform_standard_uColour;
+static GLuint _uniform_standard_uCamera;
+static GLuint _uniform_standard_uPlane;
+static GLuint _uniform_standard_g_world_depth;
 static void shader_standard_uMdl(m4x3f m){
    glUniformMatrix4x3fv( _uniform_standard_uMdl, 1, GL_FALSE, (float *)m );
 }
 static void shader_standard_uPv(m4x4f m){
    glUniformMatrix4fv( _uniform_standard_uPv, 1, GL_FALSE, (float *)m );
 }
+static void shader_standard_uTexGarbage(int i){
+   glUniform1i( _uniform_standard_uTexGarbage, i );
+}
 static void shader_standard_uTexMain(int i){
    glUniform1i( _uniform_standard_uTexMain, i );
 }
-static void shader_standard_uColour(v4f v){
-   glUniform4fv( _uniform_standard_uColour, 1, v );
+static void shader_standard_uCamera(v3f v){
+   glUniform3fv( _uniform_standard_uCamera, 1, v );
+}
+static void shader_standard_uPlane(v4f v){
+   glUniform4fv( _uniform_standard_uPlane, 1, v );
+}
+static void shader_standard_g_world_depth(int i){
+   glUniform1i( _uniform_standard_g_world_depth, i );
 }
 static void shader_standard_register(void){
    vg_shader_register( &_shader_standard );
@@ -88,7 +218,10 @@ static void shader_standard_use(void){ glUseProgram(_shader_standard.id); }
 static void shader_standard_link(void){
    _uniform_standard_uMdl = glGetUniformLocation( _shader_standard.id, "uMdl" );
    _uniform_standard_uPv = glGetUniformLocation( _shader_standard.id, "uPv" );
+   _uniform_standard_uTexGarbage = glGetUniformLocation( _shader_standard.id, "uTexGarbage" );
    _uniform_standard_uTexMain = glGetUniformLocation( _shader_standard.id, "uTexMain" );
-   _uniform_standard_uColour = glGetUniformLocation( _shader_standard.id, "uColour" );
+   _uniform_standard_uCamera = glGetUniformLocation( _shader_standard.id, "uCamera" );
+   _uniform_standard_uPlane = glGetUniformLocation( _shader_standard.id, "uPlane" );
+   _uniform_standard_g_world_depth = glGetUniformLocation( _shader_standard.id, "g_world_depth" );
 }
 #endif /* SHADER_standard_H */
diff --git a/textures_src/menu.png b/textures_src/menu.png
new file mode 100644 (file)
index 0000000..c2b57ce
Binary files /dev/null and b/textures_src/menu.png differ
index e45097ba49afcbb3b1b6a943ddc58c26f7667b58..7ca63c138f52e0ad1e60f0550b55adaa43c3c906 100644 (file)
Binary files a/textures_src/scoretext.png and b/textures_src/scoretext.png differ
diff --git a/world.h b/world.h
index e5c039a495113f8ae528ed8b7e4890d1e3ad7064..5f297d0c68e8d6a5bd0908bcc85e05f201875145 100644 (file)
--- a/world.h
+++ b/world.h
@@ -53,12 +53,6 @@ enum geo_type
    k_geo_type_water = 2
 };
 
-enum material_flag
-{
-   k_material_flag_skate_surface = 0x1,
-   k_material_flag_collision = 0x2
-};
-
 VG_STATIC struct gworld
 {
    /*
@@ -335,7 +329,7 @@ world;
  */
 
 VG_STATIC int ray_hit_is_ramp( ray_hit *hit );
-VG_STATIC int ray_hit_is_terrain( ray_hit *hit );
+VG_STATIC struct world_material *ray_hit_material( ray_hit *hit );
 VG_STATIC void ray_world_get_tri( ray_hit *hit, v3f tri[3] );
 VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit );
 
@@ -456,7 +450,7 @@ VG_STATIC void world_init(void)
    vg_loader_highwater( world_routes_init, NULL, NULL );
 
    /* Allocate dynamic world memory arena */
-   u32 max_size = 72*1024*1024;
+   u32 max_size = 76*1024*1024;
    world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size,
                                                    VG_MEMORY_SYSTEM );
 }
@@ -649,28 +643,31 @@ VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit )
    return scene_raycast( world.scene_geo, world.geo_bh, pos, dir, hit );
 }
 
-VG_STATIC int ray_hit_is_terrain( ray_hit *hit )
+VG_STATIC struct world_material *world_tri_index_material( u32 index )
 {
-   return 0;
-#if 0
-   u32 valid_start = 0,
-       valid_end   = world.sm_terrain.vertex_count;
+   for( int i=1; i<world.material_count; i++ )
+   {
+      struct world_material *mat = &world.materials[i];
 
-   return (hit->tri[0] >= valid_start) &&
-          (hit->tri[0]  < valid_end);
-#endif
+      if( (index >= mat->sm_geo.vertex_start) &&
+          (index  < mat->sm_geo.vertex_start+mat->sm_geo.vertex_count ) )
+      {
+         return mat;
+      }
+   }
+
+   /* error material */
+   return &world.materials[0];
 }
 
-VG_STATIC int ray_hit_is_ramp( ray_hit *hit )
+VG_STATIC struct world_material *world_contact_material( rb_ct *ct )
 {
-   return 1;
-#if 0
-   u32 valid_start = world.sm_geo_std.vertex_start,
-       valid_end   = world.sm_geo_vb.vertex_start;
+   return world_tri_index_material( ct->element_id );
+}
 
-   return (hit->tri[0] >= valid_start) &&
-          (hit->tri[0]  < valid_end);
-#endif
+VG_STATIC struct world_material *ray_hit_material( ray_hit *hit )
+{
+   return world_tri_index_material( hit->tri[0] );
 }
 
 #endif /* WORLD_H */
index c87112afd6ed15887c648239bd590d00b2f38a9d..9ee1e6beb3329d7403f4602a8f3fe5d33d87271e 100644 (file)
@@ -34,7 +34,7 @@ VG_STATIC void world_add_all_if_material( m4x3f transform, scene *pscene,
 }
 
 /* Sprinkle foliage models over the map on terrain material */
-VG_STATIC void world_apply_procedural_foliage(void)
+VG_STATIC void world_apply_procedural_foliage( struct world_material *mat )
 {
    vg_linear_clear( vg_mem.scratch );
 
@@ -61,8 +61,8 @@ VG_STATIC void world_apply_procedural_foliage(void)
 
       if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit ))
       {
-         if( (hit.normal[1] > 0.8f) && ray_hit_is_terrain(&hit) &&
-             (hit.pos[1] > 0.0f+10.0f) )
+         struct world_material *m1 = ray_hit_material( &hit );
+         if((hit.normal[1] > 0.8f) && (m1 == mat) && (hit.pos[1] > 0.0f+10.0f))
          {
             v4f qsurface, qrandom;
             v3f axis;
@@ -173,22 +173,8 @@ VG_STATIC void world_pct_water( mdl_node *pnode )
       return;
    }
 
-   mdl_submesh *sm = mdl_node_submesh( world.meta, pnode, 0 );
-   
-   if( sm )
-   {
-      vg_acquire_thread_sync();
-      {
-         mdl_unpack_submesh( world.meta, &world.mesh_water, sm );
-         world.water.enabled = 1;
-         water_set_surface( pnode->co[1] );
-      }
-      vg_release_thread_sync();
-   }
-   else
-   {
-      vg_warn( "Water entity has no submeshes!\n" );
-   }
+   world.water.enabled = 1;
+   water_set_surface( pnode->co[1] );
 }
 
 VG_STATIC void world_pct_audio( mdl_node *pnode )
@@ -322,7 +308,7 @@ VG_STATIC void world_generate(void)
    /* 
     * Compile meshes into the world scenes
     */
-   world.scene_geo = scene_init( world.dynamic_vgl, 350000, 1200000 );
+   world.scene_geo = scene_init( world.dynamic_vgl, 320000, 1200000 );
 
    m4x3f midentity;
    m4x3_identity( midentity );
@@ -340,13 +326,10 @@ VG_STATIC void world_generate(void)
       struct world_material *mat = &world.materials[ i ];
 
       if( mat->info.flags & k_material_flag_collision )
-      {
          world_add_all_if_material( midentity, world.scene_geo, world.meta, i );
-         scene_copy_slice( world.scene_geo, &mat->sm_geo );
-      }
-   }
-
 
+      scene_copy_slice( world.scene_geo, &mat->sm_geo );
+   }
 
 
 
@@ -386,7 +369,21 @@ VG_STATIC void world_generate(void)
    scene_copy_slice( world.scene_no_collide, &world.sm_foliage_main );
 #endif
 
+   for( int i=0; i<world.material_count; i++ )
+   {
+      struct world_material *mat = &world.materials[ i ];
+
+      if( !(mat->info.flags & k_material_flag_collision) )
+      {
+         world_add_all_if_material( midentity, world.scene_no_collide, 
+                                    world.meta, i );
+      }
 
+      if( mat->info.flags & k_material_flag_grow_grass )
+         world_apply_procedural_foliage( mat );
+
+      scene_copy_slice( world.scene_no_collide, &mat->sm_no_collide );
+   }
 
    /* upload and free that */
    vg_acquire_thread_sync();
@@ -561,7 +558,6 @@ VG_STATIC void world_unload(void)
    mesh_free( &world.mesh_route_lines );
    mesh_free( &world.mesh_geo );
    mesh_free( &world.mesh_no_collide );
-   mesh_free( &world.mesh_water );
 
    world.time = 0.0;
    world.rewind_from = 0.0;
index 25d72ee5e9df1e99a95932be02259f5a945534cd..8398a60cd526b5dfb2369bf894e694cdf42d0cf5 100644 (file)
@@ -7,28 +7,16 @@
 
 #include "world.h"
 
-vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi",
-                                 .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
-
 vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi",
                                  .flags = VG_TEXTURE_NEAREST };
 
-vg_tex2d tex_alphatest = { .path = "textures/alphatest.qoi",
-                                 .flags = VG_TEXTURE_NEAREST };
-
-vg_tex2d tex_graffiti = { .path = "textures/graffitibox.qoi",
-                                 .flags = VG_TEXTURE_NEAREST };
-
 VG_STATIC void world_render_init(void)
 {
    vg_info( "Loading default world textures\n" );
 
    vg_acquire_thread_sync();
    {
-      vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours, 
-                                     &tex_terrain_noise,
-                                     &tex_alphatest,
-                                     &tex_graffiti }, 4 );
+      vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_noise }, 1 );
    }
    vg_release_thread_sync();
 }
@@ -39,10 +27,9 @@ VG_STATIC void render_world_depth( m4x4f projection, m4x3f camera );
  * Rendering
  */
 
-VG_STATIC void bind_terrain_textures(void)
+VG_STATIC void bind_terrain_noise(void)
 {
    vg_tex2d_bind( &tex_terrain_noise, 0 );
-   vg_tex2d_bind( &tex_terrain_colours, 1 );
 }
 
 VG_STATIC void world_render_if( enum mdl_shader shader, 
@@ -106,6 +93,24 @@ VG_STATIC void render_world_vb( m4x4f projection, v3f camera )
                              bindpoint_diffuse_texture1 );
 }
 
+VG_STATIC void render_world_standard( m4x4f projection, v3f camera )
+{
+   m4x3f identity_matrix;
+   m4x3_identity( identity_matrix );
+
+   shader_standard_use();
+   shader_standard_uTexGarbage(0);
+   shader_standard_uTexMain(1);
+   shader_link_standard_ub( _shader_standard.id, 2 );
+   bind_terrain_noise();
+
+   shader_standard_uPv( projection );
+   shader_standard_uMdl( identity_matrix );
+   shader_standard_uCamera( camera );
+   
+   world_render_both_stages( k_shader_standard,
+                             bindpoint_diffuse_texture1 );
+}
 
 VG_STATIC void render_world_alphatest( m4x4f projection, v3f camera )
 {
@@ -116,8 +121,7 @@ VG_STATIC void render_world_alphatest( m4x4f projection, v3f camera )
    shader_alphatest_uTexGarbage(0);
    shader_alphatest_uTexMain(1);
    shader_link_standard_ub( _shader_alphatest.id, 2 );
-
-   vg_tex2d_bind( &tex_terrain_noise, 0 );
+   bind_terrain_noise();
 
    shader_alphatest_uPv( projection );
    shader_alphatest_uMdl( identity_matrix );
index 97fc557b604201517f4240a43a15f4c20cf4715b..5a7c07b36df0b154c921a3970fd050eaafb19d63 100644 (file)
@@ -1119,7 +1119,7 @@ VG_STATIC void world_routes_update(void)
    }
 }
 
-VG_STATIC void bind_terrain_textures(void);
+VG_STATIC void bind_terrain_noise(void);
 VG_STATIC void render_world_routes( m4x4f projection, v3f camera )
 {
    m4x3f identity_matrix;
@@ -1128,7 +1128,7 @@ VG_STATIC void render_world_routes( m4x4f projection, v3f camera )
    shader_route_use();
    shader_route_uTexGarbage(0);
    shader_link_standard_ub( _shader_route.id, 2 );
-   bind_terrain_textures();
+   bind_terrain_noise();
 
    shader_route_uPv( projection );
    shader_route_uMdl( identity_matrix );
index a83fe0a92359c4b8cb9cb885fb30b9dc360474d2..5b5bd9973e5bb907860fb77e9518b8d5b9d406ff 100644 (file)
@@ -99,6 +99,7 @@ VG_STATIC void sfd_update(void)
    }
 }
 
+VG_STATIC void bind_terrain_noise(void);
 VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform )
 {
    mesh_bind( &world.sfd.mesh_display );
@@ -107,7 +108,7 @@ VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform )
    shader_scoretext_uTexGarbage(0);
    shader_scoretext_uTexGradients(1);
    shader_link_standard_ub( _shader_scoretext.id, 2 );
-   bind_terrain_textures();
+   bind_terrain_noise();
    vg_tex2d_bind( &tex_scoretext, 1 );
 
    shader_scoretext_uPv( projection );
@@ -128,7 +129,8 @@ VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform )
    shader_vblend_uTexGarbage(0);
    shader_vblend_uTexGradients(1);
    shader_link_standard_ub( _shader_vblend.id, 2 );
-   bind_terrain_textures();
+   bind_terrain_noise();
+   vg_tex2d_bind( &tex_scoretext, 1 );
 
    shader_vblend_uPv( projection );
    shader_vblend_uMdl( transform );
index 928d36c95175c6d73cbad7bfee03f0b61a67fd93..e31994ab57a111ac30f221957eb865c6fb8b050b 100644 (file)
@@ -157,7 +157,7 @@ VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera )
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glBlendEquation(GL_FUNC_ADD);
 
-   mesh_bind( &world.mesh_water );
+   mesh_bind( &world.mesh_no_collide );
 
    for( int i=0; i<world.material_count; i++ )
    {