Skip to content

Commit 78ae0fc

Browse files
committed
Cleanup. MediumStack book keeping takes place in shader evaluation. Medium sub classes need a static create method. Added anisotropic test.
1 parent 865eba8 commit 78ae0fc

17 files changed

Lines changed: 491 additions & 479 deletions

File tree

src/cmake/testing.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ macro (osl_add_all_tests)
362362
render-cornell
363363
render-displacement
364364
render-furnace-diffuse
365+
render-mx-anisotropic-vdf
365366
render-mx-furnace-burley-diffuse
366367
render-mx-furnace-oren-nayar
367368
render-mx-furnace-sheen

src/testrender/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# The 'testrender' executable
66
set (testrender_srcs
77
shading.cpp
8-
volume.cpp
98
simpleraytracer.cpp
109
scene.cpp
1110
bvh.cpp
@@ -35,8 +34,6 @@ if (OSL_USE_OPTIX)
3534
sampling.h
3635
shading.h
3736
shading.cpp
38-
volume.h
39-
volume.cpp
4037
simpleraytracer.cpp
4138
)
4239

src/testrender/shading.cpp

Lines changed: 136 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,123 @@ struct ZeltnerBurleySheen final : public BSDF, MxSheenParams {
15131513
}
15141514
};
15151515

