Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
532 views
in Technique[技术] by (71.8m points)

geometry - How to do a shader to convert to azimuthal_equidistant

I have a 360 texture in Equirectangular Projection.

With what GLSL shader can I convert it into a azimuthal equidistant projection?

See also: http://earth.nullschool.net/#current/wind/isobaric/500hPa/azimuthal_equidistant=24.64,98.15,169

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would do it in Fragment shader.

  1. bind Equirectangular texture as 2D texture
  2. bind projection shader
  3. draw Quad covering the screen or target texture
  4. store or use the result.

In Vertex shader I would:

Just pass the vertex coordinates as varying to fragment shader (no point using matrices here you can directly use x,y coordinates in range <-1,+1>)

In fragment shader I would:

  1. compute azimuth and distance of interpolated vertex from point (0,0) (simple length and atan2 call)
  2. then convert them to (u,v) coordinates of texture (just scale...)
  3. and lastly render fragment with selected texel or throw it out if out of range ...

[edit1] just did bust a small example:

GL draw

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);

Vertex:

varying vec2 pos;
void main()
    {
    pos=gl_Vertex.xy;
    gl_Position=gl_Vertex;
    }

Fragment:

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;
    }

Input texture:

earth rectangular

Output render:

earth azimuthal equidistant

[notes]

The vertical line is caused by not using GL_CLAMP_TO_EDGE on source texture. It can be repaired by using texture coordinates range shifted by 1 pixel on booth sides or use GL_CLAMP_TO_EDGE extension if present.

Weird atan() operands are result of rotating left by 90 degrees to match North azimuth to be UP.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...