diff options
author | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
---|---|---|
committer | Stuart Broadfoot <gbroadfoot@hotmail.com> | 2012-12-28 18:21:30 +0400 |
commit | e9ba345c46c93a193193f01d4bfac714a666d384 (patch) | |
tree | 49df9d78dc9327de642779e300e1592e5d7b3a42 /source | |
parent | 857df8065face58eff5556953cdf2dd72e09f2b6 (diff) |
New feature
Patch [#33445] - Experimental Cycles Hair Rendering (CPU only)
This patch allows hair data to be exported to cycles and introduces a new line segment primitive to render with.
The UI appears under the particle tab and there is a new hair info node available.
It is only available under the experimental feature set and for cpu rendering.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.c | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 267 | ||||
-rw-r--r-- | source/blender/nodes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/nodes/NOD_shader.h | 1 | ||||
-rw-r--r-- | source/blender/nodes/shader/nodes/node_shader_hair_info.c | 58 |
7 files changed, 328 insertions, 2 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b8f168cbdea..0a2f757b38e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -557,6 +557,7 @@ struct ShadeResult; #define SH_NODE_BSDF_REFRACTION 173 #define SH_NODE_TANGENT 174 #define SH_NODE_NORMAL_MAP 175 +#define SH_NODE_HAIR_INFO 176 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index a6ec1f33edc..84e280034ed 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2323,6 +2323,7 @@ static void registerShaderNodes(bNodeTreeType *ttype) register_node_type_sh_layer_weight(ttype); register_node_type_sh_tex_coord(ttype); register_node_type_sh_particle_info(ttype); + register_node_type_sh_hair_info(ttype); register_node_type_sh_bump(ttype); register_node_type_sh_script(ttype); register_node_type_sh_tangent(ttype); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index de535156199..46f2306f284 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -84,6 +84,7 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" ) DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" ) DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" ) +DefNode( ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" ) DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" ) DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" ) DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" ) diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 93f940b1aa3..b0b68b11ec9 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -238,7 +238,220 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float } } -/* property update functions */ +static void rna_ParticleHairKey_co_object(HairKey *hairkey, Object *object, ParticleSystemModifierData *modifier, ParticleData *particle, + float n_co[3]) +{ + + DerivedMesh *hairdm = (modifier->psys->flag & PSYS_HAIR_DYNAMICS) ? modifier->psys->hair_out_dm : NULL; + if (particle) { + if (hairdm) { + MVert *mvert = CDDM_get_vert(hairdm, particle->hair_index + (hairkey - particle->hair)); + copy_v3_v3(n_co, mvert->co); + } + else { + float hairmat[4][4]; + psys_mat_hair_to_object(object, modifier->dm, modifier->psys->part->from, particle, hairmat); + copy_v3_v3(n_co, hairkey->co); + mul_m4_v3(hairmat, n_co); + } + } + else { + zero_v3(n_co); + } +} + +static void rna_Particle_uv_on_emitter(ParticleData *particle, ParticleSystemModifierData *modifier, float n_uv[2]) +{ + /*psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, sd.orco, 0);*/ + + /* get uvco & mcol */ + int num = particle->num_dmcache; + int from = modifier->psys->part->from; + + if (num == DMCACHE_NOTFOUND) + if (particle->num < modifier->dm->getNumTessFaces(modifier->dm)) + num = particle->num; + + /* get uvco */ + if (n_uv && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + + if (num != DMCACHE_NOTFOUND) { + MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE); + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0); + mtface += num; + + psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv); + } + else { + n_uv[0] = 0.0f; + n_uv[1] = 0.0f; + } + } +} + +static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *object, ParticleSystemModifierData *modifier, int particle_no, int step, + float n_co[3]) +{ + ParticleSettings *part = 0; + ParticleData *pars = 0; + ParticleCacheKey *cache = 0; + int totchild=0; + int path_nbr=0; + int totpart; + int max_k = 0; + + if (particlesystem == NULL) + return; + + part = particlesystem->part; + pars = particlesystem->particles; + + if (part == NULL || pars == NULL || !psys_check_enabled(object, particlesystem)) + return; + + if (part->ren_as==PART_DRAW_OB || part->ren_as==PART_DRAW_GR || part->ren_as==PART_DRAW_NOT) + return; + + totchild = particlesystem->totchild * part->disp / 100; + + /* can happen for disconnected/global hair */ + if (part->type == PART_HAIR && !particlesystem->childcache) + totchild = 0; + + totpart = particlesystem->totpart; + + if (particle_no >= totpart + totchild) + return; + + if (part->ren_as == PART_DRAW_PATH && particlesystem->pathcache) + path_nbr=(int)pow(2.0, part->draw_step); + + if (particle_no<totpart) { + + if (path_nbr) { + cache = particlesystem->pathcache[particle_no]; + max_k = (int)cache->steps; + } + + } + else { + + if (path_nbr) { + cache = particlesystem->childcache[particle_no-totpart]; + + if (cache->steps < 0) + max_k = 0; + else + max_k = (int)cache->steps; + } + } + + /*strands key loop data stored in cache + step->co*/ + if (path_nbr) { + if (step>=0 && step<=path_nbr) { + if (step<=max_k) + copy_v3_v3(n_co, (cache+step)->co); + } + } + +} + +static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, + float n_uv[2]) +{ + ParticleSettings *part = 0; + int totpart; + int totchild = 0; + int num; + + /* 1. check that everything is ok & updated */ + if (particlesystem == NULL) + return; + + part=particlesystem->part; + + totchild = particlesystem->totchild; + + /* can happen for disconnected/global hair */ + if (part->type == PART_HAIR && !particlesystem->childcache) + totchild = 0; + + totpart = particlesystem->totpart; + + if (particle_no >= totpart + totchild) + return; + +/* 3. start creating renderable things */ + /* setup per particle individual stuff */ + if (particle_no<totpart) { + + /* get uvco & mcol */ + num = particle->num_dmcache; + + if (num == DMCACHE_NOTFOUND) + if (particle->num < modifier->dm->getNumTessFaces(modifier->dm)) + num = particle->num; + + if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if (num != DMCACHE_NOTFOUND) { + MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE); + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0); + mtface += num; + + psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv); + } + else { + n_uv[0] = 0.0f; + n_uv[1] = 0.0f; + } + } + } + else { + ChildParticle *cpa = particlesystem->child + particle_no-totpart; + + num = cpa->num; + + /* get uvco & mcol */ + if (part->childtype == PART_CHILD_FACES) { + if (n_uv && ELEM(PART_FROM_FACE, PART_FROM_FACE, PART_FROM_VOLUME)) { + if (cpa->num != DMCACHE_NOTFOUND) { + MFace *mface = modifier->dm->getTessFaceData(modifier->dm, cpa->num, CD_MFACE); + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0); + mtface += cpa->num; + + psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, n_uv); + } + else { + n_uv[0] = 0.0f; + n_uv[1] = 0.0f; + } + } + } + else { + ParticleData *parent = particlesystem->particles + cpa->parent; + num = parent->num_dmcache; + + if (num == DMCACHE_NOTFOUND) + if (parent->num < modifier->dm->getNumTessFaces(modifier->dm)) + num = parent->num; + + if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if (num != DMCACHE_NOTFOUND) { + MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE); + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0); + mtface += num; + + psys_interpolate_uvs(mtface, mface->v4, parent->fuv, n_uv); + } + else { + n_uv[0] = 0.0f; + n_uv[1] = 0.0f; + } + } + } + } +} + static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag) { if (ptr->type == &RNA_ParticleSystem) { @@ -905,6 +1118,7 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "ParticleHairKey", NULL); RNA_def_struct_sdna(srna, "HairKey"); @@ -928,6 +1142,19 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Location", "Location of the hair key in its internal coordinate system, " "relative to the emitting face"); + + /* Aided co func */ + func = RNA_def_function(srna, "co_object", "rna_ParticleHairKey_co_object"); + RNA_def_function_ui_description(func, "Obtain hairkey location with particle and modifier data"); + + prop = RNA_def_pointer(func, "object", "Object", "", "Object"); + prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + prop = RNA_def_pointer(func, "particle", "Particle", "", "hair particle"); + + prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", + "Exported hairkey location", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); } static void rna_def_particle_key(BlenderRNA *brna) @@ -979,6 +1206,7 @@ static void rna_def_particle(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; static EnumPropertyItem alive_items[] = { /*{PARS_KILLED, "KILLED", 0, "Killed", ""}, */ @@ -1083,6 +1311,15 @@ static void rna_def_particle(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Alive State", ""); /* short rt2; */ + +/* UVs */ + func = RNA_def_function(srna, "uv_on_emitter", "rna_Particle_uv_on_emitter"); + RNA_def_function_ui_description(func, "Obtain uv for particle on derived mesh"); + prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS); + RNA_def_property_array(prop, 2); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); } static void rna_def_particle_dupliweight(BlenderRNA *brna) @@ -2696,6 +2933,7 @@ static void rna_def_particle_system(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "ParticleSystem", NULL); RNA_def_struct_ui_text(srna, "Particle System", "Particle system in an object"); @@ -2793,7 +3031,6 @@ static void rna_def_particle_system(BlenderRNA *brna) "rna_ParticleSystem_active_particle_target_index_range"); RNA_def_property_ui_text(prop, "Active Particle Target Index", ""); - /* billboard */ prop = RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "bb_uvname[0]"); @@ -2995,6 +3232,32 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_struct_path_func(srna, "rna_ParticleSystem_path"); + + /* extract cached hair location data */ + func = RNA_def_function(srna, "co_hair", "rna_ParticleSystem_co_hair"); + RNA_def_function_ui_description(func, "Obtain cache hair data"); + + prop = RNA_def_pointer(func, "object", "Object", "", "Object"); + prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX); + prop = RNA_def_int(func, "step", 0, INT_MIN, INT_MAX, "step no", "", INT_MIN, INT_MAX); + + prop = RNA_def_float_vector(func, "co", 3, NULL, -FLT_MAX, FLT_MAX, "Co", + "Exported hairkey location", -1e4, 1e4); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); + + /* extract hair UVs */ + func = RNA_def_function(srna, "uv_on_emitter", "rna_ParticleSystem_uv_on_emitter"); + RNA_def_function_ui_description(func, "Obtain uv for all particles"); + prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); + prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle"); + prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX); + prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS); + RNA_def_property_array(prop, 2); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + RNA_def_function_output(func, prop); + } void RNA_def_particle(BlenderRNA *brna) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 141a3680df2..a7b491cf42b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -168,6 +168,7 @@ set(SRC shader/nodes/node_shader_mix_shader.c shader/nodes/node_shader_normal_map.c shader/nodes/node_shader_object_info.c + shader/nodes/node_shader_hair_info.c shader/nodes/node_shader_output_lamp.c shader/nodes/node_shader_output_material.c shader/nodes/node_shader_output_world.c diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 74135776c9c..0a7a11e4506 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -78,6 +78,7 @@ void register_node_type_sh_fresnel(struct bNodeTreeType *ttype); void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype); void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype); void register_node_type_sh_particle_info(struct bNodeTreeType *ttype); +void register_node_type_sh_hair_info(struct bNodeTreeType *ttype); void register_node_type_sh_script(struct bNodeTreeType *ttype); void register_node_type_sh_normal_map(struct bNodeTreeType *ttype); void register_node_type_sh_tangent(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/shader/nodes/node_shader_hair_info.c b/source/blender/nodes/shader/nodes/node_shader_hair_info.c new file mode 100644 index 00000000000..8e6f40faf24 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_hair_info.c @@ -0,0 +1,58 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +static bNodeSocketTemplate outputs[] = { + { SOCK_FLOAT, 0, N_("Is Strand"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Intercept"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, + { -1, 0, "" } +}; + +static int node_shader_gpu_curve_attrib(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "NODE_HAIR_INFO", in, out); +} + +/* node type definition */ +void register_node_type_sh_hair_info(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, SH_NODE_HAIR_INFO, "Hair Info", NODE_CLASS_INPUT, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, NULL, outputs); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_exec(&ntype, NULL); + node_type_gpu(&ntype, node_shader_gpu_curve_attrib); + + nodeRegisterType(ttype, &ntype); +} |