Skip to content

Commit

Permalink
Merge pull request #3183 from pmolodo/pr/hdEmbree-random-seed
Browse files Browse the repository at this point in the history
[hdEmbree] add HDEMBREE_RANDOM_NUMBER_SEED (hdEmbree-UsdLux-PR01)

(Internal change: 2341333)
  • Loading branch information
pixar-oss committed Sep 19, 2024
2 parents c219fcf + f53d3e6 commit 31e637a
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 34 deletions.
60 changes: 43 additions & 17 deletions pxr/imaging/plugin/hdEmbree/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,49 @@ TF_INSTANTIATE_SINGLETON(HdEmbreeConfig);
// Each configuration variable has an associated environment variable.
// The environment variable macro takes the variable name, a default value,
// and a description...
TF_DEFINE_ENV_SETTING(HDEMBREE_SAMPLES_TO_CONVERGENCE, 100,
"Samples per pixel before we stop rendering (must be >= 1)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_SAMPLES_TO_CONVERGENCE,
HdEmbreeDefaultSamplesToConvergence,
"Samples per pixel before we stop rendering (must be >= 1)");

TF_DEFINE_ENV_SETTING(HDEMBREE_TILE_SIZE, 8,
"Size (per axis) of threading work units (must be >= 1)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_TILE_SIZE,
HdEmbreeDefaultTileSize,
"Size (per axis) of threading work units (must be >= 1)");

TF_DEFINE_ENV_SETTING(HDEMBREE_AMBIENT_OCCLUSION_SAMPLES, 16,
"Ambient occlusion samples per camera ray (must be >= 0; a value of 0 disables ambient occlusion)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_AMBIENT_OCCLUSION_SAMPLES,
HdEmbreeDefaultAmbientOcclusionSamples,
"Ambient occlusion samples per camera ray (must be >= 0;"
" a value of 0 disables ambient occlusion)");

TF_DEFINE_ENV_SETTING(HDEMBREE_JITTER_CAMERA, 1,
"Should HdEmbree jitter camera rays while rendering? (values >0 are true)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_JITTER_CAMERA,
HdEmbreeDefaultJitterCamera,
"Should HdEmbree jitter camera rays while rendering?");

TF_DEFINE_ENV_SETTING(HDEMBREE_USE_FACE_COLORS, 1,
"Should HdEmbree use face colors while rendering? (values > 0 are true)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_USE_FACE_COLORS,
HdEmbreeDefaultUseFaceColors,
"Should HdEmbree use face colors while rendering?");

TF_DEFINE_ENV_SETTING(HDEMBREE_CAMERA_LIGHT_INTENSITY, 300,
"Intensity of the camera light, specified as a percentage of <1,1,1>.");
TF_DEFINE_ENV_SETTING(
HDEMBREE_CAMERA_LIGHT_INTENSITY,
HdEmbreeDefaultCameraLightIntensity,
"Intensity of the camera light, specified as a percentage of <1,1,1>.");

TF_DEFINE_ENV_SETTING(HDEMBREE_PRINT_CONFIGURATION, 0,
"Should HdEmbree print configuration on startup? (values > 0 are true)");
TF_DEFINE_ENV_SETTING(
HDEMBREE_RANDOM_NUMBER_SEED,
HdEmbreeDefaultRandomNumberSeed,
"Seed to give to the random number generator. A value of anything other"
" than -1, combined with setting PXR_WORK_THREAD_LIMIT=1, should"
" give deterministic / repeatable results. A value of -1 (the"
" default) will allow the implementation to set a value that varies"
" from invocation to invocation and thread to thread.");

TF_DEFINE_ENV_SETTING(HDEMBREE_PRINT_CONFIGURATION,
false,
"Should HdEmbree print configuration on startup?");

HdEmbreeConfig::HdEmbreeConfig()
{
Expand All @@ -50,12 +73,13 @@ HdEmbreeConfig::HdEmbreeConfig()
TfGetEnvSetting(HDEMBREE_TILE_SIZE));
ambientOcclusionSamples = std::max(0,
TfGetEnvSetting(HDEMBREE_AMBIENT_OCCLUSION_SAMPLES));
jitterCamera = (TfGetEnvSetting(HDEMBREE_JITTER_CAMERA) > 0);
useFaceColors = (TfGetEnvSetting(HDEMBREE_USE_FACE_COLORS) > 0);
jitterCamera = (TfGetEnvSetting(HDEMBREE_JITTER_CAMERA));
useFaceColors = (TfGetEnvSetting(HDEMBREE_USE_FACE_COLORS));
cameraLightIntensity = (std::max(100,
TfGetEnvSetting(HDEMBREE_CAMERA_LIGHT_INTENSITY)) / 100.0f);
randomNumberSeed = TfGetEnvSetting(HDEMBREE_RANDOM_NUMBER_SEED);

if (TfGetEnvSetting(HDEMBREE_PRINT_CONFIGURATION) > 0) {
if (TfGetEnvSetting(HDEMBREE_PRINT_CONFIGURATION)) {
std::cout
<< "HdEmbree Configuration: \n"
<< " samplesToConvergence = "
Expand All @@ -70,6 +94,8 @@ HdEmbreeConfig::HdEmbreeConfig()
<< useFaceColors << "\n"
<< " cameraLightIntensity = "
<< cameraLightIntensity << "\n"
<< " randomNumberSeed = "
<< randomNumberSeed << "\n"
;
}
}
Expand Down
42 changes: 32 additions & 10 deletions pxr/imaging/plugin/hdEmbree/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@

PXR_NAMESPACE_OPEN_SCOPE

// NOTE: types here restricted to bool/int/string, as also used for
// TF_DEFINE_ENV_SETTING
constexpr int HdEmbreeDefaultSamplesToConvergence = 100;
constexpr int HdEmbreeDefaultTileSize = 8;
constexpr int HdEmbreeDefaultAmbientOcclusionSamples = 16;
constexpr bool HdEmbreeDefaultJitterCamera = true;
constexpr bool HdEmbreeDefaultUseFaceColors = true;
constexpr int HdEmbreeDefaultCameraLightIntensity = 300;
constexpr int HdEmbreeDefaultRandomNumberSeed = -1;

/// \class HdEmbreeConfig
///
/// This class is a singleton, holding configuration parameters for HdEmbree.
Expand All @@ -27,45 +37,57 @@ PXR_NAMESPACE_OPEN_SCOPE
///
class HdEmbreeConfig {
public:

/// \brief Return the configuration singleton.
static const HdEmbreeConfig &GetInstance();

/// How many samples do we need before a pixel is considered
/// converged?
///
/// Override with *HDEMBREE_SAMPLES_TO_CONVERGENCE*.
unsigned int samplesToConvergence;
unsigned int samplesToConvergence = HdEmbreeDefaultSamplesToConvergence;

/// How many pixels are in an atomic unit of parallel work?
/// A work item is a square of size [tileSize x tileSize] pixels.
///
/// Override with *HDEMBREE_TILE_SIZE*.
unsigned int tileSize;
unsigned int tileSize = HdEmbreeDefaultTileSize;

/// How many ambient occlusion rays should we generate per
/// camera ray?
///
/// Override with *HDEMBREE_AMBIENT_OCCLUSION_SAMPLES*.
unsigned int ambientOcclusionSamples;
unsigned int ambientOcclusionSamples = HdEmbreeDefaultAmbientOcclusionSamples;

/// Should the renderpass jitter camera rays for antialiasing?
///
/// Override with *HDEMBREE_JITTER_CAMERA*. Integer values greater than
/// zero are considered "true".
bool jitterCamera;
/// Override with *HDEMBREE_JITTER_CAMERA*. The case-insensitive strings
/// "true", "yes", "on", and "1" are considered true; an empty value uses
/// the default, and all other values are false.
bool jitterCamera = HdEmbreeDefaultJitterCamera;

/// Should the renderpass use the color primvar, or flat white colors?
/// (Flat white shows off ambient occlusion better).
///
/// Override with *HDEMBREE_USE_FACE_COLORS*. Integer values greater than
/// zero are considered "true".
bool useFaceColors;
/// Override with *HDEMBREE_USE_FACE_COLORS*. The case-insensitive strings
/// "true", "yes", "on", and "1" are considered true; an empty value uses
/// the default, and all other values are false.
bool useFaceColors = HdEmbreeDefaultUseFaceColors;

/// What should the intensity of the camera light be, specified as a
/// percent of <1, 1, 1>. For example, 300 would be <3, 3, 3>.
///
/// Override with *HDEMBREE_CAMERA_LIGHT_INTENSITY*.
float cameraLightIntensity;
float cameraLightIntensity = HdEmbreeDefaultCameraLightIntensity;

/// Seed to give to the random number generator. A value of anything other
/// than -1, combined with setting PXR_WORK_THREAD_LIMIT=1, should give
/// deterministic / repeatable results. A value of -1 (the default) will
/// allow the implementation to set a value that varies from invocation to
/// invocation and thread to thread.
///
/// Override with *HDEMBREE_RANDOM_NUMBER_SEED*.
int randomNumberSeed = HdEmbreeDefaultRandomNumberSeed;

private:
// The constructor initializes the config variables with their
Expand Down
5 changes: 4 additions & 1 deletion pxr/imaging/plugin/hdEmbree/renderDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void
HdEmbreeRenderDelegate::_Initialize()
{
// Initialize the settings and settings descriptors.
_settingDescriptors.resize(4);
_settingDescriptors.resize(5);
_settingDescriptors[0] = { "Enable Scene Colors",
HdEmbreeRenderSettingsTokens->enableSceneColors,
VtValue(HdEmbreeConfig::GetInstance().useFaceColors) };
Expand All @@ -112,6 +112,9 @@ HdEmbreeRenderDelegate::_Initialize()
_settingDescriptors[3] = { "Samples To Convergence",
HdRenderSettingsTokens->convergedSamplesPerPixel,
VtValue(int(HdEmbreeConfig::GetInstance().samplesToConvergence)) };
_settingDescriptors[4] = { "Random Number Seed",
HdEmbreeRenderSettingsTokens->randomNumberSeed,
VtValue(HdEmbreeConfig::GetInstance().randomNumberSeed) };
_PopulateDefaultSettings(_settingDescriptors);

// Initialize the embree library handle (_rtcDevice).
Expand Down
3 changes: 2 additions & 1 deletion pxr/imaging/plugin/hdEmbree/renderDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class HdEmbreeRenderParam;
#define HDEMBREE_RENDER_SETTINGS_TOKENS \
(enableAmbientOcclusion) \
(enableSceneColors) \
(ambientOcclusionSamples)
(ambientOcclusionSamples) \
(randomNumberSeed)

// Also: HdRenderSettingsTokens->convergedSamplesPerPixel

Expand Down
4 changes: 4 additions & 0 deletions pxr/imaging/plugin/hdEmbree/renderPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ HdEmbreeRenderPass::_Execute(HdRenderPassStateSharedPtr const& renderPassState,
renderDelegate->GetRenderSetting<bool>(
HdEmbreeRenderSettingsTokens->enableSceneColors, true));

_renderer->SetRandomNumberSeed(
renderDelegate->GetRenderSetting<unsigned int>(
HdEmbreeRenderSettingsTokens->randomNumberSeed, (unsigned int)-1));

needStartRender = true;
}

Expand Down
20 changes: 16 additions & 4 deletions pxr/imaging/plugin/hdEmbree/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ HdEmbreeRenderer::SetEnableSceneColors(bool enableSceneColors)
_enableSceneColors = enableSceneColors;
}

void
HdEmbreeRenderer::SetRandomNumberSeed(int randomNumberSeed)
{
_randomNumberSeed = randomNumberSeed;
}

void
HdEmbreeRenderer::SetDataWindow(const GfRect2i &dataWindow)
{
Expand Down Expand Up @@ -432,8 +438,8 @@ HdEmbreeRenderer::Render(HdRenderThread *renderThread)
// Always pass the renderThread to _RenderTiles to allow the first frame
// to be interrupted.
WorkParallelForN(numTilesX*numTilesY,
std::bind(&HdEmbreeRenderer::_RenderTiles, this, renderThread,
std::placeholders::_1, std::placeholders::_2));
std::bind(&HdEmbreeRenderer::_RenderTiles, this,
renderThread, i, std::placeholders::_1, std::placeholders::_2));

// After the first pass, mark the single-sampled attachments as
// converged and unmap them. If there are no multisampled attachments,
Expand Down Expand Up @@ -472,7 +478,7 @@ HdEmbreeRenderer::Render(HdRenderThread *renderThread)
}

void
HdEmbreeRenderer::_RenderTiles(HdRenderThread *renderThread,
HdEmbreeRenderer::_RenderTiles(HdRenderThread *renderThread, int sampleNum,
size_t tileStart, size_t tileEnd)
{
const unsigned int minX = _dataWindow.GetMinX();
Expand All @@ -497,8 +503,14 @@ HdEmbreeRenderer::_RenderTiles(HdRenderThread *renderThread,

// Initialize the RNG for this tile (each tile creates one as
// a lazy way to do thread-local RNGs).
size_t seed = std::chrono::system_clock::now().time_since_epoch().count();
size_t seed;
if (_randomNumberSeed == -1) {
seed = std::chrono::system_clock::now().time_since_epoch().count();
} else {
seed = static_cast<size_t>(_randomNumberSeed);
}
seed = TfHash::Combine(seed, tileStart);
seed = TfHash::Combine(seed, sampleNum);
std::default_random_engine random(seed);

// Create a uniform distribution for jitter calculations.
Expand Down
10 changes: 9 additions & 1 deletion pxr/imaging/plugin/hdEmbree/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ class HdEmbreeRenderer final
/// everything as white.
void SetEnableSceneColors(bool enableSceneColors);

/// Sets a number to seed the random number generator with.
/// \param randomNumberSeed If -1, then the random number generator
/// is seeded in a non-deterministic way;
/// otherwise, it is seeded with this value.
void SetRandomNumberSeed(int randomNumberSeed);

/// Rendering entrypoint: add one sample per pixel to the whole sample
/// buffer, and then loop until the image is converged. After each pass,
/// the image will be resolved into a color buffer.
Expand Down Expand Up @@ -115,7 +121,7 @@ class HdEmbreeRenderer final
// work. For each tile, iterate over pixels in the tile, generating camera
// rays, and following them/calculating color with _TraceRay. This function
// renders all tiles between tileStart and tileEnd.
void _RenderTiles(HdRenderThread *renderThread,
void _RenderTiles(HdRenderThread *renderThread, int sampleNum,
size_t tileStart, size_t tileEnd);

// Cast a ray into the scene and if it hits an object, write to the bound
Expand Down Expand Up @@ -184,6 +190,8 @@ class HdEmbreeRenderer final
int _ambientOcclusionSamples;
// Should we enable scene colors?
bool _enableSceneColors;
// If other than -1, use this to seed the random number generator with.
int _randomNumberSeed;

// How many samples have been completed.
std::atomic<int> _completedSamples;
Expand Down

0 comments on commit 31e637a

Please sign in to comment.