sfd
authorhgn <hgodden00@gmail.com>
Mon, 27 Mar 2023 10:54:07 +0000 (11:54 +0100)
committerhgn <hgodden00@gmail.com>
Mon, 27 Mar 2023 10:54:07 +0000 (11:54 +0100)
12 files changed:
blender_export.py
build.c
maps_src/mp_gridmap.mdl
models_src/rs_scoretext.mdl [new file with mode: 0644]
scene.h
shaders/scene_scoretext.h [new file with mode: 0644]
shaders/scene_sfd.vs [new file with mode: 0644]
world.h
world_gen.h
world_render.h
world_routes.h
world_sfd.h

index dee0d8f1ee0102774ce2f48da898b035f46f9bc6..721bba6962b4fd5bc3ecc27d0a984761acde58c1 100644 (file)
@@ -2371,15 +2371,16 @@ def node_graph( route_nodes ):
 
 def cv_draw_route( route, route_nodes ):
 #{
-   pole = Vector((0.2,0.2,20))
-   hat = Vector((20,2.0,0.2))
+   pole = Vector((0.2,0.2,10))
+   hat = Vector((1,8,0.2))
    cc = route.SR_data.ent_route[0].colour
 
-   cv_draw_ucube( route.matrix_world, cc, Vector((20,1,10)) )
-   cv_draw_ucube( route.matrix_world, cc, pole, Vector((-20,1,-10)) )
-   cv_draw_ucube( route.matrix_world, cc, pole, Vector(( 20,1,-10)) )
-   cv_draw_ucube( route.matrix_world, cc, hat, Vector((0,-1, 10)) )
-   cv_draw_ucube( route.matrix_world, cc, hat, Vector((0,-1,-10)) )
+   cv_draw_ucube(route.matrix_world,cc,Vector((0.5,-7.5,6)),\
+                                       Vector((0,-6.5,5.5)))
+   cv_draw_ucube(route.matrix_world,cc,pole, Vector(( 0.5, 0.5,0)) )
+   cv_draw_ucube(route.matrix_world,cc,pole, Vector(( 0.5,-13.5,0)) )
+   cv_draw_ucube(route.matrix_world,cc,hat, Vector((-0.5,-6.5, 12)) )
+   cv_draw_ucube(route.matrix_world,cc,hat, Vector((-0.5,-6.5,-1)) )
 
    checkpoints = route.SR_data.ent_route[0].gates
    graph = node_graph( route_nodes )
diff --git a/build.c b/build.c
index 5e1652e33152e3088c7aa33ff52cdc05e2b0f90d..1201177d9ea357b5d1349250a3c0df00861f302f 100644 (file)
--- a/build.c
+++ b/build.c
@@ -126,6 +126,7 @@ void build_shaders(void)
    _S( "scene_position",            "scene.vs", "scene_position.fs" );
    _S( "scene_water",               "scene.vs", "scene_water.fs" );
    _S( "scene_water_fast",          "scene.vs", "scene_water_fast.fs" );
+   _S( "scene_scoretext",           "scene_sfd.vs", "scene_standard.fs" );
 
    /* Models */
    _S( "model_sky",            "model.vs",         "model_sky.fs" );
index 46386d29f2a94f3c4fd00ac2fc5f31450272ea6a..f7d2e41ff829a4ee59d6cfb9fd24f1b0ca4a72dc 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
diff --git a/models_src/rs_scoretext.mdl b/models_src/rs_scoretext.mdl
new file mode 100644 (file)
index 0000000..a85faa6
Binary files /dev/null and b/models_src/rs_scoretext.mdl differ
diff --git a/scene.h b/scene.h
index cd1a8ea10689b5eb0c9303209b43dfa0b2c35ff3..81d00c3f5c94c06f15ea1be92e80fbb69038a42f 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -247,7 +247,7 @@ VG_STATIC void scene_upload( scene *pscene, glmesh *mesh )
    glEnableVertexAttribArray( 0 );
 
    /* 1: normal */
