Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ellipsoids shape for volumetric primitives #1464

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions include/mitsuba/core/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,11 +238,11 @@ MI_INLINE Index find_interval(dr::scalar_t<Index> size,

/**
* \brief This function computes a suitable middle point for use in the \ref bisect() function
*
*
* To mitigate the issue of varying density of floating point numbers on the
* number line, the floats are reinterpreted as unsigned integers. As long as
* sign of both numbers is the same, this maps the floats to the evenly spaced
* set of integers. The middle of these integers ensures that the space of
* set of integers. The middle of these integers ensures that the space of
* numbers is halved on each iteration of the bisection.
*
* Note that this strategy does not work if the numbers have different sign.
Expand Down Expand Up @@ -401,6 +401,34 @@ solve_quadratic(const Value &a, const Value &b, const Value &c) {
return { valid_linear || valid_quadratic, x0, x1 };
}

/**
* \brief Solve a quadratic equation of the form a*x^2 + b*x + c = 0.
* Taken from "Precision Improvements for Ray/Sphere Intersection", Ray Tracing Gems 2
* \return \c true if a solution could be found
*/
template <typename Value>
MI_INLINE std::tuple<dr::mask_t<Value>, Value, Value>
improved_solve_quadratic(const Value &a, const Value &b, const Value &c, const Value &discr) {
using Scalar = dr::scalar_t<Value>;
using Mask = dr::mask_t<Value>;
// Check if the quadratic eq is solvable
Mask valid_quadratic = (discr >= Scalar(0));
Value x0, x1;
if (likely(dr::any_or<true>(valid_quadratic))){
Value new_discr = dr::sqrt(a * discr);
Value q = b + dr::copysign(new_discr, b);

Value x0p = c * dr::rcp(q),
x1p = q * dr::rcp(a);

// Order the results so that x0 < x1
x0 = dr::minimum(x0p, x1p);
x1 = dr::maximum(x0p, x1p);
}

return { valid_quadratic, x0, x1 };
}

//! @}
// -----------------------------------------------------------------------

Expand Down
3 changes: 3 additions & 0 deletions include/mitsuba/core/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ enum class ParamFlags : uint32_t {

/// Tracking gradients w.r.t. this parameter will introduce discontinuities
Discontinuous = 0x2,

/// This parameter is read-only!
ReadOnly = 0x4,
};

MI_DECLARE_ENUM_OPERATORS(ParamFlags)
Expand Down
2 changes: 2 additions & 0 deletions include/mitsuba/core/plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class MI_EXPORT_LIB PluginManager : public Object {
const Class *get_plugin_class(const std::string &name,
const std::string &variant);

std::string get_plugin_type(const std::string &plugin_name);

/// Return the list of loaded plugins
std::vector<std::string> loaded_plugins() const;

Expand Down
27 changes: 26 additions & 1 deletion include/mitsuba/python/docstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -5362,6 +5362,8 @@ discontinuities)doc";

static const char *__doc_mitsuba_ParamFlags_NonDifferentiable = R"doc(Tracking gradients w.r.t. this parameter is not allowed)doc";

static const char *__doc_mitsuba_ParamFlags_ReadOnly = R"doc()doc";

static const char *__doc_mitsuba_PhaseFunction = R"doc()doc";

static const char *__doc_mitsuba_PhaseFunction_2 = R"doc()doc";
Expand Down Expand Up @@ -6213,6 +6215,8 @@ static const char *__doc_mitsuba_RayFlags_All = R"doc(//! Compound compute flags

static const char *__doc_mitsuba_RayFlags_AllNonDifferentiable = R"doc(Compute all fields of the surface interaction ignoring shape's motion)doc";

static const char *__doc_mitsuba_RayFlags_BackfaceCulling = R"doc(Enable backface culling)doc";

static const char *__doc_mitsuba_RayFlags_DetachShape = R"doc(Derivatives of the SurfaceInteraction fields ignore shape's motion)doc";

static const char *__doc_mitsuba_RayFlags_Empty = R"doc(No flags set)doc";
Expand Down Expand Up @@ -7494,6 +7498,8 @@ static const char *__doc_mitsuba_ShapeKDTree_to_string = R"doc(Return a human-re

static const char *__doc_mitsuba_ShapeType = R"doc(Enumeration of all shape types in Mitsuba)doc";

static const char *__doc_mitsuba_ShapeType_Ellipsoids = R"doc(Ellipsoids (`ellipsoids`))doc";

static const char *__doc_mitsuba_ShapeType_BSplineCurve = R"doc(B-Spline curves (`bsplinecurve`))doc";

static const char *__doc_mitsuba_ShapeType_Cylinder = R"doc(Cylinders (`cylinder`))doc";
Expand Down Expand Up @@ -7667,6 +7673,18 @@ Parameter ``si``:
Returns:
An trichromatic intensity or reflectance value)doc";

