shader 中的坐标系修正

384 阅读3分钟

前言

我们之前提到过——坐标修正的概念。但只是一笔带过。今天我们来详细了解下坐标修正。话不多说,直接开始。

c1c849bb65f4d96a.jpg

什么是坐标修正

我们在前面文章的 shader 编写中,都进行了坐标修正。即以下代码:

    vec2 uv =fragCoord/iResolution.xy; //坐标除以画布大小得到归一化uv坐标
    // uv 居中
    uv=(uv*2.)-1.0;
    uv.x*=iResolution.x/iResolution.y; // 修正uv坐标未自动适应画布比例的问题

从代码中,我们不难看出,我们进行了以下操作:

  1. 得到 uv 坐标,uv 坐标的范围为[0-1]
  2. 将 uv 坐标系的原点移到中心点
  3. 修正坐标系的比例

所以,我们可以知道,坐标修正即是对坐标系进行以上三个步骤。

详解坐标修正

我们接下来详细解释下,为何上述三步可以达到坐标修正的目的?

uv 坐标

uv 坐标:输入坐标fragCoord除以画布大小iResolution.xy,我们就能得到一个归一化的坐标,把它命名为uv,所以,我们使用 vec2 uv =fragCoord/iResolution.xy;可以得到我们的 uv 坐标,x,y 的范围都在[0,1]之间。

以下为 uv 坐标可视化的图片:

image.png

原点居中

我们先来看原点未居中的 uv 的图片: image.png

再来看看我们原点居中了的 uv 的图片: image.png

为何uv=(uv*2.)-1.0能实现原点居中的效果呢?我们来仔细分析下:

  1. uv*2.0——我们的 uv 范围变成了[0,2]
  2. (uv*2.)-1.0——我们的 uv 范围变成了[-1,1],这时候,我们的原点在(0,0)点,并且(0,0)点为中心点

画布比例修正

画布比例修正:uv.x*=iResolution.x/iResolution.y;,是三步中相对最难理解的点。我将会画图解释,希望讲解清楚。

我们为什么要进行画布比列修正呢?

当我们在一个16:9的屏幕上使用 shader 绘制一个圆:

image.png

为什么会这样呢?——这是因为我们画布的宽高不相等,所以,我们x轴和y轴上的一个单位代表的长度不一样

image.png

我们可以看到,取相同刻度,x轴上长度大于y轴上长度,所以,我们画出来的圆会是一个椭圆。

那我们怎么得到一个圆呢?——uv.x*=iResolution.x/iResolution.y;

为什么这样做就可以得到一个圆呢?

  1. 在宽屏情况下,iResolution.x/iResolution.y > 1

  2. uv.x*=iResolution.x/iResolution.y;——使得uv.x变大了,x轴上每个刻度代表的值变大了,即:r=0.5,之前我在x轴上取0.5需要两个刻度,现在我可能就只需要1个刻度。这样就使得我们的图形比例跟y轴保持一致了

image.png

我们可以看到,蓝色的刻度便是原来代表(1,0)和(-1,0)的刻度,现在它们已经是(2,0)和(-2,0)了。这样我们取r=0.5,便只需要之前的1/4个刻度了便可以了。x轴上的图案便被按照相应比例缩小了

总结

以上便是坐标修正的全部内容了,如有错误之处,欢迎大家留言指出,谢谢大家了。