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

Thi*_*ago 6 opengl math shader transformation

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

由此:

在此输入图像描述

对此:

在此输入图像描述

我知道在极坐标和矩形系统之间转换坐标的公式,但我在编写着色器以实现所需效果时遇到问题。

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

  1. 使用 gl_FragCoord.xy 查找当前片段的坐标
  2. 确定对应于点 (x, y) 的 r 和 theta。
  3. 将r和theta转换为texture_x和texture_y(将用于对纹理进行采样)
  4. 将采样的像素传输到当前片段

我的最终结果是相同的输入纹理顺时针旋转 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);
}
Run Code Online (Sandbox Code Playgroud)

dat*_*olf 2

在你的着色器中,你首先转换成极坐标

\n\n
float r = sqrt(pow(fragCoords.x, 2) + pow(fragCoords.y, 2));\nfloat theta = atan(fragCoords.y, fragCoords.x);\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后你不把它们翻译回笛卡尔

\n\n
float tX = r * sin(theta); \nfloat tY = r * cos(theta);\n
Run Code Online (Sandbox Code Playgroud)\n\n

您想保留在极坐标中,因此只需将rtheta插入纹理坐标即可

\n\n
vec2 texCoords = vec2(r , theta);\nvec4 texFrag = texture2D(tex, texCoords);\n
Run Code Online (Sandbox Code Playgroud)\n\n

然而,从您粘贴的图像的外观来看,涉及一些重新规范化步骤,因此(r, theta)将覆盖一个矩形区域。如果我没有完全弄错的话,那么 r 的缩放比例是从中心底部到与矩形区域相交的光线的距离。如果我们假设 theta=0 是垂直向上的,那么对于范围 [-atan(0.5)\xe2\x80\xa6atan(0.5)] ,它会按 1/(height*sin(theta)) 缩放,在该范围之外按 1 缩放/(0.5*宽度*cos(θ))

\n