Come implementare questo tipo di increspature con uno shader di frammenti GLSL?


11

Quindi ho già implementato la parte di riflessione:

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

fonte

Ora la domanda è: come vengono implementate queste increspature?


3
Questa non è una risposta completa, ma una serie di suggerimenti: è necessaria un'uniforme per "animare" l'effetto, ovvero una variabile simile al tempo. Usando quel timevalore, puoi spostare il uv.xycon un (sin(time),cos(time))vettore di offset. Naturalmente, è necessario capire le ampiezze degli offset seno e coseno. Comincerei con l'offset del uv.yprimo e vedo come posso regolare ulteriormente l'effetto.
teodron,

Grazie mille per questi suggerimenti. Si è scoperto che questo è ciò di cui ho bisogno dopo aver provato l'implementazione di @ LeFauve.
cepro,

Risposte:


11

Ho cercato di attuare ciò che teodron ha suggerito:

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

Sembra abbastanza vicino (è difficile da dire senza l'immagine di base) ma puoi modificare i parametri.

Puoi vederlo in azione qui: https://www.shadertoy.com/view/Xll3R7

Alcune osservazioni:

  • Ho dovuto invertire la coordinata y poiché stavo capovolgendo l'immagine, ma potrebbe dipendere da ciò che passi in risoluzione.xy; se il risultato è invertito per te, basta invertire uv.y
  • Ho cambiato le tue dichiarazioni uniformi in modo che funzioni con shadertoy. Puoi ignorare queste modifiche.
  • Dovrai tuttavia aggiungere un'uniforme che fornisca il tempo e utilizzarlo al posto di iGlobalTime (che è il tempo in secondi)
  • Ho aggiunto un effetto di marea poiché sembra che ce ne sia uno nel tuo esempio ma è difficile da dire (vedi la variabile sepoffset). Puoi rimuoverlo se non ti piace
  • Ho rimosso il colore di sovrapposizione poiché non sembrava buono e il tuo esempio non ne aveva uno
  • Per modificare l'effetto secondo i tuoi gusti:
    • cambia il fattore di iGlobalTime per accelerare / rallentare l'effetto (puoi cambiarli separatamente se vuoi, diciamo accelerare il movimento xe rallentare il movimento y)
    • cambia il fattore cos () per amplificare / attenuare l'effetto

EDIT: ho cambiato yoffset per includere la modifica da @cepro


1
Grande sforzo! +1
teodron,

3
Grazie per l'aiuto :). Questo dà davvero un risultato abbastanza vicino. Ma penso che manchi un ultimo ingrediente. Si noti, nella foto, che più si avvicinano quelle increspature alla fotocamera (parte inferiore dello schermo), più sono grandi (allungate verticalmente). Quindi forse dobbiamo ridimensionare l'offset y di uv.y? float yoffset = ((0.3 - uv.y) /0.3) * 0.05 * (1.0 + cos (iGlobalTime * 3.0 + 50.0 * uv.y)) ;. Ho provato questo e mi piace un po 'il risultato.
cepro,

Buona cattura per le increspature più vicine @cepro. L'ho perso
LeFauve il

IMO c'è qualcosa che non va nel pettern d'onda modificato. Mentre le onde aumentano per me, hanno quello strano modello "specchiato" (GTX 680 nell'ultimo Chrome).
Mario
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.