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

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

问题描述

我有一个

输出渲染:

[注释]

垂直线是由于没有在源纹理上使用 GL_CLAMP_TO_EDGE 造成的.它可以通过使用在展台两侧移动 1 个像素的纹理坐标范围或使用 GL_CLAMP_TO_EDGE 扩展(如果存在)来修复.

奇怪的 atan() 操作数是向左旋转 90 度以匹配北方位角向上的结果.

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天全站免登陆