Blender  V2.93
eevee_lights.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2016, Blender Foundation.
17  */
18 
23 #include "BLI_sys_types.h" /* bool */
24 
25 #include "BKE_object.h"
26 
27 #include "DEG_depsgraph_query.h"
28 
29 #include "eevee_private.h"
30 
31 /* Reconstruct local obmat from EEVEE_light. (normalized) */
32 void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4])
33 {
34  copy_v3_v3(r_mat[0], evli->rightvec);
35  copy_v3_v3(r_mat[1], evli->upvec);
36  negate_v3_v3(r_mat[2], evli->forwardvec);
37  copy_v3_v3(r_mat[3], evli->position);
38  r_mat[0][3] = 0.0f;
39  r_mat[1][3] = 0.0f;
40  r_mat[2][3] = 0.0f;
41  r_mat[3][3] = 1.0f;
42 }
43 
44 static float light_attenuation_radius_get(const Light *la,
45  float light_threshold,
46  float light_power)
47 {
48  if (la->mode & LA_CUSTOM_ATTENUATION) {
49  return la->att_dist;
50  }
51  /* Compute the distance (using the inverse square law)
52  * at which the light power reaches the light_threshold. */
53  return sqrtf(max_ff(1e-16, light_power / max_ff(1e-16, light_threshold)));
54 }
55 
56 static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, const float scale[3])
57 {
58  if (la->type == LA_SPOT) {
59  /* Spot size & blend */
60  evli->sizex = scale[0] / scale[2];
61  evli->sizey = scale[1] / scale[2];
62  evli->spotsize = cosf(la->spotsize * 0.5f);
63  evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
64  evli->radius = max_ff(0.001f, la->area_size);
65  }
66  else if (la->type == LA_AREA) {
67  evli->sizex = max_ff(0.003f, la->area_size * scale[0] * 0.5f);
69  evli->sizey = max_ff(0.003f, la->area_sizey * scale[1] * 0.5f);
70  }
71  else {
72  evli->sizey = max_ff(0.003f, la->area_size * scale[1] * 0.5f);
73  }
74  /* For volume point lighting. */
75  evli->radius = max_ff(0.001f, hypotf(evli->sizex, evli->sizey) * 0.5f);
76  }
77  else if (la->type == LA_SUN) {
78  evli->radius = max_ff(0.001f, tanf(min_ff(la->sun_angle, DEG2RADF(179.9f)) / 2.0f));
79  }
80  else {
81  evli->radius = max_ff(0.001f, la->area_size);
82  }
83 }
84 
85 static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
86 {
87  float power;
88  /* Make illumination power constant */
89  if (la->type == LA_AREA) {
90  power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
91  0.8f; /* XXX : Empirical, Fit cycles power */
93  /* Scale power to account for the lower area of the ellipse compared to the surrounding
94  * rectangle. */
95  power *= 4.0f / M_PI;
96  }
97  }
98  else if (ELEM(la->type, LA_SPOT, LA_LOCAL)) {
99  power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* 1/(4*r²*Pi²) */
100 
101  /* for point lights (a.k.a radius == 0.0) */
102  // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
103  }
104  else { /* LA_SUN */
105  power = 1.0f / (evli->radius * evli->radius * M_PI);
106  /* Make illumination power closer to cycles for bigger radii. Cycles uses a cos^3 term that we
107  * cannot reproduce so we account for that by scaling the light power. This function is the
108  * result of a rough manual fitting. */
109  power += 1.0f / (2.0f * M_PI); /* power *= 1 + r²/2 */
110  }
111  return power;
112 }
113 
114 static float light_shape_power_volume_get(const Light *la,
115  const EEVEE_Light *evli,
116  float area_power)
117 {
118  /* Volume light is evaluated as point lights. Remove the shape power. */
119  float power = 1.0f / area_power;
120 
121  if (la->type == LA_AREA) {
122  /* Match cycles. Empirical fit... must correspond to some constant. */
123  power *= 0.0792f * M_PI;
124  /* This corrects for area light most representative point trick. The fit was found by
125  * reducing the average error compared to cycles. */
126  float area = evli->sizex * evli->sizey;
127  float tmp = M_PI_2 / (M_PI_2 + sqrtf(area));
128  /* Lerp between 1.0 and the limit (1 / pi). */
129  power *= tmp + (1.0f - tmp) * M_1_PI;
130  }
131  else if (ELEM(la->type, LA_SPOT, LA_LOCAL)) {
132  /* Match cycles. Empirical fit... must correspond to some constant. */
133  power *= 0.0792f;
134  }
135  else { /* LA_SUN */
136  /* Nothing to do. */
137  }
138  return power;
139 }
140 
141 /* Update buffer with light data */
142 static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
143 {
144  const Light *la = (Light *)ob->data;
145  float mat[4][4], scale[3];
146 
147  const DRWContextState *draw_ctx = DRW_context_state_get();
148  const float light_threshold = draw_ctx->scene->eevee.light_threshold;
149 
150  /* Position */
151  copy_v3_v3(evli->position, ob->obmat[3]);
152 
153  /* Color */
154  copy_v3_v3(evli->color, &la->r);
155 
156  evli->diff = la->diff_fac;
157  evli->spec = la->spec_fac;
158  evli->volume = la->volume_fac;
159 
160  float max_power = max_fff(la->r, la->g, la->b) * fabsf(la->energy / 100.0f);
161  float surface_max_power = max_ff(evli->diff, evli->spec) * max_power;
162  float volume_max_power = evli->volume * max_power;
163 
164  /* Influence Radii. */
165  float att_radius = light_attenuation_radius_get(la, light_threshold, surface_max_power);
166  float att_radius_volume = light_attenuation_radius_get(la, light_threshold, volume_max_power);
167  /* Take the inverse square of this distance. */
168  evli->invsqrdist = 1.0f / max_ff(1e-4f, square_f(att_radius));
169  evli->invsqrdist_volume = 1.0f / max_ff(1e-4f, square_f(att_radius_volume));
170 
171  /* Vectors */
172  normalize_m4_m4_ex(mat, ob->obmat, scale);
173  copy_v3_v3(evli->forwardvec, mat[2]);
174  normalize_v3(evli->forwardvec);
175  negate_v3(evli->forwardvec);
176 
177  copy_v3_v3(evli->rightvec, mat[0]);
178  normalize_v3(evli->rightvec);
179 
180  copy_v3_v3(evli->upvec, mat[1]);
181  normalize_v3(evli->upvec);
182 
183  /* Make sure we have a consistent Right Hand coord frame.
184  * (in case of negatively scaled Z axis) */
185  float cross[3];
186  cross_v3_v3v3(cross, evli->rightvec, evli->forwardvec);
187  if (dot_v3v3(cross, evli->upvec) < 0.0) {
188  negate_v3(evli->upvec);
189  }
190 
191  light_shape_parameters_set(evli, la, scale);
192 
193  /* Light Type */
194  evli->light_type = (float)la->type;
195  if ((la->type == LA_AREA) && ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
197  }
198 
199  float shape_power = light_shape_power_get(la, evli);
200  mul_v3_fl(evli->color, shape_power * la->energy);
201 
202  evli->volume *= light_shape_power_volume_get(la, evli, shape_power);
203 
204  /* No shadow by default */
205  evli->shadow_id = -1.0f;
206 }
207 
209 {
210  EEVEE_LightsInfo *linfo = sldata->lights;
211  linfo->num_light = 0;
212 
213  EEVEE_shadows_cache_init(sldata, vedata);
214 }
215 
217 {
218  EEVEE_LightsInfo *linfo = sldata->lights;
219  const Light *la = (Light *)ob->data;
220 
221  if (linfo->num_light >= MAX_LIGHT) {
222  printf("Too many lights in the scene !!!\n");
223  return;
224  }
225 
226  /* Early out if light has no power. */
227  if (la->energy == 0.0f || is_zero_v3(&la->r)) {
228  return;
229  }
230 
231  EEVEE_Light *evli = linfo->light_data + linfo->num_light;
232  eevee_light_setup(ob, evli);
233 
234  if (la->mode & LA_SHADOW) {
235  if (la->type == LA_SUN) {
236  EEVEE_shadows_cascade_add(linfo, evli, ob);
237  }
238  else if (ELEM(la->type, LA_SPOT, LA_LOCAL, LA_AREA)) {
239  EEVEE_shadows_cube_add(linfo, evli, ob);
240  }
241  }
242 
243  linfo->num_light++;
244 }
245 
247 {
248  EEVEE_LightsInfo *linfo = sldata->lights;
249 
250  sldata->common_data.la_num_light = linfo->num_light;
251 
252  /* Clamp volume lights power. */
253  float upper_bound = vedata->stl->effects->volume_light_clamp;
254  for (int i = 0; i < linfo->num_light; i++) {
255  EEVEE_Light *evli = linfo->light_data + i;
256 
257  float power = max_fff(UNPACK3(evli->color)) * evli->volume;
258  if (power > 0.0f && evli->light_type != LA_SUN) {
259  /* The limit of the power attenuation function when the distance to the light goes to 0 is
260  * 2 / r² where r is the light radius. We need to find the right radius that emits at most
261  * the volume light upper bound. Inverting the function we get: */
262  float min_radius = 1.0f / sqrtf(0.5f * upper_bound / power);
263  /* Square it here to avoid a multiplication inside the shader. */
264  evli->volume_radius = square_f(max_ff(min_radius, evli->radius));
265  }
266  }
267 
268  GPU_uniformbuf_update(sldata->light_ubo, &linfo->light_data);
269 }
typedef float(TangentPoint)[2]
General operations, lookup, etc. for blender objects.
MINLINE float max_fff(float a, float b, float c)
#define M_1_PI
Definition: BLI_math_base.h:59
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
#define M_PI_2
Definition: BLI_math_base.h:41
MINLINE float square_f(float a)
#define M_PI
Definition: BLI_math_base.h:38
void normalize_m4_m4_ex(float R[4][4], const float M[4][4], float r_scale[3]) ATTR_NONNULL()
Definition: math_matrix.c:1963
#define DEG2RADF(_deg)
MINLINE float normalize_v3(float r[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
#define UNPACK3(a)
#define ELEM(...)
#define LA_AREA
#define LA_SPOT
#define LA_AREA_ELLIPSE
#define LA_SUN
#define LA_SHADOW
#define LA_LOCAL
#define LA_CUSTOM_ATTENUATION
#define LA_AREA_DISK
#define LA_AREA_RECT
void GPU_uniformbuf_update(GPUUniformBuf *ubo, const void *data)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
const DRWContextState * DRW_context_state_get(void)
static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
Definition: eevee_lights.c:142
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Definition: eevee_lights.c:246
void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
Definition: eevee_lights.c:216
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Definition: eevee_lights.c:208
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4])
Definition: eevee_lights.c:32
static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
Definition: eevee_lights.c:85
static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, const float scale[3])
Definition: eevee_lights.c:56
static float light_shape_power_volume_get(const Light *la, const EEVEE_Light *evli, float area_power)
Definition: eevee_lights.c:114
static float light_attenuation_radius_get(const Light *la, float light_threshold, float light_power)
Definition: eevee_lights.c:44
void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Definition: eevee_shadows.c:96
#define LAMPTYPE_AREA_ELLIPSE
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob)
void EEVEE_shadows_cascade_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob)
#define MAX_LIGHT
Definition: eevee_private.h:50
#define cosf(x)
#define tanf(x)
#define hypotf(x, y)
#define fabsf(x)
#define sqrtf(x)
static void area(int d1, int d2, int e1, int e2, float weights[2])
struct Scene * scene
Definition: DRW_render.h:745
EEVEE_StorageList * stl
float rightvec[3]
float color[3]
float forwardvec[3]
float upvec[3]
float light_type
float invsqrdist
float invsqrdist_volume
float volume_radius
float position[3]
struct EEVEE_Light light_data[MAX_LIGHT]
struct EEVEE_EffectsInfo * effects
struct EEVEE_CommonUniformBuffer common_data
struct GPUUniformBuf * light_ubo
struct EEVEE_LightsInfo * lights
float sun_angle
float r
float energy
float att_dist
float spec_fac
float area_sizey
short area_shape
float spotblend
float g
float spotsize
float area_size
float b
float volume_fac
short type
float diff_fac
float obmat[4][4]
void * data
float light_threshold
struct SceneEEVEE eevee
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119