Skip to content

Commit

Permalink
updated
Browse files Browse the repository at this point in the history
  • Loading branch information
xelatihy committed Jan 31, 2024
1 parent 4b52148 commit 59bab61
Show file tree
Hide file tree
Showing 11 changed files with 1,458 additions and 1,681 deletions.
1 change: 0 additions & 1 deletion apps/ysamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include <yocto/yocto_image.h>
#include <yocto/yocto_math.h>
#include <yocto/yocto_modeling.h>
#include <yocto/yocto_sampling.h>
#include <yocto/yocto_scene.h>
#include <yocto/yocto_sceneio.h>

Expand Down
2 changes: 1 addition & 1 deletion libs/yocto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ add_library(yocto STATIC
yocto_image.h
yocto_scene.h yocto_scene.cpp
yocto_raytracing.h yocto_raytracing.cpp
yocto_sampling.h yocto_shading.h
yocto_shading.h
yocto_modeling.h yocto_animation.h
yocto_trace.h yocto_trace.cpp
yocto_modelio.h yocto_modelio.cpp
Expand Down
1 change: 0 additions & 1 deletion libs/yocto/yocto_diagram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <future>
#include <unordered_set>

#include "yocto_sampling.h"
#include "yocto_sceneio.h"

// -----------------------------------------------------------------------------
Expand Down
325 changes: 325 additions & 0 deletions libs/yocto/yocto_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,102 @@ inline void shuffle(vector<T>& vals, rng_state& rng);

} // namespace yocto

// -----------------------------------------------------------------------------
// MONTECARLO SAMPLING FUNCTIONS
// -----------------------------------------------------------------------------
namespace yocto {

// Sample an hemispherical direction with uniform distribution.
inline vec3f sample_hemisphere(vec2f ruv);
inline float sample_hemisphere_pdf(vec3f direction);

// Sample an hemispherical direction with uniform distribution.
inline vec3f sample_hemisphere(vec3f normal, vec2f ruv);
inline float sample_hemisphere_pdf(vec3f normal, vec3f direction);

// Sample a spherical direction with uniform distribution.
inline vec3f sample_sphere(vec2f ruv);
inline float sample_sphere_pdf(vec3f w);

// Sample an hemispherical direction with cosine distribution.
inline vec3f sample_hemisphere_cos(vec2f ruv);
inline float sample_hemisphere_cos_pdf(vec3f direction);

// Sample an hemispherical direction with cosine distribution.
inline vec3f sample_hemisphere_cos(vec3f normal, vec2f ruv);
inline float sample_hemisphere_cos_pdf(vec3f normal, vec3f direction);

// Sample an hemispherical direction with cosine power distribution.
inline vec3f sample_hemisphere_cospower(float exponent, vec2f ruv);
inline float sample_hemisphere_cospower_pdf(float exponent, vec3f direction);

// Sample an hemispherical direction with cosine power distribution.
inline vec3f sample_hemisphere_cospower(
float exponent, vec3f normal, vec2f ruv);
inline float sample_hemisphere_cospower_pdf(
float exponent, vec3f normal, vec3f direction);

// Sample a point uniformly on a disk.
inline vec2f sample_disk(vec2f ruv);
inline float sample_disk_pdf(vec2f point);

// Sample a point uniformly on a cylinder, without caps.
inline vec3f sample_cylinder(vec2f ruv);
inline float sample_cylinder_pdf(vec3f point);

// Sample a point uniformly on a triangle returning the baricentric coordinates.
inline vec2f sample_triangle(vec2f ruv);

// Sample a point uniformly on a triangle.
inline vec3f sample_triangle(vec3f p0, vec3f p1, vec3f p2, vec2f ruv);
// Pdf for uniform triangle sampling, i.e. triangle area.
inline float sample_triangle_pdf(vec3f p0, vec3f p1, vec3f p2);

// Sample an index with uniform distribution.
inline int sample_uniform(int size, float r);
inline float sample_uniform_pdf(int size);

// Sample an index with uniform distribution.
inline float sample_uniform(const vector<float>& elements, float r);
inline float sample_uniform_pdf(const vector<float>& elements);

// Sample a discrete distribution represented by its cdf.
inline int sample_discrete(const vector<float>& cdf, float r);
// Pdf for uniform discrete distribution sampling.
inline float sample_discrete_pdf(const vector<float>& cdf, int idx);

} // namespace yocto

