Тени, отбрасываемые объектами очень далеко от источника света - PullRequest
2 голосов
/ 11 марта 2019

У меня проблема с тенями, отбрасываемыми объектами очень далеко от источника света.Я использую подход карты глубины для рендеринга теней в моей симуляции Солнечной системы.Солнце является точечным источником света, и я хотел бы наблюдать тень луны на земле.Но поскольку луна является действительно крошечным объектом по отношению к расстоянию между ней и солнцем и поскольку разрешение карты глубины ограничено, присутствие луны и земли игнорируется при визуализации текстуры карты глубинного куба.

Карта глубины Солнечной системы:

enter image description here

Вы можете видеть, что даже при увеличении размера луны она оставляет лишь небольшуюслед на карте глубины куба.С этой большой луной затмения работают, но как только я уменьшаю луну до ее фактического размера, она больше не отображается на карте глубины и поэтому больше не учитывается при расчете теней.Я использую 4096 X 4096 текстур.Есть ли способ решить эту проблему или мой подход обречен на провал?Любая помощь будет высоко ценится.

1 Ответ

2 голосов
/ 11 марта 2019

Необходимо сделать важное замечание: когда вы смотрите на Землю поближе, вам, вероятно, нет дела до теней на Марсе. Поэтому вместо использования карты кубов для карты теней всей Солнечной системы используйте плоскую карту теней, чтобы покрыть только околоземную область.

С картой глубины 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 - радиусы Солнца и луна.

Для реалистичных размеров этот код дает мне следующие изображения:

image image

Если я уменьшу размер Солнца вдвое, я получу следующее:

image image

...