所有光线追踪器所具有的一件事就是ray类射线进行像素颜色的采集。 让我们将射线看作函数p(t)= A + t * B。这里p是一个3D位置,沿着3D线。 A是射线源,B是射线方向,射线参数是t。 [
#ifndef RAYH
#define RAYH
#include “vec3.h”
class ray
{
public:
ray() { }
ray(const vec3& a, const vec3& b) { A = a; B = b; }
vec3 origin() const { return A; }
vec3 direction() const { return B; }
vec3 point_at_parameter(float t) const { return A + t* B; }
vec3 A;
vec3 B;
};
#endif
假定观测者位于原点处,他将观测上图所示的截面。为了获得每个像素的颜色,观测者将向该像素所在的位置发射出一条射线(ray)进行采样。 作者使用右手坐标系,观察点在(0,0,0),y轴向上,x轴向右,屏幕里面是z的负轴,u,v偏移量表示距离左下角的距离。 [
#include
#include
#include “ray.h”
using namespace std;
vec3 Color(const ray& r)
{
vec3 unit_direction = unit_vector(r.direction());
//t从0到1
float t = 0.5f \* (unit\_direction.y() + 1.0f);
//线性混合,t=1时蓝色,t=0时白色,t介于中间时是混合颜色
//blended\_value = (1-t)\*start\_value + t\*end\_value
return (1.0f - t) \* vec3(1.0, 1.0, 1.0) + t \* vec3(0.5, 0.7, 1.0);
}
int main()
{
ofstream outfile;
outfile.open(“IMG.ppm”);
int nx = 800;
int ny = 400;
outfile << "P3\\n" << nx << " " << ny << "\\n255\\n";
//视锥体左下角
vec3 lower\_left\_corner(-2.0f, -1.0f, -1.0f);
//距离左下角的水平距离
vec3 horizontal(4.0f, 0.0f, 0.0f);
//距离左下角的垂直距离
vec3 vertical(0.0f, 2.0f, 0.0f);
//起始点
vec3 origin(0.0f, 0.0f, 0.0f);
for (int j = ny - 1; j >= 0; j--)
{
for (int i = 0; i < nx; i++)
{
//u从0开始越来越接近1;v从无限接近1开始,越来越接近0
float u = float(i) / float(nx);
float v = float(j) / float(ny);
ray r(origin, lower\_left\_corner +u \* horizontal + v \* vertical);
vec3 col = Color(r);
int ir = int(255.99 \* col\[0\]);
int ig = int(255.99 \* col\[1\]);
int ib = int(255.99 \* col\[2\]);
outfile << ir << " " << ig << " " << ib << "\\n";
}
}
outfile.close();
return 0;
}
运行效果: 参考书籍:《Ray Tracing in One Weekend》 RTIOW系列项目地址:GitHub RTIOW系列笔记: RTIOW-ch1:Output an image RTIOW-ch2:The vec3 class RTIOW-ch3:Rays, a simple camera, and background RTIOW-ch4:Adding a sphere RTIOW-ch5:Surface normals and multiple objects RTIOW-ch6:Antialiasing RTIOW-ch7:Diffuse Materials RTIOW-ch8:Metal RTIOW-ch9:Dielectrics RTIOW-ch10:Positionable camera RTIOW-ch11:Defocus Blur RTIOW-ch12:Where next