【问题标题】:GLSL ES - Mapping texture from rectangular to polar coordinates with repeatingGLSL ES - 将纹理从矩形映射到极坐标并重复
【发布时间】:2014-09-19 10:47:27
【问题描述】:

我需要将矩形纹理扭曲为具有极坐标的纹理。为了阐明我的问题,我将对其进行说明:

我有图片:

我必须使用着色器将其变形为如下所示:

然后我要把它映射到飞机上。 我怎样才能做到这一点?任何帮助将不胜感激!

【问题讨论】:

    标签: libgdx glsl opengl-es-2.0 shader glsles


    【解决方案1】:

    这并不是特别难。您只需要将纹理坐标转换为极坐标,并使用纹理的s 方向的半径和t 方向的方位角。

    假设您想以这种方式对四边形进行纹理化,并假设您为此使用标准 texcoords,因此左下角的顶点将具有 (0,0),右上角的顶点 (1,1) 作为纹理坐标。

    所以在片段着色器中,您只需将插值的 texcoords(为此使用tc)转换为极坐标。因为中心将在 (0.5, 0.5),我们必须先将其偏移。

     vec2 x=tc - vec2(0.5,0.5);
     float radius=length(x);
     float angle=atan(x.y, x.x);
    

    现在您需要做的就是将范围映射回 [0,1] 纹理空间。这里的最大半径为 0.5,因此您可以简单地使用 2*radius 作为 s 坐标,角度将在 [-pi,pi] 中,因此您应该将 @987654327 映射到 [0,1] @坐标。

    更新1

    到目前为止,我遗漏了一些细节。从您的图像中可以清楚地看出,您不希望将内圈映射到纹理。但这很容易被合并。我在这里只假设两个半径:r_inner,它是内圆的半径,以及 r_outer,它是你想要映射到外部的半径。让我为此画一个简单的片段着色器:

    #version ...
    precision ...
    
    varying vec2 tc; // texcoords from vertex shader
    uniform sampler2D tex;
    
    #define PI 3.14159265358979323844
    
    void main ()
    {
        const float r_inner=0.25; 
        const float t_outer=0.5; 
    
        vec2 x = v_tex - vec2(0.5);
        float radius = length(x);
        float angle = atan(x.y, x.x);
    
        vec2 tc_polar; // the new polar texcoords
        // map radius so that for r=r_inner -> 0 and r=r_outer -> 1
        tc_polar.s = ( radius - r_inner) / (r_outer - r_inner);
    
        // map angle from [-PI,PI] to [0,1]
        tc_polar.t = angle * 0.5 / PI + 0.5;
    
        // texture mapping
        gl_FragColor = texture2D(tex, tc_polar);
    }
    

    现在还缺少一个细节。上面生成的映射会为图像中有黑色的任何位置生成超出 [0,1] 范围的 texcoords。但是这里的纹理采样不会自动给黑色。最简单的解决方案是对GL_TEXTURE_WRAP_S 使用GL_CLAMP_TO_BORDER 模式(默认边框颜色为(0,0,0,0),因此您可能不需要指定它,或者您可以将GL_TEXTURE_BORDER_COLOR 显式设置为(0,0,0,1),如果您工作使用 alpha 混合并且不想要任何透明度)。这样,您将免费获得黑色。其他选项是使用GL_CLAMP_TO_EDGE 并在纹理的左端和右端添加一个黑色像素列。另一种方法是在着色器中添加一个分支并检查 tc_polar.s 是否低于 0 或高于 1,但我不建议在这个用例中这样做。

    【讨论】:

    • 您知道如何更改此着色器以从段中生成结果吗?所以,我需要重复给定的纹理,而不是拉伸。
    • @Nolesh:你能详细说明一下吗?你到底想重复什么?
    • 我需要添加圈子组成的段数。例如,我为这个计数分配了 180。因此,整个纹理每 2 度拉伸一次。这个过程重复 180 次,而整个圆圈没有被填满。通过此操作,我希望提高分辨率 t
    • @Nolesh:因此,如果我做对了,您只需将纹理沿 t 维度重复 180 次,以获得整个圆。所以你所要做的就是将GL_TEXTURE_WRAP_T模式设置为GL_REPEAT并将t纹理坐标(现在在[0,1]中)乘以180。
    • 这正是我想要的!非常感谢!
    【解决方案2】:

    对于那些想要更灵活的着色器的人来说:

    uniform float Angle; // range 2pi / 100000.0 to 1.0 (rounded down), exponential
    uniform float AngleMin; // range -3.2 to 3.2
    uniform float AngleWidth; // range 0.0 to 6.4
    uniform float Radius; // range -10000.0 to 1.0
    uniform float RadiusMin; // range 0.0 to 2.0
    uniform float RadiusWidth; // range 0.0 to 2.0
    uniform vec2 Center; // range: -1.0 to 3.0
    
    uniform sampler2D Texture;
    
    void main()
    {
        // Normalised texture coords
        vec2 texCoord = gl_TexCoord[0].xy;
        // Shift origin to texture centre (with offset)
        vec2 normCoord;
        normCoord.x = 2.0 * texCoord.x – Center.x;
        normCoord.y = 2.0 * texCoord.y – Center.y;
        // Convert Cartesian to Polar coords
        float r = length(normCoord);
        float theta = atan(normCoord.y, normCoord.x);
    
        // The actual effect
        r = (r < RadiusMin) ? r : (r > RadiusMin + RadiusWidth) ? r : ceil(r / Radius) * Radius;
        theta = (theta < AngleMin) ? theta : (theta > AngleMin + AngleWidth) ? theta : floor(theta / Angle) * Angle;
    
        // Convert Polar back to Cartesian coords
        normCoord.x = r * cos(theta);
        normCoord.y = r * sin(theta);
        // Shift origin back to bottom-left (taking offset into account)
        texCoord.x = normCoord.x / 2.0 + (Center.x / 2.0);
        texCoord.y = normCoord.y / 2.0 + (Center.y / 2.0);
    
        // Output
        gl_FragColor = texture2D(Texture, texCoord);
    }
    

    来源:polarpixellate glsl

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-07
      • 2023-03-08
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多