Skip to content

Commit

Permalink
Pbrt fixes (#902)
Browse files Browse the repository at this point in the history
* PBRT Engine fixes:
- Fix transformation composition
- Optimized scene rebuild process

* PBRT gemetry transformation fix

* Adjusting simulation light enabling threshold

* Fix for PBRT SDF geometry shapes

* Update PBRT SDF for simulation and optimization

* PBRT Support for rendering transparent frames and custom background color

* Take into account rotation center for PBRT geometry transformation
  • Loading branch information
NadirRoGue committed Dec 7, 2020
1 parent 67c8cf5 commit 2efa2f8
Show file tree
Hide file tree
Showing 11 changed files with 423 additions and 378 deletions.
6 changes: 3 additions & 3 deletions engines/pbrt/PBRTCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@ void PBRTCamera::manualCommit(const Vector2ui& resolution)
return;

const auto& srcPos = getPosition();
const pbrt::Point3f pos = glmToPbrt3<pbrt::Point3f>(srcPos);
const pbrt::Point3f pos = TO_PBRT_P3(srcPos);

const auto srcDir = glm::rotate(getOrientation(), Vector3d(0., 0., -1.));

const auto srcLook = srcPos + srcDir * 100.0;
const pbrt::Point3f look = glmToPbrt3<pbrt::Point3f>(srcLook);
const pbrt::Point3f look = TO_PBRT_P3(srcLook);

const auto srcUp = glm::normalize(glm::rotate(getOrientation(), Vector3d(0., -1., 0.)));
const pbrt::Vector3f up = glmToPbrt3<pbrt::Vector3f>(srcUp);
const pbrt::Vector3f up = TO_PBRT_V3(srcUp);

_camToWorldMatrix = pbrt::LookAt(pos, look, up);
_worldToCamMatrix = pbrt::Transform(_camToWorldMatrix.GetInverseMatrix(),
Expand Down
29 changes: 24 additions & 5 deletions engines/pbrt/PBRTFrameBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,36 @@ PBRTFrameBuffer::PBRTFrameBuffer(const std::string& name, const Vector2ui& frame

void PBRTFrameBuffer::fillColorBuffer(const std::vector<pbrt::Float>& src)
{
std::fill(_colorBuffer.begin(), _colorBuffer.end(), 255u);
const size_t colorDepth = getColorDepth();
if(colorDepth == 0)
throw std::runtime_error("PBRTFrameBuffer: 0 depth color is not supported");

if((colorDepth == 3 && _colorBuffer.size() % 3 != 0)
|| (colorDepth == 4 && _colorBuffer.size() % 4 != 0))
throw std::runtime_error("PBRTFrameBuffer: Color buffer does not match color depth");

for(size_t i = 0; i < _colorBuffer.size(); ++i)
_colorBuffer[i] = _backgroundColor[i % colorDepth];

//std::fill(_colorBuffer.begin(), _colorBuffer.end(), 255u);

#pragma omp parallel for
for (uint32_t x = 0; x < _frameSize.x; ++x)
{
for (uint32_t y = 0; y < _frameSize.y; ++y)
{
uint8_t* dst = &_colorBuffer[x * (_frameSize.y * getColorDepth()) + (y * getColorDepth())];
dst[0] = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 0]);
dst[1] = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 1]);
dst[2] = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 2]);
auto r = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 0]);
auto g = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 1]);
auto b = BRAYNS_PBRT_TO_BYTE(src[3 * (x * _frameSize.y + y) + 2]);
if(r > 0 && g > 0 && b > 0)
{
uint8_t* dst = &_colorBuffer[x * (_frameSize.y * colorDepth) + (y * colorDepth)];
dst[0] = r;
dst[1] = g;
dst[2] = b;
if(colorDepth == 4)
dst[3] = 255;
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions engines/pbrt/PBRTFrameBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,19 @@ class PBRTFrameBuffer : public FrameBuffer
return std::unique_lock<std::mutex>(_mapMutex);
}

