纹理变形着色器:极坐标到矩形坐标

时间:2014-02-01 06:37:15

标签: opengl math shader transformation

我正在使用OpenGL编写2D游戏,我计划了一个阴影投射算法,需要将纹理从极坐标转换为直角坐标。期望的效果如下:

由此:

enter image description here

对此:

enter image description here

我知道在Polar和Rectangular系统之间转换坐标的公式,但我在编写着色器时遇到了问题,以达到预期的效果。

我的着色器接收纹理作为输入,并应将扭曲的纹理绘制到屏幕上。我计划了以下内容(知道片段着色器一次对一个片段起作用):

  1. 使用gl_FragCoord.xy
  2. 查找当前片段的坐标
  3. 确定与点(x,y)对应的r和theta。
  4. 将r和theta转换为texture_x和texture_y(将用于对纹理进行采样)
  5. 将采样像素传输到当前片段
  6. 我的最终结果是顺时针旋转90度的相同输入纹理。我认为我在步骤3中遗漏了一些东西。我可能只是得到当前片段的相同x和y,因为我只是使用变换和逆变换公式。 我该如何进行预期的结果?

    这是我的着色器:

    #version 120
    
    uniform sampler2D tex;
    
    void main() {
    
      vec2 fragCoords = gl_FragCoord.xy - vec2(128, 128); //shift the coordinates so that 0, 0 is in the center of the screen (the final texture is 256 * 256)
      fragCoords /= vec2(256, 256);
      float r = sqrt(pow(fragCoords.x, 2) + pow(fragCoords.y, 2));
      float theta = atan(fragCoords.y, fragCoords.x);
    
      if (fragCoords.y/fragCoords.x <= 0.5 && fragCoords.y/fragCoords.x >= -0.5) {
        r *= 1/(256*sin(theta));
      } else {
        r *= 1/(0.5*256*cos(theta));
      }
    
      vec2 texCoords = vec2(r, theta);
      vec4 texFrag = texture2D(tex, texCoords);
    
      gl_FragColor = texFrag * vec4(1.0, 0.0, 0.0, 1.0);
    }
    

1 个答案:

答案 0 :(得分:1)

在着色器中,您首先要转换为极坐标

float r = sqrt(pow(fragCoords.x, 2) + pow(fragCoords.y, 2));
float theta = atan(fragCoords.y, fragCoords.x);

然后你不会把它们翻译成笛卡儿式的

float tX = r * sin(theta); 
float tY = r * cos(theta);

您希望保持极坐标,只需将rtheta插入纹理坐标

vec2 texCoords = vec2(r , theta);
vec4 texFrag = texture2D(tex, texCoords);

然而,通过您粘贴的图像的外观,涉及一些重整化步骤,因此(r, theta)将覆盖矩形区域。如果我没有完全弄错的话,那么r将通过从中心底部射出的光线与矩形区域相交的距离来缩放。如果我们假设theta = 0是直线上升,则对于[-atan(0.5)... atan(0.5)]范围,它按1 /(height * sin(theta))缩放,在该范围外缩小1 /(0.5 *宽度* COS(THETA))