1516+
/// @name Mediums
1517+
struct HenyeyGreenstein final : public BSDF {
1518+
const float g;
1519+
OSL_HOSTDEVICE HenyeyGreenstein(float g)
1520+
: BSDF(this),
1521+
g(g)
1522+
{
1523+
}
1524+
1525+
static OSL_HOSTDEVICE float PhaseHG(float cos_theta, float g) {
1526+
const float denom = 1 + g * g + 2 * g * cos_theta;
1527+
return (1 - g * g) / (4 * M_PI * denom * sqrtf(denom));
1528+
}
1529+
1530+
OSL_HOSTDEVICE Sample eval(const Vec3& wo, const Vec3& wi) const
1531+
{
1532+
const float pdf = PhaseHG(dot(wo, wi), g);
1533+
return { wi, Color3(pdf), pdf, 0.0f };
1534+
}
1535+
1536+
OSL_HOSTDEVICE Sample sample(const Vec3& wo, float rx, float ry, float rz) const
1537+
{
1538+
TangentFrame frame = TangentFrame::from_normal(wo);
1539+
1540+
float cos_theta;
1541+
if (abs(g) < 1e-3f) {
1542+
cos_theta = 1.0f - 2.0f * rx;
1543+
} else {
1544+
float sqr_term = (1 - g * g) / (1 - g + 2 * g * rx);
1545+
cos_theta = (1 + g * g - sqr_term * sqr_term) / (2 * g);
1546+
cos_theta = OIIO::clamp(cos_theta, -1.0f, 1.0f);
1547+
}
1548+
1549+
float sin_theta = sqrtf(OIIO::clamp(1.0f - cos_theta * cos_theta, 0.0f, 1.0f));
1550+
float phi = 2 * M_PI * ry;
1551+
Vec3 local_wi = Vec3(sin_theta * cosf(phi), sin_theta * sinf(phi), cos_theta);
1552+
1553+
Vec3 wi = frame.toworld(local_wi);
1554+
float pdf_val = PhaseHG(cos_theta, g);
1555+
1556+
Color3 weight = Color3(1.0f);
1557+
return { wi, weight, pdf_val, 0.0f };
1558+
}
1559+
1560+
};
1561+
1562+
struct HomogeneousVolume final : public Medium, MediumParams {
1563+
1564+
OSL_HOSTDEVICE HomogeneousVolume(const MediumParams& params)
1565+
: Medium(this), MediumParams(params)
1566+
{
1567+
}
1568+
1569+
OSL_HOSTDEVICE static HomogeneousVolume* create(void* storage, const MediumParams& params) {
1570+
HomogeneousVolume* volume = new (storage) HomogeneousVolume(params);
1571+
volume->phase_func = new HenyeyGreenstein(params.medium_g); // assuming g is anisotropy parameter
1572+
return volume;
1573+
}
1574+
1575+
OSL_HOSTDEVICE Medium::Sample sample(const Ray &ray, Sampler &sampler, Intersection& hit) const
1576+
{
1577+
Vec3 rand_vol = sampler.get();
1578+
float max_sigma_t = std::max(std::max(sigma_t.x, sigma_t.y), sigma_t.z);
1579+
/*
1580+
if (max_sigma_t <= 0.0f) {
1581+
// vacuum: no attenuation, pdf irrelevant
1582+
return Medium::Sample { hit.t, false, Color3(1.0f) };
1583+
}
1584+
*/
1585+
float t_volume = -logf(1.0f - rand_vol.x) / max_sigma_t;
1586+
bool volume_scatter = (t_volume < hit.t);
1587+
1588+
Color3 weight;
1589+
Color3 tr;
1590+
1591+
if (volume_scatter) {
1592+
tr = transmittance(t_volume);
1593+
1594+
Color3 albedo = Color3(
1595+
sigma_s.x / sigma_t.x,
1596+
sigma_s.y / sigma_t.y,
1597+
sigma_s.z / sigma_t.z
1598+
);
1599+
1600+
weight = albedo / tr;
1601+
} else {
1602+
tr = transmittance(hit.t);
1603+
weight = Color3(
1604+
1.0 / tr.x,
1605+
1.0 / tr.y,
1606+
1.0 / tr.z
1607+
);
1608+
}
1609+
/*
1610+
if (pdf <= 0.0f) {
1611+
// ensure Tr is black in this degenerate case if we expected absorption
1612+
return Medium::Sample { hit.t, false, tr };
1613+
}
1614+
*/
1615+
return Medium::Sample { volume_scatter, t_volume, tr, weight };
1616+
}
1617+
1618+
OSL_HOSTDEVICE Color3 transmittance(float distance) const
1619+
{ //Beer-Lambert law
1620+
return Color3(expf(-sigma_t.x * distance),
1621+
expf(-sigma_t.y * distance),
1622+
expf(-sigma_t.z * distance));
1623+
}
1624+
};
1625+
1626+
struct EmptyVolume final : public Medium {
1627+
OSL_HOSTDEVICE EmptyVolume() :
1628+
Medium(this)
1629+
{
1630+
}
1631+
};
1632+
15161633
OSL_HOSTDEVICE Color3
15171634
evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness,
15181635
const ClosureColor* closure)
@@ -1606,8 +1723,8 @@ evaluate_layer_opacity(const ShaderGlobalsType& sg, float path_roughness,
16061723

16071724
OSL_HOSTDEVICE void
16081725
process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
1609-
ShadingResult& result, const ClosureColor* closure,
1610-
const Color3& w)
1726+
ShadingResult& result, MediumStack &medium_stack,
1727+
const ClosureColor* closure, const Color3& w)
16111728
{
16121729
if (!closure)
16131730
return;
@@ -1652,6 +1769,11 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
16521769
result.medium_data.sigma_t = cw * params.extinction;
16531770
result.medium_data.sigma_s = params.albedo * result.medium_data.sigma_t;
16541771
result.medium_data.medium_g = params.anisotropy;
1772+
1773+
if (!sg.backfacing) { // if entering
1774+
medium_stack.push_medium<HomogeneousVolume>(result.medium_data);
1775+
}
1776+
16551777
closure = nullptr;
16561778
break;
16571779
}
@@ -1673,6 +1795,11 @@ process_medium_closure(const ShaderGlobalsType& sg, float path_roughness,
16731795
// Track IOR and priority here
16741796
result.medium_data.refraction_ior = sg.backfacing ? 1.0f / params.ior
16751797
: params.ior;
1798+
1799+
if (!sg.backfacing) { // if entering
1800+
medium_stack.push_medium<HomogeneousVolume>(result.medium_data);
1801+
}
1802+
16761803
//result.medium_data.priority = params.priority;
16771804
closure = nullptr;
16781805
break;
@@ -1961,10 +2088,11 @@ process_bsdf_closure(const ShaderGlobalsType& sg, float path_roughness,
19612088

19622089
OSL_HOSTDEVICE void
19632090
process_closure(const ShaderGlobalsType& sg, float path_roughness,
1964-
ShadingResult& result, const ClosureColor* Ci, bool light_only)
2091+
ShadingResult& result, MediumStack &medium_stack,
2092+
const ClosureColor* Ci, bool light_only)
19652093
{
19662094
if (!light_only)
1967-
process_medium_closure(sg, path_roughness, result, Ci, Color3(1));
2095+
process_medium_closure(sg, path_roughness, result, medium_stack, Ci, Color3(1));
19682096
process_bsdf_closure(sg, path_roughness, result, Ci, Color3(1), light_only);
19692097
}
19702098

@@ -2026,5 +2154,9 @@ BSDF::sample_vrtl(const Vec3& wo, float rx, float ry, float rz) const
20262154
return dispatch([&](auto bsdf) { return bsdf.sample(wo, rx, ry, rz); });
20272155
}
20282156

2157+
Medium::Sample Medium::sample_vrtl(const Ray &ray, Sampler &sampler, Intersection& hit) const
2158+
{
2159+
return dispatch([&](auto volume) { return volume.sample(ray, sampler, hit); });
2160+
}
20292161

20302162
OSL_NAMESPACE_END

0 commit comments

Comments
 (0)