【问题标题】:RayTracer spherical MappingRayTracer 球面映射
【发布时间】:2019-04-12 04:50:00
【问题描述】:

我正在使用“Ray Tracer From The Ground Up”一书作为教程,但我在相同的代码中没有相同的结果,我认为它是相同的(我已经检查了几次)。

我的问题是球形 Mapping texture to Sphere.

代码(d_type::Bfloat 是双精度):

void getTexelCoord(const Vector3Bf localHitPoint, const d_type::Bint m_width, const d_type::Bint m_height, d_type::Bint& row, d_type::Bint& column) const
{
    d_type::Bfloat theta=acosf(localHitPoint.y);
    d_type::Bfloat phi= atan2f(localHitPoint.x,localHitPoint.z);
    if(phi<0.0)
    {
        phi+=TWO_PI;
    }
    d_type::Bfloat u =phi*INV_TWO_PI;
    d_type::Bfloat v=1-theta*INV_PI;

    column = (d_type::Bint)((m_width-1)*u);
    row = (d_type::Bint)((m_height-1)*v);

}


virtual Colour getColour(const Info&info )const
{
    d_type::Bint row,column;
    if(m_mapping)
    {
         m_mapping->getTexelCoord(info.m_localHitPoint,hres, vres, row, column);
    }
    else
    {
         row=(int)(info.uv.x*(hres-1));
         column=(int)(info.uv.y*(vres-1));

    }
        return m_image->getColour(row,column);
}



 Colour getColour(const int row, const int column) const {
        int index = column + hres * (vres - row - 1);
        int pixels_size = hres*vres;

        if (index < pixels_size)
                return (m_pixels[index]);
        else
                return (Colour::Red);    
}

Sphere 中的局部生命值是这样计算的:

info.m_localHitPoint=(ray.getOrigin()+(ray.getDirection()*t));

其中 t 是闭合交点

【问题讨论】:

    标签: c++ raytracing


    【解决方案1】:

    根据您的坐标空间的惯用手,我在自己的光线追踪器中有以下几乎等效代码:

    double u = 0.5 - atan2(n.z, n.x) * math::one_over_2pi;
    double v = 0.5 - asin(n.y) * math::one_over_pi;
    

    注意 0.5 的用途,在我的例子中,坐标都在 0..1 范围内。

    【讨论】:

    • 一样....只是改变了纹理的旋转,但是白色的表带是一样的。
    • 所以要么你的纹理只填充了图像的一半,要么你的高度值在某处超出了 2 倍
    • 当我将读取的值从文件更改为红色时,所有球体都是红色的......所以纹理有问题。
    • 球面映射文件的宽度通常是其高度的两倍,但您的代码应该已经考虑到了这一点。回复:更改为全红色 - 这只是表明您正在为球体上的每个命中点调用纹理函数。
    • 从文件加载是好的。我只在球体被射线击中时调用纹理函数。
    【解决方案2】:

    这一切都很奇怪......但是球体的光度必须是 1.. 并且一切正常;)

    问题出在 localHitPoint。它不是本地的,而是全球的,所以在this 问题中,一切都得到了解释。 SphereMapping 工作代码:

    void getTexelCoord(const Vector3Bf &localHitPoint, const d_type::Bint m_width, const d_type::Bint m_height, d_type::Bint& row, d_type::Bint& column) const
        {
    
            Vector3Bf normal=localHitPoint - m_sphere->getCenter();
            Vector3Bf::normalize(normal);
            d_type::Bfloat u=0.5+atan2(normal.z,normal.x)*INV_TWO_PI;
            d_type::Bfloat v = 0.5-asin(normal.y)*INV_PI;
            column =(int)(m_width*u);
            row =(int)(m_height)*v;
        }
    

    其中 m_sphere 是具有此映射的材质(纹理)的球体。

    【讨论】:

    • 啊,所以您确实使用了我的方程式,然后(尽管可能仍然存在“用手习惯”问题,也许可以通过您在计算 @987654327 时使用 + 而不是 - 来解释@)。我没有发现起源问题的原因是,在实现中,光线在“对象”空间而不是“世界”空间中更为常见。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 2011-03-19
    相关资源
    最近更新 更多