Як оживити абстрактну 2d текстуру води зверху вниз?


24

Зараз я реалізую гру з видом на океан. Я використовую наступну, трохи абстрактну текстуру:введіть тут опис зображення

Фактична текстура прозора, я додав зелений колір для наочності.

Зараз у мене проблема полягає в тому, що я не знаю, як оживити цю текстуру, щоб вода виглядала приємно. Я спробував перемістити текстуру з гріхом хвилі: texture.y += sin(angle). Звичайно, зараз вся текстура рухається, що виглядає наче нереально. Наступне, що я спробував - додати ще один шар і реалізувати ефект паралакса. Так що відбиття під поверхнею води також рухалися б, але набагато повільніше. Це виглядає трохи краще, але все ж не ... досить приємно.

Я думаю, що найкраще виглядатиме анімація, якби окремі клітинки розширювались і стискалися, на зразок павутини або шматка тканини. Уявіть собі, якби хтось трохи потягнув за собою одну вершину цих комірок, і сусідня комірка розшириться, і комірка, до якої я тягнуться до (або підштовхує), скоротиться. Вигляд, як павутина пружин (?). Але у мене немає поняття, як реалізувати щось подібне:

  • Що для цього математична модель? Щось із пружинами, де сили штовхають / тягнуть?
  • І якщо так, то як я віднесу цю модель до заданої текстури? Збереження всіх кривих, а що ні ...

(Я також відкритий до різних ідей / відповідей щодо того, як оживити дану текстуру. Реалізм не в цьому суть, просто якась приємна виглядає вода, як рухи ...)

Рішення від DMGregory

Я розмістив приклад libgdx в цьому дописі: 2d водна анімація нерівна і не гладка (див. Відповідь про фільтрування текстур)

Відповіді:


41

Поширений спосіб це використовувати - непрямий пошук текстури в шейдері для спотворення текстури дисплея:

Gif анімовані gif анімації

Тут я використовую текстуру з деяким низькочастотним кольоровим шумом (плитка гладкими краплями випадкових кольорів) і прокручую її по геометрії дисплея з часом.

введіть тут опис зображення

Замість того, щоб малювати кольори з цієї текстури, я замість цього беру червоно-зелені канали і віднімаю, 0.5fщоб перетворити їх на псевдовипадковий 2D-вектор, який плавно змінюється в часі та просторі.

Потім я можу додати невелику кратну кількість цього вектора до моїх УФ-координат, перш ніж взяти пробу з основної текстури води. Це зміщує частину текстури, яку ми читаємо та відображаємо, обертаючи її навколо.

Упорядковуючи два зразки від цього шуму, прокручуючи в протилежних напрямках, ми можемо приховати напрямок руху, так що це просто схоже на безцільне збивання.

В Unity шейдер виглядав би так: він повинен бути досить простим для перекладу на вибрану вами мову шейдера:

fixed4 frag (v2f i) : SV_Target
{               
    float2 waveUV = i.uv * _NoiseScale;
    float2 travel = _NoiseScrollVelocity * _Time.x;

    float2 uv = i.uv;
    uv += _Distortion * (tex2D(_Noise, waveUV + travel).rg - 0.5f);
    waveUV += 0.2f; // Force an offset between the two samples.
    uv += _Distortion * (tex2D(_Noise, waveUV - travel).rg - 0.5f);

    // Sample the main texture from the distorted UV coordinates.
    fixed4 col = tex2D(_MainTex, uv);

    return col;
}

1
Це виглядає дійсно приємно. Я не впевнений, що я розумію всі атрибути: _NoseScale = скаляр для масштабування "карти шуму". _NoiseScrollVelocity = Вектор2, з якою швидкістю ми рухаємось по карті шуму. _Шум =?. _Distortion = Скалярний я вибираю як фактор спотворення? v2f = Вершина, визначаємо колір. i =?
morpheus05

_Noiseце [пробовідбірник текстур, який читає] маленьку крихітку випадкову текстуру, що зверху. v2f iце інтерпольовані дані з вершинного шейдера - в основному ми використовуємо його , щоб отримати координати текстури для пікселя ми малюємо, i.uv. І ви абсолютно правильно ставитесь до всього іншого.
DMGregory

