Merge branch 'master' into blender2.8
[blender.git] / source / blender / draw / engines / workbench / workbench_data.c
1 #include "workbench_private.h"
2
3 #include "DNA_userdef_types.h"
4
5 #include "UI_resources.h"
6
7
8 void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info)
9 {
10         effect_info->jitter_index = 0;
11         effect_info->view_updated = true;
12 }
13
14 void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
15 {
16         const DRWContextState *draw_ctx = DRW_context_state_get();
17         const Scene *scene = draw_ctx->scene;
18         wpd->material_hash = BLI_ghash_ptr_new(__func__);
19         wpd->user_preferences = &U;
20
21         View3D *v3d = draw_ctx->v3d;
22         if (!v3d) {
23                 wpd->shading = scene->display.shading;
24                 wpd->use_color_view_settings = true;
25         }
26         else if (v3d->shading.type == OB_RENDER &&
27                  BKE_scene_uses_blender_workbench(scene))
28         {
29                 wpd->shading = scene->display.shading;
30                 wpd->use_color_view_settings = true;
31         }
32         else {
33                 wpd->shading = v3d->shading;
34                 wpd->use_color_view_settings = false;
35         }
36
37         if (wpd->shading.light == V3D_LIGHTING_MATCAP) {
38                 wpd->studio_light = BKE_studiolight_find(
39                         wpd->shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
40         }
41         else {
42                 wpd->studio_light = BKE_studiolight_find(
43                         wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
44         }
45
46         /* If matcaps are missing, use this as fallback. */
47         if (UNLIKELY(wpd->studio_light == NULL)) {
48                 wpd->studio_light = BKE_studiolight_find(
49                         wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
50         }
51
52         wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity;
53
54         WORKBENCH_UBO_World *wd = &wpd->world_data;
55         wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
56         wd->background_alpha = (DRW_state_is_image_render() && scene->r.alphamode == R_ALPHAPREMUL) ? 0.0f : 1.0f;
57
58         if (!v3d || ((v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD) &&
59             (scene->world != NULL)))
60         {
61                 copy_v3_v3(wd->background_color_low, &scene->world->horr);
62                 copy_v3_v3(wd->background_color_high, &scene->world->horr);
63         }
64         else if (v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT) {
65                 copy_v3_v3(wd->background_color_low, v3d->shading.background_color);
66                 copy_v3_v3(wd->background_color_high, v3d->shading.background_color);
67         }
68         else if (v3d) {
69                 UI_GetThemeColor3fv(UI_GetThemeValue(TH_SHOW_BACK_GRAD) ? TH_LOW_GRAD : TH_HIGH_GRAD, wd->background_color_low);
70                 UI_GetThemeColor3fv(TH_HIGH_GRAD, wd->background_color_high);
71
72                 /* XXX: Really quick conversion to avoid washed out background.
73                  * Needs to be addressed properly (color managed using ocio). */
74                 srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high);
75                 srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low);
76         }
77         else {
78                 zero_v3(wd->background_color_low);
79                 zero_v3(wd->background_color_high);
80         }
81
82         studiolight_update_world(wpd, wpd->studio_light, wd);
83
84         copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color);
85         wd->object_outline_color[3] = 1.0f;
86
87         wd->curvature_ridge = 0.5f / max_ff(SQUARE(wpd->shading.curvature_ridge_factor), 1e-4f);
88         wd->curvature_valley = 0.7f / max_ff(SQUARE(wpd->shading.curvature_valley_factor), 1e-4f);
89
90         wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data);
91
92         /* Cavity settings */
93         {
94                 const int ssao_samples = scene->display.matcap_ssao_samples;
95
96                 float invproj[4][4];
97                 const bool is_persp = DRW_viewport_is_persp_get();
98                 /* view vectors for the corners of the view frustum.
99                  * Can be used to recreate the world space position easily */
100                 float viewvecs[3][4] = {
101                     {-1.0f, -1.0f, -1.0f, 1.0f},
102                     {1.0f, -1.0f, -1.0f, 1.0f},
103                     {-1.0f, 1.0f, -1.0f, 1.0f}
104                 };
105                 int i;
106                 const float *size = DRW_viewport_size_get();
107
108                 wpd->ssao_params[0] = ssao_samples;
109                 wpd->ssao_params[1] = size[0] / 64.0;
110                 wpd->ssao_params[2] = size[1] / 64.0;
111                 wpd->ssao_params[3] = 0;
112
113                 /* distance, factor, factor, attenuation */
114                 copy_v4_fl4(
115                         wpd->ssao_settings,
116                         scene->display.matcap_ssao_distance,
117                         wpd->shading.cavity_valley_factor,
118                         wpd->shading.cavity_ridge_factor,
119                         scene->display.matcap_ssao_attenuation);
120
121                 /* invert the view matrix */
122                 DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN);
123                 invert_m4_m4(invproj, wpd->winmat);
124
125                 /* convert the view vectors to view space */
126                 for (i = 0; i < 3; i++) {
127                         mul_m4_v4(invproj, viewvecs[i]);
128                         /* normalized trick see:
129                          * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
130                         mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
131                         if (is_persp)
132                                 mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
133                         viewvecs[i][3] = 1.0;
134
135                         copy_v4_v4(wpd->viewvecs[i], viewvecs[i]);
136                 }
137
138                 /* we need to store the differences */
139                 wpd->viewvecs[1][0] -= wpd->viewvecs[0][0];
140                 wpd->viewvecs[1][1] = wpd->viewvecs[2][1] - wpd->viewvecs[0][1];
141
142                 /* calculate a depth offset as well */
143                 if (!is_persp) {
144                         float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
145                         mul_m4_v4(invproj, vec_far);
146                         mul_v3_fl(vec_far, 1.0f / vec_far[3]);
147                         wpd->viewvecs[1][2] = vec_far[2] - wpd->viewvecs[0][2];
148                 }
149         }
150
151         wpd->volumes_do = false;
152         BLI_listbase_clear(&wpd->smoke_domains);
153 }
154
155 void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, float r_light_direction[3])
156 {
157         const DRWContextState *draw_ctx = DRW_context_state_get();
158         Scene *scene = draw_ctx->scene;
159         WORKBENCH_UBO_World *wd = &wpd->world_data;
160         float view_matrix[4][4];
161         DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
162
163         copy_v3_v3(r_light_direction, scene->display.light_direction);
164         SWAP(float, r_light_direction[2], r_light_direction[1]);
165         r_light_direction[2] = -r_light_direction[2];
166         r_light_direction[0] = -r_light_direction[0];
167
168         /* Shadow direction. */
169         mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction);
170
171         DRW_uniformbuffer_update(wpd->world_ubo, wd);
172 }
173
174 void workbench_private_data_free(WORKBENCH_PrivateData *wpd)
175 {
176         BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN);
177         DRW_UBO_FREE_SAFE(wpd->world_ubo);
178 }