cf0ed3147d094dc672c59391bac38f34d73d4681
[blender.git] / source / blender / draw / engines / workbench / workbench_materials.c
1
2
3 #include "workbench_private.h"
4
5 #include "BIF_gl.h"
6
7 #include "BLI_dynstr.h"
8 #include "BLI_hash.h"
9
10 #define HSV_SATURATION 0.5
11 #define HSV_VALUE 0.8
12
13 void workbench_material_update_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_MaterialData *data)
14 {
15         /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no texture could be determined */
16         int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ? V3D_SHADING_MATERIAL_COLOR : wpd->shading.color_type;
17         copy_v4_fl4(data->diffuse_color, 0.8f, 0.8f, 0.8f, 1.0f);
18         copy_v4_fl4(data->specular_color, 0.05f, 0.05f, 0.05f, 1.0f); /* Dielectric: 5% reflective. */
19         data->roughness = 0.5; /* sqrtf(0.25f); */
20
21         if (color_type == V3D_SHADING_SINGLE_COLOR) {
22                 copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
23         }
24         else if (color_type == V3D_SHADING_RANDOM_COLOR) {
25                 uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
26                 if (ob->id.lib) {
27                         hash = (hash * 13) ^ BLI_ghashutil_strhash_p_murmur(ob->id.lib->name);
28                 }
29
30                 float hue = BLI_hash_int_01(hash);
31                 float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
32                 hsv_to_rgb_v(hsv, data->diffuse_color);
33         }
34         else {
35                 /* V3D_SHADING_MATERIAL_COLOR */
36                 if (mat) {
37                         if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
38                                 mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
39                                 mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic);
40                                 add_v3_fl(data->specular_color, 0.05f * (1.0f - mat->metallic));
41                                 data->roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */
42                         }
43                         else {
44                                 copy_v3_v3(data->diffuse_color, &mat->r);
45                         }
46                 }
47         }
48 }
49
50 char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
51 {
52         char *str = NULL;
53
54         DynStr *ds = BLI_dynstr_new();
55
56         if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
57                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_OBJECT_OUTLINE\n");
58         }
59         if (wpd->shading.flag & V3D_SHADING_SHADOW) {
60                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SHADOW\n");
61         }
62         if (SSAO_ENABLED(wpd)) {
63                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SSAO\n");
64         }
65         if (CURVATURE_ENABLED(wpd)) {
66                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_CURVATURE\n");
67                 if (U.pixelsize > 1.5f) {
68                         BLI_dynstr_appendf(ds, "#define CURVATURE_OFFSET 2\n");
69                 }
70                 else {
71                         BLI_dynstr_appendf(ds, "#define CURVATURE_OFFSET 1\n");
72                 }
73         }
74         if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
75                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
76         }
77         if (STUDIOLIGHT_ENABLED(wpd)) {
78                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_STUDIO\n");
79         }
80         if (FLAT_ENABLED(wpd)) {
81                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_FLAT\n");
82         }
83         if (MATCAP_ENABLED(wpd)) {
84                 BLI_dynstr_appendf(ds, "#define V3D_LIGHTING_MATCAP\n");
85         }
86         if (STUDIOLIGHT_ORIENTATION_WORLD_ENABLED(wpd)) {
87                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_WORLD\n");
88         }
89         if (STUDIOLIGHT_ORIENTATION_CAMERA_ENABLED(wpd)) {
90                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_CAMERA\n");
91         }
92         if (STUDIOLIGHT_ORIENTATION_VIEWNORMAL_ENABLED(wpd)) {
93                 BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_ORIENTATION_VIEWNORMAL\n");
94         }
95         if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
96                 BLI_dynstr_appendf(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
97         }
98         if (use_textures) {
99                 BLI_dynstr_appendf(ds, "#define V3D_SHADING_TEXTURE_COLOR\n");
100         }
101         if (NORMAL_ENCODING_ENABLED()) {
102                 BLI_dynstr_appendf(ds, "#define WORKBENCH_ENCODE_NORMALS\n");
103         }
104         if (is_hair) {
105                 BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
106         }
107
108         BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_SH_BANDS %d\n", STUDIOLIGHT_SH_BANDS);
109         BLI_dynstr_appendf(ds, "#define STUDIOLIGHT_SH_MAX_COMPONENTS %d\n", WORKBENCH_SH_DATA_LEN);
110
111         str = BLI_dynstr_get_cstring(ds);
112         BLI_dynstr_free(ds);
113         return str;
114 }
115
116 uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost)
117 {
118         uint input[4];
119         uint result;
120         float *color = material_template->diffuse_color;
121         input[0] = (uint)(color[0] * 512);
122         input[1] = (uint)(color[1] * 512);
123         input[2] = (uint)(color[2] * 512);
124         input[3] = material_template->object_id;
125         result = BLI_ghashutil_uinthash_v4_murmur(input);
126
127         color = material_template->specular_color;
128         input[0] = (uint)(color[0] * 512);
129         input[1] = (uint)(color[1] * 512);
130         input[2] = (uint)(color[2] * 512);
131         input[3] = (uint)(material_template->roughness * 512);
132         result += BLI_ghashutil_uinthash_v4_murmur(input);
133
134         result += BLI_ghashutil_uinthash((uint)is_ghost);
135
136         /* add texture reference */
137         if (material_template->ima) {
138                 result += BLI_ghashutil_inthash_p_murmur(material_template->ima);
139         }
140
141         return result;
142 }
143
144 int workbench_material_get_shader_index(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
145 {
146         /* NOTE: change MAX_SHADERS accordingly when modifying this function. */
147         int index = 0;
148         /* 1 bit V3D_SHADING_TEXTURE_COLOR */
149         SET_FLAG_FROM_TEST(index, use_textures, 1 << 0);
150         /* 2 bits FLAT/STUDIO/MATCAP/SCENE */
151         SET_FLAG_FROM_TEST(index, wpd->shading.light, wpd->shading.light << 1);
152         /* 1 bit V3D_SHADING_SPECULAR_HIGHLIGHT */
153         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT, 1 << 3);
154         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 4);
155         SET_FLAG_FROM_TEST(index, SSAO_ENABLED(wpd), 1 << 5);
156         SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 6);
157         bool uses_curvature = CURVATURE_ENABLED(wpd);
158         SET_FLAG_FROM_TEST(index, uses_curvature, 1 << 7);
159         SET_FLAG_FROM_TEST(index, uses_curvature && (U.pixelsize > 1.5f), 1 << 8);
160         /* 2 bits STUDIOLIGHT_ORIENTATION */
161         SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_WORLD, 1 << 9);
162         SET_FLAG_FROM_TEST(index, wpd->studio_light->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL, 1 << 10);
163         /* 1 bit for hair */
164         SET_FLAG_FROM_TEST(index, is_hair, 1 << 11);
165         return index;
166 }
167
168 int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob)
169 {
170         int color_type = wpd->shading.color_type;
171         if ((color_type == V3D_SHADING_TEXTURE_COLOR && ima == NULL) || (ob->dt < OB_TEXTURE)) {
172                 color_type = V3D_SHADING_MATERIAL_COLOR;
173         }
174         return color_type;
175 }
176
177 void workbench_material_shgroup_uniform(
178         WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material, Object *ob)
179 {
180         if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) {
181                 GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
182                 DRW_shgroup_uniform_texture(grp, "image", tex);
183         }
184         else {
185                 DRW_shgroup_uniform_vec4(grp, "materialDiffuseColor", material->diffuse_color, 1);
186         }
187
188         if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
189                 DRW_shgroup_uniform_vec4(grp, "materialSpecularColor", material->specular_color, 1);
190                 DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
191         }
192 }
193
194 void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material)
195 {
196         dest_material->object_id = source_material->object_id;
197         copy_v4_v4(dest_material->diffuse_color, source_material->diffuse_color);
198         copy_v4_v4(dest_material->specular_color, source_material->specular_color);
199         dest_material->roughness = source_material->roughness;
200         dest_material->ima = source_material->ima;
201 }