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 82
| #include "../3rdParty/svpng/svpng.inc" #include "../Chapter6/Camera.h" #include "Sphere.h" #include "CollisibleList.h" #include "Metal.h" #include "Lambertian.h" #include <cstdio> #include <limits>
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; }
Color3f paint(const Ray &r, const Collisible &obj, int depth) { CollideRecord rec; if (obj.collide(r, 0.001f, std::numeric_limits<float>::max(), rec)) { Ray scattered; Vector3f attenuation; if (depth < 50 && rec.material->scatter(r, rec, attenuation, scattered)) { return attenuation * paint(scattered, obj, depth + 1); } return {0.0f, 0.0f, 0.0f}; }
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("ch8.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[4]; Material *mats[4]; mats[0] = new Lambertian({0.8, 0.3, 0.3}); mats[1] = new Lambertian({0.8, 0.8, 0.0}); mats[2] = new Metal({0.8, 0.6, 0.2}, 0.3); mats[3] = new Metal({0.8, 0.8, 0.8}, 0.3);
obj[0] = new Sphere({0, 0, -1}, 0.5, mats[0]); obj[1] = new Sphere({0, -100.5, -1}, 100, mats[1]); obj[2] = new Sphere({1, 0, -1}, 0.5, mats[2]); obj[3] = new Sphere({-1, 0, -1}, 0.5, mats[3]);
for (int i = 0; i < 4; i++) list.add(obj[i]);
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 + genFloat()) / WIDTH; float v = (float)(y + genFloat()) / HEIGHT; col += paint(camera.getRay(u, v), list, 0); } col /= SAMPLE_TIMES; col = {sqrtf(col[0]), sqrtf(col[1]), sqrtf(col[2])}; paint(d, x, y, col, 1.0f); } }
for (int i = 0; i < 4; i++) delete mats[i]; for (int i = 0; i < 4; i++) delete obj[i]; svpng(f, WIDTH, HEIGHT, d, 1); fclose(f); }
|