Skip to content

Commit

Permalink
feature: implement GaussianFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
w3ntao committed Jan 3, 2025
1 parent 2436761 commit 6a8eecf
Show file tree
Hide file tree
Showing 18 changed files with 318 additions and 86 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ add_executable(${PROJ_NAME}
src/pbrt/films/grey_scale_film.cu
src/pbrt/films/rgb_film.cu

src/pbrt/filters/box.cu
src/pbrt/filters/mitchell.cu
src/pbrt/filters/gaussian.cu

src/pbrt/integrators/ambient_occlusion.cu
src/pbrt/integrators/bdpt.cu
Expand Down
22 changes: 17 additions & 5 deletions src/pbrt/base/film.cu
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void Film::init(RGBFilm *rgb_film) {
PBRT_CPU_GPU
Point2i Film::get_resolution() const {
switch (type) {
case (Type::rgb): {
case Type::rgb: {
return static_cast<const RGBFilm *>(ptr)->get_resolution();
}
}
Expand All @@ -33,10 +33,22 @@ Point2i Film::get_resolution() const {
return {};
}

PBRT_CPU_GPU
const Filter *Film::get_filter() const {
switch (type) {
case Type::rgb: {
return static_cast<const RGBFilm *>(ptr)->get_filter();
}
}

REPORT_FATAL_ERROR();
return nullptr;
}

PBRT_CPU_GPU
Bounds2f Film::sample_bounds() const {
switch (type) {
case (Type::rgb): {
case Type::rgb: {
return static_cast<const RGBFilm *>(ptr)->sample_bounds();
}
}
Expand All @@ -49,7 +61,7 @@ PBRT_CPU_GPU
void Film::add_sample(uint pixel_index, const SampledSpectrum &radiance_l,
const SampledWavelengths &lambda, FloatType weight) {
switch (type) {
case (Type::rgb): {
case Type::rgb: {
return static_cast<RGBFilm *>(ptr)->add_sample(pixel_index, radiance_l, lambda, weight);
}
}
Expand All @@ -61,7 +73,7 @@ PBRT_CPU_GPU
void Film::add_sample(const Point2i &p_film, const SampledSpectrum &radiance_l,
const SampledWavelengths &lambda, FloatType weight) {
switch (type) {
case (Type::rgb): {
case Type::rgb: {
return static_cast<RGBFilm *>(ptr)->add_sample(p_film, radiance_l, lambda, weight);
}
}
Expand All @@ -72,7 +84,7 @@ void Film::add_sample(const Point2i &p_film, const SampledSpectrum &radiance_l,
void Film::add_splat(const Point2f &p_film, const SampledSpectrum &radiance_l,
const SampledWavelengths &lambda) {
switch (type) {
case (Type::rgb): {
case Type::rgb: {
return static_cast<RGBFilm *>(ptr)->add_splat(p_film, radiance_l, lambda);
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/pbrt/base/film.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class Film {
PBRT_CPU_GPU
Point2i get_resolution() const;

PBRT_CPU_GPU
const Filter *get_filter() const;

PBRT_CPU_GPU
Bounds2f sample_bounds() const;

Expand Down
88 changes: 60 additions & 28 deletions src/pbrt/base/filter.cu
Original file line number Diff line number Diff line change
@@ -1,58 +1,70 @@
#include "pbrt/base/filter.h"
#include "pbrt/filters/box.h"
#include "pbrt/filters/gaussian.h"
#include "pbrt/filters/mitchell.h"

const Filter *Filter::create_box_filter(FloatType radius,
std::vector<void *> &gpu_dynamic_pointers) {
BoxFilter *box_filter;
CHECK_CUDA_ERROR(cudaMallocManaged(&box_filter, sizeof(BoxFilter)));

const Filter *Filter::create(const std::string &filter_type, const ParameterDictionary &parameters,
std::vector<void *> &gpu_dynamic_pointers) {
Filter *filter;
CHECK_CUDA_ERROR(cudaMallocManaged(&filter, sizeof(Filter)));

gpu_dynamic_pointers.push_back(box_filter);
gpu_dynamic_pointers.push_back(filter);

box_filter->init(radius);
filter->init(box_filter);
if (filter_type == "box") {
auto box_filter = BoxFilter::create(parameters, gpu_dynamic_pointers);

return filter;
}
filter->init(box_filter);

const Filter *Filter::create_mitchell_filter(const Vector2f &radius, FloatType b, FloatType c,
std::vector<void *> &gpu_dynamic_pointers) {
MitchellFilter *mitchell_filter;
CHECK_CUDA_ERROR(cudaMallocManaged(&mitchell_filter, sizeof(MitchellFilter)));
gpu_dynamic_pointers.push_back(mitchell_filter);
mitchell_filter->init(radius, b, c);
return filter;
}

Filter *filter;
CHECK_CUDA_ERROR(cudaMallocManaged(&filter, sizeof(Filter)));
gpu_dynamic_pointers.push_back(filter);
if (filter_type == "gaussian") {
auto gaussian_filter = GaussianFilter::create(parameters, gpu_dynamic_pointers);

filter->init(mitchell_filter);
mitchell_filter->build_filter_sampler(filter, gpu_dynamic_pointers);
filter->init(gaussian_filter);
gaussian_filter->init_sampler(filter, gpu_dynamic_pointers);

return filter;
}

return filter;
if (filter_type == "mitchell") {
auto mitchell_filter = MitchellFilter::create(parameters, gpu_dynamic_pointers);

filter->init(mitchell_filter);
mitchell_filter->init_sampler(filter, gpu_dynamic_pointers);

return filter;
}

REPORT_FATAL_ERROR();
return nullptr;
}

void Filter::init(const BoxFilter *box_filter) {
ptr = box_filter;
type = Type::box;
}

void Filter::init(const GaussianFilter *gaussian_filter) {
ptr = gaussian_filter;
type = Type::gaussian;
}

void Filter::init(const MitchellFilter *mitchell_filter) {
ptr = mitchell_filter;
type = Type::mitchell;
}

PBRT_CPU_GPU
Vector2f Filter::radius() const {
Vector2f Filter::get_radius() const {
switch (type) {
case Type::box: {
return static_cast<const BoxFilter *>(ptr)->get_radius();
}

case Type::gaussian: {
return static_cast<const GaussianFilter *>(ptr)->get_radius();
}

case Type::mitchell: {
return static_cast<const MitchellFilter *>(ptr)->get_radius();
}
Expand All @@ -65,6 +77,14 @@ Vector2f Filter::radius() const {
PBRT_CPU_GPU
FloatType Filter::get_integral() const {
switch (type) {
case Type::box: {
return static_cast<const BoxFilter *>(ptr)->get_integral();
}

case Type::gaussian: {
return static_cast<const GaussianFilter *>(ptr)->get_integral();
}

case Type::mitchell: {
return static_cast<const MitchellFilter *>(ptr)->get_integral();
}
Expand All @@ -78,7 +98,15 @@ FloatType Filter::get_integral() const {
PBRT_CPU_GPU
FloatType Filter::evaluate(const Point2f p) const {
switch (type) {
case (Type::mitchell): {
case Type::box: {
return static_cast<const BoxFilter *>(ptr)->evaluate(p);
}

case Type::gaussian: {
return static_cast<const GaussianFilter *>(ptr)->evaluate(p);
}

case Type::mitchell: {
return static_cast<const MitchellFilter *>(ptr)->evaluate(p);
}
}
Expand All @@ -90,11 +118,15 @@ FloatType Filter::evaluate(const Point2f p) const {
PBRT_CPU_GPU
FilterSample Filter::sample(const Point2f u) const {
switch (type) {
case (Type::box): {
case Type::box: {
return static_cast<const BoxFilter *>(ptr)->sample(u);
}

case (Type::mitchell): {
case Type::gaussian: {
return static_cast<const GaussianFilter *>(ptr)->sample(u);
}

case Type::mitchell: {
return static_cast<const MitchellFilter *>(ptr)->sample(u);
}
}
Expand All @@ -115,7 +147,7 @@ const FilterSampler *FilterSampler::create(const Filter *filter,
}

void FilterSampler::init(const Filter *filter, std::vector<void *> &gpu_dynamic_pointers) {
const auto filter_radius = filter->radius();
const auto filter_radius = filter->get_radius();

domain = Bounds2f(Point2f(-filter_radius), Point2f(filter_radius));
f.init(int(32 * filter_radius.x), int(32 * filter_radius.y), gpu_dynamic_pointers);
Expand Down
23 changes: 13 additions & 10 deletions src/pbrt/base/filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include <vector>

class BoxFilter;
class GaussianFilter;
class MitchellFilter;
class ParameterDictionary;

struct FilterSample {
Point2f p;
Expand All @@ -24,21 +26,16 @@ class Filter {
public:
enum class Type {
box,
gaussian,
mitchell,
};

static const Filter *create_box_filter(FloatType radius,
std::vector<void *> &gpu_dynamic_pointers);

static const Filter *create_mitchell_filter(const Vector2f &radius, FloatType b, FloatType c,
std::vector<void *> &gpu_dynamic_pointers);

void init(const BoxFilter *box_filter);

void init(const MitchellFilter *mitchell_filter);
static const Filter *create(const std::string &filter_type,
const ParameterDictionary &parameters,
std::vector<void *> &gpu_dynamic_pointers);

PBRT_CPU_GPU
Vector2f radius() const;
Vector2f get_radius() const;

PBRT_CPU_GPU
FloatType get_integral() const;
Expand All @@ -52,6 +49,12 @@ class Filter {
private:
Type type;
const void *ptr;

void init(const BoxFilter *box_filter);

void init(const GaussianFilter *gaussian_filter);

void init(const MitchellFilter *mitchell_filter);
};

class FilterSampler {
Expand Down
2 changes: 1 addition & 1 deletion src/pbrt/cameras/perspective.cu
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void PerspectiveCamera::init(const Point2i &resolution, const CameraTransform &c
camera_from_raster(Point3f(0.0, 1.0, 0.0)) - camera_from_raster(Point3f(0.0, 0.0, 0.0));

// Compute _cosTotalWidth_ for perspective camera
auto radius = Point2f(filter->radius());
auto radius = Point2f(filter->get_radius());
Point3f pCorner(-radius.x, -radius.y, 0.f);

Vector3f wCornerCamera = this->camera_from_raster(pCorner).to_vector3().normalize();
Expand Down
29 changes: 29 additions & 0 deletions src/pbrt/films/grey_scale_film.cu
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ext/lodepng/lodepng.h"
#include "pbrt/base/filter.h"
#include "pbrt/films/grey_scale_film.h"
#include "pbrt/spectrum_util/color_encoding.h"
#include "pbrt/spectrum_util/rgb.h"
Expand Down Expand Up @@ -90,3 +91,31 @@ void GreyScaleFilm::write_to_png(const std::string &filename) const {
throw std::runtime_error("lodepng::encode() fail");
}
}

void GreyScaleFilm::add_splat(const Point2f &p_film, FloatType val, const Filter *filter) {
if (filter == nullptr) {
REPORT_FATAL_ERROR();
}

Point2f pDiscrete = p_film + Vector2f(0.5, 0.5);

Vector2f radius = filter->get_radius();

Bounds2i splatBounds((pDiscrete - radius).floor(),
(pDiscrete + radius).floor() + Vector2i(1, 1));

splatBounds = splatBounds.intersect(pixel_bound);

for (const auto pi : splatBounds.range()) {
auto weight =
std::abs(filter->evaluate(Point2f(p_film - pi.to_point2f() - Vector2f(0.5, 0.5))));
// note: with std::abs(), it contributes differently than the original Film::add_splat()

if (weight == 0) {
continue;
}

auto pixel_index = pi.x + pi.y * resolution.x;
pixels[pixel_index] += weight * val;
}
}
7 changes: 7 additions & 0 deletions src/pbrt/films/grey_scale_film.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
#pragma once

#include "pbrt/euclidean_space/bounds2.h"
#include "pbrt/euclidean_space/point2.h"
#include <vector>

class Filter;

class GreyScaleFilm {
public:
GreyScaleFilm(const Point2i &_resolution)
: resolution(_resolution),
pixel_bound(Bounds2i(Point2i(0, 0), Point2i(_resolution.x, _resolution.y))),
pixels(std::vector<FloatType>(_resolution.x * _resolution.y, 0)) {}

void add_sample(const Point2i &coord, FloatType val) {
pixels[coord.y * resolution.x + coord.x] += val;
}

void add_splat(const Point2f &p_film, FloatType val, const Filter *filter);

void write_to_png(const std::string &filename) const;

private:
Point2i resolution;
std::vector<FloatType> pixels;
Bounds2i pixel_bound;
};
Loading

0 comments on commit 6a8eecf

Please sign in to comment.