Я реалізував шейдер і якимось чином він не працює (він не рухається або спотворення велике), я вважаю, що я не встановив значення правильно. час = різниця від останнього кадру в мс. noise_scale = 1 (я використовую вашу текстуру, режим обгортання повторюється) noise_scroll_velocity = [0,01, 0,01] спотворення = 0,02
morpheus05

Зауважте, що змінна називається Time, а не DeltaTime. Якщо ви використовуєте різницю у часі, а частота кадрів є послідовною, то ви завжди отримуватимете однакове число, і ви будете повторно запускати шейдер з тими ж входами, отримуючи однаковий вихід (нічого не рухається). Гірше, якщо ваш кадр невідповідний, тоді ви отримаєте вібрацію назад і назад. Ви хочете, щоб пройшов загальний час, а не час дельта.
DMGregory

Незабаром, коли я потрапив, я зрозумів, що зараз це майже працює. Здається, анімація сприймає хвилі з правого нижнього кута, а через 10 секунд вона просто згасає, як хвилі, що зупиняються. Що може бути причиною цього?
morpheus05

6

Це називається їдким ефектом, і генерування цих ефектів під час виконання досить забирає багато часу, тому це традиційно робиться за допомогою попередньо наданої кадрової анімації. Є інструменти, які створюватимуть для вас їдкі кадри анімації, такі як Caustics Generator , який має безкоштовну версію для некомерційного використання. Також є кілька попередньо виготовлених, які ви можете придбати за значно дешевше, ніж про версію інструменту, про який я згадав.

Зауважте, що їдкий вплив також є ефектом, що застосовується як легке печиво на підводній місцевості або на підводній поверхні. Тобто, розміщувати її на поверхні води, дивлячись вниз, це не нормально, як виглядає вода.


Це дуже цікаво, я також буду дивитись на цей генератор (хоча подія, я спробую варіант шейдера, якщо я це розумію ...)
morpheus05

4

Це схоже на текстуру, яку можна створити з графіка voronoi, наприклад:

введіть тут опис зображення

Ви можете зробити невеликі, плавні коригування графіка, переміщуючи точки; повторне малювання графіка кожен кадр буде досить дорогим, тому ви, швидше за все, хочете заздалегідь зробити анімацію.


4
Я фактично давав каустику таким чином у шейдері раніше. Це не обов'язково так дорого, як ви могли б подумати ( ось приклад рендерування країв Вороного в реальному часі в шейдері WebGL ), хоча отримання правильної гладкої форми на краях - а не точкових багатокутників - може бути складним.
DMGregory

Ооо, це дуже приємно; У мене є кілька генераторів місцевості, для яких це було б дуже зручно.
FacticiusVir

0

Існує метод старої школи, що включає нижній шар текстури та дві напівпрозорі текстури для відображення вгорі.

Якщо ви хочете пройти всю дорогу і хочете, щоб вода не виглядала повною клонованими хвилями або синьо-блакитними супами, схеми руху досягають мети.

https://steamcdn-a.akamaihd.net/apps/valve/2010/siggraph2010_vlachos_waterflow.pdf


3
Хоча посилання можуть допомогти, вони ніколи не дають хороших відповідей. Чи можете ви розширити обидва ці тези? Як би йшлося про його реалізацію?
Vaillancourt

Перший метод - це в основному дуже старий метод, який використовується для анімування води - ви берете текстуру води базового шару, котрий координати UVW зміщуються у вибраному вами напрямку. Тепер ви застосуєте на додаток звичайну карту / нерівну карту, яку ви переміщуєте в інший бік - якщо це зроблено добре, це виглядає переконливо для малих річок. Він дуже обмежений, хоча для великих водойм - як би все, що перебирає хвилі, отримає ефект муару. Посилання пояснює використання потокових карт далекіше, ніж я міг би.
Піка

Будь ласка, використовуйте функцію редагування, щоб поліпшити питання щодо того, що ви тут додали :) Люди звикли шукати відповіді у публікації, а не в коментарях.
Vaillancourt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.