-static void scene_shadow_sphere( scene *pscene, v3f sphere,
- v4f params, v3f lightdir )
-{
- for( int i=0; i<pscene->vertex_count; i++ )
- {
- model_vert *vert = &pscene->verts[i];
-
- v3f delta;
- v3_sub( sphere, vert->co, delta );
-
- float d = v3_dot( lightdir, delta );
- v3f closest;
-
- v3_muls( lightdir, d, closest );
- float dist = v3_dist( closest, delta ),
- shading = vg_maxf( dist - params[0], 0.0f );
-
- shading = vg_minf( shading * params[1], 1.0f );
- vert->colour[1] *= shading;
- }
-}
-
-static void scene_shadow_gradient( scene *pscene, int comp,
- float start, float length )
-{
- float scale = 1.0f / length;
-
- for( int i=0; i<pscene->vertex_count; i++ )
- {
- model_vert *vert = &pscene->verts[i];
- float shading = start + vert->co[comp] * scale;
-
- vert->colour[1] = shading;
- }
-}
-
-
-/*
- * Experimental SDF based shadows
- *
- * https://iquilezles.org/articles/distfunctions/
- */
-static float sd_cone( v3f co, sdf_primative *prim )
-{
- float bound = prim->info[1]*1.75f;
- if( v3_dist2( prim->origin, co ) > bound*bound )
- return 999999.9f;
-
- v3f p;
- v3_sub( co, prim->origin, p );
-
- float h = prim->info[1];
- v2f c = { prim->info[2], prim->info[3] };
-
- v2f q, w, a, b;
- v2_muls( (v2f){ c[0]/c[1], -1.0f }, h, q );
-
- w[0] = v2_length( (v2f){ p[0], p[2] } );
- w[1] = p[1];
-
- v2_muladds( w, q, -vg_clampf( v2_dot(w,q)/v2_dot(q,q), 0.0f, 1.0f ), a );
- v2_muladd( w, q, (v2f){ vg_clampf( w[0]/q[0], 0.0f, 1.0f ), 1.0f }, b );
-
- float k = vg_signf( q[1] ),
- d = vg_minf( v2_dot( a,a ), v2_dot( b,b ) ),
- s = vg_maxf( k*(w[0]*q[1]-w[1]*q[0]), k*(w[1]-q[1]) );
-
- return sqrtf(d)*vg_signf(s);
-}
-
-#define CACHE_AMBIENT_SHAPES
-
-static float scene_ambient_sample( scene *pscene, v3f pos, v3f dir )
-{
- float accum = 0.0f;
-
-#ifdef CACHE_AMBIENT_SHAPES
- static struct shadower *local_shadowers[32];
- static int local_shadower_count = 0;
- static v3f local_shadower_last = { -99999.9f, -999999.9f, -9999999.9f };
-
- if( v3_dist2( pos, local_shadower_last ) > 10.0f*10.0f )
- {
- local_shadower_count = 0;
- v3_copy( pos, local_shadower_last );
-
- for( int k=0; k<pscene->shadower_count; k++ )
- {
- struct shadower *shadower = &pscene->shadowers[k];
-
- if( sd_cone( pos, &shadower->sdf ) <= 20.0f )
- {
- local_shadowers[ local_shadower_count ++ ] = shadower;
- if( local_shadower_count == vg_list_size( local_shadowers ) )
- break;
- }
- }
- }
-#endif
-
- for( int j=0; j<5; j++ )
- {
- v3f tracepos;
- v3_muladds( pos, dir, 1.5f*(float)j, tracepos );
-
- float mindist = 99999.9f;
-
-#ifndef CACHE_AMBIENT_SHAPES
-
- for( int k=0; k<pscene->shadower_count; k++ ){
- struct shadower *shadower = &pscene->shadowers[k];
-#else
-
- for( int k=0; k<local_shadower_count; k++ ){
- struct shadower *shadower = local_shadowers[k];
-#endif
-
- float dist = vg_maxf( 0.0f, sd_cone( tracepos, &shadower->sdf ));
- mindist = vg_minf( mindist, dist );
- }
-
-
- accum += vg_clampf( 1.0f - mindist, 0.0f, 1.0f )*0.2f;
- }
-
- return accum;
-}
-
-#define DYNAMIC_GRID
-#define JUST_DO_EVERY_VERT
-
-static void scene_compute_occlusion( scene *pscene )