Loading... ![球面UV](https://res.lazyun.cn/typecho/2022/06/04/tellurion1.jpg?x-oss-process=style/compress) ### 代码和说明 #### 1. 固定地轴Shader [](https://www.bilibili.com/video/BV1Rr4y1G7eV/) 主要逻辑在Fragment Shader中,具体如下: ``` real4 frag(v2f i) : SV_Target { // 将UV原点换到图片中央 float2 uv = i.uv - 0.5; // 根据勾股定理计算 z = sqrt( r*r - (x*x + y*y )) float3 pos = float3(uv.x, uv.y, sqrt(0.25 - (uv.x * uv.x + uv.y * uv.y))); // 将得到的点坐标转换到球面坐标系,得到phi角度并转到(-1,1) float p = atan2(pos.x, pos.z) * INV_PI; // 结合_Time.y 和 输入参数转动速度 float2 suv = float2(frac(p + (_Speed * _Time.y)), i.uv.y); // 使用distance确定出圆的范围,结合smoothstep获得平滑的圆边缘 real4 col = tex2D(_MainTex, suv) * smoothstep(0.51, 0.49, distance(i.uv, 0.5)); return col; } ``` #### 2.地轴可旋转Shader 效果如下: [](https://www.bilibili.com/video/BV1wY411u7Rr) Shader说明如下: ``` real4 frag(v2f i) : SV_Target { // 球的半径为UV范围的一半 half r = 0.5; // 半径的平方 half rr = r * r; // 移动UV原点到画布中心 float2 uv = i.uv - r; // 将角度转为弧度 half angle = radians(_Angle); float x = uv.x; float xx = x * x; // 根据勾股定理算出当前点在笛卡尔坐标相对x轴的距离 float le = sqrt(rr - xx); // 计算当前点所在YZ平面确定的圆上旋转角度 float angleY = asin(uv.y/le); // 当前旋转角度加上给定的地轴旋转角度就是当前点的最终角度 // 根据该角度计算当前点的最终坐标 float y = sin(angleY + angle) * le; float z = sqrt(rr - (xx + y * y)); // 当前点如果位于背面,因为地轴旋转导致显示出现的情况,则需要将z值反转 if(HALF_PI - angleY < angle) { z = -z; } // 将最终坐标转成球面坐标系,然后映射到UV的范围 float p = atan2(x, z) * INV_PI * 0.5; float t = (asin(y / r) * INV_PI + .5); // 最终经过球面映射的UV float2 suv = float2(frac(p + (_Speed * _Time.y)), t); real4 col = tex2D(_MainTex, suv) * smoothstep(0.51, 0.49, distance(i.uv, 0.5)); return col; } ``` 最后修改:2022 年 06 月 11 日 © 禁止转载 赞 15