Skip to content

Env map importance sampling#969

Open
kevyuu wants to merge 78 commits intomasterfrom
env_map_importance_sampling
Open

Env map importance sampling#969
kevyuu wants to merge 78 commits intomasterfrom
env_map_importance_sampling

Conversation

@kevyuu
Copy link
Contributor

@kevyuu kevyuu commented Dec 19, 2025

Description

Rework environment map importance sampling to vulkan and hlsl

Testing

Rework example 0 to use vulkan and hlsl
Unit Test Pull Request

TODO list:

  • Implement Warpmap Generation in hlsl
  • Implement Warpmap hierarchical map sampling in hlsl

CMakeLists.txt Outdated
option(NBL_BUILD_MITSUBA_LOADER "Enable nbl::ext::MitsubaLoader?" ON)
option(NBL_BUILD_IMGUI "Enable nbl::ext::ImGui?" ON)
option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension?" ON)
option(NBL_BUILD_ENVMAP_IMPORTANCE_SAMPLING "Enable Nabla Envmap Importance Sampling extension?" ON)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer an extension, dont need the option

Comment on lines +140 to +157
vector2_type inverseWarp_and_deferredPdf(NBL_REF_ARG(scalar_type) pdf, vector3_type direction) NBL_CONST_MEMBER_FUNC
{
vector2_type envmapUv = PostWarpT::inverseWarp(direction);
scalar_type luma;
_lumaMap.get(envmapUv, luma);
pdf = (luma * _rcpAvgLuma) * PostWarpT::backwardDensity(direction);
return envmapUv;
}

scalar_type deferredPdf(vector3_type direction) NBL_CONST_MEMBER_FUNC
{
vector2_type envmapUv = PostWarpT::inverseWarp(direction);
scalar_type luma;
_lumaMap.get(envmapUv, luma);
return luma * _rcpAvgLuma * PostWarpT::backwardDensity(direction);
}

vector3_type generate_and_pdf(NBL_REF_ARG(scalar_type) pdf, NBL_REF_ARG(vector2_type) uv, vector2_type xi) NBL_CONST_MEMBER_FUNC

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make it conform to #1001 's ResamplableSampler

Comment on lines +112 to +117
template <typename ScalarT, typename LuminanceAccessorT, typename HierarchicalSamplerT, typename PostWarpT
NBL_PRIMARY_REQUIRES(is_scalar_v<ScalarT> &&
concepts::accessors::GenericReadAccessor<LuminanceAccessorT, ScalarT, float32_t2> &&
hierarchical_image::HierarchicalSampler<HierarchicalSamplerT, ScalarT> &&
concepts::Warp<PostWarpT>)
struct HierarchicalImage

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be called WarpmapSampler or something like that

const vector2_type texelCoord = xi * float32_t2(_lastWarpPixel);

matrix<scalar_type, 4, 2> uvs = _warpMap.sampleUvs(uint32_t2(texelCoord));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warpmap should convert you from [0,1] normalized xi to its own texels,the sampleUvs should really work same as textureGather, it should take normalized uvs as input


matrix<scalar_type, 4, 2> uvs = _warpMap.sampleUvs(uint32_t2(texelCoord));

const vector2_type interpolant = frac(texelCoord);
Copy link
Member

@devshgraphicsprogramming devshgraphicsprogramming Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make the _warpMap.gather spit out the interpolant so its cleaner (requires a specialized gather overload, adding on top of Gatherable concept)

LuminanceAccessorT _lumaMap;
HierarchicalSamplerT _warpMap;
uint32_t2 _warpSize;
uint32_t2 _lastWarpPixel;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you actually only need to store the _lastWarpPixel.x * _lastWarpPixel.y prodct, I expect the warpmap to handle gathering

Comment on lines +87 to +88
if (choseSecond(wx_0, wx_1, xi.x))
p.x |= 1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw you can get the PDF of the finally chosen texel as metadata if on the final call to choseSecond you save wx_0 or wx_1 and thats your chosen pixel luminance, you just need to know the average to and total number of texels (corner sampled edges count as half pixels) get the PDF

(obvioulsy if mip2x1 is 0, the PDF is either 1.0 or the dummy from the choice on line 64)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants