Skip to content

Commit

Permalink
specular;super sample denoising
Browse files Browse the repository at this point in the history
  • Loading branch information
Shiina Miyuki committed Nov 1, 2020
1 parent 3724d02 commit 6c2efe5
Show file tree
Hide file tree
Showing 19 changed files with 336 additions and 44 deletions.
8 changes: 8 additions & 0 deletions src/akari/cmd/akari.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace pybind11 {
namespace py = pybind11;
static std::string inputFilename;
static int spp = 0;
static int super_sampling = 0;
static bool denoise = false;
void parse(int argc, const char **argv) {
try {
Expand All @@ -47,6 +48,7 @@ void parse(int argc, const char **argv) {
auto opt = options.allow_unrecognised_options().add_options();
opt("i,input", "Input Scene Description File", cxxopts::value<std::string>());
opt("v,verbose", "Use verbose output");
opt("ss", "Use super sampling", cxxopts::value<int>());
opt("spp", "Override scene spp setting", cxxopts::value<int>());
opt("denoise", "Run denoiser");
opt("gpu", "Use gpu rendering");
Expand All @@ -62,6 +64,9 @@ void parse(int argc, const char **argv) {
if (result.count("spp")) {
spp = result["spp"].as<int>();
}
if (result.count("ss")) {
super_sampling = result["ss"].as<int>();
}
if (result.count("verbose")) {
GetDefaultLogger()->log_verbose(true);
}
Expand Down Expand Up @@ -97,6 +102,9 @@ void parse_and_run() {
if (spp > 0) {
scene->set_spp(spp);
}
if (super_sampling > 1) {
scene->super_sample(super_sampling);
}
if (denoise) {
scene->run_denosier(denoise);
}
Expand Down
4 changes: 2 additions & 2 deletions src/akari/core/film.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace akari {
public:
Float splatScale = 1.0f;
explicit Film(const ivec2 &dimension) : radiance(dimension), weight(dimension) {}
Tile tile(const Bounds2i &bounds) { return Tile(bounds); }
Tile tile(const Bounds2i &bounds) { return Tile(Bounds2i(ivec2(0), resolution()).intersect(bounds)); }
[[nodiscard]] ivec2 resolution() const { return radiance.resolution(); }

[[nodiscard]] Bounds2i bounds() const { return Bounds2i{ivec2(0), resolution()}; }
Expand Down Expand Up @@ -105,7 +105,7 @@ namespace akari {
}
},
1024);
return image;
return image;
}
void write_image(const fs::path &path, const PostProcessor &postProcessor = GammaCorrection()) const {
RGBAImage image = to_rgba_image();
Expand Down
18 changes: 17 additions & 1 deletion src/akari/core/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,23 @@ namespace akari {
},
1024);
}

void Convolution::process(const RGBAImage &in, RGBAImage &out) const {
out.resize(in.resolution() / stride);
parallel_for(
out.resolution().y,
[&](uint32_t y, uint32_t) {
for (int x = 0; x < out.resolution().x; x++) {
RGB sum = RGB(0.0);
for (int y0 = 0; y0 < kernel.resolution().y; y0++) {
for (int x0 = 0; x0 < kernel.resolution().x; x0++) {
sum += in(x * stride.x + x0, y * stride.y + y0).rgb * kernel(x0, y0);
}
}
out(x, y) = RGBA(sum, 1.0);
}
},
1024);
}
std::shared_ptr<ImageWriter> default_image_writer() { return std::make_shared<DefaultImageWriter>(); }

class DefaultImageReader : public ImageReader {
Expand Down
7 changes: 7 additions & 0 deletions src/akari/core/image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,14 @@ namespace akari {
explicit GammaCorrection() {}
void process(const RGBAImage &in, RGBAImage &out) const override;
};
class AKR_EXPORT Convolution : public PostProcessor {
TImage<Float> kernel;
ivec2 stride;

public:
explicit Convolution(TImage<Float> kernel, ivec2 stride) : kernel(kernel), stride(stride) {}
void process(const RGBAImage &in, RGBAImage &out) const override;
};
class PostProcessingPipeline : public PostProcessor {
std::list<std::shared_ptr<PostProcessor>> pipeline;

Expand Down
3 changes: 3 additions & 0 deletions src/akari/render/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ namespace akari::render {
public:
virtual CameraSample generate_ray(const vec2 &u1, const vec2 &u2, const ivec2 &raster) const = 0;
virtual ivec2 resolution() const = 0;

virtual ~Camera() = default;
};
class CameraNode : public SceneGraphNode {
public:
virtual std::shared_ptr<const Camera> create_camera(Allocator<> allocator) = 0;
virtual ivec2 resolution() const = 0;
virtual void set_resolution(const ivec2 &res) = 0;
};
} // namespace akari::render
10 changes: 6 additions & 4 deletions src/akari/render/cameras/perspective.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace akari::render {
preprocess();
}
ivec2 resolution() const { return _resolution; }
CameraSample generate_ray(const vec2 &u1, const vec2 &u2, const ivec2 &raster) const {
CameraSample generate_ray(const vec2 &u1, const vec2 &u2, const ivec2 &raster) const override {
CameraSample sample;
sample.p_lens = concentric_disk_sampling(u1) * lens_radius;
sample.p_film = vec2(raster) + u2;
Expand All @@ -79,7 +79,7 @@ namespace akari::render {
public:
vec3 position;
vec3 rotation;
ivec2 resolution = ivec2(512, 512);
ivec2 resolution_ = ivec2(512, 512);
double fov = glm::radians(80.0f);
void object_field(sdl::Parser &parser, sdl::ParserContext &ctx, const std::string &field,
const sdl::Value &value) override {
Expand All @@ -90,14 +90,16 @@ namespace akari::render {
} else if (field == "position") {
position = load<vec3>(value);
} else if (field == "resolution") {
resolution = load<ivec2>(value);
resolution_ = load<ivec2>(value);
}
}
std::shared_ptr<const Camera> create_camera(Allocator<> allocator) override {
TRSTransform TRS{position, rotation, Vec3(1.0)};
auto c2w = TRS();
return make_pmr_shared<PerspectiveCamera>(allocator, resolution, c2w, fov);
return make_pmr_shared<PerspectiveCamera>(allocator, resolution_, c2w, fov);
}
ivec2 resolution() const override { return resolution_; }
void set_resolution(const ivec2 &res) override { resolution_ = res; }
};
AKR_EXPORT_NODE(PerspectiveCamera, PerspectiveCameraNode)
} // namespace akari::render
61 changes: 61 additions & 0 deletions src/akari/render/closure.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@


// MIT License
//
// Copyright (c) 2020 椎名深雪
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#include <akari/render/closure.h>

namespace akari::render {
Spectrum FresnelNoOp::evaluate(Float cosThetaI) const { return Spectrum(1.0f); }
Spectrum FresnelConductor::evaluate(Float cosThetaI) const { return fr_conductor(cosThetaI, etaI, etaT, k); }
Spectrum FresnelDielectric::evaluate(Float cosThetaI) const {
return Spectrum(fr_dielectric(cosThetaI, etaI, etaT));
}
[[nodiscard]] std::optional<BSDFSample> FresnelSpecular::sample(const vec2 &u, const Vec3 &wo) const {
Float F = fr_dielectric(cos_theta(wo), etaA, etaB);
AKR_ASSERT(F >= 0.0);
BSDFSample sample;
if (u[0] < F) {
sample.wi = reflect(-wo, vec3(0, 1, 0));
sample.pdf = F;
sample.sampled = BSDFType::SpecularReflection;
sample.f = F * R / abs_cos_theta(sample.wi);
} else {
bool entering = cos_theta(wo) > 0;
Float etaI = entering ? etaA : etaB;
Float etaT = entering ? etaB : etaA;
auto wt = refract(wo, faceforward(wo, vec3(0, 1, 0)), etaI / etaT);
if (!wt) {
AKR_ASSERT(etaI > etaT);
return std::nullopt;
}
Spectrum ft = T * (1 - F);
sample.sampled = BSDFType::SpecularTransmission;

ft *= (etaI * etaI) / (etaT * etaT);
sample.pdf = 1 - F;
sample.wi = *wt;
sample.f = ft / abs_cos_theta(sample.wi);
}
return sample;
}
} // namespace akari::render
76 changes: 76 additions & 0 deletions src/akari/render/closure.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,30 @@ namespace akari::render {
Spectrum f = Spectrum(0.0f);
BSDFType sampled = BSDFType::Unset;
};
class Fresnel {
public:
virtual Spectrum evaluate(Float cosThetaI) const = 0;
};
class AKR_EXPORT FresnelNoOp : public Fresnel {
public:
[[nodiscard]] Spectrum evaluate(Float cosThetaI) const override;
};

class AKR_EXPORT FresnelConductor : public Fresnel {
const Spectrum etaI, etaT, k;

public:
FresnelConductor(const Spectrum &etaI, const Spectrum &etaT, const Spectrum &k)
: etaI(etaI), etaT(etaT), k(k) {}
[[nodiscard]] Spectrum evaluate(Float cosThetaI) const override;
};
class AKR_EXPORT FresnelDielectric : public Fresnel {
const Float etaI, etaT;

public:
FresnelDielectric(const Float &etaI, const Float &etaT) : etaI(etaI), etaT(etaT) {}
[[nodiscard]] Spectrum evaluate(Float cosThetaI) const override;
};
class AKR_EXPORT BSDFClosure {
public:
[[nodiscard]] virtual Float evaluate_pdf(const Vec3 &wo, const Vec3 &wi) const = 0;
Expand Down Expand Up @@ -152,7 +175,60 @@ namespace akari::render {
return sample;
}
};
class SpecularReflection : public BSDFClosure {
Spectrum R;

public:
SpecularReflection(const Spectrum &R) : R(R) {}
[[nodiscard]] Float evaluate_pdf(const Vec3 &wo, const Vec3 &wi) const { return 0.0f; }
[[nodiscard]] Spectrum evaluate(const Vec3 &wo, const Vec3 &wi) const { return Spectrum(0.0f); }
[[nodiscard]] BSDFType type() const { return BSDFType::SpecularReflection; }
std::optional<BSDFSample> sample(const vec2 &u, const Vec3 &wo) const {
BSDFSample sample;
sample.wi = glm::reflect(-wo, vec3(0, 1, 0));
sample.sampled = type();
sample.pdf = 1.0;
sample.f = R / (std::abs(cos_theta(sample.wi)));
return sample;
}
};
class SpecularTransmission : public BSDFClosure {
Spectrum R;
Float eta;

public:
SpecularTransmission(const Spectrum &R, Float eta) : R(R), eta(eta) {}
[[nodiscard]] Float evaluate_pdf(const Vec3 &wo, const Vec3 &wi) const { return 0.0f; }
[[nodiscard]] Spectrum evaluate(const Vec3 &wo, const Vec3 &wi) const { return Spectrum(0.0f); }
[[nodiscard]] BSDFType type() const { return BSDFType::SpecularTransmission; }
std::optional<BSDFSample> sample(const vec2 &u, const Vec3 &wo) const {
BSDFSample sample;
Float etaIO = same_hemisphere(wo, vec3(0, 1, 0)) ? eta : 1.0f / eta;
auto wt = refract(wo, faceforward(wo, vec3(0, 1, 0)), etaIO);
if (!wt) {
return std::nullopt;
}
sample.wi = *wt;
sample.sampled = type();
sample.pdf = 1.0;
sample.f = R / (std::abs(cos_theta(sample.wi)));
return sample;
}
};

class AKR_EXPORT FresnelSpecular : public BSDFClosure {
const Spectrum R, T;
const Float etaA, etaB;
const FresnelDielectric fresnel;

public:
explicit FresnelSpecular(const Spectrum &R, const Spectrum &T, Float etaA, Float etaB)
: R(R), T(T), etaA(etaA), etaB(etaB), fresnel(etaA, etaB) {}
[[nodiscard]] BSDFType type() const { return BSDFType::SpecularTransmission | BSDFType::SpecularReflection; }
[[nodiscard]] Float evaluate_pdf(const vec3 &wo, const vec3 &wi) const override { return 0; }
[[nodiscard]] Spectrum evaluate(const vec3 &wo, const vec3 &wi) const override { return Spectrum(0); }
[[nodiscard]] std::optional<BSDFSample> sample(const vec2 &u, const Vec3 &wo) const override;
};
class PassThrough : public BSDFClosure {
Spectrum R;

Expand Down
11 changes: 6 additions & 5 deletions src/akari/render/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,17 @@ namespace akari::render {
inline float cos2_phi(const glm::vec3 &w) { return (cos_phi(w) * cos_phi(w)); }
inline float sin2_phi(const glm::vec3 &w) { return (sin_phi(w) * sin_phi(w)); }
inline bool same_hemisphere(const glm::vec3 &wo, const glm::vec3 &wi) { return ((wo.y * wi.y) >= float(0.0)); }
inline bool refract(const glm::vec3 &wi, const glm::vec3 &n, float eta, glm::vec3 &wt) {
inline std::optional<glm::vec3> refract(const glm::vec3 &wi, const glm::vec3 &n, float eta) {
float cosThetaI = glm::dot(n, wi);
float sin2ThetaI = glm::max(float(0.0), (float(1.0) - (cosThetaI * cosThetaI)));
float sin2ThetaT = ((eta * eta) * sin2ThetaI);
if ((sin2ThetaT >= float(1.0)))
return false;
return std::nullopt;
float cosThetaT = glm::sqrt((float(1.0) - sin2ThetaT));
wt = ((eta * -wi) + (((eta * cosThetaI) - cosThetaT) * n));
return true;
auto wt = ((eta * -wi) + (((eta * cosThetaI) - cosThetaT) * n));
return wt;
}
inline vec3 faceforward(const vec3 &w, const vec3 &n) { return dot(w, n) < 0.0 ? -n : n; }
inline float fr_dielectric(float cosThetaI, float etaI, float etaT) {
bool entering = (cosThetaI > float(0.0));
if (!entering) {
Expand Down Expand Up @@ -92,7 +93,7 @@ namespace akari::render {
return glm::vec3(sinTheta * glm::cos(phi), cosTheta, sinTheta * glm::sin(phi));
}

inline float spherical_theta(const vec3& v) { return glm::acos(glm::clamp(v.y, -1.0f, 1.0f)); }
inline float spherical_theta(const vec3 &v) { return glm::acos(glm::clamp(v.y, -1.0f, 1.0f)); }

inline float spherical_phi(const glm::vec3 v) {
float p = glm::atan(v.z, v.x);
Expand Down
2 changes: 1 addition & 1 deletion src/akari/render/integrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace akari::render {
value = mat->albedo(sp);
} break;
case AOV::normal:
value = trig.ng();
value = trig.ns(isct->uv);
break;
}
break;
Expand Down
14 changes: 8 additions & 6 deletions src/akari/render/integrators/ppg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ namespace akari::render {
if (si.triangle.light) {
auto light = si.triangle.light;
Spectrum I = beta * light->Le(wo, ctx.sp);
if (depth == 0) {
if (depth == 0 || BSDFType::Unset != (prev_vertex->sampled_lobe() & BSDFType::Specular)) {
accumulate_radiance_wo_beta(I);
} else {
vec3 prev_p = prev_vertex->p();
Expand Down Expand Up @@ -664,11 +664,13 @@ namespace akari::render {
if (!vertex) {
break;
}
std::optional<DirectLighting> has_direct = compute_direct_lighting(si, surface_hit, select_light());
if (has_direct) {
auto &direct = *has_direct;
if (!is_black(direct.color) && !scene->occlude(direct.shadow_ray)) {
accumulate_radiance_wo_beta(direct.color);
if ((vertex->sampled_lobe & BSDFType::Specular) == BSDFType::Unset) {
std::optional<DirectLighting> has_direct = compute_direct_lighting(si, surface_hit, select_light());
if (has_direct) {
auto &direct = *has_direct;
if (!is_black(direct.color) && !scene->occlude(direct.shadow_ray)) {
accumulate_radiance_wo_beta(direct.color);
}
}
}
vertices[n_vertices].L = Spectrum(0);
Expand Down
Loading

0 comments on commit 6c2efe5

Please sign in to comment.