Commit 2fb7fe5a authored by Jan Scheffczyk's avatar Jan Scheffczyk

qMerge branch 'master' of https://github.com/mmp/pbrt-v3

parents 3172d8e6 9d36d8df
......@@ -7,3 +7,6 @@
[submodule "src/ext/glog"]
path = src/ext/glog
url = https://github.com/google/glog.git
[submodule "src/ext/ptex"]
path = src/ext/ptex
url = https://github.com/wdas/ptex.git
......@@ -5,7 +5,6 @@ install:
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo apt-get update
- sudo apt-get install -yq build-essential gcc-4.8 g++-4.8 make bison flex libpthread-stubs0-dev
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-4.6
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
- echo 2 | sudo update-alternatives --config gcc
- |
......
This diff is collapsed.
......@@ -4,29 +4,31 @@ branches:
- master
- book
os:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017
configuration: Release
platform: x64
clone_folder: c:\pbrt-v3
install:
# os detection
- ps: if ($env:VS140COMNTOOLS -gt 0) { $env:VS_VER = 14 } else { $env:VS_VER = 12 }
- echo %VS_VER%
- set PATH=C:\Program Files (x86)\MSBuild\%VS_VER%.0\Bin;%PATH%
- echo %PATH%
- git submodule update --init --recursive
# os detection
- ps: if ($env:VS140COMNTOOLS -gt 0) { $env:VS_VER = 14 } else { $env:VS_VER = 12 }
- echo %VS_VER%
- set PATH=C:\Program Files (x86)\MSBuild\%VS_VER%.0\Bin;%PATH%
- echo %PATH%
- git submodule update --init --recursive
before_build:
- md c:\pbrt-v3\build
- cd c:\pbrt-v3\build
- set WIN32=1
- ps: if ($env:VS_VER -eq 14) {cmake -G "Visual Studio 14 2015 Win64" ..} else {cmake -G "Visual Studio 12 2013 Win64" ..}
- md c:\pbrt-v3\build
- cd c:\pbrt-v3\build
- set WIN32=1
- ps: if ($env:VS_VER -eq 14) {cmake -G "Visual Studio 14 2015 Win64" ..} else {cmake -G "Visual Studio 12 2013 Win64" ..}
build:
project: c:\pbrt-v3\build\pbrt-v3.sln
parallel: true
verbosity: normal
build_script:
- msbuild c:\pbrt-v3\build\pbrt-v3.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
- msbuild c:\pbrt-v3\build\pbrt-v3.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
after_build:
- cd c:\pbrt-v3\build\Release
- pbrt_test.exe
- cd c:\pbrt-v3\build\Release
- pbrt_test.exe
......@@ -40,6 +40,7 @@
#include "reflection.h"
#include "stats.h"
#include "lowdiscrepancy.h"
#include <array>
namespace pbrt {
......@@ -103,9 +104,13 @@ bool RealisticCamera::TraceLensesFromFilm(const Ray &rCamera, Ray *rOut) const {
Float t;
Normal3f n;
bool isStop = (element.curvatureRadius == 0);
if (isStop)
if (isStop) {
// The refracted ray computed in the previous lens element
// interface may be pointed towards film plane(+z) in some
// extreme situations; in such cases, 't' becomes negative.
if (rLens.d.z >= 0.0) return false;
t = (elementZ - rLens.o.z) / rLens.d.z;
else {
} else {
Float radius = element.curvatureRadius;
Float zCenter = elementZ + element.curvatureRadius;
if (!IntersectSphericalElement(radius, zCenter, rLens, &t, &n))
......@@ -452,7 +457,7 @@ Float RealisticCamera::FocusThickLens(Float focusDistance) {
// Compute translation of lens, _delta_, to focus at _focusDistance_
Float f = fz[0] - pz[0];
Float z = -focusDistance;
Float c = (pz[1] - z - pz[0]) * (pz[1] - z * 4 * f - pz[0]);
Float c = (pz[1] - z - pz[0]) * (pz[1] - z - 4 * f - pz[0]);
CHECK_GT(c, 0) << "Coefficient must be positive. It looks focusDistance: " << focusDistance << " is too short for a given lenses configuration";
Float delta =
0.5f * (pz[1] - z + pz[0] - std::sqrt(c));
......@@ -483,11 +488,27 @@ Float RealisticCamera::FocusBinarySearch(Float focusDistance) {
Float RealisticCamera::FocusDistance(Float filmDistance) {
// Find offset ray from film center through lens
Bounds2f bounds = BoundExitPupil(0, .001 * film->diagonal);
Float lu = 0.1f * bounds.pMax[0];
const std::array<Float, 3> scaleFactors = {0.1f, 0.01f, 0.001f};
Float lu = 0.0f;
Ray ray;
if (!TraceLensesFromFilm(Ray(Point3f(0, 0, LensRearZ() - filmDistance),
Vector3f(lu, 0, filmDistance)),
&ray)) {
// Try some different and decreasing scaling factor to find focus ray
// more quickly when `aperturediameter` is too small.
// (e.g. 2 [mm] for `aperturediameter` with wide.22mm.dat),
bool foundFocusRay = false;
for (Float scale : scaleFactors) {
lu = scale * bounds.pMax[0];
if (TraceLensesFromFilm(Ray(Point3f(0, 0, LensRearZ() - filmDistance),
Vector3f(lu, 0, filmDistance)),
&ray)) {
foundFocusRay = true;
break;
}
}
if (!foundFocusRay) {
Error(
"Focus ray at lens pos(%f,0) didn't make it through the lenses "
"with film distance %f?!??\n",
......@@ -502,6 +523,7 @@ Float RealisticCamera::FocusDistance(Float filmDistance) {
return zFocus;
}
Bounds2f RealisticCamera::BoundExitPupil(Float pFilmX0, Float pFilmX1) const {
Bounds2f pupilBounds;
// Sample a collection of points on the rear lens to find exit pupil
......
......@@ -67,6 +67,7 @@
#include "lights/point.h"
#include "lights/projection.h"
#include "lights/spot.h"
#include "materials/disney.h"
#include "materials/fourier.h"
#include "materials/glass.h"
#include "materials/hair.h"
......@@ -106,6 +107,7 @@
#include "textures/imagemap.h"
#include "textures/marble.h"
#include "textures/mix.h"
#include "textures/ptex.h"
#include "textures/scale.h"
#include "textures/uv.h"
#include "textures/windy.h"
......@@ -423,6 +425,8 @@ std::shared_ptr<Material> MakeMaterial(const std::string &name,
material = CreateMirrorMaterial(mp);
else if (name == "hair")
material = CreateHairMaterial(mp);
else if (name == "disney")
material = CreateDisneyMaterial(mp);
else if (name == "mix") {
std::string m1 = mp.FindString("namedmaterial1", "");
std::string m2 = mp.FindString("namedmaterial2", "");
......@@ -500,6 +504,8 @@ std::shared_ptr<Texture<Float>> MakeFloatTexture(const std::string &name,
tex = CreateMarbleFloatTexture(tex2world, tp);
else if (name == "windy")
tex = CreateWindyFloatTexture(tex2world, tp);
else if (name == "ptex")
tex = CreatePtexFloatTexture(tex2world, tp);
else
Warning("Float texture \"%s\" unknown.", name.c_str());
tp.ReportUnused();
......@@ -534,6 +540,8 @@ std::shared_ptr<Texture<Spectrum>> MakeSpectrumTexture(
tex = CreateMarbleSpectrumTexture(tex2world, tp);
else if (name == "windy")
tex = CreateWindySpectrumTexture(tex2world, tp);
else if (name == "ptex")
tex = CreatePtexSpectrumTexture(tex2world, tp);
else
Warning("Spectrum texture \"%s\" unknown.", name.c_str());
tp.ReportUnused();
......@@ -1385,6 +1393,19 @@ void pbrtWorldEnd() {
if (scene && integrator) integrator->Render(*scene);
CHECK_EQ(CurrentProfilerState(), ProfToBits(Prof::IntegratorRender));
ProfilerState = ProfToBits(Prof::SceneConstruction);
}
// Clean up after rendering. Do this before reporting stats so that
// destructors can run and update stats as needed.
graphicsState = GraphicsState();
transformCache.Clear();
currentApiState = APIState::OptionsBlock;
ImageTexture<Float, Float>::ClearCache();
ImageTexture<RGBSpectrum, Spectrum>::ClearCache();
if (!PbrtOptions.cat && !PbrtOptions.toPly) {
MergeWorkerThreadStats();
ReportThreadStats();
if (!PbrtOptions.quiet) {
......@@ -1393,22 +1414,12 @@ void pbrtWorldEnd() {
ClearStats();
ClearProfiler();
}
CHECK_EQ(CurrentProfilerState(), ProfToBits(Prof::IntegratorRender));
ProfilerState = ProfToBits(Prof::SceneConstruction);
}
// Clean up after rendering
graphicsState = GraphicsState();
transformCache.Clear();
currentApiState = APIState::OptionsBlock;
for (int i = 0; i < MaxTransforms; ++i) curTransform[i] = Transform();
activeTransformBits = AllTransformsBits;
namedCoordinateSystems.erase(namedCoordinateSystems.begin(),
namedCoordinateSystems.end());
ImageTexture<Float, Float>::ClearCache();
ImageTexture<RGBSpectrum, Spectrum>::ClearCache();
}
Scene *RenderOptions::MakeScene() {
......
......@@ -1272,12 +1272,14 @@ Bounds3<T> Union(const Bounds3<T> &b1, const Bounds3<T> &b2) {
template <typename T>
Bounds3<T> Intersect(const Bounds3<T> &b1, const Bounds3<T> &b2) {
return Bounds3<T>(Point3<T>(std::max(b1.pMin.x, b2.pMin.x),
std::max(b1.pMin.y, b2.pMin.y),
std::max(b1.pMin.z, b2.pMin.z)),
Point3<T>(std::min(b1.pMax.x, b2.pMax.x),
std::min(b1.pMax.y, b2.pMax.y),
std::min(b1.pMax.z, b2.pMax.z)));
// Important: assign to pMin/pMax directly and don't run the Bounds2()
// constructor, since it takes min/max of the points passed to it. In
// turn, that breaks returning an invalid bound for the case where we
// intersect non-overlapping bounds (as we'd like to happen).
Bounds3<T> ret;
ret.pMin = Max(b1.pMin, b2.pMin);
ret.pMax = Min(b1.pMax, b2.pMax);
return ret;
}
template <typename T>
......@@ -1354,11 +1356,14 @@ Bounds2<T> Union(const Bounds2<T> &b, const Bounds2<T> &b2) {
}
template <typename T>
Bounds2<T> Intersect(const Bounds2<T> &b, const Bounds2<T> &b2) {
Bounds2<T> ret(
Point2<T>(std::max(b.pMin.x, b2.pMin.x), std::max(b.pMin.y, b2.pMin.y)),
Point2<T>(std::min(b.pMax.x, b2.pMax.x),
std::min(b.pMax.y, b2.pMax.y)));
Bounds2<T> Intersect(const Bounds2<T> &b1, const Bounds2<T> &b2) {
// Important: assign to pMin/pMax directly and don't run the Bounds2()
// constructor, since it takes min/max of the points passed to it. In
// turn, that breaks returning an invalid bound for the case where we
// intersect non-overlapping bounds (as we'd like to happen).
Bounds2<T> ret;
ret.pMin = Max(b1.pMin, b2.pMin);
ret.pMax = Min(b1.pMax, b2.pMax);
return ret;
}
......
......@@ -270,8 +270,8 @@ static RGBSpectrum *ReadImagePNG(const std::string &name, int *width,
RGBSpectrum *ret = new RGBSpectrum[*width * *height];
unsigned char *src = rgb;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x, src += 3) {
for (unsigned int y = 0; y < h; ++y) {
for (unsigned int x = 0; x < w; ++x, src += 3) {
Float c[3];
c[0] = src[0] / 255.f;
c[1] = src[1] / 255.f;
......
......@@ -44,7 +44,8 @@ namespace pbrt {
SurfaceInteraction::SurfaceInteraction(
const Point3f &p, const Vector3f &pError, const Point2f &uv,
const Vector3f &wo, const Vector3f &dpdu, const Vector3f &dpdv,
const Normal3f &dndu, const Normal3f &dndv, Float time, const Shape *shape)
const Normal3f &dndu, const Normal3f &dndv, Float time, const Shape *shape,
int faceIndex)
: Interaction(p, Normal3f(Normalize(Cross(dpdu, dpdv))), pError, wo, time,
nullptr),
uv(uv),
......@@ -52,7 +53,8 @@ SurfaceInteraction::SurfaceInteraction(
dpdv(dpdv),
dndu(dndu),
dndv(dndv),
shape(shape) {
shape(shape),
faceIndex(faceIndex) {
// Initialize shading geometry from true geometry
shading.n = n;
shading.dpdu = dpdu;
......
......@@ -122,7 +122,8 @@ class SurfaceInteraction : public Interaction {
const Point2f &uv, const Vector3f &wo,
const Vector3f &dpdu, const Vector3f &dpdv,
const Normal3f &dndu, const Normal3f &dndv, Float time,
const Shape *sh);
const Shape *sh,
int faceIndex = 0);
void SetShadingGeometry(const Vector3f &dpdu, const Vector3f &dpdv,
const Normal3f &dndu, const Normal3f &dndv,
bool orientationIsAuthoritative);
......@@ -148,6 +149,11 @@ class SurfaceInteraction : public Interaction {
BSSRDF *bssrdf = nullptr;
mutable Vector3f dpdx, dpdy;
mutable Float dudx = 0, dvdx = 0, dudy = 0, dvdy = 0;
// Added after book publication. Shapes can optionally provide a face
// index with an intersection point for use in Ptex texture lookups.
// If Ptex isn't being used, then this value is ignored.
int faceIndex = 0;
};
} // namespace pbrt
......
......@@ -66,7 +66,7 @@ std::unique_ptr<LightDistribution> CreateLightSampleDistribution(
UniformLightDistribution::UniformLightDistribution(const Scene &scene) {
std::vector<Float> prob(scene.lights.size(), Float(1));
distrib.reset(new Distribution1D(&prob[0], prob.size()));
distrib.reset(new Distribution1D(&prob[0], int(prob.size())));
}
const Distribution1D *UniformLightDistribution::Lookup(const Point3f &p) const {
......@@ -295,7 +295,7 @@ SpatialLightDistribution::ComputeDistribution(Point3i pi) const {
", avgContrib = " << avgContrib;
// Compute a sampling distribution from the accumulated contributions.
return new Distribution1D(&lightContrib[0], lightContrib.size());
return new Distribution1D(&lightContrib[0], int(lightContrib.size()));
}
} // namespace pbrt
......@@ -387,12 +387,7 @@ uint32_t CMaxMinDist[17][32] = {
// Low Discrepancy Static Functions
template <int base>
#if defined(PBRT_IS_MSVC)
__declspec(noinline)
#else
__attribute__ ((noinline))
#endif
static Float RadicalInverseSpecialized(uint64_t a) {
PBRT_NOINLINE static Float RadicalInverseSpecialized(uint64_t a) {
const Float invBase = (Float)1 / (Float)base;
uint64_t reversedDigits = 0;
Float invBaseN = 1;
......@@ -408,12 +403,7 @@ static Float RadicalInverseSpecialized(uint64_t a) {
}
template <int base>
#if defined(PBRT_IS_MSVC)
__declspec(noinline)
#else
__attribute__((noinline))
#endif
static Float
PBRT_NOINLINE static Float
ScrambledRadicalInverseSpecialized(const uint16_t *perm, uint64_t a) {
const Float invBase = (Float)1 / (Float)base;
uint64_t reversedDigits = 0;
......
......@@ -38,9 +38,9 @@ namespace pbrt {
// Memory Allocation Functions
void *AllocAligned(size_t size) {
#if defined(PBRT_IS_WINDOWS)
#if defined(PBRT_HAVE__ALIGNED_MALLOC)
return _aligned_malloc(size, PBRT_L1_CACHE_LINE_SIZE);
#elif defined(PBRT_IS_OPENBSD) || defined(PBRT_IS_OSX) || defined(PBRT_IS_FREEBSD)
#elif defined(PBRT_HAVE_POSIX_MEMALIGN)
void *ptr;
if (posix_memalign(&ptr, PBRT_L1_CACHE_LINE_SIZE, size) != 0) ptr = nullptr;
return ptr;
......@@ -51,7 +51,7 @@ void *AllocAligned(size_t size) {
void FreeAligned(void *ptr) {
if (!ptr) return;
#if defined(PBRT_IS_WINDOWS)
#if defined(PBRT_HAVE__ALIGNED_MALLOC)
_aligned_free(ptr);
#else
free(ptr);
......
......@@ -40,8 +40,8 @@
// core/memory.h*
#include "pbrt.h"
#include "port.h"
#include <list>
#include <cstddef>
namespace pbrt {
......@@ -69,7 +69,18 @@ alignas(PBRT_L1_CACHE_LINE_SIZE)
}
void *Alloc(size_t nBytes) {
// Round up _nBytes_ to minimum machine alignment
nBytes = ((nBytes + 15) & (~15));
#if __GNUC__ == 4 && __GNUC_MINOR__ < 9
// gcc bug: max_align_t wasn't in std:: until 4.9.0
const int align = alignof(::max_align_t);
#elif !defined(PBRT_HAVE_ALIGNOF)
const int align = 16;
#else
const int align = alignof(std::max_align_t);
#endif
#ifdef PBRT_HAVE_CONSTEXPR
static_assert(IsPowerOf2(align), "Minimum alignment not a power of two");
#endif
nBytes = (nBytes + align - 1) & ~(align - 1);
if (currentBlockPos + nBytes > currentAllocSize) {
// Add current block to _usedBlocks_ list
if (currentBlock) {
......
......@@ -201,15 +201,15 @@ Vector3f BeckmannDistribution::Sample_wh(const Vector3f &wo,
// Compute $\tan^2 \theta$ and $\phi$ for Beckmann distribution sample
Float tan2Theta, phi;
if (alphax == alphay) {
Float logSample = std::log(u[0]);
if (std::isinf(logSample)) logSample = 0;
Float logSample = std::log(1 - u[0]);
DCHECK(!std::isinf(logSample));
tan2Theta = -alphax * alphax * logSample;
phi = u[1] * 2 * Pi;
} else {
// Compute _tan2Theta_ and _phi_ for anisotropic Beckmann
// distribution
Float logSample = std::log(u[0]);
if (std::isinf(logSample)) logSample = 0;
Float logSample = std::log(1 - u[0]);
DCHECK(!std::isinf(logSample));
phi = std::atan(alphay / alphax *
std::tan(2 * Pi * u[1] + 0.5f * Pi));
if (u[1] > 0.5f) phi += Pi;
......
......@@ -55,7 +55,7 @@ class MicrofacetDistribution {
// if (Dot(w, wh) * CosTheta(w) < 0.) return 0.;
return 1 / (1 + Lambda(w));
}
Float G(const Vector3f &wo, const Vector3f &wi) const {
virtual Float G(const Vector3f &wo, const Vector3f &wi) const {
return 1 / (1 + Lambda(wo) + Lambda(wi));
}
virtual Vector3f Sample_wh(const Vector3f &wo, const Point2f &u) const = 0;
......
......@@ -39,8 +39,6 @@
#define PBRT_CORE_PBRT_H
// core/pbrt.h*
#include "port.h"
// Global Include Files
#include <type_traits>
#include <algorithm>
......@@ -63,6 +61,21 @@
#include <glog/logging.h>
// Platform-specific definitions
#if defined(_WIN32) || defined(_WIN64)
#define PBRT_IS_WINDOWS
#endif
#if defined(_MSC_VER)
#define PBRT_IS_MSVC
#if _MSC_VER == 1800
#define snprintf _snprintf
#endif
#endif
#ifndef PBRT_L1_CACHE_LINE_SIZE
#define PBRT_L1_CACHE_LINE_SIZE 64
#endif
#include <stdint.h>
#if defined(PBRT_IS_MSVC)
#include <float.h>
......
......@@ -67,10 +67,10 @@ struct Distribution1D {
for (int i = 1; i < n + 1; ++i) cdf[i] /= funcInt;
}
}
int Count() const { return func.size(); }
int Count() const { return (int)func.size(); }
Float SampleContinuous(Float u, Float *pdf, int *off = nullptr) const {
// Find surrounding CDF segments and _offset_
int offset = FindInterval(cdf.size(),
int offset = FindInterval((int)cdf.size(),
[&](int index) { return cdf[index] <= u; });
if (off) *off = offset;
// Compute offset along CDF segment
......@@ -90,7 +90,7 @@ struct Distribution1D {
int SampleDiscrete(Float u, Float *pdf = nullptr,
Float *uRemapped = nullptr) const {
// Find surrounding CDF segments and _offset_
int offset = FindInterval(cdf.size(),
int offset = FindInterval((int)cdf.size(),
[&](int index) { return cdf[index] <= u; });
if (pdf) *pdf = (funcInt > 0) ? func[offset] / (funcInt * Count()) : 0;
if (uRemapped)
......
......@@ -181,6 +181,7 @@ enum class Prof {
GetSample,
TexFiltTrilerp,
TexFiltEWA,
TexFiltPtex,
NumProfCategories
};
......@@ -235,6 +236,7 @@ static const char *ProfNames[] = {
"Sampler::GetSample[12]D()",
"MIPMap::Lookup() (trilinear)",
"MIPMap::Lookup() (EWA)",
"Ptex lookup",
};
static_assert((int)Prof::NumProfCategories ==
......@@ -289,8 +291,7 @@ void CleanupProfiler();
} \
static StatRegisterer STATS_REG##var(STATS_FUNC##var)
// Work around lack of support for constexpr in VS2013.
#ifdef PBRT_IS_MSVC2013
#ifndef PBRT_HAVE_CONSTEXPR
#define STATS_INT64_T_MIN LLONG_MAX
#define STATS_INT64_T_MAX _I64_MIN
#define STATS_DBL_T_MIN DBL_MAX
......
Subproject commit 59eac370e52af48a3f4dab77a60f91523c3e70ac
......@@ -156,11 +156,11 @@ struct Vertex {
// Vertex Public Data
VertexType type;
Spectrum beta;
#ifdef PBRT_IS_MSVC2013
struct {
#else
#ifdef PBRT_HAVE_NONPOD_IN_UNIONS
union {
#endif // PBRT_IS_MSVC2013
#else
struct {
#endif // PBRT_HAVE_NONPOD_IN_UNIONS
EndpointInteraction ei;
MediumInteraction mi;
SurfaceInteraction si;
......@@ -384,7 +384,7 @@ struct Vertex {
// Compute sampling density for non-infinite light sources
Float pdfPos, pdfDir;
light->Pdf_Le(Ray(p(), w, time()), ng(), &pdfPos, &pdfDir);
light->Pdf_Le(Ray(p(), w, Infinity, time()), ng(), &pdfPos, &pdfDir);
pdf = pdfDir * invDist2;
}
if (v.IsOnSurface()) pdf *= AbsDot(v.ng(), w);
......@@ -417,7 +417,7 @@ struct Vertex {
size_t index = lightToDistrIndex.find(light)->second;
pdfChoice = lightDistr.DiscretePDF(index);
light->Pdf_Le(Ray(p(), w, time()), ng(), &pdfPos, &pdfDir);
light->Pdf_Le(Ray(p(), w, Infinity, time()), ng(), &pdfPos, &pdfDir);
return pdfPos * pdfChoice;
}
}
......
......@@ -194,7 +194,7 @@ void MLTIntegrator::Render(const Scene &scene) {
L(scene, arena, lightDistr, lightToIndex, sampler, depth, &pRaster).y();
arena.Reset();
}
if ((i + 1 % 256) == 0) progress.Update();
if ((i + 1) % 256 == 0) progress.Update();
}, nBootstrap, chunkSize);
progress.Done();
}
......
......@@ -65,7 +65,7 @@ Float SpotLight::Falloff(const Vector3f &w) const {
Vector3f wl = Normalize(WorldToLight(w));
Float cosTheta = wl.z;
if (cosTheta < cosTotalWidth) return 0;
if (cosTheta > cosFalloffStart) return 1;
if (cosTheta >= cosFalloffStart) return 1;
// Compute falloff inside spotlight cone
Float delta =
(cosTheta - cosTotalWidth) / (cosFalloffStart - cosTotalWidth);
......
This diff is collapsed.
/*
pbrt source code is Copyright(c) 1998-2017
Matt Pharr, Greg Humphreys, and Wenzel Jakob.
This file is part of pbrt.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(_MSC_VER)
#define NOMINMAX
#pragma once
#endif
#ifndef PBRT_MATERIALS_DISNEY_H
#define PBRT_MATERIALS_DISNEY_H
// materials/disney.h*
#include "material.h"
#include "pbrt.h"
namespace pbrt {
// DisneyMaterial Declarations
class DisneyMaterial : public Material {
public:
// DisneyMaterial Public Methods
DisneyMaterial(const std::shared_ptr<Texture<Spectrum>> &color,
const std::shared_ptr<Texture<Float>> &metallic,
const std::shared_ptr<Texture<Float>> &eta,
const std::shared_ptr<Texture<Float>> &roughness,
const std::shared_ptr<Texture<Float>> &specularTint,
const std::shared_ptr<Texture<Float>> &anisotropic,
const std::shared_ptr<Texture<Float>> &sheen,
const std::shared_ptr<Texture<Float>> &sheenTint,
const std::shared_ptr<Texture<Float>> &clearcoat,
const std::shared_ptr<Texture<Float>> &clearcoatGloss,
const std::shared_ptr<Texture<Float>> &specTrans,
const std::shared_ptr<Texture<Spectrum>> &scatterDistance,
bool thin,
const std::shared_ptr<Texture<Float>> &flatness,
const std::shared_ptr<Texture<Float>> &diffTrans,
const std::shared_ptr<Texture<Float>> &bumpMap)
: color(color),
metallic(metallic),
eta(eta),
roughness(roughness),
specularTint(specularTint),
anisotropic(anisotropic),
sheen(sheen),
sheenTint(sheenTint),
clearcoat(clearcoat),
clearcoatGloss(clearcoatGloss),
specTrans(specTrans),
scatterDistance(scatterDistance),
thin(thin),
flatness(flatness),
diffTrans(diffTrans),
bumpMap(bumpMap) {}
void ComputeScatteringFunctions(SurfaceInteraction *si, MemoryArena &arena,
TransportMode mode,
bool allowMultipleLobes) const;
private:
// DisneyMaterial Private Data
std::shared_ptr<Texture<Spectrum>> color;
std::shared_ptr<Texture<Float>> baseColor, metallic, eta;
std::shared_ptr<Texture<Float>> roughness, specularTint, anisotropic, sheen;
std::shared_ptr<Texture<Float>> sheenTint, clearcoat, clearcoatGloss;
std::shared_ptr<Texture<Float>> specTrans;
std::shared_ptr<Texture<Spectrum>> scatterDistance;
bool thin;
std::shared_ptr<Texture<Float>> flatness, diffTrans, bumpMap;
};
DisneyMaterial *CreateDisneyMaterial(const TextureParams &mp);
} // namespace pbrt
#endif // PBRT_MATERIALS_DISNEY_H
......@@ -54,7 +54,7 @@ class SobolSampler : public GlobalSampler {
if (!IsPowerOf2(samplesPerPixel))
Warning("Non power-of-two sample count rounded up to %" PRId64
" for SobolSampler.",
samplesPerPixel);
this->samplesPerPixel);
resolution = RoundUpPow2(
std::max(sampleBounds.Diagonal().x, sampleBounds.Diagonal().y));
log2Resolution = Log2Int(resolution);
......
......@@ -55,7 +55,8 @@ TriangleMesh::TriangleMesh(
const Transform &ObjectToWorld, int nTriangles, const int *vertexIndices,
int nVertices, const Point3f *P, const Vector3f *S, const Normal3f *N,
const Point2f *UV, const std::shared_ptr<Texture<Float>> &alphaMask,
const std::shared_ptr<Texture<Float>> &shadowAlphaMask)
const std::shared_ptr<Texture<Float>> &shadowAlphaMask,
const int *fIndices)
: nTriangles(nTriangles),
nVertices(nVertices),
vertexIndices(vertexIndices, vertexIndices + 3 * nTriangles),
......@@ -84,6 +85,9 @@ TriangleMesh::TriangleMesh(
s.reset(new Vector3f[nVertices]);
for (int i = 0; i < nVertices; ++i) s[i] = ObjectToWorld(S[i]);
}
if (fIndices)
faceIndices = std::vector<int>(fIndices, fIndices + nTriangles);
}
std::vector<std::shared_ptr<Shape>> CreateTriangleMesh(
......@@ -91,10 +95,11 @@ std::vector<std::shared_ptr<Shape>> CreateTriangleMesh(
bool reverseOrientation, int nTriangles, const int *vertexIndices,
int nVertices, const Point3f *p, const Vector3f *s, const Normal3f *n,