它是如何从 3 行转换为 1 行代码的?在着色器中重新映射 uv 并修复纵横比

How did it get converted into 1 line of code from 3 lines? Remapping uv and fixing aspect ratio in shaders

提问人:Artyom Chernyaev 提问时间:5/16/2023 最后编辑:Yakov GalkaArtyom Chernyaev 更新时间:6/10/2023 访问量:33

问:

你会如何从中得到

vec2 uv = fragCoord/iResolution.xy; // <0, 1>
uv -= 0.5; // <-0.5,0.5>
uv.x *= iResolution.x/iResolution.y; // fix aspect ratio

到这个?

vec2 uv = (fragCoord - .5 * iResolution.xy) / iResolution.y; // Condense 3 lines down to a single line!

好吧,我试着把它分解成组件

((fragCoord.x-0.5) / iResolution.x) * (iResolution.x / iResolution.y)

((fragCoord.y-0.5) / iResolution.y)

数学 矢量 GLSL 着色器 VEC

评论

0赞 Mike 'Pomax' Kamermans 5/16/2023
你为什么需要?除了“更难阅读”(与有用相反)之外,单行文字解决了三行问题吗?
0赞 Artyom Chernyaev 5/16/2023
我只是好奇它是如何被压缩成一行的。好吧,单行少用一个除法。(我认为这很好?
0赞 Mike 'Pomax' Kamermans 5/16/2023
它没有,他们做不同的事情。这三条线仅通过在末尾缩放来固定纵横比,单行线根据它来缩放整个 vec2,因此它同时更改了 和 ,并变为 1。xyxyy
1赞 Yakov Galka 6/10/2023
@Mike'Pomax'Kamermans:这实际上不是真的。这两个代码段是等效的。请参阅我的答案中的推导。

答:

2赞 Yakov Galka 6/10/2023 #1

让我们添加第 4 行:

vec2 uv = fragCoord/iResolution.xy;
uv -= 0.5;
uv.x *= iResolution.x/iResolution.y;
uv.y *= iResolution.y/iResolution.y;

请注意,因此我们添加的行不会更改任何内容。但是,它提供了简化代码的可能性。现在,我们可以通过对双分量向量进行操作来组合第 3 行和第 4 行:iResolution.y/iResolution.y == 1

vec2 uv = fragCoord/iResolution.xy;
uv -= 0.5;
uv *= iResolution.xy/iResolution.y;

将它们组合成一个代数表达式,将其转换为:

vec2 uv = (fragCoord/iResolution.xy - 0.5)*iResolution.xy/iResolution.y;

现在我们可以进入括号(乘法分配律):iResolution.xy

vec2 uv = (fragCoord/iResolution.xy*iResolution.xy - 0.5*iResolution.xy)/iResolution.y;

而且,当然,除以抵消与乘以 ,因此我们得出了您拥有的一个衬里:fragCoordiResolution.xyiResolution.xy

vec2 uv = (fragCoord - 0.5*iResolution.xy)/iResolution.y;