-   glVertexAttribPointer( 1, 3, GL_BYTE, GL_TRUE,
+   glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE,
          stride, (void *)offsetof(scene_vert, norm) );
    glEnableVertexAttribArray( 1 );
 
diff --git a/shaders/scene_scoretext.h b/shaders/scene_scoretext.h
new file mode 100644 (file)
index 0000000..dcefedb
--- /dev/null
@@ -0,0 +1,535 @@
+#ifndef SHADER_scene_scoretext_H
+#define SHADER_scene_scoretext_H
+static void shader_scene_scoretext_link(void);
+static void shader_scene_scoretext_register(void);
+static struct vg_shader _shader_scene_scoretext = {
+   .name = "scene_scoretext",
+   .link = shader_scene_scoretext_link,
+   .vs = 
+{
+.orig_file = "shaders/scene_sfd.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\n"
+"\n"
+"#line       1        1 \n"
+"const float k_motion_lerp_amount = 0.01;\n"
+"\n"
+"#line      2        0 \n"
+"\n"
+"out vec3 aMotionVec0;\n"
+"out vec3 aMotionVec1;\n"
+"\n"
+"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n"
+"{\n"
+"   // This magically solves some artifacting errors!\n"
+"   //\n"
+"   vproj1 = vproj0*(1.0-k_motion_lerp_amount) + vproj1*k_motion_lerp_amount;\n"
+"\n"
+"   aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n"
+"   aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n"
+"}\n"
+"\n"
+"#line      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform vec3   uInfo;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   float w = ((a_norm.w)-0.5)*2.0 + fract(uInfo.z) - 0.0;\n"
+"   float c = -cos(w*0.2);\n"
+"   float s = -sin(w*0.2);\n"
+"   float r = 0.2;\n"
+"\n"
+"   float w1 = clamp( w*4.0 - a_co.y*10.0, -1.0, 1.0 ) * (3.14159265*0.5);\n"
+"   float c1 = cos(w1);\n"
+"   float s1 = sin(w1);\n"
+"\n"
+"   float yoff = step(0.01,fract(uInfo.z))*-0.5;\n"
+"\n"
+"   mat4x3 mlocal;\n"
+"   mlocal[0] = vec3(c1, s1,0.0);\n"
+"   mlocal[1] = vec3(-s1,c1,0.0);\n"
+"   mlocal[2] = vec3(0.0,0.0,1.0);\n"
+"   mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5);\n"
+"\n"
+"   vec3 local_pos0 = mlocal * vec4( a_co, 1.0 );\n"
+"   vec3 world_pos0 = uMdl * vec4( local_pos0, 1.0 );\n"
+"\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( local_pos0, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * mat3(mlocal) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_standard.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"uniform vec3 uBoard0;\n"
+"uniform vec3 uBoard1;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max(0.0,dot(normal,g_sun_dir.xyz)*0.75+0.25) \n"
+"                           * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     42        0 \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 world_water_depth( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return texture( g_world_depth, depth_coord ).g - ref_depth;\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.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
+"{\n"
+"   if( g_shadow_samples == 0 )\n"
+"   {\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample((dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample((dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample((dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample((dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample((dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample((dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample((dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample((dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( g_sun_dir.xyz \n"
+"                                    * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, uBoard0, uBoard1 )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"#line       1        2 \n"
+"const float k_motion_lerp_amount = 0.01;\n"
+"\n"
+"#line      2        0 \n"
+"\n"
+"layout (location = 1) out vec2 oMotionVec;\n"
+"\n"
+"in vec3 aMotionVec0;\n"
+"in vec3 aMotionVec1;\n"
+"\n"
+"void compute_motion_vectors()\n"
+"{\n"
+"   // Write motion vectors\n"
+"   vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n"
+"   vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n"
+"\n"
+"   oMotionVec = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount);\n"
+"}\n"
+"\n"
+"#line     10        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"}\n"
+""},
+};
+
+static GLuint _uniform_scene_scoretext_uMdl;
+static GLuint _uniform_scene_scoretext_uPv;
+static GLuint _uniform_scene_scoretext_uPvmPrev;
+static GLuint _uniform_scene_scoretext_uInfo;
+static GLuint _uniform_scene_scoretext_uTexGarbage;
+static GLuint _uniform_scene_scoretext_uTexMain;
+static GLuint _uniform_scene_scoretext_uCamera;
+static GLuint _uniform_scene_scoretext_uPlane;
+static GLuint _uniform_scene_scoretext_uBoard0;
+static GLuint _uniform_scene_scoretext_uBoard1;
+static GLuint _uniform_scene_scoretext_g_world_depth;
+static GLuint _uniform_scene_scoretext_uLightsArray;
+static GLuint _uniform_scene_scoretext_uLightsIndex;
+static void shader_scene_scoretext_uMdl(m4x3f m){
+   glUniformMatrix4x3fv(_uniform_scene_scoretext_uMdl,1,GL_FALSE,(float*)m);
+}
+static void shader_scene_scoretext_uPv(m4x4f m){
+   glUniformMatrix4fv(_uniform_scene_scoretext_uPv,1,GL_FALSE,(float*)m);
+}
+static void shader_scene_scoretext_uPvmPrev(m4x4f m){
+   glUniformMatrix4fv(_uniform_scene_scoretext_uPvmPrev,1,GL_FALSE,(float*)m);
+}
+static void shader_scene_scoretext_uInfo(v3f v){
+   glUniform3fv(_uniform_scene_scoretext_uInfo,1,v);
+}
+static void shader_scene_scoretext_uTexGarbage(int i){
+   glUniform1i(_uniform_scene_scoretext_uTexGarbage,i);
+}
+static void shader_scene_scoretext_uTexMain(int i){
+   glUniform1i(_uniform_scene_scoretext_uTexMain,i);
+}
+static void shader_scene_scoretext_uCamera(v3f v){
+   glUniform3fv(_uniform_scene_scoretext_uCamera,1,v);
+}
+static void shader_scene_scoretext_uPlane(v4f v){
+   glUniform4fv(_uniform_scene_scoretext_uPlane,1,v);
+}
+static void shader_scene_scoretext_uBoard0(v3f v){
+   glUniform3fv(_uniform_scene_scoretext_uBoard0,1,v);
+}
+static void shader_scene_scoretext_uBoard1(v3f v){
+   glUniform3fv(_uniform_scene_scoretext_uBoard1,1,v);
+}
+static void shader_scene_scoretext_g_world_depth(int i){
+   glUniform1i(_uniform_scene_scoretext_g_world_depth,i);
+}
+static void shader_scene_scoretext_register(void){
+   vg_shader_register( &_shader_scene_scoretext );
+}
+static void shader_scene_scoretext_use(void){ glUseProgram(_shader_scene_scoretext.id); }
+static void shader_scene_scoretext_link(void){
+   _uniform_scene_scoretext_uMdl = glGetUniformLocation( _shader_scene_scoretext.id, "uMdl" );
+   _uniform_scene_scoretext_uPv = glGetUniformLocation( _shader_scene_scoretext.id, "uPv" );
+   _uniform_scene_scoretext_uPvmPrev = glGetUniformLocation( _shader_scene_scoretext.id, "uPvmPrev" );
+   _uniform_scene_scoretext_uInfo = glGetUniformLocation( _shader_scene_scoretext.id, "uInfo" );
+   _uniform_scene_scoretext_uTexGarbage = glGetUniformLocation( _shader_scene_scoretext.id, "uTexGarbage" );
+   _uniform_scene_scoretext_uTexMain = glGetUniformLocation( _shader_scene_scoretext.id, "uTexMain" );
+   _uniform_scene_scoretext_uCamera = glGetUniformLocation( _shader_scene_scoretext.id, "uCamera" );
+   _uniform_scene_scoretext_uPlane = glGetUniformLocation( _shader_scene_scoretext.id, "uPlane" );
+   _uniform_scene_scoretext_uBoard0 = glGetUniformLocation( _shader_scene_scoretext.id, "uBoard0" );
+   _uniform_scene_scoretext_uBoard1 = glGetUniformLocation( _shader_scene_scoretext.id, "uBoard1" );
+   _uniform_scene_scoretext_g_world_depth = glGetUniformLocation( _shader_scene_scoretext.id, "g_world_depth" );
+   _uniform_scene_scoretext_uLightsArray = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsArray" );
+   _uniform_scene_scoretext_uLightsIndex = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsIndex" );
+}
+#endif /* SHADER_scene_scoretext_H */
diff --git a/shaders/scene_sfd.vs b/shaders/scene_sfd.vs
new file mode 100644 (file)
index 0000000..d81ac99
--- /dev/null
@@ -0,0 +1,50 @@
+layout (location=0) in vec3  a_co;
+layout (location=1) in vec4  a_norm;
+layout (location=2) in vec2  a_uv;
+
+#include "motion_vectors_vs.glsl"
+
+uniform mat4x3 uMdl;
+uniform mat4   uPv;
+uniform mat4   uPvmPrev;
+uniform vec3   uInfo;
+
+out vec2 aUv;
+out vec4 aNorm;
+out vec3 aCo;
+out vec3 aWorldCo;
+
+void main()
+{
+   float w = ((a_norm.w)-0.5)*2.0 + fract(uInfo.z) - 0.0;
+   float c = -cos(w*0.2);
+   float s = -sin(w*0.2);
+   float r = 0.2;
+
+   float w1 = clamp( w*4.0 - a_co.y*10.0, -1.0, 1.0 ) * (3.14159265*0.5);
+   float c1 = cos(w1);
+   float s1 = sin(w1);
+
+   float yoff = step(0.01,fract(uInfo.z))*-0.5;
+
+   mat4x3 mlocal;
+   mlocal[0] = vec3(c1, s1,0.0);
+   mlocal[1] = vec3(-s1,c1,0.0);
+   mlocal[2] = vec3(0.0,0.0,1.0);
+   mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5);
+
+   vec3 local_pos0 = mlocal * vec4( a_co, 1.0 );
+   vec3 world_pos0 = uMdl * vec4( local_pos0, 1.0 );
+
+   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );
+   vec4 vproj1     = uPvmPrev * vec4( local_pos0, 1.0 );
+
+   vs_motion_out( vproj0, vproj1 );
+
+   gl_Position = vproj0;
+
+   aUv = a_uv + vec2( floor(uInfo.z+0.5)*(1.0/64.0), yoff );
+   aNorm = vec4( mat3(uMdl) * mat3(mlocal) * a_norm.xyz, a_norm.w );
+   aCo = a_co;
+   aWorldCo = world_pos0;
+}
diff --git a/world.h b/world.h
index 37ff044910b0c238750ec11e484c870f8f1ebf02..f00e146b0f53fe0f0c7a199f5aeb93f45335d268 100644 (file)
--- a/world.h
+++ b/world.h
@@ -28,8 +28,6 @@ typedef struct world_instance world_instance;
 
 #include "shaders/model_sky.h"
 
