diff options
Diffstat (limited to 'source/blender')
6 files changed, 192 insertions, 9 deletions
diff --git a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl index b28b3cadd6f..d4c35d14182 100644 --- a/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl +++ b/source/blender/draw/engines/clay/shaders/clay_particle_vert.glsl @@ -4,7 +4,7 @@ uniform mat3 NormalMatrix; uniform mat4 ModelViewMatrix; in vec3 pos; -in vec3 tang; +in vec3 nor; in int ind; out vec3 tangent; out vec3 viewPosition; @@ -28,7 +28,7 @@ float rand(int s) void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - tangent = normalize(NormalMatrix * tang); + tangent = normalize(NormalMatrix * nor); viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz; colRand = rand(ind); } diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 2177d3d065c..915a0065b60 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -151,6 +151,7 @@ static void EEVEE_draw_scene(void *vedata) /* Shading pass */ DRW_draw_pass(psl->default_pass); DRW_draw_pass(psl->default_flat_pass); + DRW_draw_pass(psl->default_hair_pass); DRW_draw_pass(psl->material_pass); /* Post Process */ diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index c4c331ab1a4..b9ad507c6ce 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -30,6 +30,8 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" +#include "BKE_particle.h" + #include "GPU_material.h" #include "eevee_engine.h" @@ -55,6 +57,7 @@ enum { enum { VAR_MAT_MESH = (1 << 0), VAR_MAT_PROBE = (1 << 1), + VAR_MAT_HAIR = (1 << 2), }; /* *********** STATIC *********** */ @@ -63,6 +66,7 @@ static struct { struct GPUShader *default_lit; struct GPUShader *default_lit_flat; + struct GPUShader *default_lit_hair; struct GPUShader *default_background; @@ -183,12 +187,19 @@ void EEVEE_materials_init(void) datatoc_lit_surface_vert_glsl, NULL, frag_str, SHADER_DEFINES "#define MESH_SHADER\n"); + e_data.default_lit_flat = DRW_shader_create( datatoc_lit_surface_vert_glsl, NULL, frag_str, SHADER_DEFINES "#define MESH_SHADER\n" "#define USE_FLAT_NORMAL\n"); + e_data.default_lit_hair = DRW_shader_create( + datatoc_lit_surface_vert_glsl, NULL, frag_str, + SHADER_DEFINES + "#define MESH_SHADER\n" + "#define HAIR_SHADER\n"); + MEM_freeN(frag_str); /* Textures */ @@ -257,6 +268,15 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, Material *ma) SHADER_DEFINES "#define MESH_SHADER\n"); } +struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma) +{ + return GPU_material_from_nodetree( + scene, ma->nodetree, &ma->gpumaterial, &DRW_engine_viewport_eevee_type, + VAR_MAT_HAIR, + datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib, + SHADER_DEFINES "#define MESH_SHADER\n" "#define HAIR_SHADER\n"); +} + static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata) { DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); @@ -280,6 +300,7 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) /* Create Material Ghash */ { stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash"); + stl->g_data->hair_material_hash = BLI_ghash_ptr_new("Eevee_hair_material ghash"); } { @@ -322,7 +343,7 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) { struct GPUShader *depth_sh = DRW_shader_create_3D_depth_only(); - DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE; psl->depth_pass = DRW_pass_create("Depth Pass", state); stl->g_data->depth_shgrp = DRW_shgroup_create(depth_sh, psl->depth_pass); @@ -332,7 +353,7 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_WIRE; psl->default_pass = DRW_pass_create("Default Lit Pass", state); DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit, psl->default_pass); add_standard_uniforms(shgrp, sldata); @@ -340,10 +361,14 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) psl->default_flat_pass = DRW_pass_create("Default Flat Lit Pass", state); shgrp = DRW_shgroup_create(e_data.default_lit_flat, psl->default_flat_pass); add_standard_uniforms(shgrp, sldata); + + psl->default_hair_pass = DRW_pass_create("Default Hair Lit Pass", state); + shgrp = DRW_shgroup_create(e_data.default_lit_hair, psl->default_hair_pass); + add_standard_uniforms(shgrp, sldata); } { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL; + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_WIRE; psl->material_pass = DRW_pass_create("Material Shader Pass", state); } } @@ -441,6 +466,81 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl } } } + + if (ob->type == OB_MESH) { + 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; + + if (draw_as == PART_DRAW_PATH && (psys->pathcache || psys->childcache)) { + struct 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]; + + 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; + + DRW_shgroup_call_add(stl->g_data->depth_shgrp, hair_geom, mat); + + 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); + + shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass); + if (shgrp) { + add_standard_uniforms(shgrp, sldata); + + 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 = DRW_shgroup_create(e_data.default_lit_hair, psl->default_hair_pass); + 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); + } + } + } + } + } + } + } } void EEVEE_materials_cache_finish(EEVEE_Data *vedata) @@ -448,6 +548,7 @@ void EEVEE_materials_cache_finish(EEVEE_Data *vedata) EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; BLI_ghash_free(stl->g_data->material_hash, NULL, NULL); + BLI_ghash_free(stl->g_data->hair_material_hash, NULL, NULL); } void EEVEE_materials_free(void) @@ -455,6 +556,7 @@ void EEVEE_materials_free(void) MEM_SAFE_FREE(e_data.frag_shader_lib); DRW_SHADER_FREE_SAFE(e_data.default_lit); DRW_SHADER_FREE_SAFE(e_data.default_lit_flat); + DRW_SHADER_FREE_SAFE(e_data.default_lit_hair); DRW_SHADER_FREE_SAFE(e_data.default_background); DRW_TEXTURE_FREE_SAFE(e_data.util_tex); -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index f3b37f41532..f3c8a63a5d7 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -67,6 +67,7 @@ typedef struct EEVEE_PassList { struct DRWPass *depth_pass_cull; struct DRWPass *default_pass; struct DRWPass *default_flat_pass; + struct DRWPass *default_hair_pass; struct DRWPass *material_pass; struct DRWPass *background_pass; } EEVEE_PassList; @@ -318,6 +319,7 @@ typedef struct EEVEE_PrivateData { struct DRWShadingGroup *depth_shgrp; struct DRWShadingGroup *depth_shgrp_cull; struct GHash *material_hash; + struct GHash *hair_material_hash; } EEVEE_PrivateData; /* Transient data */ /* eevee_data.c */ @@ -336,6 +338,7 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, str struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); struct GPUMaterial *EEVEE_material_mesh_lightprobe_get(struct Scene *scene, Material *ma); struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, Material *ma); +struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma); void EEVEE_materials_free(void); /* eevee_lights.c */ diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index e361f08b26b..8f11835a1cc 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -88,11 +88,74 @@ vec4 texture_octahedron(sampler2DArray tex, vec4 cubevec) return texture(tex, vec3(uvs, cubevec.w)); } +#ifdef HAIR_SHADER +vec3 light_diffuse(LightData ld, ShadingData sd, vec3 albedo) +{ + if (ld.l_type == SUN) { + return direct_diffuse_sun(ld, sd) * albedo; + } + else if (ld.l_type == AREA) { + return direct_diffuse_rectangle(ld, sd) * albedo; + } + else { + return direct_diffuse_sphere(ld, sd) * albedo; + } +} + +vec3 light_specular(LightData ld, ShadingData sd, float roughness, vec3 f0) +{ + if (ld.l_type == SUN) { + return direct_ggx_sun(ld, sd, roughness, f0); + } + else if (ld.l_type == AREA) { + return direct_ggx_rectangle(ld, sd, roughness, f0); + } + else { + return direct_ggx_sphere(ld, sd, roughness, f0); + } +} void light_shade( LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0, out vec3 diffuse, out vec3 specular) { + const float transmission = 0.3; /* Uniform internal scattering factor */ + ShadingData sd_new = sd; + + vec3 lamp_vec; + + if (ld.l_type == SUN || ld.l_type == AREA) { + lamp_vec = ld.l_forward; + } + else { + lamp_vec = -sd.l_vector; + } + + vec3 norm_view = cross(sd.V, sd.N); + norm_view = normalize(cross(norm_view, sd.N)); /* Normal facing view */ + + vec3 norm_lamp = cross(lamp_vec, sd.N); + norm_lamp = normalize(cross(sd.N, norm_lamp)); /* Normal facing lamp */ + + /* Rotate view vector onto the cross(tangent, light) plane */ + vec3 view_vec = normalize(norm_lamp * dot(norm_view, sd.V) + sd.N * dot(sd.N, sd.V)); + + float occlusion = (dot(norm_view, norm_lamp) * 0.5 + 0.5); + float occltrans = transmission + (occlusion * (1.0 - transmission)); /* Includes transmission component */ + + sd_new.N = -norm_lamp; + + diffuse = light_diffuse(ld, sd_new, albedo) * occltrans; + + sd_new.V = view_vec; + + specular = light_specular(ld, sd_new, roughness, f0) * occlusion; +} +#else +void light_shade( + LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0, + out vec3 diffuse, out vec3 specular) +{ #ifdef USE_LTC if (ld.l_type == SUN) { /* TODO disk area light */ @@ -118,6 +181,7 @@ void light_shade( } #endif } +#endif void light_visibility(LightData ld, ShadingData sd, out float vis) { @@ -254,20 +318,33 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, sd.W = worldPosition; vec3 radiance = vec3(0.0); + +#ifdef HAIR_SHADER + /* View facing normal */ + vec3 norm_view = cross(sd.V, sd.N); + norm_view = normalize(cross(norm_view, sd.N)); /* Normal facing view */ +#endif + + /* Analitic Lights */ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { LightData ld = lights_data[i]; vec3 diff, spec; - float vis; + float vis = 1.0; sd.l_vector = ld.l_position - worldPosition; +#ifndef HAIR_SHADER light_visibility(ld, sd, vis); +#endif light_shade(ld, sd, albedo, roughnessSquared, f0, diff, spec); radiance += vis * (diff + spec) * ld.l_color; } +#ifdef HAIR_SHADER + sd.N = -norm_view; +#endif /* Envmaps */ vec3 R = reflect(-sd.V, sd.N); @@ -314,4 +391,4 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, diff_accum.rgb * albedo; return radiance + indirect_radiance * ao; -}
\ No newline at end of file +} diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index f4b16f1873a..febba333a2b 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -183,7 +183,7 @@ static void particle_batch_cache_ensure_pos_and_seg(ParticleSystem *psys, Partic if (format.attrib_ct == 0) { /* initialize vertex format */ attr_id.pos = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); - attr_id.tan = VertexFormat_add_attrib(&format, "tang", COMP_F32, 3, KEEP_FLOAT); + attr_id.tan = VertexFormat_add_attrib(&format, "nor", COMP_F32, 3, KEEP_FLOAT); attr_id.ind = VertexFormat_add_attrib(&format, "ind", COMP_I32, 1, KEEP_INT); } |