Blender  V2.93
eevee_subsurface.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 
25 #include "DRW_render.h"
26 
27 #include "BLI_string_utils.h"
28 
29 #include "DEG_depsgraph_query.h"
30 
31 #include "GPU_capabilities.h"
32 #include "GPU_material.h"
33 #include "GPU_texture.h"
34 
35 #include "eevee_private.h"
36 
38 {
39 }
40 
42 {
43  EEVEE_EffectsInfo *effects = vedata->stl->effects;
44  EEVEE_StorageList *stl = vedata->stl;
45  EEVEE_FramebufferList *fbl = vedata->fbl;
46  EEVEE_TextureList *txl = vedata->txl;
48  const float *viewport_size = DRW_viewport_size_get();
49  const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
50 
51  if (effects->enabled_effects & EFFECT_SSS) {
52  /* NOTE : we need another stencil because the stencil buffer is on the same texture
53  * as the depth buffer we are sampling from. This could be avoided if the stencil is
54  * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
55  * OR OpenGL 4.3 / ARB_ES3_compatibility if using a render-buffer instead. */
57  fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8, &draw_engine_eevee_type);
59  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
61  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
63  fs_size[0], fs_size[1], GPU_R16F, &draw_engine_eevee_type);
65  fs_size[0], fs_size[1], GPU_R11F_G11F_B10F, &draw_engine_eevee_type);
66 
67  GPUTexture *stencil_tex = effects->sss_stencil;
68 
70  /* Blitting stencil buffer does not work on macOS + Radeon Pro.
71  * Blit depth instead and use sss_stencil's depth as depth texture,
72  * and dtxl->depth as stencil mask. */
73  GPU_framebuffer_ensure_config(
74  &fbl->sss_blit_fb, {GPU_ATTACHMENT_TEXTURE(effects->sss_stencil), GPU_ATTACHMENT_NONE});
75 
76  stencil_tex = dtxl->depth;
77  }
78 
79  GPU_framebuffer_ensure_config(
80  &fbl->sss_blur_fb,
81  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(effects->sss_blur)});
82 
83  GPU_framebuffer_ensure_config(
84  &fbl->sss_resolve_fb,
85  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->color)});
86 
87  GPU_framebuffer_ensure_config(
88  &fbl->sss_translucency_fb,
89  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance)});
90 
91  GPU_framebuffer_ensure_config(&fbl->sss_clear_fb,
92  {GPU_ATTACHMENT_NONE,
93  GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
94  GPU_ATTACHMENT_TEXTURE(effects->sss_radius)});
96  EEVEE_subsurface_output_init(sldata, vedata, 0);
97  }
98  else {
101  }
102  }
103  else {
104  /* Cleanup to release memory */
110  effects->sss_stencil = NULL;
111  effects->sss_blur = NULL;
112  effects->sss_irradiance = NULL;
113  effects->sss_radius = NULL;
114  }
115 }
116 
118  EEVEE_Data *vedata,
119  uint UNUSED(tot_samples))
120 {
121  EEVEE_FramebufferList *fbl = vedata->fbl;
122  EEVEE_TextureList *txl = vedata->txl;
123  EEVEE_StorageList *stl = vedata->stl;
124  EEVEE_EffectsInfo *effects = stl->effects;
125 
126  const eGPUTextureFormat texture_format_light = GPU_RGBA32F;
127  const bool texture_created = txl->sss_accum == NULL;
128  DRW_texture_ensure_fullscreen_2d(&txl->sss_accum, texture_format_light, 0);
129 
130  GPUTexture *stencil_tex = effects->sss_stencil;
131 
134  /* Blitting stencil buffer does not work on macOS + Radeon Pro.
135  * Blit depth instead and use sss_stencil's depth as depth texture,
136  * and dtxl->depth as stencil mask. */
137  stencil_tex = dtxl->depth;
138  }
139 
140  GPU_framebuffer_ensure_config(
141  &fbl->sss_accum_fb,
142  {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->sss_accum)});
143 
144  /* Clear texture.
145  * Due to the late initialization of the SSS it can happen that the `taa_current_sample` is
146  * already higher than one. This is noticeable when loading a file that has the diffuse light
147  * pass in look dev mode active. `texture_created` will make sure that newly created textures
148  * are cleared. */
149  if (effects->taa_current_sample == 1 || texture_created) {
150  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
152  GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
153  }
154 }
155 
157 {
158  EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
159  EEVEE_EffectsInfo *effects = vedata->stl->effects;
160  EEVEE_PassList *psl = vedata->psl;
161 
162  const DRWContextState *draw_ctx = DRW_context_state_get();
163  const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
164 
165  effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
166  effects->sss_surface_count = 0;
167  common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
168 
176 }
177 
179  EEVEE_Data *vedata,
180  Material *ma,
181  DRWShadingGroup *shgrp,
182  struct GPUMaterial *gpumat)
183 {
184  EEVEE_PassList *psl = vedata->psl;
185  EEVEE_StorageList *stl = vedata->stl;
186  EEVEE_EffectsInfo *effects = stl->effects;
189 
190  struct GPUTexture *sss_tex_profile = NULL;
191  struct GPUUniformBuf *sss_profile = GPU_material_sss_profile_get(
192  gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
193 
194  if (!sss_profile) {
195  BLI_assert(0 && "SSS pass requested but no SSS data was found");
196  return;
197  }
198 
199  /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
200  if (effects->sss_surface_count >= 254) {
201  /* TODO : display message. */
202  printf("Error: Too many different Subsurface shader in the scene.\n");
203  return;
204  }
205 
206  int sss_id = ++(effects->sss_surface_count);
207  /* Make main pass output stencil mask. */
208  DRW_shgroup_stencil_mask(shgrp, sss_id);
209 
210  {
212 
214  psl->sss_blur_ps);
216  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
217  DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_irradiance, state);
218  DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
219  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
220  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
221  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
222  DRW_shgroup_stencil_mask(grp, sss_id);
224 
227  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
228  DRW_shgroup_uniform_texture_ref_ex(grp, "sssIrradiance", &effects->sss_blur, state);
229  DRW_shgroup_uniform_texture_ref_ex(grp, "sssAlbedo", &effects->sss_albedo, state);
230  DRW_shgroup_uniform_texture_ref_ex(grp, "sssRadius", &effects->sss_radius, state);
231  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
232  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
233  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
234  DRW_shgroup_stencil_mask(grp, sss_id);
236  }
237 
238  if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
240  psl->sss_translucency_ps);
242  DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
243  DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
244  DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
245  DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
246  DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
247  DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
248  DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
249  DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
250  DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
251  DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
252  DRW_shgroup_stencil_mask(grp, sss_id);
254  }
255 }
256 
258 {
259  EEVEE_PassList *psl = vedata->psl;
260  EEVEE_FramebufferList *fbl = vedata->fbl;
261  EEVEE_StorageList *stl = vedata->stl;
262  EEVEE_EffectsInfo *effects = stl->effects;
263 
264  if ((effects->enabled_effects & EFFECT_SSS) != 0) {
265  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
266  /* Clear sss_data texture only... can this be done in a more clever way? */
268  GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
269 
270  GPU_framebuffer_ensure_config(&fbl->main_fb,
271  {GPU_ATTACHMENT_LEAVE,
272  GPU_ATTACHMENT_LEAVE,
273  GPU_ATTACHMENT_LEAVE,
274  GPU_ATTACHMENT_LEAVE,
275  GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance),
276  GPU_ATTACHMENT_TEXTURE(effects->sss_radius),
277  GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
278 
281 
282  /* Restore */
283  GPU_framebuffer_ensure_config(&fbl->main_fb,
284  {GPU_ATTACHMENT_LEAVE,
285  GPU_ATTACHMENT_LEAVE,
286  GPU_ATTACHMENT_LEAVE,
287  GPU_ATTACHMENT_LEAVE,
288  GPU_ATTACHMENT_NONE,
289  GPU_ATTACHMENT_NONE,
290  GPU_ATTACHMENT_NONE});
291  }
292 }
293 
295 {
296  EEVEE_PassList *psl = vedata->psl;
297  EEVEE_StorageList *stl = vedata->stl;
298  EEVEE_TextureList *txl = vedata->txl;
299  EEVEE_FramebufferList *fbl = vedata->fbl;
300  EEVEE_EffectsInfo *effects = stl->effects;
301 
302  if ((effects->enabled_effects & EFFECT_SSS) != 0) {
303  const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
304 
305  DRW_stats_group_start("SSS");
306 
308  /* Copy depth channel */
310  }
311  else {
312  /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
314  }
315 
317  /* We sample the shadow-maps using normal sampler. We need to disable Comparison mode.
318  * TODO(fclem): avoid this by using sampler objects.*/
321 
324 
325  /* Reset original state. */
328  }
329 
330  /* 1. horizontal pass */
332  GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
334 
335  /* 2. vertical pass + Resolve */
339 
342  }
343 }
344 
346 {
347  EEVEE_PassList *psl = vedata->psl;
348  EEVEE_FramebufferList *fbl = vedata->fbl;
349  EEVEE_StorageList *stl = vedata->stl;
350  EEVEE_EffectsInfo *effects = stl->effects;
351 
352  if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
353  /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
355 
356  /* Only do vertical pass + Resolve */
359 
360  /* Restore */
362  }
363 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
unsigned int uint
Definition: BLI_sys_types.h:83
#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:312
@ DRW_STATE_STENCIL_EQUAL
Definition: DRW_render.h:332
@ DRW_STATE_BLEND_ADD
Definition: DRW_render.h:336
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:593
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:180
bool GPU_depth_blitting_workaround(void)
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
@ 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:519
eGPUSamplerState
Definition: GPU_texture.h:40
@ GPU_SAMPLER_DEFAULT
Definition: GPU_texture.h:41
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
Definition: gpu_texture.cc:460
eGPUTextureFormat
Definition: GPU_texture.h:84
@ GPU_DEPTH24_STENCIL8
Definition: GPU_texture.h:121
@ GPU_R16F
Definition: GPU_texture.h:114
@ GPU_RGBA32F
Definition: GPU_texture.h:91
@ GPU_R11F_G11F_B10F
Definition: GPU_texture.h:119
struct GPUUniformBuf GPUUniformBuf
const DRWContextState * DRW_context_state_get(void)
const float * DRW_viewport_size_get(void)
Definition: draw_manager.c:439
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:702
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuf *ubo)
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:37
DrawEngineType draw_engine_eevee_type
Definition: eevee_engine.c:622
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)
static ulong state[N]
static void clear(Message *msg)
Definition: msgfmt.c:294
struct Depsgraph * depsgraph
Definition: DRW_render.h:753
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::@202 renderpass_ubo
struct GPUUniformBuf * common_ubo
struct GPUUniformBuf * light_ubo
struct GPUTexture * shadow_cascade_pool
float sss_jitter_threshold
struct SceneEEVEE eevee