提交 05d8bcbd 编写于 作者: M Matt Pharr

Add basic support for displacement-mapped PLY meshes.

上级 91f78dc6
......@@ -7,9 +7,11 @@
#include <pbrt/pbrt.h>
#include <pbrt/base/texture.h>
#include <pbrt/util/taggedptr.h>
#include <pbrt/util/vecmath.h>
#include <map>
#include <string>
namespace pbrt {
......@@ -38,6 +40,7 @@ class Shape
const Transform *objectFromRender,
bool reverseOrientation,
const ParameterDictionary &parameters,
const std::map<std::string, FloatTexture> &floatTextures,
const FileLoc *loc, Allocator alloc);
std::string ToString() const;
......
......@@ -195,10 +195,12 @@ int displace(std::vector<std::string> args) {
TriQuadMesh outputMesh =
mesh.Displace([](Point3f v0, Point3f v1) { return Distance(v0, v1); }, edgeLength,
[&](Point3f p, Point2f uv) {
Float d = immeta.image.Bilerp(uvScale * uv,
WrapMode::Repeat).Average();
return d * scale;
[&](Point3f *p, const Normal3f *n, const Point2f *uv, int nVertices) {
ParallelFor(0, nVertices, [&](int64_t i) {
Point2f uvp(uvScale * uv[i][0], 1 - uvScale * uv[i][1]);
Float d = immeta.image.Bilerp(uvp, WrapMode::Repeat).Average();
p[i] += Vector3f(d * scale * n[i]);
});
});
if (!WritePLY(outFilename, outputMesh.triIndices, {}, outputMesh.p,
......
......@@ -305,6 +305,52 @@ OptixTraversableHandle OptiXAggregate::createGASForTriangles(
plyMesh.ConvertToOnlyTriangles();
Float edgeLength = shape.parameters.GetOneFloat("displacement.edgelength", 1.f);
std::string displacementTexName = shape.parameters.GetTexture("displacement");
if (!displacementTexName.empty()) {
auto iter = floatTextures.find(displacementTexName);
if (iter == floatTextures.end())
ErrorExit(&shape.loc, "%s: no such texture defined.", displacementTexName);
FloatTexture displacement = iter->second;
LOG_VERBOSE("Starting to displace mesh \"%s\" with \"%s\"", filename,
displacementTexName);
plyMesh =
plyMesh.Displace([&](Point3f v0, Point3f v1) {
v0 = (*shape.renderFromObject)(v0);
v1 = (*shape.renderFromObject)(v1);
return Distance(v0, v1);
}, edgeLength,
[&](Point3f *pCPU, const Normal3f *nCPU, const Point2f *uvCPU, int nVertices) {
Point3f *p = alloc.allocate_object<Point3f>(nVertices);
Normal3f *n = alloc.allocate_object<Normal3f>(nVertices);
Point2f *uv = alloc.allocate_object<Point2f>(nVertices);
std::memcpy(p, pCPU, nVertices * sizeof(Point3f));
std::memcpy(n, nCPU, nVertices * sizeof(Normal3f));
std::memcpy(uv, uvCPU, nVertices * sizeof(Point2f));
GPUParallelFor("Evaluate Displacement", nVertices,
[=] PBRT_GPU (int i) {
TextureEvalContext ctx;
ctx.p = p[i];
ctx.uv = uv[i];
Float d = UniversalTextureEvaluator()(displacement, ctx);
p[i] += Vector3f(d * n[i]);
});
GPUWait();
std::memcpy(pCPU, p, nVertices * sizeof(Point3f));
alloc.deallocate_object(p, nVertices);
alloc.deallocate_object(n, nVertices);
alloc.deallocate_object(uv, nVertices);
}, &shape.loc);
LOG_ERROR("Finished displacing mesh \"%s\" with \"%s\" -> %d tris", filename,
displacementTexName, plyMesh.triIndices.size() / 3);
}
mesh = alloc.new_object<TriangleMesh>(
*shape.renderFromObject, shape.reverseOrientation, plyMesh.triIndices,
plyMesh.p, std::vector<Vector3f>(), plyMesh.n, plyMesh.uv,
......@@ -514,7 +560,7 @@ OptixTraversableHandle OptiXAggregate::createGASForQuadrics(
pstd::vector<Shape> shapes = Shape::Create(
s.name, s.renderFromObject, s.objectFromRender,
s.reverseOrientation, s.parameters, &s.loc, alloc);
s.reverseOrientation, s.parameters, floatTextures, &s.loc, alloc);
if (shapes.empty())
continue;
CHECK_EQ(1, shapes.size());
......@@ -987,7 +1033,8 @@ OptiXAggregate::OptiXAggregate(
OptixTraversableHandle triangleGASTraversable = createGASForTriangles(
scene.shapes, hitPGTriangle, anyhitPGShadowTriangle, hitPGRandomHitTriangle,
textures.floatTextures, namedMaterials, materials, media, shapeIndexToAreaLights, &bounds);
textures.floatTextures, namedMaterials, materials, media, shapeIndexToAreaLights,
&bounds);
int bilinearSBTOffset = intersectHGRecords.size();
OptixTraversableHandle bilinearPatchGASTraversable =
createGASForBLPs(scene.shapes, hitPGBilinearPatch, anyhitPGShadowBilinearPatch,
......
......@@ -53,6 +53,9 @@ class OptiXAggregate : public WavefrontAggregate {
private:
struct HitgroupRecord;
// WAR: The enclosing parent function ("createGASForTriangles") for an extended __device__
// lambda cannot have private or protected access within its class
public:
OptixTraversableHandle createGASForTriangles(
const std::vector<ShapeSceneEntity> &shapes, const OptixProgramGroup &intersectPG,
const OptixProgramGroup &shadowPG, const OptixProgramGroup &randomHitPG,
......@@ -63,6 +66,7 @@ class OptiXAggregate : public WavefrontAggregate {
const std::map<int, pstd::vector<Light> *> &shapeIndexToAreaLights,
Bounds3f *gasBounds);
private:
OptixTraversableHandle createGASForBLPs(
const std::vector<ShapeSceneEntity> &shapes, const OptixProgramGroup &intersectPG,
const OptixProgramGroup &shadowPG, const OptixProgramGroup &randomHitPG,
......
......@@ -1114,7 +1114,8 @@ std::vector<Light> ParsedScene::CreateLights(
pstd::vector<pbrt::Shape> shapeObjects =
Shape::Create(sh.name, sh.renderFromObject, sh.objectFromRender,
sh.reverseOrientation, sh.parameters, &sh.loc, alloc);
sh.reverseOrientation, sh.parameters, textures.floatTextures,
&sh.loc, alloc);
FloatTexture alphaTex = getAlphaTexture(sh.parameters, &sh.loc);
......@@ -1183,7 +1184,8 @@ Primitive ParsedScene::CreateAggregate(
const auto &sh = shapes[i];
shapeVectors[i] =
Shape::Create(sh.name, sh.renderFromObject, sh.objectFromRender,
sh.reverseOrientation, sh.parameters, &sh.loc, alloc);
sh.reverseOrientation, sh.parameters,
textures.floatTextures, &sh.loc, alloc);
});
std::vector<Primitive> primitives;
......@@ -1246,7 +1248,7 @@ Primitive ParsedScene::CreateAggregate(
for (auto &sh : shapes) {
pstd::vector<pbrt::Shape> shapes =
Shape::Create(sh.name, sh.identity, sh.identity, sh.reverseOrientation,
sh.parameters, &sh.loc, alloc);
sh.parameters, textures.floatTextures, &sh.loc, alloc);
if (shapes.empty())
continue;
......
......@@ -4,6 +4,7 @@
#include <pbrt/shapes.h>
#include <pbrt/textures.h>
#ifdef PBRT_BUILD_GPU_RENDERER
#include <pbrt/gpu/util.h>
#endif // PBRT_BUILD_GPU_RENDERER
......@@ -1379,6 +1380,7 @@ pstd::vector<Shape> Shape::Create(const std::string &name,
const Transform *objectFromRender,
bool reverseOrientation,
const ParameterDictionary &parameters,
const std::map<std::string, FloatTexture> &floatTextures,
const FileLoc *loc, Allocator alloc) {
pstd::vector<Shape> shapes(alloc);
if (name == "sphere") {
......@@ -1412,6 +1414,38 @@ pstd::vector<Shape> Shape::Create(const std::string &name,
std::string filename = ResolveFilename(parameters.GetOneString("filename", ""));
TriQuadMesh plyMesh = TriQuadMesh::ReadPLY(filename);
Float edgeLength = parameters.GetOneFloat("displacement.edgelength", 1.f);
std::string displacementTexName = parameters.GetTexture("displacement");
if (!displacementTexName.empty()) {
auto iter = floatTextures.find(displacementTexName);
if (iter == floatTextures.end())
ErrorExit(loc, "%s: no such texture defined.", displacementTexName);
FloatTexture displacement = iter->second;
LOG_VERBOSE("Starting to displace mesh \"%s\" with \"%s\"", filename,
displacementTexName);
plyMesh =
plyMesh.Displace([&](Point3f v0, Point3f v1) {
v0 = (*renderFromObject)(v0);
v1 = (*renderFromObject)(v1);
return Distance(v0, v1);
}, edgeLength,
[&](Point3f *p, const Normal3f *n, const Point2f *uv, int nVertices) {
ParallelFor(0, nVertices,
[=] (int i) {
TextureEvalContext ctx;
ctx.p = p[i];
ctx.uv = uv[i];
Float d = UniversalTextureEvaluator()(displacement, ctx);
p[i] += Vector3f(d * n[i]);
});
}, loc);
LOG_ERROR("Finished displacing mesh \"%s\" with \"%s\" -> %d tris", filename,
displacementTexName, plyMesh.triIndices.size() / 3);
}
if (!plyMesh.triIndices.empty()) {
TriangleMesh *mesh = alloc.new_object<TriangleMesh>(
*renderFromObject, reverseOrientation, plyMesh.triIndices, plyMesh.p,
......
......@@ -71,6 +71,7 @@ class BilinearPatchMesh {
};
struct HashIntPair {
PBRT_CPU_GPU
size_t operator()(std::pair<int, int> p) const {
return MixBits(uint64_t(p.first) << 32 | p.second);
};
......@@ -105,10 +106,8 @@ struct TriQuadMesh {
triIndices[3*i+2], edgeSplit);
// Displace
ParallelFor(0, outputMesh.p.size(), [&](int64_t i) {
Float d = displace(outputMesh.p[i], outputMesh.uv[i]);
outputMesh.p[i] += Vector3f(d * outputMesh.n[i]);
});
displace(outputMesh.p.data(), outputMesh.n.data(), outputMesh.uv.data(),
outputMesh.p.size());
outputMesh.ComputeNormals();
......
......@@ -176,7 +176,8 @@ WavefrontPathIntegrator::WavefrontPathIntegrator(Allocator alloc, ParsedScene &s
pstd::vector<Shape> shapes =
Shape::Create(shape.name, shape.renderFromObject, shape.objectFromRender,
shape.reverseOrientation, shape.parameters, &shape.loc, alloc);
shape.reverseOrientation, shape.parameters,
textures.floatTextures, &shape.loc, alloc);
if (shapes.empty())
continue;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册