В Minecraft, когда вы смотрите на воду, чем глубже вы видите, тем темнее становится. Кто-нибудь знает, как кодировать что-то подобное?
Minecraft с эффектом
похожая игра без эффекта
В Minecraft, когда вы смотрите на воду, чем глубже вы видите, тем темнее становится. Кто-нибудь знает, как кодировать что-то подобное?
Minecraft с эффектом
похожая игра без эффекта
Ответы:
Существуют два основных подхода к освещению воды в зависимости от глубины:
Minecraft использует воксельное освещение, которое распространяет свет на соседние кубы, уменьшая яркость в зависимости от типа блока. Темные океаны являются побочным эффектом этой системы.
Вода блокирует солнечный свет и уменьшает свет на 3 уровня на блок (вместо 1 уровня по умолчанию), что означает, что яркость в океане для каждого расстояния от поверхности составляет:
0 (surface): 15 (direct sunlight)
1: 12
2: 9
3: 6
4: 3
5 and below: 0 (darkness)
Источник: Minecraft Wiki - Light
В играх с традиционной моделью освещения этот эффект можно создать, измеряя количество воды, находящейся между источником света и дном океана. Затем свет исчезает в зависимости от этого расстояния. Есть несколько способов сделать это:
Если у вас плоская поверхность, вы можете легко рассчитать расстояние, которое свет проходит в воде, если вы передадите нормаль поверхности от водоема и точечное произведение этого нормаля и положение поверхности в геометрический шейдер.
Эффективное расстояние воды
где - положение вершины и угол между направлением света под поверхностью и поверхностью воды, перпендикулярным массе воды.
На закате только достигает чуть менее 50 °, потому что свет преломляется при входе в воду.
Вот запись в блоге с хорошим объяснением: Цифровая камера: полное внутреннее отражение
Еще одна запись с более подробной информацией: Цифровая камера: закон преломления Снелла
Если вы используете карту высот на поверхности, параллельной воде, становится . Правильный коэффициент равен 1, если солнце находится прямо над поверхностью воды.
С точечным источником света вы должны рассчитать для каждой вершины, основываясь на относительном положении источника света.
При фиксированном уровне воды или фиксированном направлении света части уравнения являются постоянными и не должны рассчитываться в шейдере по соображениям производительности.
Если вы визуализируете поверхность воды на отдельной карте глубины (как видно из источника света), вы можете использовать эту текстуру глубины, чтобы вычислить расстояние, которое свет проходит в воде, прежде чем ударить по поверхности.
Для этого вы проецируете каждую вершину в проекцию вида источника света в вершинном шейдере и выполняете поиск текстуры в пиксельном шейдере.
Если поверхность относительно плоская, вы должны использовать источник преломленного света для лучших результатов.
* Вы можете определить количество воды перед ближайшей твердой поверхностью, посчитав глубину от POV света следующим образом:
Результирующая текстура теперь содержит количество воды перед источником света в пространстве светового обзора, поэтому значение должно быть преобразовано обратно перед использованием. Этот метод работает для расчета направленного света (минус преломление), но приведет к неправильному окружающему освещению, если поверхности очень неровные и между водоемами большое количество воздуха, воздействующее на одни и те же фрагменты.
Плюсы и минусы те же, что и для обычного отображения теней, за исключением того, что при расчете глубины вам понадобится еще один буфер, а производительность будет хуже, потому что вам придется рисовать больше геометрии.
Трассировка лучей - безусловно, самое точное, но и самое дорогое решение для рендеринга прозрачных объемов. Есть два способа сделать это: 1. Отслеживание от дна океана к поверхности и 2. Отслеживание от источника света к воде. Несколько лучей необходимы для каждой точки на полу, чтобы рассчитать яркость.
Есть еще несколько вещей, которые необходимо учитывать при рендеринге воды:
Свет в воде снова рассеивается во время путешествия к наблюдателю, поэтому вы должны смешать его в сплошной цвет.
Если наблюдатель погружен в воду , вы можете просто визуализировать туман на основе окончательного результата буфера глубины. Цвет тумана, но не его плотность, должен меняться с удалением наблюдателя от поверхности! (Minecraft использует только эту часть эффекта.)
Если наблюдатель смотрит на воду сверху , вам нужно рассчитать туман на основе разницы глубины между поверхностью и геометрией под водой. Цвет тумана должен стать немного темнее с большей разницей в глубине, но должен измениться только до точки, где туман полностью непрозрачен.
Цвет тумана также должен зависеть от направления обзора для каждого пикселя, поэтому он немного темнее, если смотреть вниз в обоих случаях.
Если вы используете бесшовную мозаичную 3D-текстуру вместо надписи для искусственной каустики, вы можете избежать растяжения вертикальных поверхностей. Сила рассеянного света у поверхности варьируется в трех измерениях, поэтому использование 2D-текстуры обычно приводит к растяжению где-то в сцене. Вы можете смоделировать изменение углов освещения, проецируя положения вершин пола в другую систему координат.
Другая возможность состоит в том, чтобы рассчитать плотность света на основе положения поверхности в системе координат света, хотя это, скорее всего, будет стоить некоторой производительности.
Каустика должна исчезать быстрее, чем рассеянный свет с увеличением глубины.
Цвета разбросаны по-разному, поэтому светлый цвет должен меняться с увеличением глубины. Это также предотвращает появление крутых кромок, например, если пляж пересекает поверхность воды.
Из-за преломления свет падает на дно океана гораздо круче, чем обычно. В статье Википедии о законе Снелла есть формулы для углов и векторов.
Я считаю, что эффект освещения неба в Майнкрафте прямо вниз - вещи затеняются тем, что находится над ними, независимо от того, где солнце. Затем применяется локальное освещение от факелов и т. Д. С эффектом спада - чем дальше от источника света, тем меньше света получает куб.
Если сделать это таким образом, каждый слой воды будет кумулятивно затенять слой под ним, так что каждый становится все темнее. Листва деревьев обеспечивает такой оттенок, однако он не является кумулятивным. Вы получаете тот же оттенок под деревом, будь то 1 или 100 кубиков листвы.
Один из признаков того, что этот метод используется, заключается в том, что вода не темнеет, когда находится дальше от зрителя, - только когда вы спускаетесь. Да, эффект тумана срабатывает на расстоянии, но не эффект темноты воды.
Таким образом, основная формула для расчета освещения будет выглядеть примерно так в псевдокоде ...
light_on_cube = 1.0
for each cube above target cube, from lowest to highest {
if cube being examined is tree foliage
light_on_cube = 0.5
else if cube being examined is water
light_on_cube = light_on_cube - 0.1
else if cube being examined is solid
light_on_cube = 0
}
Это не идеально для расчета освещения под выступами или в пещерах, так как при использовании этого метода было бы совершенно темно под выступом. Но можно добавить как локальные источники света (факелы, огни и т. Д.), Так и трактовать освещенные солнцем блоки в качестве источников света. Нечто подобное может сделать это ...
Идея состоит в том, что если куб освещается солнцем или факелом, то куб рядом с ним также будет освещен каким-то образом. И чем дальше вы находитесь от этого освещенного куба, тем меньше света будет. Это своего рода хитрый способ оценить рассеянное освещение, но я думаю (?) Это сработает.
Возможно, я неправильно понимаю вопрос, но почему вы не можете просто изменить цвет блоков в зависимости от их глубины?
Если у вас есть глубина d (в блоках, начиная с 0), то разумным уравнением для яркости будет:
L = (1- т ) е - кд + м
Код: L = (1.0 - m) * exp(-k * d) + m;
k контролирует, насколько быстро становится темнее (выше = быстрее). Разумное значение будет 0,5.
m - минимальная яркость, которую вы хотите.
L варьируется от 0 до 1.
Если вы не знаете, как изменить цвет блоков в любом графическом API, который вы используете, задайте это как отдельный вопрос (с указанием того, какой API вы используете, и используете ли вы шейдеры или нет).
e^-kd
Бит просто экспоненциальный спад, который является стандартной функцией для вещей , которые постепенно стремятся к нулю в течение некоторого значения (глубины). Умножение на (1-m)
и сложение m
просто для масштабирования и смещения затухания так, чтобы оно заканчивалось как минимум, m
но все равно начиналось с 1
. en.wikipedia.org/wiki/Exponential_decay