diff options
8 files changed, 150 insertions, 65 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 96b168cdeee..7150cac6add 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -32,6 +32,7 @@ #include "DNA_camera_types.h" #include "DNA_screen_types.h" #include "DNA_view3d_types.h" +#include "DNA_world_types.h" #include "BKE_camera.h" #include "BKE_object.h" @@ -402,14 +403,17 @@ void EEVEE_effects_init(EEVEE_Data *vedata) &tex, 1); if (BKE_collection_engine_property_value_get_bool(props, "volumetric_enable")) { - /* MinMax Pyramid */ + /* Integration result */ DRWFboTexture tex_vol = {&stl->g_data->volumetric, DRW_TEX_RGBA_16, DRW_TEX_MIPMAP | DRW_TEX_FILTER | DRW_TEX_TEMP}; DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type, (int)viewport_size[0] / 2, (int)viewport_size[1] / 2, &tex_vol, 1); - effects->enabled_effects |= EFFECT_VOLUMETRIC; + World *wo = scene->world; + if ((wo != NULL) && (wo->use_nodes != NULL) && (wo->nodetree != NULL)) { + effects->enabled_effects |= EFFECT_VOLUMETRIC; + } } } @@ -441,27 +445,38 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); - { - struct GPUShader *sh = EEVEE_material_world_volume_get(NULL, NULL); - psl->volumetric_integrate_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->volumetric_integrate_ps); - DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src); - DRW_shgroup_uniform_buffer(grp, "shadowCubes", &sldata->shadow_depth_cube_pool); - DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_int(grp, "light_count", &sldata->lamps->num_light, 1); - DRW_shgroup_uniform_int(grp, "grid_count", &sldata->probes->num_render_grid, 1); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_call_add(grp, quad, NULL); + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + struct World *wo = scene->world; /* Already checked non NULL */ - psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION); - grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_ps); - DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src); - DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric); - DRW_shgroup_call_add(grp, quad, NULL); + struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo); + psl->volumetric_integrate_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_material_create(mat, psl->volumetric_integrate_ps); + + if (grp != NULL) { + DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src); + DRW_shgroup_uniform_buffer(grp, "shadowCubes", &sldata->shadow_depth_cube_pool); + DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_int(grp, "light_count", &sldata->lamps->num_light, 1); + DRW_shgroup_uniform_int(grp, "grid_count", &sldata->probes->num_render_grid, 1); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION); + grp = DRW_shgroup_create(e_data.volumetric_upsample_sh, psl->volumetric_resolve_ps); + DRW_shgroup_uniform_buffer(grp, "depthFull", &e_data.depth_src); + DRW_shgroup_uniform_buffer(grp, "volumetricBuffer", &stl->g_data->volumetric); + DRW_shgroup_call_add(grp, quad, NULL); + } + else { + /* Compilation failled */ + effects->enabled_effects &= ~EFFECT_VOLUMETRIC; + } } { diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index ee518cc268c..5ae60ff4ef6 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -73,7 +73,6 @@ static struct { extern char datatoc_background_vert_glsl[]; extern char datatoc_default_world_frag_glsl[]; -extern char datatoc_fullscreen_vert_glsl[]; extern char datatoc_lightprobe_filter_glossy_frag_glsl[]; extern char datatoc_lightprobe_filter_diffuse_frag_glsl[]; extern char datatoc_lightprobe_geom_glsl[]; diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index f7c28530aef..c35b94e8105 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -63,8 +63,8 @@ /* *********** STATIC *********** */ static struct { char *frag_shader_lib; + char *volume_shader_lib; - struct GPUShader *default_volume_sh; struct GPUShader *default_prepass_sh; struct GPUShader *default_prepass_clip_sh; struct GPUShader *default_lit[VAR_MAT_MAX]; @@ -273,6 +273,12 @@ void EEVEE_materials_init(EEVEE_StorageList *stl) ds_frag = BLI_dynstr_new(); BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); + BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl); + e_data.volume_shader_lib = BLI_dynstr_get_cstring(ds_frag); + BLI_dynstr_free(ds_frag); + + ds_frag = BLI_dynstr_new(); + BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl); frag_str = BLI_dynstr_get_cstring(ds_frag); BLI_dynstr_free(ds_frag); @@ -290,16 +296,6 @@ void EEVEE_materials_init(EEVEE_StorageList *stl) MEM_freeN(frag_str); - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); - BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl); - frag_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); - - e_data.default_volume_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES "#define STEP_INTEGRATE\n"); - - MEM_freeN(frag_str); - /* Textures */ const int layers = 3; float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels"); @@ -403,9 +399,19 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor SHADER_DEFINES "#define WORLD_BACKGROUND\n"); } -struct GPUShader *EEVEE_material_world_volume_get(struct Scene *UNUSED(scene), World *UNUSED(wo)) +struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo) { - return e_data.default_volume_sh; + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_WORLD_VOLUME; + + GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine, options); + if (mat != NULL) { + return mat; + } + return GPU_material_from_nodetree( + scene, wo->nodetree, &wo->gpumaterial, engine, options, + datatoc_background_vert_glsl, NULL, e_data.volume_shader_lib, + SHADER_DEFINES "#define VOLUMETRICS\n"); } struct GPUMaterial *EEVEE_material_mesh_get( @@ -785,7 +791,7 @@ void EEVEE_materials_free(void) DRW_SHADER_FREE_SAFE(e_data.default_lit[i]); } MEM_SAFE_FREE(e_data.frag_shader_lib); - DRW_SHADER_FREE_SAFE(e_data.default_volume_sh); + MEM_SAFE_FREE(e_data.volume_shader_lib); DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); DRW_SHADER_FREE_SAFE(e_data.default_background); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 727edfb9607..adfa598b91c 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -50,6 +50,7 @@ extern struct DrawEngineType draw_engine_eevee_type; enum { VAR_WORLD_BACKGROUND, VAR_WORLD_PROBE, + VAR_WORLD_VOLUME, }; /* Material shader variations */ @@ -424,7 +425,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl void EEVEE_materials_cache_finish(EEVEE_Data *vedata); struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); -struct GPUShader *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo); +struct GPUMaterial *EEVEE_material_world_volume_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, bool use_ao, bool use_bent_normals); struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 6f255583340..2c72df16135 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -17,6 +17,44 @@ uniform vec4 viewvecs[2]; #define cameraPos ViewMatrixInverse[3].xyz /* ------- Structures -------- */ +#ifdef VOLUMETRICS + +#define NODETREE_EXEC + +struct Closure { + vec3 absorption; + vec3 scatter; + vec3 emission; + float anisotropy; +}; + +#define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0); + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + cl.absorption = mix(cl1.absorption, cl2.absorption, fac); + cl.scatter = mix(cl1.scatter, cl2.scatter, fac); + cl.emission = mix(cl1.emission, cl2.emission, fac); + cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac); + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl; + cl.absorption = cl1.absorption + cl2.absorption; + cl.scatter = cl1.scatter + cl2.scatter; + cl.emission = cl1.emission + cl2.emission; + cl.anisotropy = cl1.anisotropy + cl2.anisotropy; + return cl; +} + +Closure nodetree_exec(void); /* Prototype */ + + +#endif /* VOLUMETRICS */ + struct LightData { vec4 position_influence; /* w : InfluenceRadius */ diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index 8e7393a2f58..fe80fed232f 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -1,34 +1,17 @@ out vec4 FragColor; -#ifdef STEP_INTEGRATE +#ifdef VOLUMETRICS uniform sampler2D depthFull; -float find_next_step(float near, float far, float noise, int iter, int iter_count) -{ - const float lambda = 0.8f; /* TODO : Parameter */ - - float progress = (float(iter) + noise) / float(iter_count); - - float linear_split = mix(near, far, progress); - - if (ProjectionMatrix[3][3] == 0.0) { - float exp_split = near * pow(far / near, progress); - return mix(linear_split, exp_split, lambda); - } - else { - return linear_split; - } -} - void participating_media_properties(vec3 wpos, out vec3 absorption, out vec3 scattering, out float anisotropy) { - /* TODO Call nodetree from here. */ - absorption = vec3(0.00); - scattering = vec3(1.0) * step(-1.0, -wpos.z); + Closure cl = nodetree_exec(); - anisotropy = -0.8; + absorption = cl.absorption; + scattering = cl.scatter; + anisotropy = cl.anisotropy; } float phase_function_isotropic() @@ -38,7 +21,7 @@ float phase_function_isotropic() float phase_function(vec3 v, vec3 l, float g) { -#if 0 +#if 1 /* Henyey-Greenstein */ float cos_theta = dot(v, l); float sqr_g = g * g; @@ -54,6 +37,23 @@ vec3 light_volume(LightData ld, vec4 l_vector, vec3 l_col) return l_col * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI) / (dist * dist); } +float find_next_step(float near, float far, float noise, int iter, int iter_count) +{ + const float lambda = 0.8f; /* TODO : Parameter */ + + float progress = (float(iter) + noise) / float(iter_count); + + float linear_split = mix(near, far, progress); + + if (ProjectionMatrix[3][3] == 0.0) { + float exp_split = near * pow(far / near, progress); + return mix(linear_split, exp_split, lambda); + } + else { + return linear_split; + } +} + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ void main() diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index afe862bb70f..5765644cd2b 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2653,8 +2653,8 @@ layout(std140) uniform lightSource { glLight glLightSource[NUM_LIGHTS]; }; +#ifndef VOLUMETRICS /* bsdfs */ - void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) { /* ambient light */ @@ -2905,13 +2905,18 @@ void node_ambient_occlusion(vec4 color, out Closure result) { result = Closure(color.rgb, color.a); } +#endif /* VOLUMETRICS */ /* emission */ void node_emission(vec4 color, float strength, vec3 N, out Closure result) { +#ifndef VOLUMETRICS color *= strength; result = Closure(color.rgb, color.a); +#else + result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); +#endif } /* background */ @@ -2931,8 +2936,23 @@ void background_transform_to_world(vec3 viewvec, out vec3 worldvec) void node_background(vec4 color, float strength, out Closure result) { +#ifndef VOLUMETRICS color *= strength; result = Closure(color.rgb, color.a); +#else + result = CLOSURE_DEFAULT; +#endif +} + +/* volumes */ + +void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) +{ +#ifdef VOLUMETRICS + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); +#else + result = CLOSURE_DEFAULT; +#endif } /* closures */ @@ -3947,9 +3967,14 @@ uniform float backgroundAlpha; void node_output_world(Closure surface, Closure volume, out Closure result) { +#ifndef VOLUMETRICS result = Closure(surface.radiance, backgroundAlpha); +#else + result = volume; +#endif /* VOLUMETRICS */ } +#ifndef VOLUMETRICS /* TODO : clean this ifdef mess */ /* EEVEE output */ #ifdef EEVEE_ENGINE @@ -3982,7 +4007,8 @@ void node_output_eevee_material(Closure surface, out Closure result) result = Closure(surface.radiance, length(viewPosition)); } -#endif +#endif /* EEVEE_ENGINE */ +#endif /* VOLUMETRICS */ /* ********************** matcap style render ******************** */ diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c index 0c5647b4ba8..4fb1188c1d2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c +++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c @@ -41,9 +41,9 @@ static bNodeSocketTemplate sh_node_volume_scatter_out[] = { { -1, 0, "" } }; -static int node_shader_gpu_volume_scatter(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out)) +static int node_shader_gpu_volume_scatter(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { - return false; + return GPU_stack_link(mat, "node_volume_scatter", in, out); } /* node type definition */ |