Как сделать шейдер для конвертации в azimuthal_equidistant

У меня есть 360 текстур в равноугольной проекции.

С каким GLSL-шейдером я могу преобразовать его в азимутальную эквидистантную проекцию?

Смотрите также: http://earth.nullschool.net/#current/wind/isobaric/500hPa/azimuthal_equidistant=24.64,98.15,169

1 ответ

Решение

Я бы сделал это в шейдере Fragment.

  1. связать равноугольную текстуру как 2D текстуру
  2. шейдер проекции связывания
  3. нарисуйте Quad, покрывающий экран или целевую текстуру
  4. сохранить или использовать результат.

В Vertex Shader я бы:

Просто передайте координаты вершины как varying фрагментировать шейдер (нет смысла использовать матрицы здесь вы можете напрямую использовать координаты x,y в диапазоне <-1,+1>)

Во фрагментном шейдере я бы:

  1. вычисление azimuth а также distance интерполированных vertex из точки (0,0) (просто length а также atan2 вызов)
  2. затем преобразовать их в (u,v) координаты текстуры (просто масштаб...)
  3. и, наконец, визуализировать фрагмент с выбранным текселем или выбросить его, если он выходит за пределы диапазона...

[edit1] только что разорил небольшой пример:

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

Фрагмент:

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 градусов, чтобы соответствовать северному азимуту, чтобы быть ВВЕРХ.

Другие вопросы по тегам