YafaRay Core  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
bglight.cc
Go to the documentation of this file.
1 /****************************************************************************
2  * bglight.cc: a light source using the background
3  * This is part of the yafaray package
4  * Copyright (C) 2006 Mathias Wein (Lynx)
5  * Copyright (C) 2009 Rodrigo Placencia (DarkTide)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 
22 #include <lights/bglight.h>
23 #include <core_api/background.h>
24 #include <core_api/texture.h>
25 #include <utilities/sample_utils.h>
26 
28 
29 #define MAX_VSAMPLES 360
30 #define MAX_USAMPLES 720
31 #define MIN_SAMPLES 16
32 
33 #define SMPL_OFF 0.4999f
34 
35 #define sigma 0.000001f
36 
37 #define addOff(v) (v + SMPL_OFF)
38 #define clampSample(s, m) std::max(0, std::min((int)(s), m - 1))
39 
40 #define multPdf(p0, p1) (p0 * p1)
41 #define calcPdf(p0, p1, s) std::max( sigma, multPdf(p0, p1) * (float)M_1_2PI * clampZero(sinSample(s)) )
42 #define calcInvPdf(p0, p1, s) std::max( sigma, (float)M_2PI * sinSample(s) * clampZero(multPdf(p0, p1)) )
43 
44 inline float clampZero(float val)
45 {
46  if(val > 0.f) return 1.f / val;
47  else return 0.f;
48 }
49 
50 inline float sinSample(float s)
51 {
52  return fSin(s * M_PI);
53 }
54 
55 bgLight_t::bgLight_t(int sampl, bool absIntersect, bool bLightEnabled, bool bCastShadows):
56 light_t(LIGHT_NONE), samples(sampl), absInter(absIntersect)
57 {
58  lLightEnabled = bLightEnabled;
59  lCastShadows = bCastShadows;
60  background = nullptr;
61  uDist = nullptr;
62  vDist = nullptr;
63 }
64 
66 {
67  for(int i = 0; i < vDist->count; i++) delete uDist[i];
68  if(uDist) delete[] uDist;
69  uDist = nullptr;
70  if(vDist) delete vDist;
71  vDist = nullptr;
72 }
73 
75 {
76  float *fu = new float[MAX_USAMPLES];
77  float *fv = new float[MAX_VSAMPLES];
78  float inu = 0, inv = 0;
79  float fx = 0.f, fy = 0.f;
80  float sintheta = 0.f;
81  int nu = 0, nv = MAX_VSAMPLES;
82 
83  ray_t ray;
84  ray.from = point3d_t(0.f);
85 
86  inv = 1.f / (float)nv;
87 
88  uDist = new pdf1D_t*[nv];
89 
90  for (int y = 0; y < nv; y++)
91  {
92  fy = ((float)y + 0.5f) * inv;
93 
94  sintheta = sinSample(fy);
95 
96  nu = MIN_SAMPLES + (int)(sintheta * (MAX_USAMPLES - MIN_SAMPLES));
97  inu = 1.f / (float)nu;
98 
99  for(int x = 0; x < nu; x++)
100  {
101  fx = ((float)x + 0.5f) * inu;
102 
103  invSpheremap(fx, fy, ray.dir);
104 
105  fu[x] = background->eval(ray, true).energy() * sintheta;
106  }
107 
108  uDist[y] = new pdf1D_t(fu, nu);
109 
110  fv[y] = uDist[y]->integral;
111  }
112 
113  vDist = new pdf1D_t(fv, nv);
114 
115  delete[] fv;
116  delete[] fu;
117 
118  bound_t w=scene.getSceneBound();
119  worldCenter = 0.5 * (w.a + w.g);
120  worldRadius = 0.5 * (w.g - w.a).length();
122  iaPdf = 1.f / aPdf;
123  worldPIFactor = (M_2PI * aPdf);
124 }
125 
126 inline float bgLight_t::CalcFromSample(float s1, float s2, float &u, float &v, bool inv) const
127 {
128  int iv;
129  float pdf1 = 0.f, pdf2 = 0.f;
130 
131  v = vDist->Sample(s2, &pdf2);
132 
133  iv = clampSample(addOff(v), vDist->count);
134 
135  u = uDist[iv]->Sample(s1, &pdf1);
136 
137  u *= uDist[iv]->invCount;
138  v *= vDist->invCount;
139 
140  if(inv)return calcInvPdf(pdf1, pdf2, v);
141 
142  return calcPdf(pdf1, pdf2, v);
143 }
144 
145 inline float bgLight_t::CalcFromDir(const vector3d_t &dir, float &u, float &v, bool inv) const
146 {
147  int iv, iu;
148  float pdf1 = 0.f, pdf2 = 0.f;
149 
150  spheremap(dir, u, v); // Returns u,v pair in [0,1] range
151 
152  iv = clampSample(addOff(v * vDist->count), vDist->count);
153  iu = clampSample(addOff(u * uDist[iv]->count), uDist[iv]->count);
154 
155  pdf1 = uDist[iv]->func[iu] * uDist[iv]->invIntegral;
156  pdf2 = vDist->func[iv] * vDist->invIntegral;
157 
158  if(inv)return calcInvPdf(pdf1, pdf2, v);
159 
160  return calcPdf(pdf1, pdf2, v);
161 
162 }
163 
164 void bgLight_t::sample_dir(float s1, float s2, vector3d_t &dir, float &pdf, bool inv) const
165 {
166  float u = 0.f, v = 0.f;
167 
168  pdf = CalcFromSample(s1, s2, u, v, inv);
169 
170  invSpheremap(u, v, dir);
171 }
172 
173 // dir points from surface point to background
174 float bgLight_t::dir_pdf(const vector3d_t dir) const
175 {
176  float u = 0.f, v = 0.f;
177 
178  return CalcFromDir(dir, u, v);
179 }
180 
181 bool bgLight_t::illumSample(const surfacePoint_t &sp, lSample_t &s, ray_t &wi) const
182 {
183  if( photonOnly() ) return false;
184 
185  float u = 0.f, v = 0.f;
186  vector3d_t U, V;
187 
188  wi.tmax = -1.0;
189 
190  s.pdf = CalcFromSample(s.s1, s.s2, u, v, false);
191 
192  invSpheremap(u, v, wi.dir);
193 
194  s.col = background->eval(wi, true);
195 
196  return true;
197 }
198 
199 bool bgLight_t::intersect(const ray_t &ray, float &t, color_t &col, float &ipdf) const
200 {
201  float u = 0.f, v = 0.f;
202  ray_t tr = ray;
203  vector3d_t absDir = tr.dir;
204 
205  if(absInter) absDir = -absDir;
206 
207  ipdf = CalcFromDir(absDir, u, v, true);
208 
209  invSpheremap(u, v, tr.dir);
210 
211  col = background->eval(tr, true);
212 
213  col.clampProportionalRGB(lClampIntersect); //trick to reduce light sampling noise at the expense of realism and inexact overall light. 0.f disables clamping
214 
215  return true;
216 }
217 
219 {
220  color_t energy = background->eval(ray_t(point3d_t(0,0,0), vector3d_t(0.5, 0.5, 0.5)), true) * worldPIFactor;
221  return energy;
222 }
223 
224 color_t bgLight_t::emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
225 {
226  color_t pcol;
227  vector3d_t U, V;
228  vector3d_t offs;
229  float u, v;
230 
231  sample_dir(s3, s4, ray.dir, ipdf, true);
232 
233  pcol = background->eval(ray, true);
234  ray.dir = -ray.dir;
235 
236  createCS(ray.dir, U, V);
237  ShirleyDisk(s1, s2, u, v);
238 
239  offs = u*U + v*V;
240 
241  ray.from = worldCenter + worldRadius*(offs - ray.dir);
242 
243  return pcol * aPdf;
244 }
245 
247 {
248  color_t pcol;
249  vector3d_t U, V;
250  vector3d_t offs;
251  float u, v;
252 
253  sample_dir(s.s1, s.s2, wo, s.dirPdf, true);
254 
255  pcol = background->eval(ray_t(point3d_t(0,0,0), wo), true);
256  wo = -wo;
257 
258  createCS(wo, U, V);
259  ShirleyDisk(s.s1, s.s2, u, v);
260 
261  offs = u*U + v*V;
262 
263  s.sp->P = worldCenter + worldRadius*offs - worldRadius*wo;
264  s.sp->N = s.sp->Ng = wo;
265  s.areaPdf = 1.f;
266  s.flags = flags;
267 
268  return pcol;
269 }
270 
271 float bgLight_t::illumPdf(const surfacePoint_t &sp, const surfacePoint_t &sp_light) const
272 {
273  vector3d_t dir = (sp_light.P - sp.P).normalize();
274  return dir_pdf(dir);
275 }
276 
277 void bgLight_t::emitPdf(const surfacePoint_t &sp, const vector3d_t &wo, float &areaPdf, float &dirPdf, float &cos_wo) const
278 {
279  vector3d_t wi = wo;
280  wi.normalize();
281  cos_wo = wi.z;
282  wi = -wi;
283  dirPdf = dir_pdf(wi);
284  areaPdf = 1.f;
285 }
286 
288 {
289  int samples = 16;
290  bool shootD = true;
291  bool shootC = true;
292  bool absInt = false;
293  bool lightEnabled = true;
294  bool castShadows = true;
295  bool pOnly = false;
296 
297  params.getParam("samples", samples);
298  params.getParam("with_caustic", shootC);
299  params.getParam("with_diffuse", shootD);
300  params.getParam("abs_intersect", absInt);
301  params.getParam("light_enabled", lightEnabled);
302  params.getParam("cast_shadows", castShadows);
303  params.getParam("photon_only",pOnly);
304 
305  bgLight_t *light = new bgLight_t(samples, absInt, lightEnabled, castShadows);
306 
307  light->lShootCaustic = shootC;
308  light->lShootDiffuse = shootD;
309  light->lPhotonOnly = pOnly;
310 
311  return light;
312 }
313 
314 extern "C"
315 {
317  {
318  render.registerFactory("bglight", bgLight_t::factory);
319  }
320 }
321 
323 
point3d_t g
Definition: bound.h:134
vector3d_t dir
Definition: ray.h:19
bool lightEnabled() const
Enable/disable entire light source.
Definition: light.h:65
point3d_t worldCenter
Definition: bglight.h:58
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 ~bgLight_t()
Definition: bglight.cc:65
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: bglight.cc:246
float pdf
Definition: light.h:21
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: bglight.cc:271
bool lCastShadows
enable/disable if the light should cast direct shadows
Definition: light.h:84
vector3d_t & normalize()
Definition: vector3d.h:267
LIGHTF_t flags
Definition: light.h:25
void invSpheremap(float u, float v, vector3d_t &p)
Definition: texture.h:105
pdf1D_t * vDist
Definition: bglight.h:56
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
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: bglight.cc:199
float s1
Definition: light.h:19
#define addOff(v)
Definition: bglight.cc:37
#define __BEGIN_YAFRAY
float areaPdf
Definition: light.h:23
float integral
Definition: sample_utils.h:143
float sinSample(float s)
Definition: bglight.cc:50
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
#define MAX_USAMPLES
Definition: bglight.cc:30
#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
virtual void init(scene_t &scene)
allow for preprocessing when scene loading has finished
Definition: bglight.cc:74
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
void spheremap(const point3d_t &p, float &u, float &v)
Definition: texture.h:85
float fSin(float x)
float worldRadius
Definition: bglight.h:59
#define YAFRAYPLUGIN_EXPORT
Definition: color.h:49
YAFRAYCORE_EXPORT void ShirleyDisk(float r1, float r2, float &u, float &v)
Definition: vector3d.cc:155
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: bglight.cc:181
bgLight_t(int sampl, bool invertIntersect=false, bool bLightEnabled=true, bool bCastShadows=true)
Definition: bglight.cc:55
#define MIN_SAMPLES
Definition: bglight.cc:31
Definition: light.h:29
void sample_dir(float s1, float s2, vector3d_t &dir, float &pdf, bool inv=false) const
Definition: bglight.cc:164
float lClampIntersect
trick to reduce light sampling noise at the expense of realism and inexact overall light...
Definition: light.h:88
#define MAX_VSAMPLES
Definition: bglight.cc:29
Definition: bound.h:50
bool absInter
Definition: bglight.h:62
float CalcFromSample(float s1, float s2, float &u, float &v, bool inv=false) const
Definition: bglight.cc:126
pdf1D_t ** uDist
Definition: bglight.h:56
#define M_2PI
YAFRAYPLUGIN_EXPORT void registerPlugin(renderEnvironment_t &render)
Definition: darksky.cc:378
float z
Definition: vector3d.h:92
static light_t * factory(paraMap_t &params, renderEnvironment_t &render)
Definition: bglight.cc:287
float Sample(float u, float *pdf) const
Definition: sample_utils.h:107
background_t * background
Definition: light.h:82
float worldPIFactor
Definition: bglight.h:61
float dir_pdf(const vector3d_t dir) const
Definition: bglight.cc:174
vector3d_t N
the shading normal.
Definition: surface.h:70
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
virtual color_t totalEnergy() const
total energy emmitted during whole frame
Definition: bglight.cc:218
void clampProportionalRGB(float maxValue)
Definition: color.h:477
float invIntegral
Definition: sample_utils.h:143
#define calcInvPdf(p0, p1, s)
Definition: bglight.cc:42
float clampZero(float val)
Definition: bglight.cc:44
point3d_t a
Two points define the box.
Definition: bound.h:134
float energy() const
Definition: color.h:81
#define calcPdf(p0, p1, s)
Definition: bglight.cc:41
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: bglight.cc:277
point3d_t P
the (world) position.
Definition: surface.h:73
virtual color_t eval(const ray_t &ray, bool from_postprocessed=false) const =0
#define clampSample(s, m)
Definition: bglight.cc:38
int samples
Definition: bglight.h:57
float iaPdf
Definition: bglight.h:60
bound_t getSceneBound() const
Definition: scene.cc:798
float invCount
Definition: sample_utils.h:143
float CalcFromDir(const vector3d_t &dir, float &u, float &v, bool inv=false) const
Definition: bglight.cc:145
float dirPdf
Definition: light.h:22
virtual color_t emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
emit a photon
Definition: bglight.cc:224
bool lShootDiffuse
enable/disable if the light can shoot diffuse photons (photonmap integrator)
Definition: light.h:86
point3d_t from
Definition: ray.h:18
color_t col
Definition: light.h:24
float aPdf
Definition: bglight.h:60
float * func
Definition: sample_utils.h:142
#define __END_YAFRAY