一周光追4.2Texture Coordinates for Spheres翻译

对于球体,纹理坐标通常基于某种形式的经度和纬度,即球面坐标。【译注:球面坐标三要素θ,φ,r】我们要映射 θ 和φ 到纹理坐标 u 和 v,其中u, v∈ [0, 1]

为了映射 θ φ 到 u  v,且令u, v∈ [0, 1]

 要计算 θ 和φ, 对于以原点为中心的单位球面上的给定点,我们从相应笛卡尔坐标的方程开始:

直角坐标系与球坐标系的互化

 我们根据以上三个式子反解出 θ 和φ。<cmath>提供了函数 atan2()。atan2有两个形参,两个参数之比为待反解的正切值。并且,atan2()是四象限反正切。我们可以传入-x/z,就可以得到φ。

【译注:四象限反正切vs反正切

反正切atan图像

 反正切atan只有两个象限,f = anctan(a/b),若a/b为正,答案为0~π/2,若a/b为负,答案为-π/2~0 相当于只考虑单位圆的右半部分

而四象限反正切,见下图

四象限反正切的定义

四象限反正切的图示

相当于扩充了答案的范围,考虑整个单位圆。译注结束】

atan2() 返回 −π~π,但它们从 0 变为 π,然后翻转到 −π 并返回到零。虽然这在数学上是正确的,但我们希望u的范围是从 0 到 1,而不是从 0 至 1/2 然后从 −1/2 到 0。

很巧的是,atan2有如下关系:

 第二个公式产生的值从 0 连续至2π .因此,我们可以计算φ 如

【译注:从左下角开始,值域就是连续的了】

 θ 的推导更直接:

所以对于一个球体,(u,v)计算由以下函数函数完成,该函数取以原点为中心的单位球面上的点,并计算 u 和 v

// Listing 22: [sphere.h] get_sphere_uv function

class sphere : public hittable {
    ...
    private:
        static void get_sphere_uv(const point3& p, double& u, double& v) {
            // p: a given point on the sphere of radius one, centered at the origin.
            // u: returned value [0,1] of angle around the Y axis from X=-1.
            // v: returned value [0,1] of angle from Y=-1 to Y=+1.
            //     <1 0 0> yields <0.50 0.50>       <-1  0  0> yields <0.00 0.50>
            //     <0 1 0> yields <0.50 1.00>       < 0 -1  0> yields <0.50 0.00>
            //     <0 0 1> yields <0.25 0.50>       < 0  0 -1> yields <0.75 0.50>

            auto theta = acos(-p.y());
            auto phi = atan2(-p.z(), p.x()) + pi;

            u = phi / (2*pi);
            v = theta / pi;
        }
};

猜你喜欢

转载自blog.csdn.net/weixin_45339670/article/details/131383863