【Ray Tracing in One Weekend】(ch8)Metal&Lambertian
来源:互联网 发布:java的后缀名 编辑:程序博客网 时间:2024/06/05 07:23
ch8:Metal
再回顾一下上一章中求撞击点颜色的Color()方法:
Vec3 Color(const Ray& r, Hitable *world){ hit_record rec; if (world->hit(r, 0.0, FLT_MAX, rec)) { Vec3 target = rec.p + rec.normal + RandomInUnitSphere(); //递归,每次吸收50%的能量 return 0.5f*Color(Ray(rec.p, target - rec.p), world); } else { //绘制背景 Vec3 unit_direction = unit_vector(r.direction()); float t = 0.5f*(unit_direction.y() + 1.0f); //(1-t)*白色+t*蓝色,结果是一个蓝白的渐变 return (1.0f - t)*Vec3(1.0f, 1.0f, 1.0f) + t*Vec3(0.5f, 0.7f, 1.0f); }}
这里我们给球体的是Diffuse材质,反射方向是随机的,反射率是0.5,即每次光线射入吸收该光线颜色(三个通道)的50%,所以球体会有灰色的趋向(灰色即RGB三值近似)。现实中的Diffuse材质的物体,都有其自身的颜色,其反射率等参数各不相同,为了方便,现在我们把材质也抽象为一个类:
#pragma once#include "Hitable.h"//通过入射光线,计算反射光线Vec3 Reflect(const Vec3& v, const Vec3& n){ return v - 2 * dot(v, n)*n;}//生成随机方向的标准向量Vec3 RandomInUnitSphere(){ Vec3 p; do { p = 2.0f * Vec3((rand() % 100 / float(100)), (rand() % 100 / float(100)), (rand() % 100 / float(100))) - Vec3(1.0f, 1.0f, 1.0f); } while (dot(p, p) >= 1.0f); return p;}//抽象出的材质类class Material {public: virtual bool Scatter(const Ray& r_in, const hit_record& rec, Vec3& attenuation, Ray& scattered) const = 0;};//漫反射材质class Lambertian : public Material {public: Lambertian(const Vec3& a):albedo(a){} virtual bool Scatter(const Ray& r_in, const hit_record& rec, Vec3& attenuation, Ray& scattered) const { Vec3 target = rec.p + rec.normal + RandomInUnitSphere(); scattered = Ray(rec.p, target - rec.p); attenuation = albedo; return true; } Vec3 albedo;};//镜面反射材质class Metal : public Material {public: Metal(const Vec3& a, float f) : albedo(a) { if (f < 1) fuzz = f; else fuzz = 1; } virtual bool Scatter(const Ray& r_in, const hit_record& rec, Vec3& attenuation, Ray& scattered) const { Vec3 reflected = Reflect(unit_vector(r_in.direction()), rec.normal); scattered = Ray(rec.p, reflected + fuzz*RandomInUnitSphere()); attenuation = albedo; return (dot(scattered.direction(), rec.normal) > 0); } Vec3 albedo; float fuzz;};
将求反射光线的部分放到了材质类的Scatter()方法里,每个材质可以自己定义其反射光线。
同时应注意到我们添加了新的材质类型:Metal,用来表现发生镜面反射的材质。
同时修改Main方法为:
Vec3 Color(const Ray& r, Hitable *world, int depth){ hit_record rec; if (world->hit(r, 0.001f, FLT_MAX, rec)) { Ray scattered; Vec3 attenuation; if (depth < 50 && rec.mat_ptr->Scatter(r, rec, attenuation, scattered)) { return attenuation*Color(scattered, world, depth + 1); } else { return Vec3(0.0f, 0.0f, 0.0f); } } else { //绘制背景 Vec3 unit_direction = unit_vector(r.direction()); float t = 0.5f*(unit_direction.y() + 1.0f); //(1-t)*白色+t*蓝色,结果是一个蓝白的渐变 return (1.0f - t)*Vec3(1.0f, 1.0f, 1.0f) + t*Vec3(0.5f, 0.7f, 1.0f); }}int main(){ ofstream outfile; outfile.open("ch8Image_fuzz.ppm"); int nx = 200; int ny = 100; //采样次数 int ns = 100; outfile << "P3\n" << nx << " " << ny << "\n255\n"; Hitable *list[4]; list[0] = new Sphere(Vec3(0.0f, 0.0f, -1.0f), 0.5f, new Lambertian(Vec3(0.8f, 0.3f, 0.3f))); list[1] = new Sphere(Vec3(0.0f, -100.5f, -1.0f), 100.0f, new Lambertian(Vec3(0.8f, 0.8f, 0.0f))); list[2] = new Sphere(Vec3(1.0f, 0.0f, -1.0f), 0.5f, new Metal(Vec3(0.8f, 0.6f, 0.2f),0.3f)); list[3] = new Sphere(Vec3(-1.0f, 0.0f, -1.0f), 0.5f, new Metal(Vec3(0.8f, 0.8f, 0.8f),1.0f)); Hitable *world = new HitableList(list, 4); Camera cam; //随机数引擎 default_random_engine reng; uniform_real_distribution<float> uni_dist(0.0f, 1.0f); for (int j = ny - 1; j >= 0; j--) { for (int i = 0; i < nx; i++) { Vec3 col(0.0f, 0.0f, 0.0f); //每个区域采样ns次 for (int s = 0; s < ns; s++) { float u = float(i + uni_dist(reng)) / float(nx); float v = float(j + uni_dist(reng)) / float(ny); Ray r = cam.getRay(u,v); //Vec3 p = r.point_at_parameter(2.0); //将本区域((u,v)到(u+1,v+1))的颜色值累加 col += Color(r, world, 0); } //获得区域的颜色均值 col /= float(ns); //gamma矫正 col = Vec3(sqrt(col[0]), sqrt(col[1]), sqrt(col[2])); 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;}
渲染结果如图:
同样的,我也作死渲了一个高清版:
阅读全文
0 0
- 【Ray Tracing in One Weekend】(ch8)Metal&Lambertian
- 《Ray Tracing in One Weekend》——Chapter 8: Metal
- 【Ray Tracing in One Weekend】(ch3)射线类
- 【Ray Tracing in One Weekend】(ch7)漫反射材质
- 【Ray Tracing in One Weekend】(ch9)Dielectrics
- 【Ray Tracing in One Weekend】(ch10)Positionable camera
- 总结《Ray Tracing in One Weekend》
- 【Ray Tracing in One Weekend】(ch6)Ray Tracer 里的反走样
- 问题三十:《Ray Tracing In One Weekend》封面图形生成
- 《Ray Tracing in One Weekend》——Chapter 0: Overview
- 《Ray Tracing in One Weekend》——Chapter 6: Antialiasing
- 《Ray Tracing in One Weekend》——Chapter 9: Dielectrics
- 【Ray Tracing in One Weekend】(ch0~1)c++生成的第一张图片
- 【Ray Tracing in One Weekend】(ch2)世界的基石?向量
- 【Ray Tracing in One Weekend】(ch4)场景中第一个物体,球体
- 【Ray Tracing in One Weekend】(ch5)法向量的可视化与多个球的出现
- 《Ray Tracing in One Weekend》——Chapter 1: Output an image
- 《Ray Tracing in One Weekend》——Chapter 2: The vec3 class
- 底部弹出的Popuwindow 用于更换头像
- 服务熔断、降级、限流、异步RPC -- HyStrix
- Python学习流程控制 if 语句、while语句、for..in...循环
- arm-linux-gcc 之 stmdb/stmfd/ldmia/ldmfd or push/pop ???
- Java调用C/C++编写的第三方dll动态链接库(非native API)--- JNI
- 【Ray Tracing in One Weekend】(ch8)Metal&Lambertian
- 使用Delphi怎么连接SQL数据库
- 上传文件保存字节流,下载
- hrbust 1401 九连环
- 【技巧】Eclipse ctrl+左键 进入方法
- 光标函数(自己整理的,求指导)
- ubuntu下修改键位
- python中subprocess.Popen执行命令并持续获取返回值
- 《Java编程技巧1001条》358条:控制随机整数的范围