+ }
+
+ if( !viewing_from_gate ){
+ f32 greyout = 0.0f;
+ if( mdl_entity_id_type(world_static.focused_entity) == k_ent_challenge )
+ greyout = world_static.focus_strength;
+
+ if( greyout > 0.0f ){
+ glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
+ glEnable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendEquation(GL_FUNC_ADD);
+
+ shader_blitcolour_use();
+ shader_blitcolour_uColour( (v4f){ 0.5f, 0.5f, 0.5f, greyout*0.56f } );
+ render_fsquad();
+
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDrawBuffers( 2, (GLenum[]){ GL_COLOR_ATTACHMENT0,
+ GL_COLOR_ATTACHMENT1 } );
+ }
+
+ render_world_fxglow( world, world, cam, NULL, 1, 1, 0 );
+ }
+
+ if( with_water ){
+ render_water_texture( world, cam );
+ render_fb_bind( gpipeline.fb_main, 1 );
+ }
+
+ if( stenciled ){
+ glStencilFunc( GL_EQUAL, 1, 0xFF );
+ glStencilMask( 0x00 );
+ glEnable( GL_CULL_FACE );
+ glEnable( GL_STENCIL_TEST );
+ }
+
+ if( with_water ){
+ render_water_surface( world, cam );
+ }
+
+ render_remote_players( world, cam );
+ render_other_entities( world, cam );
+ ent_miniworld_render( world, cam );
+
+ if( stenciled ){
+ glStencilMask( 0xFF );
+ glStencilFunc( GL_ALWAYS, 1, 0xFF );
+ glDisable( GL_STENCIL_TEST );
+ }
+}
+
+
+static void render_world_override_pass( world_instance *world,
+ struct world_pass *pass,
+ m4x3f mmdl, m3x3f mnormal,
+ m4x4f mpvm_prev ){
+ for( int i=0; i<world->surface_count; i++ ){
+ struct world_surface *mat = &world->surfaces[i];
+ if( mat->info.flags & k_material_flag_ghosts ) continue;
+
+ mdl_submesh *sm;
+ if( pass->geo_type == k_world_geo_type_solid )
+ sm = &mat->sm_geo;
+ else
+ sm = &mat->sm_no_collide;
+
+ if( !sm->indice_count )
+ continue;
+
+ pass->fn_set_mdl( mmdl );
+ pass->fn_set_uNormalMtx( mnormal );
+ pass->fn_set_uPvmPrev( mpvm_prev );
+ pass->fn_bind_textures( world, mat );
+ mdl_draw_submesh( sm );
+ }
+}
+
+void render_world_override( world_instance *world,
+ world_instance *lighting_source,
+ m4x3f mmdl,
+ vg_camera *cam,
+ ent_spawn *dest_spawn, v4f map_info )
+{
+ struct world_pass pass = {
+ .cam = cam,
+ .fn_bind_textures = bindpoint_override,
+ .fn_set_mdl = shader_scene_override_uMdl,
+ .fn_set_uPvmPrev = shader_scene_override_uPvmPrev,
+ .fn_set_uNormalMtx = shader_scene_override_uNormalMtx,
+ .shader = k_shader_override
+ };
+
+ shader_scene_override_use();
+ shader_scene_override_uTexGarbage(0);
+ shader_scene_override_uTexMain(1);
+ shader_scene_override_uPv( pass.cam->mtx.pv );
+ shader_scene_override_uMapInfo( map_info );
+
+ WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( lighting_source, scene_override );
+ bind_terrain_noise();
+
+ shader_scene_override_uCamera( pass.cam->transform[3] );
+
+ m4x4f mpvm_prev;
+ m4x3_expand( mmdl, mpvm_prev );
+ m4x4_mul( cam->mtx_prev.pv, mpvm_prev, mpvm_prev );
+
+ m3x3f mnormal;
+ m3x3_inv( mmdl, mnormal );
+ m3x3_transpose( mnormal, mnormal );
+ v3_normalize( mnormal[0] );
+ v3_normalize( mnormal[1] );
+ v3_normalize( mnormal[2] );
+
+ v4f uPlayerPos, uSpawnPos;
+ v4_zero( uPlayerPos );
+ v4_zero( uSpawnPos );
+
+ v3_copy( world->player_co, uPlayerPos );
+
+ if( dest_spawn && (v3_dist2(dest_spawn->transform.co,uPlayerPos) > 0.1f) )
+ v3_copy( dest_spawn->transform.co, uSpawnPos );
+ else
+ v3_add( uPlayerPos, (v3f){0,-1,0}, uSpawnPos );
+
+ uPlayerPos[3] = v3_dist(uPlayerPos,uSpawnPos);
+ uSpawnPos[3] = 1.0f/uPlayerPos[3];