doxygen: add newline after \file
[blender.git] / source / blender / draw / engines / eevee / eevee_mist.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  * Implementation of Blender Mist pass.
23  * IMPORTANT: This is a "post process" of the Z depth so it will lack any transparent objects.
24  */
25
26 #include "DRW_engine.h"
27 #include "DRW_render.h"
28
29 #include "DNA_world_types.h"
30
31 #include "BLI_string_utils.h"
32
33 #include "eevee_private.h"
34
35 extern char datatoc_common_view_lib_glsl[];
36 extern char datatoc_common_uniforms_lib_glsl[];
37 extern char datatoc_bsdf_common_lib_glsl[];
38 extern char datatoc_effect_mist_frag_glsl[];
39
40 static struct {
41         struct GPUShader *mist_sh;
42 } e_data = {NULL}; /* Engine data */
43
44 void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
45 {
46         const DRWContextState *draw_ctx = DRW_context_state_get();
47         EEVEE_FramebufferList *fbl = vedata->fbl;
48         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
49         EEVEE_TextureList *txl = vedata->txl;
50         EEVEE_StorageList *stl = vedata->stl;
51         EEVEE_PassList *psl = vedata->psl;
52         EEVEE_PrivateData *g_data = stl->g_data;
53         Scene *scene = draw_ctx->scene;
54
55         float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
56
57         if (e_data.mist_sh == NULL) {
58                 char *frag_str = BLI_string_joinN(
59                         datatoc_common_view_lib_glsl,
60                         datatoc_common_uniforms_lib_glsl,
61                         datatoc_bsdf_common_lib_glsl,
62                         datatoc_effect_mist_frag_glsl);
63
64                 e_data.mist_sh = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n");
65
66                 MEM_freeN(frag_str);
67         }
68
69         /* Create FrameBuffer. */
70         DRW_texture_ensure_fullscreen_2D(&txl->mist_accum, GPU_R32F, 0); /* Should be enough precision for many samples. */
71
72         GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, {
73                 GPU_ATTACHMENT_NONE,
74                 GPU_ATTACHMENT_TEXTURE(txl->mist_accum)
75         });
76
77         /* Clear texture. */
78         GPU_framebuffer_bind(fbl->mist_accum_fb);
79         GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear);
80
81         /* Mist settings. */
82         if (scene && scene->world) {
83                 g_data->mist_start = scene->world->miststa;
84                 g_data->mist_inv_dist = (scene->world->mistdist > 0.0f) ? 1.0f / scene->world->mistdist : 0.0f;
85
86                 switch (scene->world->mistype) {
87                         case WO_MIST_QUADRATIC:
88                                 g_data->mist_falloff = 2.0f;
89                                 break;
90                         case WO_MIST_LINEAR:
91                                 g_data->mist_falloff = 1.0f;
92                                 break;
93                         case WO_MIST_INVERSE_QUADRATIC:
94                                 g_data->mist_falloff = 0.5f;
95                                 break;
96                 }
97         }
98         else {
99                 float near = -sldata->common_data.view_vecs[0][2];
100                 float range = sldata->common_data.view_vecs[1][2];
101                 /* Fallback */
102                 g_data->mist_start = near;
103                 g_data->mist_inv_dist = 1.0f / fabsf(range);
104                 g_data->mist_falloff = 1.0f;
105         }
106
107         /* XXX ??!! WHY? If not it does not match cycles. */
108         g_data->mist_falloff *= 0.5f;
109
110         /* Create Pass and shgroup. */
111         psl->mist_accum_ps = DRW_pass_create("Mist Accum", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
112         DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
113         DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
114         DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
115         DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
116         DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
117 }
118
119 void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
120 {
121         EEVEE_FramebufferList *fbl = vedata->fbl;
122         EEVEE_PassList *psl = vedata->psl;
123
124         if (fbl->mist_accum_fb != NULL) {
125                 GPU_framebuffer_bind(fbl->mist_accum_fb);
126                 DRW_draw_pass(psl->mist_accum_ps);
127
128                 /* Restore */
129                 GPU_framebuffer_bind(fbl->main_fb);
130         }
131 }
132
133 void EEVEE_mist_free(void)
134 {
135         DRW_SHADER_FREE_SAFE(e_data.mist_sh);
136 }