doxygen: add newline after \file
[blender.git] / source / blender / draw / engines / eevee / eevee_subsurface.c
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
19 /** \file
20  * \ingroup draw_engine
21  *
22  * Screen space subsurface scattering technique.
23  */
24
25 #include "DRW_render.h"
26
27 #include "BLI_string_utils.h"
28
29 #include "DEG_depsgraph_query.h"
30
31 #include "eevee_private.h"
32 #include "GPU_texture.h"
33 #include "GPU_extensions.h"
34
35 static struct {
36         struct GPUShader *sss_sh[4];
37 } e_data = {{NULL}}; /* Engine data */
38
39 extern char datatoc_common_view_lib_glsl[];
40 extern char datatoc_common_uniforms_lib_glsl[];
41 extern char datatoc_effect_subsurface_frag_glsl[];
42
43 static void eevee_create_shader_subsurface(void)
44 {
45         char *frag_str = BLI_string_joinN(
46                 datatoc_common_view_lib_glsl,
47                 datatoc_common_uniforms_lib_glsl,
48                 datatoc_effect_subsurface_frag_glsl);
49
50         e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
51         e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
52         e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
53                                                                   "#define USE_SEP_ALBEDO\n");
54         e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
55                                                                   "#define USE_SEP_ALBEDO\n"
56                                                                   "#define RESULT_ACCUM\n");
57
58         MEM_freeN(frag_str);
59 }
60
61 int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
62 {
63         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
64         EEVEE_StorageList *stl = vedata->stl;
65         EEVEE_EffectsInfo *effects = stl->effects;
66         EEVEE_FramebufferList *fbl = vedata->fbl;
67         EEVEE_TextureList *txl = vedata->txl;
68         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
69         const float *viewport_size = DRW_viewport_size_get();
70         const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
71
72         const DRWContextState *draw_ctx = DRW_context_state_get();
73         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
74
75         if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) {
76                 effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
77                 effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0;
78                 common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
79
80                 /* Shaders */
81                 if (!e_data.sss_sh[0]) {
82                         eevee_create_shader_subsurface();
83                 }
84
85                 /* NOTE : we need another stencil because the stencil buffer is on the same texture
86                  * as the depth buffer we are sampling from. This could be avoided if the stencil is
87                  * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
88                  * OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */
89                 effects->sss_stencil = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8,
90                                                                  &draw_engine_eevee_type);
91                 effects->sss_blur =    DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F,
92                                                                  &draw_engine_eevee_type);
93                 effects->sss_data =    DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F,
94                                                                  &draw_engine_eevee_type);
95
96                 GPUTexture *stencil_tex = effects->sss_stencil;
97
98                 if (GPU_depth_blitting_workaround()) {
99                         /* Blitting stencil buffer does not work on macOS + Radeon Pro.
100                          * Blit depth instead and use sss_stencil's depth as depth texture,
101                          * and dtxl->depth as stencil mask. */
102                         GPU_framebuffer_ensure_config(&fbl->sss_blit_fb, {
103                                 GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
104                                 GPU_ATTACHMENT_NONE
105                         });
106
107                         stencil_tex = dtxl->depth;
108                 }
109
110                 GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, {
111                         GPU_ATTACHMENT_TEXTURE(stencil_tex),
112                         GPU_ATTACHMENT_TEXTURE(effects->sss_blur)
113                 });
114
115                 GPU_framebuffer_ensure_config(&fbl->sss_resolve_fb, {
116                         GPU_ATTACHMENT_TEXTURE(stencil_tex),
117                         GPU_ATTACHMENT_TEXTURE(txl->color)
118                 });
119
120                 GPU_framebuffer_ensure_config(&fbl->sss_clear_fb, {
121                         GPU_ATTACHMENT_NONE,
122                         GPU_ATTACHMENT_TEXTURE(effects->sss_data)
123                 });
124
125                 if (effects->sss_separate_albedo) {
126                         effects->sss_albedo = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_R11F_G11F_B10F,
127                                                                         &draw_engine_eevee_type);
128                 }
129                 else {
130                         effects->sss_albedo = NULL;
131                 }
132                 return EFFECT_SSS;
133         }
134
135         /* Cleanup to release memory */
136         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
137         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
138         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
139         effects->sss_stencil = NULL;
140         effects->sss_blur = NULL;
141         effects->sss_data = NULL;
142
143         return 0;
144 }
145
146 static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp)
147 {
148         DRW_shgroup_stencil_mask(shgrp, 255);
149 }
150
151 void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
152 {
153         EEVEE_FramebufferList *fbl = vedata->fbl;
154         EEVEE_TextureList *txl = vedata->txl;
155         EEVEE_StorageList *stl = vedata->stl;
156         EEVEE_EffectsInfo *effects = stl->effects;
157
158         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
159         const DRWContextState *draw_ctx = DRW_context_state_get();
160         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
161
162         if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) {
163                 DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, GPU_RGBA16F, 0);
164                 DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, GPU_RGBA16F, 0);
165
166                 GPUTexture *stencil_tex = effects->sss_stencil;
167
168                 if (GPU_depth_blitting_workaround()) {
169                         /* Blitting stencil buffer does not work on macOS + Radeon Pro.
170                          * Blit depth instead and use sss_stencil's depth as depth texture,
171                          * and dtxl->depth as stencil mask. */
172                         stencil_tex = dtxl->depth;
173                 }
174
175                 GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, {
176                         GPU_ATTACHMENT_TEXTURE(stencil_tex),
177                         GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum),
178                         GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)
179                 });
180
181                 /* Clear texture. */
182                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
183                 GPU_framebuffer_bind(fbl->sss_accum_fb);
184                 GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
185
186                 /* Make the opaque refraction pass mask the sss. */
187                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
188                                  DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
189                 DRW_pass_state_set(vedata->psl->refract_pass, state);
190                 DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
191         }
192         else {
193                 /* Cleanup to release memory */
194                 DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum);
195                 DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum);
196                 GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
197         }
198 }
199
200 void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
201 {
202         EEVEE_PassList *psl = vedata->psl;
203         EEVEE_StorageList *stl = vedata->stl;
204         EEVEE_EffectsInfo *effects = stl->effects;
205
206         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
207                 /** Screen Space SubSurface Scattering overview
208                  * TODO
209                  */
210                 psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
211
212                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL;
213                 psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state);
214                 psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state);
215         }
216 }
217
218 void EEVEE_subsurface_add_pass(
219         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, struct GPUUniformBuffer *sss_profile)
220 {
221         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
222         EEVEE_PassList *psl = vedata->psl;
223         EEVEE_StorageList *stl = vedata->stl;
224         EEVEE_EffectsInfo *effects = stl->effects;
225         struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
226         GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
227
228         DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
229         DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
230         DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
231         DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_data);
232         DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
233         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
234         DRW_shgroup_stencil_mask(grp, sss_id);
235         DRW_shgroup_call_add(grp, quad, NULL);
236
237         struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
238         grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
239         DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
240         DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
241         DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
242         DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
243         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
244         DRW_shgroup_stencil_mask(grp, sss_id);
245         DRW_shgroup_call_add(grp, quad, NULL);
246
247         if (effects->sss_separate_albedo) {
248                 DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
249         }
250
251         if (DRW_state_is_image_render()) {
252                 grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
253                 DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
254                 DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
255                 DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
256                 DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
257                 DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
258                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
259                 DRW_shgroup_stencil_mask(grp, sss_id);
260                 DRW_shgroup_call_add(grp, quad, NULL);
261         }
262 }
263
264 void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
265 {
266         EEVEE_PassList *psl = vedata->psl;
267         EEVEE_FramebufferList *fbl = vedata->fbl;
268         EEVEE_StorageList *stl = vedata->stl;
269         EEVEE_EffectsInfo *effects = stl->effects;
270
271         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
272                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
273                 /* Clear sss_data texture only... can this be done in a more clever way? */
274                 GPU_framebuffer_bind(fbl->sss_clear_fb);
275                 GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
276
277                 GPU_framebuffer_ensure_config(&fbl->main_fb, {
278                         GPU_ATTACHMENT_LEAVE,
279                         GPU_ATTACHMENT_LEAVE,
280                         GPU_ATTACHMENT_LEAVE,
281                         GPU_ATTACHMENT_LEAVE,
282                         GPU_ATTACHMENT_TEXTURE(effects->sss_data),
283                         GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)
284                 });
285
286                 GPU_framebuffer_bind(fbl->main_fb);
287                 DRW_draw_pass(psl->sss_pass);
288
289                 /* Restore */
290                 GPU_framebuffer_ensure_config(&fbl->main_fb, {
291                         GPU_ATTACHMENT_LEAVE,
292                         GPU_ATTACHMENT_LEAVE,
293                         GPU_ATTACHMENT_LEAVE,
294                         GPU_ATTACHMENT_LEAVE,
295                         GPU_ATTACHMENT_NONE,
296                         GPU_ATTACHMENT_NONE
297                 });
298         }
299 }
300
301 void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
302 {
303         EEVEE_PassList *psl = vedata->psl;
304         EEVEE_StorageList *stl = vedata->stl;
305         EEVEE_TextureList *txl = vedata->txl;
306         EEVEE_FramebufferList *fbl = vedata->fbl;
307         EEVEE_EffectsInfo *effects = stl->effects;
308
309         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
310                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
311
312                 DRW_stats_group_start("SSS");
313
314                 if (GPU_depth_blitting_workaround()) {
315                         /* Copy depth channel */
316                         GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blit_fb, 0, GPU_DEPTH_BIT);
317                 }
318                 else {
319                         /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
320                         GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
321                 }
322
323                 /* 1. horizontal pass */
324                 GPU_framebuffer_bind(fbl->sss_blur_fb);
325                 GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
326                 DRW_draw_pass(psl->sss_blur_ps);
327
328                 /* 2. vertical pass + Resolve */
329                 GPU_framebuffer_texture_attach(fbl->sss_resolve_fb, txl->color, 0, 0);
330                 GPU_framebuffer_bind(fbl->sss_resolve_fb);
331                 DRW_draw_pass(psl->sss_resolve_ps);
332
333                 GPU_framebuffer_bind(fbl->main_fb);
334                 DRW_stats_group_end();
335         }
336 }
337
338 void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
339 {
340         EEVEE_PassList *psl = vedata->psl;
341         EEVEE_FramebufferList *fbl = vedata->fbl;
342         EEVEE_StorageList *stl = vedata->stl;
343         EEVEE_EffectsInfo *effects = stl->effects;
344
345         if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
346                 /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
347                 GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
348
349                 /* Only do vertical pass + Resolve */
350                 GPU_framebuffer_bind(fbl->sss_accum_fb);
351                 DRW_draw_pass(psl->sss_accum_ps);
352
353                 /* Restore */
354                 GPU_framebuffer_bind(fbl->main_fb);
355         }
356 }
357
358 void EEVEE_subsurface_free(void)
359 {
360         DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]);
361         DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]);
362         DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]);
363         DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]);
364 }