You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于世界坐标计算立方体贴图球面(CubeSphere)的切线向量?

如何基于世界坐标计算立方体贴图球面(CubeSphere)的切线向量?

Hey there! This is a tricky but interesting geometry problem—let's break it down step by step to find a clean, mathematically sound solution.

First, let's recap what we need: the tangent vector points along the positive UV x-axis direction in world space, and it must be perpendicular to the cubesphere's normal (which is just normalize(uvw) for any world space point uvw).

Key Insight: Derive from the UV Generation Logic

Your provided HLSL code for generating cubesphere UVs holds the key to solving this. Let's focus on one face first (say, the positive X face) since you mentioned handling other faces via rotation/flipping is trivial.

For the positive X face (where abs(x) > abs(y) and abs(x) > abs(z), plus x > 0):
The UV x-coordinate u is calculated as:

vec2 uv = v.yz/v.x; // v = uvw, so uv = (y/x, z/x)
vec2 distort = 1.45109572583 - 0.451095725826*abs(uv);
uv *= distort;
float u = 0.5 + 0.5*uv.x;

Simplifying, u depends on y/x (scaled by the distortion factor). To find the direction of increasing u, we compute the gradient of u with respect to world coordinates (x,y,z).

The critical observation here is that the distortion factor is a positive scalar multiplier—it affects the magnitude of the gradient but not its direction. After computing partial derivatives and simplifying, we find the direction of maximum u increase is perpendicular to both the normal and the X-axis:

vec3 tangent = normalize(vec3(-y, x, 0));

Let's verify with examples:

  • At the center of the positive X face (1,0,0), the tangent is (0,1,0)—which makes sense, since moving along positive Y increases u from 0 to 1.
  • At (1,1,0), the tangent is normalize(vec3(-1,1,0))—moving in this direction increases y/x (since y goes up and x goes down slightly), which in turn increases u.

Extending to All Faces

Using the same logic, we can derive the tangent vector for every face of the cubesphere. Here's the complete set of formulas:

  • Positive X face (abs(x) ≥ abs(y), abs(x) ≥ abs(z), x > 0):

    vec3 tangent = normalize(vec3(-uvw.y, uvw.x, 0));
    
  • Negative X face (abs(x) ≥ abs(y), abs(x) ≥ abs(z), x < 0):

    vec3 tangent = normalize(vec3(-uvw.y, uvw.x, 0));
    

    (The negative x automatically adjusts the direction to match increasing u.)

  • Positive Y face (abs(y) ≥ abs(x), abs(y) ≥ abs(z), y > 0):

    vec3 tangent = normalize(vec3(0, -uvw.z, uvw.y));
    
  • Negative Y face (abs(y) ≥ abs(x), abs(y) ≥ abs(z), y < 0):

    vec3 tangent = normalize(vec3(0, -uvw.z, uvw.y));
    
  • Positive Z face (abs(z) ≥ abs(x), abs(z) ≥ abs(y), z > 0):

    vec3 tangent = normalize(vec3(uvw.z, 0, -uvw.x));
    
  • Negative Z face (abs(z) ≥ abs(x), abs(z) ≥ abs(y), z < 0):

    vec3 tangent = normalize(vec3(uvw.z, 0, -uvw.x));
    

Why This Works (and Naive Approaches Don't)

  • The naive approach of using cross(Normal, vec3(0,1,0)) fails because it doesn't account for how UVs are warped across the cubesphere face—this formula correctly aligns with the actual direction of increasing u.
  • Unlike approximate solutions, these formulas are mathematically derived directly from the UV generation logic, so they'll match the tangent direction you'd get from a precomputed cubesphere mesh.

Implementing This in Code

In your shader, first determine which face the current world vector is on, then apply the corresponding formula:

vec3 uvw = normalize(worldPosition); // Your world space vector
vec3 n = abs(uvw);
vec3 tangent;

if(n.x > n.y && n.x > n.z) {
    tangent = normalize(vec3(-uvw.y, uvw.x, 0));
} else if(n.y > n.z) {
    tangent = normalize(vec3(0, -uvw.z, uvw.y));
} else {
    tangent = normalize(vec3(uvw.z, 0, -uvw.x));
}

This will give you the correct unit tangent vector aligned with the positive UV x-axis in world space, no precomputed mesh data required!

备注:内容来源于stack exchange,提问作者geht sie gar nix an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 15:38:05