YafaRay Core  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
spherelight.cc
Go to the documentation of this file.
1 /****************************************************************************
2  * spherelight.cc: a spherical area light source
3  * This is part of the yafray package
4  * Copyright (C) 2006 Mathias Wein
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20 
21 #include <core_api/light.h>
22 #include <core_api/surface.h>
23 #include <core_api/environment.h>
24 #include <core_api/object3d.h>
25 #include <utilities/sample_utils.h>
26 
28 
37 class sphereLight_t : public light_t
38 {
39  public:
40  sphereLight_t(const point3d_t &c, float rad, const color_t &col, float inte, int nsam, bool bLightEnabled=true, bool bCastShadows=true);
42  virtual void init(scene_t &scene);
43  virtual color_t totalEnergy() const;
44  virtual color_t emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const;
45  virtual color_t emitSample(vector3d_t &wo, lSample_t &s) const;
46  virtual bool diracLight() const { return false; }
47  virtual bool illumSample(const surfacePoint_t &sp, lSample_t &s, ray_t &wi) const;
48  virtual bool illuminate(const surfacePoint_t &sp, color_t &col, ray_t &wi)const { return false; }
49  virtual bool canIntersect() const{ return false; }
50  virtual bool intersect(const ray_t &ray, float &t, color_t &col, float &ipdf) const;
51  virtual float illumPdf(const surfacePoint_t &sp, const surfacePoint_t &sp_light) const;
52  virtual void emitPdf(const surfacePoint_t &sp, const vector3d_t &wo, float &areaPdf, float &dirPdf, float &cos_wo) const;
53  virtual int nSamples() const { return samples; }
54  static light_t *factory(paraMap_t &params, renderEnvironment_t &render);
55  protected:
59  int samples;
60  unsigned int objID;
61  float area, invArea;
62 };
63 
64 sphereLight_t::sphereLight_t(const point3d_t &c, float rad, const color_t &col, float inte, int nsam, bool bLightEnabled, bool bCastShadows):
65  center(c), radius(rad), samples(nsam)
66 {
67  lLightEnabled = bLightEnabled;
68  lCastShadows = bCastShadows;
69  color = col*inte;
71  square_radius_epsilon = square_radius * 1.000003815; // ~0.2% larger radius squared
72  area = square_radius * 4.0 * M_PI;
73  invArea = 1.f/area;
74 }
75 
77 
79 {
80  if(objID)
81  {
82  object3d_t *obj = scene.getObject(objID);
83  if(obj) obj->setLight(this);
84  else Y_ERROR << "SphereLight: Invalid object ID given!" << yendl;
85  }
86 }
87 
88 color_t sphereLight_t::totalEnergy() const { return color * area /* * M_PI */; }
89 
90 inline bool sphereIntersect(const ray_t &ray, const point3d_t &c, float R2, float &d1, float &d2)
91 {
92  vector3d_t vf=ray.from-c;
93  float ea=ray.dir*ray.dir;
94  float eb=2.0*vf*ray.dir;
95  float ec=vf*vf-R2;
96  float osc=eb*eb-4.0*ea*ec;
97  if(osc<0){ d1 = fSqrt(ec/ea); return false; } // assume tangential hit/miss condition => Pythagoras
98  osc=fSqrt(osc);
99  d1=(-eb-osc)/(2.0*ea);
100  d2=(-eb+osc)/(2.0*ea);
101  return true;
102 }
103 
105 {
106  if( photonOnly() ) return false;
107 
108  vector3d_t cdir = center - sp.P;
109  float dist_sqr = cdir.lengthSqr();
110  if(dist_sqr <= square_radius) return false; //only emit light on the outside!
111 
112  float dist = fSqrt(dist_sqr);
113  float idist_sqr = 1.f/(dist_sqr);
114  float cosAlpha = fSqrt(1.f - square_radius * idist_sqr);
115  cdir *= 1.f/dist;
116  vector3d_t du, dv;
117  createCS(cdir, du, dv);
118 
119  wi.dir = sampleCone(cdir, du, dv, cosAlpha, s.s1, s.s2);
120  float d1, d2;
121  if( !sphereIntersect(wi, center, square_radius_epsilon, d1, d2) )
122  {
123  return false;
124  }
125  wi.tmax = d1;
126 
127  s.pdf = 1.f / (2.f * (1.f - cosAlpha));
128  s.col = color;
129  s.flags = flags;
130  if(s.sp)
131  {
132  s.sp->P = wi.from + d1 * wi.dir;
133  s.sp->N = s.sp->Ng = (s.sp->P - center).normalize();
134  }
135  return true;
136 }
137 
138 bool sphereLight_t::intersect(const ray_t &ray, float &t, color_t &col, float &ipdf) const
139 {
140  float d1, d2;
141  if( sphereIntersect(ray, center, square_radius, d1, d2) )
142  {
143  vector3d_t cdir = center - ray.from;
144  float dist_sqr = cdir.lengthSqr();
145  if(dist_sqr <= square_radius) return false; //only emit light on the outside!
146  float idist_sqr = 1.f/(dist_sqr);
147  float cosAlpha = fSqrt(1.f - square_radius * idist_sqr);
148  ipdf = 2.f * (1.f - cosAlpha);
149  col = color;
150  return true;
151  }
152  return false;
153 }
154 
155 float sphereLight_t::illumPdf(const surfacePoint_t &sp, const surfacePoint_t &sp_light) const
156 {
157  vector3d_t cdir = center - sp.P;
158  float dist_sqr = cdir.lengthSqr();
159  if(dist_sqr <= square_radius) return 0.f; //only emit light on the outside!
160  float idist_sqr = 1.f/(dist_sqr);
161  float cosAlpha = fSqrt(1.f - square_radius * idist_sqr);
162  return 1.f / (2.f * (1.f - cosAlpha));
163 }
164 
165 void sphereLight_t::emitPdf(const surfacePoint_t &sp, const vector3d_t &wo, float &areaPdf, float &dirPdf, float &cos_wo) const
166 {
167  areaPdf = invArea * M_PI;
168  cos_wo = wo*sp.N;
170  dirPdf = cos_wo > 0 ? cos_wo : 0.f;
171 }
172 
173 color_t sphereLight_t::emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
174 {
175  vector3d_t sdir = SampleSphere(s3, s4);
176  ray.from = center + radius*sdir;
177  vector3d_t du, dv;
178  createCS(sdir, du, dv);
179  ray.dir = SampleCosHemisphere(sdir, du, dv, s1, s2);
180  ipdf = area;
181  return color;
182 }
183 
185 {
186  vector3d_t sdir = SampleSphere(s.s3, s.s4);
187  s.sp->P = center + radius * sdir;
188  s.sp->N = s.sp->Ng = sdir;
189  vector3d_t du, dv;
190  createCS(sdir, du, dv);
191  wo = SampleCosHemisphere(sdir, du, dv, s.s1, s.s2);
192  s.dirPdf = std::fabs(sdir * wo);
193  s.areaPdf = invArea * M_PI;
194  s.flags = flags;
195  return color;
196 }
197 
199 {
200  point3d_t from(0.0);
201  color_t color(1.0);
202  float power = 1.0;
203  float radius = 1.f;
204  int samples = 4;
205  int object = 0;
206  bool lightEnabled = true;
207  bool castShadows = true;
208  bool shootD = true;
209  bool shootC = true;
210  bool pOnly = false;
211 
212  params.getParam("from",from);
213  params.getParam("color",color);
214  params.getParam("power",power);
215  params.getParam("radius",radius);
216  params.getParam("samples",samples);
217  params.getParam("object", object);
218  params.getParam("light_enabled", lightEnabled);
219  params.getParam("cast_shadows", castShadows);
220  params.getParam("with_caustic", shootC);
221  params.getParam("with_diffuse", shootD);
222  params.getParam("photon_only",pOnly);
223 
224  sphereLight_t *light = new sphereLight_t(from, radius, color, power, samples, lightEnabled, castShadows);
225 
226  light->objID = (unsigned int)object;
227  light->lShootCaustic = shootC;
228  light->lShootDiffuse = shootD;
229  light->lPhotonOnly = pOnly;
230 
231  return light;
232 }
233 
234 extern "C"
235 {
237  {
238  render.registerFactory("spherelight", sphereLight_t::factory);
239  }
240 }
241 
vector3d_t dir
Definition: ray.h:19
bool lightEnabled() const
Enable/disable entire light source.
Definition: light.h:65
color_t color
includes intensity amplification! so...
Definition: spherelight.cc:58
virtual int nSamples() const
(preferred) number of samples for direct lighting
Definition: spherelight.cc:53
bool lShootCaustic
enable/disable if the light can shoot caustic photons (photonmap integrator)
Definition: light.h:85
virtual void registerFactory(const std::string &name, light_factory_t *f)
Definition: environment.cc:997
virtual float illumPdf(const surfacePoint_t &sp, const surfacePoint_t &sp_light) const
get the pdf for sampling the incoming direction wi at surface point sp (illumSample!) ...
Definition: spherelight.cc:155
float pdf
Definition: light.h:21
vector3d_t sampleCone(const vector3d_t &D, const vector3d_t &U, const vector3d_t &V, float maxCosAng, float s1, float s2)
uniformly sample a cone. Using doubles because for small cone angles the cosine is very close to one...
Definition: sample_utils.h:60
virtual void init(scene_t &scene)
allow for preprocessing when scene loading has finished
Definition: spherelight.cc:78
bool lCastShadows
enable/disable if the light should cast direct shadows
Definition: light.h:84
point3d_t center
Definition: spherelight.cc:56
unsigned int objID
Definition: spherelight.cc:60
LIGHTF_t flags
Definition: light.h:25
void createCS(const vector3d_t &N, vector3d_t &u, vector3d_t &v)
Definition: vector3d.h:337
float s2
Definition: light.h:19
LIGHTF_t flags
Definition: light.h:81
vector3d_t SampleCosHemisphere(const vector3d_t &N, const vector3d_t &Ru, const vector3d_t &Rv, float s1, float s2)
Sample a cosine-weighted hemisphere given the the coordinate system built by N, Ru, Rv.
Definition: sample_utils.h:25
float lengthSqr() const
Definition: vector3d.h:82
float s1
Definition: light.h:19
#define __BEGIN_YAFRAY
virtual bool canIntersect() const
indicate whether the light can intersect with a ray (by the intersect function)
Definition: spherelight.cc:49
float areaPdf
Definition: light.h:23
Definition: ray.h:11
bool castShadows() const
Definition: light.h:66
bool photonOnly() const
checks if the light is a photon-only light (only shoots photons, not illuminating) ...
Definition: light.h:72
virtual color_t emitSample(vector3d_t &wo, lSample_t &s) const
create a sample of light emission, similar to emitPhoton, just more suited for bidirectional methods ...
Definition: spherelight.cc:184
#define M_PI
Definition: vector3d.h:41
surfacePoint_t * sp
surface point on the light source, may only be complete enough to call other light methods with it! ...
Definition: light.h:26
Definition: scene.h:143
bool lLightEnabled
enable/disable light
Definition: light.h:83
bool lPhotonOnly
enable/disable if the light is a photon-only light (only shoots photons, not illuminating) ...
Definition: light.h:87
vector3d_t Ng
the geometric normal.
Definition: surface.h:71
#define YAFRAYPLUGIN_EXPORT
sphereLight_t(const point3d_t &c, float rad, const color_t &col, float inte, int nsam, bool bLightEnabled=true, bool bCastShadows=true)
Definition: spherelight.cc:64
Definition: color.h:49
virtual color_t totalEnergy() const
total energy emmitted during whole frame
Definition: spherelight.cc:88
Definition: light.h:29
virtual bool illumSample(const surfacePoint_t &sp, lSample_t &s, ray_t &wi) const
illuminate a given surface point, generating sample s, fill in s.sp if not nullptr; Set ray to test v...
Definition: spherelight.cc:104
virtual void emitPdf(const surfacePoint_t &sp, const vector3d_t &wo, float &areaPdf, float &dirPdf, float &cos_wo) const
get the pdf values for sampling point sp on the light and outgoing direction wo when emitting energy ...
Definition: spherelight.cc:165
YAFRAYPLUGIN_EXPORT void registerPlugin(renderEnvironment_t &render)
Definition: darksky.cc:378
float square_radius
Definition: spherelight.cc:57
bool sphereIntersect(const ray_t &ray, const point3d_t &c, float R2, float &d1, float &d2)
Definition: spherelight.cc:90
vector3d_t N
the shading normal.
Definition: surface.h:70
virtual bool diracLight() const
indicate whether the light has a dirac delta distribution or not
Definition: spherelight.cc:46
float tmax
Definition: ray.h:20
bool getParam(const std::string &name, T &val) const
template function to get a value, available types are those of parameter_t::getVal() ...
Definition: params.h:82
object3d_t * getObject(objID_t id) const
Definition: scene.cc:782
virtual color_t emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
emit a photon
Definition: spherelight.cc:173
vector3d_t SampleSphere(float s1, float s2)
Uniform sample a sphere.
Definition: sample_utils.h:38
virtual bool illuminate(const surfacePoint_t &sp, color_t &col, ray_t &wi) const
illuminate a given surfance point; Set ray to test visibility by integrator. Only for dirac lights...
Definition: spherelight.cc:48
static light_t * factory(paraMap_t &params, renderEnvironment_t &render)
Definition: spherelight.cc:198
float s3
Definition: light.h:20
virtual void setLight(const light_t *l)
Definition: object3d.h:45
point3d_t P
the (world) position.
Definition: surface.h:73
float s4
Definition: light.h:20
float fSqrt(float a)
float dirPdf
Definition: light.h:22
bool lShootDiffuse
enable/disable if the light can shoot diffuse photons (photonmap integrator)
Definition: light.h:86
virtual bool intersect(const ray_t &ray, float &t, color_t &col, float &ipdf) const
intersect the light source with a ray, giving back distance, energy and 1/PDF
Definition: spherelight.cc:138
point3d_t from
Definition: ray.h:18
float square_radius_epsilon
Definition: spherelight.cc:57
color_t col
Definition: light.h:24
#define __END_YAFRAY