Opengl es WebGL-在平面上显示球体

Opengl es WebGL-在平面上显示球体,opengl-es,glsl,webgl,shader,vertex-shader,Opengl Es,Glsl,Webgl,Shader,Vertex Shader,我想展示一个图像,就像它是在一个球体上,但在一个平面上。 这一操作的一个例子是Mercatore投影,即从行星“展开”的地球地图。 为了更好地解释我自己,在一个球体上有一个正方形的纹理-不是在整个球体上,而是在它的一部分上-我想在一个平面上展示在球体上看到这个纹理的结果。 我已经找到了这个: 但是我想使用着色器,因为它可能是最有效的,但也可能是最困难的。我很难找到正确的配方。是否存在任何数学框架?您应该指定您真正想要的投影。曲面有很多方法(不仅仅是球体)。你的问题是这种变换的逆,所以首先是直接

我想展示一个图像,就像它是在一个球体上,但在一个平面上。 这一操作的一个例子是Mercatore投影,即从行星“展开”的地球地图。 为了更好地解释我自己,在一个球体上有一个正方形的纹理-不是在整个球体上,而是在它的一部分上-我想在一个平面上展示在球体上看到这个纹理的结果。 我已经找到了这个:


但是我想使用着色器,因为它可能是最有效的,但也可能是最困难的。我很难找到正确的配方。是否存在任何数学框架?

您应该指定您真正想要的投影。曲面有很多方法(不仅仅是球体)。你的问题是这种变换的逆,所以首先是直接投影(平面->球面)。我使用这两个(都用于特定目的):

  • 从球体上区域中间的距离与平面上的距离匹配

    这用于校正曲面上的纹理,例如眼镜上的装饰图案等

  • 与球体上视图轴的垂直距离与平面上的距离匹配

    因此,如果您从视图轴查看,您会在球体和平面上看到相同的图像,只需设置坐标系,使
    Z
    轴为查看方向,
    x,y
    轴与二维平面轴相对应。然后只需计算z坐标以匹配球面

  • 我想你想要第一个选项

    因此,计算中点
    (x0,y0)
    作为边界框的中心或等距点平均点。通过以弧度为单位的atan2计算每个点和坐标(从中点算起)
    ang

    然后计算
    dx,dy
    并将二维坐标计算为
    (x,y)=(x0+dx,y0+dy)

    下面是结果示例(我将其用于任何类型的曲率):

    [Notes]

    还有另一种基于光线投射的方法,可能还有更多

    <强> [Eddi1] C++示例>/P>

    为您破获小型C++类:

    //---------------------------------------------------------------------------
    #包括
    类球面投影
    {
    公众:
    浮动x0,y0,z0,r0;//三维球体
    浮点u0,v0;//二维图像的中点
    浮点m;//缩放二维图像
    int mode;//哪种投影类型
    球面投影()
    {
    x0=0.0;y0=0.0;z0=0.0;r0=1.0;
    u0=0.0;v0=0.0;m=1.0;
    模式=1;
    }
    无效uv2xyz(浮动和x、浮动和y、浮动和z、浮动u、浮动v)
    {
    如果(模式==1)
    {
    浮子a、b;
    //围绕中点缩放二维位置,并从弧长转换为角度
    u=(u-u0)*m/r0;
    v=(v-v0)*m/r0;
    //修正两个轴的半径分布
    a=u/cos(v);
    b=v/cos(u);
    //计算曲面上的三维笛卡尔点
    z=z0+(r0*cos(b)*cos(a));
    x=x0+(r0*cos(b)*sin(a));
    y=y0+(r0*sin(b));
    }
    如果(模式==2)
    {
    //围绕中点缩放的二维位置
    x=(u-u0)*m;
    y=(v-v0)*m;
    //计算曲面上的三维笛卡尔点
    x=x0+x;
    y=y0+y;
    z=z0+sqrt(r0*r0-x*x-y*y);
    }
    }
    无效uv2xy(浮动和x、浮动和y、浮动u、浮动v)
    {
    如果(模式==1)
    {
    浮动a、b、z;
    //围绕中点缩放二维位置,并从弧长转换为角度
    a=(u-u0)*m/r0;
    b=(v-v0)*m/r0;
    //修正两个轴上的半径分布,并转换回二维位置
    x=u0+(a*r0/(m*cos(b));
    y=v0+(b*r0/(m*cos(a));
    }
    如果(模式==2)
    {
    浮动z;
    //围绕中点+Z轴缩放的二维位置
    x=(u-u0)*m;
    y=(v-v0)*m;
    z=sqrt(r0*r0-x*x-y*y);
    //计算弧长并转换回二维位置
    x=u0+(r0*atan2(x,z)/m);
    y=v0+(r0*atan2(y,z)/m);
    }
    }
    };
    //---------------------------------------------------------------------------
    
    以下是如何使用此选项(在OpenGL中渲染):

    那么3D坐标就是球面变换:

    x=x0+(r0*cos(b)*cos(a));
    y=y0+(r0*cos(b)*sin(a));
    z=z0+(r0*sin(b));
    


    如果你想要反向转换谷歌球面坐标系统,我不太明白。您以何种形式拥有哪些数据?您希望生成哪些数据?你能用图片解释一下吗?嗨@NicoSchertler,编辑了这个问题!那么你有什么数据?如果你想做Mercatore投影,这里有一些公式。你想知道什么?我有一个图像,我想像右边的图像一样显示它,但是使用WebGL。这张图片取自Hugin软件。只有使用两个不同的投影(一个向前,一个向后),这才有意义。不管怎样,只要查一下你想用的投影公式就行了。谢谢。但事实上,最后两张图片对我来说不是很清楚。。我想将1)图像投影到一个球体上(如问题中图像左侧所示),然后从那里,2)将图像投影到平面上的等矩形投影(如右侧所示)。我认为,从你的代码来看,2)选项做了第一部分,虽然没有放大图像的底部和顶部,但只限制了图像的侧面center@Novalink这是一个距离中点相等的例子。透明度有点混乱,基本上源是方形网格图像(2D矢量格式),然后对其进行校正,图像在平面(右侧)a上显示校正后的图像
    a=x*2.0*M_PI; b=(y-0.5)*M_PI;
    
    x=x0+(r0*cos(b)*cos(a));
    y=y0+(r0*cos(b)*sin(a));
    z=z0+(r0*sin(b));