Skip to content

Commit 9f9c859

Browse files
committed
MediumStack stores Medium sub classes similar to CompositeBSDF. PhaseFunction has been deleted.
1 parent db903d6 commit 9f9c859

7 files changed

Lines changed: 242 additions & 225 deletions

File tree

src/testrender/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ if (OSL_USE_OPTIX)
3535
sampling.h
3636
shading.h
3737
shading.cpp
38+
volume.h
39+
volume.cpp
3840
simpleraytracer.cpp
3941
)
4042

src/testrender/shading.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,6 @@ struct MxDielectric : public bsdl::mtx::DielectricLobe<BSDLLobe> {
167167
}
168168
};
169169

170-
171-
172170
#ifndef __CUDACC__
173171
// Helper to register BSDL closures
174172
struct BSDLtoOSL {
@@ -1675,7 +1673,7 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
16751673
// Track IOR and priority here
16761674
result.medium_data.refraction_ior = sg.backfacing ? 1.0f / params.ior
16771675
: params.ior;
1678-
result.medium_data.priority = params.priority;
1676+
//result.medium_data.priority = params.priority;
16791677
closure = nullptr;
16801678
break;
16811679
}

src/testrender/shading.h

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
#include "optics.h"
1818
#include "sampling.h"
19-
#include "volume.h"
20-
2119

2220
OSL_NAMESPACE_BEGIN
2321

@@ -262,6 +260,7 @@ struct EnergyCompensatedOrenNayar;
262260
struct ZeltnerBurleySheen;
263261
struct CharlieSheen;
264262
struct SpiThinLayer;
263+
struct HenyeyGreenstein;
265264

266265
// StaticVirtual generates a switch/case dispatch method for us given
267266
// a list of possible subtypes. We just need to forward declare them.
@@ -271,7 +270,8 @@ using AbstractBSDF = bsdl::StaticVirtual<
271270
MicrofacetBeckmannBoth, MicrofacetGGXRefl, MicrofacetGGXRefr,
272271
MicrofacetGGXBoth, MxConductor, MxDielectric, MxBurleyDiffuse,
273272
EnergyCompensatedOrenNayar, ZeltnerBurleySheen, CharlieSheen,
274-
MxGeneralizedSchlickOpaque, MxGeneralizedSchlick, SpiThinLayer>;
273+
MxGeneralizedSchlickOpaque, MxGeneralizedSchlick, SpiThinLayer,
274+
HenyeyGreenstein>;
275275

276276
// Then we just need to inherit from AbstractBSDF
277277

@@ -455,13 +455,84 @@ struct CompositeBSDF {
455455
int num_bsdfs, num_bytes;
456456
};
457457

458-
struct MediumProperties;
458+
struct VolumeParams {
459+
Color3 sigma_t = Color3(0.0f); // extinction coefficient
460+
Color3 sigma_s = Color3(0.0f); //scattering
461+
float medium_g = 0.0f; // volumetric anisotropy
462+
float refraction_ior = 1.0f;
463+
//int priority = 0;
459464

465+
OSL_HOSTDEVICE bool is_vacuum() const
466+
{
467+
return sigma_t.x <= 0.0f && sigma_t.y <= 0.0f && sigma_t.z <= 0.0f;
468+
}
469+
470+
OSL_HOSTDEVICE bool operator==(const VolumeParams &rhs) const {
471+
return refraction_ior == rhs.refraction_ior &&
472+
medium_g == rhs.medium_g &&
473+
sigma_t.x == rhs.sigma_t.x &&
474+
sigma_t.y == rhs.sigma_t.y &&
475+
sigma_t.z == rhs.sigma_t.z &&
476+
sigma_s.x == rhs.sigma_s.x &&
477+
sigma_s.y == rhs.sigma_s.y &&
478+
sigma_s.z == rhs.sigma_s.z;
479+
}
480+
481+
OSL_HOSTDEVICE float max_sigma_t() const
482+
{
483+
return std::max(std::max(sigma_t.x, sigma_t.y), sigma_t.z);
484+
}
485+
};
460486

461487
struct ShadingResult {
462488
Color3 Le = Color3(0.0f);
463489
CompositeBSDF bsdf = {};
464-
MediumProperties medium_data = {};
490+
VolumeParams medium_data = {};
491+
};
492+
493+
struct HenyeyGreenstein final : public BSDF {
494+
const float g;
495+
OSL_HOSTDEVICE HenyeyGreenstein(float g)
496+
: BSDF(this),
497+
g(g)
498+
{
499+
}
500+
501+
static OSL_HOSTDEVICE float PhaseHG(float cos_theta, float g) {
502+
const float denom = 1 + g * g + 2 * g * cos_theta;
503+
return (1 - g * g) / (4 * M_PI * denom * sqrtf(denom));
504+
}
505+
506+
OSL_HOSTDEVICE Sample eval(const Vec3& wo, const Vec3& wi) const
507+
{
508+
const float pdf = PhaseHG(dot(wo, wi), g);
509+
return { wi, Color3(pdf), pdf, 0.0f };
510+
}
511+
512+
OSL_HOSTDEVICE Sample sample(const Vec3& wo, float rx, float ry, float rz) const
513+
{
514+
TangentFrame frame = TangentFrame::from_normal(wo);
515+
516+
float cos_theta;
517+
if (abs(g) < 1e-3f) {
518+
cos_theta = 1.0f - 2.0f * rx;
519+
} else {
520+
float sqr_term = (1 - g * g) / (1 - g + 2 * g * rx);
521+
cos_theta = (1 + g * g - sqr_term * sqr_term) / (2 * g);
522+
cos_theta = OIIO::clamp(cos_theta, -1.0f, 1.0f);
523+
}
524+
525+
float sin_theta = sqrtf(OIIO::clamp(1.0f - cos_theta * cos_theta, 0.0f, 1.0f));
526+
float phi = 2 * M_PI * ry;
527+
Vec3 local_wi = Vec3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
528+
529+
Vec3 wi = frame.toworld(local_wi);
530+
float pdf_val = PhaseHG(cos_theta, g);
531+
532+
Color3 weight = Color3(1.0f);
533+
return { wi, weight, pdf_val, 0.0f };
534+
}
535+
465536
};
466537