// -----------------------------------------------------------------------------
// SHAPE SAMPLING
// -----------------------------------------------------------------------------
namespace yocto {

// Pick a point in a point set uniformly.
inline int sample_points(int npoints, float re);
inline int sample_points(const vector<float>& cdf, float re);
inline vector<float> sample_points_cdf(int npoints);

// Pick a point on lines uniformly.
inline pair<int, float> sample_lines(
const vector<float>& cdf, float re, float ru);
inline vector<float> sample_lines_cdf(
const vector<vec2i>& lines, const vector<vec3f>& positions);

// Pick a point on a triangle mesh uniformly.
inline pair<int, vec2f> sample_triangles(
const vector<float>& cdf, float re, vec2f ruv);
inline vector<float> sample_triangles_cdf(
const vector<vec3i>& triangles, const vector<vec3f>& positions);

// Pick a point on a quad mesh uniformly.
inline pair<int, vec2f> sample_quads(
const vector<float>& cdf, float re, vec2f ruv);
inline vector<float> sample_quads_cdf(
const vector<vec4i>& quads, const vector<vec3f>& positions);

} // namespace yocto

// -----------------------------------------------------------------------------
// PYTHON-LIKE ITERATORS
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -3509,6 +3605,235 @@ inline void shuffle(vector<T>& vals, rng_state& rng) {

} // namespace yocto

