diff options
author | Luca Rood <dev@lucarood.com> | 2017-06-22 20:19:55 +0300 |
---|---|---|
committer | Luca Rood <dev@lucarood.com> | 2017-06-26 13:17:18 +0300 |
commit | cbbfacdac09a6728ca3eb26e7e9269815db569d1 (patch) | |
tree | afe89da604f1471d5e6337596657d3f1c8f14867 /source/blender | |
parent | 6f0b80425b8da760acf9909feba2b0988ddedada (diff) |
Hair UV implementation for Eevee
This implements UV support for Eevee hair, enabling the usage of
textures.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/draw/engines/clay/clay_engine.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 111 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_particles.c | 187 |
6 files changed, 245 insertions, 66 deletions
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index f39438e660c..00cc93a9db2 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -828,7 +828,7 @@ static void CLAY_cache_populate(void *vedata, Object *ob) unit_m4(mat); if (draw_as == PART_DRAW_PATH) { - geom = DRW_cache_particles_get_hair(psys); + geom = DRW_cache_particles_get_hair(psys, NULL); hair_shgrp = CLAY_hair_shgrp_get(ob, stl, psl); DRW_shgroup_call_add(hair_shgrp, geom, mat); } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 6126aab1014..74cb6b0d7a0 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -26,6 +26,7 @@ #include "DRW_render.h" #include "DNA_world_types.h" +#include "DNA_modifier_types.h" #include "BLI_dynstr.h" #include "BLI_ghash.h" @@ -624,72 +625,76 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl if (ob != draw_ctx->scene->obedit) { material_hash = stl->g_data->hair_material_hash; - 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; + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_ParticleSystem) { + ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; - if (draw_as == PART_DRAW_PATH && (psys->pathcache || psys->childcache)) { - struct Gwn_Batch *hair_geom = DRW_cache_particles_get_hair(psys); - DRWShadingGroup *shgrp = NULL; - Material *ma = give_current_material(ob, part->omat); - static float mat[4][4]; + 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; - unit_m4(mat); + if (draw_as == PART_DRAW_PATH && (psys->pathcache || psys->childcache)) { + struct Gwn_Batch *hair_geom = DRW_cache_particles_get_hair(psys, md); + DRWShadingGroup *shgrp = NULL; + Material *ma = give_current_material(ob, part->omat); + static float mat[4][4]; - if (ma == NULL) { - ma = &defmaterial; - } + unit_m4(mat); + + if (ma == NULL) { + ma = &defmaterial; + } - float *color_p = &ma->r; - float *metal_p = &ma->ray_mirror; - float *spec_p = &ma->spec; - float *rough_p = &ma->gloss_mir; + float *color_p = &ma->r; + float *metal_p = &ma->ray_mirror; + float *spec_p = &ma->spec; + float *rough_p = &ma->gloss_mir; - DRW_shgroup_call_add(stl->g_data->depth_shgrp, hair_geom, mat); - DRW_shgroup_call_add(stl->g_data->depth_shgrp_clip, hair_geom, mat); + DRW_shgroup_call_add(stl->g_data->depth_shgrp, hair_geom, mat); + DRW_shgroup_call_add(stl->g_data->depth_shgrp_clip, hair_geom, mat); - shgrp = BLI_ghash_lookup(material_hash, (const void *)ma); + shgrp = BLI_ghash_lookup(material_hash, (const void *)ma); - if (shgrp) { - DRW_shgroup_call_add(shgrp, hair_geom, mat); - } - else { - if (ma->use_nodes && ma->nodetree) { - Scene *scene = draw_ctx->scene; - struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma, - stl->effects->use_ao, stl->effects->use_bent_normals); + if (shgrp) { + DRW_shgroup_call_add(shgrp, hair_geom, mat); + } + else { + if (ma->use_nodes && ma->nodetree) { + Scene *scene = draw_ctx->scene; + struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma, + stl->effects->use_ao, stl->effects->use_bent_normals); + + shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass); + if (shgrp) { + add_standard_uniforms(shgrp, sldata, vedata); + + BLI_ghash_insert(material_hash, ma, shgrp); + + DRW_shgroup_call_add(shgrp, hair_geom, mat); + } + else { + /* Shader failed : pink color */ + static float col[3] = {1.0f, 0.0f, 1.0f}; + static float half = 0.5f; + + color_p = col; + metal_p = spec_p = rough_p = ½ + } + } - shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass); - if (shgrp) { - add_standard_uniforms(shgrp, sldata, vedata); + /* Fallback to default shader */ + if (shgrp == NULL) { + shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, + stl->effects->use_ao, stl->effects->use_bent_normals); + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); BLI_ghash_insert(material_hash, ma, shgrp); DRW_shgroup_call_add(shgrp, hair_geom, mat); } - else { - /* Shader failed : pink color */ - static float col[3] = {1.0f, 0.0f, 1.0f}; - static float half = 0.5f; - - color_p = col; - metal_p = spec_p = rough_p = ½ - } - } - - /* Fallback to default shader */ - if (shgrp == NULL) { - shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, - stl->effects->use_ao, stl->effects->use_bent_normals); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - - BLI_ghash_insert(material_hash, ma, shgrp); - - DRW_shgroup_call_add(shgrp, hair_geom, mat); } } } diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 4dfb9f960c2..5d0485b03e6 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -29,6 +29,7 @@ #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" +#include "DNA_modifier_types.h" #include "BLI_utildefines.h" #include "BLI_math.h" @@ -2331,9 +2332,9 @@ Gwn_Batch *DRW_cache_lattice_vert_overlay_get(Object *ob) /** \name Particles * \{ */ -Gwn_Batch *DRW_cache_particles_get_hair(ParticleSystem *psys) +Gwn_Batch *DRW_cache_particles_get_hair(ParticleSystem *psys, ModifierData *md) { - return DRW_particles_batch_cache_get_hair(psys); + return DRW_particles_batch_cache_get_hair(psys, md); } Gwn_Batch *DRW_cache_particles_get_dots(ParticleSystem *psys) diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index a4fac3fe71f..857d4c60053 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -28,6 +28,7 @@ struct Gwn_Batch; struct Object; +struct ModifierData; void DRW_shape_cache_free(void); @@ -144,7 +145,7 @@ struct Gwn_Batch *DRW_cache_lattice_wire_get(struct Object *ob); struct Gwn_Batch *DRW_cache_lattice_vert_overlay_get(struct Object *ob); /* Particles */ -struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys); +struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys, struct ModifierData *md); struct Gwn_Batch *DRW_cache_particles_get_dots(struct ParticleSystem *psys); struct Gwn_Batch *DRW_cache_particles_get_prim(int type); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 066ca9f60e0..8786dda9d51 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -30,6 +30,7 @@ struct Gwn_Batch; struct ListBase; struct CurveCache; struct ParticleSystem; +struct ModifierData; struct Curve; struct Lattice; @@ -94,7 +95,7 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me); /* Particles */ -struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys); +struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys, struct ModifierData *md); struct Gwn_Batch *DRW_particles_batch_cache_get_dots(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 index 6b15bd673c9..f3f658dbd8d 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -33,10 +33,13 @@ #include "BLI_utildefines.h" #include "BLI_math_vector.h" +#include "BLI_ghash.h" +#include "DNA_modifier_types.h" #include "DNA_particle_types.h" #include "BKE_particle.h" +#include "BKE_DerivedMesh.h" #include "GPU_batch.h" @@ -170,21 +173,46 @@ static void ensure_seg_pt_count(ParticleSystem *psys, ParticleBatchCache *cache) } /* Gwn_Batch cache usage. */ -static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ParticleBatchCache *cache) +static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, ModifierData *md, ParticleBatchCache *cache) { if (cache->pos == NULL || cache->segments == NULL) { int curr_point = 0; + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; GWN_VERTBUF_DISCARD_SAFE(cache->pos); GWN_INDEXBUF_DISCARD_SAFE(cache->segments); static Gwn_VertFormat format = { 0 }; static struct { uint pos, tan, ind; } attr_id; - if (format.attrib_ct == 0) { - /* initialize vertex format */ - attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT); + unsigned int *uv_id; + int uv_layers = 0; + MTFace **mtfaces; + float (**parent_uvs)[2] = NULL; + bool simple = psys->part->childtype == PART_CHILD_PARTICLES; + + if (psmd) { + if (CustomData_has_layer(&psmd->dm_final->loopData, CD_MLOOPUV)) { + uv_layers = CustomData_number_of_layers(&psmd->dm_final->loopData, CD_MLOOPUV); + } + } + + GWN_vertformat_clear(&format); + + /* initialize vertex format */ + attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.tan = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + attr_id.ind = GWN_vertformat_attr_add(&format, "ind", GWN_COMP_I32, 1, GWN_FETCH_INT); + + if (psmd) { + uv_id = MEM_mallocN(sizeof(*uv_id) * uv_layers, "UV attrib format"); + + for (int i = 0; i < uv_layers; i++) { + const char *name = CustomData_get_layer_name(&psmd->dm_final->loopData, CD_MLOOPUV, i); + char uuid[32]; + + BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name)); + uv_id[i] = GWN_vertformat_attr_add(&format, uuid, GWN_COMP_F32, 2, GWN_FETCH_FLOAT); + } } cache->pos = GWN_vertbuf_create_with_format(&format); @@ -193,12 +221,55 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic Gwn_IndexBufBuilder elb; GWN_indexbuf_init(&elb, GWN_PRIM_LINES, cache->segment_count, cache->point_count); + if (uv_layers) { + DM_ensure_tessface(psmd->dm_final); + + mtfaces = MEM_mallocN(sizeof(*mtfaces) * uv_layers, "Faces UV layers"); + + for (int i = 0; i < uv_layers; i++) { + mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->dm_final->faceData, CD_MTFACE, i); + } + } + if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + if (simple) { + parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs"); + } + for (int i = 0; i < psys->totpart; i++) { ParticleCacheKey *path = psys->pathcache[i]; if (path->segments > 0) { float tangent[3]; + int from = psmd ? psmd->psys->part->from : 0; + float (*uv)[2]; + + if (psmd) { + uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs"); + + if (simple) { + parent_uvs[i] = uv; + } + } + + if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + ParticleData *particle = &psys->particles[i]; + int num = particle->num_dmcache; + + if (num == DMCACHE_NOTFOUND) { + if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) { + num = particle->num; + } + } + + if (num != DMCACHE_NOTFOUND) { + MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); + + for (int j = 0; j < uv_layers; j++) { + psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]); + } + } + } for (int j = 0; j < path->segments; j++) { if (j == 0) { @@ -212,6 +283,12 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i); + if (psmd) { + for (int k = 0; k < uv_layers; k++) { + GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]); + } + } + GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1); curr_point++; @@ -223,6 +300,16 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &i); + if (psmd) { + for (int k = 0; k < uv_layers; k++) { + GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, uv[k]); + } + + if (!simple) { + MEM_freeN(uv); + } + } + curr_point++; } } @@ -231,11 +318,61 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic if (psys->childcache) { int child_count = psys->totchild * psys->part->disp / 100; + if (simple && !parent_uvs) { + parent_uvs = MEM_callocN(sizeof(*parent_uvs) * psys->totpart, "Parent particle UVs"); + } + for (int i = 0, x = psys->totpart; i < child_count; i++, x++) { ParticleCacheKey *path = psys->childcache[i]; float tangent[3]; if (path->segments > 0) { + int from = psmd ? psmd->psys->part->from : 0; + float (*uv)[2]; + + if (!simple) { + if (psmd) { + uv = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs"); + } + + if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + ChildParticle *particle = &psys->child[i]; + int num = psys->part->childtype == particle->num; + + if (num != DMCACHE_NOTFOUND) { + MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); + + for (int j = 0; j < uv_layers; j++) { + psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, uv[j]); + } + } + } + } + else if (!parent_uvs[psys->child[i].parent]) { + if (psmd) { + parent_uvs[psys->child[i].parent] = MEM_callocN(sizeof(*uv) * uv_layers, "Particle UVs"); + } + + if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + ParticleData *particle = &psys->particles[psys->child[i].parent]; + int num = particle->num_dmcache; + + if (num == DMCACHE_NOTFOUND) { + if (particle->num < psmd->dm_final->getNumTessFaces(psmd->dm_final)) { + num = particle->num; + } + } + + if (num != DMCACHE_NOTFOUND) { + MFace *mface = psmd->dm_final->getTessFaceData(psmd->dm_final, num, CD_MFACE); + + for (int j = 0; j < uv_layers; j++) { + psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, parent_uvs[psys->child[i].parent][j]); + } + } + } + } + for (int j = 0; j < path->segments; j++) { if (j == 0) { sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); @@ -248,6 +385,13 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x); + if (psmd) { + for (int k = 0; k < uv_layers; k++) { + GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, + simple ? parent_uvs[psys->child[i].parent][k] : uv[k]); + } + } + GWN_indexbuf_add_line_verts(&elb, curr_point, curr_point + 1); curr_point++; @@ -259,11 +403,38 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic GWN_vertbuf_attr_set(cache->pos, attr_id.tan, curr_point, tangent); GWN_vertbuf_attr_set(cache->pos, attr_id.ind, curr_point, &x); + if (psmd) { + for (int k = 0; k < uv_layers; k++) { + GWN_vertbuf_attr_set(cache->pos, uv_id[k], curr_point, + simple ? parent_uvs[psys->child[i].parent][k] : uv[k]); + } + + if (!simple) { + MEM_freeN(uv); + } + } + curr_point++; } } } + if (parent_uvs) { + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_uvs[i]); + } + + MEM_freeN(parent_uvs); + } + + if (uv_layers) { + MEM_freeN(mtfaces); + } + + if (psmd) { + MEM_freeN(uv_id); + } + cache->segments = GWN_indexbuf_build(&elb); } } @@ -322,13 +493,13 @@ static void particle_batch_cache_ensure_pos(ParticleSystem *psys, ParticleBatchC } } -Gwn_Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys) +Gwn_Batch *DRW_particles_batch_cache_get_hair(ParticleSystem *psys, ModifierData *md) { 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); + particle_batch_cache_ensure_pos_and_seg(psys, md, cache); cache->hairs = GWN_batch_create(GWN_PRIM_LINES, cache->pos, cache->segments); } |