【Ray Tracing The Next Week 超详解】 光线追踪2-3

 Preface

终于到了激动人心的纹理章节了

然鹅,看了下,并不激动

因为我们之前就接触过

当初有一个 attenuation 吗?

对了,这就是我们的rgb分量过滤器,我们画出的红色、蓝色、绿色等等,都是通过它来控制的

专业点的词语叫做rgb衰减比例,比如rtvec(1.,0.,0.),最后呈现出来的是红色,因为r保留了100%

它是怎么控制的呢,我们来回顾一下这个过程

首先,我们创建一个材质球

后面那个rtvec(0.4,0.2,0.1)就是衰减比例(衰减到原来的百分之。。)

之后

进入数据成员中,之后主函数调用lerp的时候

info.materialp->scatter(sight, info, attenuation, scattered))

球体的材质调用scatter函数

即:

没有丝毫改动地有数据成员传递到了attenuation 中

然后用attenuation 做乘法进行rgb衰减,递归就不用说了吧,最后递归到深处为黑色,不然为背景色

为什么要在前言将这个东东,因为

attenuation 所控制形成的物体表面颜色就是最简单的纹理

说白了这章比较简单,因为下一章是这本书的另外一个高难度章节(分别分布于第二章和第四章)

所以,中间第三章来点简单好玩的,过渡一下

 先看效果

Chapter 3:Solid Textures

废话不多说,先写一个纹理类

/// texture.hpp

// -----------------------------------------------------
// [author]        lv
// [begin ]        2019.1
// [brief ]        the texture-class for the ray-tracing project
//                from the 《ray tracing the next week》

#pragma once

namespace rt
{

class texture
    {
public:

    virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const = 0;

    };

}

u 和 v后面用到再讲,p就是衰减向量

然后写一个常量纹理(基础纹理)

/// constant_tex.hpp

// -----------------------------------------------------
// [author]        lv
// [begin ]        2019.1
// [brief ]        the constant_texture-class for the ray-tracing project
//                from the 《ray tracing the next week》
// -----------------------------------------------------

#pragma once

namespace rt
{

class constant_texture :public texture
    {
    public:

        constant_texture() {  }

        constant_texture(const rtvec& color);

        virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;

    public:

        inline const rtvec& color()const { return _color; }

    private:

        rtvec _color;

    };

inline constant_texture::constant_texture(const rtvec& color)
    :_color(color)
    {
    }

rtvec constant_texture::value(rtvar u, rtvar v, const rtvec& p)const
    {
    return _color;
    }

}

之后,我们把材质中的rtvec向量改为纹理指针

/// diffuse.hpp
// https://www.cnblogs.com/lv-anchoret/p/10198423.html

// -----------------------------------------------------
// [author]        lv
// [begin ]        2018.12
// [brief ]        one of the materials
// -----------------------------------------------------

#pragma once

namespace rt
{

class texture;

//diffuse material
class lambertian : public material
    {
public:
    lambertian(texture* _tex);

    virtual bool scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const override;

protected:

    texture* _albedo;
    };

inline lambertian::lambertian(texture* _tex)
    :_albedo(_tex)
    {
    }

bool lambertian::scatter(const ray& rIn, const hitInfo& info, rtvec& attenuation, ray& scattered)const
    {
    rtvec target = info._p + info._n + lvgm::random_unit_sphere();
    scattered = ray{ info._p, target - info._p };
    attenuation = _albedo->value(0.,0.,info._p);
    return true;
    }

}

之前我们创建的材质球代码就要改一种风格了

把其他的材质类也做相应的改动

我们今天最重要的是弄棋盘(checkerboard)纹理

棋盘纹理就是交错的双色格子,呈现一定的规律性

所以我们想象一下利用某些映射函数来实现这种类似二值性,且呈现周期性

我们比较容易想到利用正余弦函数,呈现周期性,且值域为【-1,1】是个有界函数

如何体现二值呢,正负嘛,正余弦函数一定关于x轴对称

如何将物体表面和正余弦函数联系在一起形成双色交错的格子呢

表面法向量!!

综上,如果我们在所有三个维度中相乘某个正余弦函数,那么该公式的符号形成一个棋盘形式

即:rtvar sines = sin(10 * p.x()) * sin(10 * p.y()) * sin(10 * p.z());

当然,你也可以试一下sgnx函数,设置一个相关的判别式

/// checker_tex.hpp

// -----------------------------------------------------
// [author]        lv
// [begin ]        2019.1
// [brief ]        the checker_texture-class for the ray-tracing project
//                from the 《ray tracing the next week》
// -----------------------------------------------------

#pragma once

namespace rt
{

class checker_texture :public texture
    {
    public:
        checker_texture() {  }

        checker_texture(texture* t1, texture* t2);

        virtual rtvec value(rtvar u, rtvar v, const rtvec& p)const override;

    private:

        texture* _even;

        texture* _odd;

    };

inline checker_texture::checker_texture(texture * t1, texture * t2)
        :_even(t1)
        , _odd(t2)
    {
    }

rtvec checker_texture::value(rtvar u, rtvar v, const rtvec& p)const
    {
    rtvar sines = sin(30 * p.x()) * sin(30 * p.y()) * sin(30 * p.z());
    if (sines < 0)
        return _odd->value(u, v, p);
    else
        return _even->value(u, v, p);
    }

}