// -----------------------------------------------------------------------------
// IMPLEMENTATION OF MONTECARLO SAMPLING FUNCTIONS
// -----------------------------------------------------------------------------
namespace yocto {

// Sample an hemispherical direction with uniform distribution.
inline vec3f sample_hemisphere(vec2f ruv) {
auto z = ruv.y;
auto r = sqrt(clamp(1 - z * z, 0.0f, 1.0f));
auto phi = 2 * pif * ruv.x;
return {r * cos(phi), r * sin(phi), z};
}
inline float sample_hemisphere_pdf(vec3f direction) {
return (direction.z <= 0) ? 0 : 1 / (2 * pif);
}

// Sample an hemispherical direction with uniform distribution.
inline vec3f sample_hemisphere(vec3f normal, vec2f ruv) {
auto z = ruv.y;
auto r = sqrt(clamp(1 - z * z, 0.0f, 1.0f));
auto phi = 2 * pif * ruv.x;
auto local_direction = vec3f{r * cos(phi), r * sin(phi), z};
return transform_direction(basis_fromz(normal), local_direction);
}
inline float sample_hemisphere_pdf(vec3f normal, vec3f direction) {
return (dot(normal, direction) <= 0) ? 0 : 1 / (2 * pif);
}

// Sample a spherical direction with uniform distribution.
inline vec3f sample_sphere(vec2f ruv) {
auto z = 2 * ruv.y - 1;
auto r = sqrt(clamp(1 - z * z, 0.0f, 1.0f));
auto phi = 2 * pif * ruv.x;
return {r * cos(phi), r * sin(phi), z};
}
inline float sample_sphere_pdf(vec3f w) { return 1 / (4 * pif); }

// Sample an hemispherical direction with cosine distribution.
inline vec3f sample_hemisphere_cos(vec2f ruv) {
auto z = sqrt(ruv.y);
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
return {r * cos(phi), r * sin(phi), z};
}
inline float sample_hemisphere_cos_pdf(vec3f direction) {
return (direction.z <= 0) ? 0 : direction.z / pif;
}

// Sample an hemispherical direction with cosine distribution.
inline vec3f sample_hemisphere_cos(vec3f normal, vec2f ruv) {
auto z = sqrt(ruv.y);
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
auto local_direction = vec3f{r * cos(phi), r * sin(phi), z};
return transform_direction(basis_fromz(normal), local_direction);
}
inline float sample_hemisphere_cos_pdf(vec3f normal, vec3f direction) {
auto cosw = dot(normal, direction);
return (cosw <= 0) ? 0 : cosw / pif;
}

// Sample an hemispherical direction with cosine power distribution.
inline vec3f sample_hemisphere_cospower(float exponent, vec2f ruv) {
auto z = pow(ruv.y, 1 / (exponent + 1));
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
return {r * cos(phi), r * sin(phi), z};
}
inline float sample_hemisphere_cospower_pdf(float exponent, vec3f direction) {
return (direction.z <= 0)
? 0
: pow(direction.z, exponent) * (exponent + 1) / (2 * pif);
}

// Sample an hemispherical direction with cosine power distribution.
inline vec3f sample_hemisphere_cospower(
float exponent, vec3f normal, vec2f ruv) {
auto z = pow(ruv.y, 1 / (exponent + 1));
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
auto local_direction = vec3f{r * cos(phi), r * sin(phi), z};
return transform_direction(basis_fromz(normal), local_direction);
}
inline float sample_hemisphere_cospower_pdf(
float exponent, vec3f normal, vec3f direction) {
auto cosw = dot(normal, direction);
return (cosw <= 0) ? 0 : pow(cosw, exponent) * (exponent + 1) / (2 * pif);
}

// Sample a point uniformly on a disk.
inline vec2f sample_disk(vec2f ruv) {
auto r = sqrt(ruv.y);
auto phi = 2 * pif * ruv.x;
return {cos(phi) * r, sin(phi) * r};
}
inline float sample_disk_pdf() { return 1 / pif; }

// Sample a point uniformly on a cylinder, without caps.
inline vec3f sample_cylinder(vec2f ruv) {
auto phi = 2 * pif * ruv.x;
return {sin(phi), cos(phi), ruv.y * 2 - 1};
}
inline float sample_cylinder_pdf(vec3f point) { return 1 / pif; }

// Sample a point uniformly on a triangle returning the baricentric coordinates.
inline vec2f sample_triangle(vec2f ruv) {
return {1 - sqrt(ruv.x), ruv.y * sqrt(ruv.x)};
}

// Sample a point uniformly on a triangle.
inline vec3f sample_triangle(vec3f p0, vec3f p1, vec3f p2, vec2f ruv) {
auto uv = sample_triangle(ruv);
return p0 * (1 - uv.x - uv.y) + p1 * uv.x + p2 * uv.y;
}
// Pdf for uniform triangle sampling, i.e. triangle area.
inline float sample_triangle_pdf(vec3f p0, vec3f p1, vec3f p2) {
return 2 / length(cross(p1 - p0, p2 - p0));
}

// Sample an index with uniform distribution.
inline int sample_uniform(int size, float r) {
return clamp((int)(r * size), 0, size - 1);
}
inline float sample_uniform_pdf(int size) { return (float)1 / (float)size; }

// Sample an index with uniform distribution.
inline float sample_uniform(const vector<float>& elements, float r) {
if (elements.empty()) return {};
auto size = (int)elements.size();
return elements[clamp((int)(r * size), 0, size - 1)];
}
inline float sample_uniform_pdf(const vector<float>& elements) {
if (elements.empty()) return 0;
return 1.0f / (int)elements.size();
}

// Sample a discrete distribution represented by its cdf.
inline int sample_discrete(const vector<float>& cdf, float r) {
r = clamp(r * cdf.back(), (float)0, cdf.back() - (float)0.00001);
auto idx = (int)(std::upper_bound(cdf.data(), cdf.data() + cdf.size(), r) -
cdf.data());
return clamp(idx, 0, (int)cdf.size() - 1);
}
// Pdf for uniform discrete distribution sampling.
inline float sample_discrete_pdf(const vector<float>& cdf, int idx) {
if (idx == 0) return cdf[0];
return cdf[idx] - cdf[idx - 1];
}

} // namespace yocto

