GLSL 着色器:极坐标中的映射条
GLSL Shader: Mapping Bars in Polar-Coordinates
我想创建此着色器的极坐标表示:https://www.shadertoy.com/view/4sfSDN
所以它看起来像这个截图:
http://postimg.org/image/uwc34jxxz/
我知道极坐标系的基础知识:如何计算 r 和 ϕ,但我只能将这些值与图像上的 texture2d() 加载函数一起使用。
当我只有上面着色器中的振幅值时,我无法正常工作。
r 应该以某种方式基于幅度,但是我不知道如何在没有 texture2d() 函数的情况下绘制圆...我只能用 r 绘制圆,但是没有不同的幅度。或者我什至需要用循环中生成的条形图填充矩阵并从那里加载圆圈?
我很确定这是可能的,因为 shadertoy 上有疯狂的着色器,但我不太明白...
谁能指出我的解决方案?
根据您发布的着色器,我认为只需将 uv
转换为极坐标就足够了。
所以你要找的是距中心的角度和半径。首先让我们变换 uv
使其给出从中心指向的向量:
uv = fragCoord - (iResolution*.5);
接下来尝试将其归一化。由于视图不是正方形,因此归一化变换应该仅按 1 个坐标进行
if(iResolution.x>iResolution.y)
{
uv = uv/iResolution.y;
}
else
{
uv = uv/iResolution.x;
}
这会产生一种适合的效果,但如果需要,您可以硬编码一个或另一个。如果可用 (uv = uv/min(iResolution.x, iResolution.y))
),可以使用 min
来删除条件。
所以此时 uv
向量从中心指向在一维归一化的坐标系中的像素位置。
现在要获得角度,您可以简单地使用 atan(uv.y, uv.x)
。要获得半径,您需要 length(uv)
。
您的情况下的半径将针对 [0, .5] 范围内的较短维度,因此您可以将其乘以 2.0,但这是一个您稍后可以更改以获得所需效果的因素,以便最大值没有达到边界,但可能有 80% 左右(随便玩玩)。
角度在 [-Pi, Pi] 范围内,而且在文档中它说它不适用于 X = 0
,您需要自己处理。所以现在必须将角度转换到 [.0, 1.0] 范围内才能访问纹理坐标:
angle = angle/(Pi*2.0) + .5
所以现在构造新的uv
uv = vec2(angle, radius)
并使用与之前相同的着色器。
您还需要记住,拐角处的半径可能大于 1.0,这可能会产生错误的纹理访问。在这种情况下,最好丢弃片段。
来自着色器玩具:
#define M_PI 3.1415926535897932384626433832795
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy - (iResolution.xy*.5);
uv = uv/min(iResolution.x, iResolution.y);
float angle = atan(uv.y, uv.x);
angle = angle/(M_PI*2.0) + .5;
float radius = length(uv);
uv = vec2(angle, radius*2.0);
float bars = 24.;
float fft = texture2D( iChannel0, vec2(floor(uv.x*bars)/bars,0.25) ).x;
float amp = (fft - uv.y)*100.;
fragColor = vec4(amp,0.,0.,1.0);
}
我想创建此着色器的极坐标表示:https://www.shadertoy.com/view/4sfSDN
所以它看起来像这个截图: http://postimg.org/image/uwc34jxxz/
我知道极坐标系的基础知识:如何计算 r 和 ϕ,但我只能将这些值与图像上的 texture2d() 加载函数一起使用。
当我只有上面着色器中的振幅值时,我无法正常工作。
r 应该以某种方式基于幅度,但是我不知道如何在没有 texture2d() 函数的情况下绘制圆...我只能用 r 绘制圆,但是没有不同的幅度。或者我什至需要用循环中生成的条形图填充矩阵并从那里加载圆圈?
我很确定这是可能的,因为 shadertoy 上有疯狂的着色器,但我不太明白... 谁能指出我的解决方案?
根据您发布的着色器,我认为只需将 uv
转换为极坐标就足够了。
所以你要找的是距中心的角度和半径。首先让我们变换 uv
使其给出从中心指向的向量:
uv = fragCoord - (iResolution*.5);
接下来尝试将其归一化。由于视图不是正方形,因此归一化变换应该仅按 1 个坐标进行
if(iResolution.x>iResolution.y)
{
uv = uv/iResolution.y;
}
else
{
uv = uv/iResolution.x;
}
这会产生一种适合的效果,但如果需要,您可以硬编码一个或另一个。如果可用 (uv = uv/min(iResolution.x, iResolution.y))
),可以使用 min
来删除条件。
所以此时 uv
向量从中心指向在一维归一化的坐标系中的像素位置。
现在要获得角度,您可以简单地使用 atan(uv.y, uv.x)
。要获得半径,您需要 length(uv)
。
您的情况下的半径将针对 [0, .5] 范围内的较短维度,因此您可以将其乘以 2.0,但这是一个您稍后可以更改以获得所需效果的因素,以便最大值没有达到边界,但可能有 80% 左右(随便玩玩)。
角度在 [-Pi, Pi] 范围内,而且在文档中它说它不适用于 X = 0
,您需要自己处理。所以现在必须将角度转换到 [.0, 1.0] 范围内才能访问纹理坐标:
angle = angle/(Pi*2.0) + .5
所以现在构造新的uv
uv = vec2(angle, radius)
并使用与之前相同的着色器。
您还需要记住,拐角处的半径可能大于 1.0,这可能会产生错误的纹理访问。在这种情况下,最好丢弃片段。
来自着色器玩具:
#define M_PI 3.1415926535897932384626433832795
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy - (iResolution.xy*.5);
uv = uv/min(iResolution.x, iResolution.y);
float angle = atan(uv.y, uv.x);
angle = angle/(M_PI*2.0) + .5;
float radius = length(uv);
uv = vec2(angle, radius*2.0);
float bars = 24.;
float fft = texture2D( iChannel0, vec2(floor(uv.x*bars)/bars,0.25) ).x;
float amp = (fft - uv.y)*100.;
fragColor = vec4(amp,0.,0.,1.0);
}