我们把大球设置为棋盘纹理

就是开篇图

然后,我把判别式中的10改成了30依旧是原图

10(左)30(右)

y = sin(wx + φ)

你可以尝试改动一下φ参数试一下

下面是另外一个图:

随机球体生成函数改成

相机参数依旧是之前的

会得到这样一个图

感谢您的阅读,生活愉快~

原文地址:https://www.cnblogs.com/lv-anchoret/p/10285473.html

时间: 2024-11-06 03:46:42

【Ray Tracing The Next Week 超详解】 光线追踪2-3的相关文章

【Ray Tracing The Next Week 超详解】 光线追踪2-6 Cornell box

Chapter 6:Rectangles and Lights 今天,我们来学习长方形区域光照  先看效果 light 首先我们需要设计一个发光的材质 /// light.hpp // ----------------------------------------------------- // [author] lv // [begin ] 2019.1 // [brief ] the areaLight-class for the ray-tracing project // from t

【Ray Tracing in One Weekend 超详解】 光线追踪1-10

<Ray Tracing in One Weekend>完结篇 最近课程上机实验,封面图渲染时间也超长,所以写东西就落下了,见谅 这篇之后,我会继续<Ray Tracing The Next Week>,还请多多关注 这几天我在渲染这本书的封面图,封面图还没出,不算结束,刚好安排了10节 今天呢,有两件事: 1.阐述整个工程的文件组织即内容 2.阐述封面,完结 12.1工程文件组织 试过很多方法,问过很多老师,无奈,子类继承实现的父类纯虚函数实在无法和类声明分成两个文件(即声明放于

【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 &amp;&amp; 场景案例

上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画质问题及优化方案 3. 新的场景几何体——长方体 轴平行长方体 任意长方体 我们这一篇重实践轻理论阐述 ready 1. 需要上一章的知识 但是,上一章的Cornell box画质优化仅限于盒子本身,如果作为场景和其他物体放在一起就不能那么优化画质 即,Cornell box像素计算失败应该返回黑色

【Ray Tracing in One Weekend 超详解】 光线追踪1-7 Dielectric 半径为负,实心球体镂空技巧

今天讲这本书最后一种材质 Preface 水,玻璃和钻石等透明材料是电介质.当光线照射它们时,它会分裂成反射光线和折射(透射)光线. 处理方案:在反射或折射之间随机选择并且每次交互仅产生一条散射光线 (实施方法:随机取样,具体见后文) 调试最困难的部分是折射光线.如果有折射光线的话,我通常首先让所有的光折射.对于这个项目,我试图在我们的场景中放置两个玻璃球,我得到了这个:   上述图片是对的吗?显然,在实际生活中,那两个玻璃球看起来怪怪的,实际情况下,里面的内容应该将现在的进行上下颠倒,且没有黑

POJ 1659 Frogs&#39; Neighborhood(可图性判定—Havel-Hakimi定理)【超详解】

Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9897   Accepted: 4137   Special Judge Description 未名湖附近共有N个大小湖泊L1, L2, ..., Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤ i ≤ N).如果湖泊Li和Lj之间有水路相连,则青蛙Fi和Fj互称为邻居.现在已知每只青蛙的邻居数目x1, x2, ..

CentOS6启动过程超详解分析

CentOS 6 开机流程--linux由kernel和rootfs组成.kernel负责进程管理.内存管理.网络管理.驱动程序.文件系统.安全等;rootfs由程序和glibc组成,完善操作系统的功能.同时linux内核的特点是模块化,通过对模块装载卸载可以对内核功能自定义.linux内核文件:/boot/vmlinuz-2.6.32-696.el6.x86_64 整体的流程 BIOS/开机自检 MBR引导(Boot Loader) 启动内核 启动第一个进程init 一.BIOS/开机自检 1

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-5 random direction &amp; ONB

 Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要通过实践,改进当前的效果 于是乎,就有了后面的章节,几乎整本书都在讲,如何一步一步地改进上一篇的画质,使其更加符合现实,上一篇其实是抛砖引玉 这本书的小标题名为the rest of your life 通过前面几章,我们可以更好地理解这句话:我们通过MC积分优化效果,采用的是pdf函数,之前说过,

高斯消元法(Gauss Elimination)【超详解&amp;模板】

高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 1.线性方程组 1)构造增广矩阵,即系数矩阵A增加上常数向量b(A|b) 2)通过以交换行.某行乘以非负常数和两行相加这三种初等变化将原系统转化为更简单的三角形式(triangular form) 注:这里的初等变化可以通过

海量数据处理算法总结【超详解】

1. Bloom Filter [Bloom Filter]Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在集合的快速的概率算法.Bloom Filter有可能会出现错误判断,但不会漏掉判断.也就是Bloom Filter判断元素不再集合,那肯定不在.如果判断元素存在集合中,有一定的概率判断错误.因此,Bloom Filter不适合那些“零错误”的应用场合. 而在能容忍低错误率的应用场合