Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Документация для продвинутых пользователей
                Рендеринг воды эффект постобработки

Рендеринг воды эффект постобработки

Опубликованно: 27.06.2017, 12:33
Последняя редакция, Andry: 03.09.2017 21:46

Удивительно но SeaMonkey WaterFilter очень настраиваемый. Он может визуализировать любой тип воды, а также имитировать эффект погружения подводу, включая световые эффекты, называемые каустиками. Эффект основан на рендеринге воды Wojciech Toman в качестве эффекта постобработки, опубликованном на gamedev.net. Вот видео:

water-post

SeaMonkey WaterFilter идеально подходит для океанов и озер, и особенно для подводных сцен. Но если вам нужна всего лишь небольшая простая водная поверхность, такая как водный желоб или мелкий фонтан, вам будет достаточно использовать SimpleWaterProcessor.

Теория

Эффект является частью отложенного процесса рендеринга, используя преимущество предварительно вычесленного position bufferи и back buffer (текстура, представляющая положение пикселей экрана в пространстве взгляда и текстуру рендеринга сцены).

После некоторых вычислений это позволяет восстановить положение, в мировом пространстве, для каждого пикселя на экране. «Если пиксель находится под заданной глубиной в воде, давайте сделаем его синим пикселом! Синий пиксель? Не совсем, нам нужны волны, мы хотим рябь, мы хотим пену, мы хотим отражения и рефракцию.

В статье GameDev.net описывается, как можно получить эти эффекты, но основная идея состоит в том, чтобы генерировать волны из карты высоты, создавать ряби из карты нормалей, смешивать текстуры пены, когда глубина воды ниже определенной высоты, вычислять преломление цвет с помощью умного алгоритма затухания цвета, а затем отображать эффект отражения и зеркальности, вычисляя выражение Френеля (как в простом эффекте воды). Кроме того, этот эффект позволяет смешать воду у берег с землей, чтобы избежать жестких краев классических водных эффектов, основанных на grids или quads.

Как мы реализовали его в jME3?

По умолчанию поведение jME3 заключается в использовании процесса прямого рендеринга, поэтому нет позиции буфера, которую мы могли бы использовать. Но пока рендеринг основной сцены в кадровом буфере в FilterPostPorcessor, мы можем записать в железо текстуру буфер глубины, без каких-либо дополнительных затрат.

Существует несколько способов восстановления положения пикселя в пространстве мира из буфера глубины. Расчетные затраты выше, чем просто выбор позиции буфера, но пропускная способность и требуемая память намного ниже.

Теперь у нас есть визуализированная сцена в текстуре, и мы можем восстановить позицию, в мировом пространстве, каждого пикселя. Мы будем рады!

– Nehon

Примеры кода

Это тестовые примеры в репозитории jME3:

Использование Водного Фильтра

В методе simpleInitApp() вы присоединяете свою сцену к rootNode, как правило, к ландшафт с небом. Не забудьте добавить направленный свет(directional light), так как вода зависит от вектора направления света. Конструктор WaterFilter ожидает узел с прикрепленной сценой, которая должна отражаться в воде, и векторную информацию от направления источника света.

Вот как вы используете код постобработку фильтра воды в вашем коде:

private FilterPostProcessor fpp;
private WaterFilter water;
private Vector3f lightDir = new Vector3f(-4.9f, -1.3f, 5.9f); // тот же источник света
private float initialWaterHeight = 0.8f; // выберите значение для вашей сцены
...

public void simpleInitApp() {
  ...
  fpp = new FilterPostProcessor(assetManager);
  water = new WaterFilter(rootNode, lightDir);
  water.setWaterHeight(initialWaterHeight);
  fpp.addFilter(water);
  viewPort.addProcessor(fpp);
  ...
}

Обычно вы делаете в воде отражением всего, что связано с rootNode. Но вы также можете предоставить пользовательский узел (под-узел rootNode) конструктору WaterFilter, который имеет только подмножество узлов сцены. Это будет подходящей оптимизацией, если у вас много узлов, которые находятся далеко от воды или где то закрыты, и никогда не будут отражаться в воде.

Дополнительно: Волны

Если вам нужны волны, задайте высоту воды в цикле обновления. Мы повторно используем переменную initialWaterHeight и повторно устанавливаем значение waterHeight в зависимости от времени. Это вызывает волны.

private float time = 0.0f;
private float waterHeight = 0.0f;

@Override
public void simpleUpdate(float tpf) {
  super.simpleUpdate(tpf);
  time += tpf;
  waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
  water.setWaterHeight(initialWaterHeight + waterHeight);
}

Дополнительно: Водная волна и цветовые эффекты

water-reflection-muddy

Все эти эффекты являются необязательными. У каждого сеттера также есть геттер.

