Comment implémenter ce type d'ondulations avec un shader de fragments GLSL?

11

J'ai donc déjà implémenté la partie réflexion:

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;
}
}

la source

Maintenant, la question est de savoir comment ces ondulations sont mises en œuvre?

cepro
la source
3
Ce n'est pas une réponse complète, mais une série d'indices: vous avez besoin d'un uniforme pour "animer" l'effet - c'est-à-dire une variable temporelle. En utilisant cette timevaleur, vous pouvez déplacer le uv.xyavec un (sin(time),cos(time))vecteur de décalage. Bien sûr, vous devez déterminer les amplitudes des décalages sinus et cosinus. Je commencerais par juste compenser le uv.ypremier et voir comment je peux ajuster davantage l'effet.
teodron
Merci beaucoup pour ces conseils. Il s'est avéré que c'est ce dont j'avais besoin après avoir essayé l'implémentation de @ LeFauve.
cepro

Réponses:

11

J'ai essayé de mettre en œuvre ce que teodron a suggéré:

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;
    }
}

Il semble assez proche (c'est difficile à dire sans l'image de base) mais vous pouvez modifier les paramètres.

Vous pouvez le voir en action là: https://www.shadertoy.com/view/Xll3R7

Quelques remarques:

  • J'ai dû inverser la coordonnée y depuis que j'obtenais l'image à l'envers, mais cela peut dépendre de ce que vous passez dans resolution.xy; si le résultat est inversé pour vous, décochez simplement uv.y
  • J'ai changé vos déclarations d'uniformes pour qu'elles fonctionnent avec shadertoy. Vous pouvez ignorer ces modifications.
  • Vous devrez cependant ajouter un uniforme fournissant l'heure et l'utiliser à la place de iGlobalTime (qui est le temps en secondes)
  • J'ai ajouté un effet de marée car il semble qu'il y en ait un sur votre exemple mais c'est difficile à dire (voir variable sepoffset). Vous pouvez le supprimer si vous ne l'aimez pas
  • J'ai supprimé la couleur de superposition car elle ne semblait pas bonne et votre exemple n'en avait pas
  • Pour ajuster l'effet à votre goût:
    • changer le facteur d'iGlobalTime pour accélérer / ralentir l'effet (vous pouvez changer chacun d'eux séparément si vous voulez, disons accélérer le mouvement x et ralentir le mouvement y)
    • changer le facteur cos () pour amplifier / atténuer l'effet

EDIT: j'ai changé le yoffset pour inclure la modification de @cepro

LeFauve
la source
1
Grand effort! +1
teodron
3
Merci de votre aide :). Cela donne vraiment un résultat assez serré. Mais je pense qu'il manque un dernier ingrédient. Notez, dans l'image, que plus ces ondulations sont proches de la caméra (en bas de l'écran), plus elles sont grandes (étirées verticalement). Alors peut-être que nous devons mettre à l'échelle le décalage y par le uv.y? float yoffset = ((0,3 - uv.y) /0,3) * 0,05 * (1,0 + cos (iGlobalTime * 3,0 + 50,0 * uv.y)) ;. J'ai essayé cela et j'aime un peu le résultat.
cepro
Bonne prise pour les ondulations plus proches @cepro. Je l'ai manqué
LeFauve
OMI, il y a quelque chose qui ne va pas avec le modèle de vague modifié. Alors que les vagues augmentent pour moi, elles ont ce motif étrange "en miroir" (GTX 680 dans le dernier Chrome).
Mario