// -----------------------------------------------------------------------------
// IMPLEMENTATION OF SHAPE SAMPLING
// -----------------------------------------------------------------------------
namespace yocto {

// Pick a point in a point set uniformly.
inline int sample_points(int npoints, float re) {
return sample_uniform(npoints, re);
}
inline int sample_points(const vector<float>& cdf, float re) {
return sample_discrete(cdf, re);
}
inline vector<float> sample_points_cdf(int npoints) {
auto cdf = vector<float>(npoints);
for (auto i = 0; i < cdf.size(); i++) cdf[i] = 1 + (i != 0 ? cdf[i - 1] : 0);
return cdf;
}

// Pick a point on lines uniformly.
inline pair<int, float> sample_lines(
const vector<float>& cdf, float re, float ru) {
return {sample_discrete(cdf, re), ru};
}
inline vector<float> sample_lines_cdf(
const vector<vec2i>& lines, const vector<vec3f>& positions) {
auto cdf = vector<float>(lines.size());
for (auto i = 0; i < cdf.size(); i++) {
auto& l = lines[i];
auto w = line_length(positions[l.x], positions[l.y]);
cdf[i] = w + (i != 0 ? cdf[i - 1] : 0);
}
return cdf;
}

// Pick a point on a triangle mesh uniformly.
inline pair<int, vec2f> sample_triangles(
const vector<float>& cdf, float re, vec2f ruv) {
return {sample_discrete(cdf, re), sample_triangle(ruv)};
}
inline vector<float> sample_triangles_cdf(
const vector<vec3i>& triangles, const vector<vec3f>& positions) {
auto cdf = vector<float>(triangles.size());
for (auto i = 0; i < cdf.size(); i++) {
auto& t = triangles[i];
auto w = triangle_area(positions[t.x], positions[t.y], positions[t.z]);
cdf[i] = w + (i != 0 ? cdf[i - 1] : 0);
}
return cdf;
}

// Pick a point on a quad mesh uniformly.
inline pair<int, vec2f> sample_quads(
const vector<float>& cdf, float re, vec2f ruv) {
return {sample_discrete(cdf, re), ruv};
}
inline pair<int, vec2f> sample_quads(
const vector<vec4i>& quads, const vector<float>& cdf, float re, vec2f ruv) {
auto element = sample_discrete(cdf, re);
if (quads[element].z == quads[element].w) {
return {element, sample_triangle(ruv)};
} else {
return {element, ruv};
}
}
inline vector<float> sample_quads_cdf(
const vector<vec4i>& quads, const vector<vec3f>& positions) {
auto cdf = vector<float>(quads.size());
for (auto i = 0; i < cdf.size(); i++) {
auto& q = quads[i];
auto w = quad_area(
positions[q.x], positions[q.y], positions[q.z], positions[q.w]);
cdf[i] = w + (i ? cdf[i - 1] : 0);
}
return cdf;
}

} // namespace yocto

// -----------------------------------------------------------------------------
// PYTHON-LIKE ITERATORS
// -----------------------------------------------------------------------------
Expand Down
19 changes: 0 additions & 19 deletions libs/yocto/yocto_raytracing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,25 +987,6 @@ static inline vec3f fresnel_schlick(
(1 - specular) * pow(clamp(1 - abs(cosine), 0.0f, 1.0f), 5.0f);
}

// Sample an hemispherical direction with cosine distribution.
static inline vec3f sample_hemisphere_cos(vec3f normal, vec2f ruv) {
auto z = sqrt(ruv.y);
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
auto local_direction = vec3f{r * cos(phi), r * sin(phi), z};
return transform_direction(basis_fromz(normal), local_direction);
}

// Sample an hemispherical direction with cosine power distribution.
inline vec3f sample_hemisphere_cospower(
float exponent, vec3f normal, vec2f ruv) {
auto z = pow(ruv.y, 1 / (exponent + 1));
auto r = sqrt(1 - z * z);
auto phi = 2 * pif * ruv.x;
auto local_direction = vec3f{r * cos(phi), r * sin(phi), z};
return transform_direction(basis_fromz(normal), local_direction);
}

} // namespace yocto

// -----------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 59bab61

Please sign in to comment.