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:
authorClément Foucault <foucault.clem@gmail.com>2020-06-02 17:58:07 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-06-02 17:58:07 +0300
commitb18c2a3c413b7741b2a854b7bd25721352be2589 (patch)
tree7dbdc9556a5eb4ff8f4d52afae01a9d3c47f7951 /source/blender/draw/engines
parentb82cb0ad3241ead3faee699847bc3e0065e304cd (diff)
EEVEE: Refactor of eevee_material.c
These are the modifications: -With DRW modification we reduce the number of passes we need to populate. -Rename passes for consistent naming. -Reduce complexity in code compilation -Cleanup how renderpass accumulation passes are setup, using pass instances. -Make sculpt mode compatible with shadows -Make hair passes compatible with SSS -Error shader and lookdev materials now use standalone materials. -Support default shader (world and material) using a default nodetree internally. -Change BLEND_CLIP to be emulated by gpu nodetree. Making less shader variations. -Use BLI_memblock for cache memory allocation. -Renderpasses are handled by switching a UBO ref bind. One major hack in this patch is the use of modified pointer as ghash keys. This rely on the assumption that the keys will never overlap because the number of options per key will never be bigger than the pointed struct. The use of one single nodetree to support default material is also a bit hacky since it won't support concurent usage of this nodetree. (see EEVEE_shader_default_surface_nodetree) Another change is that objects with shader errors now appear solid magenta instead of shaded magenta. This is only because of code reuse purpose but could be changed if really needed. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D7642
Diffstat (limited to 'source/blender/draw/engines')
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c91
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut_gen.c198
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c2388
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h170
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c488
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c125
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c29
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl27
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl21
24 files changed, 1542 insertions, 2223 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 6874947de55..a19af77124f 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -24,6 +24,8 @@
#include "DRW_render.h"
+#include "BLI_memblock.h"
+
#include "eevee_lightcache.h"
#include "eevee_private.h"
@@ -54,8 +56,17 @@ void EEVEE_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]);
+
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.combined);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit);
+
+ if (sldata->material_cache) {
+ BLI_memblock_destroy(sldata->material_cache, NULL);
+ sldata->material_cache = NULL;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 05b18da4374..ab846fe0f11 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -333,8 +333,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
DRW_shgroup_call(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a1112eb92df..b698574f9d7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -88,7 +88,7 @@ static void eevee_engine_init(void *ved)
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, camera, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
}
@@ -230,7 +230,7 @@ static void eevee_draw_scene(void *vedata)
BLI_halton_3d(primes, offset, samp, r);
EEVEE_update_noise(psl, fbl, r);
EEVEE_volumes_set_jitter(sldata, samp - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
}
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
@@ -274,8 +274,7 @@ static void eevee_draw_scene(void *vedata)
/* Depth prepass */
DRW_stats_group_start("Prepass");
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_stats_group_end();
/* Create minmax texture */
@@ -289,9 +288,9 @@ static void eevee_draw_scene(void *vedata)
/* Shading pass */
DRW_stats_group_start("Shading");
if (DRW_state_draw_background()) {
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
}
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
DRW_stats_group_end();
@@ -306,9 +305,8 @@ static void eevee_draw_scene(void *vedata)
/* Opaque refraction */
DRW_stats_group_start("Opaque Refraction");
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
DRW_stats_group_end();
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 198d06d845c..4cdd166f09c 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -818,7 +818,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_render_viewport_size_set(viewport_size);
EEVEE_effects_init(sldata, vedata, NULL, true);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 3350c512b17..83b2a9bb6d4 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -248,8 +248,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_instances(grp, NULL, geom, 6);
@@ -271,8 +270,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -293,8 +291,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -337,51 +334,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
/* LookDev */
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
- /* END */
+
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float queue_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
-
- eGPUMaterialStatus status = GPU_material_status(gpumat);
-
- switch (status) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
- DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- stl->g_data->queued_shaders_count++;
- col = queue_col;
- break;
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+ DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
DRW_shgroup_call(grp, geom, NULL);
}
@@ -408,8 +383,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
/* TODO (fclem) get rid of those UBO. */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2);
}
@@ -436,8 +410,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(shgrp, "renderpass_block", sldata->renderpass_ubo.combined);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count);
}
@@ -455,8 +428,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(),
psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance(
grp, e_data.format_probe_display_planar, DRW_cache_quad_get());
@@ -923,12 +895,10 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_draw_pass(psl->probe_background);
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
DRW_draw_pass(psl->transparent_pass);
}
@@ -987,10 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Slight modification: we handle refraction as normal
* shading and don't do SSRefraction. */
- DRW_draw_pass(psl->depth_pass_clip);
- DRW_draw_pass(psl->depth_pass_clip_cull);
- DRW_draw_pass(psl->refract_depth_pass_clip);
- DRW_draw_pass(psl->refract_depth_pass_clip_cull);
+ DRW_draw_pass(psl->depth_ps);
+ DRW_draw_pass(psl->depth_refract_ps);
DRW_draw_pass(psl->probe_background);
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
@@ -999,10 +967,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
+ DRW_draw_pass(psl->material_refract_ps);
/* Transparent */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index b33be750d80..18365d69514 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -34,6 +34,8 @@
#include "ED_screen.h"
+#include "GPU_material.h"
+
#include "UI_resources.h"
#include "eevee_lightcache.h"
@@ -56,6 +58,43 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata)
g_data->studiolight_rot_z = 0.0f;
}
+static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ DRWShadingGroup *grp;
+
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
+ int mat_options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
+ DRW_STATE_CULL_BACK;
+
+ {
+ Material *ma = EEVEE_material_default_diffuse_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_diffuse_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+ {
+ Material *ma = EEVEE_material_default_glossy_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_glossy_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+}
+
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
@@ -106,6 +145,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
effects->anchor[1] = rect->ymin;
EEVEE_temporal_sampling_reset(vedata);
}
+
+ eevee_lookdev_hdri_preview_init(vedata, sldata);
}
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
@@ -176,8 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c
new file mode 100644
index 00000000000..5f20d6fbfb8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * EEVEE LUT generation:
+ *
+ * Routine to generate the LUT used by eevee stored in eevee_lut.h
+ * Theses functions are not to be used in the final executable.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_alloca.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
+
+extern char datatoc_bsdf_lut_frag_glsl[];
+extern char datatoc_btdf_lut_frag_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+
+static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
+{
+ struct GPUTexture *tex;
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
+ datatoc_lightprobe_geom_glsl,
+ datatoc_bsdf_lut_frag_glsl,
+ lib_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n");
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+ DRW_draw_pass(pass);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
+
+ printf("{");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, \n", data[i], data[i + 1]);
+ }
+ printf("}");
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+ struct GPUTexture *tex;
+ struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float a2 = 0.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *frag_str = BLI_string_joinN(
+ datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n"
+ "#define LUT_SIZE 64\n");
+
+ MEM_freeN(frag_str);
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+ float inc = 1.0f / 31.0f;
+ float roughness = 1e-8f - inc;
+ FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+ fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+ do {
+ roughness += inc;
+ CLAMP(roughness, 1e-4f, 1.0f);
+ a2 = powf(roughness, 4.0f);
+ DRW_draw_pass(pass);
+
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+#if 1
+ fprintf(f, "\t{\n\t\t");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ fprintf(f, "%ff,", data[i]);
+ if (((i / 3) + 1) % 12 == 0) {
+ fprintf(f, "\n\t\t");
+ }
+ else {
+ fprintf(f, " ");
+ }
+ }
+ fprintf(f, "\n\t},\n");
+#else
+ for (int i = 0; i < w * h * 3; i += 3) {
+ if (data[i] < 0.01) {
+ printf(" ");
+ }
+ else if (data[i] < 0.3) {
+ printf(".");
+ }
+ else if (data[i] < 0.6) {
+ printf("+");
+ }
+ else if (data[i] < 0.9) {
+ printf("%%");
+ }
+ else {
+ printf("#");
+ }
+ if ((i / 3 + 1) % 64 == 0) {
+ printf("\n");
+ }
+ }
+#endif
+
+ } while (roughness < 1.0f);
+ fprintf(f, "\n};\n");
+
+ fclose(f);
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 03cdb02a48a..0563d098a1c 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -23,10 +23,10 @@
#include "DRW_render.h"
#include "BLI_alloca.h"
-#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_bits.h"
+#include "BLI_memblock.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
@@ -48,29 +48,11 @@
/* *********** STATIC *********** */
static struct {
- char *frag_shader_lib;
- char *vert_shader_str;
- char *vert_shadow_shader_str;
- char *vert_background_shader_str;
- char *vert_volume_shader_str;
- char *geom_volume_shader_str;
- char *volume_shader_lib;
-
- struct GPUShader *default_prepass_sh;
- struct GPUShader *default_prepass_clip_sh;
- struct GPUShader *default_hair_prepass_sh;
- struct GPUShader *default_hair_prepass_clip_sh;
- struct GPUShader *default_lit[VAR_MAT_MAX];
- struct GPUShader *default_background;
- struct GPUShader *update_noise_sh;
-
/* 64*64 array texture containing all LUTs and other utilitarian arrays.
* Packing enables us to same precious textures slots. */
struct GPUTexture *util_tex;
struct GPUTexture *noise_tex;
- uint sss_count;
-
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -82,8 +64,6 @@ extern char datatoc_prepass_vert_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
-extern char datatoc_bsdf_lut_frag_glsl[];
-extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
@@ -107,392 +87,91 @@ extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
-#define DEFAULT_RENDER_PASS_FLAG 0xefffffff
-
-/* Iterator for render passes. This iteration will only do the material based render passes. it
- * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`.
- *
- * parameters:
- * - `render_passes_` is a bitflag for render_passes that needs to be iterated over.
- * - `render_pass_index_` is a parameter name where the index of the render_pass will be available
- * during iteration. This index can be used to select the right pass in the `psl`.
- * - `render_pass_` is the bitflag of the render_pass of the current iteration.
- *
- * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and
- * `RENDER_PASS_ITER_END`.
- */
-#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \
- const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \
- EEVEE_RENDERPASSES_MATERIAL & \
- ~EEVEE_RENDER_PASS_ENVIRONMENT; \
- if (__filtered_##render_pass_index_ != 0) { \
- int render_pass_index_ = 1; \
- for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \
- bit_##render_pass_++) { \
- eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \
- if ((__filtered_##render_pass_index_ & render_pass_) != 0) {
-#define RENDER_PASS_ITER_END(render_pass_index_) \
- render_pass_index_ += 1; \
- } \
- } \
- } \
- ((void)0)
+typedef struct EeveeMaterialCache {
+ struct DRWShadingGroup *depth_grp;
+ struct DRWShadingGroup *shading_grp;
+ struct DRWShadingGroup *shadow_grp;
+ struct GPUMaterial *shading_gpumat;
+ /* Meh, Used by hair to ensure draw order when calling DRW_shgroup_create_sub.
+ * Pointers to ghash values. */
+ struct DRWShadingGroup **depth_grp_p;
+ struct DRWShadingGroup **shading_grp_p;
+ struct DRWShadingGroup **shadow_grp_p;
+} EeveeMaterialCache;
/* *********** FUNCTIONS *********** */
-#if 0 /* Used only to generate the LUT values */
-static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
-{
- struct GPUTexture *tex;
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
-
- struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
- datatoc_lightprobe_geom_glsl,
- datatoc_bsdf_lut_frag_glsl,
- lib_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n");
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
- DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
- DRW_draw_pass(pass);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
-
- printf("{");
- for (int i = 0; i < w * h * 3; i += 3) {
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, \n", data[i], data[i + 1]);
- }
- printf("}");
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-
-static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
-{
- struct GPUTexture *tex;
- struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float a2 = 0.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *frag_str = BLI_string_joinN(
- datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
-
- struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n"
- "#define LUT_SIZE 64\n");
-
- MEM_freeN(frag_str);
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
- DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
-
- float inc = 1.0f / 31.0f;
- float roughness = 1e-8f - inc;
- FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
- fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
- do {
- roughness += inc;
- CLAMP(roughness, 1e-4f, 1.0f);
- a2 = powf(roughness, 4.0f);
- DRW_draw_pass(pass);
-
- GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
-
-# if 1
- fprintf(f, "\t{\n\t\t");
- for (int i = 0; i < w * h * 3; i += 3) {
- fprintf(f, "%ff,", data[i]);
- if (((i / 3) + 1) % 12 == 0) {
- fprintf(f, "\n\t\t");
- }
- else {
- fprintf(f, " ");
- }
- }
- fprintf(f, "\n\t},\n");
-# else
- for (int i = 0; i < w * h * 3; i += 3) {
- if (data[i] < 0.01) {
- printf(" ");
- }
- else if (data[i] < 0.3) {
- printf(".");
- }
- else if (data[i] < 0.6) {
- printf("+");
- }
- else if (data[i] < 0.9) {
- printf("%%");
- }
- else {
- printf("#");
- }
- if ((i / 3 + 1) % 64 == 0) {
- printf("\n");
- }
- }
-# endif
-
- } while (roughness < 1.0f);
- fprintf(f, "\n};\n");
-
- fclose(f);
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-#endif
/* XXX TODO define all shared resources in a shared place without duplication */
struct GPUTexture *EEVEE_materials_get_util_tex(void)
{
return e_data.util_tex;
}
-static char *eevee_get_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
-
- if ((options & VAR_MAT_MESH) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
- if ((options & VAR_MAT_HAIR) != 0) {
- BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
- }
- if ((options & VAR_MAT_PROBE) != 0) {
- BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
- }
- if ((options & VAR_MAT_CLIP) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n");
- }
- if ((options & VAR_MAT_SHADOW) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_SHADER\n");
- }
- if ((options & VAR_MAT_HASH) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
- }
- if ((options & VAR_MAT_BLEND) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
- }
- if ((options & VAR_MAT_MULT) != 0) {
- BLI_dynstr_append(ds, "#define USE_MULTIPLY\n");
- }
- if ((options & VAR_MAT_REFRACT) != 0) {
- BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
- }
- if ((options & VAR_MAT_LOOKDEV) != 0) {
- BLI_dynstr_append(ds, "#define LOOKDEV\n");
- }
- if ((options & VAR_MAT_HOLDOUT) != 0) {
- BLI_dynstr_append(ds, "#define HOLDOUT\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-static char *eevee_get_volume_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
- BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
-
- if ((options & VAR_MAT_VOLUME) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata)
-{
- return sldata->renderpass_ubo[0];
-}
-
-/* Get the render pass ubo for rendering the given render_pass. */
-static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata,
- eViewLayerEEVEEPassType render_pass)
-{
- int index;
- switch (render_pass) {
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- index = 1;
- break;
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- index = 2;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- index = 3;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- index = 4;
- break;
- case EEVEE_RENDER_PASS_EMIT:
- index = 5;
- break;
- default:
- index = 0;
- break;
- }
- return sldata->renderpass_ubo[index];
-}
/**
* ssr_id can be null to disable ssr contribution.
*/
-static void add_standard_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- int *ssr_id,
- float *refract_depth,
- bool use_diffuse,
- bool use_glossy,
- bool use_refract,
- bool use_ssrefraction,
- bool use_alpha_blend,
- eViewLayerEEVEEPassType render_pass)
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend)
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
LightCache *lcache = vedata->stl->g_data->light_cache;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass));
+ DRW_shgroup_uniform_block_persistent(shgrp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block_persistent(shgrp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block_persistent(shgrp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block_persistent(shgrp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block_persistent(shgrp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block_persistent(shgrp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block_ref_persistent(shgrp, "renderpass_block", &pd->renderpass_ubo);
DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1);
+ DRW_shgroup_uniform_texture_persistent(shgrp, "utilTex", e_data.util_tex);
if (use_diffuse || use_glossy || use_refract) {
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
+ DRW_shgroup_uniform_texture_ref_persistent(
+ shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref_persistent(
+ shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
}
if ((use_diffuse || use_glossy) && !use_ssrefraction) {
- DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &effects->gtao_horizons);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "horizonBuffer", &effects->gtao_horizons);
}
if (use_diffuse) {
- DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
}
if (use_glossy || use_refract) {
- DRW_shgroup_uniform_texture_ref(shgrp, "probeCubes", &lcache->cube_tx.tex);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "probeCubes", &lcache->cube_tx.tex);
}
if (use_glossy) {
- DRW_shgroup_uniform_texture_ref(shgrp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "probePlanars", &vedata->txl->planar_pool);
DRW_shgroup_uniform_int_copy(shgrp, "outputSsrId", ssr_id ? *ssr_id : 0);
}
if (use_refract) {
DRW_shgroup_uniform_float_copy(
shgrp, "refractionDepth", (refract_depth) ? *refract_depth : 0.0);
if (use_ssrefraction) {
- DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
+ DRW_shgroup_uniform_texture_ref_persistent(
+ shgrp, "colorBuffer", &vedata->txl->refract_color);
}
}
if (use_alpha_blend) {
- DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &effects->volume_scatter);
- DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &effects->volume_transmit);
+ DRW_shgroup_uniform_texture_ref_persistent(shgrp, "inScattering", &effects->volume_scatter);
+ DRW_shgroup_uniform_texture_ref_persistent(
+ shgrp, "inTransmittance", &effects->volume_transmit);
}
}
-/* Add the uniforms for the background shader to `shgrp`. */
-static void add_background_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata)
-{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
-}
-
-static void create_default_shader(int options)
-{
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl);
-
- char *defines = eevee_get_defines(options);
-
- e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines);
-
- MEM_freeN(defines);
- MEM_freeN(frag_str);
-}
-
static void eevee_init_noise_texture(void)
{
e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise);
@@ -559,8 +238,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
e_data.noise_offsets[1] = offsets[1];
e_data.noise_offsets[2] = offsets[2];
- /* Attach & detach because we don't currently support multiple FB per texture,
- * and this would be the case for multiple viewport. */
GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
}
@@ -606,94 +283,15 @@ void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_vi
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_PrivateData *g_data = stl->g_data;
- if (!e_data.frag_shader_lib) {
- /* Shaders */
- e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_bsdf_sampling_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_raytrace_lib_glsl,
- datatoc_ssr_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- /* Add one for each Closure */
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_volumetric_lib_glsl);
-
- e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- datatoc_volumetric_lib_glsl,
- datatoc_volumetric_frag_glsl);
-
- e_data.vert_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
-
- e_data.vert_shadow_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
-
- e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_background_vert_glsl);
-
- e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_vert_glsl);
-
- e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_geom_glsl);
-
- e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
- NULL,
- datatoc_default_world_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
-
- char *vert_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
-
- e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL);
-
- e_data.default_prepass_clip_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
-
- e_data.default_hair_prepass_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n");
-
- e_data.default_hair_prepass_clip_sh = DRW_shader_create(vert_str,
- NULL,
- datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n"
- "#define CLIP_PLANES\n");
- MEM_freeN(vert_str);
-
- e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ if (!e_data.util_tex) {
+ EEVEE_shaders_material_shaders_init();
eevee_init_util_texture();
eevee_init_noise_texture();
@@ -728,33 +326,36 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
{
/* Create RenderPass UBO */
- if (sldata->renderpass_ubo[0] == NULL) {
- /* EEVEE_RENDER_PASS_COMBINED */
- sldata->renderpass_data[0] = (const EEVEE_RenderPassData){
- true, true, true, true, true, false};
- /* EEVEE_RENDER_PASS_DIFFUSE_COLOR */
- sldata->renderpass_data[1] = (const EEVEE_RenderPassData){
- true, false, false, false, false, true};
- /* EEVEE_RENDER_PASS_DIFFUSE_LIGHT */
- sldata->renderpass_data[2] = (const EEVEE_RenderPassData){
- true, true, false, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_COLOR */
- sldata->renderpass_data[3] = (const EEVEE_RenderPassData){
- false, false, true, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_LIGHT */
- sldata->renderpass_data[4] = (const EEVEE_RenderPassData){
- false, false, true, true, false, false};
- /* EEVEE_RENDER_PASS_EMIT */
- sldata->renderpass_data[5] = (const EEVEE_RenderPassData){
- false, false, false, false, true, false};
-
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData),
- &sldata->renderpass_data[i]);
- }
+ if (sldata->renderpass_ubo.combined == NULL) {
+ sldata->renderpass_ubo.combined = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, true, true, true, false});
+
+ sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, false, false, false, false, true});
+
+ sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, false, false, false, false});
+
+ sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, false, false, false});
+
+ sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, true, false, false});
+
+ sldata->renderpass_ubo.emit = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, false, false, true, false});
}
- /* HACK: EEVEE_material_world_background_get can create a new context. This can only be
+ /* Used combined pass by default. */
+ g_data->renderpass_ubo = sldata->renderpass_ubo.combined;
+
+ /* HACK: EEVEE_material_get can create a new context. This can only be
* done when there is no active framebuffer. We do this here otherwise
* `EEVEE_renderpasses_output_init` will fail. It cannot be done in
* `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized.
@@ -763,414 +364,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
struct Scene *scene = draw_ctx->scene;
struct World *wo = scene->world;
if (wo && wo->use_nodes) {
- EEVEE_material_world_background_get(scene, wo);
+ EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
}
}
}
}
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- const int options = VAR_WORLD_PROBE;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, false);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define PROBE_CAPTURE\n",
- false);
-}
-
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_BACKGROUND;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define WORLD_BACKGROUND\n",
- true);
-}
-
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
- Material *ma,
- EEVEE_Data *UNUSED(vedata),
- bool use_blend,
- bool use_refract)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
- SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- true);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- false);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-/**
- * Create a default shading group inside the given pass.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- DRWPass *pass,
- bool is_hair,
- bool use_blend,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
-
- return shgrp;
-}
-
-/**
- * Create a default shading group inside the default pass without standard uniforms.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool is_hair,
- bool holdout,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- EEVEE_PassList *psl = vedata->psl;
-
- BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- if (psl->default_pass[options] == NULL) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->default_pass[options], state);
-
- /* XXX / WATCH: This creates non persistent binds for the ubos and textures.
- * But it's currently OK because the following shgroups does not add any bind.
- * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
- if (!is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options],
- psl->default_pass[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- }
- }
-
- if (is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- return shgrp;
- }
- else {
- return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- }
-}
-
-static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
-static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- BLI_assert((ob && psys && md));
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, pass, e_data.default_lit[options]);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@@ -1180,10 +379,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
+
+ if (sldata->material_cache == NULL) {
+ sldata->material_cache = BLI_memblock_create(sizeof(EeveeMaterialCache));
+ }
+ else {
+ BLI_memblock_clear(sldata->material_cache, NULL);
+ }
}
{
- DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -1191,485 +397,297 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
- EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL);
+ EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL);
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
-
- switch (GPU_material_status(gpumat)) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- col = compile_col;
- break;
- case GPU_MAT_FAILED:
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(
+ vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->background_ps);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
- grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ GPUShader *sh = EEVEE_shaders_default_background_sh_get();
+ grp = DRW_shgroup_create(sh, psl->background_ps);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
DRW_shgroup_call(grp, geom, NULL);
}
}
- {
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->depth_pass, state);
- stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_cull, state);
- stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->depth_pass_clip, state);
- stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_clip_cull, state);
- stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip_cull);
- }
+#define EEVEE_PASS_CREATE(pass, state) \
+ do { \
+ DRW_PASS_CREATE(psl->pass##_ps, state); \
+ DRW_PASS_CREATE(psl->pass##_cull_ps, state | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_ps, psl->pass##_cull_ps); \
+ } while (0)
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->material_pass, state);
- DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK);
- }
+#define EEVEE_CLIP_PASS_CREATE(pass, state) \
+ do { \
+ DRWState st = state | DRW_STATE_CLIP_PLANES; \
+ DRW_PASS_INSTANCE_CREATE(psl->pass##_clip_ps, psl->pass##_ps, st); \
+ DRW_PASS_INSTANCE_CREATE( \
+ psl->pass##_clip_cull_ps, psl->pass##_cull_ps, st | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_clip_ps, psl->pass##_clip_cull_ps); \
+ } while (0)
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->refract_depth_pass, state);
- stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_cull, state);
- stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip, state);
- stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->refract_depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state);
- stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(
- e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
- }
+ DRWState state_depth = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRWState state_shading = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRWState state_sss = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES);
- DRW_PASS_CREATE(psl->refract_pass, state);
- }
+ EEVEE_PASS_CREATE(depth, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth, state_depth);
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS);
- DRW_PASS_CREATE(psl->sss_pass, state);
- DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
- e_data.sss_count = 0;
+ EEVEE_PASS_CREATE(depth_refract, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth_refract, state_depth);
+
+ EEVEE_PASS_CREATE(material, state_shading);
+ EEVEE_PASS_CREATE(material_refract, state_shading);
+ EEVEE_PASS_CREATE(material_sss, state_shading | state_sss);
}
+ {
+ /* Renderpass accumulation. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
+ /* Create an instance of each of theses passes and link them together. */
+ DRWPass *passes[] = {
+ psl->material_ps,
+ psl->material_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ };
+ DRWPass *first = NULL, *last = NULL;
+ for (int i = 0; i < ARRAY_SIZE(passes); i++) {
+ DRWPass *pass = DRW_pass_create_instance("Renderpass Accumulation", passes[i], state);
+ if (first == NULL) {
+ first = last = pass;
+ }
+ else {
+ DRW_pass_link(last, pass);
+ last = pass;
+ }
+ }
+ psl->material_accum_ps = first;
+ /* Same for background */
+ DRW_PASS_INSTANCE_CREATE(psl->background_accum_ps, psl->background_ps, state);
+ }
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
DRW_PASS_CREATE(psl->transparent_pass, state);
}
-
{
DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
+ GPUShader *sh = EEVEE_shaders_update_noise_sh_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->update_noise_pass);
DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
+}
- if (eevee_hdri_preview_overlay_enabled(draw_ctx->v3d)) {
- DRWShadingGroup *shgrp;
-
- struct GPUBatch *sphere = DRW_cache_sphere_get();
- static float color_chrome[3] = {1.0f, 1.0f, 1.0f};
- static float color_diffuse[3] = {0.8f, 0.8f, 0.8f};
- int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+BLI_INLINE void material_shadow(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ bool is_hair,
+ EeveeMaterialCache *emc)
+{
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
+ if (ma->blend_shadow != MA_BS_NONE) {
+ /* Shadow Pass */
+ const bool use_shadow_shader = ma->use_nodes && ma->nodetree &&
+ ELEM(ma->blend_shadow, MA_BS_CLIP, MA_BS_HASHED);
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_shadow_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_shadow_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ /* Avoid possible confusion with depth pre-pass options. */
+ int option = KEY_SHADOW;
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
+ }
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, psl->shadow_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_CULL_BACK;
-
- DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
-
- DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- {
- memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass));
- for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count;
- pass_index++) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
- DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state);
- }
+ emc->shadow_grp = grp;
+ emc->shadow_grp_p = grp_p;
+ }
+ else {
+ emc->shadow_grp = NULL;
+ emc->shadow_grp_p = NULL;
}
}
-#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
- do { \
- if (oedata) { \
- DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
- } \
- else { \
- DRW_shgroup_call(shgrp, geom, ob); \
- } \
- } while (0)
-
-#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
- do { \
- if (shgrp) { \
- ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
- } \
- } while (0)
-
-typedef struct EeveeMaterialShadingGroups {
- struct DRWShadingGroup *shading_grp;
- struct DRWShadingGroup *depth_grp;
- struct DRWShadingGroup *depth_clip_grp;
- struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES];
-} EeveeMaterialShadingGroups;
-
-static void material_opaque(Material *ma,
- GHash *material_hash,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct GPUMaterial **gpumat_depth,
- struct EeveeMaterialShadingGroups *shgrps,
- bool holdout)
+static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ const bool is_hair)
{
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- bool use_diffuse, use_glossy, use_refract;
- bool store_material = true;
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
- const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
- const bool use_gpumat = (ma->use_nodes && ma->nodetree && !holdout);
+ const bool do_cull = !is_hair && (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
+ const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
-
- EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
-
- if (emsg) {
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
+ const bool use_depth_shader = use_gpumat && ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED);
- /* This will have been created already, just perform a lookup. */
- *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) :
- NULL;
- *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false) :
- NULL;
- return;
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ void *key = (char *)ma + is_hair;
+ /* Search for other material instances (sharing the same Material datablock). */
+ EeveeMaterialCache **emc_p, *emc;
+ if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) {
+ return **emc_p;
+ }
+ else {
+ *emc_p = emc = BLI_memblock_alloc(sldata->material_cache);
}
- emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups");
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
-
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract);
-
- eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
-
- /* Alpha CLipped : Discard pixel from depth pass, then
- * fail the depth test for shading. */
- if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
- *gpumat_depth = EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false);
-
- eGPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth);
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else if (use_ssrefract) {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth,
- (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
- }
- else {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
- }
+ material_shadow(vedata, sldata, ma, is_hair, emc);
- if (emsg->depth_grp != NULL) {
- use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(emsg->depth_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- add_standard_uniforms(emsg->depth_clip_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (ma->blend_method == MA_BM_CLIP) {
- DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- DRW_shgroup_uniform_float(
- emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
+ {
+ /* Depth Pass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, use_depth_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_depth_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ int option = 0;
+ SET_FLAG_FROM_TEST(option, do_cull, KEY_CULL);
+ SET_FLAG_FROM_TEST(option, use_ssrefract, KEY_REFRACT);
+ DRWPass *depth_ps = (DRWPass *[]){
+ psl->depth_ps,
+ psl->depth_cull_ps,
+ psl->depth_refract_ps,
+ psl->depth_refract_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key. */
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- static int no_ssr = 0;
- static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ?
- &first_ssr :
- &no_ssr;
- const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
- use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- emsg->shading_grp = DRW_shgroup_material_create(
- *gpumat,
- (use_ssrefract) ?
- psl->refract_pass :
- (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) :
- ((do_cull) ? psl->material_pass_cull : psl->material_pass));
-
- add_standard_uniforms(emsg->shading_grp,
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (use_sss) {
- struct GPUTexture *sss_tex_profile = NULL;
- struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
- *gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-
- if (sss_profile) {
- /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
- if (e_data.sss_count < 254) {
- int sss_id = e_data.sss_count + 1;
- DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id);
- EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile);
- if (use_translucency) {
- EEVEE_subsurface_translucency_add_pass(
- sldata, vedata, sss_id, sss_profile, sss_tex_profile);
- }
- e_data.sss_count++;
- }
- else {
- /* TODO : display message. */
- printf("Error: Too many different Subsurface shader in the scene.\n");
- }
- }
- }
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create(
- *gpumat, psl->material_accum_pass[render_pass_index]);
- add_standard_uniforms(emsg->material_accum_grp[render_pass_index],
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- store_material = false;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, depth_ps);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- }
- /* Fallback to default shader */
- if (emsg->shading_grp == NULL) {
- bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
- emsg->shading_grp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get(
- sldata,
- vedata,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- 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);
- emsg->material_accum_grp[render_pass_index] = shgrp;
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback default depth prepass */
- if (emsg->depth_grp == NULL) {
- if (use_ssrefract) {
- emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull :
- stl->g_data->refract_depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull :
- stl->g_data->refract_depth_shgrp_clip;
+ emc->depth_grp = grp;
+ emc->depth_grp_p = grp_p;
+ }
+ {
+ /* Shading Pass */
+ int mat_options = VAR_MAT_MESH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SSS);
+
+ int ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? 1 : 0;
+ int option = (use_ssrefract ? 0 : (use_sss ? 1 : 2)) * 2 + do_cull;
+ DRWPass *shading_pass = (DRWPass *[]){
+ psl->material_refract_ps,
+ psl->material_refract_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ psl->material_ps,
+ psl->material_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key */
+ option = option * 2 + is_hair;
+
+ /* Search for the same shaders usage in the pass. */
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ BLI_assert(option <= 16);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
else {
- emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull :
- stl->g_data->depth_shgrp_clip;
+ *grp_p = grp = DRW_shgroup_create(sh, shading_pass);
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, false);
}
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
- if (store_material) {
- BLI_ghash_insert(material_hash, ma, emsg);
- }
- else {
- MEM_freeN(emsg);
+ if (use_sss) {
+ EEVEE_subsurface_add_pass(sldata, vedata, ma, grp, gpumat);
+ }
+
+ emc->shading_grp = grp;
+ emc->shading_grp_p = grp_p;
+ emc->shading_gpumat = gpumat;
}
+ return *emc;
}
-static void material_transparent(Material *ma,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct EeveeMaterialShadingGroups *shgrps)
+static EeveeMaterialCache material_transparent(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EeveeMaterialCache emc = {0};
const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_gpumat = ma->use_nodes && ma->nodetree;
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
- const float *color_p = &ma->r;
- const float *metal_p = &ma->metallic;
- const float *spec_p = &ma->spec;
- const float *rough_p = &ma->roughness;
-
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState cur_state;
@@ -1677,81 +695,53 @@ static void material_transparent(Material *ma,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
- /* Depth prepass */
+ material_shadow(vedata, sldata, ma, false, &emc);
+
if (use_prepass) {
- shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+ /* Depth prepass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->transparent_pass);
+
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- DRW_shgroup_state_disable(shgrps->depth_grp, all_state);
- DRW_shgroup_state_enable(shgrps->depth_grp, cur_state);
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
+
+ emc.depth_grp = grp;
}
+ {
+ /* Shading */
+ int ssr_id = -1; /* TODO transparent SSR */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
+ DRWShadingGroup *grp = DRW_shgroup_create(GPU_material_get_shader(gpumat),
+ psl->transparent_pass);
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract);
-
- switch (GPU_material_status(*gpumat)) {
- case GPU_MAT_SUCCESS: {
- static int ssr_id = -1; /* TODO transparent SSR */
-
- shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
-
- bool use_blend = true;
- bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(shgrps->shading_grp,
- sldata,
- vedata,
- &ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
- break;
- }
- case GPU_MAT_QUEUED: {
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- }
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback to default shader */
- if (shgrps->shading_grp == NULL) {
- shgrps->shading_grp = EEVEE_default_shading_group_create(
- sldata, vedata, psl->transparent_pass, false, true, false);
- DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1);
- }
+ cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
+ cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
- cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+ /* Disable other blend modes and use the one we want. */
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
- /* Disable other blend modes and use the one we want. */
- DRW_shgroup_state_disable(shgrps->shading_grp, all_state);
- DRW_shgroup_state_enable(shgrps->shading_grp, cur_state);
+ emc.shading_grp = grp;
+ emc.shading_gpumat = gpumat;
+ }
+ return emc;
}
/* Return correct material or empty default material if slot is empty. */
@@ -1766,12 +756,35 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou
ma = BKE_material_default_volume();
}
else {
- ma = BKE_material_default_empty();
+ ma = BKE_material_default_surface();
}
}
return ma;
}
+BLI_INLINE EeveeMaterialCache eevee_material_cache_get(
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair)
+{
+ const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
+ EeveeMaterialCache matcache;
+ Material *ma = eevee_object_material_get(ob, slot, holdout);
+ switch (ma->blend_method) {
+ case MA_BM_BLEND:
+ if (!is_hair) {
+ matcache = material_transparent(vedata, sldata, ma);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case MA_BM_SOLID:
+ case MA_BM_CLIP:
+ case MA_BM_HASHED:
+ default:
+ matcache = material_opaque(vedata, sldata, ma, is_hair);
+ break;
+ }
+ return matcache;
+}
+
static void eevee_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1780,240 +793,49 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata,
int matnr,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
-
- DRWShadingGroup *shgrp = NULL;
- Material *ma = eevee_object_material_get(ob, matnr - 1, holdout);
- const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout;
- const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED);
- const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP);
- const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
-
- GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL;
- eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS;
-
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
+ EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true);
- /* Depth prepass. */
- if (use_gpumat && (use_alpha_clip || use_alpha_hash)) {
- GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false);
-
- eGPUMaterialStatus status_mat_depth = GPU_material_status(gpumat_depth);
-
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else {
- const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE);
- const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY);
- const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT);
-
- for (int i = 0; i < 2; i++) {
- DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth);
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (use_alpha_clip) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
- }
+ if (matcache.depth_grp) {
+ *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp);
}
-
- /* Fallback to default shader */
- if (shgrp == NULL) {
- for (int i = 0; i < 2; i++) {
- DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
- struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh :
- e_data.default_hair_prepass_clip_sh;
- DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh);
- }
+ if (matcache.shading_grp) {
+ *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp);
}
-
- shgrp = NULL;
-
- if (gpumat) {
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- static float half = 0.5f;
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat);
-
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* HACK: Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs are present.
- * This binds utilTex even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Add the hair to all the render_passes that are enabled */
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = DRW_shgroup_material_hair_create(
- ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat);
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs that need it are present.
- * This binds `utilTex` even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
+ if (matcache.shadow_grp) {
+ *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp);
+ *cast_shadow = true;
}
+}
- /* Fallback to default shader */
- if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr);
- 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);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = EEVEE_default_hair_render_pass_shading_group_get(
- sldata,
- vedata,
- ob,
- psys,
- md,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- 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);
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
+ do { \
+ if (oedata) { \
+ DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
+ } \
+ else { \
+ DRW_shgroup_call(shgrp, geom, ob); \
+ } \
+ } while (0)
- /* Shadows */
- char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID;
- const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED);
- switch (blend_shadow) {
- case MA_BS_SOLID:
- DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- case MA_BS_HASHED:
- gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true);
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat);
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (!shadow_alpha_hash) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
+ do { \
+ if (shgrp) { \
+ ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
+ } \
+ } while (0)
+
+#define MATCACHE_AS_ARRAY(matcache, member, materials_len, output_array) \
+ for (int i = 0; i < materials_len; i++) { \
+ output_array[i] = matcache[i].member; \
}
-}
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- GHash *material_hash = stl->g_data->material_hash;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
@@ -2022,139 +844,64 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const int materials_len = DRW_cache_object_material_count_get(ob);
- struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array,
- materials_len);
-
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
-
+ EeveeMaterialCache *matcache = BLI_array_alloca(matcache, materials_len);
for (int i = 0; i < materials_len; i++) {
- ma_array[i] = eevee_object_material_get(ob, i, holdout);
- memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups));
- gpumat_array[i] = NULL;
- gpumat_depth_array[i] = NULL;
-
- switch (ma_array[i]->blend_method) {
- case MA_BM_SOLID:
- case MA_BM_CLIP:
- case MA_BM_HASHED:
- material_opaque(ma_array[i],
- material_hash,
- sldata,
- vedata,
- &gpumat_array[i],
- &gpumat_depth_array[i],
- &shgrps_array[i],
- holdout);
- break;
- case MA_BM_BLEND:
- material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ matcache[i] = eevee_material_cache_get(vedata, sldata, ob, i, false);
}
/* Only support single volume material for now. */
/* XXX We rely on the previously compiled surface shader
* to know if the material has a "volume nodetree".
*/
- bool use_volume_material = (gpumat_array[0] &&
- GPU_material_has_volume_output(gpumat_array[0]));
+ bool use_volume_material = (matcache[0].shading_gpumat &&
+ GPU_material_has_volume_output(matcache[0].shading_gpumat));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
- /* Get per-material split surface */
- struct GPUBatch **mat_geom = NULL;
-
- if (!use_sculpt_pbvh) {
- mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
- }
-
if (use_sculpt_pbvh) {
- struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array,
- materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].shading_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ MATCACHE_AS_ARRAY(matcache, shading_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index];
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- }
+ MATCACHE_AS_ARRAY(matcache, depth_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- /* TODO(fclem): Support shadows in sculpt mode. */
+ MATCACHE_AS_ARRAY(matcache, shadow_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
}
- else if (mat_geom) {
- for (int i = 0; i < materials_len; i++) {
- if (mat_geom[i] == NULL) {
- continue;
- }
+ else {
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ MATCACHE_AS_ARRAY(matcache, shading_gpumat, materials_len, gpumat_array);
+ /* Get per-material split surface */
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
+ ob, gpumat_array, materials_len);
- /* Do not render surface if we are rendering a volume object
- * and do not have a surface closure. */
- if (use_volume_material &&
- (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
- continue;
- }
+ if (mat_geom) {
+ for (int i = 0; i < materials_len; i++) {
+ if (mat_geom[i] == NULL) {
+ continue;
+ }
- /* XXX TODO rewrite this to include the dupli objects.
- * This means we cannot exclude dupli objects from reflections!!! */
- EEVEE_ObjectEngineData *oedata = NULL;
- if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
- oedata = EEVEE_object_data_ensure(ob);
- oedata->ob = ob;
- oedata->test_data = &sldata->probes->vis_data;
- }
- EeveeMaterialShadingGroups *shgrps = &shgrps_array[i];
- ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- ADD_SHGROUP_CALL_SAFE(
- shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata);
- }
+ /* Do not render surface if we are rendering a volume object
+ * and do not have a surface closure. */
+ if (use_volume_material &&
+ (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
+ continue;
+ }
- /* Shadow Pass */
- struct GPUMaterial *gpumat;
- const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree);
- char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID;
- switch (blend_shadow) {
- case MA_BS_SOLID:
- EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
- EEVEE_shadows_caster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
- *cast_shadow = true;
- break;
- case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
- EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+ /* XXX TODO rewrite this to include the dupli objects.
+ * This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
+ if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
+ oedata = EEVEE_object_data_ensure(ob);
+ oedata->ob = ob;
+ oedata->test_data = &sldata->probes->vis_data;
+ }
+
+ ADD_SHGROUP_CALL(matcache[i].shading_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].depth_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].shadow_grp, ob, mat_geom[i], oedata);
+ *cast_shadow = (matcache[i].shadow_grp != NULL);
}
}
}
@@ -2205,11 +952,12 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
- BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+ BLI_ghash_free(pd->material_hash, NULL, NULL);
- SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS);
+ SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS);
/* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
EEVEE_subsurface_draw_init(sldata, vedata);
@@ -2217,38 +965,10 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
void EEVEE_materials_free(void)
{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
- }
- MEM_SAFE_FREE(e_data.frag_shader_lib);
- MEM_SAFE_FREE(e_data.vert_shader_str);
- MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
- MEM_SAFE_FREE(e_data.vert_background_shader_str);
- MEM_SAFE_FREE(e_data.vert_volume_shader_str);
- MEM_SAFE_FREE(e_data.geom_volume_shader_str);
- MEM_SAFE_FREE(e_data.volume_shader_lib);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);
- 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);
- DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
}
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl)
-{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- if (psl->default_pass[i]) {
- DRW_draw_pass(psl->default_pass[i]);
- }
- }
-
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
-}
-
/* -------------------------------------------------------------------- */
/** \name Render Passes
@@ -2256,172 +976,140 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
/* For diffuse and glossy we calculate the final light + color buffer where we extract the
* light from by dividing by the color buffer. When one the light is requested we also tag
* the color buffer to do the extraction. */
- if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
}
- if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
}
+}
- /* Calculate the number of material based render passes */
- uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL);
- if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) ==
- 0) {
- num_render_passes += 1;
+static void material_renderpass_init(EEVEE_FramebufferList *fbl,
+ GPUTexture **output_tx,
+ const eGPUTextureFormat format,
+ const bool do_clear)
+{
+ DRW_texture_ensure_fullscreen_2d(output_tx, format, 0);
+ /* Clear texture. */
+ if (do_clear) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* TODO(fclem) replace by GPU_texture_clear once it is fast. */
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
+ GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx);
}
- stl->g_data->render_passes_material_count = num_render_passes;
}
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_FramebufferList *fbl = vedata->fbl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PassList *psl = vedata->psl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *pd = stl->g_data;
- float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* Should be enough precision for many samples. */
+ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
+ const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1);
/* Create FrameBuffer. */
+ GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- /* Should be enough precision for many samples. */
- const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F :
- GPU_RGBA16F;
- const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL;
- if (render_passes != 0) {
- GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
- {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1;
- for (int bit = 0; bit < 32; bit++) {
- eViewLayerEEVEEPassType bitflag = (1 << bit);
- if ((render_passes & bitflag) != 0) {
-
- DRW_texture_ensure_fullscreen_2d(
- &txl->material_accum[render_pass_index], texture_format_material_accum, 0);
-
- /* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[render_pass_index]);
- }
- render_pass_index++;
- }
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear);
- if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (effects->enabled_effects & EFFECT_SSR)) {
+ if (effects->enabled_effects & EFFECT_SSR) {
EEVEE_reflection_output_init(sldata, vedata, tot_samples);
}
+ }
+}
- if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
- Scene *scene = draw_ctx->scene;
- World *wo = scene->world;
+static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
+ DRWPass *renderpass,
+ EEVEE_PrivateData *pd,
+ GPUTexture *output_tx,
+ struct GPUUniformBuffer *renderpass_option_ubo)
+{
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
- if (wo && wo->use_nodes && wo->nodetree) {
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
- if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) {
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
- }
- }
- }
+ pd->renderpass_ubo = renderpass_option_ubo;
+ DRW_draw_pass(renderpass);
+
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx);
}
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_TextureList *txl = vedata->txl;
if (fbl->material_accum_fb != NULL) {
- for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- if (txl->material_accum[renderpass_index] != NULL) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- DRW_draw_pass(psl->material_accum_pass[renderpass_index]);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[renderpass_index]);
- }
+ DRWPass *material_accum_ps = psl->material_accum_ps;
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_accumulate(
+ fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined);
}
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (stl->effects->enabled_effects & EFFECT_SSR)) {
- EEVEE_reflection_output_accumulate(sldata, vedata);
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
}
- }
-}
-
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- EEVEE_StorageList *stl = vedata->stl;
-
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0);
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0);
-
- /* pass_index 0 is reserved for the environment pass. */
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) {
- return 0;
- }
-
- /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */
- int index = 1;
- eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL &
- ~EEVEE_RENDER_PASS_ENVIRONMENT;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light);
- for (int bitshift = 0; bitshift < 32; bitshift++) {
- eViewLayerEEVEEPassType pass_flag = (1 << bitshift);
- if (pass_flag == renderpass_type) {
- break;
+ if (effects->enabled_effects & EFFECT_SSS) {
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
+ }
}
- if (active_material_passes & pass_flag) {
- index++;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color);
}
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light);
- return index;
-}
+ if (effects->enabled_effects & EFFECT_SSR) {
+ EEVEE_reflection_output_accumulate(sldata, vedata);
+ }
+ }
-/* Get the pass index that contains the color pass for the given renderpass_type. */
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- BLI_assert(
- ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT));
- eViewLayerEEVEEPassType color_pass_type;
- switch (renderpass_type) {
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR;
- break;
- default:
- color_pass_type = 0;
- BLI_assert(false);
+ /* Restore default. */
+ pd->renderpass_ubo = sldata->renderpass_ubo.combined;
+ GPU_framebuffer_bind(fbl->main_fb);
}
- return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type);
}
+
/* \} */
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index cdcfd64d995..7b942784ee9 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -114,8 +114,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index be4dfd07ce1..f5ebbe08dd1 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -170,8 +170,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
@@ -209,8 +208,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR);
@@ -219,8 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
@@ -233,8 +230,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 264f301e52c..dbe2adef789 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -158,35 +158,34 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
(EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \
EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \
EEVEE_RENDER_PASS_ENVIRONMENT)
-#define MAX_MATERIAL_RENDER_PASSES 6
-#define MAX_MATERIAL_RENDER_PASSES_UBO 6
-/* World shader variations */
-enum {
- VAR_WORLD_BACKGROUND = 0,
- VAR_WORLD_PROBE = 1,
- VAR_WORLD_VOLUME = 2,
-};
/* Material shader variations */
enum {
VAR_MAT_MESH = (1 << 0),
- VAR_MAT_PROBE = (1 << 1),
+ VAR_MAT_VOLUME = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
- VAR_MAT_BLEND = (1 << 3),
- VAR_MAT_VOLUME = (1 << 4),
+ VAR_MAT_PROBE = (1 << 3),
+ VAR_MAT_BLEND = (1 << 4),
VAR_MAT_LOOKDEV = (1 << 5),
VAR_MAT_HOLDOUT = (1 << 6),
- /* Max number of variation */
- /* IMPORTANT : Leave it last and set
- * it's value accordingly. */
- VAR_MAT_MAX = (1 << 7),
- /* These are options that are not counted in VAR_MAT_MAX
- * because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 9),
- VAR_MAT_HASH = (1 << 10),
- VAR_MAT_MULT = (1 << 11),
- VAR_MAT_SHADOW = (1 << 12),
- VAR_MAT_REFRACT = (1 << 13),
+ VAR_MAT_HASH = (1 << 7),
+ VAR_MAT_DEPTH = (1 << 8),
+ VAR_MAT_REFRACT = (1 << 9),
+ VAR_WORLD_BACKGROUND = (1 << 10),
+ VAR_WORLD_PROBE = (1 << 11),
+ VAR_WORLD_VOLUME = (1 << 12),
+ VAR_DEFAULT = (1 << 13),
+};
+
+/* Material shader cache keys */
+enum {
+ /* HACK: This assumes the struct GPUShader will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing.
+ * We combine the GPUShader pointer with the key. */
+ KEY_CULL = (1 << 0),
+ KEY_REFRACT = (1 << 1),
+ KEY_HAIR = (1 << 2),
+ KEY_SHADOW = (1 << 3),
};
/* ************ PROBE UBO ************* */
@@ -272,23 +271,26 @@ typedef struct EEVEE_PassList {
struct DRWPass *maxz_copydepth_ps;
struct DRWPass *maxz_copydepth_layer_ps;
- struct DRWPass *depth_pass;
- struct DRWPass *depth_pass_cull;
- struct DRWPass *depth_pass_clip;
- struct DRWPass *depth_pass_clip_cull;
- struct DRWPass *refract_depth_pass;
- struct DRWPass *refract_depth_pass_cull;
- struct DRWPass *refract_depth_pass_clip;
- struct DRWPass *refract_depth_pass_clip_cull;
- struct DRWPass *default_pass[VAR_MAT_MAX];
- struct DRWPass *sss_pass;
- struct DRWPass *sss_pass_cull;
- struct DRWPass *material_pass;
- struct DRWPass *material_pass_cull;
- struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES];
- struct DRWPass *refract_pass;
+ /* Renderpass Accumulation. */
+ struct DRWPass *material_accum_ps;
+ struct DRWPass *background_accum_ps;
+
+ struct DRWPass *depth_ps;
+ struct DRWPass *depth_cull_ps;
+ struct DRWPass *depth_clip_ps;
+ struct DRWPass *depth_clip_cull_ps;
+ struct DRWPass *depth_refract_ps;
+ struct DRWPass *depth_refract_cull_ps;
+ struct DRWPass *depth_refract_clip_ps;
+ struct DRWPass *depth_refract_clip_cull_ps;
+ struct DRWPass *material_ps;
+ struct DRWPass *material_cull_ps;
+ struct DRWPass *material_refract_ps;
+ struct DRWPass *material_refract_cull_ps;
+ struct DRWPass *material_sss_ps;
+ struct DRWPass *material_sss_cull_ps;
struct DRWPass *transparent_pass;
- struct DRWPass *background_pass;
+ struct DRWPass *background_ps;
struct DRWPass *update_noise_pass;
struct DRWPass *lookdev_glossy_pass;
struct DRWPass *lookdev_diffuse_pass;
@@ -348,7 +350,12 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *mist_accum;
struct GPUTexture *ao_accum;
struct GPUTexture *sss_accum;
- struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES];
+ struct GPUTexture *env_accum;
+ struct GPUTexture *diff_color_accum;
+ struct GPUTexture *diff_light_accum;
+ struct GPUTexture *spec_color_accum;
+ struct GPUTexture *spec_light_accum;
+ struct GPUTexture *emit_accum;
struct GPUTexture *bloom_accum;
struct GPUTexture *ssr_accum;
struct GPUTexture *shadow_accum;
@@ -574,6 +581,7 @@ typedef struct EEVEE_EffectsInfo {
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
+ int sss_surface_count;
struct GPUTexture *sss_irradiance; /* Textures from pool */
struct GPUTexture *sss_radius;
struct GPUTexture *sss_albedo;
@@ -754,14 +762,22 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *planar_ubo;
/* Material Render passes */
- struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO];
- struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO];
+ struct {
+ struct GPUUniformBuffer *combined;
+ struct GPUUniformBuffer *diff_color;
+ struct GPUUniformBuffer *diff_light;
+ struct GPUUniformBuffer *spec_color;
+ struct GPUUniformBuffer *spec_light;
+ struct GPUUniformBuffer *emit;
+ } renderpass_ubo;
/* Common Uniform Buffer */
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
struct LightCache *fallback_lightcache;
+
+ struct BLI_memblock *material_cache;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -809,14 +825,6 @@ typedef struct EEVEE_Data {
typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *shadow_accum_shgrp;
- struct DRWShadingGroup *depth_shgrp;
- struct DRWShadingGroup *depth_shgrp_cull;
- struct DRWShadingGroup *depth_shgrp_clip;
- struct DRWShadingGroup *depth_shgrp_clip_cull;
- struct DRWShadingGroup *refract_depth_shgrp;
- struct DRWShadingGroup *refract_depth_shgrp_cull;
- struct DRWShadingGroup *refract_depth_shgrp_clip;
- struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
float background_alpha; /* TODO find a better place for this. */
@@ -862,9 +870,8 @@ typedef struct EEVEE_PrivateData {
GPUTexture *renderpass_input;
GPUTexture *renderpass_col_input;
GPUTexture *renderpass_light_input;
- /* The number of active material based render passes */
- uint render_passes_material_count;
-
+ /* Renderpass ubo reference used by material pass. */
+ struct GPUUniformBuffer *renderpass_ubo;
/** For rendering shadows. */
struct DRWView *cube_views[6];
/** For rendering probes. */
@@ -892,6 +899,7 @@ EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -908,31 +916,20 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
Object *ob,
bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, 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 GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_mesh_get(
- struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract);
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow);
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma);
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata);
void EEVEE_materials_free(void);
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend);
/* eevee_lights.c */
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -943,16 +940,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh);
void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata);
void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata,
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob);
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold);
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
@@ -986,6 +973,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
+void EEVEE_shaders_material_shaders_init(void);
struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_default_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void);
@@ -993,12 +981,22 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
+struct GPUShader *EEVEE_shaders_default_background_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
+struct GPUShader *EEVEE_shaders_update_noise_sh_get(void);
struct GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void);
struct GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects);
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma);
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo);
+Material *EEVEE_material_default_diffuse_get(void);
+Material *EEVEE_material_default_glossy_get(void);
+Material *EEVEE_material_default_error_get(void);
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options);
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
void EEVEE_shaders_free(void);
/* eevee_lightprobes.c */
@@ -1105,13 +1103,9 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata,
uint tot_samples);
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- struct GPUTexture *sss_tex_profile);
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 076738dcbdf..89a5ad2198a 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -151,7 +151,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
@@ -463,7 +463,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
GPU_ATTACHMENT_NONE});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
GPU_framebuffer_ensure_config(&fbl->main_fb,
{GPU_ATTACHMENT_LEAVE,
@@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_update_noise(psl, fbl, r);
EEVEE_temporal_sampling_matrices_calc(stl->effects, r);
EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
/* Refresh Probes
* Shadows needs to be updated for correct probes */
@@ -578,8 +578,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
GPU_framebuffer_bind(fbl->main_fb);
GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
/* Create minmax texture */
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
@@ -587,16 +586,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Shading pass */
eevee_render_draw_background(vedata);
GPU_framebuffer_bind(fbl->main_fb);
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
EEVEE_reflection_compute(sldata, vedata);
EEVEE_refraction_compute(sldata, vedata);
/* Opaque refraction */
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
/* Result NORMAL */
eevee_render_result_normal(rl, viewname, rect, vedata, sldata);
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 9112e14dcf5..4a1880caf7d 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -201,8 +201,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
grp, "inputSecondLightBuffer", &g_data->renderpass_light_input);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1);
DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1);
DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1);
@@ -225,7 +224,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
* Only invoke this function for passes that need post-processing.
*
* After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */
-void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
+void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata),
EEVEE_Data *vedata,
eViewLayerEEVEEPassType renderpass_type)
{
@@ -276,22 +275,30 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
g_data->renderpass_input = txl->shadow_accum;
break;
}
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- case EEVEE_RENDER_PASS_ENVIRONMENT:
+ case EEVEE_RENDER_PASS_DIFFUSE_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->diff_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_SPECULAR_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->spec_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_ENVIRONMENT: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->env_accum;
+ break;
+ }
case EEVEE_RENDER_PASS_EMIT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
+ g_data->renderpass_input = txl->emit_accum;
break;
}
case EEVEE_RENDER_PASS_SPECULAR_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->spec_light_accum;
+ g_data->renderpass_col_input = txl->spec_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->ssr_accum;
@@ -303,11 +310,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
}
case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->diff_light_accum;
+ g_data->renderpass_col_input = txl->diff_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->sss_accum;
@@ -343,10 +347,6 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata,
if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) {
EEVEE_mist_output_accumulate(sldata, vedata);
}
- if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 &&
- (effects->enabled_effects & EFFECT_SSS) != 0) {
- EEVEE_subsurface_output_accumulate(sldata, vedata);
- }
if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) {
EEVEE_occlusion_output_accumulate(sldata, vedata);
}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2e467fe8535..cece67334c5 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -237,8 +237,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
@@ -259,8 +258,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 50b7c5c5f97..4d25f62a317 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -22,12 +22,20 @@
#include "DRW_render.h"
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
+
+#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "MEM_guardedalloc.h"
+#include "GPU_material.h"
#include "GPU_shader.h"
+#include "NOD_shader.h"
+
+#include "eevee_engine.h"
#include "eevee_private.h"
static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
@@ -61,6 +69,38 @@ static struct {
struct GPUShader *taa_resolve_sh;
struct GPUShader *taa_resolve_reproject_sh;
+ /* General purpose Shaders. */
+ struct GPUShader *default_background;
+ struct GPUShader *update_noise_sh;
+
+ /* Shader strings */
+ char *frag_shader_lib;
+ char *vert_shader_str;
+ char *vert_shadow_shader_str;
+ char *vert_background_shader_str;
+ char *vert_volume_shader_str;
+ char *geom_volume_shader_str;
+ char *volume_shader_lib;
+
+ /* LookDev Materials */
+ Material *glossy_mat;
+ Material *diffuse_mat;
+
+ Material *error_mat;
+
+ /* Default Material */
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ bNodeSocketValueFloat *metallic_socket;
+ bNodeSocketValueFloat *roughness_socket;
+ bNodeSocketValueFloat *specular_socket;
+ } surface;
+
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ } world;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
@@ -68,27 +108,42 @@ extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_default_world_frag_glsl[];
-extern char datatoc_lightprobe_geom_glsl[];
-extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_cube_display_frag_glsl[];
extern char datatoc_lightprobe_cube_display_vert_glsl[];
extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_grid_display_frag_glsl[];
extern char datatoc_lightprobe_grid_display_vert_glsl[];
extern char datatoc_lightprobe_grid_fill_frag_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_lightprobe_planar_display_frag_glsl[];
extern char datatoc_lightprobe_planar_display_vert_glsl[];
extern char datatoc_lightprobe_planar_downsample_frag_glsl[];
extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
-extern char datatoc_irradiance_lib_glsl[];
-extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lights_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_ltc_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
-extern char datatoc_cubemap_lib_glsl[];
+extern char datatoc_prepass_frag_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_ssr_lib_glsl[];
+extern char datatoc_update_noise_frag_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
/* Velocity Resolve */
extern char datatoc_effect_velocity_resolve_frag_glsl[];
@@ -150,6 +205,64 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
NULL);
}
+void EEVEE_shaders_material_shaders_init(void)
+{
+ e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_ssr_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ /* Add one for each Closure */
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_volumetric_lib_glsl);
+
+ e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ datatoc_volumetric_lib_glsl,
+ datatoc_volumetric_frag_glsl);
+
+ e_data.vert_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
+
+ e_data.vert_shadow_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
+
+ e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_background_vert_glsl);
+
+ e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_vert_glsl);
+
+ e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_geom_glsl);
+}
+
GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
{
return e_data.probe_filter_glossy_sh;
@@ -292,6 +405,26 @@ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void)
return e_data.velocity_resolve_sh;
}
+GPUShader *EEVEE_shaders_default_background_sh_get(void)
+{
+ if (e_data.default_background == NULL) {
+ e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ }
+ return e_data.default_background;
+}
+
+GPUShader *EEVEE_shaders_update_noise_sh_get(void)
+{
+ if (e_data.update_noise_sh == NULL) {
+ e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ }
+ return e_data.update_noise_sh;
+}
+
GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
{
GPUShader **sh;
@@ -316,8 +449,330 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
return *sh;
}
+Material *EEVEE_material_default_diffuse_get(void)
+{
+ if (!e_data.diffuse_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.diffuse_mat = ma;
+ }
+ return e_data.diffuse_mat;
+}
+
+Material *EEVEE_material_default_glossy_get(void)
+{
+ if (!e_data.glossy_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
+ bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness");
+ ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.glossy_mat = ma;
+ }
+ return e_data.glossy_mat;
+}
+
+Material *EEVEE_material_default_error_get(void)
+{
+ if (!e_data.error_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ /* Use emission and output material to be compatible with both World and Material. */
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "Emission"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.error_mat = ma;
+ }
+ return e_data.error_mat;
+}
+
+/* Configure a default nodetree with the given material. */
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.surface.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+ bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bsdf, bsdf_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value;
+ e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value;
+ e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value;
+ e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value;
+ e_data.surface.ntree = ntree;
+ }
+ /* Update */
+ copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b);
+ e_data.surface.metallic_socket->value = ma->metallic;
+ e_data.surface.roughness_socket->value = ma->roughness;
+ e_data.surface.specular_socket->value = ma->spec;
+
+ return e_data.surface.ntree;
+}
+
+/* Configure a default nodetree with the given world. */
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.world.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD);
+ bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bg, bg_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value;
+ e_data.world.ntree = ntree;
+ }
+
+ copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb);
+
+ return e_data.world.ntree;
+}
+
+static char *eevee_get_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, SHADER_DEFINES);
+
+ if ((options & VAR_WORLD_BACKGROUND) != 0) {
+ BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n");
+ }
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
+ }
+ if ((options & VAR_MAT_MESH) != 0) {
+ BLI_dynstr_append(ds, "#define MESH_SHADER\n");
+ }
+ if ((options & VAR_MAT_DEPTH) != 0) {
+ BLI_dynstr_append(ds, "#define DEPTH_SHADER\n");
+ }
+ if ((options & VAR_MAT_HAIR) != 0) {
+ BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
+ }
+ if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) {
+ BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
+ }
+ if ((options & VAR_MAT_HASH) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
+ }
+ if ((options & VAR_MAT_BLEND) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
+ }
+ if ((options & VAR_MAT_REFRACT) != 0) {
+ BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
+ }
+ if ((options & VAR_MAT_LOOKDEV) != 0) {
+ BLI_dynstr_append(ds, "#define LOOKDEV\n");
+ }
+ if ((options & VAR_MAT_HOLDOUT) != 0) {
+ BLI_dynstr_append(ds, "#define HOLDOUT\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+static char *eevee_get_vert(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.vert_volume_shader_str);
+ }
+ else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
+ str = BLI_strdup(e_data.vert_background_shader_str);
+ }
+ else {
+ str = BLI_strdup(e_data.vert_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_geom(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.geom_volume_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_frag(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.volume_shader_lib);
+ }
+ else if ((options & VAR_MAT_DEPTH) != 0) {
+ str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
+ }
+ else {
+ str = BLI_strdup(e_data.frag_shader_lib);
+ }
+
+ return str;
+}
+
+static struct GPUMaterial *eevee_material_get_ex(
+ struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
+{
+ BLI_assert(ma || wo);
+ const bool is_volume = (options & VAR_MAT_VOLUME) != 0;
+ const bool is_default = (options & VAR_DEFAULT) != 0;
+ const void *engine = &DRW_engine_viewport_eevee_type;
+
+ GPUMaterial *mat = NULL;
+
+ if (ma) {
+ mat = DRW_shader_find_from_material(ma, engine, options, deferred);
+ }
+ else {
+ mat = DRW_shader_find_from_world(wo, engine, options, deferred);
+ }
+
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+ char *vert = eevee_get_vert(options);
+ char *geom = eevee_get_geom(options);
+ char *frag = eevee_get_frag(options);
+
+ if (ma) {
+ bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma);
+ mat = DRW_shader_create_from_material(
+ scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+ else {
+ bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo);
+ mat = DRW_shader_create_from_world(
+ scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+
+ MEM_SAFE_FREE(defines);
+ MEM_SAFE_FREE(vert);
+ MEM_SAFE_FREE(geom);
+ MEM_SAFE_FREE(frag);
+
+ return mat;
+}
+
+/* Note: Compilation is not deferred. */
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options)
+{
+ Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() :
+ BKE_material_default_surface();
+ BLI_assert(def_ma->use_nodes && def_ma->nodetree);
+
+ return eevee_material_get_ex(scene, def_ma, NULL, options, false);
+}
+
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options)
+{
+ if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) {
+ options |= VAR_DEFAULT;
+ }
+
+ /* Meh, implicit option. World probe cannot be deferred because they need
+ * to be rendered immediatly. */
+ const bool deferred = (options & VAR_WORLD_PROBE) == 0;
+
+ GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred);
+
+ int status = GPU_material_status(mat);
+ switch (status) {
+ case GPU_MAT_SUCCESS:
+ break;
+ case GPU_MAT_QUEUED:
+ vedata->stl->g_data->queued_shaders_count++;
+ mat = EEVEE_material_default_get(scene, ma, options);
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ ma = EEVEE_material_default_error_get();
+ mat = eevee_material_get_ex(scene, ma, NULL, options, false);
+ break;
+ }
+ /* Returned material should be ready to be drawn. */
+ BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS);
+ return mat;
+}
+
void EEVEE_shaders_free(void)
{
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
+ MEM_SAFE_FREE(e_data.vert_shader_str);
+ MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
+ MEM_SAFE_FREE(e_data.vert_background_shader_str);
+ MEM_SAFE_FREE(e_data.vert_volume_shader_str);
+ MEM_SAFE_FREE(e_data.geom_volume_shader_str);
+ MEM_SAFE_FREE(e_data.volume_shader_lib);
+ DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
@@ -332,4 +787,27 @@ void EEVEE_shaders_free(void)
DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
+
+ if (e_data.glossy_mat) {
+ BKE_id_free(NULL, e_data.glossy_mat);
+ e_data.glossy_mat = NULL;
+ }
+ if (e_data.diffuse_mat) {
+ BKE_id_free(NULL, e_data.diffuse_mat);
+ e_data.diffuse_mat = NULL;
+ }
+ if (e_data.error_mat) {
+ BKE_id_free(NULL, e_data.error_mat);
+ e_data.error_mat = NULL;
+ }
+ if (e_data.surface.ntree) {
+ ntreeFreeEmbeddedTree(e_data.surface.ntree);
+ MEM_freeN(e_data.surface.ntree);
+ e_data.surface.ntree = NULL;
+ }
+ if (e_data.world.ntree) {
+ ntreeFreeEmbeddedTree(e_data.world.ntree);
+ MEM_freeN(e_data.world.ntree);
+ e_data.world.ntree = NULL;
+ }
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index fb338d85fde..84c50a22ae6 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -159,47 +159,6 @@ void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-/* Add a shadow caster to the shadowpasses */
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob)
-{
- DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
-}
-
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold)
-{
- /* TODO / PERF : reuse the same shading group for objects with the same material */
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
-
- if (grp == NULL) {
- return;
- }
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-
- if (alpha_threshold != NULL) {
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- }
-
- DRW_shgroup_call(grp, geom, ob);
-}
-
/* Make that object update shadow casting lights inside its influence bounding box. */
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
{
@@ -470,8 +429,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 0726f1822cc..7674148f76a 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -29,7 +29,9 @@
#include "DEG_depsgraph_query.h"
#include "GPU_extensions.h"
+#include "GPU_material.h"
#include "GPU_texture.h"
+
#include "eevee_private.h"
static struct {
@@ -83,6 +85,7 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_surface_count = 0;
common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
@@ -221,70 +224,77 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile)
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat)
{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-
- grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-}
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
+ gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- GPUTexture *sss_tex_profile)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
- GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
+ if (!sss_profile) {
+ BLI_assert(0 && "SSS pass requested but no SSS data was found");
+ return;
+ }
+
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (effects->sss_surface_count >= 254) {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ return;
+ }
+
+ int sss_id = ++(effects->sss_surface_count);
+ /* Make main pass output stencil mask. */
+ DRW_shgroup_stencil_mask(shgrp, sss_id);
+
+ {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
+ if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -310,8 +320,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->sss_pass);
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_sss_ps);
/* Restore */
GPU_framebuffer_ensure_config(&fbl->main_fb,
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index b70d872c4af..d57048f2c4e 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -292,8 +292,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
// DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 55e7b0eb0e3..90860e94270 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -355,7 +355,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct World *wo = scene->world;
if (wo != NULL && wo->use_nodes && wo->nodetree &&
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME);
if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
@@ -369,8 +369,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
@@ -388,8 +387,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
}
@@ -590,12 +588,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
return;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH;
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
eGPUMaterialStatus status = GPU_material_status(mat);
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
- }
/* If shader failed to compile or is currently compiling. */
if (status != GPU_MAT_SUCCESS) {
return;
@@ -609,8 +605,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
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, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -661,8 +656,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -671,8 +665,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(
grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]);
@@ -683,8 +676,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@@ -916,8 +908,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
else {
/* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 8662c0ecb6a..57b16418696 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -6,13 +6,9 @@
#if defined(MESH_SHADER)
# if !defined(USE_ALPHA_HASH)
-# if !defined(USE_ALPHA_CLIP)
-# if !defined(SHADOW_SHADER)
-# if !defined(USE_MULTIPLY)
-# if !defined(USE_ALPHA_BLEND)
-# define ENABLE_DEFERED_AO
-# endif
-# endif
+# if !defined(DEPTH_SHADER)
+# if !defined(USE_ALPHA_BLEND)
+# define ENABLE_DEFERED_AO
# endif
# endif
# endif
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 c3518198805..402d306df45 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -928,7 +928,7 @@ Closure closure_emission(vec3 rgb)
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
-# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER)
+# if defined(MESH_SHADER) && !defined(DEPTH_SHADER)
/* clang-format on */
# ifndef USE_ALPHA_BLEND
layout(location = 0) out vec4 outRadiance;
@@ -1001,6 +1001,10 @@ void main()
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
+# ifdef LOOKDEV
+ gl_FragDepth = 0.0;
+# endif
+
# ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
@@ -1011,6 +1015,6 @@ void main()
# endif
}
-# endif /* MESH_SHADER && !SHADOW_SHADER */
+# endif /* MESH_SHADER */
#endif /* VOLUMETRICS */
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 8c2619650b9..bc7879763c3 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -177,7 +177,7 @@ void CLOSURE_NAME(vec3 N
out_refr = vec3(0.0);
#endif
-#if defined(SHADOW_SHADER) || defined(WORLD_BACKGROUND)
+#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
return;
#else
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index cf20b3ff5b9..1b94fc2bee1 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -4,11 +4,12 @@ in vec3 pos;
in vec3 nor;
#endif
+#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
-
out vec3 worldNormal;
out vec3 viewNormal;
+#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
@@ -41,22 +42,28 @@ void main()
hairThickness,
hairThickTime);
worldNormal = cross(hairTangent, binor);
- worldPosition = pos;
+ vec3 world_pos = pos;
#else
- worldPosition = point_object_to_world(pos);
- worldNormal = normalize(normal_object_to_world(nor));
+ vec3 world_pos = point_object_to_world(pos);
#endif
- /* No need to normalize since this is just a rotation. */
- viewNormal = normal_world_to_view(worldNormal);
+ gl_Position = point_world_to_ndc(world_pos);
+ /* Used for planar reflections */
+ gl_ClipDistance[0] = dot(vec4(world_pos, 1.0), clipPlanes[0]);
+
+#ifdef MESH_SHADER
+ worldPosition = world_pos;
viewPosition = point_world_to_view(worldPosition);
- gl_Position = point_world_to_ndc(worldPosition);
- /* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]);
+# ifndef HAIR_SHADER
+ worldNormal = normalize(normal_object_to_world(nor));
+# endif
-#ifdef USE_ATTR
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
+# ifdef USE_ATTR
pass_attr(pos);
+# endif
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index b49dbfceba2..9acd8f998f6 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -45,26 +45,22 @@ float hashed_alpha_threshold(vec3 co)
/* Find our final, uniformly distributed alpha threshold. */
float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z;
+ /* Jitter the threshold for TAA accumulation. */
+ threshold = fract(threshold + alphaHashOffset);
+
/* Avoids threshold == 0. */
threshold = clamp(threshold, 1.0e-6, 1.0);
- /* Jitter the threshold for TAA accumulation. */
- return fract(threshold + alphaHashOffset);
+ return threshold;
}
#endif
-#ifdef USE_ALPHA_CLIP
-uniform float alphaThreshold;
-#endif
+#define NODETREE_EXEC
void main()
{
- /* For now do nothing.
- * In the future, output object motion blur. */
-
-#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP)
-# define NODETREE_EXEC
+#if defined(USE_ALPHA_HASH)
Closure cl = nodetree_exec();
@@ -75,11 +71,6 @@ void main()
if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
-# elif defined(USE_ALPHA_CLIP)
- /* Alpha clip */
- if (opacity <= alphaThreshold) {
- discard;
- }
# endif
#endif
}