基础光线追踪(7) - 漫反射材质

基础光线追踪(7) - 漫反射材质

实现简单的漫反射材质。

漫反射材质

漫反射材料不发光,只吸收和反射环境的光(反射光的方向是随机的),所以将漫射材料的球体的颜色设置为背景颜色乘以某系数是合理的(如 $\frac 1 2$)。
对于反射光方向,在交点处单位法向量的基础上加上一个长度小于 $1$ 的随机向量即可。

Chapter7 Pre

伽马校正

对于 $\frac 1 2$ 的系数,我们需要对颜色开根进行伽马校正。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "../3rdParty/svpng/svpng.inc"
#include "../Chapter5/Sphere.h"
#include "../Chapter5/CollisibleList.h"
#include "../Chapter6/Camera.h"
#include <cstdio>
#include <limits>
#include <random>
#include <functional>

const int WIDTH = 640;
const int HEIGHT = 480;

using byte = unsigned char;

void paint(byte *d, int x, int y, Color3f color, float alpha) {
d += 4 * ((HEIGHT - y - 1) * WIDTH + x);
d[0] = 255 * color.r;
d[1] = 255 * color.g;
d[2] = 255 * color.b;
d[3] = 255 * alpha;
}

Color3f mix(const Color3f &a, const Color3f &b, float t) { return a * (1.0f - t) + b * t; }

std::uniform_real_distribution<float> dis;
std::mt19937 engine;
auto gen = std::bind(dis, engine);

Vector3f getRandomUnit() {
Vector3f p;
do {
p = 2.0f * Vector3f(gen(), gen(), gen()) - Vector3f(1, 1, 1);
} while (p.length2() >= 1.0);
return p;
}

Color3f paint(const Ray &r, const Collisible &obj) {
CollideRecord rec;
if (obj.collide(r, 0.001f, std::numeric_limits<float>::max(), rec))
return 0.5f * paint({rec.p, rec.normal + getRandomUnit()}, obj);

Vector3f dir = r.getDir();
float t = 0.5f * (dir.y + 1.0f);
return mix({1.0f, 1.0f, 1.0f}, {0.5f, 0.7f, 1.0f}, t);
}

int main() {
byte d[4 * WIDTH * HEIGHT];
FILE *f = fopen("ch7.png", "wb");

Camera camera({0.0f, 0.0f, 0.0f}, {-2.0f, -1.5f, -1.0f}, {4.0f, 0.0f, 0.0f},
{0.0f, 3.0f, 0.0f});

CollisibleList list;
Collisible *obj[2];
obj[0] = new Sphere({0, 0, -1}, 0.5);
obj[1] = new Sphere({0, -100.5, -1}, 100);

list.add(obj[0]);
list.add(obj[1]);

const int SAMPLE_TIMES = 100;
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
Color3f col;
for (int i = 0; i < SAMPLE_TIMES; i++) {
float u = (float)(x + gen()) / WIDTH;
float v = (float)(y + gen()) / HEIGHT;
col += paint(camera.getRay(u, v), list);
}
col /= SAMPLE_TIMES;
col = {sqrtf(col[0]), sqrtf(col[1]), sqrtf(col[2])};
paint(d, x, y, col, 1.0f);
}
}

delete obj[0];
delete obj[1];
svpng(f, WIDTH, HEIGHT, d, 1);
fclose(f);
}

效果

Chapter7

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×