From 58312d5a9e94388f94f8a796b63ff80021a00077 Mon Sep 17 00:00:00 2001 From: Cyrille Favreau Date: Mon, 20 Sep 2021 09:05:30 +0200 Subject: [PATCH] Added displacement option to SDF geometry --- brayns/common/geometry/SDFGeometry.h | 23 +++++++++++------- engines/ospray/ispc/geometry/RayMarching.isph | 5 ++-- .../ospray/ispc/geometry/SDFGeometries.ispc | 24 ++++++++++++++----- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/brayns/common/geometry/SDFGeometry.h b/brayns/common/geometry/SDFGeometry.h index 6feb2057a..7fd8caf43 100644 --- a/brayns/common/geometry/SDFGeometry.h +++ b/brayns/common/geometry/SDFGeometry.h @@ -35,7 +35,7 @@ enum class SDFType : uint8_t struct SDFGeometry { uint64_t userData; - Vector3f center; // TO BE REMOVED, for v3 cache compatibility only + Vector3f userParams; // Currently used exclusively for displacement Vector3f p0; Vector3f p1; float r0 = -1.f; @@ -46,10 +46,12 @@ struct SDFGeometry }; inline SDFGeometry createSDFSphere(const Vector3f& center, const float radius, - const uint64_t data = 0) + const uint64_t data = 0, + const Vector3f& userParams = Vector3f(0.f)) { SDFGeometry geom; geom.userData = data; + geom.userParams = userParams; geom.p0 = center; geom.r0 = radius; geom.type = SDFType::Sphere; @@ -57,10 +59,12 @@ inline SDFGeometry createSDFSphere(const Vector3f& center, const float radius, } inline SDFGeometry createSDFPill(const Vector3f& p0, const Vector3f& p1, - const float radius, const uint64_t data = 0) + const float radius, const uint64_t data = 0, + const Vector3f& userParams = Vector3f(0.f)) { SDFGeometry geom; geom.userData = data; + geom.userParams = userParams; geom.p0 = p0; geom.p1 = p1; geom.r0 = radius; @@ -70,10 +74,12 @@ inline SDFGeometry createSDFPill(const Vector3f& p0, const Vector3f& p1, inline SDFGeometry createSDFConePill(const Vector3f& p0, const Vector3f& p1, const float r0, const float r1, - const uint64_t data = 0) + const uint64_t data = 0, + const Vector3f& userParams = Vector3f(0.f)) { SDFGeometry geom; geom.userData = data; + geom.userParams = userParams; geom.p0 = p0; geom.p1 = p1; geom.r0 = r0; @@ -89,12 +95,11 @@ inline SDFGeometry createSDFConePill(const Vector3f& p0, const Vector3f& p1, return geom; } -inline SDFGeometry createSDFConePillSigmoid(const Vector3f& p0, - const Vector3f& p1, const float r0, - const float r1, - const uint64_t data = 0) +inline SDFGeometry createSDFConePillSigmoid( + const Vector3f& p0, const Vector3f& p1, const float r0, const float r1, + const uint64_t data = 0, const Vector3f& userParams = Vector3f(0.f)) { - SDFGeometry geom = createSDFConePill(p0, p1, r0, r1, data); + SDFGeometry geom = createSDFConePill(p0, p1, r0, r1, data, userParams); geom.type = SDFType::ConePillSigmoid; return geom; } diff --git a/engines/ospray/ispc/geometry/RayMarching.isph b/engines/ospray/ispc/geometry/RayMarching.isph index 434c4b7da..06a6fdd4c 100644 --- a/engines/ospray/ispc/geometry/RayMarching.isph +++ b/engines/ospray/ispc/geometry/RayMarching.isph @@ -61,8 +61,9 @@ inline vec3f computeNormal(const vec3f& pos, const SDFParams& params) { // tetrahedron technique (4 evaluations) - const uniform vec3f k0 = make_vec3f(1, -1, -1), k1 = make_vec3f(-1, -1, 1), - k2 = make_vec3f(-1, 1, -1), k3 = make_vec3f(1, 1, 1); + const uniform float t = 2.f; + const uniform vec3f k0 = make_vec3f( t, -t, -t), k1 = make_vec3f(-t, -t, t), + k2 = make_vec3f(-t, t, -t), k3 = make_vec3f(t, t, t); return normalize(k0 * sdfDistance(pos + e * k0, geo, prim, params) + k1 * sdfDistance(pos + e * k1, geo, prim, params) + diff --git a/engines/ospray/ispc/geometry/SDFGeometries.ispc b/engines/ospray/ispc/geometry/SDFGeometries.ispc index a599e7903..7f6c9a958 100644 --- a/engines/ospray/ispc/geometry/SDFGeometries.ispc +++ b/engines/ospray/ispc/geometry/SDFGeometries.ispc @@ -56,6 +56,11 @@ inline float smootherstep(const float x) return x * x * x * (x * (x * 6 - 15) + 10); } +inline float opDisplacement(const vec3f& p, const float a, const float b) +{ + return a * sin(b * p.x) * sin(b * p.y) * sin(b * p.z); +} + inline float sdSphere(const vec3f& p, const vec3f c, float r) { return length(p - c) - r; @@ -83,12 +88,12 @@ inline float sdConePill(const vec3f& p, const vec3f p0, const vec3f p1, // distance to p0 along cone axis const float c1 = dot(w, v); - if (c1 <= 0) + if (c1 <= 0) // p0 Sphere return length(p - p0) - r0; // cone length const float c2 = dot(v, v); - if (c2 <= c1) + if (c2 <= c1) // p1 Sphere return length(p - p1) - r1; const float b = c1 / c2; @@ -108,7 +113,7 @@ inline float sdConePill(const vec3f& p, const vec3f p0, const vec3f p1, struct SDFGeometry { uint64 userData; - vec3f center; // TO BE REMOVED, for v3 cache compatibility only + vec3f userParams; vec3f p0; vec3f p1; float r0; @@ -179,14 +184,20 @@ const uniform SDFGeometry* varying getPrimitiveVarying( inline float calcDistance(const uniform SDFGeometry& primitive, const vec3f& p) { + float displacement = 0.f; + if (primitive.userParams.x > 0.f) + displacement = opDisplacement(p, primitive.r0 * primitive.userParams.x, + primitive.userParams.y); if (primitive.type == SDF_TYPE_SPHERE) - return sdSphere(p, primitive.p0, primitive.r0); + return displacement + sdSphere(p, primitive.p0, primitive.r0); if (primitive.type == SDF_TYPE_PILL) - return sdCapsule(p, primitive.p0, primitive.p1, primitive.r0); + return displacement + + sdCapsule(p, primitive.p0, primitive.p1, primitive.r0); if (primitive.type == SDF_TYPE_CONE_PILL || primitive.type == SDF_TYPE_CONE_PILL_SIGMOID) { - return sdConePill(p, primitive.p0, primitive.p1, primitive.r0, + return displacement + + sdConePill(p, primitive.p0, primitive.p1, primitive.r0, primitive.r1, primitive.type == SDF_TYPE_CONE_PILL_SIGMOID); } @@ -221,6 +232,7 @@ float sdfDistance(const vec3f& p, uDataPtr_t geo_, uDataPtr_t prim_, const Geo_ptr geo = (const Geo_ptr)geo_; const Prim_ptr prim = (const Prim_ptr)prim_; + // Primitive float d = calcDistance(*prim, p); // TODO don't blend soma if far enough from eye