Использование шейдера для перемещения текселя в центр

Я пытаюсь переместить квадрат текстуры текселя в центр текстуры в следующий раз. Следующий код выполняет эту работу, если я не хочу, чтобы пиксель был обрамлен, когда он достиг центра геометрии (плоскости), и на данный момент он становится все более маленьким, а время увеличивается, а текстура кажется сжатой.

enter image description here

uniform float time;
varying vec2 vUv;

void main() {

    vec2 center = vec2(0.5, 0.5);
    vec2 newPosition = vec2(vUv.x + t * (center.x - vUv.x), vUv.y + t * (center.y - vUv.y);

    gl_FragColor = texture2D( texture, vec2(newPosition.x, newPosition.y) );
}

Изменить:

Подумайте об этом как о черной дыре в центре текстуры. enter image description here

Ответ 1

Как я понимаю, вы хотите, чтобы texel находился в vUv, когда t=0 и через center через некоторое время.

Результат - это увеличение по центру текстуры.

На самом деле ваш код делает это от t = 0 до t = 1. Когда t = 1 положение текселя center.

У вас такое же поведение, используя функцию mix.

vec2 newPosition = mix(vUv, center, t);

Также, когда t = 1 все, тексель находится в center, и изображение представляет собой одноцветное изображение. (Цвет центра текстуры).

Ваша проблема в том, что t продолжает расти. И когда t > 1 тексель продолжается на своем пути. После того, как все они встречаются в центре, теперь они отклоняются друг от друга. Эффект заключается в том, что текстура меняется на противоположную, и вы видите уменьшение.

В зависимости от того, как вы хотите, чтобы это закончилось, есть несколько решений:

  • Вы хотите перейти к максимальному масштабированию и сохранить это изображение: clamp t в диапазоне [0, 1] как это t = clamp(t, 0, 1);.

  • Вы хотите перейти к максимальному масштабированию, и изображение исчезнет: прекратите рисовать его, когда t > 1 (или t >= 1, если вы не хотите одиночного цветного изображения).

  • Вы хотите бесконечное масштабирование, т.е. тексель приближается и приближается к центру, но никогда не достигает его.

Для этого третьего поведения вы можете использовать новый t, скажем t2:

  • t2 = 1 - 1/(t*k+1); // Where k > 0
  • t2 = 1 - pow(k, -t); // Where k > 1
  • t2 = f(t); // Where f(0) = 0, f is increasing, continuous and limit in +∞ is 1

Ответ 2

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

float time = -u_time * 0.15;
vec2 p = 2.0 * gl_FragCoord.xy / u_res.xy -1.0;
vec2 uv;

float a = atan(p.y,p.x);
float r = sqrt(dot(p,p));
uv.x = time+.1/r;
uv.y = a/3.1416;

vec4 bg = texture2D(u_texture, uv);

Я надеюсь, что это будет полезно.