GLSL Shader: Mapping Bars in Polar-Coordinates

时间:2015-09-01 22:58:37

标签: opengl-es fragment-shader polar-coordinates

I'd like to create a polar representation of this shader: https://www.shadertoy.com/view/4sfSDN

So that it looks like in this screenshot: http://postimg.org/image/uwc34jxxz/

I know the basics of the polar-system: How to calculate r and ϕ, but i can only use those values with a texture2d() load function on a image.

When i only have a amplitude value like in the shader above, i dont get it working.

r should somehow be based of the amplitude, but then i dont know how to draw the circle without the texture2d() function... i can draw a circle with r only, but then there are no different amplitudes. Or do i even need to fill a matrix with the generated bars in a loop and load the circle from there?

Im quite sure it is possible, because of the insane shaders on shadertoy, but i dont quite get it... Can anyone point me out to a solution?

1 个答案:

答案 0 :(得分:0)

从你发布的着色器中我认为只需将uv转换为极坐标即可。

所以你要找的是距离中心的角度和半径。首先让我们转换uv,以便它给出从中心指向的矢量:

uv = fragCoord - (iResolution*.5);

接下来尝试将其标准化。由于视图不是正方形,因此归一化变换应仅为1坐标,以便

if(iResolution.x>iResolution.y)
{
   uv = uv/iResolution.y;
}
else
{
   uv = uv/iResolution.x;
}

这会产生合适的效果,但如果需要,您可能只需硬编码一个或另一个。如果可用(min),可以使用uv = uv/min(iResolution.x, iResolution.y))来删除条件。

因此,此时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);
}