【问题标题】:Equirectangular or radial texture scaling on a sphere in Unity ShaderUnity Shader 中球体上的等距矩形或径向纹理缩放
【发布时间】:2020-06-23 08:51:00
【问题描述】:

我想在一个球体上投影几个等距矩形纹理(每个纹理仅包含地球大陆上保持其原始等距矩形形状,其余部分是透明的)。我想缩放球体,以便大陆保持其表面/大小并保持在其位置而不随球体缩放。所有这些都在着色器中完成。投影仪方法被排除在外,因为大陆/纹理可以根据其原始大小或球体大小映射到截锥体后面。

我现在正在为此苦苦挣扎,因为有些日子无法找到解决方案。

到目前为止,我的方法是根据球体的缩放比例调整纹理 UV 的大小(以便它似乎保持其表面和位置),但它不能正常工作,因为它在笛卡尔平面中缩放,而它应该是在等角坐标系或径向坐标系中缩放。而且我不知道这样做的数学...

也许有人知道在等角坐标系或径向坐标系中缩放的数学?也许我只是使事情复杂化,并且与世界坐标有关。我也在考虑将 equirectangular 投影到 gnomonic,缩放,然后重新投影到 equirectangular,但我很确定这是矫枉过正而且太近似了。

参见插图。 texture scaling on a sphere

着色器“Unlit/Equirectangular2SphereSimple” { 特性 { [NoScaleOffset] _FirstTex ("Equirectangular (First)", 2D) = "white" {} _Scale ("Scale", Range(0,10)) = 1.0 } 子着色器 { 经过 { 标签 { "DisableBatching"="True" } CG程序 #pragma 顶点 vert #pragma 片段片段 #pragma 目标 3.0 #include "UnityCG.cginc" sampler2D _FirstTex; 一半 _Scale; 结构 v2f { float4 位置:SV_POSITION; float3 texcoord : TEXCOORD0; }; 内联 float2 ToRadialCoords(float3 coords) { float3 normalizedCoords = normalize(coords); 浮动纬度 = acos(normalizedCoords.y); 浮点经度 = atan2(normalizedCoords.z, normalizedCoords.x); float2 sphereCoords = float2(经度,纬度) * (1/UNITY_PI); 返回 float2(0.5F - sphereCoords.x * 0.5F, 1.0F - sphereCoords.y); } v2f vert(appdata_full v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); //注意:我们需要逆x法线 o.texcoord = v.vertex * half3(-1,_Scale,1); //如果不在极点,缩放不起作用 返回 o; } 固定4碎片(v2f i):SV_Target { float2 equirectangularUV = ToRadialCoords(i.texcoord); fixed4 first = tex2D(_FirstTex, equirectangularUV); 首先返回.a != 0 ?第一个:固定4(1,1,1,1); } ENDCG } } 后备“VertexLit” }

【问题讨论】:

    标签: unity3d geometry shader coordinates textures


    【解决方案1】:

    没有尝试过,但我认为可靠的工作解决方案将是:

    1. 将 uv 计算移至顶点着色器。单位空间中的球体模型位置 (xyz) -> 经度/纬度 -> equirectangular coords。
    2. 在绘制每个大陆时,选择其中心的方向并将其作为统一传递。我们称之为 CenterDir
    3. 绘制大陆时,请查看当前球体方向 (Cur),如果它与 CenterDir 位于同一半球 - 旋转 Cur 更多CenterDir 或以 CurCenterDir 之间的角度加权。
    4. 1 的 uv 计算中使用来自 3 的倾斜方向。

    还有a good basis for prototyping this feature and checking other options in shadertoy

    【讨论】:

    • 感谢您的回答。这似乎是一个很好的方法。但是,我显然是着色器的新手,所以我不确定如何在 CGPROGRAM 中实现这一点,我添加了代码
    • 我没有使用过 Unity 及其着色器语言包装器。我可能会从逐步为每个数据块着色球体开始。并检查是否正确。然后它会分解成一些小问题,我认为其中大部分都有一些教程答案。
    猜你喜欢
    • 2018-11-07
    • 2014-04-23
    • 1970-01-01
    • 2021-10-07
    • 2013-12-04
    • 1970-01-01
    • 2013-10-21
    • 2015-04-20
    • 2021-09-12
    相关资源
    最近更新 更多