Workbench: Matcaps T55291
[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 (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
56                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
57         }
58         if (STUDIOLIGHT_ENABLED(wpd)) {
59                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_STUDIO\n");
60         }
61         if (FLAT_ENABLED(wpd)) {
62                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_FLAT\n");
63         }
64         if (MATCAP_ENABLED(wpd)) {
65                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_MATCAP\n");
66         }
67         if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
68                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_WORLD\n");
69         }
70         if (STUDIOLIGHT_ORIENTATION_CAMERA_ENABLED(wpd)) {
71                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_CAMERA\n");
72         }
73         if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
74                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_VIEWNORMAL\n");
75         }
76         if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
77                 BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
78         }
79         switch (drawtype) {
80                 case OB_SOLID:
81                         BLI_dynstr_appendf(ds, "#define OB_SOLID\n");
82                         break;
83                 case OB_TEXTURE:
84                         BLI_dynstr_appendf(ds, "#define OB_TEXTURE\n");
85                         break;
86         }
87
88         if (NORMAL_ENCODING_ENABLED()) {
89                 BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n");
90         }
91         if (is_hair) {
92                 BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
93         }
94
95 #ifdef WORKBENCH_REVEALAGE_ENABLED
96         BLI_dynstr_appendf(ds, "#define WORKBENCH_REVEALAGE_ENABLED\n");
97 #endif
98
99         str = BLI_dynstr_get_cstring(ds);
100         BLI_dynstr_free(ds);
101         return str;
102 }
103
104 uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template)
105 {
106         uint input[4];
107         uint result;
108         float *color = material_template->material_data.diffuse_color;
109         input[0] = (uint)(color[0] * 512);
110         input[1] = (uint)(color[1] * 512);
111         input[2] = (uint)(color[2] * 512);
112         input[3] = material_template->object_id;
113         result = BLI_ghashutil_uinthash_v4_murmur(input);
114
115         color = material_template->material_data.specular_color;
116         input[0] = (uint)(color[0] * 512);
117         input[1] = (uint)(color[1] * 512);
118         input[2] = (uint)(color[2] * 512);
119         input[3] = (uint)(material_template->material_data.roughness * 512);
120         result += BLI_ghashutil_uinthash_v4_murmur(input);
121
122         if (material_template->drawtype == OB_TEXTURE) {
123                 /* add texture reference */
124                 result += BLI_ghashutil_inthash_p_murmur(material_template->ima);
125         }
126         return result;
127 }
128
129 int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, int drawtype, bool is_hair)
130 {
131         /* NOTE: change MAX_SHADERS accordingly when modifying this function. */
132         int index = 0;
133         /* 1 bit OB_SOLID and OB_TEXTURE */
134         SET_FLAG_FROM_TEST(index, drawtype == OB_TEXTURE, 1 << 0);
135         /* 2 bits FLAT/STUDIO/MATCAP/SCENE */
136         SET_FLAG_FROM_TEST(index, wpd->shading.light, wpd->shading.light << 1);
137         /* 1 bit V3D_SHADING_SPECULAR_HIGHLIGHT */
138         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT, 1 << 3);
139         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 4);
140         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 5);
141         /* 2 bits STUDIOLIGHT_ORIENTATION */
142         SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 6);
143         SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 7);
144         /* 1 bit for hair */
145         SET_FLAG_FROM_TEST(index, is_hair, 1 << 8);
146         return index;
147 }
148
149 void workbench_material_set_normal_world_matrix(
150         DRWShadingGroup *grp, WORKBENCH_PrivateData *wpd, float persistent_matrix[3][3])
151 {
152         if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
153                 float view_matrix_inverse[4][4];
154                 float rot_matrix[4][4];
155                 float matrix[4][4];
156                 axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
157                 DRW_viewport_matrix_get(view_matrix_inverse, DRW_MAT_VIEWINV);
158                 mul_m4_m4m4(matrix, rot_matrix, view_matrix_inverse);
159                 copy_m3_m4(persistent_matrix, matrix);
160                 DRW_shgroup_uniform_mat3(grp, "normalWorldMatrix", persistent_matrix);
161         }
162 }