如何做着色器转换为azimuthal_equidistant [英] How to do a shader to convert to azimuthal_equidistant

查看:161
本文介绍了如何做着色器转换为azimuthal_equidistant的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个



[注释]



垂直线是由于在源纹理上未使用 GL_CLAMP_TO_EDGE 造成的。它可以通过在展台两侧使用1像素的纹理坐标范围进行修复,或者使用 GL_CLAMP_TO_EDGE 扩展名(如果有的话)。

怪异 atan()操作数是向左旋转90度以匹配北方位角度为UP的结果。


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

解决方案

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:

Output render:

[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.

这篇关于如何做着色器转换为azimuthal_equidistant的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