【Ray Trace from Groud Up】光线追踪代码实现解析

本文深入探讨光线追踪技术的核心——Whitted算法,并详细解析其在光线追踪场景中的应用。通过实现一个追踪类和材质构造,文章展示了如何在场景中追踪反射光线并准确地进行渲染。此外,还介绍了PLY文件格式、多焦距取样技术、Pinhole相机布局及不同材质的光照计算方法,为光线追踪领域的实践者提供深入理解。

代码资源下载

-------------------------------------------------------------------------------------------------------------------------------

总体结构框架:


本节采用的光线追踪算法是Whitted 发明的。 trace the reflected rays as they bounce between reflective objects in the scene. 具体分为下面5个步骤:

1.添加max_depth 标示最大碰撞次数;

2.ray tracer 记录光线碰撞次数

3. 实现一个新的追踪类whitted, 该类中 trace_ray 使用记录

4.使用 PerfectSpecular BRDF

5 implement 至少一个 reflective material constructs the reflected rays and ray traces them

vp.set_hres(600);      
vp.set_vres(600);    
vp.set_samples(num_samples); 
vp.set_max_depth(2);    

tracer_ptr = new Whitted(this); 
background_color = black;

MultiJittered* sampler_ptr = new MultiJittered(num_samples);

返回黑色当深度值大于 max_depth 并且把 它存储在 ShadeRec 对象中。 这个函数循环调用。

RGBColor    
Whitted::trace_ray(const Ray ray, const int depth) const { 
    if (depth > world_ptr->vp.max_depth) 
        return(black); 
    else { 
        ShadeRec sr(world_ptr->hit_objects(ray));    
                    
        if (sr.hit_an_object) { 
            sr.depth = depth; 
            sr.ray = ray;    
            return (sr.material_ptr->shade(sr));   
        } 
        else 
            return (world_ptr->background_color); 
    } 
}


定义一个A Reflective Material 材质,继承Phong 模型,这样可以使用 ambient,diffuse and specular direct illumination。

该函数中也是循环调用了 trace_ray , 因为Whitted::trace_ray中也是循环调用的

RGBColor 
Reflective::shade(ShadeRec& sr) {    
    RGBColor L(Phong::shade(sr));  // direct illumination 
    
    Vector3D wo = -sr.ray.d; 
    Vector3D wi;    
    RGBColor fr = reflective_brdf->sample_f(sr, wo, wi); 
    Ray reflected_ray(sr.hit_point, wi); 
    reflected_ray.depth = sr.depth + 1; 
    
    L += fr * sr.w.tracer_ptr->trace_ray(reflected_ray, sr.depth + 1) * (sr.normal * wi); 
                    
    return (L); 
}

Ply Files:

PLY 文件是Greg Turk 在90年代中期首创用于存储多边形meshes 。这种文件格式可以是ASCII 或者 二进制,本例子中使用的PLY 文件用于存储三角形坐标(x,y,z)和有索引信息的三角形面片。如下,3 0 1 2 的3 表示有3 个顶点,0,1,2 表示顶点索引 


Computing the Normals

使用顶点周围的三角形,按相邻三角形信息可以优化算法

for each vertex{

      normal = zero normal

for each triangle that shares the vertex

      add the triangle normal to normal

normalize the normal

}

add the normal to the mesh

multi-Jittered Sampling

为什么需要使用 采样呢?

1. avoid aliasing when samping pixels

2. Cameras with a finite-area lens are used to show depth of field, the lens must be samples

3.to represent area lights and soft shadows more accurately, we must sample the light suiraces

4.Global illumination and glossy reflection requires sampling of BRDFs ans BTDFs

本质上说,该技术结合了 jittering 和 n-rooks 采样技术

16 * 16 的grid,分为 4 * 4的 grid,用随机方法初始化每个 4*4 的 grid jittered 分配,也是 n-rooks 分配方法


Pinhole

Camera Arrangements

 每个相机都有自己的 look-at 点 , 所以视线方向是平行的(with toe-in, the left and right cameras have a common look-at point )。view planes 都是一致的

两个窗口也是一致的,这点要求摄像机使用非对称的 view frustums 视体锥


这样,左右摄像机的window需要做偏移,如下


pinhole_ptr->set_eye(-6, 5, 11);        
pinhole_ptr->set_lookat(0 , 0, 0); 
pinhole_ptr->set_view_distance(5200);  
pinhole_ptr->compute_uvw();     
set_camera(pinhole_ptr); 

The purpose of each shading function is to compute the exitant  radiance at the hit point in the w0 direction

we specify a matte materail with an ambient reflection coefficient ka, a diffuse reflection coefficient kd, and

a diffuse color cd.


The Matte:: shade function in listing computes the ambient illumination and then loops over the lights to compute

the direct diffuse illumination.   the ambient BRDF calls rho and the diffuse BRDF callls f.   先计算漫反射,然后计算

diffuse specular reflection. 

RGBColor
Matte::shade(ShadeRec& sr) {

	Vector3D 	wo 			= -sr.ray.d;
	RGBColor 	L 			= ambient_brdf->rho(sr, wo) * sr.w.ambient_ptr->L(sr);
	int 		num_lights	= sr.w.lights.size();

	for (int j = 0; j < num_lights; j++) {
		Vector3D wi = sr.w.lights[j]->get_direction(sr);
		float ndotwi = sr.normal * wi;

		if (ndotwi > 0.0) {

			bool in_shadow = false;
			if (sr.w.lights[j]->casts_shadows()) {
				Ray shadowRay(sr.hit_point, wi);
				in_shadow = sr.w.lights[j]->in_shadow(shadowRay, sr);
			}

			if (!in_shadow)
				L += diffuse_brdf->f(sr, wo, wi) * sr.w.lights[j]->L(sr) * ndotwi;
		}
	}

	return (L);
}

Perfect Diffuse DRBF: where incident radiance is scattered equally in all directions.The function f returns the BRDF itself, unless it contains a delta function.

The function sample_f is use to compute the direction of reflected rays for simulating reflective materials and diffuse-diffuse light transport. 

 The function rho returns the bihemispherical reflectance phh.  in plain English, it means that the incoming radiance is the same from all directions and doesn’t vary with position.

in Lambertian, phh = kd * cd.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不负初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值