Код: Выделить всё
void Render(const Camera& camera, std::vector& color_buffer) {
constexpr float fSAMPLES_PER_PIXEL = static_cast(SAMPLES_PER_PIXEL);
#pragma omp parallel for
for (uint32_t y = 0; y < IMG_HEIGHT; y++) {
for (uint32_t x = 0; x < IMG_WIDTH; x++) {
glm::vec3 color{0.0f};
for (uint32_t i = 0; i < SAMPLES_PER_PIXEL; i++) {
// TODO: Perform better AA
Ray ray = camera.RayThrough(x + Util::RandomFloat() - 0.5f, y + Util::RandomFloat() - 0.5f);
color += TraceRay(ray);
}
color_buffer[y * IMG_WIDTH + x] = color / fSAMPLES_PER_PIXEL;
}
}
}
Код: Выделить всё
glm::vec3 TraceRay(Ray& ray) {
glm::vec3 Lo{0.0f};
glm::vec3 throughput{1.0f};
for (uint32_t i = 0; i emission;
const glm::vec3 wo = glm::normalize(-ray.direction);
const Sample sample = material->sample(wo, hp.normal);
// PDF near zero => extremely unlikely path
if (sample.pdf < Util::EPSILON)
break;
const float cosine = glm::dot(sample.wi, hp.normal);
const glm::vec3 brdf = material->f(sample.wi, wo, hp.normal);
throughput *= brdf * cosine / sample.pdf;
// throughput has decreased so much => not much point in continuing
if (throughput.x < Util::EPSILON && throughput.y < Util::EPSILON && throughput.z < Util::EPSILON)
break;
// Russian roulette
static uint32_t ITERS_BEFORE_RR = 5;
const float p = glm::max(glm::max(throughput.x, throughput.y), throughput.z);
if (i >= ITERS_BEFORE_RR && Util::RandomFloat() > p) {
break;
}
throughput *= (1.0f / p);
// Bounce ray
ray.origin = hp.position + Util::EPSILON * sample.wi;
ray.direction = sample.wi;
}
return Lo;
}
glm::vec3 Environment(const Ray& ray) {
static const glm::vec3 SKY_COLOR{ 0.5f, 0.7f, 1.0f };
const float alpha = 0.5f * (glm::normalize(ray.direction).y + 1.0f);
const glm::vec3 skyColor = alpha * SKY_COLOR + (1.0f - alpha) * glm::vec3{1.0f};
return skyColor;
}
Код: Выделить всё
#pragma once
#include "Material.hpp"
#include "../Util.hpp"
#include
#include
#include
struct Lambertian : Material {
Lambertian(const glm::vec3 color, const glm::vec3 emission = glm::vec3(0.0f))
: Material(color, emission) {}
[[nodiscard]] glm::vec3 f(const glm::vec3& wi, const glm::vec3& wo, const glm::vec3& normal) const {
const glm::vec3 brdf = color / glm::pi();
return brdf;
}
[[nodiscard]] Sample sample(const glm::vec3& wo, const glm::vec3& normal) const {
const Sample sample{
.wi = Util::CosineSampleHemisphere(normal),
.pdf = glm::max(glm::dot(sample.wi, normal), 0.0f) / glm::pi()
};
return sample;
}
};
Код: Выделить всё
#pragma once
#include "Material.hpp"
#include "../Util.hpp"
#include
#include
#include
struct Mirror : Material {
Mirror(const glm::vec3 color, const glm::vec3 emission = glm::vec3(0.0f))
: Material(color, emission) {}
[[nodiscard]] glm::vec3 f(const glm::vec3& wi, const glm::vec3& wo, const glm::vec3& normal) const {
const glm::vec3 brdf = color;
return brdf;
}
[[nodiscard]] Sample sample(const glm::vec3& wo, const glm::vec3& normal) const {
const Sample sample{
.wi = glm::reflect(-wo, normal),//-wo - 2 * glm::dot(-wo, normal) * normal,
.pdf = 1.0f
};
return sample;
}
};
Код: Выделить всё
#include "Util.hpp"
#include
#include
static thread_local std::random_device rd;
static thread_local std::mt19937 generator(rd());
float Util::RandomFloat()
{
std::uniform_real_distribution dist(0, 1);
return dist(generator);
}
float Util::RandomFloat(const float &a, const float &b)
{
return a + (b - a) * RandomFloat();
}
int Util::RandomInt(const int& a, const int& b)
{
return int(RandomFloat(a, b + 1));
}
glm::vec3 Util::CosineSampleHemisphere(const glm::vec3 &normal)
{
float r1 = RandomFloat();
float r2 = RandomFloat();
float phi = 2.0f * Util::PI * r1;
float x = std::cos(phi) * std::sqrt(r2);
float y = std::sin(phi) * std::sqrt(r2);
float z = std::sqrt(1.0f - r2);
return Util::ToNormalCoordSystem({x, y, z}, normal);
}
glm::vec3 Util::ToNormalCoordSystem(const glm::vec3 &local, const glm::vec3 &normal)
{
const glm::vec3 up = std::abs(normal.z) < 0.999f ? glm::vec3(0, 0, 1) : glm::vec3(1, 0, 0);
const glm::vec3 tangent = glm::normalize(glm::cross(up, normal));
const glm::vec3 bitangent = glm::cross(normal, tangent);
return glm::normalize(tangent * local.x + bitangent * local.y + normal * local.z);
}
std::cout
Подробнее здесь: https://stackoverflow.com/questions/794 ... too-bright