Blender  V3.3
eevee_subsurface.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2016 Blender Foundation. */
3 
10 #include "DRW_render.h"
11 
12 #include "BLI_string_utils.h"
13 
14 #include "DEG_depsgraph_query.h"
15 
16 #include "GPU_capabilities.h"
17 #include "GPU_material.h"
18 #include "GPU_texture.h"
19 
20 #include "eevee_private.h"
21 
23 {
24 }
25 
27 {
28  EEVEE_EffectsInfo *effects = vedata->stl->effects;
29  EEVEE_StorageList *stl = vedata->stl;
30  EEVEE_FramebufferList *fbl = vedata->fbl;
31  EEVEE_TextureList *txl = vedata->txl;
33  const float *viewport_size = DRW_viewport_size_get();
34  const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
35 
36  if (effects->enabled_effects & EFFECT_SSS) {
37  /* NOTE: we need another stencil because the stencil buffer is on the same texture
38  * as the depth buffer we are sampling from. This could be avoided if the stencil is
39  * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
40  * OR OpenGL 4.3 / ARB_ES3_compatibility if using a render-buffer instead. */
42  fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8, &draw_engine_eevee_type);
44  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
46  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
48  fs_size[0], fs_size[1], GPU_R16F, &draw_engine_eevee_type);
50  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
51 
52  GPUTexture *stencil_tex = effects->sss_stencil;
53 
55  /* Blitting stencil buffer does not work on macOS + Radeon Pro.
56  * Blit depth instead and use sss_stencil's depth as depth texture,
57  * and dtxl->depth as stencil mask. */
58  GPU_framebuffer_ensure_config(
59  &fbl->sss_blit_fb, {GPU_ATTACHMENT_TEXTURE(effects->sss_stencil), GPU_ATTACHMENT_NONE});
60 
61  stencil_tex = dtxl->depth;
62  }
63 
64  GPU_framebuffer_ensure_config(
65  &fbl->sss_blur_fb,
66  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(effects->sss_blur)});
67 
68  GPU_framebuffer_ensure_config(
69  &fbl->sss_resolve_fb,
70  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->color)});
71 
72  GPU_framebuffer_ensure_config(
73  &fbl->sss_translucency_fb,
74  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance)});
75 
76  GPU_framebuffer_ensure_config(&fbl->sss_clear_fb,
77  {GPU_ATTACHMENT_NONE,
78  GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
79  GPU_ATTACHMENT_TEXTURE(effects->sss_radius)});
81  EEVEE_subsurface_output_init(sldata, vedata, 0);
82  }
83  else {
84  GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
86  }
87  }
88  else {
89  /* Cleanup to release memory */
90  GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
91  GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
92  GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
93  GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
95  effects->sss_stencil = NULL;
96  effects->sss_blur = NULL;
97  effects->sss_irradiance = NULL;
98  effects->sss_radius = NULL;
99  }
100 }
101 
103  EEVEE_Data *vedata,
104  uint UNUSED(tot_samples))
105 {
106  EEVEE_FramebufferList *fbl = vedata->fbl;
107  EEVEE_TextureList *txl = vedata->txl;
108  EEVEE_StorageList *stl = vedata->stl;
109  EEVEE_EffectsInfo *effects = stl->effects;
110 
111  const eGPUTextureFormat texture_format_light = GPU_RGBA32F;
112  const bool texture_created = txl->sss_accum == NULL;
113  DRW_texture_ensure_fullscreen_2d(&txl->sss_accum, texture_format_light, 0);
114 
115  GPUTexture *stencil_tex = effects->sss_stencil;
116 
119  /* Blitting stencil buffer does not work on macOS + Radeon Pro.
120  * Blit depth instead and use sss_stencil's depth as depth texture,
121  * and dtxl->depth as stencil mask. */
122  stencil_tex = dtxl->depth;
123  }
124 
125  GPU_framebuffer_ensure_config(
126  &fbl->sss_accum_fb,
127  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->sss_accum)});
128 
129  /* Clear texture.
130  * Due to the late initialization of the SSS it can happen that the `taa_current_sample` is
131  * already higher than one. This is noticeable when loading a file that has the diffuse light
132  * pass in look-dev mode active. `texture_created` will make sure that newly created textures
133  * are cleared. */
134  if (effects->taa_current_sample == 1 || texture_created) {
135  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
137  GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
138  }
139 }
140 
142 {
143  EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
144  EEVEE_EffectsInfo *effects = vedata->stl->effects;
145  EEVEE_PassList *psl = vedata->psl;
146 
147  const DRWContextState *draw_ctx = DRW_context_state_get();
148  const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
149 
150  effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
151  effects->sss_surface_count = 0;
152  common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
153 
161 }
162 
164  EEVEE_Data *vedata,
165  Material *ma,
166  DRWShadingGroup *shgrp,
167  struct GPUMaterial *gpumat)
168 {
169  EEVEE_PassList *psl = vedata->psl;
170  EEVEE_StorageList *stl = vedata->stl;
171  EEVEE_EffectsInfo *effects = stl->effects;
174 
175  struct GPUTexture *sss_tex_profile = NULL;
176  struct GPUUniformBuf *sss_profile = GPU_material_sss_profile_get(
177  gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
178 
179  if (!sss_profile) {
180  BLI_assert_msg(0, "SSS pass requested but no SSS data was found");
181  return;
182  }
183 
184  /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
185  if (effects->sss_surface_count >= 254) {
186  /* TODO: display message. */
187  printf("Error: Too many different Subsurface shader in the scene.\n");
188  return;
189  }
190 
191  int sss_id = ++(effects->sss_surface_count);
192  /* Make main pass output stencil mask. */
193  DRW_shgroup_stencil_mask(shgrp, sss_id);
194 
195  {
197 
199  psl->sss_blur_ps);
201  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
202  DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_irradiance, state);
203  DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
204  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
205  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
206  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
207  DRW_shgroup_stencil_mask(grp, sss_id);
209 
212  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
213  DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_blur, state);
214  DRW_shgroup_uniform_texture_ref_ex(grp, "sssAlbedo", &effects->sss_albedo, state);
215  DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
216  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
217  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
218  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
219  DRW_shgroup_stencil_mask(grp, sss_id);
221  }
222 
223  if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
225  psl->sss_translucency_ps);
227  DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
228  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
229  DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
230  DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
231  DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
232  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
233  DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
234  DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
235  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
236  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
237  DRW_shgroup_stencil_mask(grp, sss_id);
239  }
240 }
241 
243 {
244  EEVEE_PassList *psl = vedata->psl;
245  EEVEE_FramebufferList *fbl = vedata->fbl;
246  EEVEE_StorageList *stl = vedata->stl;
247  EEVEE_EffectsInfo *effects = stl->effects;
248 
249  if ((effects->enabled_effects & EFFECT_SSS) != 0) {
250  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
251  /* Clear sss_data texture only... can this be done in a more clever way? */
253  GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
254 
255  GPU_framebuffer_ensure_config(&fbl->main_fb,
256  {GPU_ATTACHMENT_LEAVE,
257  GPU_ATTACHMENT_LEAVE,
258  GPU_ATTACHMENT_LEAVE,
259  GPU_ATTACHMENT_LEAVE,
260  GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
261  GPU_ATTACHMENT_TEXTURE(effects->sss_radius),
262  GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
263 
266 
267  /* Restore */
268  GPU_framebuffer_ensure_config(&fbl->main_fb,
269  {GPU_ATTACHMENT_LEAVE,
270  GPU_ATTACHMENT_LEAVE,
271  GPU_ATTACHMENT_LEAVE,
272  GPU_ATTACHMENT_LEAVE,
273  GPU_ATTACHMENT_NONE,
274  GPU_ATTACHMENT_NONE,
275  GPU_ATTACHMENT_NONE});
276  }
277 }
278 
280 {
281  EEVEE_PassList *psl = vedata->psl;
282  EEVEE_StorageList *stl = vedata->stl;
283  EEVEE_TextureList *txl = vedata->txl;
284  EEVEE_FramebufferList *fbl = vedata->fbl;
285  EEVEE_EffectsInfo *effects = stl->effects;
286 
287  if ((effects->enabled_effects & EFFECT_SSS) != 0) {
288  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
289 
290  DRW_stats_group_start("SSS");
291 
293  /* Copy depth channel */
295  }
296  else {
297  /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
299  }
300 
302  /* We sample the shadow-maps using normal sampler. We need to disable Comparison mode.
303  * TODO(fclem): avoid this by using sampler objects. */
306 
309 
310  /* Reset original state. */
313  }
314 
315  /* 1. horizontal pass */
317  GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
319 
320  /* 2. vertical pass + Resolve */
324 
327  }
328 }
329 
331 {
332  EEVEE_PassList *psl = vedata->psl;
333  EEVEE_FramebufferList *fbl = vedata->fbl;
334  EEVEE_StorageList *stl = vedata->stl;
335  EEVEE_EffectsInfo *effects = stl->effects;
336 
337  if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
338  /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
340 
341  /* Only do vertical pass + Resolve */
344 
345  /* Restore */
347  }
348 }
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ EEVEE_RENDER_PASS_DIFFUSE_LIGHT
@ MA_BL_TRANSLUCENCY
DRWState
Definition: DRW_render.h:298
@ DRW_STATE_STENCIL_EQUAL
Definition: DRW_render.h:320
@ DRW_STATE_BLEND_ADD
Definition: DRW_render.h:324
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:690
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:183
bool GPU_depth_blitting_workaround(void)
@ GPU_DEPTH_BIT
@ GPU_STENCIL_BIT
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
struct GPUUniformBuf * GPU_material_sss_profile_get(GPUMaterial *material, int sample_len, struct GPUTexture **tex_profile)
Definition: gpu_material.c:455
eGPUSamplerState
Definition: GPU_texture.h:25
@ GPU_SAMPLER_DEFAULT
Definition: GPU_texture.h:26
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
Definition: gpu_texture.cc:510
eGPUTextureFormat
Definition: GPU_texture.h:83
@ GPU_DEPTH24_STENCIL8
Definition: GPU_texture.h:120
@ GPU_R16F
Definition: GPU_texture.h:113
@ GPU_RGBA32F
Definition: GPU_texture.h:90
@ GPU_R11F_G11F_B10F
Definition: GPU_texture.h:118
struct GPUUniformBuf GPUUniformBuf
const DRWContextState * DRW_context_state_get(void)
const float * DRW_viewport_size_get(void)
Definition: draw_manager.c:288
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:638
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_uniform_texture_ref_ex(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex, eGPUSamplerState sampler_state)
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, uint tri_count)
bool DRW_pass_is_empty(DRWPass *pass)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
void DRW_draw_pass(DRWPass *pass)
void DRW_stats_group_start(const char *name)
void DRW_stats_group_end(void)
void DRW_texture_ensure_fullscreen_2d(GPUTexture **tex, eGPUTextureFormat format, DRWTextureFlag flags)
GPUTexture * DRW_texture_pool_query_2d(int w, int h, eGPUTextureFormat format, DrawEngineType *engine_type)
struct GPUTexture * depth_src
Definition: eevee_effects.c:22
DrawEngineType draw_engine_eevee_type
Definition: eevee_engine.c:618
struct GPUTexture * EEVEE_materials_get_util_tex(void)
struct GPUShader * EEVEE_shaders_subsurface_translucency_sh_get(void)
struct GPUShader * EEVEE_shaders_subsurface_first_pass_sh_get(void)
struct GPUShader * EEVEE_shaders_subsurface_second_pass_sh_get(void)
@ EFFECT_SSS
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
void EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *UNUSED(vedata))
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Material *ma, DRWShadingGroup *shgrp, struct GPUMaterial *gpumat)
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, uint UNUSED(tot_samples))
void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
void GPU_framebuffer_blit(GPUFrameBuffer *gpufb_read, int read_slot, GPUFrameBuffer *gpufb_write, int write_slot, eGPUFrameBufferBits blit_buffers)
const int state
static void clear(Message *msg)
Definition: msgfmt.c:278
struct Depsgraph * depsgraph
Definition: DRW_render.h:987
struct GPUTexture * depth
EEVEE_TextureList * txl
EEVEE_StorageList * stl
EEVEE_PassList * psl
EEVEE_FramebufferList * fbl
struct GPUTexture * sss_irradiance
struct GPUTexture * sss_blur
struct GPUTexture * sss_radius
EEVEE_EffectsFlag enabled_effects
struct GPUTexture * sss_stencil
struct GPUTexture * sss_albedo
struct GPUFrameBuffer * main_fb
struct GPUFrameBuffer * sss_resolve_fb
struct GPUFrameBuffer * sss_translucency_fb
struct GPUFrameBuffer * sss_blit_fb
struct GPUFrameBuffer * sss_accum_fb
struct GPUFrameBuffer * sss_clear_fb
struct GPUFrameBuffer * sss_blur_fb
struct DRWPass * material_sss_ps
struct DRWPass * sss_resolve_ps
struct DRWPass * sss_blur_ps
struct DRWPass * sss_translucency_ps
eViewLayerEEVEEPassType render_passes
struct EEVEE_PrivateData * g_data
struct EEVEE_EffectsInfo * effects
struct GPUTexture * sss_accum
struct GPUTexture * color
struct EEVEE_CommonUniformBuffer common_data
struct GPUTexture * shadow_cube_pool
struct GPUUniformBuf * combined
struct GPUUniformBuf * shadow_ubo
struct EEVEE_ViewLayerData::@210 renderpass_ubo
struct GPUUniformBuf * common_ubo
struct GPUUniformBuf * light_ubo
struct GPUTexture * shadow_cascade_pool
float sss_jitter_threshold
struct SceneEEVEE eevee