Preface

注:鉴于很多网站随意爬取数据,可能导致内容残缺以及引用失效等问题,影响阅读,请认准原创网址:

https://www.cnblogs.com/lv-anchoret/category/1368696.html

我们这节主要讲把之前的概率密度做混合,以得到更好的效果

我们上一篇以前经常用关于cos函数的pdf,上一节用的是与光源采样相关的pdf,那么,我们把两者结合到一起,协调它们之间的比例,我们就可以得到一个有着两种概率密度模型的pdf,这往往是更贴近生活的,那么我们今天就来学习测试一下。

 Ready

这一节就是把前几篇的概率密度做混合,所以,需要的就是熟悉之前的内容。

当然,之前的框架代码也比较丑,基本都是在lerp函数里面做调整,所以,我们顺便把框架搭得更好一点

 正文

我们都知道,设计pdf的一个很重要的原则就是使得累积概率密度达到且只达到1,所以,我们先采用一种非常简单的比例协调方式混合两个pdf。

例如我们有如下的混合密度方程

pdf_mixture(direction) = 1/2 * pdf_reflection(direction) + 1/2 * pdf_light(direction)

即,两者各占一半

要实现两者,代码描述也很简单:

if ( rand01() < 0.5 )
pdf_reflection(); ...
else
pdf_light(); ...
 
但是评估pdf_mixture会稍微有点微妙。 我们需要同时评估pdf_reflection和pdf_light,因为有一些方向可以生成pdf方向。 例如,我们可以使用pdf_reflection生成朝向光的方向
 
如果我们回顾之前的内容,你会发现,这一部分主要解决两个问题:
1.此处的pdf函数值
2.按照某个随机模型产生一个随机数
 
我们抽象出这些操作之后,就可以写一个关于我们的pdf的一个基类:
///pdf.hpp

// -----------------------------------------------------
// [author] lv
// [ time ] 2019.3
// [brief ] In the Monte Carlo system, pdf acts as the
// most important element of Important-Sample
// ----------------------------------------------------- #pragma once namespace rt
{ // the basic class of pdf system
class pdf
{
public:
/*
@brief: we get the value of pdf function by this interface
@param: the direction of location
@retur: the value of the pdf function
*/
virtual rtvar value(const rtvec & direction)const = ; /*
@brief: generate a random number with a Probability model
@param: none
@retur: the Three-dimensional random vector
*/
virtual rtvec generate()const = ;
}; }//rt namespace

我们来实现关于它的一些子类

首先我们来实现关于cosine 概率密度的模型

///cosine_pdf.hpp

// -----------------------------------------------------
// [author] lv
// [ time ] 2019.3
// [brief ] one of the pdf' forms
// ----------------------------------------------------- #pragma once namespace rt
{ class cosine_pdf :public pdf
{
public:
//constructor
cosine_pdf(const rtvec& w); /*
@brief: we get the value of pdf function by this interface
@param: the direction of location
@retur: the value of the pdf function
*/
virtual rtvar value(const rtvec& direction)const; /*
@brief: generate a random number with a Probability model
@param: none
@retur: the Three-dimensional random vector
*/
virtual rtvec generate()const; private: onb _uvw;
}; inline cosine_pdf::cosine_pdf(const rtvec& w)
{
_uvw.build_from_w(w);
} rtvar cosine_pdf::value(const rtvec& direction)const
{
rtvar cosine = dot(direction.ret_unitization(), _uvw.w());
if (cosine > .)
return cosine / π;
else
return .;
} rtvec cosine_pdf::generate()const
{
return _uvw.local(random_cosine_direction());
}
}

这个模型之前细说过,cosine大于0的时候返回cosine/π,反之,则返回0。因为光线反射之后如果和表面法线的夹角为钝角的时候,违反反射规律,不以反射。生成随机数的那个之前也讲过,在上上一篇

其实这些都不是新东西,就是把之前讲的的那一套整合了一下

得到结果也就是之前的效果

我们把主函数里面的lerp()也改一下

每个像素点采样100次,取均值,即sample 为 100时

这是代码敲错了,意外得到的一张图

现在我们尝试,光源采样,即

///hit_pdf.hpp

// -----------------------------------------------------
// [author] lv
// [ time ] 2019.3
// [brief ] toward to the hitable
// ----------------------------------------------------- #pragma once namespace rt
{ class hit_pdf :public pdf
{
public: /*
@param: info -> Geometry information
origion -> the point of intersection
*/
hit_pdf(intersect* info, const rtvec& origion)
:_intersectp(info)
,_o(origion)
{
} /*
@brief: we get the value of pdf function by this interface
@param: the direction of location
@retur: the value of the pdf function
*/
virtual rtvar value(const rtvec& direction)const
{
return _intersectp->pdf_value(_o, direction);
} /*
@brief: generate a random number with a Probability model
@param: none
@retur: the Three-dimensional random vector
*/
virtual rtvec generate()const
{
return _intersectp->random(_o);
} private: rtvec _o; intersect * _intersectp;
}; }// rt namespace

