remap字面意思为重映射,它将值从一个范围重映射到另一个范围。该算法不属于shader api的一部分,但是在实际开发中又显得很重要。
上图演示的是用remap算法把uv的横纵坐标从01范围转变为-11范围(UV坐标从左下角开始计算),remap算法与smoothstep算法(可参考Shader实验室:smoothstep函数一节)中的某一部分计算方式有点类似,下面我们进入原理部分。
原理
要介绍remap算法,就不得不先介绍下它的公式。
remap算法公式: y = (x - t1) / (t2 - t1) * (s2 - s1) + s1。
先分析其前半部分: y = (x - t1) / (t2 - t1)。
假设 t2 = 0.7, t1 = - 0.8 代入至公式中,可得:
y = (x - (-0.8)) / (0.7 - (-0.8)),从代入式可知:
当 x = -0.8 时,y = 0;
当 x = 0.7 时,y = 1;
根据结论我们作图如下:
根据求取的结果与示意图,我们可得出如下结论:
当x = t1时,y = 0;
当x = t2时,y = 1;
该结论很重要,它可以使我们很容易在思考该类问题时,在大脑中建立抽象的坐标系,这让我们处理图形图像相关问题时显得更加得心应手。
前半部分的计算我们已经分析完毕了,其实这部分算法也是remap算法,因为它已经能让我们达到重映射的目的了。接下来我们结合整个公式进行分析,分析方式还是以代入数字的方式进行。
对 y = (x - t1) / (t2 - t1) * (s2 - s1) + s1 公式进行数字代入。
假设 t2 = 0.7,t1 = -0.8保持不变,令s2 = 0.3,s1 = 0.2待入至公式得:
y = (x - (-0.8)) / (0.7 - (-0.8)) * (0.3 - 0.2) + 0.2。
根据代入结果,作图如下:
可得结果:
当 x = -0.8时,y = 0.2;
当 x = 0.7 时, y = 0.3;
也就是,
当 x = t1 时,y = s1;
当 x = t2 时,y = s2;
根据分析结果,下面进入实验部分,我们会做出文章开头那张图片的效果,并对其进行进一步处理。
实验
- 首先新建Shader与材质文件,Shader文件选择Unlit类型。
- 在Shader Pass内部定义remap函数,如下:
half remap(half x, half t1, half t2, half s1, half s2)
{
return (x - t1) / (t2 - t1) * (s2 - s1) + s1;
}
- 在Pass中的frag函数进行如下操作:
fixed4 frag (v2f i) : SV_Target
{
//当uv.x = 0时,结果等于 s1 = -1
//当uv.x = 1.0时,结果等于 s2 = 1
half remapX = remap(i.uv.x, 0, 1.0, -1.0, 1.0);
//当uv.y = 0时,结果等于 s1 = -1
//当uv.y = 1.0时,结果等于 s2 = 1
half remapY = remap(i.uv.y, 0, 1.0, -1.0, 1.0);
return float4(remapX, remapX, 0, 1);
}
- 完成Shader代码,赋值该Shader到新建的材质,并把该材质赋予Quad
- 得到的结果如下:
感兴趣的小伙伴可扫描下方二维码关注我们。