纹理扭曲着色器:极坐标转矩形坐标

6

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

enter image description here

我知道如何在极坐标系和矩形坐标系之间进行坐标转换,但是在编写着色器以实现所需效果方面遇到了问题。

我的着色器接收一个纹理作为输入,并应该将扭曲的纹理绘制到屏幕上。我安排了以下步骤(知道片段着色器每次只对一个片段进行操作):

  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);
}
1个回答

2
在您的着色器中,首先将其转换为极坐标。
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*width*cos(theta)) 进行缩放。

我不进行归一化,是否可以得到我期望的结果附近的东西?我尝试了(直接使用r和theta),但结果与我预期的相差甚远。之后,我尝试添加缩放因子,但似乎也没有起作用。我应该发布代码吗? - Thiago
@Thiago:这真的取决于您放置坐标系原点的位置。如果您将极坐标直接放入纹理坐标中,结果会大不相同。但是通过更改原点和基向量(即theta=0基向量的方向),可以实现它。然而,我自己也花了一个小时左右来调试它。 - datenwolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接