Необходимо сделать важное замечание: когда вы смотрите на Землю поближе, вам, вероятно, нет дела до теней на Марсе. Поэтому вместо использования карты кубов для карты теней всей Солнечной системы используйте плоскую карту теней, чтобы покрыть только околоземную область.
С картой глубины 4096x4096 и расстоянием до Луны 384000 км вы получаете разрешение ~ 100 км на тексель, и Луна займет карту с радиусом ~ 20 текселей на карте теней.
Однако есть лучший подход. Поскольку планеты и луны приблизительно сферические и их всего несколько, вы можете просто выполнить пересечение лучевой сферы на фрагмент для вычисления теней. Можно рассчитать угловую площадь пересечения между луной и солнечными дисками, чтобы получить рендеринг зонты / полутени в реальном времени. Вот функция, которая приближает фактор тени в шейдере:
float soft_shadow(vec3 light, float light_radius,
vec3 occluder, float occluder_radius, vec3 fragment)
{
vec3 v0 = light - fragment;
vec3 v1 = occluder - fragment;
float R0 = length(v0);
float R1 = length(v1);
float a0 = light_radius/R0;
float a1 = occluder_radius/R1;
float a = length(cross(v0, v1))/(R0*R1);
a = smoothstep(a0 - a1, a0 + a1, a);
return 1 - (1 - a)*pow(a1/a0, 2);
}
Здесь 0.0
означает полную тень, 1.0
означает отсутствие тени вообще. light
, occluder
и fragment
- это местоположения Солнца, Луны и фрагмента в непроективном пространстве , тогда как light_radius
и occluder_radius
- радиусы Солнца и луна.
Для реалистичных размеров этот код дает мне следующие изображения:
Если я уменьшу размер Солнца вдвое, я получу следующее: