-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrenderer.cpp
More file actions
102 lines (78 loc) · 2.66 KB
/
renderer.cpp
File metadata and controls
102 lines (78 loc) · 2.66 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <QtMath>
#include "material.h"
#include "renderer.h"
#include "utility.h"
#include "ray.h"
Renderer::Renderer(int imageWidth, Camera* camera, HittableList* world, QObject* parent)
:QThread(parent),
_imageWidth(imageWidth),
_camera(camera),
_world(world)
{
}
void Renderer::run()
{
const auto aspectRatio = 16.0 / 9.0;
const int imageHeight = static_cast<int>(_imageWidth / aspectRatio);
const int samplesPerPixel = 100; //Very heavy effect on operation time
const int maxDepth = 50;
QImage* image = new QImage(_imageWidth, imageHeight, QImage::Format_RGB32);
for (int j = 0; j < imageHeight; j++)
{
emit updateProgressBar(j + 1);
for (int i = 0; i < _imageWidth; i++)
{
QVector3D pixelColor(0, 0, 0);
for (int s = 0; s < samplesPerPixel; s++)
{
auto u = (i + Utility::randomDouble()) / (_imageWidth - 1);
auto v = (j + Utility::randomDouble()) / (imageHeight - 1);
Ray r = _camera->getRay(u, v);
pixelColor += rayColor(r, *_world, maxDepth);
}
image->setPixel(i, imageHeight - 1 - j, colorValue(pixelColor, samplesPerPixel));
}
}
emit imageDone(*image);
}
QRgb Renderer::colorValue(QVector3D pixelColor, int samplesPerPixel)
{
auto r = pixelColor.x();
auto g = pixelColor.y();
auto b = pixelColor.z();
auto scale = 1.0 / samplesPerPixel;
r *= scale;
g *= scale;
b *= scale;
// r *= qSqrt(scale * r); //gamma-correct for gamma=2.0.
// g *= qSqrt(scale * g);
// b *= qSqrt(scale * b);
int ir = static_cast<int>(256 * Utility::clamp(r, 0.0, 0.999));
int ig = static_cast<int>(256 * Utility::clamp(g, 0.0, 0.999));
int ib = static_cast<int>(256 * Utility::clamp(b, 0.0, 0.999));
return qRgb(ir, ig, ib);
}
QVector3D Renderer::rayColor(const Ray& r, const Hittable& world, int depth)
{
HitRecord rec;
QVector3D nullColor(0, 0, 0);
if (depth <= 0)
{
return nullColor;
}
const double shadowAcneFixCoefficient = 0.001;
if (world.hit(r, shadowAcneFixCoefficient, infinity, rec))
{
Ray scattered;
QVector3D colorAttenuation;
AbstractMaterial* material = rec.material();
if (material->scatter(r, rec, colorAttenuation, scattered))
{
return colorAttenuation * rayColor(scattered, world, depth-1);
}
return nullColor;
}
QVector3D unitDirection = Utility::unitVector(r.direction());
auto t = 0.5*(unitDirection.y() + 1.0);
return (1.0 - t) * QVector3D(1.0, 1.0, 1.0) + t * QVector3D(0.5, 0.7, 1.0);
}