将墨卡托投影转换为等边矩形的着色器? [英] Shader that transforms a mercator projection to equirectangular?

查看:100
本文介绍了将墨卡托投影转换为等边矩形的着色器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用

输出示例:

 着色器"Unlit/NewUnlitShader 1"{特性{_MainTex(纹理",2D)=白色" {}[Enum(Equirectangular,0,Azimuthal,1)]_Azimuthal("Projection",float)= 0}子着色器{标签{"RenderType" =不透明"}100级经过{CG程序#pragma顶点vert#pragma片段片段#include"UnityCG.cginc"结构化应用数据{float4顶点:位置;float2 uv:TEXCOORD0;};结构v2f{float2 uv:TEXCOORD0;float4顶点:SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;float _Azimuthal;v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv,_MainTex);返回o;}#define PI 3.141592653589793238462f#define PI2 6.283185307179586476924ffloat2 uvToEquirectangular(float2 uv){float lat =(uv.x)* PI2;//从0到2PI浮动lon =(uv.y-.5f)* PI;//从-PI到PI返回float2(lat,lon);}float2 uvAsAzimuthalToEquirectangular(float2 uv){float2坐标=(uv-.5)* 4;浮点半径=长度(坐标);浮角= atan2(坐标x,坐标x)+ PI;//来自https://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection的公式浮动纬度=角度;浮动lon = 2 * acos(半径/2)-PI/2;返回float2(lat,lon);}fixed4 frag(v2f i):SV_Target{//获取等角坐标float2 coord = _Azimuthal吗?uvAsAzimuthalToEquirectangular(i.uv):uvToEquirectangular(i.uv);//与墨卡托相等浮点数x = coord.x;浮点y = log(tan(PI/4. + coord.y/2.));//将x,y变成[0,1]范围x = x/PI2;y =(y + PI)/PI2;fixed4 col = tex2D(_MainTex,float2(x,y));//只是为了使其看起来更好col = _Azimuthal&&长度(i.uv * 2-1)>1个1:col;返回col;}ENDCG}}} 

I am trying to make a shader in Unity taking a mercator projection texture as a source and converting it to an equirectangular projection texture.

Input example:

Output example:

This example does the opposite with an equirectangular as source.

If you look at the source of the above example:

 // mercator
 float latClamped = clamp(lat, -1.4835298641951802, 1.4835298641951802);
 float yMerc = log(tan(PI / 4.0 + latClamped / 2.0)) / PI2;
 float xMerc = xEqui / 2.0;
 vec4 mercatorPos = vec4(xMerc, yMerc, 0.0, 1.0);

Can anyone help to reverse this so I'm able to go from a mercator map as a source to equirectangular (or even better, azimuthal).

Looking for a way to do 2D texture deformations going from x/y to longitude(x)/latitude(y) and back.

I appreciate your input.

解决方案

If you want to output the equirectangular projection, you need to convert from equirectangular coordinates to mercator coordinates and then sample the mercator projection at those coordinates.

This is what it would look like in a fragment shader from uvs:

//uv to equirectangular
float lat = (uv.x) * 2 * PI;    // from 0 to 2PI
float lon = (uv.y - .5f) * PI;  // from -PI to PI

// equirectangular to mercator
float x = lat;
float y = log(tan(PI / 4. + lon / 2.));

// bring x,y into [0,1] range
x = x / (2*PI);
y = (y+PI) / (2*PI);

// sample mercator projection
fixed4 col = tex2D(_MainTex, float2(x,y));

The same thing applies to the azimuthal projection: You can go from azimuthal coordinates -> equirectangular -> mercator and sample the image. Or you can find a formula to go directly from azimuthal -> mercator. The

Shader "Unlit/NewUnlitShader 1"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Enum(Equirectangular,0,Azimuthal,1)]
        _Azimuthal("Projection", float) = 0

    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag           

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;                
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Azimuthal;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
#define PI 3.141592653589793238462f
#define PI2 6.283185307179586476924f

            float2 uvToEquirectangular(float2 uv) {
                float lat = (uv.x) * PI2;   // from 0 to 2PI
                float lon = (uv.y - .5f) * PI;  // from -PI to PI
                return float2(lat, lon);
            }

            float2 uvAsAzimuthalToEquirectangular(float2 uv) {                  
                float2 coord = (uv - .5) * 4; 

                float radius = length(coord);
                float angle = atan2(coord.y, coord.x) + PI;

                //formula from https://en.wikipedia.org/wiki/Lambert_azimuthal_equal-area_projection
                float lat = angle;
                float lon = 2 * acos(radius / 2.) - PI / 2;
                return float2(lat, lon);
            }           

            fixed4 frag(v2f i) : SV_Target
            {
                // get equirectangular coordinates
                float2 coord = _Azimuthal ? uvAsAzimuthalToEquirectangular(i.uv) : uvToEquirectangular(i.uv);

                // equirectangular to mercator
                float x = coord.x;
                float y = log(tan(PI / 4. + coord.y / 2.));
                // brin x,y into [0,1] range
                x = x / PI2;
                y = (y + PI) / PI2;                 

                fixed4 col = tex2D(_MainTex, float2(x,y));

                // just to make it look nicer
                col = _Azimuthal && length(i.uv*2-1) > 1 ? 1 : col;

                return col;
            }
            ENDCG
        }
    }
}

这篇关于将墨卡托投影转换为等边矩形的着色器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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