YafaRay Core  v3.3.0-5-g3a98966
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
arealight.cc
Go to the documentation of this file.
1 /****************************************************************************
2  * arealight.cc: a rectangular 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/surface.h>
22 #include <core_api/object3d.h>
23 #include <lights/arealight.h>
24 #include <lights/meshlight.h>
25 #include <lights/bgportallight.h>
26 #include <utilities/sample_utils.h>
27 #include <iostream>
28 
30 
31 //int hit_t1=0, hit_t2=0;
32 
34  const color_t &col,float inte, int nsam, bool bLightEnabled, bool bCastShadows):
35  corner(c), toX(v1), toY(v2), samples(nsam), intensity(inte)
36 {
37  lLightEnabled = bLightEnabled;
38  lCastShadows = bCastShadows;
39 
40  fnormal = toY^toX; //f normal is "flipped" normal direction...
41  color = col*inte * M_PI;
42  area = fnormal.normLen();
43  invArea = 1.0/area;
44 
45  normal = -fnormal;
46  du = toX;
47  du.normalize();
48  dv = normal^du;
49  c2 = corner + toX;
50  c3 = corner + (toX + toY);
51  c4 = corner + toY;
52 }
53 
55 {
56  // Empty
57 }
58 
60 {
61  if(objID)
62  {
63  object3d_t *obj = scene.getObject(objID);
64  if(obj) obj->setLight(this);
65  else Y_WARNING << "AreaLight: Invalid object ID given!" << yendl;
66  }
67 }
68 
70 
72 {
73  if( photonOnly() ) return false;
74 
75  //get point on area light and vector to surface point:
76  point3d_t p = corner + s.s1*toX + s.s2*toY;
77  vector3d_t ldir = p - sp.P;
78  //normalize vec and compute inverse square distance
79  float dist_sqr = ldir.lengthSqr();
80  float dist = fSqrt(dist_sqr);
81  if(dist <= 0.0) return false;
82  ldir *= 1.f/dist;
83  float cos_angle = ldir*fnormal;
84  //no light if point is behind area light (single sided!)
85  if(cos_angle <= 0) return false;
86 
87  // fill direction
88  wi.tmax = dist;
89  wi.dir = ldir;
90 
91  s.col = color;
92  // pdf = distance^2 / area * cos(norm, ldir);
93  s.pdf = dist_sqr*M_PI / (area * cos_angle);
94  s.flags = LIGHT_NONE; // no delta functions...
95  if(s.sp)
96  {
97  s.sp->P = p;
98  s.sp->N = s.sp->Ng = normal;
99  }
100  return true;
101 }
102 
103 color_t areaLight_t::emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
104 {
105  ipdf = area/* * M_PI */; // really two pi?
106  ray.from = corner + s3*toX + s4*toY;
107  ray.dir = SampleCosHemisphere(normal, du, dv, s1, s2);
108  return color;
109 }
110 
112 {
113  s.areaPdf = invArea * M_PI;
114  s.sp->P = corner + s.s3*toX + s.s4*toY;
115  wo = SampleCosHemisphere(normal, du, dv, s.s1, s.s2);
116  s.sp->N = s.sp->Ng = normal;
117  s.dirPdf = std::fabs(normal * wo);
118  s.flags = LIGHT_NONE; // no delta functions...
119  return color; // still not 100% sure this is correct without cosine...
120 }
121 
122 inline bool triIntersect(const point3d_t &a, const point3d_t &b, const point3d_t &c, const ray_t &ray, float &t)
123 {
124  vector3d_t edge1, edge2, tvec, pvec, qvec;
125  float det, inv_det, u, v;
126  edge1 = b - a;
127  edge2 = c - a;
128  pvec = ray.dir ^ edge2;
129  det = edge1 * pvec;
130  if (det == 0.0) return false;
131  inv_det = 1.0 / det;
132  tvec = ray.from - a;
133  u = (tvec*pvec) * inv_det;
134  if (u < 0.0 || u > 1.0) return false;
135  qvec = tvec^edge1;
136  v = (ray.dir*qvec) * inv_det;
137  if ((v<0.0) || ((u+v)>1.0) ) return false;
138  t = edge2 * qvec * inv_det;
139 
140  return true;
141 }
142 
143 bool areaLight_t::intersect(const ray_t &ray, float &t, color_t &col, float &ipdf) const
144 {
145  float cos_angle = ray.dir*fnormal;
146  //no light if point is behind area light (single sided!)
147  if(cos_angle <= 0) return false;
148 
149  if(!triIntersect(corner, c2, c3, ray, t))
150  {
151  if(!triIntersect(corner, c3, c4, ray, t)) return false;
152  }
153  if( !(t > 1.0e-10f) ) return false;
154 
155  col = color;
156  // pdf = distance^2 / area * cos(norm, ldir); ipdf = 1/pdf;
157  ipdf = 1.f/(t*t) * area * cos_angle * M_1_PI;
158  return true;
159 }
160 
161 float areaLight_t::illumPdf(const surfacePoint_t &sp, const surfacePoint_t &sp_light) const
162 {
163  vector3d_t wi = sp_light.P - sp.P;
164  float r2 = wi.normLenSqr();
165  float cos_n = wi*fnormal;
166  return cos_n > 0 ? r2 * M_PI / (area * cos_n) : 0.f;
167 }
168 
169 void areaLight_t::emitPdf(const surfacePoint_t &sp, const vector3d_t &wo, float &areaPdf, float &dirPdf, float &cos_wo) const
170 {
171  areaPdf = invArea * M_PI;
172  cos_wo = wo*sp.N;
173  dirPdf = cos_wo > 0 ? cos_wo : 0.f;
174 }
175 
177 {
178  point3d_t corner(0.0);
179  point3d_t p1(0.0);
180  point3d_t p2(0.0);
181  color_t color(1.0);
182  float power = 1.0;
183  int samples = 4;
184  int object = 0;
185  bool lightEnabled = true;
186  bool castShadows = true;
187  bool shootD = true;
188  bool shootC = true;
189  bool pOnly = false;
190 
191  params.getParam("corner",corner);
192  params.getParam("point1",p1);
193  params.getParam("point2",p2);
194  params.getParam("color",color);
195  params.getParam("power",power);
196  params.getParam("samples",samples);
197  params.getParam("object", object);
198  params.getParam("light_enabled", lightEnabled);
199  params.getParam("cast_shadows", castShadows);
200  params.getParam("with_caustic", shootC);
201  params.getParam("with_diffuse", shootD);
202  params.getParam("photon_only",pOnly);
203 
204  areaLight_t *light = new areaLight_t(corner, p1-corner, p2-corner, color, power, samples, lightEnabled, castShadows);
205 
206  light->objID = (unsigned int)object;
207  light->lShootCaustic = shootC;
208  light->lShootDiffuse = shootD;
209  light->lPhotonOnly = pOnly;
210 
211  return light;
212 }
213 
214 extern "C"
215 {
216 
218  {
219  render.registerFactory("arealight", areaLight_t::factory);
220  render.registerFactory("bgPortalLight",bgPortalLight_t::factory);
221  render.registerFactory("meshlight", meshLight_t::factory);
222  }
223 
224 }
vector3d_t dir
Definition: ray.h:19
bool lightEnabled() const
Enable/disable entire light source.
Definition: light.h:65
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
float invArea
Definition: arealight.h:37
float pdf
Definition: light.h:21
virtual color_t emitPhoton(float s1, float s2, float s3, float s4, ray_t &ray, float &ipdf) const
emit a photon
Definition: arealight.cc:103
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: arealight.cc:161
bool lCastShadows
enable/disable if the light should cast direct shadows
Definition: light.h:84
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: arealight.cc:111
vector3d_t & normalize()
Definition: vector3d.h:267
LIGHTF_t flags
Definition: light.h:25
point3d_t c2
Definition: arealight.h:30
vector3d_t toY
Definition: arealight.h:31
virtual void init(scene_t &scene)
allow for preprocessing when scene loading has finished
Definition: arealight.cc:59
float s2
Definition: light.h:19
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
vector3d_t du
Definition: arealight.h:32
float s1
Definition: light.h:19
color_t color
includes intensity amplification! so...
Definition: arealight.h:33
#define __BEGIN_YAFRAY
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
#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
bool triIntersect(const point3d_t &a, const point3d_t &b, const point3d_t &c, const ray_t &ray, float &t)
Definition: arealight.cc:122
areaLight_t(const point3d_t &c, const vector3d_t &v1, const vector3d_t &v2, const color_t &col, float inte, int nsam, bool bLightEnabled=true, bool bCastShadows=true)
Definition: arealight.cc:33
#define YAFRAYPLUGIN_EXPORT
Definition: color.h:49
float area
Definition: arealight.h:37
Definition: light.h:29
point3d_t c4
Definition: arealight.h:30
virtual void emitPdf(const surfacePoint_t &sp, const vector3d_t &wi, 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: arealight.cc:169
float normLenSqr()
Definition: vector3d.h:72
YAFRAYPLUGIN_EXPORT void registerPlugin(renderEnvironment_t &render)
Definition: darksky.cc:378
unsigned int objID
Definition: arealight.h:35
vector3d_t dv
directions for hemisampler (emitting photons)
Definition: arealight.h:32
point3d_t c3
Definition: arealight.h:30
point3d_t corner
Definition: arealight.h:30
vector3d_t normal
Definition: arealight.h:31
vector3d_t N
the shading normal.
Definition: surface.h:70
float tmax
Definition: ray.h:20
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: arealight.cc:71
float normLen()
Definition: vector3d.h:61
static light_t * factory(paraMap_t &params, renderEnvironment_t &render)
Definition: arealight.cc:176
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
#define M_1_PI
virtual color_t totalEnergy() const
total energy emmitted during whole frame
Definition: arealight.cc:69
static light_t * factory(paraMap_t &params, renderEnvironment_t &render)
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
static light_t * factory(paraMap_t &params, renderEnvironment_t &render)
Definition: meshlight.cc:229
vector3d_t fnormal
Definition: arealight.h:31
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: arealight.cc:143
int samples
Definition: arealight.h:34
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
vector3d_t toX
Definition: arealight.h:31
point3d_t from
Definition: ray.h:18
color_t col
Definition: light.h:24
#define __END_YAFRAY