void setBackgroundColor(const Vector3d& color)
{
_backgroundColor[0] = static_cast<uint8_t>(color.x * 255.0);
_backgroundColor[1] = static_cast<uint8_t>(color.y * 255.0);
_backgroundColor[2] = static_cast<uint8_t>(color.z * 255.0);
_backgroundColor[3] = 0;
}

private:
uint8_ts _colorBuffer;
std::mutex _mapMutex;

std::array<uint8_t, 4> _backgroundColor {0, 0, 0, 0};
};
}

Expand Down
135 changes: 86 additions & 49 deletions engines/pbrt/PBRTModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ std::shared_ptr<pbrt::AreaLight> createLightForShape(std::shared_ptr<ShapeType>&
MaterialPtr& mat,
const float value)
{
static constexpr float NO_LIGHT_THRESHOLD = 0.1f;
static constexpr float INTENSITY_THRESHOLD = 0.3f;

const auto cvalue = glm::clamp(static_cast<double>(value),
tf.getValuesRange().x,
tf.getValuesRange().y);
Expand All @@ -144,18 +147,18 @@ std::shared_ptr<pbrt::AreaLight> createLightForShape(std::shared_ptr<ShapeType>&
const brayns::Vector3f color = tf.getColorForValue(value);
if(mat)
{
if(intensity < 0.1f)
if(intensity < NO_LIGHT_THRESHOLD)
mat->setDiffuseColor({1.f, 1.f, 1.f});
else
mat->setDiffuseColor({color.r, color.g, color.b});
}

// Do not add light if the intensity is below a given threshold
if(intensity < 0.75f)
if(intensity < INTENSITY_THRESHOLD)
return std::shared_ptr<pbrt::AreaLight>{nullptr};

// remap intensity if we are adding light
intensity = (intensity - 0.75f) / 0.25f;
intensity = (intensity - INTENSITY_THRESHOLD) / (1.f - INTENSITY_THRESHOLD);
// smoothsetep light intensity
const float lightIntensity = (intensity*intensity*intensity*
(intensity*(intensity * 6 - 15) + 10)) * 3.f;
Expand Down Expand Up @@ -209,18 +212,18 @@ PBRTModel::commitToPBRT(const Transformation &transform, const std::string& rend

// Both ways transforms
_objectToWorld = pbrtTransform(transform);
_worldToObject = pbrt::Transform (_objectToWorld.GetInverseMatrix(),
_objectToWorld.GetMatrix());

// Parse medium which will be added *inside* the model shapes
_parseMedium(&_objectToWorld);

_transformPool.clear();

// Create shapes
auto spheres = _createSpheres(&_objectToWorld, &_worldToObject);
auto cylinders = _createCylinders(&_objectToWorld, &_worldToObject);
auto cones = _createCones(&_objectToWorld, &_worldToObject);
auto meshes = _createMeshes(&_objectToWorld, &_worldToObject);
auto sdfGeoms = _createSDFGeometries(&_objectToWorld, &_worldToObject);
auto spheres = _createSpheres(_objectToWorld);
auto cylinders = _createCylinders(_objectToWorld);
auto cones = _createCones(_objectToWorld);
auto meshes = _createMeshes(_objectToWorld);
auto sdfGeoms = _createSDFGeometries(_objectToWorld);

// Insert all into the result
Primitives result;
Expand Down Expand Up @@ -291,10 +294,9 @@ void PBRTModel::_commitMaterials(const std::string& renderer)


std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>
PBRTModel::_createSpheres(pbrt::Transform* otw, pbrt::Transform* wto)
PBRTModel::_createSpheres(const pbrt::Transform& transform)
{
Primitives result;

const pbrt::MediumInterface dummyMI (_modelMedium.get(), nullptr);

for(const auto& sphereList : getSpheres())
Expand All @@ -317,11 +319,11 @@ PBRTModel::_createSpheres(pbrt::Transform* otw, pbrt::Transform* wto)
sphere.center.z));

std::unique_ptr<pbrt::Transform> otwFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(otw->GetMatrix(),
(new pbrt::Transform(pbrt::Matrix4x4::Mul(transform.GetMatrix(),
otwS.GetMatrix())));
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(wto->GetMatrix(),
otwS.GetInverseMatrix())));
(new pbrt::Transform(otwFinal->GetInverseMatrix(),
otwFinal->GetMatrix()));

auto otwFinalPtr = otwFinal.get();
auto wtoFinalPtr = wtoFinal.get();
Expand Down Expand Up @@ -358,10 +360,9 @@ PBRTModel::_createSpheres(pbrt::Transform* otw, pbrt::Transform* wto)
}

