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