2014-09-19 72 views

回答

3

這並不特別困難。您只需將紋理座標轉換爲極座標,並使用半徑作爲紋理的方向,方位角爲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]中,因此您應將其映射到[0,1]以獲得t座標。

UPDATE1

有我離開了迄今爲止一些細節。從您的圖像中可以清楚地看到,您不希望內圈映射到紋理。但是這可以很容易地被合併。我只假設這裏有兩個半徑: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_EDGE。這樣,你幾乎可以免費得到黑色。另一種方法是在着色器中添加一個布爾值,並檢查tc_polar.s是否低於0或高於1.

+0

你能分享完整的着色器代碼嗎? – Nolesh 2014-09-22 12:49:38

+0

@Nolesh:我更新了我的答案。 – derhass 2014-09-22 18:50:37

+0

你知道如何改變這個着色器來創建段的結果嗎?所以,我需要重複給定的紋理,而不是拉伸。 – Nolesh 2014-09-23 13:18:46

0

我找到了上述着色器的擴展版本:polarpixellate glsl。這篇文章適合那些想要更靈活着色的人。