对应的intersect类也要改一下

/// intersect.hpp
//https://www.cnblogs.com/lv-anchoret/p/10190092.html
// -----------------------------------------------------
// [author] lv
// [begin ] 2018.12
// [refre ] 2019.3
// [brief ] the intersect-class for the ray-tracing project
// from the 《ray tracing in one week》
// ----------------------------------------------------- #pragma once #include "E:\OpenGL\光线追踪\code\ray tracing 1-3\ray tracing 1-3\ray.hpp" namespace rt
{
class material;
class aabb; // the infomation of intersection point struct hitInfo
{
lvgm::precision _t; //ray 中的系数t
rtvec _p; //相交点、撞击点
rtvec _n; //_p点的表面法线
material* _materialp; //材质
rtvar _u; //texture-u
rtvar _v; //texture-v
}; // the statement of intersect class class intersect
{
public: /*
@brief: 撞击函数,求取撞击点相关记录信息
@param: sight->视线
系数t的上下界->筛选撞击点
info->返回撞击点信息
@retur: 是否存在合法撞击点
*/
virtual bool hit(const ray& sight, rtvar t_min, rtvar t_max, hitInfo& info)const = ; /*
@brief: get the box of Geometry
*/
virtual aabb getbox()const = ; /*
Get the value of pdf function
*/
virtual rtvar pdf_value(const rtvec& o, const rtvec& v)const
{
return .;
} /*
generate the random number
*/
virtual rtvec random(const rtvec& o)const
{
return rtvec(, , );
} }; }// rt namespace

因为我们现在只是拿区域光源做实验,并不是所有的几何体派生类都要继承pdf相关的方法,所以,它们两个以虚函数的形式存在即可。

那么就剩下xz长方形了

rtvar xz_rect::pdf_value(const rtvec& o, const rtvec& v)const
{
hitInfo rec;
if (this->hit(ray(o, v), 1e-, rt::rtInf(), rec))
{
rtvar area = (_x2 - _x1)*(_z2 - _z1);
rtvar distance_squared = rec._t * rec._t * v.squar();
rtvar cosine = fabs(dot(v, rec._n) / v.normal());
return distance_squared / (cosine*area);
}
else
return .;
} rtvec xz_rect::random(const rtvec& o)const
{
rtvec random_point = rtvec(_x1 + lvgm::rand01() * (_x2 - _x1), _other, _z1 + lvgm::rand01()*(_z2 - _z1));
return random_point - o;
}

把上一篇写在lerp函数里面的一大堆东西整合到类里面

那么我们的lerp就统一化了:

我们取sample为10,即可得到很好的效果:

现在我们将写一个关于混合概率密度的类:

///mixture_pdf.hpp

// -----------------------------------------------------
// [author] lv
// [ time ] 2019.3
// [brief ] mixture pdfs
// ----------------------------------------------------- #pragma once namespace rt
{ class mixture_pdf :public pdf
{
public: mixture_pdf(pdf * p1, pdf* p2)
{
_p[] = p1;
_p[1] = p2;
} /*
@brief: we get the value of pdf function by this interface
@param: the direction of location
@retur: the value of the pdf function
*/
virtual rtvar value(const rtvec& direction)const
{
return 0.5*_p[]->value(direction) + 0.5*_p[]->value(direction);
} /*
@brief: generate a random number with a Probability model
@param: none
@retur: the Three-dimensional random vector
*/
virtual rtvec generate()const
{
if (lvgm::rand01() < 0.5)
return _p[]->generate();
else
return _p[]->generate();
} private: pdf* _p[]; }; }// rt namespace

我们的lerp函数如下:

我们采样10次得到:

但是觉得效果不是很理想,我们来做一些测试

1. pdf 方程修改为 mixture_pdf = 1/3 * hit_pdf + 2/3  * cosine_pdf

2. pdf 方程修改为 mixture_pdf = 2/3 * hit_pdf + 1/3  * cosine_pdf

3. random修改  2/3 取 hit_pdf产生的随机值, 1/3 取 cosine_pdf 产生的随机值

4. random修改  1/3 取 hit_pdf产生的随机值, 2/3 取 cosine_pdf 产生的随机值

我们去上述方案的3、1,即:

得到图:

这张图显然比均分的效果要好

这里我们看不出到底是random起作用还是value,我们不妨取2、3组合

3把2的彩色噪声消除了些,但是这张图和原始的均分图差不多一样

所以结论,random和value的比例交叉比较好

我们采样1000次得到:

渲染中。。。。(就是清晰了点)

/***********************************************************************************/

跑了一晚上爬起来发现除零错误了,又抽空跑完了

/************************************************************************************/

本书第九章(下一章)介绍了一些关于当前渲染器的看法

作者在描述阴影光线和混合密度设计时,作者个人更偏向于混合密度设计,所以并没有在渲染器中采用阴影光线