static const char *__doc_mitsuba_Shape_eval_attribute_X =
R"doc(Evaluate a dynamic shape attribute at the given surface interaction.

Parameter ``name``:
Name of the attribute to evaluate

Parameter ``si``:
Surface interaction associated with the query

Returns:
An dynamic array of attribute values)doc";

static const char *__doc_mitsuba_Shape_eval_parameterization =
R"doc(Parameterize the mesh using UV values

Expand Down Expand Up @@ -10874,6 +10892,14 @@ stratification in the context of Monte Carlo integration.)doc";
static const char *__doc_mitsuba_math_solve_quadratic =
R"doc(Solve a quadratic equation of the form a*x^2 + b*x + c = 0.

Returns:
``True`` if a solution could be found)doc";

static const char *__doc_mitsuba_math_improved_solve_quadratic =
R"doc(Solve a quadratic equation of the form a*x^2 + b*x + c = 0.

Taken from "Precision Improvements for Ray/Sphere Intersection", Ray Tracing Gems 2

Returns:
``True`` if a solution could be found)doc";

Expand Down Expand Up @@ -12503,4 +12529,3 @@ static const char *__doc_operator_lshift = R"doc(Turns a vector of elements into
#if defined(__GNUG__)
#pragma GCC diagnostic pop
#endif

