Как въехать в трансформации пространства

В школе мы проходили графики разных функций, например, параболы: y = x². Я никак не мог понять, почему при увеличении x, например y = (x + 1)² график сдвигается влево. Интуиция говорила, что должен вправо сдвигаться!

Дальше хуже: оказалось, что при умножении икса y = (2x)² график не растягивается вдоль оси x а наоборот, сужается.

Если не верите, проверьте сами.

Когда начал копать шейдеры, оказалось, что школьные проблемы до сих пор не решены. Поэтому первый год я подбирал нужный оператор методом тыка: плюс не помог, окей, поставим минус.

Сейчас, вроде, разобрался, сейчас расскажу.

Возьмём шейдер, который рисует кружочек:

precision highp float;
uniform vec2 resolution;
out vec4 outColor;

void main(){
  vec2 uv=(gl_FragCoord.xy*2.-resolution)/resolution.y*2.; // find UV coordinates of a pixel
  outColor.rg+=fract(uv); // draw grid while space is not transformed yet
  outColor.b=1.; // nice colors!
  
  // TRANSFORMATIONS WILL BE HERE
  
  outColor+=step(length(uv),1.); // draw circle in transformed space
  // it's like pixel is saying “if my distance to the origin is less than 1, I go white”
}

bit.ly/3OP90VN

Действительно, uv*=2.; уменьшает картинку:

https://bit.ly/3PbJyK9

а uv/=2.; растягивает её:

https://bit.ly/3yKkCDU

Аналогично uv.x += 1.;. сдвигает график влево, а uv.x -= 1. — вправо. Где логика, где разум?

На какое-то время я думал, что нашёл спасение в вот такой формулировке:

Когда мы трансформируем координаты, мы меняем не картинку а пространство. Например, если делаем uv*=2.;, все изменения в пространстве начинают происходить в два раза быстрее, вот кружок и уменьшается.

Но пользоваться такой мыслью при программировании было сложно. Наконец придумалась более удобная:

Когда мы меняем координаты точки, она начинает притворяться другой точкой с новыми координатами.

Допустим, пиксель. Вычисляем его uv координаты и получаем (0, 0.5). После умножения каждого компонента на 2 этот пиксель притворится точкой (0, 1), а это правый край нашей единичной окружности. Значит наш пиксель этот край и покажет.

Получилось, что край окружности стал в два раза ближе к центру, чем был бы без трансформации.

Упражнения: Возьмите исходный шейдер с кружком и добавьте трансформацию, чтобы окружность:

  • сдвинулась вниз на 1.;
  • скукожилась по оси y в 4 раза;
  • стала с радиусом 0.5 и с центром в (0.5, 0.5)

Что думаете про такой способ думать о трансформациях пространства? Что осталось непонятным? А может, вы знаете, как проще трансформации объяснить? Расскажите тут в комментариях или напишите мне в телеграм.