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/collimated', ['src/luminaires/collimated.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/directional', ['src/luminaires/directional.cpp'])
|
||||
plugins += env.SharedLibrary('plugins/portal', ['src/luminaires/portal.cpp'])
|
||||
|
||||
# Integrators
|
||||
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'.
|
||||
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
|
||||
void drawBackground(const Transform &clipToWorld, const Point &camPos);
|
||||
|
@ -171,7 +171,7 @@ private:
|
|||
|
||||
struct VPLProgramConfiguration {
|
||||
VPLDependencyNode vpl, bsdf, luminaire;
|
||||
bool hasLuminaire;
|
||||
bool hasLuminaire, faceNormals;
|
||||
int param_shadowMap, param_vplPos, param_camPos, param_vplPower;
|
||||
int param_vplN, param_vplS, param_vplT, param_vplWi, param_vplUV;
|
||||
int param_nearClip, param_invClipRange, param_minDist;
|
||||
|
@ -179,8 +179,8 @@ private:
|
|||
|
||||
inline VPLProgramConfiguration() { }
|
||||
|
||||
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire)
|
||||
: vpl(vpl), bsdf(bsdf), luminaire(luminaire) {
|
||||
inline VPLProgramConfiguration(Shader *vpl, Shader *bsdf, Shader *luminaire, bool faceNormals)
|
||||
: vpl(vpl), bsdf(bsdf), luminaire(luminaire), faceNormals(faceNormals) {
|
||||
hasLuminaire = (luminaire != NULL);
|
||||
}
|
||||
|
||||
|
@ -224,6 +224,8 @@ private:
|
|||
oss << ", luminaire=";
|
||||
luminaire.toString(oss);
|
||||
}
|
||||
if (faceNormals)
|
||||
oss << ", faceNormals";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ public:
|
|||
m_renderer->beginDrawingMeshes();
|
||||
for (unsigned int j=0; j<meshes.size(); j++) {
|
||||
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
||||
meshes[j]->getLuminaire(), camPos);
|
||||
meshes[j]->getLuminaire(), camPos,
|
||||
!meshes[j]->hasVertexNormals());
|
||||
m_renderer->drawTriMesh(meshes[j]);
|
||||
m_shaderManager->unbind();
|
||||
}
|
||||
|
|
|
@ -97,8 +97,17 @@ int GLProgram::createShader(int type, const std::string &source) {
|
|||
glGetObjectParameterivARB(id, GL_COMPILE_STATUS, &result);
|
||||
if (result == GL_FALSE) {
|
||||
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 != "")
|
||||
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
|
||||
Log(EError, "Unknown error encountered while compiling a shader!");
|
||||
} else if (infoLog != "") {
|
||||
|
|
|
@ -281,7 +281,7 @@ void VPLShaderManager::setVPL(const VPL &vpl) {
|
|||
}
|
||||
|
||||
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 *vplShader = (vpl.type == ELuminaireVPL)
|
||||
? m_renderer->getShaderForResource(vpl.luminaire)
|
||||
|
@ -300,7 +300,8 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
|
|||
|
||||
bool anisotropic = bsdf->getType() & BSDF::EAnisotropicMaterial;
|
||||
|
||||
m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader, lumShader);
|
||||
m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader,
|
||||
lumShader, faceNormals);
|
||||
m_targetConfig.toString(oss);
|
||||
std::string configName = oss.str();
|
||||
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 */
|
||||
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 */
|
||||
oss.str("");
|
||||
oss << "#version 120" << endl;
|
||||
if (anisotropic)
|
||||
oss << "varying vec3 tangent;" << endl;
|
||||
if (!faceNormals)
|
||||
oss << "varying vec3 normal;" << endl;
|
||||
oss << "uniform vec3 vplPos, camPos;" << endl;
|
||||
|
||||
oss << "uniform vec3 vplPos, camPos;" << endl
|
||||
<< "varying vec3 normal, lightVec, camVec;" << endl
|
||||
<< "varying vec2 uv;" << endl
|
||||
<< "varying vec3 vertexColor;" << endl
|
||||
<< endl
|
||||
<< "void main() {" << endl
|
||||
<< " normal = gl_Normal;" << endl
|
||||
<< " uv = gl_MultiTexCoord0.xy;" << endl
|
||||
<< " camVec = camPos - gl_Vertex.xyz;" << endl
|
||||
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl
|
||||
<< " gl_Position = ftransform();" << endl
|
||||
<< " vertexColor = gl_Color.rgb;" << endl;
|
||||
if (!faceNormals) {
|
||||
oss << "varying vec3 lightVec, camVec;" << endl
|
||||
<< "varying vec2 uv;" << endl
|
||||
<< "varying vec3 vertexColor;" << endl
|
||||
<< endl
|
||||
<< "void main() {" << endl
|
||||
<< " uv = gl_MultiTexCoord0.xy;" << endl
|
||||
<< " camVec = camPos - gl_Vertex.xyz;" << endl
|
||||
<< " lightVec = vplPos - gl_Vertex.xyz;" << endl
|
||||
<< " gl_Position = ftransform();" << 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)
|
||||
oss << " tangent = gl_MultiTexCoord1.xyz;" << endl;
|
||||
oss << "}" << endl;
|
||||
|
|
|
@ -52,14 +52,14 @@ void Intersection::computePartials(const RayDifferential &ray) {
|
|||
A[0][1] = dpdv[axes[0]];
|
||||
A[1][0] = dpdu[axes[1]];
|
||||
A[1][1] = dpdv[axes[1]];
|
||||
|
||||
|
||||
/* Auxilary intersection point of the adjacent rays */
|
||||
Point px = ray.rx(tx), py = ray.ry(ty);
|
||||
Bx[0] = px[axes[0]] - p[axes[0]];
|
||||
Bx[1] = px[axes[1]] - p[axes[1]];
|
||||
By[0] = py[axes[0]] - p[axes[0]];
|
||||
By[1] = py[axes[1]] - p[axes[1]];
|
||||
|
||||
|
||||
if (EXPECT_TAKEN(solveLinearSystem2x2(A, Bx, x))) {
|
||||
dudx = x[0]; dvdx = x[1];
|
||||
} else {
|
||||
|
|
|
@ -312,7 +312,11 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe
|
|||
&p1 = positions[idx1],
|
||||
&p2 = positions[idx2];
|
||||
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)) {
|
||||
|
@ -369,9 +373,13 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe
|
|||
its.p.x = secRay4.o[0].f[idx];
|
||||
its.p.y = secRay4.o[1].f[idx];
|
||||
its.p.z = secRay4.o[2].f[idx];
|
||||
its.shFrame.s = normalize(its.dpdu - its.shFrame.n
|
||||
* dot(its.shFrame.n, its.dpdu));
|
||||
its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
|
||||
if (EXPECT_NOT_TAKEN(bsdf->getType() & BSDF::EAnisotropicMaterial)) {
|
||||
its.shFrame.s = normalize(its.dpdu - its.shFrame.n
|
||||
* dot(its.shFrame.n, its.dpdu));
|
||||
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];
|
||||
wi = normalize(wi);
|
||||
|
||||
|
|
|
@ -252,7 +252,8 @@ void TriMesh::configure() {
|
|||
for (size_t i=0; i<m_vertexCount; i++)
|
||||
m_bsphere.expandBy(m_positions[i]);
|
||||
computeNormals();
|
||||
if (m_bsdf->getType() & BSDF::EAnisotropicMaterial && !m_tangents)
|
||||
if ((m_bsdf->getType() & BSDF::EAnisotropicMaterial
|
||||
|| m_bsdf->usesRayDifferentials()) && !m_tangents)
|
||||
computeTangentSpaceBasis();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class ConstantLuminaire : public Luminaire {
|
|||
public:
|
||||
ConstantLuminaire(const Properties &props) : Luminaire(props) {
|
||||
m_intensity = props.getSpectrum("intensity", Spectrum(1.0f));
|
||||
m_type = EOnSurface;
|
||||
m_type = EOnSurface | EDiffuseDirection;
|
||||
}
|
||||
|
||||
ConstantLuminaire(Stream *stream, InstanceManager *manager)
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
Spectrum Le(const LuminaireSamplingRecord &lRec) const {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,6 @@ public:
|
|||
|
||||
Spectrum f(const EmissionRecord &eRec) const {
|
||||
/* Directional luminaire beam is not part of the scene */
|
||||
Log(EWarn, "This function should never be called.");
|
||||
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();
|
||||
for (unsigned int j=0; j<meshes.size(); j++) {
|
||||
m_shaderManager->configure(vpl, meshes[j]->getBSDF(),
|
||||
meshes[j]->getLuminaire(), camPos);
|
||||
meshes[j]->getLuminaire(), camPos, !meshes[j]->hasVertexNormals());
|
||||
m_renderer->drawTriMesh(meshes[j]);
|
||||
m_shaderManager->unbind();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue