Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Rood <dev@lucarood.com>2017-05-09 17:23:47 +0300
committerLuca Rood <dev@lucarood.com>2017-05-12 17:14:55 +0300
commit0eb32ab22809d9c0c41bfff5082f58b1a7aa9965 (patch)
tree8dc78f984f1d8c2bc48610708b08818e077a0436
parentbd31b1f182c946f98478d6de8db890e158bc62ec (diff)
Implement hair drawing with Draw Manager in Clay engine
Part of T51378
-rw-r--r--release/scripts/startup/bl_ui/properties_collection.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py10
-rw-r--r--source/blender/blenkernel/BKE_particle.h7
-rw-r--r--source/blender/blenkernel/intern/particle.c19
-rw-r--r--source/blender/blenkernel/intern/particle_system.c2
-rw-r--r--source/blender/blenloader/intern/readfile.c2
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c211
-rw-r--r--source/blender/draw/engines/clay/shaders/particle_strand_frag.glsl46
-rw-r--r--source/blender/draw/engines/clay/shaders/particle_vert.glsl34
-rw-r--r--source/blender/draw/intern/draw_cache.c11
-rw-r--r--source/blender/draw/intern/draw_cache.h3
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h7
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c282
-rw-r--r--source/blender/draw/intern/draw_manager.c6
-rw-r--r--source/blender/draw/modes/object_mode.c2
-rw-r--r--source/blender/makesdna/DNA_particle_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c61
18 files changed, 715 insertions, 3 deletions
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
index dc02037586c..4e545778162 100644
--- a/release/scripts/startup/bl_ui/properties_collection.py
+++ b/release/scripts/startup/bl_ui/properties_collection.py
@@ -68,6 +68,16 @@ class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
col.template_override_property(collection_props, scene_props, "ssao_factor_edge")
col.template_override_property(collection_props, scene_props, "ssao_distance")
col.template_override_property(collection_props, scene_props, "ssao_attenuation")
+ col.template_override_property(collection_props, scene_props, "world_intensity")
+
+ col.separator()
+ col.label("Hair Settings:")
+ col.template_override_property(collection_props, scene_props, "diffuse_intensity")
+ col.template_override_property(collection_props, scene_props, "specular_intensity")
+ col.template_override_property(collection_props, scene_props, "specular_hardness")
+ col.template_override_property(collection_props, scene_props, "color_randomicity")
+ col.template_override_property(collection_props, scene_props, "hair_diffuse_color")
+ col.template_override_property(collection_props, scene_props, "hair_specular_color")
class COLLECTION_PT_object_mode_settings(CollectionButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 0431cd51663..e56c559a163 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -615,6 +615,16 @@ class RENDER_PT_clay_collection_settings(RenderButtonsPanel, Panel):
col.prop(props, "ssao_distance")
col.prop(props, "ssao_attenuation")
+ col.separator()
+ col.label("Hair Settings:")
+ col.prop(props, "world_intensity")
+ col.prop(props, "diffuse_intensity")
+ col.prop(props, "specular_intensity")
+ col.prop(props, "specular_hardness")
+ col.prop(props, "color_randomicity")
+ col.prop(props, "hair_diffuse_color")
+ col.prop(props, "hair_specular_color")
+
class RENDER_PT_eevee_poststack_settings(RenderButtonsPanel, Panel):
bl_label = "Post Process Stack"
COMPAT_ENGINES = {'BLENDER_EEVEE'}
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 2b6a84a2f87..90f7703b967 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -479,3 +479,10 @@ void BKE_particle_system_eval(struct EvaluationContext *eval_ctx,
struct ParticleSystem *psys);
#endif
+
+/* Draw Cache */
+enum {
+ BKE_PARTICLE_BATCH_DIRTY_ALL = 0,
+};
+void BKE_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
+void BKE_particle_batch_cache_free(struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index b6f5f11846b..71257fdc4b4 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -4305,3 +4305,22 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_EDITED;
}
}
+
+
+
+/* Draw Engine */
+void (*BKE_particle_batch_cache_dirty_cb)(ParticleSystem *psys, int mode) = NULL;
+void (*BKE_particle_batch_cache_free_cb)(ParticleSystem *psys) = NULL;
+
+void BKE_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_dirty_cb(psys, mode);
+ }
+}
+void BKE_particle_batch_cache_free(ParticleSystem *psys)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_free_cb(psys);
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index c26ac056499..2da0b6aeb4f 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4321,6 +4321,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
/* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
if (psys->renderdata==0)
invert_m4_m4(psys->imat, ob->obmat);
+
+ BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
/* ID looper */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index bd2180c28a2..cac1ec084b5 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4372,6 +4372,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
psys->tree = NULL;
psys->bvhtree = NULL;
+
+ psys->batch_cache = NULL;
}
return;
}
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index fa625f608a1..45c52187f72 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -59,6 +59,7 @@ set(SRC
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_lattice.c
intern/draw_cache_impl_mesh.c
+ intern/draw_cache_impl_particles.c
intern/draw_common.c
intern/draw_manager.c
intern/draw_manager_text.c
@@ -108,6 +109,8 @@ data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+data_to_c_simple(engines/clay/shaders/particle_vert.glsl SRC)
+data_to_c_simple(engines/clay/shaders/particle_strand_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index a405f26ea8e..95ddb3cc6fa 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -21,9 +21,12 @@
#include "DRW_render.h"
+#include "DNA_particle_types.h"
+
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
+#include "BKE_particle.h"
#include "BLI_dynstr.h"
#include "BLI_rand.h"
@@ -43,6 +46,8 @@
extern char datatoc_clay_frag_glsl[];
extern char datatoc_clay_vert_glsl[];
extern char datatoc_ssao_alchemy_glsl[];
+extern char datatoc_particle_vert_glsl[];
+extern char datatoc_particle_strand_frag_glsl[];
/* *********** LISTS *********** */
@@ -59,24 +64,45 @@ typedef struct CLAY_UBO_Material {
} CLAY_UBO_Material; /* 48 bytes */
BLI_STATIC_ASSERT_ALIGN(CLAY_UBO_Material, 16);
+typedef struct CLAY_HAIR_UBO_Material {
+ float hair_world;
+ float hair_diffuse;
+ float hair_specular;
+ float hair_hardness;
+ float hair_randomicity;
+ float pad1[3];
+ float hair_diffuse_color[3];
+ float pad2;
+ float hair_specular_color[3];
+ float pad3;
+} CLAY_HAIR_UBO_Material; /* 48 bytes */
+
#define MAX_CLAY_MAT 512 /* 512 = 9 bit material id */
typedef struct CLAY_UBO_Storage {
CLAY_UBO_Material materials[MAX_CLAY_MAT];
} CLAY_UBO_Storage;
+typedef struct CLAY_HAIR_UBO_Storage {
+ CLAY_HAIR_UBO_Material materials[MAX_CLAY_MAT];
+} CLAY_HAIR_UBO_Storage;
+
/* GPUViewport.storage
* Is freed everytime the viewport engine changes */
typedef struct CLAY_Storage {
/* Materials Parameter UBO */
CLAY_UBO_Storage mat_storage;
+ CLAY_HAIR_UBO_Storage hair_mat_storage;
int ubo_current_id;
+ int hair_ubo_current_id;
DRWShadingGroup *shgrps[MAX_CLAY_MAT];
+ DRWShadingGroup *hair_shgrps[MAX_CLAY_MAT];
} CLAY_Storage;
typedef struct CLAY_StorageList {
struct CLAY_Storage *storage;
struct GPUUniformBuffer *mat_ubo;
+ struct GPUUniformBuffer *hair_mat_ubo;
struct CLAY_PrivateData *g_data;
} CLAY_StorageList;
@@ -99,6 +125,7 @@ typedef struct CLAY_PassList {
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
struct DRWPass *clay_pass;
+ struct DRWPass *hair_pass;
} CLAY_PassList;
typedef struct CLAY_Data {
@@ -116,6 +143,7 @@ static struct {
struct GPUShader *depth_sh;
/* Shading Pass */
struct GPUShader *clay_sh;
+ struct GPUShader *hair_sh;
/* Matcap textures */
struct GPUTexture *matcap_array;
@@ -129,8 +157,12 @@ static struct {
struct GPUTexture *jitter_tx;
struct GPUTexture *sampling_tx;
+ /* hair */
+ float hair_light[3];
+
/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
int ubo_mat_idxs[MAX_CLAY_MAT];
+ int hair_ubo_mat_idxs[MAX_CLAY_MAT];
} e_data = {NULL}; /* Engine data */
typedef struct CLAY_PrivateData {
@@ -140,6 +172,7 @@ typedef struct CLAY_PrivateData {
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp_cull_select;
DRWShadingGroup *depth_shgrp_cull_active;
+ DRWShadingGroup *hair;
} CLAY_PrivateData; /* Transient data */
/* Functions */
@@ -324,6 +357,10 @@ static void CLAY_engine_init(void *vedata)
MEM_freeN(matcap_with_ao);
}
+ if (!e_data.hair_sh) {
+ e_data.hair_sh = DRW_shader_create(datatoc_particle_vert_glsl, NULL, datatoc_particle_strand_frag_glsl, "#define MAX_MATERIAL 512\n");
+ }
+
if (!stl->storage) {
stl->storage = MEM_callocN(sizeof(CLAY_Storage), "CLAY_Storage");
}
@@ -332,6 +369,10 @@ static void CLAY_engine_init(void *vedata)
stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
}
+ if (!stl->hair_mat_ubo) {
+ stl->hair_mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_HAIR_UBO_Storage), NULL);
+ }
+
if (e_data.ubo_mat_idxs[1] == 0) {
/* Just int to have pointers to them */
for (int i = 0; i < MAX_CLAY_MAT; ++i) {
@@ -413,6 +454,13 @@ static void CLAY_engine_init(void *vedata)
e_data.cached_sample_num = ssao_samples;
}
}
+
+ /* hair setup */
+ {
+ e_data.hair_light[0] = 1.0f;
+ e_data.hair_light[1] = -0.5f;
+ e_data.hair_light[2] = -0.7f;
+ }
}
static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id)
@@ -437,6 +485,16 @@ static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, in
return grp;
}
+static DRWShadingGroup *CLAY_hair_shgroup_create(DRWPass *pass, int *material_id)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.hair_sh, pass);
+
+ DRW_shgroup_uniform_vec3(grp, "light", e_data.hair_light, 1);
+ DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
+
+ return grp;
+}
+
static int search_mat_to_ubo(
CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
float matcap_val, float ssao_distance, float ssao_factor_cavity,
@@ -464,6 +522,36 @@ static int search_mat_to_ubo(
return -1;
}
+static int search_hair_mat_to_ubo(CLAY_Storage *storage, float hair_world, float hair_diffuse, float hair_specular,
+ float hair_hardness, float hair_randomicity, const float *hair_diff_color,
+ const float *hair_spec_color)
+{
+ /* For now just use a linear search and test all parameters */
+ /* TODO make a hash table */
+ for (int i = 0; i < storage->hair_ubo_current_id; ++i) {
+ CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[i];
+
+ if ((ubo->hair_world == hair_world) &&
+ (ubo->hair_diffuse == hair_diffuse) &&
+ (ubo->hair_specular == hair_specular) &&
+ (ubo->hair_hardness == hair_hardness) &&
+ (ubo->hair_randomicity == hair_randomicity) &&
+ (ubo->hair_diffuse_color[0] == hair_diff_color[0]) &&
+ (ubo->hair_diffuse_color[1] == hair_diff_color[1]) &&
+ (ubo->hair_diffuse_color[2] == hair_diff_color[2]) &&
+ (ubo->hair_diffuse_color[3] == hair_diff_color[3]) &&
+ (ubo->hair_specular_color[0] == hair_spec_color[0]) &&
+ (ubo->hair_specular_color[1] == hair_spec_color[1]) &&
+ (ubo->hair_specular_color[2] == hair_spec_color[2]) &&
+ (ubo->hair_specular_color[3] == hair_spec_color[3]))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
float matcap_val, float ssao_distance, float ssao_factor_cavity,
float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
@@ -491,6 +579,32 @@ static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap
return id;
}
+static int push_hair_mat_to_ubo(CLAY_Storage *storage, float hair_world, float hair_diffuse, float hair_specular,
+ float hair_hardness, float hair_randomicity, const float *hair_diff_color,
+ const float *hair_spec_color)
+{
+ int id = storage->hair_ubo_current_id;
+ CLAY_HAIR_UBO_Material *ubo = &storage->hair_mat_storage.materials[id];
+
+ ubo->hair_world = hair_world;
+ ubo->hair_diffuse = hair_diffuse;
+ ubo->hair_specular = hair_specular;
+ ubo->hair_hardness = hair_hardness;
+ ubo->hair_randomicity = hair_randomicity;
+ ubo->hair_diffuse_color[0] = hair_diff_color[0];
+ ubo->hair_diffuse_color[1] = hair_diff_color[1];
+ ubo->hair_diffuse_color[2] = hair_diff_color[2];
+ ubo->hair_diffuse_color[3] = hair_diff_color[3];
+ ubo->hair_specular_color[0] = hair_spec_color[0];
+ ubo->hair_specular_color[1] = hair_spec_color[1];
+ ubo->hair_specular_color[2] = hair_spec_color[2];
+ ubo->hair_specular_color[3] = hair_spec_color[3];
+
+ storage->hair_ubo_current_id++;
+
+ return id;
+}
+
static int mat_in_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
float matcap_val, float ssao_distance, float ssao_factor_cavity,
float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
@@ -510,6 +624,23 @@ static int mat_in_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue,
return id;
}
+static int hair_mat_in_ubo(CLAY_Storage *storage, float hair_world, float hair_diffuse, float hair_specular,
+ float hair_hardness, float hair_randomicity, const float *hair_diff_color,
+ const float *hair_spec_color)
+{
+ /* Search material in UBO */
+ int id = search_hair_mat_to_ubo(storage, hair_world, hair_diffuse, hair_specular,
+ hair_hardness, hair_randomicity, hair_diff_color, hair_spec_color);
+
+ /* if not found create it */
+ if (id == -1) {
+ id = push_hair_mat_to_ubo(storage, hair_world, hair_diffuse, hair_specular,
+ hair_hardness, hair_randomicity, hair_diff_color, hair_spec_color);
+ }
+
+ return id;
+}
+
static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
{
DRWShadingGroup **shgrps = stl->storage->shgrps;
@@ -541,6 +672,34 @@ static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLA
return shgrps[id];
}
+static DRWShadingGroup *CLAY_hair_shgrp_get(Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
+{
+ DRWShadingGroup **hair_shgrps = stl->storage->hair_shgrps;
+ IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
+
+ /* Default Settings */
+ float hair_world = BKE_collection_engine_property_value_get_float(props, "world_intensity");
+ float hair_diffuse = BKE_collection_engine_property_value_get_float(props, "diffuse_intensity");
+ float hair_specular = BKE_collection_engine_property_value_get_float(props, "specular_intensity");
+ float hair_hardness = BKE_collection_engine_property_value_get_float(props, "specular_hardness");
+ float hair_randomicity = BKE_collection_engine_property_value_get_float(props, "color_randomicity");
+ const float *hair_diff_color = BKE_collection_engine_property_value_get_float_array(props, "hair_diffuse_color");
+ const float *hair_spec_color = BKE_collection_engine_property_value_get_float_array(props, "hair_specular_color");
+
+ int hair_id = hair_mat_in_ubo(stl->storage, hair_world, hair_diffuse, hair_specular,
+ hair_hardness, hair_randomicity, hair_diff_color, hair_spec_color);
+
+ if (hair_shgrps[hair_id] == NULL) {
+ hair_shgrps[hair_id] = CLAY_hair_shgroup_create(psl->hair_pass, &e_data.hair_ubo_mat_idxs[hair_id]);
+ /* if it's the first shgrp, pass bind the material UBO */
+ if (stl->storage->hair_ubo_current_id == 1) {
+ DRW_shgroup_uniform_block(hair_shgrps[0], "material_block", stl->hair_mat_ubo);
+ }
+ }
+
+ return hair_shgrps[hair_id];
+}
+
static void CLAY_cache_init(void *vedata)
{
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
@@ -568,6 +727,13 @@ static void CLAY_cache_init(void *vedata)
stl->storage->ubo_current_id = 0;
memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
}
+
+ /* Hair Pass */
+ {
+ psl->hair_pass = DRW_pass_create("Hair Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->storage->hair_ubo_current_id = 0;
+ memset(stl->storage->hair_shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
+ }
}
static void CLAY_cache_populate(void *vedata, Object *ob)
@@ -575,7 +741,7 @@ static void CLAY_cache_populate(void *vedata, Object *ob)
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- DRWShadingGroup *clay_shgrp;
+ DRWShadingGroup *clay_shgrp, *hair_shgrp;
if (!DRW_object_is_renderable(ob))
return;
@@ -592,6 +758,35 @@ static void CLAY_cache_populate(void *vedata, Object *ob)
clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl);
DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
}
+
+ if (ob->type == OB_MESH) {
+ for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
+ draw_as = PART_DRAW_DOT;
+ }
+
+ switch (draw_as) {
+ case PART_DRAW_PATH:
+ geom = DRW_cache_particles_get_hair(psys);
+ break;
+ default:
+ geom = NULL;
+ break;
+ }
+
+ if (geom) {
+ static float mat[4][4];
+ unit_m4(mat);
+ hair_shgrp = CLAY_hair_shgrp_get(ob, stl, psl);
+ DRW_shgroup_call_add(hair_shgrp, geom, mat);
+ }
+ }
+ }
+ }
}
static void CLAY_cache_finish(void *vedata)
@@ -599,6 +794,7 @@ static void CLAY_cache_finish(void *vedata)
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
+ DRW_uniformbuffer_update(stl->hair_mat_ubo, &stl->storage->hair_mat_storage);
}
static void CLAY_draw_scene(void *vedata)
@@ -620,6 +816,7 @@ static void CLAY_draw_scene(void *vedata)
/* Pass 3 : Shading */
DRW_draw_pass(psl->clay_pass);
+ DRW_draw_pass(psl->hair_pass);
}
static void CLAY_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
@@ -628,6 +825,9 @@ static void CLAY_layer_collection_settings_create(RenderEngine *UNUSED(engine),
props->type == IDP_GROUP &&
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+ static float default_hair_diffuse_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ static float default_hair_specular_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
BKE_collection_engine_property_add_int(props, "matcap_icon", ICON_MATCAP_01);
BKE_collection_engine_property_add_int(props, "type", CLAY_MATCAP_NONE);
BKE_collection_engine_property_add_float(props, "matcap_rotation", 0.0f);
@@ -637,7 +837,13 @@ static void CLAY_layer_collection_settings_create(RenderEngine *UNUSED(engine),
BKE_collection_engine_property_add_float(props, "ssao_distance", 0.2f);
BKE_collection_engine_property_add_float(props, "ssao_attenuation", 1.0f);
BKE_collection_engine_property_add_float(props, "ssao_factor_cavity", 1.0f);
- BKE_collection_engine_property_add_float(props, "ssao_factor_edge", 1.0f);
+ BKE_collection_engine_property_add_float(props, "world_intensity", 0.1f);
+ BKE_collection_engine_property_add_float(props, "diffuse_intensity", 0.2f);
+ BKE_collection_engine_property_add_float(props, "specular_intensity", 0.3f);
+ BKE_collection_engine_property_add_float(props, "specular_hardness", 4.0f);
+ BKE_collection_engine_property_add_float(props, "color_randomicity", 0.0f);
+ BKE_collection_engine_property_add_float_array(props, "hair_diffuse_color", default_hair_diffuse_color, 4);
+ BKE_collection_engine_property_add_float_array(props, "hair_specular_color", default_hair_specular_color, 4);
}
static void CLAY_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
@@ -652,6 +858,7 @@ static void CLAY_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPro
static void CLAY_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.clay_sh);
+ DRW_SHADER_FREE_SAFE(e_data.hair_sh);
DRW_TEXTURE_FREE_SAFE(e_data.matcap_array);
DRW_TEXTURE_FREE_SAFE(e_data.jitter_tx);
DRW_TEXTURE_FREE_SAFE(e_data.sampling_tx);
diff --git a/source/blender/draw/engines/clay/shaders/particle_strand_frag.glsl b/source/blender/draw/engines/clay/shaders/particle_strand_frag.glsl
new file mode 100644
index 00000000000..f1ce3a55699
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/particle_strand_frag.glsl
@@ -0,0 +1,46 @@
+
+uniform vec3 light;
+
+/* Material Parameters packed in an UBO */
+struct Material {
+ vec4 one;
+ vec4 two;
+ vec4 hair_diffuse_color;
+ vec4 hair_specular_color;
+};
+
+layout(std140) uniform material_block {
+ Material shader_param[MAX_MATERIAL];
+};
+
+uniform int mat_id;
+
+#define world shader_param[mat_id].one.x
+#define diffuse shader_param[mat_id].one.y
+#define specular shader_param[mat_id].one.z
+#define hardness shader_param[mat_id].one.w
+#define randomicity shader_param[mat_id].two.x
+#define diffColor shader_param[mat_id].hair_diffuse_color
+#define specColor shader_param[mat_id].hair_specular_color
+
+in vec3 normal;
+in vec3 viewPosition;
+flat in float colRand;
+out vec4 fragColor;
+
+void main()
+{
+ vec3 normal = normalize(normal);
+ vec3 specVec = normalize(normalize(light) + normalize(viewPosition));
+ float specCos = dot(specVec, normal);
+ float diffCos = dot(normalize(light), normal);
+ float maxChan = max(max(diffColor.r, diffColor.g), diffColor.b);
+ float diff;
+ float spec;
+ diff = world; /* world */
+ diff += sqrt(1.0 - diffCos*diffCos) * diffuse; /* diffuse */
+ spec = pow(1.0 - abs(specCos), hardness) * specular; /* specular */
+ fragColor = (diffColor - (colRand * maxChan * randomicity)) * diff; /* add diffuse */
+ fragColor += specColor * spec; /* add specular */
+ fragColor = clamp(fragColor, 0.0, 1.0);
+}
diff --git a/source/blender/draw/engines/clay/shaders/particle_vert.glsl b/source/blender/draw/engines/clay/shaders/particle_vert.glsl
new file mode 100644
index 00000000000..c10cade330c
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/particle_vert.glsl
@@ -0,0 +1,34 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ModelViewMatrix;
+
+in vec3 pos;
+in vec3 nor;
+in int ind;
+out vec3 normal;
+out vec3 viewPosition;
+flat out float colRand;
+
+/* TODO: This function yields great distribution, but might be a bit inefficient because of the 4 trig ops.
+ * Something more efficient would be nice */
+float rand(int seed)
+{
+ vec4 nums = vec4(0.0);
+ nums.x = mod(tan(mod(float(seed + 1) * 238965.0, 342.0)), 1.0) + 0.01;
+ nums.y = mod(tan(mod(float(seed + 1) * 34435643.0, 756.0)), 1.0) + 0.01;
+ nums.z = mod(tan(mod(float(seed + 1) * 4356757.0, 456.0)), 1.0) + 0.01;
+ nums.w = mod(tan(mod(float(seed + 1) * 778679.0, 987.0)), 1.0) + 0.01;
+
+ float num = mod((nums.x / nums.y) + 1 - (nums.z / nums.w), 1.0);
+ num += 0.5;
+ return mod(num, 1.0);
+}
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ normal = normalize(NormalMatrix * nor);
+ viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
+ colRand = rand(ind);
+}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 5160dc97608..f5c02f244da 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -28,6 +28,7 @@
#include "DNA_mesh_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -1977,3 +1978,13 @@ Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Particles
+ * \{ */
+
+Batch *DRW_cache_particles_get_hair(ParticleSystem *psys)
+{
+ return DRW_particles_batch_cache_get_hair(psys);
+}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 00031560113..0da09bcc332 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -128,4 +128,7 @@ struct Batch *DRW_cache_lattice_verts_get(struct Object *ob);
struct Batch *DRW_cache_lattice_wire_get(struct Object *ob);
struct Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob);
+/* Particles */
+struct Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys);
+
#endif /* __DRAW_CACHE_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index ddcc55fd85e..2363d097261 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -29,6 +29,7 @@
struct Batch;
struct ListBase;
struct CurveCache;
+struct ParticleSystem;
struct Curve;
struct Lattice;
@@ -44,6 +45,9 @@ void DRW_mesh_batch_cache_free(struct Mesh *me);
void DRW_lattice_batch_cache_dirty(struct Lattice *lt, int mode);
void DRW_lattice_batch_cache_free(struct Lattice *lt);
+void DRW_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
+void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
+
/* Curve */
struct Batch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache);
struct Batch *DRW_curve_batch_cache_get_normal_edge(
@@ -85,4 +89,7 @@ struct Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
+/* Particles */
+struct Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys);
+
#endif /* __DRAW_CACHE_IMPL_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
new file mode 100644
index 00000000000..779f2f78c1f
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -0,0 +1,282 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_particles.c
+ * \ingroup draw
+ *
+ * \brief Particle API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_particle_types.h"
+
+#include "BKE_particle.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h" /* own include */
+
+static void particle_batch_cache_clear(ParticleSystem *psys);
+
+/* ---------------------------------------------------------------------- */
+/* Particle Batch Cache */
+
+typedef struct ParticleBatchCache {
+ VertexBuffer *pos;
+ ElementList *segments;
+
+ Batch *hairs;
+
+ int segment_count;
+ int point_count;
+
+ /* settings to determine if cache is invalid */
+ bool is_dirty;
+} ParticleBatchCache;
+
+/* Batch cache management. */
+
+static bool particle_batch_cache_valid(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_dirty == false) {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+ return true;
+}
+
+static void particle_batch_cache_init(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+
+ if (!cache) {
+ cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
+ cache->is_dirty = false;
+}
+
+static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys)
+{
+ if (!particle_batch_cache_valid(psys)) {
+ particle_batch_cache_clear(psys);
+ particle_batch_cache_init(psys);
+ }
+ return psys->batch_cache;
+}
+
+void DRW_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+ if (cache == NULL) {
+ return;
+ }
+ switch (mode) {
+ case BKE_PARTICLE_BATCH_DIRTY_ALL:
+ cache->is_dirty = true;
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
+
+static void particle_batch_cache_clear(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = psys->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ BATCH_DISCARD_SAFE(cache->hairs);
+
+ VERTEXBUFFER_DISCARD_SAFE(cache->pos);
+ ELEMENTLIST_DISCARD_SAFE(cache->segments);
+}
+
+void DRW_particle_batch_cache_free(ParticleSystem *psys)
+{
+ particle_batch_cache_clear(psys);
+ MEM_SAFE_FREE(psys->batch_cache);
+}
+
+static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache)
+{
+ if (cache->pos == NULL || cache->segments == NULL) {
+ cache->segment_count = 0;
+ cache->point_count = 0;
+
+ if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
+ for (int i = 0; i < psys->totpart; i++) {
+ ParticleCacheKey *path = psys->pathcache[i];
+
+ if (path->segments) {
+ cache->segment_count += path->segments;
+ cache->point_count += path->segments + 1;
+ }
+ }
+ }
+
+ if (psys->childcache) {
+ int child_count = psys->totchild * psys->part->disp / 100;
+
+ for (int i = 0; i < child_count; i++) {
+ ParticleCacheKey *path = psys->childcache[i];
+
+ if (path->segments) {
+ cache->segment_count += path->segments;
+ cache->point_count += path->segments + 1;
+ }
+ }
+ }
+ }
+}
+
+/* Batch cache usage. */
+static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ParticleBatchCache *cache)
+{
+ if (cache->pos == NULL || cache->segments == NULL) {
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, nor_id, ind_id;
+ int curr_point = 0;
+
+ VERTEXBUFFER_DISCARD_SAFE(cache->pos);
+ ELEMENTLIST_DISCARD_SAFE(cache->segments);
+
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ nor_id = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT);
+ ind_id = VertexFormat_add_attrib(&format, "ind", COMP_I32, 1, KEEP_INT);
+ }
+
+ cache->pos = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(cache->pos, cache->point_count);
+
+ ElementListBuilder elb;
+ ElementListBuilder_init(&elb, PRIM_LINES, cache->segment_count, cache->point_count);
+
+ if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
+ for (int i = 0; i < psys->totpart; i++) {
+ ParticleCacheKey *path = psys->pathcache[i];
+
+ if (path->segments) {
+ float tangent[3];
+
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
+
+ VertexBuffer_set_attrib(cache->pos, pos_id, curr_point, path[j].co);
+ VertexBuffer_set_attrib(cache->pos, nor_id, curr_point, tangent);
+ VertexBuffer_set_attrib(cache->pos, ind_id, curr_point, &i);
+
+ add_line_vertices(&elb, curr_point, curr_point + 1);
+
+ curr_point++;
+ }
+
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+
+ VertexBuffer_set_attrib(cache->pos, pos_id, curr_point, path[path->segments].co);
+ VertexBuffer_set_attrib(cache->pos, nor_id, curr_point, tangent);
+ VertexBuffer_set_attrib(cache->pos, ind_id, curr_point, &i);
+
+ curr_point++;
+ }
+ }
+ }
+
+ if (psys->childcache) {
+ int child_count = psys->totchild * psys->part->disp / 100;
+
+ for (int i = 0, x = psys->totpart; i < child_count; i++, x++) {
+ ParticleCacheKey *path = psys->childcache[i];
+ float tangent[3];
+
+ if (path->segments) {
+ for (int j = 0; j < path->segments; j++) {
+ if (j == 0) {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
+ }
+ else {
+ sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
+ }
+
+ VertexBuffer_set_attrib(cache->pos, pos_id, curr_point, path[j].co);
+ VertexBuffer_set_attrib(cache->pos, nor_id, curr_point, tangent);
+ VertexBuffer_set_attrib(cache->pos, ind_id, curr_point, &x);
+
+ add_line_vertices(&elb, curr_point, curr_point + 1);
+
+ curr_point++;
+ }
+
+ sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
+
+ VertexBuffer_set_attrib(cache->pos, pos_id, curr_point, path[path->segments].co);
+ VertexBuffer_set_attrib(cache->pos, nor_id, curr_point, tangent);
+ VertexBuffer_set_attrib(cache->pos, ind_id, curr_point, &x);
+
+ curr_point++;
+ }
+ }
+ }
+
+ cache->segments = ElementList_build(&elb);
+ }
+}
+
+Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys)
+{
+ ParticleBatchCache *cache = particle_batch_cache_get(psys);
+
+ if (cache->hairs == NULL) {
+ ensure_seg_pt_count(psys, cache);
+ particle_batch_cache_ensure_pos_and_seg(psys, cache);
+ cache->hairs = Batch_create(PRIM_LINES, cache->pos, cache->segments);
+ }
+
+ return cache->hairs;
+}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index b4efadc077d..92f72bc6664 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -3100,6 +3100,9 @@ void DRW_engines_register(void)
/* BKE: lattice.c */
extern void *BKE_lattice_batch_cache_dirty_cb;
extern void *BKE_lattice_batch_cache_free_cb;
+ /* BKE: particle.c */
+ extern void *BKE_particle_batch_cache_dirty_cb;
+ extern void *BKE_particle_batch_cache_free_cb;
BKE_curve_batch_cache_dirty_cb = DRW_curve_batch_cache_dirty;
BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free;
@@ -3109,6 +3112,9 @@ void DRW_engines_register(void)
BKE_lattice_batch_cache_dirty_cb = DRW_lattice_batch_cache_dirty;
BKE_lattice_batch_cache_free_cb = DRW_lattice_batch_cache_free;
+
+ BKE_particle_batch_cache_dirty_cb = DRW_particle_batch_cache_dirty;
+ BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free;
}
}
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index ff8118c6378..7fe6ce20608 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -31,6 +31,7 @@
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@@ -178,7 +179,6 @@ typedef struct OBJECT_PrivateData{
DRWShadingGroup *wire_select;
DRWShadingGroup *wire_select_group;
DRWShadingGroup *wire_transform;
-
} OBJECT_PrivateData; /* Transient data */
static struct {
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 1deb9bf3787..5d9d7bd7be0 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -324,6 +324,8 @@ typedef struct ParticleSystem {
float dt_frac; /* current time step, as a fraction of a frame */
float _pad; /* spare capacity */
+
+ void *batch_cache;
} ParticleSystem;
typedef enum eParticleDrawFlag {
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 614189e7bef..94ef4aed62a 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2519,6 +2519,9 @@ static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_set(PointerRNA *ptr,
#define RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(_NAME_) \
RNA_LAYER_ENGINE_GET_SET(float, Clay, COLLECTION_MODE_NONE, _NAME_)
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT_ARRAY(_NAME_, _LEN_) \
+ RNA_LAYER_ENGINE_GET_SET_ARRAY(float, Clay, COLLECTION_MODE_NONE, _NAME_, _LEN_)
+
#define RNA_LAYER_ENGINE_CLAY_GET_SET_INT(_NAME_) \
RNA_LAYER_ENGINE_GET_SET(int, Clay, COLLECTION_MODE_NONE, _NAME_)
@@ -2575,6 +2578,13 @@ RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_cavity)
RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_edge)
RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_distance)
RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_attenuation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(world_intensity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(diffuse_intensity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(specular_intensity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(specular_hardness)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(color_randomicity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT_ARRAY(hair_diffuse_color, 4)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT_ARRAY(hair_specular_color, 4)
#endif /* WITH_CLAY_ENGINE */
/* eevee engine */
@@ -6363,6 +6373,57 @@ static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+ prop = RNA_def_property(srna, "world_intensity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_world_intensity_get", "rna_LayerEngineSettings_Clay_world_intensity_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair World Light", "World lighting intensity for hair");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "diffuse_intensity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_diffuse_intensity_get", "rna_LayerEngineSettings_Clay_diffuse_intensity_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Diffuse", "Diffuse lighting intensity for hair");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "specular_intensity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_specular_intensity_get", "rna_LayerEngineSettings_Clay_specular_intensity_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Specular", "Specular lighting intensity for hair");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "specular_hardness", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_specular_hardness_get", "rna_LayerEngineSettings_Clay_specular_hardness_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Specular Hardness", "Specular hardness for hair");
+ RNA_def_property_range(prop, 0.0f, 1000.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "color_randomicity", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_color_randomicity_get", "rna_LayerEngineSettings_Clay_color_randomicity_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Color Randomicity", "Color randomicity for hair");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "hair_diffuse_color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_hair_diffuse_color_get",
+ "rna_LayerEngineSettings_Clay_hair_diffuse_color_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Diffuse Color", "Diffuse component of hair shading color");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "hair_specular_color", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_hair_specular_color_get",
+ "rna_LayerEngineSettings_Clay_hair_specular_color_set", NULL);
+ RNA_def_property_ui_text(prop, "Hair Specular Color", "Specular component of hair shading color");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
RNA_define_verify_sdna(1); /* not in sdna */
}
#endif /* WITH_CLAY_ENGINE */