Skip to content

Envmap sampling test#257

Open
kevyuu wants to merge 3 commits intomasterfrom
envmap_sampling_test
Open

Envmap sampling test#257
kevyuu wants to merge 3 commits intomasterfrom
envmap_sampling_test

Conversation

@kevyuu
Copy link
Copy Markdown

@kevyuu kevyuu commented Feb 23, 2026

This is pull request for testing environment map sampling

using namespace nbl;
using namespace nbl::hlsl;

NBL_CONSTEXPR uint32_t WorkgroupSize = 128;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

64 to be more representative of path tracing workloads

Comment on lines +1 to +28
include(common RESULT_VARIABLE RES)
if(NOT RES)
message(FATAL_ERROR "common.cmake not found. Should be in {repo_root}/cmake directory")
endif()

nbl_create_executable_project("" "" "" "" "${NBL_EXECUTABLE_PROJECT_CREATION_PCH_TARGET}")

if(NBL_EMBED_BUILTIN_RESOURCES)
set(_BR_TARGET_ ${EXECUTABLE_NAME}_builtinResourceData)
set(RESOURCE_DIR "app_resources")

get_filename_component(_SEARCH_DIRECTORIES_ "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE)
get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)

file(GLOB_RECURSE BUILTIN_RESOURCE_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}" CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${RESOURCE_DIR}/*")
foreach(RES_FILE ${BUILTIN_RESOURCE_FILES})
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "${RES_FILE}")
endforeach()

ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_SEARCH_DIRECTORIES_}" "${RESOURCE_DIR}" "nbl::this_example::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}")

LINK_BUILTIN_RESOURCES_TO_TARGET(${EXECUTABLE_NAME} ${_BR_TARGET_})
endif()

add_dependencies(${EXECUTABLE_NAME} argparse)
target_include_directories(${EXECUTABLE_NAME} PUBLIC $<TARGET_PROPERTY:argparse,INTERFACE_INCLUDE_DIRECTORIES>)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AnastaZIuk review and okay the CMake

Comment on lines +46 to +49
uint32_t2 uv = texelCoord / float32_t2(pc.warpWidth, pc.warpHeight);
const float32_t4 reds = warpMap.GatherRed(warpSampler, uv);
const float32_t4 greens = warpMap.GatherGreen(warpSampler, uv);

Copy link
Copy Markdown
Member

@devshgraphicsprogramming devshgraphicsprogramming Mar 25, 2026

Choose a reason for hiding this comment

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

youre corner sampling, so you need to add half a pixel to texelCoord when you make texelCoord out of it before the frac

Right now you're gathering the wrong pixels - for the same floor(texelCoord) you're getting different values from your gather

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it would actually make sense to pull this logic out of the warpmap accessor, and have the warpmap accessor just report the size of the warpmap and let the Warpmap sampler deal with corner sampling and computing the interpolant while this function would just take uint16_t coord instead of xi and interpolant arguments

Comment on lines +42 to +55
template<typename T>
bool checkEq(T a, T b, float32_t eps = 1e-4)
{
if constexpr (!is_vector_v<T>)
{
return abs(a - b) <= eps;
}
else
{
T _a = hlsl::max(hlsl::abs(a), hlsl::promote<T>(1e-5));
T _b = hlsl::max(hlsl::abs(b), hlsl::promote<T>(1e-5));
return nbl::hlsl::all<hlsl::vector<bool, vector_traits<T>::Dimension> >(nbl::hlsl::max<T>(_a / _b, _b / _a) <= hlsl::promote<T>(1 + eps));
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

master has a good version of this


auto shader = IAsset::castDown<IShader>(assets[0]);
return shader;
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@AnastaZIuk do we have a nice thing for this in the example commons ?

Esp if it could also use the driver to compile shaders that aren't yet compiled

Comment on lines +64 to +85
const sample_type sample = hImage.generate(xi);
const float3 L = sample.value();

float eps_x = pc.eps;
float eps_y = pc.eps;

const sample_type sample_plus_du = hImage.generate(xi + float32_t2(0.5f * eps_x, 0));
const float3 L_plus_du = sample_plus_du.value();
const sample_type sample_plus_dv = hImage.generate(xi + float32_t2(0, 0.5f * eps_y));
const float3 L_plus_dv = sample_plus_dv.value();

const sample_type sample_minus_du = hImage.generate(xi - float32_t2(0.5f * eps_x, 0));
const float3 L_minus_du = sample_minus_du.value();
const sample_type sample_minus_dv = hImage.generate(xi - float32_t2(0, 0.5f * eps_y));
const float3 L_minus_dv = sample_minus_dv.value();

float jacobian = length(cross(L_plus_du - L_minus_du, L_plus_dv - L_minus_dv)) / (eps_x * eps_y);

TestOutput testOutput;
testOutput.L = L;
testOutput.jacobian = jacobian;
testOutput.pdf = sample.pdf();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

sample is a HLSL keyword, use _sample instead

float eps_y = pc.eps;

const sample_type sample_plus_du = hImage.generate(xi + float32_t2(0.5f * eps_x, 0));
const float3 L_plus_du = sample_plus_du.value();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

when PR 1001 comes, you'll be getting these via forwardPdf then it will be useful to test that backwardPdf matches if the WarpSamplerT is BackwardTractableSampler

In either case you'll want to test that forwardWeight == backwardWeight

Comment on lines +101 to +121
using direct_hierarchical_image_type = sampling::HierarchicalWarpSampler<float, LuminanceAccessor, sampling::warp::Spherical<float> >;

float32_t eps = pc.eps;

random::PCG32 pcg = random::PCG32::construct(threadID.x);
uint32_t2 xi_uint = random::DimAdaptorRecursive<random::PCG32, 2>::__call(pcg);

float32_t2 xi = convertToFloat01(xi_uint);

xi.x = hlsl::clamp(xi.x, eps, 1.f - eps);
xi.y = hlsl::clamp(xi.y, eps, 1.f - eps);

test_sample_t testSample;
testSample.xi = xi;

uint32_t2 warpResolution = { pc.warpWidth, pc.warpHeight };
const direct_hierarchical_image_type directHImage = direct_hierarchical_image_type::create(luminanceAccessor, pc.avgLuma, warpResolution, warpResolution.x != warpResolution.y);

testSample.directOutput = GenerateTestOutput(directHImage, xi);

using cached_hierarchical_image_type = sampling::WarpmapSampler<float, LuminanceAccessor, WarpmapAccessor, sampling::warp::Spherical<float> >;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the Spherical warp you're using, is not aware of the corner sampling, so the hierarchical sampler outputs uv for corner sampling and you're warping them like regular UVs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ok as long as you make the HierarchicalWarpGenerator (to be renamed HierarchicalSampler) handle all the corner sampling for you transparently and return and accept corner sampled as [0,1]^2 relative to the corners, this can stay as is in the examples

Comment on lines +47 to +48
const float32_t4 reds = warpMap.GatherRed(warpSampler, uv);
const float32_t4 greens = warpMap.GatherGreen(warpSampler, uv);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how does this even compile? HLSL GatherRed takes a sampler object and then a floating point coordinate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

so the / float32_t2(pc.warpWidth, pc.warpHeight) division shouldn't be there

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.

2 participants