6 changes: 4 additions & 2 deletions include/mitsuba/render/interaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ enum class RayFlags : uint32_t {
/// Derivatives of the SurfaceInteraction fields ignore shape's motion
DetachShape = 0x100,

/// Enable backface culling
BackfaceCulling = 0x200,

// =============================================================
//! Compound compute flags
// =============================================================
Expand Down Expand Up @@ -495,15 +498,14 @@ struct SurfaceInteraction : Interaction<Float_, Spectrum_> {
* Flags specifying which information should be computed
*/
void finalize_surface_interaction(
const PreliminaryIntersection<Float, Shape> &pi, const Ray3f &ray,
const PreliminaryIntersection<Float, Shape> & /*pi*/, const Ray3f &ray,
uint32_t ray_flags, Mask active) {
dr::masked(t, !active) = dr::Infinity<Float>;
active &= is_valid();

dr::masked(shape, !active) = nullptr;
dr::masked(instance, !active) = nullptr;

prim_index = pi.prim_index;
time = ray.time;
wavelengths = ray.wavelengths;

Expand Down
2 changes: 2 additions & 0 deletions include/mitsuba/render/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@ class MI_EXPORT_LIB Mesh : public Shape<Float, Spectrum> {
size_t vertex_data_bytes() const;
size_t face_data_bytes() const;

bool is_mesh(Mask /*unused*/ = true) const override;

protected:
Mesh(const Properties &);
inline Mesh() {}
Expand Down
1 change: 1 addition & 0 deletions include/mitsuba/render/optix/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ constexpr float Pi = float(3.14159265358979323846);
constexpr float TwoPi = float(6.28318530717958647692);
constexpr float InvPi = float(0.31830988618379067154);
constexpr float InvTwoPi = float(0.15915494309189533577);
constexpr float SqrtTwo = float(1.41421356237309504880);

using namespace optix;

Expand Down
21 changes: 21 additions & 0 deletions include/mitsuba/render/optix/math.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,25 @@ DEVICE bool solve_quadratic(float a, float b, float c, float& x0, float&x1) {

return true;
}

DEVICE bool improved_solve_quadratic(float a, float b, float c, float discr, float& x0, float&x1) {
/*
Taken from "Precision Improvements for Ray/Sphere Intersection", Ray Tracing Gems 2
*/
// Check if the quadratic eq is solvable
if (discr < 0.f)
return false;

float new_discr = sqrt(a * discr);
float q = b + copysign(new_discr, b);

float x0p = c / q,
x1p = q / a;

// Order the results so that x0 < x1
x0 = min(x0p, x1p);
x1 = max(x0p, x1p);

return true;
}
#endif
16 changes: 16 additions & 0 deletions include/mitsuba/render/optix/matrix.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,22 @@ template <typename Value_, size_t Size_> struct Matrix {
}
printf("]\n");
}

DEVICE Vector3f prod(const Vector3f &v) const {
Vector3f result(0.f);
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j)
result = ::fmaf(v[j], m[j][i], result[i]);
return result;
}

DEVICE Vector3f prod_inv(const Vector3f &v) const {
Vector3f result = m[0];
result *= v.x();
for (size_t i = 1; i < 3; ++i)
result = fmaf(v[i], m[i], result);
return result;
}
#endif

Row m[Size];
Expand Down
71 changes: 47 additions & 24 deletions include/mitsuba/render/optix/shapes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "sdfgrid.cuh"
#include "sphere.cuh"
#include "bsplinecurve.cuh"
#include "ellipsoids.cuh"
#include "ellipsoidsmesh.cuh"
#include "linearcurve.cuh"
#else

Expand All @@ -32,16 +34,18 @@ enum OptixShapeType {
Sphere,
Cylinder,
SDFGrid,
Ellipsoids,
NumOptixShapeTypes
};
static std::string OPTIX_SHAPE_TYPE_NAMES[NumOptixShapeTypes] = {
"BSplineCurve",
"LinearCurve",
"Disk",
"LinearCurve",
"Disk",
"Rectangle",
"Sphere",
"Cylinder",
"SDFGrid"
"SDFGrid",
"Ellipsoids",
};
static std::unordered_map<std::string, size_t> OPTIX_SHAPE_TYPE_INDEX = [](){
std::unordered_map<std::string, size_t> out;
Expand All @@ -53,7 +57,14 @@ static std::unordered_map<std::string, size_t> OPTIX_SHAPE_TYPE_INDEX = [](){

/// Defines the ordering of the shapes for OptiX (hitgroups, SBT)
static OptixShapeType OPTIX_SHAPE_ORDER[] = {
BSplineCurve, LinearCurve, Disk, Rectangle, Sphere, Cylinder, SDFGrid
BSplineCurve,
LinearCurve,
Disk,
Rectangle,
Sphere,
Cylinder,
SDFGrid,
Ellipsoids
};

static constexpr size_t OPTIX_SHAPE_TYPE_COUNT = std::size(OPTIX_SHAPE_ORDER);
Expand Down Expand Up @@ -98,15 +109,17 @@ struct OptixAccelData {
uint32_t count = 0u;
};
HandleData meshes;
HandleData ellipsoids_meshes;
HandleData bspline_curves;
HandleData linear_curves;
HandleData custom_shapes;

~OptixAccelData() {
if (meshes.buffer) jit_free(meshes.buffer);
if (bspline_curves.buffer) jit_free(bspline_curves.buffer);
if (linear_curves.buffer) jit_free(linear_curves.buffer);
if (custom_shapes.buffer) jit_free(custom_shapes.buffer);
if (meshes.buffer) jit_free(meshes.buffer);
if (ellipsoids_meshes.buffer) jit_free(ellipsoids_meshes.buffer);
if (bspline_curves.buffer) jit_free(bspline_curves.buffer);
if (linear_curves.buffer) jit_free(linear_curves.buffer);
if (custom_shapes.buffer) jit_free(custom_shapes.buffer);
}
};

Expand All @@ -116,17 +129,19 @@ void fill_hitgroup_records(std::vector<ref<Shape>> &shapes,
std::vector<HitGroupSbtRecord> &out_hitgroup_records,
const OptixProgramGroup *program_groups) {

// Fill records in this order: meshes, b-spline curves, linear curves, other
// Fill records in this order: meshes, linear curves, other
struct {
size_t idx(const ref<Shape>& shape) const {
uint32_t type = shape->shape_type();
if (type == +ShapeType::Mesh)
if (shape->is_mesh() && type != +ShapeType::Ellipsoids)
return 0;
if (type == +ShapeType::BSplineCurve)
if (shape->is_mesh() && type == +ShapeType::Ellipsoids)
return 1;
if (type == +ShapeType::LinearCurve)
if (type == +ShapeType::BSplineCurve)
return 2;
return 3;
if (type == +ShapeType::LinearCurve)
return 3;
return 4;
};

bool operator()(const ref<Shape> &a, const ref<Shape> &b) const {
Expand Down Expand Up @@ -154,12 +169,13 @@ void build_gas(const OptixDeviceContext &context,
OptixAccelData& out_accel) {

// Separate geometry types
std::vector<ref<Shape>> meshes, bspline_curves,
linear_curves, custom_shapes;
std::vector<ref<Shape>> meshes, ellipsoids_meshes, bspline_curves, linear_curves, custom_shapes;
for (auto shape : shapes) {
uint32_t type = shape->shape_type();
if (type == +ShapeType::Mesh)
if (shape->is_mesh() && type != +ShapeType::Ellipsoids)
meshes.push_back(shape);
else if (shape->is_mesh() && type == +ShapeType::Ellipsoids)
ellipsoids_meshes.push_back(shape);
else if (type == +ShapeType::BSplineCurve)
bspline_curves.push_back(shape);
else if (type == +ShapeType::LinearCurve)
Expand Down Expand Up @@ -260,9 +276,10 @@ void build_gas(const OptixDeviceContext &context,

scoped_optix_context guard;

// Order: meshes, b-spline curves, linear curves, other
// Order: meshes, ellipsoids_meshes, b-spline curves, linear curves, other
build_single_gas(custom_shapes, out_accel.custom_shapes);
build_single_gas(meshes, out_accel.meshes);
build_single_gas(ellipsoids_meshes, out_accel.ellipsoids_meshes);
build_single_gas(bspline_curves, out_accel.bspline_curves);
build_single_gas(linear_curves, out_accel.linear_curves);
}
Expand All @@ -285,12 +302,17 @@ void prepare_ias(const OptixDeviceContext &context,
(float) transf.matrix(2, 0), (float) transf.matrix(2, 1),
(float) transf.matrix(2, 2), (float) transf.matrix(2, 3) };

// Check whether transformation should be disabled on the IAS
uint32_t flags = (transf == Transform4f())
? OPTIX_INSTANCE_FLAG_DISABLE_TRANSFORM
: OPTIX_INSTANCE_FLAG_NONE;

auto build_optix_instance = [&](const OptixAccelData::HandleData &handle) {
auto build_optix_instance = [&](const OptixAccelData::HandleData &handle,
bool disable_face_culling = true) {
// TODO: Here we are forcing backface culling to be disabled for meshes other
// than EllipsoidsMeshes. In case we want to enable backface culling on a
// per-mesh basis in the future, we will need to create another IAS specifically
// for meshes that request backface culling (e.g. could add Shape->enable_backface_culling())
uint32_t flags = disable_face_culling ?
OPTIX_INSTANCE_FLAG_DISABLE_TRIANGLE_FACE_CULLING :
OPTIX_INSTANCE_FLAG_NONE;

if (handle.handle) {
OptixInstance instance = {
{ T[0], T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11] },
Expand All @@ -302,8 +324,9 @@ void prepare_ias(const OptixDeviceContext &context,
}
};

// Order: meshes, b-spline curves, linear curves, other
build_optix_instance(accel.meshes);
// Order: meshes, ellipsoids_meshes, b-spline curves, linear curves, other
build_optix_instance(accel.meshes, /* disable_face_culling */ true);
build_optix_instance(accel.ellipsoids_meshes, /* disable_face_culling */ false);
build_optix_instance(accel.bspline_curves);
build_optix_instance(accel.linear_curves);
build_optix_instance(accel.custom_shapes);
Expand Down
6 changes: 6 additions & 0 deletions include/mitsuba/render/optix/vector.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ template <typename Value_, size_t Size_> struct Array {
printf((i < Size - 1 ? "%f, " : "%f"), v[i]);
printf("]\n");
}

DEVICE static Array load(const void *mem) {
Array result;
memcpy(result.v, mem, sizeof(Value) * StorageSize);
return result;
}
#endif

alignas(16) Value v[StorageSize];
Expand Down
Loading