467538
void

src/testrender/simpleraytracer.cpp

Lines changed: 32 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -975,58 +975,45 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
975975
ShaderGlobalsType sg;
976976
// trace the ray against the scene
977977
Intersection hit = scene.intersect(r, inf, prev_id);
978-
979-
const MediumProperties* current_volume = medium_stack.current();
978+
979+
const HomogeneousVolume* volume = static_cast<const HomogeneousVolume*>(medium_stack.current());
980980
bool in_medium = medium_stack.in_medium();
981981

982-
//determine whether ray is in a medium
983-
float t_volume = inf;
984-
if (in_medium && current_volume && !current_volume->is_vacuum()) {
985-
Vec3 rand_vol = sampler.get();
986-
t_volume = current_volume->sample_distance(rand_vol.x);
987-
}
982+
if (in_medium && volume && !volume->is_vacuum()) {
983+
Medium::Sample medium_sample = volume->sample(r, sampler, hit);
988984

989-
//is there volume scattering
990-
bool volume_scatter = in_medium && (t_volume < hit.t);
991-
float t_event = volume_scatter ? t_volume : hit.t;
992-
993-
//apply volumetric transmittance up to the event
994-
if (in_medium && current_volume && !current_volume->is_vacuum()) {
995-
Color3 transmittance = current_volume->transmittance(t_event);
996-
path_weight *= transmittance;
985+
path_weight *= medium_sample.transmittance;
997986

998-
//early exit if transmittance kills the path
999987
if (!(path_weight.x > 0) && !(path_weight.y > 0) && !(path_weight.z > 0)) {
1000988
break;
1001989
}
1002-
}
1003-
1004-
// do volume scattering
1005-
if (volume_scatter) {
1006-
r.origin = r.origin + r.direction * t_volume;
1007-
1008-
Vec3 rand_phase = sampler.get();
1009-
HenyeyGreenstein phase_func(current_volume->medium_g);
1010-
//IsotropicPhase phase_func;
1011-
PhaseFunction::Sample phase_sample = phase_func.sample(-r.direction, rand_phase.x, rand_phase.y);
1012-
1013-
if (phase_sample.pdf <= 0.0f) {
1014-
break;
1015-
}
1016-
1017-
//single scattering albedo = sigma_s / sigma_t
1018-
Color3 albedo = Color3(
1019-
current_volume->sigma_s.x / current_volume->sigma_t.x,
1020-
current_volume->sigma_s.y / current_volume->sigma_t.y,
1021-
current_volume->sigma_s.z / current_volume->sigma_t.z
1022-
);
1023-
1024-
path_weight *= albedo * phase_sample.weight;
990+
991+
r.origin = r.origin + r.direction * medium_sample.t;
992+
1025993

1026-
r.direction = phase_sample.wi;
1027-
bsdf_pdf = phase_sample.pdf;
994+
if (medium_sample.scatter) {
995+
996+
Vec3 rand_phase = sampler.get();
997+
HenyeyGreenstein phase_func(volume->medium_g);
998+
BSDF::Sample phase_sample = phase_func.sample(-r.direction, rand_phase.x, rand_phase.y, rand_phase.z);
999+
1000+
if (phase_sample.pdf <= 0.0f) {
1001+
break;
1002+
}
10281003

1029-
continue;
1004+
Color3 albedo = Color3(
1005+
volume->sigma_s.x / volume->sigma_t.x,
1006+
volume->sigma_s.y / volume->sigma_t.y,
1007+
volume->sigma_s.z / volume->sigma_t.z
1008+
);
1009+
1010+
path_weight *= albedo * phase_sample.weight;
1011+
1012+
r.direction = phase_sample.wi;
1013+
bsdf_pdf = phase_sample.pdf;
1014+
1015+
continue;
1016+
}
10301017
}
10311018

10321019
if (hit.t == inf) {
@@ -1217,9 +1204,9 @@ SimpleRaytracer::subpixel_radiance(float x, float y, Sampler& sampler,
12171204
bool entering = !sg.backfacing;
12181205

12191206
if (entering) {
1220-
medium_stack.push(result.medium_data);
1207+
medium_stack.push_medium<HomogeneousVolume>(result.medium_data);
12211208
} else {
1222-
medium_stack.pop();
1209+
medium_stack.pop_medium();
12231210
}
12241211
}
12251212

src/testrender/volume.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
// Copyright Contributors to the Open Shading Language project.
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
// https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
4+
15
#include "volume.h"
2-
#include "sampling.h"
36

47

58
OSL_NAMESPACE_BEGIN
69

10+
//OSL_HOSTDEVICE BSDF::Sample HomogeneousVolume::sample(Ray &r, Sampler &sampler, Intersection& hit, Color3& path_weight)
11+
712

8-
OSL_NAMESPACE_END
13+
OSL_NAMESPACE_END

0 commit comments

Comments
 (0)