support face normals in the preview
parent
4afd9afb25
commit
781006c968
|
@ -579,7 +579,6 @@ plugins += env.SharedLibrary('plugins/spot', ['src/luminaires/spot.cpp'])
|
||||||
plugins += env.SharedLibrary('plugins/point', ['src/luminaires/point.cpp'])
|
plugins += env.SharedLibrary('plugins/point', ['src/luminaires/point.cpp'])
|
||||||
plugins += env.SharedLibrary('plugins/collimated', ['src/luminaires/collimated.cpp'])
|
plugins += env.SharedLibrary('plugins/collimated', ['src/luminaires/collimated.cpp'])
|
||||||
plugins += env.SharedLibrary('plugins/directional', ['src/luminaires/directional.cpp'])
|
plugins += env.SharedLibrary('plugins/directional', ['src/luminaires/directional.cpp'])
|
||||||
plugins += env.SharedLibrary('plugins/portal', ['src/luminaires/portal.cpp'])
|
|
||||||
|
|
||||||
# Integrators
|
# Integrators
|
||||||
plugins += env.SharedLibrary('plugins/direct', ['src/integrators/direct/direct.cpp'])
|
plugins += env.SharedLibrary('plugins/direct', ['src/integrators/direct/direct.cpp'])
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
|
|
||||||
/// Prepare for rendering a material with BSDF 'bsdf' illuminated by VPL 'vpl'.
|
/// Prepare for rendering a material with BSDF 'bsdf' illuminated by VPL 'vpl'.
|
||||||
void configure(const VPL &vpl, const BSDF *bsdf,
|
void configure(const VPL &vpl, const BSDF *bsdf,
|
||||||
const Luminaire *luminaire, const Point &camPos);
|
const Luminaire *luminaire, const Point &camPos, bool faceNormals);
|
||||||
|
|
||||||
/// Draw the background if there is an environment luminaire
|
/// Draw the background if there is an environment luminaire
|
||||||
void drawBackground(const Transform &clipToWorld, const Point &camPos);
|
void drawBackground(const Transform &clipToWorld, const Point &camPos);
|
||||||
|
@ -171,7 +171,7 @@ private:
|
||||||
|
|
||||||
struct VPLProgramConfiguration {
|
struct VPLProgramConfiguration {
|
||||||
VPLDependencyNode vpl, bsdf, luminaire;
|
VPLDependencyNode vpl, bsdf, luminaire;
|
||||||
bool hasLuminaire;
|
bool hasLuminaire, faceNormals;
|
||||||
int param_shadowMap, param_vplPos, param_camPos, param_vplPower;
|
int param_shadowMap, param_vplPos, param_camPos, param_vplPower;
|
||||||
int param_vplN, param_vplS, param_vplT, param_vplWi, param_vplUV;
|
int param_vplN, param_vplS, param_vplT, param_vplWi, param_vplUV;
|
||||||
int param_nearClip, param_invClipRange, param_minDist;
|
int param_nearClip, param_invClipRange, param_minDist;
|
||||||
|
@ -179,8 +179,8 @@ private:
|
||||||
|
|
||||||
inline VPLProgramConfiguration() { }
|
inline VPLProgramConfiguration() { }
|
||||||
|
|
||||||
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire)
|
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire, bool faceNormals)
|
||||||
: vpl(vpl), bsdf(bsdf), luminaire(luminaire) {
|
: vpl(vpl), bsdf(bsdf), luminaire(luminaire), faceNormals(faceNormals) {
|
||||||
hasLuminaire = (luminaire != NULL);
|
hasLuminaire = (luminaire != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +224,8 @@ private:
|
||||||
oss << ", luminaire=";
|
oss << ", luminaire=";
|
||||||
luminaire.toString(oss);
|
luminaire.toString(oss);
|
||||||
}
|
}
|
||||||
|
if (faceNormals)
|
||||||
|
oss << ", faceNormals";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,8 @@ public:
|
||||||
m_renderer->beginDrawingMeshes();
|
m_renderer->beginDrawingMeshes();
|
||||||
for (unsigned int j=0; j<meshes.size(); j++) {
|
for (unsigned int j=0; j<meshes.size(); j++) {
|
||||||
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
||||||
meshes[j]->getLuminaire(), camPos);
|
meshes[j]->getLuminaire(), camPos,
|
||||||
|
!meshes[j]->hasVertexNormals());
|
||||||
m_renderer->drawTriMesh(meshes[j]);
|
m_renderer->drawTriMesh(meshes[j]);
|
||||||
m_shaderManager->unbind();
|
m_shaderManager->unbind();
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,17 @@ int GLProgram::createShader(int type, const std::string &source) {
|
||||||
glGetObjectParameterivARB(id, GL_COMPILE_STATUS, &result);
|
glGetObjectParameterivARB(id, GL_COMPILE_STATUS, &result);
|
||||||
if (result == GL_FALSE) {
|
if (result == GL_FALSE) {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
std::string typeStr;
|
||||||
|
if (type == GL_VERTEX_SHADER_ARB)
|
||||||
|
typeStr = "vertex";
|
||||||
|
else if (type == GL_FRAGMENT_SHADER_ARB)
|
||||||
|
typeStr = "fragment";
|
||||||
|
else if (type == GL_GEOMETRY_SHADER_ARB)
|
||||||
|
typeStr = "geometry";
|
||||||
|
else
|
||||||
|
typeStr = "unknown";
|
||||||
if (infoLog != "")
|
if (infoLog != "")
|
||||||
Log(EError, "Error compiling a shader: %s", infoLog.c_str());
|
Log(EError, "Error compiling a %s shader: %s", typeStr.c_str(), infoLog.c_str());
|
||||||
else
|
else
|
||||||
Log(EError, "Unknown error encountered while compiling a shader!");
|
Log(EError, "Unknown error encountered while compiling a shader!");
|
||||||
} else if (infoLog != "") {
|
} else if (infoLog != "") {
|
||||||
|
|
|
@ -281,7 +281,7 @@ void VPLShaderManager::setVPL(const VPL &vpl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
||||||
const Luminaire *luminaire, const Point &camPos) {
|
const Luminaire *luminaire, const Point &camPos, bool faceNormals) {
|
||||||
Shader *bsdfShader = m_renderer->getShaderForResource(bsdf);
|
Shader *bsdfShader = m_renderer->getShaderForResource(bsdf);
|
||||||
Shader *vplShader = (vpl.type == ELuminaireVPL)
|
Shader *vplShader = (vpl.type == ELuminaireVPL)
|
||||||
? m_renderer->getShaderForResource(vpl.luminaire)
|
? m_renderer->getShaderForResource(vpl.luminaire)
|
||||||
|
@ -300,7 +300,8 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
||||||
|
|
||||||
bool anisotropic = bsdf->getType() & BSDF::EAnisotropicMaterial;
|
bool anisotropic = bsdf->getType() & BSDF::EAnisotropicMaterial;
|
||||||
|
|
||||||
m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader, lumShader);
|
m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader,
|
||||||
|
lumShader, faceNormals);
|
||||||
m_targetConfig.toString(oss);
|
m_targetConfig.toString(oss);
|
||||||
std::string configName = oss.str();
|
std::string configName = oss.str();
|
||||||
std::map<std::string, ProgramAndConfiguration>::iterator it =
|
std::map<std::string, ProgramAndConfiguration>::iterator it =
|
||||||
|
@ -315,24 +316,79 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
||||||
/* No program for this particular combination exists -- create one */
|
/* No program for this particular combination exists -- create one */
|
||||||
program = m_renderer->createGPUProgram(configName);
|
program = m_renderer->createGPUProgram(configName);
|
||||||
|
|
||||||
|
if (faceNormals) {
|
||||||
|
/* Generate face normals in a geometry shader */
|
||||||
|
|
||||||
|
if (!m_renderer->getCapabilities()->isSupported(
|
||||||
|
RendererCapabilities::EGeometryShaders))
|
||||||
|
Log(EError, "Face normals require geometry shader support!");
|
||||||
|
if (anisotropic)
|
||||||
|
Log(EError, "Anisotropy and face normals can't be combined at the moment");
|
||||||
|
|
||||||
|
oss.str("");
|
||||||
|
oss << "#version 120" << endl
|
||||||
|
<< "#extension GL_EXT_geometry_shader4 : enable" << endl
|
||||||
|
<< "varying in vec3 lightVec_vertex[3], camVec_vertex[3];" << endl
|
||||||
|
<< "varying in vec2 uv_vertex[3];" << endl
|
||||||
|
<< "varying in vec3 vertexColor_vertex[3];" << endl
|
||||||
|
<< "varying out vec3 normal;" << endl
|
||||||
|
<< "varying out vec3 lightVec, camVec;" << endl
|
||||||
|
<< "varying out vec2 uv;" << endl
|
||||||
|
<< "varying out vec3 vertexColor;" << endl
|
||||||
|
<< endl
|
||||||
|
<< "void main() {" << endl
|
||||||
|
<< " normal = normalize(cross(" << endl
|
||||||
|
<< " gl_PositionIn[1].xyz-gl_PositionIn[0].xyz," << endl
|
||||||
|
<< " gl_PositionIn[2].xyz-gl_PositionIn[0].xyz));" << endl
|
||||||
|
<< " for (int i=0; i<gl_VerticesIn; ++i) {" << endl
|
||||||
|
<< " gl_Position = gl_PositionIn[i];" << endl
|
||||||
|
<< " uv = uv_vertex[i];" << endl
|
||||||
|
<< " vertexColor = vertexColor_vertex[i];" << endl
|
||||||
|
<< " lightVec = lightVec_vertex[i];" << endl
|
||||||
|
<< " camVec = camVec_vertex[i];" << endl
|
||||||
|
<< " EmitVertex();" << endl
|
||||||
|
<< " }" << endl
|
||||||
|
<< " EndPrimitive();" << endl
|
||||||
|
<< "}" << endl;
|
||||||
|
|
||||||
|
program->setMaxVertices(3);
|
||||||
|
program->setSource(GPUProgram::EGeometryProgram, oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
/* Vertex program */
|
/* Vertex program */
|
||||||
oss.str("");
|
oss.str("");
|
||||||
oss << "#version 120" << endl;
|
oss << "#version 120" << endl;
|
||||||
if (anisotropic)
|
if (anisotropic)
|
||||||
oss << "varying vec3 tangent;" << endl;
|
oss << "varying vec3 tangent;" << endl;
|
||||||
|
if (!faceNormals)
|
||||||
|
oss << "varying vec3 normal;" << endl;
|
||||||
|
oss << "uniform vec3 vplPos, camPos;" << endl;
|
||||||
|
|
||||||
oss << "uniform vec3 vplPos, camPos;" << endl
|
if (!faceNormals) {
|
||||||
<< "varying vec3 normal, lightVec, camVec;" << endl
|
oss << "varying vec3 lightVec, camVec;" << endl
|
||||||
<< "varying vec2 uv;" << endl
|
<< "varying vec2 uv;" << endl
|
||||||
<< "varying vec3 vertexColor;" << endl
|
<< "varying vec3 vertexColor;" << endl
|
||||||
<< endl
|
<< endl
|
||||||
<< "void main() {" << endl
|
<< "void main() {" << endl
|
||||||
<< " normal = gl_Normal;" << endl
|
|
||||||
<< " uv = gl_MultiTexCoord0.xy;" << endl
|
<< " uv = gl_MultiTexCoord0.xy;" << endl
|
||||||
<< " camVec = camPos - gl_Vertex.xyz;" << endl
|
<< " camVec = camPos - gl_Vertex.xyz;" << endl
|
||||||
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl
|
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl
|
||||||
<< " gl_Position = ftransform();" << endl
|
<< " gl_Position = ftransform();" << endl
|
||||||
<< " vertexColor = gl_Color.rgb;" << endl;
|
<< " vertexColor = gl_Color.rgb;" << endl;
|
||||||
|
} else {
|
||||||
|
oss << "varying vec3 lightVec_vertex, camVec_vertex;" << endl
|
||||||
|
<< "varying vec2 uv_vertex;" << endl
|
||||||
|
<< "varying vec3 vertexColor_vertex;" << endl
|
||||||
|
<< endl
|
||||||
|
<< "void main() {" << endl
|
||||||
|
<< " uv_vertex = gl_MultiTexCoord0.xy;" << endl
|
||||||
|
<< " camVec_vertex = camPos - gl_Vertex.xyz;" << endl
|
||||||
|
<< " lightVec_vertex = vplPos - gl_Vertex.xyz;" << endl
|
||||||
|
<< " gl_Position = ftransform();" << endl
|
||||||
|
<< " vertexColor_vertex = gl_Color.rgb;" << endl;
|
||||||
|
}
|
||||||
|
if (!faceNormals)
|
||||||
|
oss << " normal = gl_Normal;" << endl;
|
||||||
if (anisotropic)
|
if (anisotropic)
|
||||||
oss << " tangent = gl_MultiTexCoord1.xyz;" << endl;
|
oss << " tangent = gl_MultiTexCoord1.xyz;" << endl;
|
||||||
oss << "}" << endl;
|
oss << "}" << endl;
|
||||||
|
|
|
@ -312,7 +312,11 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe
|
||||||
&p1 = positions[idx1],
|
&p1 = positions[idx1],
|
||||||
&p2 = positions[idx2];
|
&p2 = positions[idx2];
|
||||||
Vector sideA = p1 - p0, sideB = p2 - p0;
|
Vector sideA = p1 - p0, sideB = p2 - p0;
|
||||||
its.shFrame.n = Normal(cross(sideA, sideB));
|
Vector n = cross(sideA, sideB);
|
||||||
|
Float nLengthSqr = n.lengthSquared();
|
||||||
|
if (nLengthSqr != 0)
|
||||||
|
n /= std::sqrt(nLengthSqr);
|
||||||
|
its.shFrame.n = Normal(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EXPECT_TAKEN(texcoords)) {
|
if (EXPECT_TAKEN(texcoords)) {
|
||||||
|
@ -369,9 +373,13 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe
|
||||||
its.p.x = secRay4.o[0].f[idx];
|
its.p.x = secRay4.o[0].f[idx];
|
||||||
its.p.y = secRay4.o[1].f[idx];
|
its.p.y = secRay4.o[1].f[idx];
|
||||||
its.p.z = secRay4.o[2].f[idx];
|
its.p.z = secRay4.o[2].f[idx];
|
||||||
|
if (EXPECT_NOT_TAKEN(bsdf->getType() & BSDF::EAnisotropicMaterial)) {
|
||||||
its.shFrame.s = normalize(its.dpdu - its.shFrame.n
|
its.shFrame.s = normalize(its.dpdu - its.shFrame.n
|
||||||
* dot(its.shFrame.n, its.dpdu));
|
* dot(its.shFrame.n, its.dpdu));
|
||||||
its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
|
its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
|
||||||
|
} else {
|
||||||
|
coordinateSystem(its.shFrame.n, its.shFrame.s, its.shFrame.t);
|
||||||
|
}
|
||||||
const Float ctLight = cosThetaLight.f[idx];
|
const Float ctLight = cosThetaLight.f[idx];
|
||||||
wi = normalize(wi);
|
wi = normalize(wi);
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,8 @@ void TriMesh::configure() {
|
||||||
for (size_t i=0; i<m_vertexCount; i++)
|
for (size_t i=0; i<m_vertexCount; i++)
|
||||||
m_bsphere.expandBy(m_positions[i]);
|
m_bsphere.expandBy(m_positions[i]);
|
||||||
computeNormals();
|
computeNormals();
|
||||||
if (m_bsdf->getType() & BSDF::EAnisotropicMaterial && !m_tangents)
|
if ((m_bsdf->getType() & BSDF::EAnisotropicMaterial
|
||||||
|
|| m_bsdf->usesRayDifferentials()) && !m_tangents)
|
||||||
computeTangentSpaceBasis();
|
computeTangentSpaceBasis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class ConstantLuminaire : public Luminaire {
|
||||||
public:
|
public:
|
||||||
ConstantLuminaire(const Properties &props) : Luminaire(props) {
|
ConstantLuminaire(const Properties &props) : Luminaire(props) {
|
||||||
m_intensity = props.getSpectrum("intensity", Spectrum(1.0f));
|
m_intensity = props.getSpectrum("intensity", Spectrum(1.0f));
|
||||||
m_type = EOnSurface;
|
m_type = EOnSurface | EDiffuseDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantLuminaire(Stream *stream, InstanceManager *manager)
|
ConstantLuminaire(Stream *stream, InstanceManager *manager)
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
|
|
||||||
Spectrum Le(const LuminaireSamplingRecord &lRec) const {
|
Spectrum Le(const LuminaireSamplingRecord &lRec) const {
|
||||||
/* Directional luminaire is not part of the scene */
|
/* Directional luminaire is not part of the scene */
|
||||||
Log(EWarn, "This function should never be called.");
|
Log(EError, "This function should never be called.");
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,6 @@ public:
|
||||||
|
|
||||||
Spectrum f(const EmissionRecord &eRec) const {
|
Spectrum f(const EmissionRecord &eRec) const {
|
||||||
/* Directional luminaire beam is not part of the scene */
|
/* Directional luminaire beam is not part of the scene */
|
||||||
Log(EWarn, "This function should never be called.");
|
|
||||||
return Spectrum(0.0f);
|
return Spectrum(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,212 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of Mitsuba, a physically based rendering system.
|
|
||||||
|
|
||||||
Copyright (c) 2007-2010 by Wenzel Jakob and others.
|
|
||||||
|
|
||||||
Mitsuba is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License Version 3
|
|
||||||
as published by the Free Software Foundation.
|
|
||||||
|
|
||||||
Mitsuba is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <mitsuba/render/scene.h>
|
|
||||||
#include <mitsuba/hw/gpuprogram.h>
|
|
||||||
|
|
||||||
MTS_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Portal luminaire -- can be used to turn a surface into a
|
|
||||||
* portal that exposes luminaires behind it, such as an
|
|
||||||
* environment map. This is often necessary to make interior
|
|
||||||
* lighting work efficiently enough when using algorithms like
|
|
||||||
* path tracing or photon mapping.
|
|
||||||
*/
|
|
||||||
class PortalLuminaire : public Luminaire {
|
|
||||||
public:
|
|
||||||
PortalLuminaire(const Properties &props) : Luminaire(props), m_shape(NULL) {
|
|
||||||
AssertEx(m_luminaireToWorld.isIdentity(), "Error: non-identity transformation found. "
|
|
||||||
"Portal luminaires inherit their transformation from the associated shape!");
|
|
||||||
m_type = EDiffuseDirection | EOnSurface;
|
|
||||||
m_intersectable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~PortalLuminaire() {
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
|
||||||
m_luminaires[i]->decRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
PortalLuminaire(Stream *stream, InstanceManager *manager)
|
|
||||||
: Luminaire(stream, manager) {
|
|
||||||
m_shape = static_cast<Shape *>(manager->getInstance(stream));
|
|
||||||
int luminaireCount = stream->readInt();
|
|
||||||
for (int i=0; i<luminaireCount; ++i)
|
|
||||||
addChild("", static_cast<Luminaire *>(manager->getInstance(stream)));
|
|
||||||
configure();
|
|
||||||
}
|
|
||||||
|
|
||||||
void preprocess(const Scene *scene) {
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
|
||||||
m_luminaires[i]->preprocess(scene);
|
|
||||||
configure();
|
|
||||||
}
|
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
|
||||||
Luminaire::serialize(stream, manager);
|
|
||||||
|
|
||||||
manager->serialize(stream, m_shape);
|
|
||||||
stream->writeInt((int) m_luminaires.size());
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
|
||||||
manager->serialize(stream, m_luminaires[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
|
||||||
const Class *cClass = child->getClass();
|
|
||||||
if (cClass->derivesFrom(Luminaire::m_theClass)) {
|
|
||||||
Luminaire *luminaire = static_cast<Luminaire *>(child);
|
|
||||||
m_luminaires.push_back(luminaire);
|
|
||||||
luminaire->incRef();
|
|
||||||
} else {
|
|
||||||
Luminaire::addChild(name, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParent(ConfigurableObject *parent) {
|
|
||||||
ConfigurableObject::setParent(parent);
|
|
||||||
|
|
||||||
if (parent->getClass()->derivesFrom(Shape::m_theClass)) {
|
|
||||||
m_shape = static_cast<Shape *>(parent);
|
|
||||||
parent->configure();
|
|
||||||
m_surfaceArea = m_shape->getSurfaceArea();
|
|
||||||
} else {
|
|
||||||
Log(EError, "A portal light source must be child of a shape instance");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void configure() {
|
|
||||||
m_power = Spectrum(0.0f);
|
|
||||||
if (m_luminaires.size() == 0)
|
|
||||||
Log(EError, "Portal luminaire must have one or more child luminaires!");
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i) {
|
|
||||||
m_luminaires[i]->configure();
|
|
||||||
m_power += m_luminaires[i]->getPower();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum getPower() const {
|
|
||||||
return m_power;
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum Le(const EmissionRecord &eRec) const {
|
|
||||||
Spectrum result(0.0f);
|
|
||||||
|
|
||||||
if (dot(eRec.d, eRec.sRec.n) <= 0)
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
|
||||||
result += m_luminaires[i]->Le(Ray(eRec.sRec.p, -eRec.d));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum Le(const LuminaireSamplingRecord &lRec) const {
|
|
||||||
Spectrum result(0.0f);
|
|
||||||
|
|
||||||
if (dot(lRec.d, lRec.sRec.n) <= 0)
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
|
|
||||||
for (size_t i=0; i<m_luminaires.size(); ++i)
|
|
||||||
result += m_luminaires[i]->Le(Ray(lRec.sRec.p, -lRec.d));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void sample(const Point &p, LuminaireSamplingRecord &lRec,
|
|
||||||
const Point2 &sample) const {
|
|
||||||
lRec.pdf = m_shape->sampleSolidAngle(lRec.sRec, p, sample);
|
|
||||||
lRec.d = p - lRec.sRec.p;
|
|
||||||
|
|
||||||
if (EXPECT_TAKEN(lRec.pdf > 0 && dot(lRec.d, lRec.sRec.n) > 0)) {
|
|
||||||
lRec.d = normalize(lRec.d);
|
|
||||||
lRec.Le = Le(lRec);
|
|
||||||
} else {
|
|
||||||
lRec.pdf = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void sample(const Intersection &its, LuminaireSamplingRecord &lRec,
|
|
||||||
const Point2 &sample) const {
|
|
||||||
PortalLuminaire::sample(its.p, lRec, sample);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Float pdf(const Point &p, const LuminaireSamplingRecord &lRec) const {
|
|
||||||
return m_shape->pdfSolidAngle(lRec.sRec, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
Float pdf(const Intersection &its, const LuminaireSamplingRecord &lRec) const {
|
|
||||||
return pdf(its.p, lRec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sampleEmission(EmissionRecord &eRec,
|
|
||||||
const Point2 &sample1, const Point2 &sample2) const {
|
|
||||||
eRec.pdfArea = m_shape->sampleArea(eRec.sRec, sample1);
|
|
||||||
Vector wo = squareToHemispherePSA(sample2);
|
|
||||||
eRec.pdfDir = Frame::cosTheta(wo) * INV_PI;
|
|
||||||
eRec.d = Frame(eRec.sRec.n).toWorld(wo);
|
|
||||||
eRec.P = Le(eRec);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sampleEmissionArea(EmissionRecord &eRec, const Point2 &sample) const {
|
|
||||||
eRec.pdfArea = m_shape->sampleArea(eRec.sRec, sample);
|
|
||||||
eRec.P = Spectrum(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum fArea(const EmissionRecord &eRec) const {
|
|
||||||
return Spectrum(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum sampleEmissionDirection(EmissionRecord &eRec, const Point2 &sample) const {
|
|
||||||
Vector wo = squareToHemispherePSA(sample);
|
|
||||||
eRec.d = Frame(eRec.sRec.n).toWorld(wo);
|
|
||||||
eRec.pdfDir = Frame::cosTheta(wo) * INV_PI;
|
|
||||||
return Le(eRec);
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum f(const EmissionRecord &eRec) const {
|
|
||||||
Float dp = dot(eRec.sRec.n, eRec.d);
|
|
||||||
if (dp > 0)
|
|
||||||
return Le(eRec);
|
|
||||||
else
|
|
||||||
return Spectrum(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pdfEmission(EmissionRecord &eRec) const {
|
|
||||||
Float dp = dot(eRec.sRec.n, eRec.d);
|
|
||||||
if (dp > 0)
|
|
||||||
eRec.pdfDir = dp * INV_PI;
|
|
||||||
else {
|
|
||||||
eRec.pdfDir = 0;
|
|
||||||
}
|
|
||||||
eRec.pdfArea = m_shape->pdfArea(eRec.sRec);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string toString() const {
|
|
||||||
return "PortalLuminaire[]";
|
|
||||||
}
|
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
|
||||||
private:
|
|
||||||
const Shape *m_shape;
|
|
||||||
Spectrum m_power;
|
|
||||||
std::vector<Luminaire *> m_luminaires;
|
|
||||||
};
|
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS_S(PortalLuminaire, false, Luminaire)
|
|
||||||
MTS_EXPORT_PLUGIN(PortalLuminaire, "Portal luminaire");
|
|
||||||
MTS_NAMESPACE_END
|
|
|
@ -488,7 +488,7 @@ void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) {
|
||||||
m_renderer->beginDrawingMeshes();
|
m_renderer->beginDrawingMeshes();
|
||||||
for (unsigned int j=0; j<meshes.size(); j++) {
|
for (unsigned int j=0; j<meshes.size(); j++) {
|
||||||
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
||||||
meshes[j]->getLuminaire(), camPos);
|
meshes[j]->getLuminaire(), camPos, !meshes[j]->hasVertexNormals());
|
||||||
m_renderer->drawTriMesh(meshes[j]);
|
m_renderer->drawTriMesh(meshes[j]);
|
||||||
m_shaderManager->unbind();
|
m_shaderManager->unbind();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue