如何将着色器转换为 azimuthal_equidistant
How to do a shader to convert to azimuthal_equidistant
我有一个 等角投影
我可以使用什么 GLSL 着色器将其转换为 azimuthal equidistant projection?
另请参阅:
http://earth.nullschool.net/#current/wind/isobaric/500hPa/azimuthal_equidistant=24.64,98.15,169
我会在片段着色器中完成。
- 将 Equirectangular 纹理绑定为 2D 纹理
- 绑定投影着色器
- 绘制覆盖屏幕或目标纹理的四边形
- 存储或使用结果。
在顶点着色器中我会:
只需将顶点坐标作为 varying
传递给片段着色器(此处不使用矩阵,您可以直接使用 <-1,+1>
范围内的 x,y 坐标)
在片段着色器中我会:
- 从点
(0,0)
计算 azimuth
和 distance
的内插值 vertex
(简单的 length
和 atan2
调用)
- 然后将它们转换为
(u,v)
纹理坐标(只是缩放...)
- 最后使用选定的纹素渲染片段,如果超出范围则将其丢弃...
[edit1] 刚刚做了一个小例子:
GL绘制
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr"); glUniform1i(id,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,txrmap);
glBegin(GL_QUADS);
glColor3f(1,1,1);
glVertex2f(-1.0,-1.0);
glVertex2f(-1.0,+1.0);
glVertex2f(+1.0,+1.0);
glVertex2f(+1.0,-1.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
glUseProgram(0);
glFlush();
SwapBuffers(hdc);
顶点:
varying vec2 pos;
void main()
{
pos=gl_Vertex.xy;
gl_Position=gl_Vertex;
}
片段:
uniform sampler2D txr;
varying vec2 pos;
void main()
{
const float pi2=6.283185307179586476925286766559;
vec4 c=vec4(0.0,0.0,0.0,1.0);
vec2 uv; // texture coord = scaled spherical coordinates
float a,d; // azimuth,distance
d=length(pos);
if (d<1.0) // inside projected sphere surface
{
a=atan(-pos.x,pos.y);
if (a<0.0) a+=pi2;
if (a>pi2) a-=pi2;
uv.x=a/pi2;
uv.y=d;
c=texture2D(txr,uv);
}
gl_FragColor=c;
}
输入纹理:
输出渲染:
[注释]
垂直线是由于没有在源纹理上使用GL_CLAMP_TO_EDGE
造成的。可以通过在摊位两侧使用纹理坐标范围移动 1 个像素或使用 GL_CLAMP_TO_EDGE
扩展(如果存在)来修复。
奇怪的atan()
操作数是向左旋转90度以匹配北方位角向上的结果。
我有一个
我可以使用什么 GLSL 着色器将其转换为 azimuthal equidistant projection?
另请参阅: http://earth.nullschool.net/#current/wind/isobaric/500hPa/azimuthal_equidistant=24.64,98.15,169
我会在片段着色器中完成。
- 将 Equirectangular 纹理绑定为 2D 纹理
- 绑定投影着色器
- 绘制覆盖屏幕或目标纹理的四边形
- 存储或使用结果。
在顶点着色器中我会:
只需将顶点坐标作为 varying
传递给片段着色器(此处不使用矩阵,您可以直接使用 <-1,+1>
范围内的 x,y 坐标)
在片段着色器中我会:
- 从点
(0,0)
计算azimuth
和distance
的内插值vertex
(简单的length
和atan2
调用) - 然后将它们转换为
(u,v)
纹理坐标(只是缩放...) - 最后使用选定的纹素渲染片段,如果超出范围则将其丢弃...
[edit1] 刚刚做了一个小例子:
GL绘制
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr"); glUniform1i(id,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,txrmap);
glBegin(GL_QUADS);
glColor3f(1,1,1);
glVertex2f(-1.0,-1.0);
glVertex2f(-1.0,+1.0);
glVertex2f(+1.0,+1.0);
glVertex2f(+1.0,-1.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,0);
glUseProgram(0);
glFlush();
SwapBuffers(hdc);
顶点:
varying vec2 pos;
void main()
{
pos=gl_Vertex.xy;
gl_Position=gl_Vertex;
}
片段:
uniform sampler2D txr;
varying vec2 pos;
void main()
{
const float pi2=6.283185307179586476925286766559;
vec4 c=vec4(0.0,0.0,0.0,1.0);
vec2 uv; // texture coord = scaled spherical coordinates
float a,d; // azimuth,distance
d=length(pos);
if (d<1.0) // inside projected sphere surface
{
a=atan(-pos.x,pos.y);
if (a<0.0) a+=pi2;
if (a>pi2) a-=pi2;
uv.x=a/pi2;
uv.y=d;
c=texture2D(txr,uv);
}
gl_FragColor=c;
}
输入纹理:
输出渲染:
[注释]
垂直线是由于没有在源纹理上使用GL_CLAMP_TO_EDGE
造成的。可以通过在摊位两侧使用纹理坐标范围移动 1 个像素或使用 GL_CLAMP_TO_EDGE
扩展(如果存在)来修复。
奇怪的atan()
操作数是向左旋转90度以匹配北方位角向上的结果。