作者描述了关于lerp函数中内存问题以及编码的不足

作者描述了关于玻璃材质和镜面的一些处理方法

作者还描述了关于HDR的0~1浮点表示以及RGB分组的0~255表示,还说明了这个渲染器是RGB的且基于物理的,还有一种是基于光谱的,以及两者结合的,但做起来很难,所以我们坚持RGB且基于物理的渲染器。

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

【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-7 混合概率密度的更多相关文章

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

     Preface 往后看了几章,对这本书有了新的理解 上一篇,我们第一次尝试把MC积分运用到了Lambertian材质中,当然,第一次尝试是失败的,作者发现它的渲染效果和现实有些出入,所以结尾处声明要 ...

  2. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探

     Preface 我们今天来把第三本书从开局到现在讲的一大堆理论运用到我们的框架中,那么今天我们首先将原始的材质改为基于重要性采样原理的材质 这一篇是代码工程中进行MC理论应用的初步尝试篇  Read ...

  3. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样

    Chapter7 Sample Lights Directly  Preface 今天我们来讲这个还算牛逼的技术——直接光源采样 之前我们提到过,在2-7 前两篇我们也提到要减少噪点,就是图片上的黑点 ...

  4. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-3 蒙特卡罗 (三)

    开学人倍忙,趁着第二周周末,我们继续图形相关的博客  Preface 今天我们来介绍一些理论方面的东西,为Monte Carlo 应用到我们的光线追踪器做铺垫 我们今天会介绍两章的东西,因为有一章内容 ...

  5. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-2 蒙特卡罗(二) 重要性采样

    书本内容:见相册 preface 还记的我们上一篇说的Monte Carlo 维度诅咒吗 上一篇算是二维的例子吧,大家看了之后是否想着写一个一维的Monte Carlo模拟积分?(我想了,没写出来) ...

  6. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-1 蒙特卡罗 (一)

    今天起,我们就开始学习第三本书了 这本书主要讲的是蒙特卡罗渲染,以及相关的数学.术语概念等 这本书相较于前面两本有着什么不同,承担着什么样的任务,尚涉书未深,姑妄言之: 第一本书,带领我们初探光线追踪 ...

  7. html5的float属性超详解(display,position, float)(文本流)

    html5的float属性超详解(display,position, float)(文本流) 一.总结 1.文本流: 2.float和绝对定位都不占文本流的位置 3.普通流是默认定位方式,就是依次按照 ...

  8. HTML中DOM核心知识有哪些(带实例超详解)

    HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...

  9. Mysql超详解

    Mysql超详解 一.命令框基本操作及连接Mysql 找到Mysql安装路径,查看版本 同时按快捷键win+R会弹出一个框,在框中输入cmd 点击确定后会出现一个黑框,这是命令框,我们的操作要在这命令 ...

随机推荐

  1. mysql 案例~select引起的性能问题

    案例1 背景:测试环境下发现大量select查询,而且负载飙升到90+ 排查思路: 1 老规则,按照排错脚本走一圈,规划出几个元素(1 针对库访问的统计 2针对具体语句类型的统计),发现有大量的sel ...

  2. geeksforgeeks-Array-Rotate and delete

    As usual Babul is again back with his problem and now with numbers. He thought of an array of number ...

  3. 【vue报错】——listen EADDRINUSE :::8080 解决方案

    题原因: 此项错误表示 8080 端口被占用 解决方案一: 打开cmd输入:netstat -ano|findstr "8080"查看所有端口信息,并通过findstr “8080 ...

  4. C++学习2--坦克大战编写-前置知识

    基础班学习的这一个多月里的前三周讲解基础的语法,最后一周需要做坦克大战的项目巩固提高自己掌握的语法知识.这个系列博文主要是为了把学习过程中的知识点总结并记录下来: 开发语言与开发工具:C++,VS20 ...

  5. Windows下Anaconda的安装和简单使用

    Windows下Anaconda的安装和简单使用 Anaconda is a completely free Python distribution (including for commercial ...

  6. Generative Adversarial Nets(原生GAN学习)

    学习总结于国立台湾大学 :李宏毅老师 Author: Ian Goodfellow • Paper: https://arxiv.org/abs/1701.00160 • Video: https:/ ...

  7. MySQL各个版本区别及问题总结

    参考:http://www.admin10000.com/document/62.html 一.简介 MySQL 的官网下载地址:http://www.mysql.com/downloads/ 在这个 ...

  8. linux windows 传输文件

    其中两种方式,当然,只是我自己试验的两个,其实还有别的方法,但是我也懒得实践了. 1  pscp c:\abc.sql root@192.168.1.1:/home/person/hww 2  Lrz ...

  9. PL/SQL第五章 Order by排序

    -- 排序 -- 1.列明排序 -- 2.别名排序 -- 3.列位置排序(当使用union,union all,intersect,minus集合操作,列明不同,但希望排序) SELECT deptn ...

  10. 50个常用的sql语句

    50个常用的sql语句 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,T ...