При использовании многопроходного освещения возникает проблема наложения тумана. Если рассматривать результат аддитивного смешивания, получим следующую формулу (для урощения предположим, что коэффициент наложения тумана при расчете равен 0.7):
Где L1 - результат вычисления цвета в первом проходе
L2 - во втором
C1 - суммарный результат освещения с туманом в первом проходе
C2 - во втором
В результате вычислений получили фактор тумана равный 1.4, т.е. туман наложился дважды:
Если выключить туман во втором проходе, результат будет так же неправильный:
туман не повлиял на второй проход освещения. В результате дальние объекты начнут светиться через туман (для наглядности фактор тумана увеличен):
Можно посчитать фактор тумана таким образом, чтобы в каждом проходе накладывалась только часть тумана
Самым простым решением проблемы является обнуление цвета тумана (до черного). Результат вычисления:
Что и требовалось. Результат:
Код рендера выглядит примерно так:
C1 = L1 * 0.3 + F * 0.7 // первый проход
C2 = L2 * 0.3 + F * 0.7 // второй проход
C = C1 + C2 = L1 * 0.3 + F * 0.7 + L2 * 0.3 + F * 0.7 = (L1 + L2) * 0.3 + F * 1.4
Где L1 - результат вычисления цвета в первом проходе
L2 - во втором
C1 - суммарный результат освещения с туманом в первом проходе
C2 - во втором
В результате вычислений получили фактор тумана равный 1.4, т.е. туман наложился дважды:
Если выключить туман во втором проходе, результат будет так же неправильный:
C1 = L1 * 0.3 + F * 0.7
C2 = L2
C = C1 + C2 = L1 * 0.3 + L2 + 0.7 * F
туман не повлиял на второй проход освещения. В результате дальние объекты начнут светиться через туман (для наглядности фактор тумана увеличен):
Можно посчитать фактор тумана таким образом, чтобы в каждом проходе накладывалась только часть тумана
Fi = F / N, где N - число проходов освещения. Этот подход возможен, но достаточно сложный в реализации, потому как при отсечении источников света рисуется только та часть объектов, которая попала в зону влияния источника света.
Самым простым решением проблемы является обнуление цвета тумана (до черного). Результат вычисления:
C1 = L1 * 0.3 + F * 0.7
C2 = L2 * 0.3 + F * 0.7 = L2 * 0.3 + 0.0 * 0.7 = L2 * 0.3
C = L1 + L2 = L1 * 0.3 + 0.7 * F + L2 * 0.3 = (L1 + L2) * 0.3 + F * 0.7
Что и требовалось. Результат:
Код рендера выглядит примерно так:
// сохраняем настройки цвета тумана
D3DXCOLOR saveFogColor = _fogColor;
for(size_t lightIndex = 0; lightIndex < _lights.size(); ++lightIndex)
{
context.light = _lights[lightIndex];
context.renderPass = RenderPass_Lighting;
// если включены тени, рисуем карту теней
if (context.light->enableShadows)
RenderShadowMap(&context);
// рисуем все модели в сцене
for(size_t entityIndex = 0; entityIndex < _entities.size(); ++entityIndex)
{
context.entity = _entities[entityIndex];
context.entity->model->Render(context);
}
// обнуляем туман в последующих проходах
_fogColor = D3DXCOLOR(0, 0, 0, 0);
// включаем аддитивное наложение
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
// восстанавливаем исходный цвет тумана
_fogColor = saveFogColor;
Комментариев нет:
Отправить комментарий