Blender  V3.3
workbench_materials.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2018 Blender Foundation. */
3 
8 #include "workbench_private.h"
9 
10 #include "BLI_memblock.h"
11 
12 #include "BKE_image.h"
13 #include "BKE_node.h"
14 
15 #include "BLI_dynstr.h"
16 #include "BLI_hash.h"
17 
18 #include "DNA_mesh_types.h"
19 #include "DNA_node_types.h"
20 
21 #include "GPU_uniform_buffer.h"
22 
23 #include "ED_uvedit.h"
24 
25 #define HSV_SATURATION 0.5
26 #define HSV_VALUE 0.8
27 
29  Object *ob,
30  Material *mat,
32  eV3DShadingColorType color_type)
33 {
34  float metallic = 0.0f;
35  float roughness = 0.632455532f; /* sqrtf(0.4f); */
36  float alpha = wpd->shading.xray_alpha;
37 
38  switch (color_type) {
40  copy_v3_v3(data->base_color, wpd->shading.single_color);
41  break;
44  if (ob->id.lib) {
46  }
47  float hue = BLI_hash_int_01(hash);
48  const float hsv[3] = {hue, HSV_SATURATION, HSV_VALUE};
49  hsv_to_rgb_v(hsv, data->base_color);
50  break;
51  }
54  alpha *= ob->color[3];
55  copy_v3_v3(data->base_color, ob->color);
56  break;
59  default:
60  if (mat) {
61  alpha *= mat->a;
62  copy_v3_v3(data->base_color, &mat->r);
63  metallic = mat->metallic;
64  roughness = sqrtf(mat->roughness); /* Remap to Disney roughness. */
65  }
66  else {
67  copy_v3_fl(data->base_color, 0.8f);
68  }
69  break;
70  }
71 
72  uint32_t packed_metallic = unit_float_to_uchar_clamp(metallic);
73  uint32_t packed_roughness = unit_float_to_uchar_clamp(roughness);
74  uint32_t packed_alpha = unit_float_to_uchar_clamp(alpha);
75  data->packed_data = (packed_alpha << 16u) | (packed_roughness << 8u) | packed_metallic;
76 }
77 
78 /* Return correct material or empty default material if slot is empty. */
80 {
81  Material *ma = BKE_object_material_get_eval(ob, mat_nr);
82  if (ma == NULL) {
84  }
85  return ma;
86 }
87 
89  Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, eGPUSamplerState *r_sampler)
90 {
91  bNode *node;
92  *r_sampler = 0;
93 
94  ED_object_get_active_image(ob, mat_nr, r_image, r_iuser, &node, NULL);
95  if (node && *r_image) {
96  switch (node->type) {
97  case SH_NODE_TEX_IMAGE: {
98  NodeTexImage *storage = node->storage;
99  const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
100  const bool use_repeat = (storage->extension == SHD_IMAGE_EXTENSION_REPEAT);
101  const bool use_clip = (storage->extension == SHD_IMAGE_EXTENSION_CLIP);
102  SET_FLAG_FROM_TEST(*r_sampler, use_filter, GPU_SAMPLER_FILTER);
103  SET_FLAG_FROM_TEST(*r_sampler, use_repeat, GPU_SAMPLER_REPEAT);
104  SET_FLAG_FROM_TEST(*r_sampler, use_clip, GPU_SAMPLER_CLAMP_BORDER);
105  break;
106  }
108  NodeTexEnvironment *storage = node->storage;
109  const bool use_filter = (storage->interpolation != SHD_INTERP_CLOSEST);
110  SET_FLAG_FROM_TEST(*r_sampler, use_filter, GPU_SAMPLER_FILTER);
111  break;
112  }
113  default:
114  BLI_assert_msg(0, "Node type not supported by workbench");
115  }
116  }
117 }
118 
119 /* Return true if the current material ubo has changed and needs to be rebind. */
121  uint32_t id,
122  uint32_t *r_mat_id)
123 {
124  bool resource_changed = false;
125  /* Divide in chunks of MAX_MATERIAL. */
126  uint32_t chunk = id >> 12u;
127  *r_mat_id = id & 0xFFFu;
128  /* We need to add a new chunk. */
129  while (chunk >= wpd->material_chunk_count) {
130  wpd->material_chunk_count++;
133  wpd->material_chunk_curr = chunk;
134  resource_changed = true;
135  }
136  /* We need to go back to a previous chunk. */
137  if (wpd->material_chunk_curr != chunk) {
140  wpd->material_chunk_curr = chunk;
141  resource_changed = true;
142  }
143  return resource_changed;
144 }
145 
147  Object *ob,
148  int mat_nr,
149  eV3DShadingColorType color_type,
150  eWORKBENCH_DataType datatype,
151  bool *r_transp)
152 {
153  Image *ima = NULL;
154  ImageUser *iuser = NULL;
156  const bool infront = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
157 
158  if (color_type == V3D_SHADING_TEXTURE_COLOR) {
159  workbench_material_get_image(ob, mat_nr, &ima, &iuser, &sampler);
160  if (ima == NULL) {
161  /* Fallback to material color. */
162  color_type = V3D_SHADING_MATERIAL_COLOR;
163  }
164  }
165 
166  switch (color_type) {
168  return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, datatype);
169  }
171  /* For now, we use the same ubo for material and object coloring but with different indices.
172  * This means they are mutually exclusive. */
173  BLI_assert(
175 
176  Material *ma = workbench_object_material_get(ob, mat_nr);
177 
178  const bool transp = wpd->shading.xray_alpha < 1.0f || ma->a < 1.0f;
179  WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype];
180 
181  if (r_transp && transp) {
182  *r_transp = true;
183  }
184 
185  DRWShadingGroup **grp_mat = NULL;
186  /* A hash-map stores material shgroups to pack all similar drawcalls together. */
187  if (BLI_ghash_ensure_p(prepass->material_hash, ma, (void ***)&grp_mat)) {
188  return *grp_mat;
189  }
190 
191  uint32_t mat_id, id = wpd->material_index++;
192 
193  workbench_material_chunk_select(wpd, id, &mat_id);
194  workbench_material_ubo_data(wpd, ob, ma, &wpd->material_ubo_data_curr[mat_id], color_type);
195 
196  DRWShadingGroup *grp = prepass->common_shgrp;
197  *grp_mat = grp = DRW_shgroup_create_sub(grp);
198  DRW_shgroup_uniform_block(grp, "materials_data", wpd->material_ubo_curr);
199  DRW_shgroup_uniform_int_copy(grp, "materialIndex", mat_id);
200  return grp;
201  }
203  const bool transp = wpd->shading.xray_alpha < 1.0f;
204  DRWShadingGroup *grp = wpd->prepass[transp][infront][datatype].vcol_shgrp;
205  return grp;
206  }
207  default: {
208  /* For now, we use the same ubo for material and object coloring but with different indices.
209  * This means they are mutually exclusive. */
210  BLI_assert(
212 
213  uint32_t mat_id, id = DRW_object_resource_id_get(ob);
214 
215  bool resource_changed = workbench_material_chunk_select(wpd, id, &mat_id);
216  workbench_material_ubo_data(wpd, ob, NULL, &wpd->material_ubo_data_curr[mat_id], color_type);
217 
218  const bool transp = wpd->shading.xray_alpha < 1.0f || ob->color[3] < 1.0f;
219  DRWShadingGroup **grp = &wpd->prepass[transp][infront][datatype].common_shgrp;
220  if (resource_changed) {
221  *grp = DRW_shgroup_create_sub(*grp);
222  DRW_shgroup_uniform_block(*grp, "materials_data", wpd->material_ubo_curr);
223  }
224  if (r_transp && transp) {
225  *r_transp = true;
226  }
227  return *grp;
228  }
229  }
230 }
231 
233  Object *ob,
234  int mat_nr,
235  Image *ima,
236  ImageUser *iuser,
238  eWORKBENCH_DataType datatype)
239 {
240  GPUTexture *tex = NULL, *tex_tile_data = NULL;
241 
242  if (ima == NULL) {
243  workbench_material_get_image(ob, mat_nr, &ima, &iuser, &sampler);
244  }
245 
246  if (ima) {
247  if (ima->source == IMA_SRC_TILED) {
248  tex = BKE_image_get_gpu_tiles(ima, iuser, NULL);
249  tex_tile_data = BKE_image_get_gpu_tilemap(ima, iuser, NULL);
250  }
251  else {
252  tex = BKE_image_get_gpu_texture(ima, iuser, NULL);
253  }
254  }
255 
256  if (tex == NULL) {
257  tex = wpd->dummy_image_tx;
258  }
259 
260  const bool infront = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
261  const bool transp = wpd->shading.xray_alpha < 1.0f;
262  WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype];
263 
264  DRWShadingGroup **grp_tex = NULL;
265  /* A hash-map stores image shgroups to pack all similar drawcalls together. */
266  if (BLI_ghash_ensure_p(prepass->material_hash, tex, (void ***)&grp_tex)) {
267  return *grp_tex;
268  }
269 
270  DRWShadingGroup *grp = (tex_tile_data) ? prepass->image_tiled_shgrp : prepass->image_shgrp;
271 
272  *grp_tex = grp = DRW_shgroup_create_sub(grp);
273  if (tex_tile_data) {
274  DRW_shgroup_uniform_texture_ex(grp, "imageTileArray", tex, sampler);
275  DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data);
276  }
277  else {
278  DRW_shgroup_uniform_texture_ex(grp, "imageTexture", tex, sampler);
279  }
280  DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL));
281  DRW_shgroup_uniform_float_copy(grp, "imageTransparencyCutoff", 0.1f);
282  return grp;
283 }
struct GPUTexture * BKE_image_get_gpu_tiles(struct Image *image, struct ImageUser *iuser, struct ImBuf *ibuf)
Definition: image_gpu.cc:443
struct GPUTexture * BKE_image_get_gpu_texture(struct Image *image, struct ImageUser *iuser, struct ImBuf *ibuf)
Definition: image_gpu.cc:438
struct GPUTexture * BKE_image_get_gpu_tilemap(struct Image *image, struct ImageUser *iuser, struct ImBuf *ibuf)
Definition: image_gpu.cc:448
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
Definition: material.c:707
struct Material * BKE_material_default_empty(void)
Definition: material.c:2041
#define SH_NODE_TEX_ENVIRONMENT
Definition: BKE_node.h:1128
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define BLI_INLINE
A dynamically sized string ADT.
unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr)
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:755
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition: BLI_hash.h:94
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition: math_color.c:49
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
void * BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_memblock.c:176
void * BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition: BLI_memblock.c:115
unsigned int uint
Definition: BLI_sys_types.h:67
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
@ IMA_ALPHA_PREMUL
@ IMA_SRC_TILED
#define SHD_IMAGE_EXTENSION_CLIP
#define SHD_IMAGE_EXTENSION_REPEAT
#define SHD_INTERP_CLOSEST
@ OB_DRAW_IN_FRONT
eV3DShadingColorType
@ V3D_SHADING_TEXTURE_COLOR
@ V3D_SHADING_VERTEX_COLOR
@ V3D_SHADING_MATERIAL_COLOR
@ V3D_SHADING_OBJECT_COLOR
@ V3D_SHADING_RANDOM_COLOR
@ V3D_SHADING_SINGLE_COLOR
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
bool ED_object_get_active_image(struct Object *ob, int mat_nr, struct Image **r_ima, struct ImageUser **r_iuser, struct bNode **r_node, struct bNodeTree **r_ntree)
Definition: uvedit_ops.c:109
eGPUSamplerState
Definition: GPU_texture.h:25
@ GPU_SAMPLER_REPEAT
Definition: GPU_texture.h:37
@ GPU_SAMPLER_FILTER
Definition: GPU_texture.h:27
@ GPU_SAMPLER_CLAMP_BORDER
Definition: GPU_texture.h:32
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Apply a color transformation in the HSV color model Specular Similar to the Principled BSDF node but uses the specular workflow instead of metallic
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its hue
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block SH_NODE_TEX_IMAGE
short source
char alpha_mode
OperationNode * node
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_uniform_texture_ex(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex, eGPUSamplerState sampler_state)
uint32_t DRW_object_resource_id_get(Object *UNUSED(ob))
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
#define sqrtf(x)
Definition: metal/compat.h:243
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
#define hash
Definition: noise.c:153
unsigned int uint32_t
Definition: stdint.h:80
struct Library * lib
Definition: DNA_ID.h:372
char name[66]
Definition: DNA_ID.h:378
char filepath[1024]
Definition: DNA_ID.h:461
float color[4]
float single_color[3]
struct DRWShadingGroup * vcol_shgrp
struct DRWShadingGroup * image_tiled_shgrp
struct DRWShadingGroup * common_shgrp
struct GHash * material_hash
struct DRWShadingGroup * image_shgrp
struct GPUUniformBuf * material_ubo_curr
struct BLI_memblock * material_ubo_data
struct BLI_memblock * material_ubo
struct GPUTexture * dummy_image_tx
WORKBENCH_UBO_Material * material_ubo_data_curr
WORKBENCH_Prepass prepass[2][2][WORKBENCH_DATATYPE_MAX]
GPUUniformBuf * workbench_material_ubo_alloc(WORKBENCH_PrivateData *wpd)
BLI_INLINE void workbench_material_get_image(Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, eGPUSamplerState *r_sampler)
DRWShadingGroup * workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, Image *ima, ImageUser *iuser, eGPUSamplerState sampler, eWORKBENCH_DataType datatype)
BLI_INLINE Material * workbench_object_material_get(Object *ob, int mat_nr)
void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd, Object *ob, Material *mat, WORKBENCH_UBO_Material *data, eV3DShadingColorType color_type)
BLI_INLINE bool workbench_material_chunk_select(WORKBENCH_PrivateData *wpd, uint32_t id, uint32_t *r_mat_id)
DRWShadingGroup * workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, eV3DShadingColorType color_type, eWORKBENCH_DataType datatype, bool *r_transp)
#define HSV_VALUE
#define HSV_SATURATION
eWORKBENCH_DataType