Примеры методов воды Эффекты: Волн  По умолчанию
water.setWaterHeight(-6); Используйте этот метод waterheight для создания волн.  0.0f
water.setMaxAmplitude(0.3f); Насколько высоки самые высокие волны.  1.0f
water.setWaveScale(0.008f); Устанавливает коэффициент масштаба карты высоты волн. Чем меньше значение, тем больше волны!  0.005f
water.setWindDirection(new Vector2f(0,1)) Устанавливает направление ветра, которое является направлением, в котором движутся волны  Vector2f(0.0f, -1.0f)
water.setSpeed(0.7f); Как быстро волны движутся. Установите его на 0.0f для неподвижной воды.  1.0f
water.setHeightTexture( (Texture2D)
manager.loadTexture(“Textures/waveheight.png) )
Эта карта высоты описывает форму волн  Common/MatDefs/Water/Textures/heightmap.jpg
water.setNormalTexture( (Texture2D)
manager.loadTexture(“Textures/wavenormals.png) )
Эта карта нормалей описывает форму волн  Common/MatDefs/Water/Textures/gradient_map.jpg
water.setUseRipples(false); Включает или выключает эффект ряби.  true
water.setNormalScale(0.5f) Устанавливает обычный коэффициенты масштабирования для применения к карте нормалей. Чем выше значение, тем более мелкая ряби будут видны на волнах.  1.0f
Примеры методов воды Эффекты: Цвета  По умолчанию
water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f)) Обычно вы задаёте это так же, как и направление источника света. Используйте это, чтобы установить направление света, если ваше солнце движется.  Значение, дается конструктору WaterFilter().
water.setLightColor(ColorRGBA.White) Обычно вы задаёте это так же, как цвет источника света.  RGBA.White
water.setWaterColor(ColorRGBA.Brown.mult(2.0f)); Устанавливает основной цвет воды.  зеленовато-голубой
ColorRGBA(0.0f,0.5f,0.5f,1.0f)
water.setDeepWaterColor(ColorRGBA.Brown); Устанавливает цвет глубокой воды.  темно-голубой
ColorRGBA(0.0f, 0.0f,0.2f,1.0f)
water.setWaterTransparency(0.2f); Устанавливает, как быстро исчезают цвета. Используйте это для управления прозрачностью (например, 0,05f) или мутностью (0,2f) воды.  0.1f
water.setColorExtinction(new Vector3f(10f,20f,30f)); Устанавливает на какой глубине преломляющийся цвет иссякает. Три значения: RGB (красный, зеленый, синий) в этом порядке. Играйте с этими параметрами, чтобы «мутить воду».  Vector3f(5f,20f,30f)
Примеры методов воды Эффекты: Берега  По умолчанию
water.setCenter(Vector3f.ZERO);
water.setRadius(260);
Ограничьте фильтр воды в полусфере с заданным центром и радиусом. Используйте это для озер и небольших водоемов. Не используйте это для океанов.  неиспользуется
water.setShoreHardness(1.0f); Устанавливает, насколько мягким должен быть переход между берегом и водой. Высокие значения означают более сложный переход между берегом и водой.  0.1f
water.setUseHQShoreline(false); Улучшает качество береговой линии?  true
Примеры методов воды Эффекты: Пены  По умолчанию
water.setUseFoam(false); Включает или выключает белую пена  true
water.setFoamHardness(0.5f) Устанавливает, насколько пена будет смешаться с берегом, чтобы избежать жесткого врезания в берег водной плоскости.  1.0f
water.setFoamExistence(new Vector3f(0.5f,5f,1.0f)) Три значения определяющие, на какой глубине пены начинает исчезать, на какой глубине она полностью невидима, на какой высоте появляется пена в волнах (+ waterHeight).  Vector3f(0.45f,4.35f,1.0f)
water.setFoamTexture( (Texture2D)
manager.loadTexture(“Textures/foam.png) )
Эта текстура пены будет использоваться с WrapMode.Repeat  Common/MatDefs/Water/Textures/foam.jpg
Примеры методов воды Эффекты: Освещения  По умолчанию
water.setSunScale(1f); Устанавливает, насколько большое солнце должно появиться в зеркальном эффекте света на воде.  3.0f
water.setUseSpecular(false) Включение или выключение зеркального эффекта  true
water.setShininess(0.8f) Устанавливает блеск отражений воды при преломлении  0.7f
water.setUseRefraction(true) Включает или выключает эффект преломления.  true
water.setRefractionConstant(0.2f); Чем ниже значение, тем меньше отражения видны на воде. Это константа, связанная с показателем преломления (IOR), используемым для вычисления формулы Френеля.  0.3f
water.setRefractionStrength(-0.1) Это значение изменяет текущую формулу Френеля. Если вы хотите ослабить отражения, используйте большое значение. Если вы хотите подчекнуть их, используйте значение меньше нуля.  0.0f
water.setReflectionMapSize(256) Устанавливает размер карты отражения. Чем выше, тем лучше качество, тем медленнее эффект.  512

Звуковые эффекты

Вы также должны добавить звуковые узлы с водяными звуками для завершения эффекта.

AudioNode waves = new AudioNode(assetManager, "Sounds/Environment/Ocean Waves.ogg", false);
waves.setLooping(true);
audioRenderer.playSource(waves);

Смотрите Также:


Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.