-typedef struct teleport_gate teleport_gate;
-
 enum { k_max_ui_segments = 8 };
 
 enum { k_max_ui_elements = k_max_ui_segments };
@@ -353,8 +351,9 @@ VG_STATIC struct world_global
    /* split flap display */
    struct
    {
-      mdl_submesh *sm_module, *sm_card;
       glmesh mesh_base, mesh_display;
+      mdl_submesh sm_base;
+      u32 active_route_board;
 
       u32 w, h;
       float *buffer;
@@ -362,7 +361,6 @@ VG_STATIC struct world_global
    sfd;
 
    v3f render_gate_pos;
-   int active_route_board;
    int in_volume;
 
    int switching_to_new_world;
@@ -452,9 +450,7 @@ VG_STATIC void world_init(void)
    vg_info( "Loading other world systems\n" );
 
    vg_loader_step( world_render_init, NULL );
-#if 0
    vg_loader_step( world_sfd_init, NULL );
-#endif
    vg_loader_step( world_water_init, NULL );
    vg_loader_step( world_gates_init, NULL );
    vg_loader_step( world_routes_init, NULL );
@@ -508,46 +504,46 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
 
    world_routes_update( world );
    world_routes_debug( world );
+
+   /* ---- SFD ------------ */
    
-#if 0
-   if( world->route_count > 0 ){
-      int closest = 0;
+   if( mdl_arrcount( &world->ent_route ) ){
+      u32 closest = 0;
       float min_dist = INFINITY;
 
-      for( int i=0; i<world->route_count; i++ )
-      {
-         float d = v3_dist2( world->routes[i].scoreboard_transform[3], pos );
+      for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
+         ent_route *route = mdl_arritm( &world->ent_route, i );
+         float dist = v3_dist2( route->board_transform[3], pos );
 
-         if( d < min_dist )
-         {
-            min_dist = d;
+         if( dist < min_dist ){
+            min_dist = dist;
             closest = i;
          }
       }
 
-      if( (world_global.active_route_board != closest) 
+      if( (world_global.sfd.active_route_board != closest) 
           || network_scores_updated )
       {
          network_scores_updated = 0;
-         world_global.active_route_board = closest;
-
-         struct route *route = &world->routes[closest];
+         world_global.sfd.active_route_board = closest;
 
-         u32 id = route->track_id;
+         ent_route *route = mdl_arritm( &world->ent_route, closest );
+         u32 id = route->official_track_id;
 
-         if( id != 0xffffffff )
-         {
+         if( id != 0xffffffff ){
             struct netmsg_board *local_board = 
                &scoreboard_client_data.boards[id];
 
-            for( int i=0; i<13; i++ )
-            {
+            for( int i=0; i<13; i++ ){
                sfd_encode( i, &local_board->data[27*i] );
             }
+         }else{
+            sfd_encode( 0, mdl_pstr( &world->meta, route->pstr_name ) );
+            sfd_encode( 1, "No data" );
          }
       }
    }
-#endif
+   sfd_update();
    
 #if 0
    /* TODO: Bvh */
@@ -661,7 +657,6 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
 #endif
 
 #if 0
-   sfd_update();
 
    /* process soundscape transactions */
    audio_lock();
index 38d2b6677ed366e43368d0c63e41927908335226..f63026e7b44304943e1b4d1dce39a1610de9b93e 100644 (file)
@@ -881,11 +881,12 @@ VG_STATIC void world_unload( world_instance *world )
    glDeleteTextures( 1, &world->tex_light_cubes );
 
    /* FIXME: CANT DO THIS HERE */
+   /*        whynot? */
    world_global.time = 0.0;
    world_global.rewind_from = 0.0;
    world_global.rewind_to = 0.0;
    world_global.last_use = 0.0;
-   world_global.active_route_board = 0;
+   world_global.sfd.active_route_board = 0;
 
    /* delete textures and meshes */
    glDeleteTextures( world->texture_count, world->textures );
index 31eba64401237a5cb48b9a7a79bb9fa4a3020afa..517c19fa067c7243a00660a36f9e2ac6b47f6c34 100644 (file)
@@ -389,26 +389,24 @@ VG_STATIC void render_world( world_instance *world, camera *cam )
    render_terrain( world, cam );
 
    /* Render SFD's */
-#if 0
-   int closest = 0;
+   u32 closest = 0;
    float min_dist = INFINITY;
 
-   if( !world->route_count )
+   if( !mdl_arrcount( &world->ent_route ) )
       return;
 
-   for( int i=0; i<world->route_count; i++ )
-   {
-      float dist = v3_dist2(world->routes[i].scoreboard_transform[3], cam->pos);
+   for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
+      ent_route *route = mdl_arritm( &world->ent_route, i );
+      float dist = v3_dist2( route->board_transform[3], cam->pos );
 
-      if( dist < min_dist )
-      {
+      if( dist < min_dist ){
          min_dist = dist;
          closest = i;
       }
    }
 
-   sfd_render( cam, world->routes[closest].scoreboard_transform );
-#endif
+   ent_route *route = mdl_arritm( &world->ent_route, closest );
+   sfd_render( world, cam, route->board_transform );
 }
 
 VG_STATIC void render_world_depth( world_instance *world, camera *cam )
index 2454a593c0574aae14c79ffdd68489182a23a5a8..05ef3c9586a8094634ed20e448ca6236d4b5b72a 100644 (file)
@@ -611,6 +611,8 @@ VG_STATIC void render_world_routes( world_instance *world, camera *cam )
    mesh_bind( &world_global.mesh_gate );
 
    /* skip writing into the motion vectors for this */
+   /* TODO: draw future gate if the one we're looking through is to be passed,
+    *       instead of current gate */
    glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
 
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
index 88a86396e5fd700fdaef3fc0108dcf3301c94cb3..69501e288723cfd81a5aa5996b1788f838ce8e23 100644 (file)
@@ -1,25 +1,17 @@
 /*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
 #ifndef SFD_H
 #define SFD_H
 
 #include "world.h"
-
-#if 0
-#if 0
-#include "shaders/scoretext.h"
-#include "shaders/vblend.h"
-#endif
+#include "shaders/scene_scoretext.h"
+#include "shaders/scene_vertex_blend.h"
 
 vg_tex2d tex_scoretext = { .path = "textures/scoretext.qoi",
                            .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST };
 
-/* 
- * TODO: utf-8 -> ascii
- */
-
 float sfd_encode_glyph( char c )
 {
    int value = 0;
@@ -31,12 +23,10 @@ float sfd_encode_glyph( char c )
       value = c-'A'+11;
    else if( c >= '\x01' && c <= '\x01'+10 )
       value = 63-c;
-   else
-   {
+   else{
       int base = 11+26;
 
-      switch( c )
-      {
+      switch( c ){
          case '!': value=base+0; break;
          case '?': value=base+1; break;
          case ',': value=base+2; break;
@@ -61,16 +51,13 @@ VG_STATIC void sfd_encode( u32 row, const char *str )
    int end=0;
    u32 row_h = world_global.sfd.h -1 -row;
 
-   for( int i=0; i<world_global.sfd.w; i++ )
-   {
+   for( int i=0; i<world_global.sfd.w; i++ ){
       u32 idx = (world_global.sfd.w*row_h + i) * 2;
 
-      if( end )
-      {
+      if( end ){
          world_global.sfd.buffer[idx] = 0.0f;
       }
-      else
-      {
+      else{
          if( !str[i] )
             end = 1;
 
@@ -79,22 +66,16 @@ VG_STATIC void sfd_encode( u32 row, const char *str )
    }
 }
 
-VG_STATIC void sfd_init( u32 w, u32 h )
-{
-}
-
 VG_STATIC void sfd_update(void)
 {
-   for( int i=0; i<world_global.sfd.w*world_global.sfd.h; i++ )
-   {
+   for( int i=0; i<world_global.sfd.w*world_global.sfd.h; i++ ){
       float *target = &world_global.sfd.buffer[i*2+0],
             *cur =    &world_global.sfd.buffer[i*2+1];
       
       float const rate = vg.time_delta * 15.2313131414f;
       float d1 = *target-*cur;
       
-      if( fabsf(d1) > rate )
-      {
+      if( fabsf(d1) > rate ){
          *cur += rate;
          if( *cur > 60.0f )
             *cur -= 60.0f;
@@ -105,14 +86,20 @@ VG_STATIC void sfd_update(void)
 }
 
 VG_STATIC void bind_terrain_noise(void);
-VG_STATIC void sfd_render( camera *cam, m4x3f transform )
+VG_STATIC void sfd_render( world_instance *world, camera *cam, m4x3f transform )
 {
-#if 0
-   mesh_bind( &world.sfd.mesh_display );
-   shader_scoretext_use();
-   shader_scoretext_uTexGarbage(0);
-   shader_scoretext_uTexGradients(1);
-   shader_link_standard_ub( _shader_scoretext.id, 2 );
+   mesh_bind( &world_global.sfd.mesh_display );
+   shader_scene_scoretext_use();
+   shader_scene_scoretext_uTexMain(1);
+
+   world_link_lighting_ub( world, _shader_scene_scoretext.id );
+   world_bind_position_texture( world, _shader_scene_scoretext.id, 
+                        _uniform_scene_scoretext_g_world_depth, 2 );
+   world_bind_light_array( world, _shader_scene_scoretext.id,
+                        _uniform_scene_scoretext_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_scoretext.id,
+                           _uniform_scene_scoretext_uLightsIndex, 4 );
+
    bind_terrain_noise();
    vg_tex2d_bind( &tex_scoretext, 1 );
 
@@ -120,43 +107,44 @@ VG_STATIC void sfd_render( camera *cam, m4x3f transform )
    m4x3_expand( transform, pvm_prev );
    m4x4_mul( cam->mtx_prev.pv, pvm_prev, pvm_prev );
 
-   shader_scoretext_uPv( cam->mtx.pv );
-   shader_scoretext_uPvmPrev( pvm_prev );
-   shader_scoretext_uMdl( transform );
-   shader_scoretext_uCamera( cam->transform[3] );
+   shader_scene_scoretext_uPv( cam->mtx.pv );
+   shader_scene_scoretext_uPvmPrev( pvm_prev );
+   shader_scene_scoretext_uMdl( transform );
+   shader_scene_scoretext_uCamera( cam->transform[3] );
 
-   for( int y=0;y<world.sfd.h; y++ )
-   {
-      for( int x=0; x<world.sfd.w; x++ )
-      {
-         float value = world.sfd.buffer[(y*world.sfd.w+x)*2+1];
-         shader_scoretext_uInfo( (v3f){ x,y, value } );
-         mesh_draw( &world.sfd.mesh_display );
+   for( int y=0;y<world_global.sfd.h; y++ ){
+      for( int x=0; x<world_global.sfd.w; x++ ){
+         float value = world_global.sfd.buffer[(y*world_global.sfd.w+x)*2+1];
+         shader_scene_scoretext_uInfo( (v3f){ x,y, value } );
+         mesh_draw( &world_global.sfd.mesh_display );
       }
    }
 
-   shader_vblend_use();
-   shader_vblend_uTexGarbage(0);
-   shader_vblend_uTexGradients(1);
-   shader_link_standard_ub( _shader_vblend.id, 2 );
+   shader_scene_vertex_blend_use();
+   shader_scene_vertex_blend_uTexGarbage(0);
+   shader_scene_vertex_blend_uTexGradients(1);
+   world_link_lighting_ub( world, _shader_scene_vertex_blend.id );
+   world_bind_position_texture( world, _shader_scene_vertex_blend.id, 
+                                _uniform_scene_vertex_blend_g_world_depth, 2 );
+   world_bind_light_array( world, _shader_scene_vertex_blend.id,
+                                _uniform_scene_vertex_blend_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_vertex_blend.id,
+                                _uniform_scene_vertex_blend_uLightsIndex, 4 );
    bind_terrain_noise();
    vg_tex2d_bind( &tex_scoretext, 1 );
 
-   shader_vblend_uPv( cam->mtx.pv );
-   shader_vblend_uPvmPrev( pvm_prev );
-
-   shader_vblend_uMdl( transform );
-   shader_vblend_uCamera( cam->transform[3] );
+   shader_scene_vertex_blend_uPv( cam->mtx.pv );
+   shader_scene_vertex_blend_uPvmPrev( pvm_prev );
+   shader_scene_vertex_blend_uMdl( transform );
+   shader_scene_vertex_blend_uCamera( cam->transform[3] );
    
-   mesh_bind( &world.sfd.mesh_base );
-   mesh_draw( &world.sfd.mesh_base );
-#endif
+   mesh_bind( &world_global.sfd.mesh_base );
+   mdl_draw_submesh( &world_global.sfd.sm_base );
 }
 
 VG_STATIC int world_sfd_test( int argc, const char *argv[] )
 {
-   if( argc == 2 )
-   {
+   if( argc == 2 ){
       int row = vg_min( vg_max(atoi(argv[0]),0), world_global.sfd.h);
       sfd_encode( row, argv[1] );
    }
@@ -167,10 +155,7 @@ VG_STATIC int world_sfd_test( int argc, const char *argv[] )
 VG_STATIC void world_sfd_init(void)
 {
    vg_info( "world_sfd_init\n" );
-
-#if 0
-   shader_scoretext_register();
-#endif
+   shader_scene_scoretext_register();
 
        vg_function_push( (struct vg_cmd){
                .name = "sfd",
@@ -178,43 +163,44 @@ VG_STATIC void world_sfd_init(void)
        });
 
    vg_linear_clear( vg_mem.scratch );
-   mdl_context *mboard = 
-      mdl_load_full( vg_mem.scratch, "models/rs_scoretext.mdl" );
+
+   mdl_context mscoreboard;
+   mdl_open( &mscoreboard, "models/rs_scoretext.mdl", vg_mem.scratch );
+   mdl_load_metadata_block( &mscoreboard, vg_mem.scratch );
+   mdl_load_mesh_block( &mscoreboard, vg_mem.scratch );
 
    scene *sc = scene_init( vg_mem.scratch, 3000, 8000 );
 
-   mdl_node *pn_backer = mdl_node_from_name( mboard, "backer" );
-   mdl_submesh *backer = &mboard->submesh_buffer[ pn_backer->submesh_start ];
-   mdl_node *pn_card = mdl_node_from_name( mboard, "score_card" );
-   mdl_submesh *card = &mboard->submesh_buffer[ pn_card->submesh_start ];
+   mdl_mesh *m_backer = mdl_find_mesh( &mscoreboard, "backer" ),
+            *m_card   = mdl_find_mesh( &mscoreboard, "score_card" );
+
+   mdl_submesh 
+      *sm_backer = mdl_arritm( &mscoreboard.submeshs, m_backer->submesh_start ),
+      *sm_card   = mdl_arritm( &mscoreboard.submeshs, m_card->submesh_start );
+   world_global.sfd.sm_base = *sm_backer;
+
+   mdl_close( &mscoreboard );
 
    m4x3f identity;
    m4x3_identity( identity );
 
-   /* FIXME: dont use scene header for this you fucking idiots */
-   for( int i=4;i<6;i++ )
-   {
+   for( int i=0;i<4;i++ ){
       u32 vert_start = sc->vertex_count;
-      scene_add_mdl_submesh( sc, mboard, card, identity );
+      scene_add_mdl_submesh( sc, &mscoreboard, sm_card, identity );
 
-#if 0
-      for( int j=0; j<card->vertex_count; j++ )
-      {
-         mdl_vert *vert = &sc->arrvertices[ vert_start+j ];
+      for( int j=0; j<sm_card->vertex_count; j++ ){
+         scene_vert *vert = &sc->arrvertices[ vert_start+j ];
 
          float const k_glyph_uvw = 1.0f/64.0f;
-         vert->uv[0] -= k_glyph_uvw * (float)(i-4);
-         vert->colour[0] = 0.0f;
-         vert->colour[1] = i*36;
+         vert->uv[0] -= k_glyph_uvw * (float)(i-1);
+         vert->norm[3] = i*42;
       }
-#endif
    }
 
    vg_acquire_thread_sync();
    {
       scene_upload( sc, &world_global.sfd.mesh_display );
-      mdl_unpack_submesh( mboard, &world_global.sfd.mesh_base, backer );
-
+      mdl_unpack_glmesh( &mscoreboard, &world_global.sfd.mesh_base );
       vg_tex2d_init( (vg_tex2d *[]){ &tex_scoretext }, 1 );
    }
    vg_release_thread_sync();
@@ -225,11 +211,10 @@ VG_STATIC void world_sfd_init(void)
    world_global.sfd.w = w;
    world_global.sfd.h = h;
    world_global.sfd.buffer = 
-                     vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
+         vg_linear_alloc( vg_mem.rtmemory, 2*w*h*sizeof(float) );
 
    for( int i=0; i<w*h*2; i++ )
       world_global.sfd.buffer[i] = 0.0f;
 }
-#endif
 
 #endif /* SFD_H */