Як реалізувати цей тип пульсацій за допомогою шейдера фрагмента GLSL?


11

Тому я вже реалізував частину рефлексії:

uniform sampler2D texture;
uniform vec2 resolution;
uniform vec3 overlayColor;

void main()
{
vec2 uv = gl_FragCoord.xy / resolution.xy;

if (uv.y > 0.3)// is air - no reflection or effect
{
    gl_FragColor = texture2D(texture, vec2(uv.x, uv.y));
}
else
{
    // Compute the mirror effect.
    vec4 color = texture2D(texture, vec2(uv.x, 0.6 - uv.y));
    // 
    vec4 finalColor = vec4(mix(color.rgb, overlayColor, 0.25), 1.0);
    gl_FragColor = finalColor;
}
}

джерело

Тепер питання в тому, як реалізуються ці брижі?


3
Це не повна відповідь, а ряд підказок: вам потрібна уніформа, щоб "оживити" ефект - тобто змінну за часом. З допомогою цього timeзначення можна змістити uv.xyз (sin(time),cos(time))вектором зміщення. Звичайно, ви повинні з'ясувати амплітуди зміщення синуса і косинуса. Я б почав із простого компенсації uv.yпершого та побачив, як я можу далі коригувати ефект.
теодрон

Дуже дякую за ці підказки. Виявилося, що це мені потрібно після спроби реалізації @ LeFauve.
cepro

Відповіді:


11

Я намагався реалізувати те, що запропонував теодрон:

void main()
{
    vec2 uv = gl_FragCoord.xy / resolution.xy;
    float sepoffset = 0.005*cos(iGlobalTime*3.0);
    if (uv.y > 0.3 + sepoffset)// is air - no reflection or effect
    {
        gl_FragColor = texture2D(texture, vec2(uv.x, -uv.y));
    }
    else
    {
        // Compute the mirror effect.
        float xoffset = 0.005*cos(iGlobalTime*3.0+200.0*uv.y);
        //float yoffset = 0.05*(1.0+cos(iGlobalTime*3.0+50.0*uv.y));
        float yoffset = ((0.3 - uv.y)/0.3) * 0.05*(1.0+cos(iGlobalTime*3.0+50.0*uv.y));
        vec4 color = texture2D(texture, vec2(uv.x+xoffset , -1.0*(0.6 - uv.y+ yoffset)));
        // 
        //vec4 finalColor = vec4(mix(color.rgb, overlayColor, 0.25), 1.0);
        gl_FragColor = color;
    }
}

Це виглядає досить близько (важко сказати без базового зображення), але ви можете налаштувати параметри.

Ви можете побачити його в дії там: https://www.shadertoy.com/view/Xll3R7

Деякі зауваження:

  • Мені довелося перевернути координату y, оскільки я отримував зображення догори дном, але це може залежати від того, що ви переходите в резолюцію.xy; якщо результат інвертований для вас, просто видаліть uv.y
  • Я змінив ваші єдині декларації, так що це працює з shadertoy. Ви можете проігнорувати ці зміни.
  • Однак вам потрібно буде додати уніформу, яка надає час, і використовувати її замість iGlobalTime (це час у секундах)
  • Я додав ефект відливу, оскільки, схоже, є такий на вашому прикладі, але це важко сказати (див. Змінну sepoffset). Ви можете видалити його, якщо він вам не сподобається
  • Я видалив колір накладення, оскільки він виглядає не дуже добре, і у вашому прикладі його не було
  • Щоб налаштувати ефект на свій смак:
    • змінити коефіцієнт iGlobalTime для прискорення / уповільнення ефекту (ви можете змінити кожен з них окремо, якщо хочете, скажімо, прискорити рух x і сповільнити рух y)
    • змінити коефіцієнт cos (), щоб посилити / послабити ефект

EDIT: Я змінив yoffset, щоб включити модифікацію від @cepro


1
Велике зусилля! +1
теодрон

3
Дякую за твою допомогу :). Це дійсно дає досить близький результат. Але я думаю, що в ньому відсутній останній інгредієнт. Зауважте на малюнку, що чим ближче ці брижі до камери (у нижній частині екрана), тим вони більше (вертикально розтягнуті). То, можливо, нам потрібно масштабувати зсув y на uv.y? float yoffset = ((0,3 - uv.y) /0,3) * 0,05 * (1,0 + cos (iGlobalTime * 3,0 + 50,0 * uv.y)); Я спробував це, і мені якось подобається результат.
cepro

Хороший улов для ближчих пульсацій @cepro. Я пропустив це
LeFauve

В IMO щось не так з модифікованою хвилею. Хоча хвилі збільшуються для мене, у них є такий дивний "дзеркальний" візерунок (GTX 680 в останніх Chrome).
Маріо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.