Blender  V3.3
eevee_shadows_cube.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. */
3 
8 #include "eevee_private.h"
9 
11 {
12  if (linfo->cube_len >= MAX_SHADOW_CUBE) {
13  return;
14  }
15 
16  const Light *la = (Light *)ob->data;
17  EEVEE_Shadow *sh_data = linfo->shadow_data + linfo->shadow_len;
18 
19  /* Always update dupli lights as EEVEE_LightEngineData is not saved.
20  * Same issue with dupli shadow casters. */
21  bool update = (ob->base_flag & BASE_FROM_DUPLI) != 0;
22  if (!update) {
24  if (led->need_update) {
25  update = true;
26  led->need_update = false;
27  }
28  }
29 
30  if (update) {
31  BLI_BITMAP_ENABLE(&linfo->sh_cube_update[0], linfo->cube_len);
32  }
33 
34  sh_data->near = max_ff(la->clipsta, 1e-8f);
35  sh_data->bias = max_ff(la->bias * 0.05f, 0.0f);
37 
38  /* Saving light bounds for later. */
39  BoundSphere *cube_bound = linfo->shadow_bounds + linfo->cube_len;
40  copy_v3_v3(cube_bound->center, evli->position);
41  cube_bound->radius = sqrt(1.0f / evli->invsqrdist);
42 
43  linfo->shadow_cube_light_indices[linfo->cube_len] = linfo->num_light;
44  evli->shadow_id = linfo->shadow_len++;
45  sh_data->type_data_id = linfo->cube_len++;
46 
47  /* Same as linfo->cube_len, no need to save. */
48  linfo->num_cube_layer++;
49 }
50 
52  int sample_ofs,
53  float ws_sample_pos[3])
54 {
55  float jitter[3];
56 #ifdef DEBUG_SHADOW_DISTRIBUTION
57  int i = 0;
58 start:
59 #else
60  int i = sample_ofs;
61 #endif
62  switch ((int)evli->light_type) {
63  case LA_AREA:
64  EEVEE_sample_rectangle(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
65  break;
66  case (int)LAMPTYPE_AREA_ELLIPSE:
67  EEVEE_sample_ellipse(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
68  break;
69  default:
70  EEVEE_sample_ball(i, evli->radius, jitter);
71  }
72 #ifdef DEBUG_SHADOW_DISTRIBUTION
73  float p[3];
74  add_v3_v3v3(p, jitter, ws_sample_pos);
75  DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
76  if (i++ < sample_ofs) {
77  goto start;
78  }
79 #endif
80  add_v3_v3(ws_sample_pos, jitter);
81 }
82 
83 bool EEVEE_shadows_cube_setup(EEVEE_LightsInfo *linfo, const EEVEE_Light *evli, int sample_ofs)
84 {
85  EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
86  EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + (int)shdw_data->type_data_id;
87 
88  eevee_light_matrix_get(evli, cube_data->shadowmat);
89 
90  shdw_data->far = max_ff(sqrt(1.0f / evli->invsqrdist), 3e-4);
91  shdw_data->near = min_ff(shdw_data->near, shdw_data->far - 1e-4);
92 
93  bool update = false;
94 
95  if (linfo->soft_shadows) {
96  shadow_cube_random_position_set(evli, sample_ofs, cube_data->shadowmat[3]);
97  /* Update if position changes (avoid infinite update if soft shadows does not move).
98  * Other changes are caught by depsgraph tagging. This one is for update between samples. */
99  update = !compare_v3v3(cube_data->shadowmat[3], cube_data->position, 1e-10f);
111  /* NOTE: this has implication for spotlight rendering optimization
112  * (see EEVEE_shadows_draw_cubemap). */
113  float angular_texel_size = 2.0f * DEG2RADF(90) / (float)linfo->shadow_cube_size;
114  EEVEE_random_rotation_m4(sample_ofs, angular_texel_size, cube_data->shadowmat);
115  }
116 
117  copy_v3_v3(cube_data->position, cube_data->shadowmat[3]);
118  invert_m4(cube_data->shadowmat);
119 
120  return update;
121 }
122 
124  float near, float far, int cube_res, const float viewmat[4][4], DRWView *view[6])
125 {
126  float winmat[4][4];
127  float side = near;
128 
129  /* TODO: shadow-cube array. */
130  if (true) {
131  /* This half texel offset is used to ensure correct filtering between faces. */
132  /* FIXME: This exhibit float precision issue with lower cube_res.
133  * But it seems to be caused by the perspective_m4. */
134  side *= ((float)cube_res + 1.0f) / (float)(cube_res);
135  }
136 
137  perspective_m4(winmat, -side, side, -side, side, near, far);
138 
139  for (int i = 0; i < 6; i++) {
140  float tmp[4][4];
141  mul_m4_m4m4(tmp, cubefacemat[i], viewmat);
142 
143  if (view[i] == NULL) {
144  view[i] = DRW_view_create(tmp, winmat, NULL, NULL, NULL);
145  }
146  else {
147  DRW_view_update(view[i], tmp, winmat, NULL, NULL);
148  }
149  }
150 }
151 
152 /* Does a spot angle fits a single cubeface. */
153 static bool spot_angle_fit_single_face(const EEVEE_Light *evli)
154 {
155  /* alpha = spot/cone half angle. */
156  /* beta = scaled spot/cone half angle. */
157  float cos_alpha = evli->spotsize;
158  float sin_alpha = sqrtf(max_ff(0.0f, 1.0f - cos_alpha * cos_alpha));
159  float cos_beta = min_ff(cos_alpha / hypotf(cos_alpha, sin_alpha * evli->sizex),
160  cos_alpha / hypotf(cos_alpha, sin_alpha * evli->sizey));
161  /* Don't use 45 degrees because AA jitter can offset the face. */
162  return cos_beta > cosf(DEG2RADF(42.0f));
163 }
164 
165 void EEVEE_shadows_draw_cubemap(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int cube_index)
166 {
167  EEVEE_PassList *psl = vedata->psl;
168  EEVEE_StorageList *stl = vedata->stl;
170  EEVEE_LightsInfo *linfo = sldata->lights;
171 
172  EEVEE_Light *evli = linfo->light_data + linfo->shadow_cube_light_indices[cube_index];
173  EEVEE_Shadow *shdw_data = linfo->shadow_data + (int)evli->shadow_id;
174  EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + (int)shdw_data->type_data_id;
175 
176  eevee_ensure_cube_views(shdw_data->near,
177  shdw_data->far,
178  linfo->shadow_cube_size,
179  cube_data->shadowmat,
180  g_data->cube_views);
181 
182  /* Render shadow cube */
183  /* Render 6 faces separately: seems to be faster for the general case.
184  * The only time it's more beneficial is when the CPU culling overhead
185  * outweigh the instancing overhead. which is rarely the case. */
186  for (int j = 0; j < 6; j++) {
187  /* Optimization: Only render the needed faces. */
188  /* Skip all but -Z face. */
189  if (evli->light_type == LA_SPOT && j != 5 && spot_angle_fit_single_face(evli)) {
190  continue;
191  }
192  /* Skip +Z face. */
193  if (evli->light_type != LA_LOCAL && j == 4) {
194  continue;
195  }
196  /* TODO(fclem): some cube sides can be invisible in the main views. Cull them. */
197  // if (frustum_intersect(g_data->cube_views[j], main_view))
198  // continue;
199 
200  DRW_view_set_active(g_data->cube_views[j]);
201  int layer = cube_index * 6 + j;
202  GPU_framebuffer_texture_layer_attach(sldata->shadow_fb, sldata->shadow_cube_pool, 0, layer, 0);
204  GPU_framebuffer_clear_depth(sldata->shadow_fb, 1.0f);
206  }
207 
208  BLI_BITMAP_SET(&linfo->sh_cube_update[0], cube_index, false);
209 }
typedef float(TangentPoint)[2]
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition: BLI_bitmap.h:102
sqrt(x)+1/max(0
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void perspective_m4(float mat[4][4], float left, float right, float bottom, float top, float nearClip, float farClip)
Definition: math_geom.c:4542
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
#define DEG2RADF(_deg)
MINLINE bool compare_v3v3(const float a[3], const float b[3], float limit) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
@ BASE_FROM_DUPLI
#define LA_AREA
#define LA_SPOT
#define LA_LOCAL
static AppView * view
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
BASIC_Shaders sh_data[GPU_SHADER_CFG_LEN]
Definition: basic_shader.c:33
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define cosf(x)
Definition: cuda/compat.h:101
void DRW_debug_sphere(const float center[3], const float radius, const float color[4])
Definition: draw_debug.c:111
DRWView * DRW_view_create(const float viewmat[4][4], const float winmat[4][4], const float(*culling_viewmat)[4], const float(*culling_winmat)[4], DRWCallVisibilityFn *visibility_fn)
void DRW_view_update(DRWView *view, const float viewmat[4][4], const float winmat[4][4], const float(*culling_viewmat)[4], const float(*culling_winmat)[4])
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
static struct @318 g_data
EEVEE_LightEngineData * EEVEE_light_data_ensure(Object *ob)
Definition: eevee_data.c:342
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4])
Definition: eevee_lights.c:16
void EEVEE_sample_ellipse(int sample_ofs, const float x_axis[3], const float y_axis[3], float size_x, float size_y, float rsample[3])
#define LAMPTYPE_AREA_ELLIPSE
void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4])
#define MAX_SHADOW_CUBE
Definition: eevee_private.h:39
void EEVEE_sample_ball(int sample_ofs, float radius, float rsample[3])
static const float cubefacemat[6][4][4]
void EEVEE_sample_rectangle(int sample_ofs, const float x_axis[3], const float y_axis[3], float size_x, float size_y, float rsample[3])
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh)
Definition: eevee_shadows.c:19
static void eevee_ensure_cube_views(float near, float far, int cube_res, const float viewmat[4][4], DRWView *view[6])
bool EEVEE_shadows_cube_setup(EEVEE_LightsInfo *linfo, const EEVEE_Light *evli, int sample_ofs)
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, Object *ob)
static bool spot_angle_fit_single_face(const EEVEE_Light *evli)
static void shadow_cube_random_position_set(const EEVEE_Light *evli, int sample_ofs, float ws_sample_pos[3])
void EEVEE_shadows_draw_cubemap(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, int cube_index)
void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip)
#define hypotf(x, y)
Definition: metal/compat.h:226
#define sqrtf(x)
Definition: metal/compat.h:243
static void update(bNodeTree *ntree)
float center[3]
Definition: DRW_render.h:86
float radius
Definition: DRW_render.h:86
EEVEE_StorageList * stl
EEVEE_PassList * psl
float rightvec[3]
float upvec[3]
float light_type
float invsqrdist
float position[3]
struct EEVEE_Light light_data[MAX_LIGHT]
struct EEVEE_Shadow shadow_data[MAX_SHADOW]
struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE]
struct BoundSphere shadow_bounds[MAX_LIGHT]
BLI_bitmap sh_cube_update[BLI_BITMAP_SIZE(MAX_SHADOW_CUBE)]
uchar shadow_cube_light_indices[MAX_SHADOW_CUBE]
struct DRWPass * shadow_pass
float type_data_id
struct EEVEE_PrivateData * g_data
struct GPUTexture * shadow_cube_pool
struct GPUFrameBuffer * shadow_fb
struct EEVEE_LightsInfo * lights
float clipsta
float bias
short base_flag
void * data