Move EEVEE properties into scene
[blender.git] / source / blender / draw / engines / eevee / eevee_subsurface.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file eevee_subsurface.c
23  *  \ingroup draw_engine
24  *
25  * Screen space subsurface scattering technique.
26  */
27
28 #include "DRW_render.h"
29
30 #include "BLI_string_utils.h"
31
32 #include "DEG_depsgraph_query.h"
33
34 #include "eevee_private.h"
35 #include "GPU_texture.h"
36
37 static struct {
38         struct GPUShader *sss_sh[4];
39 } e_data = {{NULL}}; /* Engine data */
40
41 extern char datatoc_common_view_lib_glsl[];
42 extern char datatoc_common_uniforms_lib_glsl[];
43 extern char datatoc_effect_subsurface_frag_glsl[];
44
45 static void eevee_create_shader_subsurface(void)
46 {
47         char *frag_str = BLI_string_joinN(
48                 datatoc_common_view_lib_glsl,
49                 datatoc_common_uniforms_lib_glsl,
50                 datatoc_effect_subsurface_frag_glsl);
51
52         e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
53         e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n");
54         e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
55                                                                   "#define USE_SEP_ALBEDO\n");
56         e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"
57                                                                   "#define USE_SEP_ALBEDO\n"
58                                                                   "#define RESULT_ACCUM\n");
59
60         MEM_freeN(frag_str);
61 }
62
63 int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
64 {
65         EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
66         EEVEE_StorageList *stl = vedata->stl;
67         EEVEE_EffectsInfo *effects = stl->effects;
68         EEVEE_FramebufferList *fbl = vedata->fbl;
69         EEVEE_TextureList *txl = vedata->txl;
70         const float *viewport_size = DRW_viewport_size_get();
71         const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
72
73         const DRWContextState *draw_ctx = DRW_context_state_get();
74         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
75
76         if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) {
77                 effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
78                 effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0;
79                 common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
80
81                 /* Force separate albedo for final render */
82                 if (DRW_state_is_image_render()) {
83                         effects->sss_separate_albedo = true;
84                 }
85
86                 /* Shaders */
87                 if (!e_data.sss_sh[0]) {
88                         eevee_create_shader_subsurface();
89                 }
90
91                 /* NOTE : we need another stencil because the stencil buffer is on the same texture
92                  * as the depth buffer we are sampling from. This could be avoided if the stencil is
93                  * a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
94                  * OR OpenGL 4.3 / ARB_ES3_compatibility if using a renderbuffer instead */
95                 effects->sss_stencil = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_DEPTH24_STENCIL8,
96                                                                  &draw_engine_eevee_type);
97                 effects->sss_blur =    DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F,
98                                                                  &draw_engine_eevee_type);
99                 effects->sss_data =    DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_RGBA16F,
100                                                                  &draw_engine_eevee_type);
101
102                 GPU_framebuffer_ensure_config(&fbl->sss_blur_fb, {
103                         GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
104                         GPU_ATTACHMENT_TEXTURE(effects->sss_blur)
105                 });
106
107                 GPU_framebuffer_ensure_config(&fbl->sss_resolve_fb, {
108                         GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
109                         GPU_ATTACHMENT_TEXTURE(txl->color)
110                 });
111
112                 GPU_framebuffer_ensure_config(&fbl->sss_clear_fb, {
113                         GPU_ATTACHMENT_NONE,
114                         GPU_ATTACHMENT_TEXTURE(effects->sss_data)
115                 });
116
117                 if (effects->sss_separate_albedo) {
118                         effects->sss_albedo = DRW_texture_pool_query_2D(fs_size[0], fs_size[1], GPU_R11F_G11F_B10F,
119                                                                         &draw_engine_eevee_type);
120                 }
121                 else {
122                         effects->sss_albedo = NULL;
123                 }
124                 return EFFECT_SSS;
125         }
126
127         /* Cleanup to release memory */
128         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
129         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
130         GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
131         effects->sss_stencil = NULL;
132         effects->sss_blur = NULL;
133         effects->sss_data = NULL;
134
135         return 0;
136 }
137
138 static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp)
139 {
140         DRW_shgroup_stencil_mask(shgrp, 255);
141 }
142
143 void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
144 {
145         EEVEE_FramebufferList *fbl = vedata->fbl;
146         EEVEE_TextureList *txl = vedata->txl;
147         EEVEE_StorageList *stl = vedata->stl;
148         EEVEE_EffectsInfo *effects = stl->effects;
149
150         const DRWContextState *draw_ctx = DRW_context_state_get();
151         const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
152
153         if (scene_eval->flag & SCE_EEVEE_SSS_ENABLED) {
154                 DRW_texture_ensure_fullscreen_2D(&txl->sss_dir_accum, GPU_RGBA16F, 0);
155                 DRW_texture_ensure_fullscreen_2D(&txl->sss_col_accum, GPU_RGBA16F, 0);
156
157                 GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, {
158                         GPU_ATTACHMENT_TEXTURE(effects->sss_stencil),
159                         GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum),
160                         GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)
161                 });
162
163                 /* Clear texture. */
164                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
165                 GPU_framebuffer_bind(fbl->sss_accum_fb);
166                 GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear);
167
168                 /* Make the opaque refraction pass mask the sss. */
169                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
170                                  DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
171                 DRW_pass_state_set(vedata->psl->refract_pass, state);
172                 DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
173         }
174         else {
175                 /* Cleanup to release memory */
176                 DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum);
177                 DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum);
178                 GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb);
179         }
180 }
181
182 void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
183 {
184         EEVEE_PassList *psl = vedata->psl;
185         EEVEE_StorageList *stl = vedata->stl;
186         EEVEE_EffectsInfo *effects = stl->effects;
187
188         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
189                 /** Screen Space SubSurface Scattering overview
190                  * TODO
191                  */
192                 psl->sss_blur_ps = DRW_pass_create("Blur Horiz", DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
193
194                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL;
195                 psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state);
196                 psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state);
197         }
198 }
199
200 void EEVEE_subsurface_add_pass(
201         EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, struct GPUUniformBuffer *sss_profile)
202 {
203         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
204         EEVEE_PassList *psl = vedata->psl;
205         EEVEE_StorageList *stl = vedata->stl;
206         EEVEE_EffectsInfo *effects = stl->effects;
207         struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
208
209         DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
210         DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
211         DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
212         DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_data);
213         DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
214         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
215         DRW_shgroup_stencil_mask(grp, sss_id);
216         DRW_shgroup_call_add(grp, quad, NULL);
217
218         struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
219         grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
220         DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
221         DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
222         DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
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_add(grp, quad, NULL);
227
228         if (effects->sss_separate_albedo) {
229                 DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
230         }
231
232         if (DRW_state_is_image_render()) {
233                 grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_accum_ps);
234                 DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
235                 DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
236                 DRW_shgroup_uniform_texture_ref(grp, "sssData", &effects->sss_blur);
237                 DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
238                 DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
239                 DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
240                 DRW_shgroup_stencil_mask(grp, sss_id);
241                 DRW_shgroup_call_add(grp, quad, NULL);
242         }
243 }
244
245 void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
246 {
247         EEVEE_PassList *psl = vedata->psl;
248         EEVEE_FramebufferList *fbl = vedata->fbl;
249         EEVEE_StorageList *stl = vedata->stl;
250         EEVEE_EffectsInfo *effects = stl->effects;
251
252         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
253                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
254                 /* Clear sss_data texture only... can this be done in a more clever way? */
255                 GPU_framebuffer_bind(fbl->sss_clear_fb);
256                 GPU_framebuffer_clear_color(fbl->sss_clear_fb, clear);
257
258                 GPU_framebuffer_ensure_config(&fbl->main_fb, {
259                         GPU_ATTACHMENT_LEAVE,
260                         GPU_ATTACHMENT_LEAVE,
261                         GPU_ATTACHMENT_LEAVE,
262                         GPU_ATTACHMENT_LEAVE,
263                         GPU_ATTACHMENT_TEXTURE(effects->sss_data),
264                         GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)
265                 });
266
267                 GPU_framebuffer_bind(fbl->main_fb);
268                 DRW_draw_pass(psl->sss_pass);
269
270                 /* Restore */
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_NONE,
277                         GPU_ATTACHMENT_NONE
278                 });
279         }
280 }
281
282 void EEVEE_subsurface_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
283 {
284         EEVEE_PassList *psl = vedata->psl;
285         EEVEE_StorageList *stl = vedata->stl;
286         EEVEE_TextureList *txl = vedata->txl;
287         EEVEE_FramebufferList *fbl = vedata->fbl;
288         EEVEE_EffectsInfo *effects = stl->effects;
289
290         if ((effects->enabled_effects & EFFECT_SSS) != 0) {
291                 float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
292
293                 DRW_stats_group_start("SSS");
294
295                 /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
296                 GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
297
298                 /* 1. horizontal pass */
299                 GPU_framebuffer_bind(fbl->sss_blur_fb);
300                 GPU_framebuffer_clear_color(fbl->sss_blur_fb, clear);
301                 DRW_draw_pass(psl->sss_blur_ps);
302
303                 /* 2. vertical pass + Resolve */
304                 GPU_framebuffer_texture_attach(fbl->sss_resolve_fb, txl->color, 0, 0);
305                 GPU_framebuffer_bind(fbl->sss_resolve_fb);
306                 DRW_draw_pass(psl->sss_resolve_ps);
307
308                 GPU_framebuffer_bind(fbl->main_fb);
309                 DRW_stats_group_end();
310         }
311 }
312
313 void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
314 {
315         EEVEE_PassList *psl = vedata->psl;
316         EEVEE_FramebufferList *fbl = vedata->fbl;
317         EEVEE_StorageList *stl = vedata->stl;
318         EEVEE_EffectsInfo *effects = stl->effects;
319
320         if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) {
321                 /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */
322                 GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT);
323
324                 /* Only do vertical pass + Resolve */
325                 GPU_framebuffer_bind(fbl->sss_accum_fb);
326                 DRW_draw_pass(psl->sss_accum_ps);
327
328                 /* Restore */
329                 GPU_framebuffer_bind(fbl->main_fb);
330         }
331 }
332
333 void EEVEE_subsurface_free(void)
334 {
335         DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]);
336         DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]);
337         DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]);
338         DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]);
339 }