std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>
PBRTModel::_createCylinders(pbrt::Transform* otw, pbrt::Transform* wto)
PBRTModel::_createCylinders(const pbrt::Transform& transform)
{
Primitives result;

const pbrt::MediumInterface dummyMI (_modelMedium.get(), nullptr);

for(const auto& cylinderList : getCylinders())
Expand All @@ -377,29 +378,24 @@ PBRTModel::_createCylinders(pbrt::Transform* otw, pbrt::Transform* wto)

for(const auto& cylinder : cylinderList.second)
{

// Compute PBRT Transform from Brayns Transform
const auto direction = glm::normalize(cylinder.up - cylinder.center);
glm::vec3 theoreticalUp (0.f, 1.f, 0.f);
if (direction == theoreticalUp)
theoreticalUp = glm::vec3(1.f, 0.f, 0.f);
auto rUp = glm::normalize(glm::cross(direction, theoreticalUp));
auto pbrtMat = pbrt::LookAt(pbrt::Point3f(cylinder.center.x,
cylinder.center.y,
cylinder.center.z),
pbrt::Point3f(cylinder.up.x,
cylinder.up.y,
cylinder.up.z),
pbrt::Vector3f(rUp.x, rUp.y, rUp.z));
auto pbrtMat = pbrt::LookAt(TO_PBRT_P3(cylinder.center),
TO_PBRT_P3(cylinder.up),
TO_PBRT_V3(rUp));

const pbrt::Transform cylTrans(pbrtMat);

// Multiply by model transformation
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(otw->GetMatrix(),
cylTrans.GetMatrix())));
std::unique_ptr<pbrt::Transform> otwFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(wto->GetMatrix(),
(new pbrt::Transform(pbrt::Matrix4x4::Mul(transform.GetMatrix(),
cylTrans.GetInverseMatrix())));
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(otwFinal->GetInverseMatrix(), otwFinal->GetMatrix()));

auto otwFinalPtr = otwFinal.get();
auto wtoFinalPtr = wtoFinal.get();
Expand Down Expand Up @@ -448,10 +444,9 @@ PBRTModel::_createCylinders(pbrt::Transform* otw, pbrt::Transform* wto)
}

std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>
PBRTModel::_createCones(pbrt::Transform* otw, pbrt::Transform* wto)
PBRTModel::_createCones(const pbrt::Transform& transform)
{
Primitives result;

const pbrt::MediumInterface dummyMI (_modelMedium.get(), nullptr);

for(const auto& coneList : getCones())
Expand All @@ -465,7 +460,6 @@ PBRTModel::_createCones(pbrt::Transform* otw, pbrt::Transform* wto)
pbrtMaterial = impl.getPBRTMaterial();
}


