started a new branch for a material development cycle. new features: glass preview in the VPL renderer, more documentation
parent
8fec5a4d87
commit
5cc7e40df2
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 |
|
@ -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\\
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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> ¶meterIDs) 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> ¶meterIDs,
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
Shader::Shader(Renderer *renderer, EShaderType type)
|
||||
: m_type(type) {
|
||||
: m_type(type), m_flags(0) {
|
||||
}
|
||||
|
||||
Shader::~Shader() {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue