Skip to content
Snippets Groups Projects
Commit 15feef3a authored by Yoel's avatar Yoel
Browse files

EmissionProfile implemented

parent a3d91781
No related branches found
No related tags found
No related merge requests found
#include "EmissionProfile.h"
#include <math.h>
#include <algorithm>
#include <numeric>
#include "../tools/Random.h"
namespace util {
EmissionProfile::EmissionProfile(const std::shared_ptr<util::Sampler>& emission,
float intensity)
: emission(emission),
uniform(true),
cdf(),
intensity(intensity),
normalizer(0.0f),
distribution(std::nullopt){};
EmissionProfile::EmissionProfile(const std::shared_ptr<util::Sampler>& emission,
const Image& distribution, float intensity)
: emission(emission),
uniform(false),
intensity(intensity),
distribution(std::make_optional(distribution)) {
// vec: a vector with texel and grey value
std::vector<std::pair<std::pair<float, float>, float>> vec;
for (int w = 0; w <= distribution.width; w++) {
for (int h = 0; h <= distribution.height; h++) {
auto xyz = distribution[{w, h}];
float grey = 0.299f * xyz[0] + 0.587f * xyz[1] + 0.114f * xyz[2];
vec.push_back({{(float)w / (float)distribution.width,
(float)h / (float)distribution.height},
grey});
}
}
// Sort the value from biggest to smallest v
std::sort(vec.begin(), vec.end(),
[](std::pair<std::pair<float, float>, float> a,
std::pair<std::pair<float, float>, float> b) {
return a.second > b.second;
});
// Build cdf
cdf = {};
float cumm = 0;
for (auto x : vec) {
cumm += x.second;
// std::cout << cumm << std::endl;
cdf.push_back({x.first, cumm});
}
// Transform cdf to cap at 1
for (int i = 0; i < cdf.size(); i++) {
cdf[i].second = cdf[i].second / cumm;
}
// Normalizer
normalizer = (distribution.width * distribution.height) / cumm;
};
std::pair<float, float> EmissionProfile::sample() const {
if (uniform) {
return {(float)util::dis0to1(util::gen),
(float)util::dis0to1(util::gen)};
} else {
auto s = dis0to1(gen);
auto res = binary_search(s);
return res.first;
}
};
util::Vec3 EmissionProfile::color(float x, float y) const {
return emission->color(x, y);
}
std::optional<float> EmissionProfile::pdf(float x, float y) const {
if (uniform) return std::nullopt;
auto xyz = distribution->color(x, y);
return std::make_optional<float>(
(0.299f * xyz[0] + 0.587f * xyz[1] + 0.114f * xyz[2]) * normalizer);
}
std::pair<std::pair<float, float>, float> EmissionProfile::binary_search(
float target, int start, int end) const {
int mid;
if (end == -1) end = cdf.size();
while (start <= end) {
mid = (start + end) / 2;
if (cdf[mid].second <= target)
start = mid + 1;
else
end = mid - 1;
}
return cdf[mid];
}
// Not used
std::pair<std::pair<float, float>, float> EmissionProfile::exponential_search(
float target) const {
if (cdf[0].second >= target) return cdf[0];
int start = 1;
while (start < cdf.size() && cdf[start].second <= target) start = 2 * start;
return binary_search(target, start / 2, std::min<int>(start, cdf.size()));
}
} // namespace util
\ No newline at end of file
#pragma once
#include <optional>
#include "../sampling/Image.h"
#include "../sampling/Sampler.h"
namespace util {
class EmissionProfile : public Sampler {
public:
// Uniform distribution constructor
EmissionProfile(const std::shared_ptr<util::Sampler>& emission,
float intensity = 1);
// Image distribution constructor
EmissionProfile(const std::shared_ptr<util::Sampler>& emission,
const Image& distribution, float intensity = 1);
// Returns a texels based on distribution
std::pair<float, float> sample() const;
util::Vec3 color(float x, float y) const override;
std::optional<float> pdf(float x, float y) const;
private:
std::shared_ptr<util::Sampler> emission;
std::optional<Image> distribution;
std::vector<std::pair<std::pair<float, float>, float>> cdf;
std::pair<std::pair<float, float>, float> binary_search(float target,
int start = 0,
int end = -1) const;
std::pair<std::pair<float, float>, float> exponential_search(
float target) const;
bool uniform;
float intensity;
float normalizer;
};
} // namespace util
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment