...
 
Commits (5)
    https://gitcode.net/imjiangjun/pbrt-v4/-/commit/02f607852d623f1213c973d80c98a9a4132cc842 Fix comment 2023-05-10T10:26:42-07:00 Matt Pharr matt@pharr.org https://gitcode.net/imjiangjun/pbrt-v4/-/commit/b8a7238e24bcdde8105cbf6a48e40bf72d9e1c8f Polish up SampledGrid interface 2023-05-10T10:29:31-07:00 Matt Pharr matt@pharr.org Make capitalization consistent for the [XYZ]Size() methods. Add PBRT_CPU_GPU to those as well as to BytesAllocated(). https://gitcode.net/imjiangjun/pbrt-v4/-/commit/d4dc2008bf244105f6ec9104e467b2ee897933d5 Add temperature scale and offset controls to GridMedium 2023-05-10T10:36:07-07:00 Matt Pharr matt@pharr.org https://gitcode.net/imjiangjun/pbrt-v4/-/commit/d250ece5d530df30de9777e651201117650cb07d Add nanovdb2pbrt utility. 2023-05-12T05:30:54-07:00 Matt Pharr matt@pharr.org Basic converter from nanovdb to pbrt's text format for volumes, including support for downsampling. https://gitcode.net/imjiangjun/pbrt-v4/-/commit/c4baa534042e2ec4eb245924efbcef477e096389 Fix CHECK in imgtool 2023-05-12T05:31:38-07:00 Matt Pharr matt@pharr.org
...@@ -1004,6 +1004,23 @@ add_sanitizers (plytool) ...@@ -1004,6 +1004,23 @@ add_sanitizers (plytool)
set_property (TARGET plytool PROPERTY FOLDER "cmd") set_property (TARGET plytool PROPERTY FOLDER "cmd")
######################
# nanovdb2pbrt
add_executable (nanovdb2pbrt src/pbrt/cmd/nanovdb2pbrt.cpp)
add_executable (pbrt::nanovdb2pbrt ALIAS nanovdb2pbrt)
target_compile_definitions (nanovdb2pbrt PRIVATE ${PBRT_DEFINITIONS})
target_compile_options (nanovdb2pbrt PUBLIC ${PBRT_CXX_FLAGS})
target_include_directories (nanovdb2pbrt PUBLIC src src/ext)
target_link_libraries (nanovdb2pbrt PRIVATE ${ALL_PBRT_LIBS} pbrt_warnings pbrt_opt)
set_target_properties (nanovdb2pbrt PROPERTIES OUTPUT_NAME nanovdb2pbrt)
add_sanitizers (nanovdb2pbrt)
set_property (TARGET nanovdb2pbrt PROPERTY FOLDER "cmd")
###################### ######################
# cyhair2pbrt # cyhair2pbrt
......
...@@ -646,7 +646,7 @@ int splitn(std::vector<std::string> args) { ...@@ -646,7 +646,7 @@ int splitn(std::vector<std::string> args) {
result.SetChannels({x, y}, desc, {rgb.r, rgb.g, rgb.b}); result.SetChannels({x, y}, desc, {rgb.r, rgb.g, rgb.b});
}; };
CHECK_LT(crops.size(), sizeof(edges) / sizeof(edges[0])); CHECK_LE(crops.size(), sizeof(edges) / sizeof(edges[0]));
ImageChannelDesc cropDesc = cropsImage.GetChannelDesc({"R", "G", "B"}); ImageChannelDesc cropDesc = cropsImage.GetChannelDesc({"R", "G", "B"});
CHECK(bool(cropDesc)); CHECK(bool(cropDesc));
......
// nanovdb2pbrt.cpp
// pbrt is Copyright(c) 1998-2023 Matt Pharr, Wenzel Jakob, and Greg Humphreys.
// The pbrt source code is licensed under the Apache License, Version 2.0.
// SPDX: Apache-2.0
#include <pbrt/pbrt.h>
#include <pbrt/media.h>
#include <pbrt/util/args.h>
#include <nanovdb/NanoVDB.h>
#define NANOVDB_USE_ZIP 1
#include <nanovdb/util/IO.h>
#include <nanovdb/util/GridHandle.h>
#include <nanovdb/util/SampleFromVoxels.h>
#include <stdio.h>
#include <vector>
using namespace pbrt;
template <typename Buffer>
static nanovdb::GridHandle<Buffer> readGrid(const std::string &filename,
const std::string &gridName,
Allocator alloc) {
NanoVDBBuffer buf(alloc);
nanovdb::GridHandle<Buffer> grid;
try {
grid =
nanovdb::io::readGrid<Buffer>(filename, gridName, 0 /* not verbose */, buf);
} catch (const std::exception &e) {
ErrorExit("nanovdb: %s: %s", filename, e.what());
}
if (grid) {
if (!grid.gridMetaData()->isFogVolume() && !grid.gridMetaData()->isUnknown())
ErrorExit("%s: \"%s\" isn't a FogVolume grid?", filename, gridName);
LOG_VERBOSE("%s: found %d \"%s\" voxels", filename,
grid.gridMetaData()->activeVoxelCount(), gridName);
}
return grid;
}
static void usage(const std::string &msg = {}) {
if (!msg.empty())
fprintf(stderr, "nanovdb2pbrt: %s\n\n", msg.c_str());
fprintf(stderr,
R"(usage: nanovdb2pbrt [<options>] <filename.nvdb>
Options:
--downsample <n> Number of times to 2x downsample the volume.
Default: 0
--grid <name> Name of grid to extract. Default: "density"
)");
exit(msg.empty() ? 0 : 1);
}
int main(int argc, char *argv[]) {
std::vector<std::string> args = GetCommandLineArguments(argv);
auto onError = [](const std::string &err) {
usage(err);
exit(1);
};
std::string filename;
std::string grid = "density";
int downsample = 0;
for (auto iter = args.begin(); iter != args.end(); ++iter) {
if ((*iter)[0] != '-') {
if (filename.empty())
filename = *iter;
else {
usage();
exit(1);
}
} else if (ParseArg(&iter, args.end(), "downsample", &downsample, onError) ||
ParseArg(&iter, args.end(), "grid", &grid, onError)) {
// success
} else {
usage();
exit(1);
}
}
if (filename.empty())
usage("must specify a nanovdb filename");
Allocator alloc;
nanovdb::GridHandle<NanoVDBBuffer> nanoGrid =
readGrid<NanoVDBBuffer>(filename, grid, alloc);
if (!nanoGrid)
ErrorExit("%s: didn't find \"%s\" grid.", filename, grid);
const nanovdb::FloatGrid *floatGrid = nanoGrid.grid<float>();
nanovdb::BBox<nanovdb::Vec3R> bbox = floatGrid->worldBBox();
Bounds3f bounds(Point3f(bbox.min()[0], bbox.min()[1], bbox.min()[2]),
Point3f(bbox.max()[0], bbox.max()[1], bbox.max()[2]));
int nx = floatGrid->indexBBox().dim()[0];
int ny = floatGrid->indexBBox().dim()[1];
int nz = floatGrid->indexBBox().dim()[2];
std::vector<Float> values;
int z0 = 0, z1 = nz;
int y0 = 0, y1 = ny;
int x0 = 0, x1 = nx;
// Fix the resolution to be a multiple of 2^downsample just to make
// downsampling easy. Chop off one at a time from the bottom and top
// of the range until we get there; the bounding box is updated as
// well so that the remaining volume doesn't shift spatially.
auto round = [=](int &low, int &high, Float &c0, Float &c1) {
Float delta = (c1-c0) / (high-low);
int mult = 1 << downsample; // want a multiple of this in resolution
while ((high - low) % mult) {
++low;
c0 += delta;
if ((high - low) % mult) {
--high;
c1 -= delta;
}
}
return high - low;
};
nz = round(z0, z1, bounds.pMin.z, bounds.pMax.z);
ny = round(y0, y1, bounds.pMin.y, bounds.pMax.y);
nx = round(x0, x1, bounds.pMin.x, bounds.pMax.x);
for (int z = z0; z < z1; ++z)
for (int y = y0; y < y1; ++y)
for (int x = x0; x < x1; ++x) {
values.push_back(floatGrid->tree().getValue({x, y, z}));
}
while (downsample > 0) {
std::vector<Float> v2;
for (int z = 0; z < nz/2; ++z)
for (int y = 0; y < ny/2; ++y)
for (int x = 0; x < nx/2; ++x) {
auto v = [&](int dx, int dy, int dz) -> Float{
return values[(2*x+dx) + nx * ((2*y+dy) + ny * (2*z+dz))];
};
v2.push_back((v(0,0,0) + v(1,0,0) + v(0,1,0) + v(1,1,0) +
v(0,0,1) + v(1,0,1) + v(0,1,1) + v(1,1,1))/8);
}
values = std::move(v2);
nx /= 2;
ny /= 2;
nz /= 2;
--downsample;
}
printf("\"integer nx\" %d \"integer ny\" %d \"integer nz\" %d\n", nx, ny, nz);
printf("\t\"point3 p0\" [ %f %f %f ] \"point3 p1\" [ %f %f %f ]\n",
bounds.pMin.x, bounds.pMin.y, bounds.pMin.z,
bounds.pMax.x, bounds.pMax.y, bounds.pMax.z);
printf("\t\"float %s\" [\n", grid.c_str());
for (int i = 0; i < values.size(); ++i) {
Float d = values[i];
if (d == 0) printf("0 ");
else printf("%f ", d);
if ((i % 20) == 19) printf("\n");
}
printf("]\n");
}
...@@ -367,7 +367,7 @@ CoatedConductorBxDF CoatedConductorMaterial::GetBxDF(TextureEvaluator texEval, ...@@ -367,7 +367,7 @@ CoatedConductorBxDF CoatedConductorMaterial::GetBxDF(TextureEvaluator texEval,
ce = texEval(conductorEta, ctx, lambda); ce = texEval(conductorEta, ctx, lambda);
ck = texEval(k, ctx, lambda); ck = texEval(k, ctx, lambda);
} else { } else {
// Avoid r==0 NaN case... // Avoid r==1 NaN case...
SampledSpectrum r = Clamp(texEval(reflectance, ctx, lambda), 0, .9999); SampledSpectrum r = Clamp(texEval(reflectance, ctx, lambda), 0, .9999);
ce = SampledSpectrum(1.f); ce = SampledSpectrum(1.f);
ck = 2 * Sqrt(r) / Sqrt(ClampZero(SampledSpectrum(1) - r)); ck = 2 * Sqrt(r) / Sqrt(ClampZero(SampledSpectrum(1) - r));
......
...@@ -212,8 +212,9 @@ STAT_MEMORY_COUNTER("Memory/Volume grids", volumeGridBytes); ...@@ -212,8 +212,9 @@ STAT_MEMORY_COUNTER("Memory/Volume grids", volumeGridBytes);
GridMedium::GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium, GridMedium::GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium,
Spectrum sigma_a, Spectrum sigma_s, Float sigmaScale, Float g, Spectrum sigma_a, Spectrum sigma_s, Float sigmaScale, Float g,
SampledGrid<Float> d, SampledGrid<Float> d,
pstd::optional<SampledGrid<Float>> temperature, Spectrum Le, pstd::optional<SampledGrid<Float>> temperature,
SampledGrid<Float> LeGrid, Allocator alloc) Float temperatureScale, Float temperatureOffset,
Spectrum Le, SampledGrid<Float> LeGrid, Allocator alloc)
: bounds(bounds), : bounds(bounds),
renderFromMedium(renderFromMedium), renderFromMedium(renderFromMedium),
sigma_a_spec(sigma_a, alloc), sigma_a_spec(sigma_a, alloc),
...@@ -221,6 +222,8 @@ GridMedium::GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium ...@@ -221,6 +222,8 @@ GridMedium::GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium
densityGrid(std::move(d)), densityGrid(std::move(d)),
phase(g), phase(g),
temperatureGrid(std::move(temperature)), temperatureGrid(std::move(temperature)),
temperatureScale(temperatureScale),
temperatureOffset(temperatureOffset),
Le_spec(Le, alloc), Le_spec(Le, alloc),
LeScale(std::move(LeGrid)), LeScale(std::move(LeGrid)),
majorantGrid(bounds, {16, 16, 16}, alloc) { majorantGrid(bounds, {16, 16, 16}, alloc) {
...@@ -316,9 +319,14 @@ GridMedium *GridMedium::Create(const ParameterDictionary &parameters, ...@@ -316,9 +319,14 @@ GridMedium *GridMedium::Create(const ParameterDictionary &parameters,
sigma_s = alloc.new_object<ConstantSpectrum>(1.f); sigma_s = alloc.new_object<ConstantSpectrum>(1.f);
Float sigmaScale = parameters.GetOneFloat("scale", 1.f); Float sigmaScale = parameters.GetOneFloat("scale", 1.f);
Float temperatureOffset = parameters.GetOneFloat("temperatureoffset",
parameters.GetOneFloat("temperaturecutoff", 0.f));
Float temperatureScale = parameters.GetOneFloat("temperaturescale", 1.f);
return alloc.new_object<GridMedium>( return alloc.new_object<GridMedium>(
Bounds3f(p0, p1), renderFromMedium, sigma_a, sigma_s, sigmaScale, g, Bounds3f(p0, p1), renderFromMedium, sigma_a, sigma_s, sigmaScale, g,
std::move(densityGrid), std::move(temperatureGrid), Le, std::move(LeGrid), alloc); std::move(densityGrid), std::move(temperatureGrid), temperatureScale,
temperatureOffset, Le, std::move(LeGrid), alloc);
} }
std::string GridMedium::ToString() const { std::string GridMedium::ToString() const {
......
...@@ -271,6 +271,7 @@ class GridMedium { ...@@ -271,6 +271,7 @@ class GridMedium {
GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium, GridMedium(const Bounds3f &bounds, const Transform &renderFromMedium,
Spectrum sigma_a, Spectrum sigma_s, Float sigmaScale, Float g, Spectrum sigma_a, Spectrum sigma_s, Float sigmaScale, Float g,
SampledGrid<Float> density, pstd::optional<SampledGrid<Float>> temperature, SampledGrid<Float> density, pstd::optional<SampledGrid<Float>> temperature,
Float temperatureScale, Float temperatureOffset,
Spectrum Le, SampledGrid<Float> LeScale, Allocator alloc); Spectrum Le, SampledGrid<Float> LeScale, Allocator alloc);
static GridMedium *Create(const ParameterDictionary &parameters, static GridMedium *Create(const ParameterDictionary &parameters,
...@@ -303,7 +304,12 @@ class GridMedium { ...@@ -303,7 +304,12 @@ class GridMedium {
// Compute emitted radiance using _temperatureGrid_ or _Le_spec_ // Compute emitted radiance using _temperatureGrid_ or _Le_spec_
if (temperatureGrid) { if (temperatureGrid) {
Float temp = temperatureGrid->Lookup(p); Float temp = temperatureGrid->Lookup(p);
Le = scale * BlackbodySpectrum(temp).Sample(lambda); // Added after book publication: optionally offset and scale
// temperature based on user-supplied parameters. (Match
// NanoVDBMedium functionality.)
temp = (temp - temperatureOffset) * temperatureScale;
if (temp > 100.f)
Le = scale * BlackbodySpectrum(temp).Sample(lambda);
} else } else
Le = scale * Le_spec.Sample(lambda); Le = scale * Le_spec.Sample(lambda);
} }
...@@ -341,6 +347,7 @@ class GridMedium { ...@@ -341,6 +347,7 @@ class GridMedium {
DenselySampledSpectrum Le_spec; DenselySampledSpectrum Le_spec;
SampledGrid<Float> LeScale; SampledGrid<Float> LeScale;
bool isEmissive; bool isEmissive;
Float temperatureScale, temperatureOffset;
MajorantGrid majorantGrid; MajorantGrid majorantGrid;
}; };
......
...@@ -773,10 +773,10 @@ class SampledGrid { ...@@ -773,10 +773,10 @@ class SampledGrid {
CHECK_EQ(nx * ny * nz, values.size()); CHECK_EQ(nx * ny * nz, values.size());
} }
size_t BytesAllocated() const { return values.size() * sizeof(T); } PBRT_CPU_GPU size_t BytesAllocated() const { return values.size() * sizeof(T); }
int XSize() const { return nx; } PBRT_CPU_GPU int XSize() const { return nx; }
int YSize() const { return ny; } PBRT_CPU_GPU int YSize() const { return ny; }
int zSize() const { return nz; } PBRT_CPU_GPU int ZSize() const { return nz; }
const_iterator begin() const { return values.begin(); } const_iterator begin() const { return values.begin(); }
const_iterator end() const { return values.end(); } const_iterator end() const { return values.end(); }
......