for(const auto& cone : coneList.second)
{
// Compute PBRT Transform from Brayns Transform
Expand All @@ -474,19 +468,19 @@ PBRTModel::_createCones(pbrt::Transform* otw, pbrt::Transform* wto)
if (direction == theoreticalUp)
theoreticalUp = glm::vec3(1.f, 0.f, 0.f);
auto rUp = glm::normalize(glm::cross(direction, theoreticalUp));
auto pbrtMat = pbrt::LookAt(pbrt::Point3f(cone.center.x, cone.center.y, cone.center.z),
pbrt::Point3f(cone.up.x, cone.up.y, cone.up.z),
pbrt::Vector3f(rUp.x, rUp.y, rUp.z));
auto pbrtMat = pbrt::LookAt(TO_PBRT_P3(cone.center),
TO_PBRT_P3(cone.up),
TO_PBRT_V3(rUp));

const pbrt::Transform conTrans(pbrtMat);

// Multiply by model transformation
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(otw->GetMatrix(),
conTrans.GetMatrix())));
std::unique_ptr<pbrt::Transform> otwFinal
(new pbrt::Transform(pbrt::Matrix4x4::Mul(wto->GetMatrix(),
(new pbrt::Transform(pbrt::Matrix4x4::Mul(transform.GetMatrix(),
conTrans.GetInverseMatrix())));
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(otwFinal->GetInverseMatrix(),
otwFinal->GetMatrix()));

auto otwFinalPtr = otwFinal.get();
auto wtoFinalPtr = wtoFinal.get();
Expand Down Expand Up @@ -530,10 +524,19 @@ PBRTModel::_createCones(pbrt::Transform* otw, pbrt::Transform* wto)
}

std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>
PBRTModel::_createMeshes(pbrt::Transform* otw, pbrt::Transform* wto)
PBRTModel::_createMeshes(const pbrt::Transform& transform)
{
Primitives result;

std::unique_ptr<pbrt::Transform> otw = std::make_unique<pbrt::Transform>(
transform.GetMatrix(), transform.GetInverseMatrix());
std::unique_ptr<pbrt::Transform> wto = std::make_unique<pbrt::Transform>(
transform.GetInverseMatrix(), transform.GetMatrix());
auto otwPtr = otw.get();
auto wtoPtr = wto.get();
_transformPool.push_back(std::move(otw));
_transformPool.push_back(std::move(wto));

const pbrt::MediumInterface dummyMI (_modelMedium.get(), nullptr);

const std::shared_ptr<pbrt::AreaLight> dummyAL;
Expand Down Expand Up @@ -595,7 +598,7 @@ PBRTModel::_createMeshes(pbrt::Transform* otw, pbrt::Transform* wto)
params.AddNormal3f("N", std::move(normals), static_cast<int>(mesh.normals.size()));
}

auto pbrtMeshList = pbrt::CreateTriangleMeshShape(otw, wto, false, params);
auto pbrtMeshList = pbrt::CreateTriangleMeshShape(otwPtr, wtoPtr, false, params);
for(auto& meshObj : pbrtMeshList)
result.push_back(std::shared_ptr<pbrt::GeometricPrimitive>(
new pbrt::GeometricPrimitive(
Expand All @@ -609,19 +612,31 @@ PBRTModel::_createMeshes(pbrt::Transform* otw, pbrt::Transform* wto)
}

std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>
PBRTModel::_createSDFGeometries(pbrt::Transform* otw, pbrt::Transform* wto)
PBRTModel::_createSDFGeometries(const pbrt::Transform& transform)
{
Primitives result;

const pbrt::MediumInterface dummyMI (_modelMedium.get(), nullptr);
const std::shared_ptr<pbrt::AreaLight> dummyAL;
std::shared_ptr<pbrt::AreaLight> dummyAL;

std::unique_ptr<pbrt::Transform> otwFinal
(new pbrt::Transform(transform.GetMatrix(), transform.GetInverseMatrix()));
std::unique_ptr<pbrt::Transform> wtoFinal
(new pbrt::Transform(otwFinal->GetInverseMatrix(), otwFinal->GetMatrix()));

auto otwFinalPtr = otwFinal.get();
auto wtoFinalPtr = wtoFinal.get();

_transformPool.push_back(std::move(otwFinal));
_transformPool.push_back(std::move(wtoFinal));

for(const auto& geometryList : getSDFGeometryData().geometryIndices)
{
std::shared_ptr<Material> mat {nullptr};
std::shared_ptr<pbrt::Material> pbrtMaterial {nullptr};
if(geometryList.first != NO_MATERIAL && !_modelMedium)
{
const auto& mat = getMaterial(geometryList.first);
mat = _materials[geometryList.first];
PBRTMaterial& impl = static_cast<PBRTMaterial&>(*mat.get());
pbrtMaterial = impl.getPBRTMaterial();
}
Expand All @@ -634,19 +649,41 @@ PBRTModel::_createSDFGeometries(pbrt::Transform* otw, pbrt::Transform* wto)
switch(geom.type)
{
case SDFType::Sphere:
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::Sphere>>(otw, wto, false, &geom, &getSDFGeometryData());
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::Sphere>>(otwFinalPtr,
wtoFinalPtr,
false,
&geom,
&getSDFGeometryData());
break;
case SDFType::Pill:
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::Pill>>(otw, wto, false, &geom, &getSDFGeometryData());
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::Pill>>(otwFinalPtr,
wtoFinalPtr,
false,
&geom,
&getSDFGeometryData());
break;
case SDFType::ConePill:
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::ConePill>>(otw, wto, false, &geom, &getSDFGeometryData());
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::ConePill>>(otwFinalPtr,
wtoFinalPtr,
false,
&geom, &getSDFGeometryData());
break;
case SDFType::ConePillSigmoid:
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::ConePillSigmoid>>(otw, wto, false, &geom, &getSDFGeometryData());
shape = std::make_shared<PBRTSDFGeometryShape<SDFType::ConePillSigmoid>>(otwFinalPtr,
wtoFinalPtr,
false,
&geom,
&getSDFGeometryData());
break;

}
}

if(!_simulationData.empty())
{
dummyAL = createLightForShape(shape, _transferFunction, mat, _simulationData[geom.userData]);
if(dummyAL)
_modelLights.push_back(dummyAL);
}

result.push_back(std::make_shared<pbrt::GeometricPrimitive>(
shape,
Expand Down
10 changes: 5 additions & 5 deletions engines/pbrt/PBRTModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ class PBRTModel : public Model

// Auxiliary functions to translate Brayns objects into PBRT objects
using Primitives = std::vector<std::shared_ptr<pbrt::GeometricPrimitive>>;
Primitives _createSpheres(pbrt::Transform* otw, pbrt::Transform* wto);
Primitives _createCylinders(pbrt::Transform* otw, pbrt::Transform* wto);
Primitives _createCones(pbrt::Transform* otw, pbrt::Transform* wto);
Primitives _createMeshes(pbrt::Transform* otw, pbrt::Transform* wto);
Primitives _createSDFGeometries(pbrt::Transform* otw, pbrt::Transform* wto);
Primitives _createSpheres(const pbrt::Transform& transform);
Primitives _createCylinders(const pbrt::Transform& transform);
Primitives _createCones(const pbrt::Transform& transform);
Primitives _createMeshes(const pbrt::Transform& transform);
Primitives _createSDFGeometries(const pbrt::Transform& transform);

void _parseMedium(pbrt::Transform* otw);

Expand Down
1 change: 1 addition & 0 deletions engines/pbrt/PBRTRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ void PBRTRenderer::render(FrameBufferPtr frameBuffer)
{
this->_pbrtRenderer->Render(*pbrtSceneImpl);
PBRTFrameBuffer* pbrtFB = static_cast<PBRTFrameBuffer*>(frameBuffer.get());
pbrtFB->setBackgroundColor(_renderingParameters.getBackgroundColor());
pbrtFB->fillColorBuffer(pbrtCam.getFilm()->_rgb);
frameBuffer->markModified();
pbrtCam.getFilm()->Clear();
Expand Down

0 comments on commit 2efa2f8

Please sign in to comment.