7c9c7b96b7bbf6224b9d1d7a08fdb5bb38faeb92
[blender.git] / source / blender / draw / engines / workbench / workbench_materials.c
1
2
3 #include "workbench_private.h"
4
5 #include "BLI_dynstr.h"
6
7 #define HSV_SATURATION 0.5
8 #define HSV_VALUE 0.9
9
10 void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data)
11 {
12         /* When in OB_TEXTURE always uyse V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */
13         int color_type = wpd->drawtype == OB_SOLID ? wpd->shading.color_type : V3D_SHADING_MATERIAL_COLOR;
14         static float default_diffuse_color[] = {0.8f, 0.8f, 0.8f, 1.0f};
15         static float default_specular_color[] = {1.0f, 1.0f, 1.0f, 1.0f};
16         copy_v4_v4(data->material_data.diffuse_color, default_diffuse_color);
17         copy_v4_v4(data->material_data.specular_color, default_specular_color);
18         data->material_data.roughness = 0.25f;
19
20         if (DRW_object_is_paint_mode(ob) || color_type == V3D_SHADING_SINGLE_COLOR) {
21                 copy_v3_v3(data->material_data.diffuse_color, wpd->shading.single_color);
22         }
23         else if (color_type == V3D_SHADING_RANDOM_COLOR) {
24                 uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
25                 if (ob->id.lib) {
26                         hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name);
27                 }
28                 float offset = fmodf((hash / 100000.0) * M_GOLDEN_RATION_CONJUGATE, 1.0);
29
30                 float hsv[3] = {offset, HSV_SATURATION, HSV_VALUE};
31                 hsv_to_rgb_v(hsv, data->material_data.diffuse_color);
32         }
33         else {
34                 /* V3D_SHADING_MATERIAL_COLOR */
35                 if (mat) {
36                         copy_v3_v3(data->material_data.diffuse_color, &mat->r);
37                         copy_v3_v3(data->material_data.specular_color, &mat->specr);
38                         data->material_data.roughness = mat->roughness;
39                 }
40         }
41 }
42
43 char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, int drawtype, bool is_hair)
44 {
45         char *str = NULL;
46
47         DynStr *ds = BLI_dynstr_new();
48
49         if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
50                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_OBJECT_OUTLINE\n");
51         }
52         if (wpd->shading.flag & V3D_SHADING_SHADOW) {
53                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SHADOW\n");
54         }
55         if (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) {
56                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
57         }
58         if (wpd->shading.light & V3D_LIGHTING_STUDIO) {
59                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_STUDIO\n");
60                 if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
61                         BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_WORLD\n");
62                 }
63                 else {
64                         BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_CAMERA\n");
65                 }
66         }
67         if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
68                 BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
69         }
70         switch (drawtype) {
71                 case OB_SOLID:
72                         BLI_dynstr_appendf(ds, "#define OB_SOLID\n");
73                         break;
74                 case OB_TEXTURE:
75                         BLI_dynstr_appendf(ds, "#define OB_TEXTURE\n");
76                         break;
77         }
78
79         if (NORMAL_ENCODING_ENABLED()) {
80                 BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n");
81         }
82         if (is_hair) {
83                 BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
84         }
85
86 #ifdef WORKBENCH_REVEALAGE_ENABLED
87         BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n");
88 #endif
89
90         str = BLI_dynstr_get_cstring(ds);
91         BLI_dynstr_free(ds);
92         return str;
93 }
94
95 uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template)
96 {
97         /* TODO: make a C-string with settings and hash the string */
98         uint input[4];
99         uint result;
100         float *color = material_template->material_data.diffuse_color;
101         input[0] = (uint)(color[0] * 512);
102         input[1] = (uint)(color[1] * 512);
103         input[2] = (uint)(color[2] * 512);
104         input[3] = material_template->object_id;
105         result = BLI_ghashutil_uinthash_v4_murmur(input);
106
107         color = material_template->material_data.specular_color;
108         input[0] = (uint)(color[0] * 512);
109         input[1] = (uint)(color[1] * 512);
110         input[2] = (uint)(color[2] * 512);
111         input[3] = (uint)(material_template->material_data.roughness * 512);
112         result += BLI_ghashutil_uinthash_v4_murmur(input);
113
114         if (material_template->drawtype == OB_TEXTURE) {
115                 /* add texture reference */
116                 result += BLI_ghashutil_inthash_p_murmur(material_template->ima);
117         }
118         return result;
119 }
120
121 int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype, bool is_hair)
122 {
123         /* NOTE: change MAX_SHADERS accordingly when modifying this function. */
124         const int DRAWOPTIONS_MASK = V3D_SHADING_OBJECT_OUTLINE | V3D_SHADING_SHADOW | V3D_SHADING_SPECULAR_HIGHLIGHT;
125         int index = (wpd->shading.flag & DRAWOPTIONS_MASK);
126         index = (index << 2) + wpd->shading.light;
127         index = (index << 3);
128         /* set the drawtype flag
129         0 = OB_SOLID,
130         1 = OB_TEXTURE
131         2 = STUDIOLIGHT_ORIENTATION_WORLD
132         */
133         SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 2);
134         SET_FLAG_FROM_TEST(index, drawtype == OB_TEXTURE, 1);
135         SET_FLAG_FROM_TEST(index, is_hair, 4);
136         return index;
137 }
138
139 void workbench_material_set_normal_world_matrix(
140         DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3])
141 {
142         if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
143                 float view_matrix_inverse[4][4];
144                 float rot_matrix[4][4];
145                 float matrix[4][4];
146                 axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
147                 DRW_viewport_matrix_get(view_matrix_inverse, DRW_MAT_VIEWINV);
148                 mul_m4_m4m4(matrix, rot_matrix, view_matrix_inverse);
149                 copy_m3_m4(persistent_matrix, matrix);
150                 DRW_shgroup_uniform_mat3(grp, "normalWorldMatrix", persistent_matrix);
151         }
152 }