started a new branch for a material development cycle. new features: glass preview in the VPL renderer, more documentation

metadata
Wenzel Jakob 2011-07-03 02:46:09 +02:00
parent 8fec5a4d87
commit 5cc7e40df2
16 changed files with 267 additions and 84 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -43,22 +43,16 @@
}
\newcommand{\renderings}[1]{
\begin{figure}[h]
\begin{figure}[h!]
\centering
\hfill
#1
\end{figure}
}
\newcommand{\rendering}[2]{
\subfigure[#1]{\fbox{\includegraphics[width=0.4\textwidth]{images/#2}}}
\hfill
}
\newcommand{\smallrendering}[2]{
\subfigure[#1]{\fbox{\includegraphics[width=0.2\textwidth]{images/#2}}}
\hfill
}
\newcommand{\rendering}[2]{\subfigure[#1]{\fbox{\includegraphics[width=0.4\textwidth]{images/#2}}}\hfill}
\newcommand{\medrendering}[2]{ \subfigure[#1]{\fbox{\includegraphics[width=0.3\textwidth]{images/#2}}}\hfill}
\newcommand{\smallrendering}[2]{ \subfigure[#1]{\fbox{\includegraphics[width=0.2\textwidth]{images/#2}}}\hfill}
\newcommand{\parameter}[3]{
\small\texttt{#1} & \small #2 & \small #3\\

View File

@ -159,7 +159,7 @@ public:
void setColorMask(bool value);
/// Set the current fixed-function pipeline color
void setColor(const Spectrum &spec);
void setColor(const Spectrum &spec, Float alpha = 1.0f);
/// Push a view transformation onto the matrix stack
void pushTransform(const Transform &trafo);

View File

@ -207,7 +207,7 @@ public:
virtual void setColorMask(bool value) = 0;
/// Set the current fixed-function pipeline color
virtual void setColor(const Spectrum &spec) = 0;
virtual void setColor(const Spectrum &spec, Float alpha = 1.0f) = 0;
/// Push a view transformation onto the matrix stack
virtual void pushTransform(const Transform &trafo) = 0;

View File

@ -25,15 +25,17 @@
MTS_NAMESPACE_BEGIN
/**
* This class is responsible for the on-demand creation of
* GPU shaders to render meshes with a particular material
* illuminated by a virtual point light source. For each
* encountered BSDF-VPL pair, a custom piece of code describing
* the characteristic light transport between them is created
* \brief This class is responsible for the on-demand creation of
* GPU shaders to render meshes that are illuminated by a virtual
* point light source.
*
* For each encountered BSDF-VPL pair, a custom piece of code
* describing the characteristic light transport between them is created
* and cached. To avoid generating a potentially huge (N squared)
* number of very similar programs, the implementation passes some
* properties using uniforms, in which case already existing code
* can be reused and we get something more like lower case n squared.
* can be reused and we get something more like lower case n squared
* (where lower n is the number of material types).
*/
class MTS_EXPORT_HW VPLShaderManager : public Object {
public:
@ -55,9 +57,12 @@ public:
/// Release bound resources
void unbind();
/// Return all bound triangle meshes
/// Return all bound opaque triangle meshes
inline const std::vector<std::pair<const TriMesh *, Transform> > &getMeshes() const { return m_meshes; }
/// Return all bound transparent triangle meshes
inline const std::vector<std::pair<const TriMesh *, Transform> > &getTransparentMeshes() const { return m_transparentMeshes; }
/// Return the shadow cube map for debugging purposes
inline GPUTexture *getShadowMap() { return m_shadowMap; }
@ -178,7 +183,7 @@ private:
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;
int param_diffuseSources, param_diffuseReceivers;
int param_diffuseSources, param_diffuseReceivers, param_alpha;
inline VPLProgramConfiguration() { }
@ -272,6 +277,7 @@ private:
ref<GPUProgram> m_backgroundProgram;
VPLDependencyNode m_backgroundDependencies;
std::vector<std::pair<const TriMesh *, Transform> > m_meshes;
std::vector<std::pair<const TriMesh *, Transform> > m_transparentMeshes;
std::vector<std::pair<const GPUGeometry *, Transform> > m_drawList;
};

View File

@ -28,10 +28,12 @@ class Renderer;
class GPUProgram;
/**
* Abstract hardware resource -- provides support for functionality,
* which can alternatively also live on the GPU. By default, the
* method 'createShader' just returns NULL, which means that the
* BSDF/Light source/Texture/.. cannot be used with a GPU-based renderer.
* \brief Abstract hardware resource.
*
* Implementations provides support for functionality that are also able to
* live on the GPU. By default, the method 'createShader' just returns \c NULL,
* which means that the BSDF/Light source/Texture/.. has not yet been ported
* to the GPU-based renderer.
*/
class MTS_EXPORT_RENDER HWResource {
public:
@ -41,8 +43,10 @@ public:
};
/**
* Shader base class for use with a VPL-style renderer. Could implement
* one of various things, such as a BSDF, a light source, or a texture.
* \brief Shader base class for use with a VPL-style renderer.
*
* Subclasses can implement one of various things, such as a BSDF,
* a light source, or a texture.
*/
class MTS_EXPORT_RENDER Shader : public Object {
public:
@ -52,59 +56,65 @@ public:
ELuminaireShader
};
/**
* Return the type of shader represented by this instance
*/
enum EFlags {
ETransparent = 0x01
};
// Return the type of shader represented by this instance
inline EShaderType getType() const { return m_type; }
/**
* List other shaders, on which this instance depends
*/
/// Return a list of flags
inline uint32_t getFlags() const { return m_flags; }
// List other shaders, on which this instance depends
virtual void putDependencies(std::vector<Shader *> &deps);
/**
* Is this shader complete? This is mainly useful to
* check whether all dependencies could be constructed
* successfully. The default implementation returns true
* \brief Is this shader complete?
*
* This is mainly useful to check whether all dependencies
* could be constructed successfully. The default
* implementation returns \c true.
*/
virtual bool isComplete() const;
/**
* Generate a string version of this shader's evaluation
* routine. The appended string should assign the name
* 'evalName' to this function. The function names of
* depedencies (as specified by 'putDependencies'), are
* supplied in the parameter 'depNames' in identical order.
* \brief Generate a string version of this shader's evaluation
* routine.
*
* The appended string should assign the name \c evalName to this
* function. The function names of depedencies (as specified by
* \ref putDependencies), are supplied in the parameter \c depNames
* in identical order.
*/
virtual void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const = 0;
/**
* This function can optionally be implemented to resolve named
* \brief This function can optionally be implemented to resolve named
* program parameters to numerical IDs for increased performance.
* The int array returned here will later be passed to bind().
*
* The int array returned here will later be passed to \ref bind().
* The default implementation does nothing.
*/
virtual void resolve(const GPUProgram *program, const std::string &evalName,
std::vector<int> &parameterIDs) const;
/**
* Configure the the associated GPU program. This
* function is typically used to bind textures and
* \brief Configure the the associated GPU program.
*
* This function is typically used to bind textures and
* to set program pararameters.
*/
virtual void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const;
/**
* Release any bound resources.
*/
/// Release any bound resources.
virtual void unbind() const;
/**
* Release all resources
*/
/// Release all resources
virtual void cleanup(Renderer *renderer);
MTS_DECLARE_CLASS()
@ -113,8 +123,9 @@ protected:
/// Virtual destructor
virtual ~Shader();
private:
protected:
EShaderType m_type;
uint32_t m_flags;
};
MTS_NAMESPACE_END

View File

@ -21,7 +21,7 @@
MTS_NAMESPACE_BEGIN
/*! \plugin{dielectric}{Ideal dielectric/glass material}
/*! \plugin{dielectric}{Smooth dielectric material}
*
* \parameters{
* \parameter{intIOR}{\Float}{Interior index of refraction \default{1.5046}}
@ -32,21 +32,59 @@ MTS_NAMESPACE_BEGIN
* factor used to modulate the transmittance component\default{1.0}}
* }
*
* This plugin models an interface between two materials having mismatched
* indices of refraction (e.g. a boundary between water and air).
* The microscopic surface structure of the surface is assumed to be perfectly
* smooth, resulting in a degenerate BSDF described by a Dirac delta function.
* For non-smooth interfaces, please take a look at the \pluginref{roughglass}
* model. When using this plugin, it is crucial that the scene contains
* meaningful and mutally compatible index of refraction change -- see
* \figref{glass-explanation} for an example.
* \renderings{
* \medrendering{Air-Water (IOR: 1$\leftrightarrow$1.33) interface, see \lstref{dielectric-water}}{bsdf_dielectric_water}
* \medrendering{Air-Diamond (IOR: 1$\leftrightarrow$2.419)}{bsdf_dielectric_diamond}
* \medrendering{Air-Glass (1$\leftrightarrow$1.504) interface with absorption, see \lstref{dielectric-glass}}{bsdf_dielectric_glass}
* }
*
* This plugin models an interface between two dielectric materials having mismatched
* indices of refraction (for instance, water and air). Exterior and interior IOR values
* can each be independently specified, where ``exterior'' refers to the side that contains
* the surface normal. When no parameters are given, the plugin activates the defaults, which
* describe a borosilicate glass BK7/air interface.
*
* In this model, the microscopic surface structure of the surface is assumed to be perfectly
* smooth, resulting in a degenerate\footnote{Meaning that for any given incoming ray of light,
* the model always scatters into a discrete set of directions, as opposed to a continuum.}
* BSDF described by a Dirac delta function. For a similar model that describes a rough
* surface microstructure, take a look at the \pluginref{roughglass} plugin.
*
* \begin{xml}[caption=A simple air-to-water interface, label=lst:dielectric-water]
* <shape type="...">
* <bsdf type="dielectric">
* <float name="intIOR" value="1.33"/>
* <float name="extIOR" value="1.0"/>
* </bsdf>
* <shape>
* \end{xml}
*
* When using this model, it is crucial that the scene contains
* meaningful and mutally compatible indices of refraction changes---see
* \figref{glass-explanation} for a description of what this entails.
*
* In many cases, we will want to additionally describe the \emph{medium} within a
* dielectric material. This requires the use of a rendering technique that is
* aware of media (e.g. the volumetric path tracer). An example of how one might
* describe a slightly absorbing piece of glass is given below:
*
* \begin{xml}[caption=A glass material with absorption, label=lst:dielectric-glass]
* <shape type="...">
* <bsdf type="dielectric">
* <float name="intIOR" value="1.504"/>
* <float name="extIOR" value="1.0"/>
* </bsdf>
* <medium type="homogeneous" name="interior">
* <rgb name="sigmaS" value="0, 0, 0"/>
* <rgb name="sigmaA" value="4, 4, 2"/>
* </medium>
* <shape>
* \end{xml}
*
* The default settings of this plugin are set to a borosilicate glass BK7/air
* interface.
*/
class Dielectric : public BSDF {
class SmoothDielectric : public BSDF {
public:
Dielectric(const Properties &props)
SmoothDielectric(const Properties &props)
: BSDF(props) {
/* Specifies the internal index of refraction at the interface */
m_intIOR = props.getFloat("intIOR", 1.5046f);
@ -66,7 +104,7 @@ public:
m_usesRayDifferentials = false;
}
Dielectric(Stream *stream, InstanceManager *manager)
SmoothDielectric(Stream *stream, InstanceManager *manager)
: BSDF(stream, manager) {
m_intIOR = stream->readFloat();
m_extIOR = stream->readFloat();
@ -81,7 +119,7 @@ public:
m_usesRayDifferentials = false;
}
virtual ~Dielectric() {
virtual ~SmoothDielectric() {
delete[] m_type;
}
@ -339,7 +377,7 @@ public:
std::string toString() const {
std::ostringstream oss;
oss << "Dielectric[" << endl
oss << "SmoothDielectric[" << endl
<< " intIOR = " << m_intIOR << "," << endl
<< " extIOR = " << m_extIOR << "," << endl
<< " specularReflectance = " << indent(m_specularReflectance->toString()) << "," << endl
@ -348,6 +386,8 @@ public:
return oss.str();
}
Shader *createShader(Renderer *renderer) const;
MTS_DECLARE_CLASS()
private:
Float m_intIOR, m_extIOR;
@ -355,7 +395,34 @@ private:
ref<Texture> m_specularReflectance;
};
/* Fake glass shader -- it is really hopeless to visualize
this material in the VPL renderer, so let's try to do at least
something that suggests the presence of a transparent boundary */
class SmoothDielectricShader : public Shader {
public:
SmoothDielectricShader(Renderer *renderer) :
Shader(renderer, EBSDFShader) {
m_flags = ETransparent;
}
MTS_IMPLEMENT_CLASS_S(Dielectric, false, BSDF)
MTS_EXPORT_PLUGIN(Dielectric, "Dielectric BSDF");
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " return vec3(0.08);" << endl
<< "}" << endl;
oss << "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " return vec3(0.08);" << endl
<< "}" << endl;
}
MTS_DECLARE_CLASS()
};
Shader *SmoothDielectric::createShader(Renderer *renderer) const {
return new SmoothDielectricShader(renderer);
}
MTS_IMPLEMENT_CLASS(SmoothDielectricShader, false, Shader)
MTS_IMPLEMENT_CLASS_S(SmoothDielectric, false, BSDF)
MTS_EXPORT_PLUGIN(SmoothDielectric, "Smooth dielectric BSDF");
MTS_NAMESPACE_END

View File

@ -23,7 +23,7 @@
MTS_NAMESPACE_BEGIN
/*! \plugin{roughglass}{Rough dielectric/glass material}
/*! \plugin{roughglass}{Rough dielectric material}
* \parameters{
* \parameter{distribution}{\String}{
* Specifies the type of microfacet normal distribution
@ -58,13 +58,19 @@ MTS_NAMESPACE_BEGIN
* factor used to modulate the transmittance component\default{1.0}}
* }
*
* \renderings{
* \medrendering{Beckmann, $\alpha$=0.2}{bsdf_dielectric_glass}
* \medrendering{Beckmann, $\alpha$=0.3}{bsdf_dielectric_glass}
* \medrendering{Beckmann, $\alpha$=0.4}{bsdf_dielectric_glass}
* }
*
* This plugin implements a realistic microfacet scattering model for rendering
* rough dielectric surfaces, such as ground glass. Microfacet theory
* describes surfaces as an arrangement of unresolved and ideally specular
* rough interfaces between dielectric materials, such as a transition from air to ground glass.
* Microfacet theory describes surfaces as an arrangement of unresolved and ideally specular
* facets, whose normals are given by a specially chosen \emph{microfacet
* distribution}. By accounting for shadowing and masking effects between
* these facets, it is possible to reproduce the off-specular reflections
* peaks observed in measurements of real-world materials.
* peaks observed in real-world measurements of such materials.
*
* This plugin is essentially the ``roughened'' equivalent of the plugin
* \pluginref{dielectric}. Its implementation is based on the paper
@ -95,7 +101,7 @@ public:
m_specularReflectance = new ConstantSpectrumTexture(
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
m_specularTransmittance = new ConstantSpectrumTexture(
props.getSpectrum("specularTransmittance", Spectrum(1.9f)));
props.getSpectrum("specularTransmittance", Spectrum(1.0f)));
Float alpha;
if (props.hasProperty("alphaB")) {
@ -763,6 +769,8 @@ public:
return oss.str();
}
Shader *createShader(Renderer *renderer) const;
MTS_DECLARE_CLASS()
private:
EDistribution m_distribution;
@ -772,6 +780,34 @@ private:
Float m_intIOR, m_extIOR;
};
/* Fake glass shader -- it is really hopeless to visualize
this material in the VPL renderer, so let's try to do at least
something that suggests the presence of a transparent boundary */
class RoughGlassShader : public Shader {
public:
RoughGlassShader(Renderer *renderer) :
Shader(renderer, EBSDFShader) {
m_flags = ETransparent;
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "vec3 " << evalName << "(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " return vec3(0.08);" << endl
<< "}" << endl;
oss << "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
<< " return vec3(0.08);" << endl
<< "}" << endl;
}
MTS_DECLARE_CLASS()
};
Shader *RoughGlass::createShader(Renderer *renderer) const {
return new RoughGlassShader(renderer);
}
MTS_IMPLEMENT_CLASS(RoughGlassShader, false, Shader)
MTS_IMPLEMENT_CLASS_S(RoughGlass, false, BSDF)
MTS_EXPORT_PLUGIN(RoughGlass, "Rough glass BSDF");
MTS_NAMESPACE_END

View File

@ -54,6 +54,7 @@ public:
/// Draw the full scene using additive blending and shadow maps
void drawShadowedScene(const Scene *scene, const VPL &vpl) {
const std::vector<std::pair<const TriMesh *, Transform> > meshes = m_shaderManager->getMeshes();
const std::vector<std::pair<const TriMesh *, Transform> > transpMeshes = m_shaderManager->getTransparentMeshes();
const ProjectiveCamera *camera = static_cast<const ProjectiveCamera *>(scene->getCamera());
Point2 jitter(0.5f - m_random->nextFloat(), 0.5f - m_random->nextFloat());
Transform projectionTransform = camera->getGLProjectionTransform(jitter);
@ -75,7 +76,29 @@ public:
m_shaderManager->unbind();
}
m_renderer->endDrawingMeshes();
m_shaderManager->drawBackground(clipToWorld, camPos, 1.0f);
if (transpMeshes.size() > 0) {
m_renderer->setDepthMask(false);
m_renderer->setBlendMode(Renderer::EBlendAlpha);
m_renderer->beginDrawingMeshes();
for (unsigned int j=0; j<transpMeshes.size(); j++) {
const TriMesh *mesh = transpMeshes[j].first;
bool hasTransform = !transpMeshes[j].second.isIdentity();
m_shaderManager->configure(vpl, mesh->getBSDF(), mesh->getLuminaire(),
camPos, !mesh->hasVertexNormals());
if (hasTransform)
m_renderer->pushTransform(transpMeshes[j].second);
m_renderer->drawTriMesh(mesh);
if (hasTransform)
m_renderer->popTransform();
m_shaderManager->unbind();
}
m_renderer->endDrawingMeshes();
m_renderer->setDepthMask(true);
m_renderer->setBlendMode(Renderer::EBlendNone);
}
}
bool preprocess(const Scene *scene, RenderQueue *queue, const RenderJob *job,

View File

@ -742,9 +742,11 @@ void GLRenderer::blitQuad(bool flipVertically) {
glGetIntegerv(GL_VIEWPORT, viewport);
Vector2 scrSize((float) viewport[2], (float) viewport[3]);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, scrSize.x, scrSize.y, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
const Float zDepth = -1.0f;
glBegin(GL_QUADS);
@ -757,6 +759,9 @@ void GLRenderer::blitQuad(bool flipVertically) {
glTexCoord2f(0.0f, flipVertically ? 0.0f : 1.0f);
glVertex3f(0.0f, scrSize.y, zDepth);
glEnd();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
void GLRenderer::drawText(const Point2i &_pos,
@ -966,10 +971,10 @@ void GLRenderer::finish() {
m_queuedTriangles = 0;
}
void GLRenderer::setColor(const Spectrum &spec) {
void GLRenderer::setColor(const Spectrum &spec, Float alpha) {
Float r, g, b;
spec.toLinearRGB(r, g, b);
glColor4f(r, g, b, 1);
glColor4f(r, g, b, alpha);
}
void GLRenderer::setBlendMode(EBlendMode mode) {

View File

@ -55,7 +55,7 @@ void VPLShaderManager::init() {
"varying float depth;\n"
"\n"
"void main() {\n"
" depth = 0;\n" // avoid a (incorrect?) warning
" depth = 0;\n" // avoid an (incorrect?) warning
" for (int side = 0; side < 6; side++) {\n"
" gl_Layer = side;\n"
" for (int i = 0; i < gl_VerticesIn; i++) {\n"
@ -118,7 +118,7 @@ void VPLShaderManager::init() {
const std::vector<Shape *> shapes = m_scene->getShapes();
const std::vector<Luminaire *> luminaires = m_scene->getLuminaires();
for (size_t i=0; i<shapes.size(); ++i) {
ref<TriMesh> triMesh = shapes[i]->createTriMesh();
if (!triMesh) {
@ -134,8 +134,12 @@ void VPLShaderManager::init() {
GPUGeometry *gpuGeo = m_renderer->registerGeometry(triMesh);
Shader *shader = triMesh->hasBSDF() ?
m_renderer->registerShaderForResource(triMesh->getBSDF()) : NULL;
if (shader != NULL && !shader->isComplete())
if (shader != NULL && !shader->isComplete()) {
m_renderer->unregisterShaderForResource(triMesh->getBSDF());
} else if (shader->getFlags() & Shader::ETransparent) {
m_transparentMeshes.push_back(std::make_pair(triMesh.get(), instance->getWorldTransform()));
continue;
}
m_meshes.push_back(std::make_pair(triMesh.get(), instance->getWorldTransform()));
if (gpuGeo)
m_drawList.push_back(std::make_pair(gpuGeo, instance->getWorldTransform()));
@ -146,8 +150,12 @@ void VPLShaderManager::init() {
GPUGeometry *gpuGeo = m_renderer->registerGeometry(triMesh);
Shader *shader = triMesh->hasBSDF() ?
m_renderer->registerShaderForResource(triMesh->getBSDF()) : NULL;
if (shader != NULL && !shader->isComplete())
if (shader != NULL && !shader->isComplete()) {
m_renderer->unregisterShaderForResource(triMesh->getBSDF());
} else if (shader->getFlags() & Shader::ETransparent) {
m_transparentMeshes.push_back(std::make_pair(triMesh.get(), Transform()));
continue;
}
m_meshes.push_back(std::make_pair(triMesh.get(), Transform()));
if (gpuGeo)
m_drawList.push_back(std::make_pair(gpuGeo, Transform()));
@ -353,7 +361,6 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
: m_renderer->getShaderForResource(luminaire);
std::ostringstream oss;
if (bsdfShader == NULL || vplShader == NULL ||
(luminaire != NULL && lumShader == NULL)) {
/* Unsupported! */
@ -361,6 +368,13 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
return;
}
#if 0
if (bsdfShader->getFlags() & Shader::ETransparent) {
m_renderer->setColor(Spectrum(1.0f), 0.3f);
return;
}
#endif
bool anisotropic = bsdf->getType() & BSDF::EAnisotropic;
m_targetConfig = VPLProgramConfiguration(vplShader, bsdfShader,
@ -464,7 +478,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
<< "/* Uniform inputs */" << endl
<< "uniform samplerCube shadowMap;" << endl
<< "uniform vec3 vplPower, vplS, vplT, vplN, vplWi;" << endl
<< "uniform float nearClip, invClipRange, minDist;" << endl
<< "uniform float nearClip, invClipRange, minDist, alpha;" << endl
<< "uniform vec2 vplUV;" << endl
<< "uniform bool diffuseSources, diffuseReceivers;" << endl
<< "varying vec3 vertexColor;" << endl
@ -546,7 +560,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
} else {
oss << ";" << endl;
}
oss << " gl_FragColor.a = 1.0;" << endl
oss << " gl_FragColor.a = alpha;" << endl
<< "}" << endl;
program->setSource(GPUProgram::EFragmentProgram, oss.str());
@ -572,6 +586,7 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
m_targetConfig.param_minDist = program->getParameterID("minDist", false);
m_targetConfig.param_diffuseSources = program->getParameterID("diffuseSources", false);
m_targetConfig.param_diffuseReceivers = program->getParameterID("diffuseReceivers", false);
m_targetConfig.param_alpha = program->getParameterID("alpha", false);
m_current.program = program;
m_current.config = m_targetConfig;
m_programs[configName] = m_current;
@ -589,11 +604,16 @@ void VPLShaderManager::configure(const VPL &vpl, const BSDF *bsdf,
program->setParameter(config.param_vplN, vpl.its.shFrame.n);
program->setParameter(config.param_vplS, vpl.its.shFrame.s);
program->setParameter(config.param_vplT, vpl.its.shFrame.t);
program->setParameter(config.param_alpha,
bsdfShader->getFlags() & Shader::ETransparent ? 0.5f : 1.0f);
if (vpl.type == ESurfaceVPL) {
program->setParameter(config.param_vplWi, vpl.its.wi);
program->setParameter(config.param_vplUV, vpl.its.uv);
program->setParameter(config.param_diffuseSources, m_diffuseSources);
}
Spectrum power = vpl.P;
if (m_diffuseSources && vpl.type == ESurfaceVPL)
power *= vpl.its.shape->getBSDF()->getDiffuseReflectance(vpl.its) * INV_PI;

View File

@ -21,7 +21,7 @@
MTS_NAMESPACE_BEGIN
Shader::Shader(Renderer *renderer, EShaderType type)
: m_type(type) {
: m_type(type), m_flags(0) {
}
Shader::~Shader() {

View File

@ -473,6 +473,7 @@ void PreviewThread::run() {
void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) {
const std::vector<std::pair<const TriMesh *, Transform> > meshes = m_shaderManager->getMeshes();
const std::vector<std::pair<const TriMesh *, Transform> > transpMeshes = m_shaderManager->getTransparentMeshes();
m_shaderManager->setVPL(vpl);
@ -510,6 +511,26 @@ void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) {
m_renderer->endDrawingMeshes();
m_shaderManager->drawBackground(clipToWorld, camPos,
m_backgroundScaleFactor);
if (transpMeshes.size() > 0) {
m_renderer->setDepthMask(false);
m_renderer->setBlendMode(Renderer::EBlendAlpha);
m_renderer->beginDrawingMeshes();
for (size_t j=0; j<transpMeshes.size(); j++) {
const TriMesh *mesh = transpMeshes[j].first;
bool hasTransform = !transpMeshes[j].second.isIdentity();
m_shaderManager->configure(vpl, mesh->getBSDF(),
mesh->getLuminaire(), camPos, !mesh->hasVertexNormals());
if (hasTransform)
m_renderer->pushTransform(transpMeshes[j].second);
m_renderer->drawTriMesh(mesh);
if (hasTransform)
m_renderer->popTransform();
m_shaderManager->unbind();
}
m_renderer->endDrawingMeshes();
m_renderer->setBlendMode(Renderer::EBlendNone);
m_renderer->setDepthMask(true);
}
m_framebuffer->releaseTarget();
target.buffer->activateTarget();