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:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt9
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h20
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c84
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders_extra.cc173
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c1
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl35
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl15
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl325
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl113
-rw-r--r--source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl252
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_empty.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl35
-rw-r--r--source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl21
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl92
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_frag.glsl141
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_lib.glsl166
-rw-r--r--source/blender/draw/engines/eevee/shaders/surface_vert.glsl108
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl111
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl6
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl28
-rw-r--r--source/blender/draw/engines/eevee/shaders/world_vert.glsl24
-rw-r--r--source/blender/draw/intern/DRW_render.h54
-rw-r--r--source/blender/draw/intern/draw_hair.c2
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c190
-rw-r--r--source/blender/draw/intern/draw_shader_shared.h21
-rw-r--r--source/blender/draw/intern/shaders/common_attribute_lib.glsl21
-rw-r--r--source/blender/draw/intern/shaders/common_math_lib.glsl6
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl54
39 files changed, 1633 insertions, 543 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index aed527639c5..6d3c203b076 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -16,6 +16,7 @@ set(INC
../editors/space_view3d
../functions
../gpu
+ ../gpu/intern
../imbuf
../makesdna
../makesrna
@@ -123,6 +124,7 @@ set(SRC
engines/eevee/eevee_sampling.c
engines/eevee/eevee_screen_raytrace.c
engines/eevee/eevee_shaders.c
+ engines/eevee/eevee_shaders_extra.cc
engines/eevee/eevee_shadows.c
engines/eevee/eevee_shadows_cascade.c
engines/eevee/eevee_shadows_cube.c
@@ -266,9 +268,13 @@ set(GLSL_SRC
engines/eevee/shaders/closure_eval_lib.glsl
engines/eevee/shaders/closure_eval_diffuse_lib.glsl
engines/eevee/shaders/closure_eval_glossy_lib.glsl
+ engines/eevee/shaders/closure_eval_surface_lib.glsl
engines/eevee/shaders/closure_eval_refraction_lib.glsl
+ engines/eevee/shaders/closure_eval_volume_lib.glsl
engines/eevee/shaders/closure_eval_translucent_lib.glsl
engines/eevee/shaders/closure_type_lib.glsl
+ engines/eevee/shaders/eevee_empty.glsl
+ engines/eevee/shaders/eevee_empty_volume.glsl
engines/eevee/shaders/effect_bloom_frag.glsl
engines/eevee/shaders/effect_dof_bokeh_frag.glsl
engines/eevee/shaders/effect_dof_dilate_tiles_frag.glsl
@@ -302,7 +308,6 @@ set(GLSL_SRC
engines/eevee/shaders/object_motion_frag.glsl
engines/eevee/shaders/object_motion_vert.glsl
engines/eevee/shaders/prepass_frag.glsl
- engines/eevee/shaders/prepass_vert.glsl
engines/eevee/shaders/shadow_accum_frag.glsl
engines/eevee/shaders/shadow_frag.glsl
engines/eevee/shaders/shadow_vert.glsl
@@ -333,6 +338,7 @@ set(GLSL_SRC
engines/eevee/shaders/volumetric_resolve_frag.glsl
engines/eevee/shaders/volumetric_scatter_frag.glsl
engines/eevee/shaders/volumetric_integration_frag.glsl
+ engines/eevee/shaders/world_vert.glsl
engines/workbench/shaders/workbench_cavity_lib.glsl
engines/workbench/shaders/workbench_common_lib.glsl
@@ -364,6 +370,7 @@ set(GLSL_SRC
engines/workbench/workbench_shader_shared.h
+ intern/shaders/common_attribute_lib.glsl
intern/shaders/common_colormanagement_lib.glsl
intern/shaders/common_globals_lib.glsl
intern/shaders/common_gpencil_lib.glsl
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index c3f9a606dd0..c46e5dd75d6 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -73,7 +73,12 @@ void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
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);
+ bool use_ao = GPU_material_flag_get(gpumat, GPU_MATFLAG_AO);
+#ifdef __APPLE__
+ /* NOTE: Some implementation do not optimize out the unused samplers. */
+ use_diffuse = use_glossy = use_refract = use_ao = true;
+#endif
LightCache *lcache = vedata->stl->g_data->light_cache;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_PrivateData *pd = vedata->stl->g_data;
@@ -91,6 +96,8 @@ void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
if (use_diffuse || use_glossy || use_refract) {
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
+ }
+ if (use_diffuse || use_glossy || use_refract || use_ao) {
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
}
if ((use_diffuse || use_glossy) && !use_ssrefraction) {
@@ -374,6 +381,13 @@ void EEVEE_materials_cache_init(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_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &stl->g_data->light_cache->cube_tx.tex);
+ DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &stl->g_data->light_cache->grid_tx.tex);
+ DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &vedata->txl->maxzbuffer);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
@@ -578,7 +592,7 @@ static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
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);
+ const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SUBSURFACE);
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;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 722c03d7536..effae313acf 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -462,7 +462,7 @@ typedef struct EEVEE_RenderPassData {
int renderPassSSSColor;
int renderPassEnvironment;
int renderPassAOV;
- int renderPassAOVActive;
+ uint renderPassAOVActive;
int _pad[3];
} EEVEE_RenderPassData;
@@ -1050,7 +1050,7 @@ typedef struct EEVEE_PrivateData {
/* Renderpasses */
/* Bitmask containing the active render_passes */
eViewLayerEEVEEPassType render_passes;
- int aov_hash;
+ uint aov_hash;
int num_aovs_used;
struct CryptomatteSession *cryptomatte_session;
bool cryptomatte_accurate_mode;
@@ -1291,6 +1291,20 @@ struct GPUMaterial *EEVEE_material_get(
EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
void EEVEE_shaders_free(void);
+void eevee_shader_extra_init(void);
+void eevee_shader_extra_exit(void);
+void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
+ GPUCodegenOutput *codegen,
+ char *frag,
+ char *vert,
+ char *geom,
+ char *defines);
+GPUShader *eevee_shaders_sh_create_helper(const char *name,
+ const char *vert_name,
+ const char *frag_name,
+ const char *defines,
+ bool use_layered_rendering);
+
/* eevee_lightprobes.c */
bool EEVEE_lightprobes_obj_visibility_cb(bool vis_in, void *user_data);
@@ -1508,7 +1522,7 @@ bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata);
* Calculate the hash for an AOV. The least significant bit is used to store the AOV
* type the rest of the bits are used for the name hash.
*/
-int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov);
+uint EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov);
/* eevee_temporal_sampling.c */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 3814cf44fd6..237c830d547 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -60,9 +60,9 @@ bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata)
return (g_data->render_passes & ~EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) == 0;
}
-int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov)
+uint EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov)
{
- int hash = BLI_hash_string(aov->name) << 1;
+ uint hash = BLI_hash_string(aov->name) << 1u;
SET_FLAG_FROM_TEST(hash, aov->type == AOV_TYPE_COLOR, EEVEE_AOV_HASH_COLOR_TYPE_MASK);
return hash;
}
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index ae5e6e94f74..4e4a2a9eb8e 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -170,6 +170,7 @@ extern char datatoc_common_math_lib_glsl[];
extern char datatoc_common_math_geom_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_common_obinfos_lib_glsl[];
+extern char datatoc_gpu_shader_codegen_lib_glsl[];
extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
@@ -178,6 +179,7 @@ extern char datatoc_bsdf_lut_frag_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_closure_type_lib_glsl[];
+extern char datatoc_closure_eval_volume_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_utiltex_lib_glsl[];
extern char datatoc_cryptomatte_frag_glsl[];
@@ -230,6 +232,7 @@ extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
extern char datatoc_lightprobe_vert_glsl[];
extern char datatoc_lights_lib_glsl[];
extern char datatoc_closure_eval_lib_glsl[];
+extern char datatoc_closure_eval_surface_lib_glsl[];
extern char datatoc_closure_eval_diffuse_lib_glsl[];
extern char datatoc_closure_eval_glossy_lib_glsl[];
extern char datatoc_closure_eval_refraction_lib_glsl[];
@@ -239,7 +242,6 @@ extern char datatoc_object_motion_frag_glsl[];
extern char datatoc_object_motion_vert_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_prepass_frag_glsl[];
-extern char datatoc_prepass_vert_glsl[];
extern char datatoc_random_lib_glsl[];
extern char datatoc_raytrace_lib_glsl[];
extern char datatoc_renderpass_lib_glsl[];
@@ -261,6 +263,7 @@ extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_volumetric_resolve_frag_glsl[];
extern char datatoc_volumetric_scatter_frag_glsl[];
extern char datatoc_volumetric_vert_glsl[];
+extern char datatoc_world_vert_glsl[];
/* *********** FUNCTIONS *********** */
@@ -275,6 +278,7 @@ static void eevee_shader_library_ensure(void)
DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib);
DRW_SHADER_LIB_ADD(e_data.lib, common_uniforms_lib);
DRW_SHADER_LIB_ADD(e_data.lib, gpu_shader_common_obinfos_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, gpu_shader_codegen_lib);
DRW_SHADER_LIB_ADD(e_data.lib, random_lib);
DRW_SHADER_LIB_ADD(e_data.lib, renderpass_lib);
DRW_SHADER_LIB_ADD(e_data.lib, bsdf_common_lib);
@@ -299,6 +303,8 @@ static void eevee_shader_library_ensure(void)
DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_glossy_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_translucent_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_refraction_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_surface_lib);
+ DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_volume_lib);
e_data.surface_lit_frag = DRW_shader_library_create_shader_string(e_data.lib,
datatoc_surface_frag_glsl);
@@ -313,6 +319,7 @@ static void eevee_shader_library_ensure(void)
void EEVEE_shaders_material_shaders_init(void)
{
+ eevee_shader_extra_init();
eevee_shader_library_ensure();
}
@@ -828,6 +835,7 @@ struct GPUShader *EEVEE_shaders_volumes_clear_sh_get()
datatoc_volumetric_frag_glsl,
e_data.lib,
SHADER_DEFINES
+ "#define STANDALONE\n"
"#define VOLUMETRICS\n"
"#define CLEAR\n");
}
@@ -842,6 +850,7 @@ struct GPUShader *EEVEE_shaders_volumes_scatter_sh_get()
datatoc_volumetric_scatter_frag_glsl,
e_data.lib,
SHADER_DEFINES
+ "#define STANDALONE\n"
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
}
@@ -857,6 +866,7 @@ struct GPUShader *EEVEE_shaders_volumes_scatter_with_lights_sh_get()
datatoc_volumetric_scatter_frag_glsl,
e_data.lib,
SHADER_DEFINES
+ "#define STANDALONE\n"
"#define VOLUMETRICS\n"
"#define VOLUME_LIGHTING\n"
"#define VOLUME_SHADOW\n");
@@ -872,7 +882,9 @@ struct GPUShader *EEVEE_shaders_volumes_integration_sh_get()
datatoc_volumetric_geom_glsl,
datatoc_volumetric_integration_frag_glsl,
e_data.lib,
- USE_VOLUME_OPTI ? "#define USE_VOLUME_OPTI\n" SHADER_DEFINES : SHADER_DEFINES);
+ USE_VOLUME_OPTI ? "#define USE_VOLUME_OPTI\n"
+ "#define STANDALONE\n" SHADER_DEFINES :
+ "#define STANDALONE\n" SHADER_DEFINES);
}
return e_data.volumetric_integration_sh;
}
@@ -1232,7 +1244,7 @@ Material *EEVEE_material_default_glossy_get(void)
Material *EEVEE_material_default_error_get(void)
{
if (!e_data.error_mat) {
- Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default error");
bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
ma->nodetree = ntree;
@@ -1375,7 +1387,7 @@ static char *eevee_get_vert(int options)
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_vert_glsl);
}
else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
- str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_background_vert_glsl);
+ str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_world_vert_glsl);
}
else {
str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_surface_vert_glsl);
@@ -1412,68 +1424,43 @@ static char *eevee_get_frag(int options)
return str;
}
-static void eevee_material_post_eval(GPUMaterial *mat,
- int options,
- const char **UNUSED(vert_code),
- const char **geom_code,
- const char **UNUSED(frag_lib),
- const char **UNUSED(defines))
+static void eevee_material_post_eval(void *UNUSED(thunk),
+ GPUMaterial *mat,
+ GPUCodegenOutput *codegen)
{
- const bool is_hair = (options & VAR_MAT_HAIR) != 0;
- const bool is_mesh = (options & VAR_MAT_MESH) != 0;
+ uint64_t options = GPU_material_uuid_get(mat);
- /* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used.
- * NOTE: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */
- if (!is_hair && is_mesh && GPU_material_flag_get(mat, GPU_MATFLAG_BARYCENTRIC) &&
- *geom_code == NULL) {
- *geom_code = e_data.surface_geom_barycentric;
- }
+ char *vert = eevee_get_vert(options);
+ char *geom = eevee_get_geom(options);
+ char *frag = eevee_get_frag(options);
+ char *defines = eevee_get_defines(options);
+
+ eevee_shader_material_create_info_amend(mat, codegen, frag, vert, geom, defines);
+
+ MEM_SAFE_FREE(defines);
+ MEM_SAFE_FREE(vert);
+ MEM_SAFE_FREE(geom);
+ MEM_SAFE_FREE(frag);
}
static struct GPUMaterial *eevee_material_get_ex(
- struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
+ struct Scene *UNUSED(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;
+ GPUCodegenCallbackFn cbfn = &eevee_material_post_eval;
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) {
- GPUMaterialEvalCallbackFn cbfn = &eevee_material_post_eval;
-
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, cbfn);
+ mat = DRW_shader_from_material(ma, ntree, options, is_volume, deferred, cbfn, NULL);
}
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, NULL);
+ mat = DRW_shader_from_world(wo, ntree, options, is_volume, deferred, cbfn, NULL);
}
-
- MEM_SAFE_FREE(defines);
- MEM_SAFE_FREE(vert);
- MEM_SAFE_FREE(geom);
- MEM_SAFE_FREE(frag);
-
return mat;
}
@@ -1520,6 +1507,7 @@ struct GPUMaterial *EEVEE_material_get(
void EEVEE_shaders_free(void)
{
+ eevee_shader_extra_exit();
MEM_SAFE_FREE(e_data.surface_prepass_frag);
MEM_SAFE_FREE(e_data.surface_lit_frag);
MEM_SAFE_FREE(e_data.surface_geom_barycentric);
diff --git a/source/blender/draw/engines/eevee/eevee_shaders_extra.cc b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc
new file mode 100644
index 00000000000..1d3e07217b5
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_shaders_extra.cc
@@ -0,0 +1,173 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+/** \file
+ * \ingroup EEVEE
+ *
+ * This file is only there to handle ShaderCreateInfos.
+ */
+
+#include "GPU_shader.h"
+
+#include "BLI_string_ref.hh"
+
+#include "gpu_shader_create_info.hh"
+
+#include "eevee_private.h"
+
+using blender::gpu::shader::StageInterfaceInfo;
+
+static StageInterfaceInfo *stage_interface = nullptr;
+
+void eevee_shader_extra_init()
+{
+ if (stage_interface != nullptr) {
+ return;
+ }
+
+ using namespace blender::gpu::shader;
+ stage_interface = new StageInterfaceInfo("ShaderStageInterface", "");
+ stage_interface->smooth(Type::VEC3, "worldPosition");
+ stage_interface->smooth(Type::VEC3, "viewPosition");
+ stage_interface->smooth(Type::VEC3, "worldNormal");
+ stage_interface->smooth(Type::VEC3, "viewNormal");
+ stage_interface->flat(Type::INT, "resourceIDFrag");
+}
+
+void eevee_shader_extra_exit()
+{
+ delete stage_interface;
+}
+
+void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
+ GPUCodegenOutput *codegen_,
+ char *frag,
+ char *vert,
+ char *geom,
+ char *defines)
+{
+ using namespace blender::gpu::shader;
+
+ uint64_t options = GPU_material_uuid_get(gpumat);
+ const bool is_background = (options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0;
+ const bool is_volume = (options & (VAR_MAT_VOLUME)) != 0;
+ const bool is_hair = (options & (VAR_MAT_HAIR)) != 0;
+ const bool is_mesh = (options & (VAR_MAT_MESH)) != 0;
+ const bool is_point_cloud = (options & (VAR_MAT_POINTCLOUD)) != 0;
+
+ GPUCodegenOutput &codegen = *codegen_;
+ ShaderCreateInfo &info = *reinterpret_cast<ShaderCreateInfo *>(codegen.create_info);
+
+ info.legacy_resource_location(true);
+ info.auto_resource_location(true);
+
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_SUBSURFACE)) {
+ info.define("USE_SSS");
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_SHADER_TO_RGBA)) {
+ info.define("USE_SHADER_TO_RGBA");
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_BARYCENTRIC) && !is_volume && !is_hair &&
+ !is_point_cloud && !is_background) {
+ info.define("USE_BARYCENTRICS");
+ info.builtins(BuiltinBits::BARYCENTRIC_COORD);
+ }
+ if (GPU_material_flag_get(gpumat, GPU_MATFLAG_BARYCENTRIC) && is_hair) {
+ info.define("USE_BARYCENTRICS");
+ }
+
+ std::stringstream attr_load;
+
+ const bool do_fragment_attrib_load = is_background || is_volume;
+
+ if (is_hair && !info.vertex_out_interfaces_.is_empty()) {
+ /** Hair attributes comme from sampler buffer. Transfer attributes to sampler. */
+ for (auto &input : info.vertex_inputs_) {
+ info.sampler(0, ImageType::FLOAT_BUFFER, input.name, Frequency::BATCH);
+ }
+ info.vertex_inputs_.clear();
+ }
+ else if (do_fragment_attrib_load && !info.vertex_out_interfaces_.is_empty()) {
+ /* Codegen outputs only one interface. */
+ const StageInterfaceInfo &iface = *info.vertex_out_interfaces_.first();
+ /* Globals the attrib_load() can write to when it is in the fragment shader. */
+ attr_load << "struct " << iface.name << " {\n";
+ for (auto &inout : iface.inouts) {
+ attr_load << " " << inout.type << " " << inout.name << ";\n";
+ }
+ attr_load << "};\n";
+ attr_load << iface.name << " " << iface.instance_name << ";\n";
+ /* Global vars just to make code valid. Only Orco is supported. */
+ for (const ShaderCreateInfo::VertIn &in : info.vertex_inputs_) {
+ attr_load << in.type << " " << in.name << ";\n";
+ }
+ info.vertex_out_interfaces_.clear();
+ }
+
+ if (!is_volume) {
+ info.define("EEVEE_GENERATED_INTERFACE");
+ info.vertex_out(*stage_interface);
+ }
+
+ attr_load << "void attrib_load()\n";
+ attr_load << "{\n";
+ attr_load << ((codegen.attr_load) ? codegen.attr_load : "");
+ attr_load << "}\n\n";
+
+ std::stringstream vert_gen, frag_gen, geom_gen;
+
+ if (do_fragment_attrib_load) {
+ frag_gen << attr_load.str();
+ }
+ else {
+ vert_gen << attr_load.str();
+ }
+
+ {
+ vert_gen << vert;
+ info.vertex_source_generated = vert_gen.str();
+ /* Everything is in generated source. */
+ info.vertex_source(is_volume ? "eevee_empty_volume.glsl" : "eevee_empty.glsl");
+ }
+
+ {
+ frag_gen << frag;
+ if (codegen.material_functions) {
+ frag_gen << codegen.material_functions;
+ }
+ frag_gen << "Closure nodetree_exec()\n";
+ frag_gen << "{\n";
+ if (GPU_material_is_volume_shader(gpumat)) {
+ frag_gen << ((codegen.volume) ? codegen.volume : "return CLOSURE_DEFAULT;\n");
+ }
+ else {
+ frag_gen << ((codegen.surface) ? codegen.surface : "return CLOSURE_DEFAULT;\n");
+ }
+ frag_gen << "}\n\n";
+
+ if (codegen.displacement && (is_hair || is_mesh)) {
+ info.define("EEVEE_DISPLACEMENT_BUMP");
+
+ frag_gen << "vec3 displacement_exec()\n";
+ frag_gen << "{\n";
+ frag_gen << codegen.displacement;
+ frag_gen << "}\n\n";
+ }
+
+ info.fragment_source_generated = frag_gen.str();
+ /* Everything is in generated source. */
+ info.fragment_source(is_volume ? "eevee_empty_volume.glsl" : "eevee_empty.glsl");
+ }
+
+ if (geom) {
+ geom_gen << geom;
+ info.geometry_source_generated = geom_gen.str();
+ info.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 3);
+ /* Everything is in generated source. */
+ info.geometry_source("eevee_empty.glsl");
+ }
+
+ if (defines) {
+ info.typedef_source_generated += blender::StringRefNull(defines);
+ }
+}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 7d210f15d8b..6a0c9fb36df 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -604,6 +604,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
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 4da30dd74ee..d8adf302e37 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -26,6 +26,10 @@
# endif
#endif
+#ifndef GPU_FRAGMENT_SHADER
+# define gl_FragCoord vec4(0.0)
+#endif
+
uniform sampler2D horizonBuffer;
/* aoSettings flags */
@@ -424,3 +428,34 @@ OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
return data;
}
+
+#ifndef GPU_FRAGMENT_SHADER
+# undef gl_FragCoord
+#endif
+
+float ambient_occlusion_eval(vec3 normal,
+ float max_distance,
+ const float inverted,
+ const float sample_count)
+{
+ /* Avoid multiline define causing compiler issues. */
+ /* clang-format off */
+#if defined(GPU_FRAGMENT_SHADER) && (defined(MESH_SHADER) || defined(HAIR_SHADER)) && !defined(DEPTH_SHADER) && !defined(VOLUMETRICS)
+ /* clang-format on */
+ vec3 bent_normal;
+ vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
+ OcclusionData data = occlusion_search(
+ viewPosition, maxzBuffer, max_distance, inverted, sample_count);
+
+ vec3 V = cameraVec(worldPosition);
+ vec3 N = normalize(normal);
+ vec3 Ng = safe_normalize(cross(dFdx(worldPosition), dFdy(worldPosition)));
+
+ float unused_error, visibility;
+ vec3 unused;
+ occlusion_eval(data, V, N, Ng, inverted, visibility, unused_error, unused);
+ return visibility;
+#else
+ return 1.0;
+#endif
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
index 5cd82d298d5..574b24b3650 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_diffuse_lib.glsl
@@ -1,6 +1,8 @@
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputDiffuse {
vec3 N; /** Shading normal. */
@@ -88,6 +90,7 @@ void closure_Diffuse_eval_end(ClosureInputDiffuse cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputDiffuse cl_out)
{
+ cl_out.radiance = render_pass_diffuse_mask(cl_out.radiance);
#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
cl_out.radiance = vec3(0.0);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
index 4271ac9105b..0deaf4054d2 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
@@ -4,6 +4,8 @@
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputGlossy {
vec3 N; /** Shading normal. */
@@ -143,6 +145,7 @@ void closure_Glossy_eval_end(ClosureInputGlossy cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputGlossy cl_out)
{
+ cl_out.radiance = render_pass_glossy_mask(cl_out.radiance);
#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
cl_out.radiance = vec3(0.0);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
index a96d8ad3dac..3f07f80571a 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl
@@ -1,8 +1,14 @@
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+// #pragma (gpu_shader_codegen_lib.glsl)
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
+#ifndef GPU_FRAGMENT_SHADER
+# define gl_FragCoord vec4(0.0)
+# define gl_FrontFacing true
+#endif
+
/**
* Extensive use of Macros to be able to change the maximum amount of evaluated closure easily.
* NOTE: GLSL does not support variadic macros.
@@ -240,7 +246,11 @@ ClosureEvalCommon closure_Common_eval_init(ClosureInputCommon cl_in)
cl_eval.N = safe_normalize(gl_FrontFacing ? worldNormal : -worldNormal);
cl_eval.vN = safe_normalize(gl_FrontFacing ? viewNormal : -viewNormal);
cl_eval.vP = viewPosition;
+#ifdef GPU_FRAGMENT_SHADER
cl_eval.Ng = safe_normalize(cross(dFdx(cl_eval.P), dFdy(cl_eval.P)));
+#else
+ cl_eval.Ng = cl_eval.N;
+#endif
cl_eval.vNg = transform_direction(ViewMatrix, cl_eval.Ng);
cl_eval.occlusion_data = occlusion_load(cl_eval.vP, cl_in.occlusion);
@@ -337,3 +347,8 @@ ClosureGridData closure_grid_eval_init(int id, inout ClosureEvalCommon cl_common
}
/** \} */
+
+#ifndef GPU_FRAGMENT_SHADER
+# undef gl_FragCoord
+# undef gl_FrontFacing
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
index 8129988920c..5c6769b185a 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_refraction_lib.glsl
@@ -4,6 +4,8 @@
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
#pragma BLENDER_REQUIRE(ssr_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputRefraction {
vec3 N; /** Shading normal. */
@@ -123,6 +125,7 @@ void closure_Refraction_eval_end(ClosureInputRefraction cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputRefraction cl_out)
{
+ cl_out.radiance = render_pass_glossy_mask(cl_out.radiance);
#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
cl_out.radiance = vec3(0.0);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl
new file mode 100644
index 00000000000..fa94b5ed272
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl
@@ -0,0 +1,325 @@
+
+#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
+
+#ifdef USE_SHADER_TO_RGBA
+bool do_sss = false;
+bool do_ssr = false;
+#else
+bool do_sss = true;
+bool do_ssr = true;
+#endif
+
+vec3 out_sss_radiance;
+vec3 out_sss_color;
+float out_sss_radius;
+
+float out_ssr_roughness;
+vec3 out_ssr_color;
+vec3 out_ssr_N;
+
+bool aov_is_valid = false;
+vec3 out_aov;
+
+bool output_sss(ClosureDiffuse diffuse, ClosureOutputDiffuse diffuse_out)
+{
+ if (diffuse.sss_id == 0u || !do_sss || !sssToggle || outputSssId == 0) {
+ return false;
+ }
+ if (renderPassSSSColor) {
+ return false;
+ }
+ out_sss_radiance = diffuse_out.radiance;
+ out_sss_color = diffuse.color * diffuse.weight;
+ out_sss_radius = avg(diffuse.sss_radius);
+ do_sss = false;
+ return true;
+}
+
+bool output_ssr(ClosureReflection reflection)
+{
+ if (!do_ssr || !ssrToggle || outputSsrId == 0) {
+ return false;
+ }
+ out_ssr_roughness = reflection.roughness;
+ out_ssr_color = reflection.color * reflection.weight;
+ out_ssr_N = reflection.N;
+ do_ssr = false;
+ return true;
+}
+
+void output_aov(vec4 color, float value, uint hash)
+{
+ /* Keep in sync with `render_pass_aov_hash` and `EEVEE_renderpasses_aov_hash`. */
+ hash <<= 1u;
+
+ if (renderPassAOV && !aov_is_valid && hash == render_pass_aov_hash()) {
+ aov_is_valid = true;
+ if (render_pass_aov_is_color()) {
+ out_aov = color.rgb;
+ }
+ else {
+ out_aov = vec3(value);
+ }
+ }
+}
+
+/* Single BSDFs. */
+CLOSURE_EVAL_FUNCTION_DECLARE_1(DiffuseBSDF, Diffuse)
+Closure closure_eval(ClosureDiffuse diffuse)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Diffuse);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+
+ CLOSURE_EVAL_FUNCTION_1(DiffuseBSDF, Diffuse);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(TranslucentBSDF, Translucent)
+Closure closure_eval(ClosureTranslucent translucent)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Translucent);
+
+ in_Translucent_0.N = translucent.N;
+
+ CLOSURE_EVAL_FUNCTION_1(TranslucentBSDF, Translucent);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Translucent_0.radiance * translucent.color * translucent.weight;
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy)
+Closure closure_eval(ClosureReflection reflection)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Glossy);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+
+ CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction)
+Closure closure_eval(ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_1(Refraction);
+
+ in_Refraction_0.N = refraction.N;
+ in_Refraction_0.roughness = refraction.roughness;
+ in_Refraction_0.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_1(RefractionBSDF, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Refraction_0.radiance * refraction.color * refraction.weight;
+ return closure;
+}
+
+Closure closure_eval(ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += render_pass_emission_mask(emission.emission) * emission.weight;
+ return closure;
+}
+
+Closure closure_eval(ClosureTransparency transparency)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.transmittance += transparency.transmittance * transparency.weight;
+ closure.holdout += transparency.holdout * transparency.weight;
+ return closure;
+}
+
+/* Glass BSDF. */
+CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction)
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+ in_Refraction_1.N = refraction.N;
+ in_Refraction_1.roughness = refraction.roughness;
+ in_Refraction_1.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_2(GlassBSDF, Glossy, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Refraction_1.radiance * refraction.color * refraction.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Dielectric BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy)
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Diffuse, Glossy);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+
+ CLOSURE_EVAL_FUNCTION_2(DielectricBSDF, Diffuse, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Specular BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_3(SpecularBSDF, Diffuse, Glossy, Glossy)
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+ in_Glossy_2.N = clearcoat.N;
+ in_Glossy_2.roughness = clearcoat.roughness;
+
+ CLOSURE_EVAL_FUNCTION_3(SpecularBSDF, Diffuse, Glossy, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Principled BSDF */
+CLOSURE_EVAL_FUNCTION_DECLARE_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction)
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
+
+ in_Diffuse_0.N = diffuse.N;
+ in_Diffuse_0.albedo = diffuse.color;
+ in_Glossy_1.N = reflection.N;
+ in_Glossy_1.roughness = reflection.roughness;
+ in_Glossy_2.N = clearcoat.N;
+ in_Glossy_2.roughness = clearcoat.roughness;
+ in_Refraction_3.N = refraction.N;
+ in_Refraction_3.roughness = refraction.roughness;
+ in_Refraction_3.ior = refraction.ior;
+
+ CLOSURE_EVAL_FUNCTION_4(PrincipledBSDF, Diffuse, Glossy, Glossy, Refraction);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Glossy_2.radiance * clearcoat.color * clearcoat.weight;
+ closure.radiance += out_Refraction_3.radiance * refraction.color * refraction.weight;
+ if (!output_sss(diffuse, out_Diffuse_0)) {
+ closure.radiance += out_Diffuse_0.radiance * diffuse.color * diffuse.weight;
+ }
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
+{
+ /* Glue with the old system. */
+ CLOSURE_VARS_DECLARE_2(Glossy, Glossy);
+
+ in_Glossy_0.N = reflection.N;
+ in_Glossy_0.roughness = reflection.roughness;
+ in_Glossy_1.N = clearcoat.N;
+ in_Glossy_1.roughness = clearcoat.roughness;
+
+ CLOSURE_EVAL_FUNCTION_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy);
+
+ Closure closure = CLOSURE_DEFAULT;
+ closure.radiance += out_Glossy_1.radiance * clearcoat.color * clearcoat.weight;
+ if (!output_ssr(reflection)) {
+ closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
+ }
+ return closure;
+}
+
+/* Not supported for surface shaders. */
+Closure closure_eval(ClosureVolumeScatter volume_scatter)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission)
+{
+ return CLOSURE_DEFAULT;
+}
+
+/* Not implemented yet. */
+Closure closure_eval(ClosureHair hair)
+{
+ return CLOSURE_DEFAULT;
+}
+
+vec4 closure_to_rgba(Closure closure)
+{
+ return vec4(closure.radiance, 1.0 - saturate(avg(closure.transmittance)));
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.radiance = cl1.radiance + cl2.radiance;
+ cl.transmittance = cl1.transmittance + cl2.transmittance;
+ cl.holdout = cl1.holdout + cl2.holdout;
+ return cl;
+}
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ /* Weights have already been applied. */
+ return closure_add(cl1, cl2);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
index 706b75cb7f9..89a6f10e634 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_translucent_lib.glsl
@@ -3,6 +3,8 @@
#pragma BLENDER_REQUIRE(lights_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
struct ClosureInputTranslucent {
vec3 N; /** Shading normal. */
@@ -69,6 +71,7 @@ void closure_Translucent_eval_end(ClosureInputTranslucent cl_in,
ClosureEvalCommon cl_common,
inout ClosureOutputTranslucent cl_out)
{
+ cl_out.radiance = render_pass_diffuse_mask(cl_out.radiance);
#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
cl_out.radiance = vec3(0.0);
diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl
new file mode 100644
index 00000000000..e450b8ad3c8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl
@@ -0,0 +1,113 @@
+
+void output_aov(vec4 color, float value, uint hash)
+{
+ /* Unsupported. */
+}
+
+/* Surface BSDFs. */
+Closure closure_eval(ClosureDiffuse diffuse)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureTranslucent translucent)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.emission = emission.emission;
+ return closure;
+}
+Closure closure_eval(ClosureTransparency transparency)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
+{
+ return CLOSURE_DEFAULT;
+}
+Closure closure_eval(ClosureHair hair)
+{
+ return CLOSURE_DEFAULT;
+}
+
+Closure closure_eval(ClosureVolumeScatter volume_scatter)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.scatter = volume_scatter.scattering;
+ closure.anisotropy = volume_scatter.anisotropy;
+ return closure;
+}
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.absorption = volume_absorption.absorption;
+ return closure;
+}
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission)
+{
+ Closure closure = CLOSURE_DEFAULT;
+ closure.absorption = volume_absorption.absorption;
+ closure.scatter = volume_scatter.scattering;
+ closure.anisotropy = volume_scatter.anisotropy;
+ closure.emission = emission.emission;
+ return closure;
+}
+
+vec4 closure_to_rgba(Closure closure)
+{
+ /* Not supported */
+ return vec4(0.0);
+}
+
+Closure closure_mix(Closure cl1, Closure cl2, float fac)
+{
+ Closure cl;
+ cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
+ cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
+ cl.emission = mix(cl1.emission, cl2.emission, fac);
+ cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
+ return cl;
+}
+
+Closure closure_add(Closure cl1, Closure cl2)
+{
+ Closure cl;
+ cl.absorption = cl1.absorption + cl2.absorption;
+ cl.scatter = cl1.scatter + cl2.scatter;
+ cl.emission = cl1.emission + cl2.emission;
+ cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
+ return cl;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
index 9022a9d3130..0096cd1747f 100644
--- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl
@@ -1,6 +1,8 @@
-#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
-#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
+#pragma BLENDER_REQUIRE(gpu_shader_codegen_lib.glsl)
+/* #pragma (common_math_geom_lib.glsl) */
+/* #pragma (common_uniforms_lib.glsl) */
+/* #pragma (renderpass_lib.glsl) */
#ifndef VOLUMETRICS
@@ -20,15 +22,6 @@ struct Closure {
vec3 radiance;
vec3 transmittance;
float holdout;
- vec4 ssr_data;
- vec2 ssr_normal;
- int flag;
-# ifdef USE_SSS
- vec3 sss_irradiance;
- vec3 sss_albedo;
- float sss_radius;
-# endif
-
#endif
/* Metal Default Constructor - Requred for C++ constructor syntax. */
@@ -45,191 +38,76 @@ struct Closure {
}
# else
/* Explicit Closure constructors -- To support GLSL syntax */
- inline Closure(vec3 in_radiance,
- vec3 in_transmittance,
- float in_holdout,
- vec4 in_ssr_data,
- vec2 in_ssr_normal,
- int in_flag
-# ifdef USE_SSS
- ,
- vec3 in_sss_irradiance,
- vec3 in_sss_albedo,
- float in_sss_radius
-# endif /* USE_SSS */
- )
- : radiance(in_radiance),
- transmittance(in_transmittance),
- holdout(in_holdout),
- ssr_data(in_ssr_data),
- ssr_normal(in_ssr_normal),
- flag(in_flag)
-# ifdef USE_SSS
- ,
- sss_irradiance(in_sss_irradiance),
- sss_albedo(in_sss_albedo),
- sss_radius(in_sss_radius)
-# endif /* USE_SSS */
+ inline Closure(vec3 in_radiance, vec3 in_transmittance, float in_holdout)
+ : radiance(in_radiance), transmittance(in_transmittance), holdout(in_holdout)
{
}
-# endif /* VOLUMETRICS */
-#endif /* GPU_METAL */
+# endif /* VOLUMETRICS */
+#endif /* GPU_METAL */
};
#ifndef GPU_METAL
/* Prototype */
-Closure nodetree_exec(void);
+Closure nodetree_exec();
+vec4 closure_to_rgba(Closure);
+void output_aov(vec4 color, float value, uint hash);
+vec3 coordinate_camera(vec3 P);
+vec3 coordinate_screen(vec3 P);
+vec3 coordinate_reflect(vec3 P, vec3 N);
+vec3 coordinate_incoming(vec3 P);
+
+/* Single BSDFs. */
+Closure closure_eval(ClosureDiffuse diffuse);
+Closure closure_eval(ClosureTranslucent translucent);
+Closure closure_eval(ClosureReflection reflection);
+Closure closure_eval(ClosureRefraction refraction);
+Closure closure_eval(ClosureEmission emission);
+Closure closure_eval(ClosureTransparency transparency);
+Closure closure_eval(ClosureVolumeScatter volume_scatter);
+Closure closure_eval(ClosureVolumeAbsorption volume_absorption);
+Closure closure_eval(ClosureHair hair);
+
+/* Glass BSDF. */
+Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction);
+/* Dielectric BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection);
+/* ClearCoat BSDF. */
+Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat);
+/* Volume BSDF. */
+Closure closure_eval(ClosureVolumeScatter volume_scatter,
+ ClosureVolumeAbsorption volume_absorption,
+ ClosureEmission emission);
+/* Specular BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat);
+/* Principled BSDF. */
+Closure closure_eval(ClosureDiffuse diffuse,
+ ClosureReflection reflection,
+ ClosureReflection clearcoat,
+ ClosureRefraction refraction);
+
+Closure closure_add(Closure cl1, Closure cl2);
+Closure closure_mix(Closure cl1, Closure cl2, float fac);
+
+float ambient_occlusion_eval(vec3 normal,
+ float distance,
+ const float inverted,
+ const float sample_count);
+
+/* WORKAROUND: Included later with libs. This is because we are mixing include systems. */
+vec3 safe_normalize(vec3 N);
+float fast_sqrt(float a);
+vec3 cameraVec(vec3 P);
+vec2 btdf_lut(float a, float b, float c);
+vec2 brdf_lut(float a, float b);
+vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c);
+vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c);
+float F_eta(float a, float b);
#endif
-/* clang-format off */
-/* Avoid multi-line defines. */
#ifdef VOLUMETRICS
# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), vec3(0), 0.0)
-#elif !defined(USE_SSS)
-# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0)
#else
-# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0, vec4(0), vec2(0), 0, vec3(0), vec3(0), 0.0)
-#endif
-/* clang-format on */
-
-#define FLAG_TEST(flag, val) (((flag) & (val)) != 0)
-
-#define CLOSURE_SSR_FLAG 1
-#define CLOSURE_SSS_FLAG 2
-#define CLOSURE_HOLDOUT_FLAG 4
-
-#ifdef VOLUMETRICS
-Closure closure_mix(Closure cl1, Closure cl2, float fac)
-{
- Closure cl;
- cl.absorption = mix(cl1.absorption, cl2.absorption, fac);
- cl.scatter = mix(cl1.scatter, cl2.scatter, fac);
- cl.emission = mix(cl1.emission, cl2.emission, fac);
- cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac);
- return cl;
-}
-
-Closure closure_add(Closure cl1, Closure cl2)
-{
- Closure cl;
- cl.absorption = cl1.absorption + cl2.absorption;
- cl.scatter = cl1.scatter + cl2.scatter;
- cl.emission = cl1.emission + cl2.emission;
- cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */
- return cl;
-}
-
-Closure closure_emission(vec3 rgb)
-{
- Closure cl = CLOSURE_DEFAULT;
- cl.emission = rgb;
- return cl;
-}
-
-#else /* SURFACE */
-
-Closure closure_mix(Closure cl1, Closure cl2, float fac)
-{
- Closure cl;
- cl.holdout = mix(cl1.holdout, cl2.holdout, fac);
-
- if (FLAG_TEST(cl1.flag, CLOSURE_HOLDOUT_FLAG)) {
- fac = 1.0;
- }
- else if (FLAG_TEST(cl2.flag, CLOSURE_HOLDOUT_FLAG)) {
- fac = 0.0;
- }
-
- cl.transmittance = mix(cl1.transmittance, cl2.transmittance, fac);
- cl.radiance = mix(cl1.radiance, cl2.radiance, fac);
- cl.flag = cl1.flag | cl2.flag;
- cl.ssr_data = mix(cl1.ssr_data, cl2.ssr_data, fac);
- bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
- /* When mixing SSR don't blend roughness and normals but only specular (ssr_data.xyz). */
- cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
- cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
-
-# ifdef USE_SSS
- cl.sss_albedo = mix(cl1.sss_albedo, cl2.sss_albedo, fac);
- bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
- /* It also does not make sense to mix SSS radius or irradiance. */
- cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
- cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
-# endif
- return cl;
-}
-
-Closure closure_add(Closure cl1, Closure cl2)
-{
- Closure cl;
- cl.transmittance = cl1.transmittance + cl2.transmittance;
- cl.radiance = cl1.radiance + cl2.radiance;
- cl.holdout = cl1.holdout + cl2.holdout;
- cl.flag = cl1.flag | cl2.flag;
- cl.ssr_data = cl1.ssr_data + cl2.ssr_data;
- bool use_cl1_ssr = FLAG_TEST(cl1.flag, CLOSURE_SSR_FLAG);
- /* When mixing SSR don't blend roughness and normals. */
- cl.ssr_data.w = (use_cl1_ssr) ? cl1.ssr_data.w : cl2.ssr_data.w;
- cl.ssr_normal = (use_cl1_ssr) ? cl1.ssr_normal : cl2.ssr_normal;
-
-# ifdef USE_SSS
- cl.sss_albedo = cl1.sss_albedo + cl2.sss_albedo;
- bool use_cl1_sss = FLAG_TEST(cl1.flag, CLOSURE_SSS_FLAG);
- /* It also does not make sense to mix SSS radius or irradiance. */
- cl.sss_radius = (use_cl1_sss) ? cl1.sss_radius : cl2.sss_radius;
- cl.sss_irradiance = (use_cl1_sss) ? cl1.sss_irradiance : cl2.sss_irradiance;
-# endif
- return cl;
-}
-
-Closure closure_emission(vec3 rgb)
-{
- Closure cl = CLOSURE_DEFAULT;
- cl.radiance = rgb;
- return cl;
-}
-
-#endif
-
-#ifndef VOLUMETRICS
-
-/* Let radiance passthrough or replace it to get the BRDF and color
- * to applied to the SSR result. */
-vec3 closure_mask_ssr_radiance(vec3 radiance, float ssr_id)
-{
- return (ssrToggle && int(ssr_id) == outputSsrId) ? vec3(1.0) : radiance;
-}
-
-void closure_load_ssr_data(
- vec3 ssr_radiance, float roughness, vec3 N, float ssr_id, inout Closure cl)
-{
- /* Still encode to avoid artifacts in the SSR pass. */
- vec3 vN = normalize(mat3(ViewMatrix) * N);
- cl.ssr_normal = normal_encode(vN, viewCameraVec(viewPosition));
-
- if (ssrToggle && int(ssr_id) == outputSsrId) {
- cl.ssr_data = vec4(ssr_radiance, roughness);
- cl.flag |= CLOSURE_SSR_FLAG;
- }
- else {
- cl.radiance += ssr_radiance;
- }
-}
-
-void closure_load_sss_data(
- float radius, vec3 sss_irradiance, vec3 sss_albedo, int sss_id, inout Closure cl)
-{
-# ifdef USE_SSS
- if (sss_id == outputSssId) {
- cl.sss_irradiance = sss_irradiance;
- cl.sss_radius = radius;
- cl.sss_albedo = sss_albedo;
- cl.flag |= CLOSURE_SSS_FLAG;
- /* Irradiance will be convolved by SSSS pass. Do not add to radiance. */
- sss_irradiance = vec3(0);
- }
-# endif
- cl.radiance += render_pass_diffuse_mask(vec3(1), sss_irradiance) * sss_albedo;
-}
-
+# define CLOSURE_DEFAULT Closure(vec3(0), vec3(0), 0.0)
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl b/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl
new file mode 100644
index 00000000000..e00bcc4e557
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_empty.glsl
@@ -0,0 +1,7 @@
+
+/* Empty GLSL source to satisfy the GPUShaderCreateInfo requirements. */
+/* Needed includes for shader nodes. */
+#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_attribute_lib.glsl)
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl b/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl
new file mode 100644
index 00000000000..a748c0092b6
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl
@@ -0,0 +1,8 @@
+
+/* Empty GLSL source to satisfy the GPUShaderCreateInfo requirements. */
+/* Needed includes for shader nodes. */
+#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_attribute_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_volume_lib.glsl)
diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
index 1aff93e01f8..e86c5e06c99 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -11,6 +11,7 @@ layout(std140) uniform sssProfile
{
vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
+ float avg_inv_radius;
int sss_samples;
};
@@ -26,7 +27,7 @@ void main(void)
vec2 pixel_size = 1.0 / vec2(textureSize(depthBuffer, 0).xy); /* TODO: precompute. */
vec2 uvs = gl_FragCoord.xy * pixel_size;
vec3 sss_irradiance = texture(sssIrradiance, uvs).rgb;
- float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w;
+ float sss_radius = texture(sssRadius, uvs).r * radii_max_radius.w * avg_inv_radius;
float depth = texture(depthBuffer, uvs).r;
float depth_view = get_view_z_from_depth(depth);
diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
index 3cf21dc32d1..5e1725ace97 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl
@@ -23,12 +23,13 @@ layout(std140) uniform sssProfile
{
vec4 sss_kernel[MAX_SSS_SAMPLES];
vec4 radii_max_radius;
+ float avg_inv_radius;
int sss_samples;
};
vec3 sss_profile(float s)
{
- s /= radii_max_radius.w;
+ s /= radii_max_radius.w * avg_inv_radius;
return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb;
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index fd08dfda060..c8eea8d7860 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -2,15 +2,12 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifdef USE_ALPHA_HASH
@@ -73,6 +70,7 @@ float hashed_alpha_threshold(vec3 co)
void main()
{
#if defined(USE_ALPHA_HASH)
+ g_data = init_globals();
Closure cl = nodetree_exec();
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
deleted file mode 100644
index f650e2eeb8c..00000000000
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
-#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-
-#ifndef HAIR_SHADER
-in vec3 pos;
-#endif
-
-void main()
-{
- GPU_INTEL_VERTEX_SHADER_WORKAROUND
-
-#ifdef HAIR_SHADER
- float time, thick_time, thickness;
- vec3 worldPosition, tan, binor;
- hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
- ModelMatrixInverse,
- ViewMatrixInverse[3].xyz,
- ViewMatrixInverse[2].xyz,
- worldPosition,
- tan,
- binor,
- time,
- thickness,
- thick_time);
-#else
- vec3 worldPosition = point_object_to_world(pos);
-#endif
-
- gl_Position = point_world_to_ndc(worldPosition);
-
-#ifdef CLIP_PLANES
- gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]);
-#endif
-}
diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
index 3e0a5e76d00..f276e4f26ca 100644
--- a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl
@@ -1,4 +1,4 @@
-#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1
+#define EEVEE_AOV_HASH_COLOR_TYPE_MASK 1u
/* ---------------------------------------------------------------------- */
/** \name Resources
@@ -14,7 +14,7 @@ layout(std140) uniform renderpass_block
bool renderPassSSSColor;
bool renderPassEnvironment;
bool renderPassAOV;
- int renderPassAOVActive;
+ uint renderPassAOVActive;
};
/** \} */
@@ -23,19 +23,14 @@ layout(std140) uniform renderpass_block
/** \name Functions
* \{ */
-vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light)
+vec3 render_pass_diffuse_mask(vec3 diffuse_light)
{
- return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0);
+ return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : vec3(1.0)) : vec3(0.0);
}
-vec3 render_pass_sss_mask(vec3 sss_color)
+vec3 render_pass_glossy_mask(vec3 specular_light)
{
- return renderPassSSSColor ? sss_color : vec3(0.0);
-}
-
-vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light)
-{
- return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0);
+ return renderPassGlossy ? (renderPassGlossyLight ? specular_light : vec3(1.0)) : vec3(0.0);
}
vec3 render_pass_emission_mask(vec3 emission_light)
@@ -45,10 +40,10 @@ vec3 render_pass_emission_mask(vec3 emission_light)
bool render_pass_aov_is_color()
{
- return (renderPassAOVActive & EEVEE_AOV_HASH_COLOR_TYPE_MASK) != 0;
+ return (renderPassAOVActive & EEVEE_AOV_HASH_COLOR_TYPE_MASK) != 0u;
}
-int render_pass_aov_hash()
+uint render_pass_aov_hash()
{
return renderPassAOVActive & ~EEVEE_AOV_HASH_COLOR_TYPE_MASK;
}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index cbfa9737a84..0e8e8dd9d01 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -1,5 +1,6 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
@@ -12,6 +13,7 @@ void main()
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
+ hairBary = hair_get_barycentric();
vec3 pos, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
@@ -52,3 +54,93 @@ void main()
# endif
#endif
}
+
+#ifdef HAIR_SHADER
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(samplerBuffer cd_buf)
+{
+ /* Not supported. */
+ return vec4(0.0, 0.0, 0.0, 1.0);
+}
+
+vec3 attr_load_uv(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec4 attr_load_color(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec4 attr_load_vec4(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec3 attr_load_vec3(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec2 attr_load_vec2(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rg;
+}
+
+float attr_load_float(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).r;
+}
+
+#else
+
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(vec4 tangent)
+{
+ tangent.xyz = safe_normalize(normal_object_to_world(tangent.xyz));
+ return tangent;
+}
+
+/* Simple passthrough. */
+vec4 attr_load_vec4(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return attr;
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return attr;
+}
+vec2 attr_load_float(vec2 attr)
+{
+ return attr;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return attr;
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
index 889bf439d5f..9ad7a4fdbc1 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl
@@ -2,16 +2,14 @@
/* Required by some nodes. */
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_diffuse_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_translucent_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_eval_refraction_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
+#pragma BLENDER_REQUIRE(renderpass_lib.glsl)
#ifdef USE_ALPHA_BLEND
/* Use dual source blending to be able to make a whole range of effects. */
@@ -22,18 +20,74 @@ layout(location = 0, index = 1) out vec4 outTransmittance;
layout(location = 0) out vec4 outRadiance;
layout(location = 1) out vec2 ssrNormals;
layout(location = 2) out vec4 ssrData;
-# ifdef USE_SSS
layout(location = 3) out vec3 sssIrradiance;
layout(location = 4) out float sssRadius;
layout(location = 5) out vec3 sssAlbedo;
+
+#endif
+
+uniform float backgroundAlpha;
+
+#ifdef EEVEE_DISPLACEMENT_BUMP
+
+# ifndef GPU_METAL
+/* Prototype. */
+vec3 displacement_exec();
# endif
+/* Return new shading normal. */
+vec3 displacement_bump()
+{
+ vec2 dHd;
+ dF_branch(dot(displacement_exec(), g_data.N + dF_impl(g_data.N)), dHd);
+
+ vec3 dPdx = dFdx(g_data.P);
+ vec3 dPdy = dFdy(g_data.P);
+
+ /* Get surface tangents from normal. */
+ vec3 Rx = cross(dPdy, g_data.N);
+ vec3 Ry = cross(g_data.N, dPdx);
+
+ /* Compute surface gradient and determinant. */
+ float det = dot(dPdx, Rx);
+
+ vec3 surfgrad = dHd.x * Rx + dHd.y * Ry;
+
+ float facing = FrontFacing ? 1.0 : -1.0;
+ return normalize(abs(det) * g_data.N - facing * sign(det) * surfgrad);
+}
+
#endif
void main()
{
+ g_data = init_globals();
+
+#ifdef EEVEE_DISPLACEMENT_BUMP
+ g_data.N = displacement_bump();
+#endif
+
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ attrib_load();
+#endif
+
+ out_ssr_color = vec3(0.0);
+ out_ssr_roughness = 0.0;
+ out_ssr_N = g_data.N;
+
+ out_sss_radiance = vec3(0.0);
+ out_sss_radius = 0.0;
+ out_sss_color = vec3(0.0);
+
Closure cl = nodetree_exec();
+#ifdef WORLD_BACKGROUND
+ if (!renderPassEnvironment) {
+ cl.holdout += 1.0 - backgroundAlpha;
+ cl.radiance *= backgroundAlpha;
+ }
+#endif
+
float holdout = saturate(1.0 - cl.holdout);
float transmit = saturate(avg(cl.transmittance));
float alpha = 1.0 - transmit;
@@ -53,38 +107,40 @@ void main()
outTransmittance = vec4(cl.transmittance, transmit) * holdout;
#else
outRadiance = vec4(cl.radiance, holdout);
- ssrNormals = cl.ssr_normal;
- ssrData = cl.ssr_data;
-# ifdef USE_SSS
- sssIrradiance = cl.sss_irradiance;
- sssRadius = cl.sss_radius;
- sssAlbedo = cl.sss_albedo;
-# endif
+ ssrNormals = normal_encode(normalize(mat3(ViewMatrix) * out_ssr_N), vec3(0.0));
+ ssrData = vec4(out_ssr_color, out_ssr_roughness);
+ sssIrradiance = out_sss_radiance;
+ sssRadius = out_sss_radius;
+ sssAlbedo = out_sss_color;
#endif
- /* For Probe capture */
-#ifdef USE_SSS
- float fac = float(!sssToggle);
-
- /* TODO(fclem): we shouldn't need this.
- * Just disable USE_SSS when USE_REFRACTION is enabled. */
-# ifdef USE_REFRACTION
+#ifdef USE_REFRACTION
/* SSRefraction pass is done after the SSS pass.
* In order to not lose the diffuse light totally we
* need to merge the SSS radiance to the main radiance. */
- fac = 1.0;
-# endif
-
- outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
+ const bool use_refraction = true;
+#else
+ const bool use_refraction = false;
#endif
+ /* For Probe capture */
+ if (!sssToggle || use_refraction) {
+ outRadiance.rgb += out_sss_radiance * out_sss_color;
+ }
#ifndef USE_ALPHA_BLEND
float alpha_div = safe_rcp(alpha);
outRadiance.rgb *= alpha_div;
ssrData.rgb *= alpha_div;
-# ifdef USE_SSS
sssAlbedo.rgb *= alpha_div;
-# endif
+
+ if (renderPassAOV) {
+ if (aov_is_valid) {
+ outRadiance = vec4(out_aov, 1.0);
+ }
+ else {
+ outRadiance = vec4(0.0);
+ }
+ }
#endif
#ifdef LOOKDEV
@@ -92,3 +148,34 @@ void main()
gl_FragDepth = 0.0;
#endif
}
+
+/* Only supported attrib for world/background shaders. */
+vec3 attr_load_orco(vec4 orco)
+{
+ return g_data.P;
+}
+/* Unsupported. */
+vec4 attr_load_tangent(vec4 tangent)
+{
+ return vec4(0);
+}
+vec4 attr_load_vec4(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return vec3(0);
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return vec2(0);
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return vec3(0);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
index d7fc5e0b52a..1f2f7cb65cc 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl
@@ -1,12 +1,23 @@
/** This describe the entire interface of the shader. */
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
#define SURFACE_INTERFACE \
vec3 worldPosition; \
vec3 viewPosition; \
vec3 worldNormal; \
vec3 viewNormal;
-#if defined(STEP_RESOLVE) || defined(STEP_RAYTRACE)
+#ifndef IN_OUT
+# if defined(GPU_VERTEX_SHADER)
+# define IN_OUT out
+# elif defined(GPU_FRAGMENT_SHADER)
+# define IN_OUT in
+# endif
+#endif
+
+#ifndef EEVEE_GENERATED_INTERFACE
+# if defined(STEP_RESOLVE) || defined(STEP_RAYTRACE)
/* SSR will set these global variables itself.
* Also make false positive compiler warnings disappear by setting values. */
vec3 worldPosition = vec3(0);
@@ -14,22 +25,23 @@ vec3 viewPosition = vec3(0);
vec3 worldNormal = vec3(0);
vec3 viewNormal = vec3(0);
-#elif defined(GPU_GEOMETRY_SHADER)
+# elif defined(GPU_GEOMETRY_SHADER)
in ShaderStageInterface{SURFACE_INTERFACE} dataIn[];
out ShaderStageInterface{SURFACE_INTERFACE} dataOut;
-# define PASS_SURFACE_INTERFACE(vert) \
- dataOut.worldPosition = dataIn[vert].worldPosition; \
- dataOut.viewPosition = dataIn[vert].viewPosition; \
- dataOut.worldNormal = dataIn[vert].worldNormal; \
- dataOut.viewNormal = dataIn[vert].viewNormal;
+# define PASS_SURFACE_INTERFACE(vert) \
+ dataOut.worldPosition = dataIn[vert].worldPosition; \
+ dataOut.viewPosition = dataIn[vert].viewPosition; \
+ dataOut.worldNormal = dataIn[vert].worldNormal; \
+ dataOut.viewNormal = dataIn[vert].viewNormal;
-#else /* GPU_VERTEX_SHADER || GPU_FRAGMENT_SHADER*/
+# else /* GPU_VERTEX_SHADER || GPU_FRAGMENT_SHADER*/
IN_OUT ShaderStageInterface{SURFACE_INTERFACE};
-#endif
+# endif
+#endif /* EEVEE_GENERATED_INTERFACE */
#ifdef HAIR_SHADER
IN_OUT ShaderHairInterface
@@ -40,6 +52,7 @@ IN_OUT ShaderHairInterface
float hairThickness;
float hairTime;
flat int hairStrandID;
+ vec2 hairBary;
};
#endif
@@ -52,3 +65,138 @@ IN_OUT ShaderPointCloudInterface
flat int pointID;
};
#endif
+
+#if defined(GPU_FRAGMENT_SHADER) && defined(CODEGEN_LIB)
+
+# if defined(USE_BARYCENTRICS) && !defined(HAIR_SHADER)
+vec3 barycentric_distances_get()
+{
+ /* NOTE: No need to undo perspective divide since it is not applied yet. */
+ vec3 pos0 = (ProjectionMatrixInverse * gpu_position_at_vertex(0)).xyz;
+ vec3 pos1 = (ProjectionMatrixInverse * gpu_position_at_vertex(1)).xyz;
+ vec3 pos2 = (ProjectionMatrixInverse * gpu_position_at_vertex(2)).xyz;
+ vec3 edge21 = pos2 - pos1;
+ vec3 edge10 = pos1 - pos0;
+ vec3 edge02 = pos0 - pos2;
+ vec3 d21 = safe_normalize(edge21);
+ vec3 d10 = safe_normalize(edge10);
+ vec3 d02 = safe_normalize(edge02);
+ vec3 dists;
+ float d = dot(d21, edge02);
+ dists.x = sqrt(dot(edge02, edge02) - d * d);
+ d = dot(d02, edge10);
+ dists.y = sqrt(dot(edge10, edge10) - d * d);
+ d = dot(d10, edge21);
+ dists.z = sqrt(dot(edge21, edge21) - d * d);
+ return dists.xyz;
+}
+# endif
+
+GlobalData init_globals(void)
+{
+ GlobalData surf;
+
+# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ surf.P = -cameraVec(worldPosition);
+ surf.N = surf.Ng = -surf.P;
+ surf.ray_length = 0.0;
+# else
+ surf.P = worldPosition;
+ surf.N = safe_normalize(worldNormal);
+ surf.Ng = safe_normalize(cross(dFdx(surf.P), dFdy(surf.P)));
+ surf.ray_length = distance(surf.P, cameraPos);
+# endif
+ surf.barycentric_coords = vec2(0.0);
+ surf.barycentric_dists = vec3(0.0);
+ if (!FrontFacing) {
+ surf.N = -surf.N;
+ }
+# ifdef HAIR_SHADER
+ /* Shade as a cylinder. */
+ vec3 B = normalize(cross(worldNormal, hairTangent));
+ float cos_theta;
+ if (hairThicknessRes == 1) {
+ /* Random cosine normal distribution on the hair surface. */
+ cos_theta = texelfetch_noise_tex(gl_FragCoord.xy).x * 2.0 - 1.0;
+ }
+ else {
+ /* Shade as a cylinder. */
+ cos_theta = hairThickTime / hairThickness;
+ }
+ float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
+ surf.N = safe_normalize(worldNormal * sin_theta + B * cos_theta);
+ surf.T = hairTangent;
+ surf.is_strand = true;
+ surf.hair_time = hairTime;
+ surf.hair_thickness = hairThickness;
+ surf.hair_strand_id = hairStrandID;
+# ifdef USE_BARYCENTRICS
+ surf.barycentric_coords = hair_resolve_barycentric(hairBary);
+# endif
+# else
+ surf.T = vec3(0.0);
+ surf.is_strand = false;
+ surf.hair_time = 0.0;
+ surf.hair_thickness = 0.0;
+ surf.hair_strand_id = 0;
+# ifdef USE_BARYCENTRICS
+ surf.barycentric_coords = gpu_BaryCoord.xy;
+ surf.barycentric_dists = barycentric_distances_get();
+# endif
+# endif
+ surf.ray_type = rayType;
+ surf.ray_depth = 0.0;
+ return surf;
+}
+#endif
+
+vec3 coordinate_camera(vec3 P)
+{
+ vec3 vP;
+#if defined(PROBE_CAPTURE)
+ /* Unsupported. It would make the probe camera-dependent. */
+ vP = P;
+#elif defined(WORLD_BACKGROUND)
+ vP = transform_direction(ViewMatrix, P);
+#else
+ vP = transform_point(ViewMatrix, P);
+#endif
+ vP.z = -vP.z;
+ return vP;
+}
+
+vec3 coordinate_screen(vec3 P)
+{
+ vec3 window = vec3(0.0);
+#if defined(PROBE_CAPTURE)
+ /* Unsupported. It would make the probe camera-dependent. */
+ window.xy = vec2(0.5);
+
+#elif defined(WORLD_BACKGROUND)
+ window.xy = project_point(ProjectionMatrix, viewPosition).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+
+#else /* MESH */
+ window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+#endif
+ return window;
+}
+
+vec3 coordinate_reflect(vec3 P, vec3 N)
+{
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ return N;
+#else
+ return -reflect(cameraVec(P), N);
+#endif
+}
+
+vec3 coordinate_incoming(vec3 P)
+{
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ return -P;
+#else
+ return cameraVec(P);
+#endif
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
index 51e9eda6cc2..6c6b810422b 100644
--- a/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl
@@ -1,6 +1,9 @@
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#ifndef HAIR_SHADER
@@ -18,6 +21,7 @@ void main()
#ifdef HAIR_SHADER
hairStrandID = hair_get_strand_id();
+ hairBary = hair_get_barycentric();
vec3 pos, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
@@ -53,11 +57,103 @@ void main()
/* No need to normalize since this is just a rotation. */
viewNormal = normal_world_to_view(worldNormal);
-# ifdef USE_ATTR
-# ifdef HAIR_SHADER
- pos = hair_get_strand_pos();
-# endif
- pass_attr(pos, NormalMatrix, ModelMatrixInverse);
-# endif
+
+ attrib_load();
#endif
}
+
+#ifdef HAIR_SHADER
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(samplerBuffer cd_buf)
+{
+ vec3 P = hair_get_strand_pos();
+ vec3 lP = transform_point(ModelMatrixInverse, P);
+ return OrcoTexCoFactors[0].xyz + lP * OrcoTexCoFactors[1].xyz;
+}
+# endif
+
+vec4 attr_load_tangent(samplerBuffer cd_buf)
+{
+ return vec4(hairTangent, 1.0);
+}
+
+vec3 attr_load_uv(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec4 attr_load_color(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec4 attr_load_vec4(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgba;
+}
+
+vec3 attr_load_vec3(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rgb;
+}
+
+vec2 attr_load_vec2(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).rg;
+}
+
+float attr_load_float(samplerBuffer cd_buf)
+{
+ return texelFetch(cd_buf, hairStrandID).r;
+}
+
+#else
+
+# ifdef OBINFO_LIB
+vec3 attr_load_orco(vec4 orco)
+{
+ /* We know when there is no orco layer when orco.w is 1.0 because it uses the generic vertex
+ * attrib (which is [0,0,0,1]). */
+ if (orco.w == 0.0) {
+ return orco.xyz * 0.5 + 0.5;
+ }
+ else {
+ /* If the object does not have any deformation, the orco layer calculation is done on the fly
+ * using the orco_madd factors. */
+ return OrcoTexCoFactors[0].xyz + pos * OrcoTexCoFactors[1].xyz;
+ }
+}
+# endif
+
+vec4 attr_load_tangent(vec4 tangent)
+{
+ tangent.xyz = normal_object_to_world(tangent.xyz);
+ return tangent;
+}
+
+/* Simple passthrough. */
+vec4 attr_load_vec4(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return attr;
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return attr;
+}
+float attr_load_float(float attr)
+{
+ return attr;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return attr;
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return attr;
+}
+#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 4ff42892f7d..e0a79872928 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -1,6 +1,5 @@
#pragma BLENDER_REQUIRE(volumetric_lib.glsl)
-#pragma BLENDER_REQUIRE(closure_type_lib.glsl)
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
@@ -18,9 +17,7 @@ flat in int slice;
vec3 worldPosition = vec3(0.0);
vec3 viewPosition = vec3(0.0);
vec3 viewNormal = vec3(0.0);
-#ifdef MESH_SHADER
-vec3 volumeObjectLocalCoord = vec3(0.0);
-#endif
+vec3 volumeOrco = vec3(0.0);
layout(location = 0) out vec4 volumeScattering;
layout(location = 1) out vec4 volumeExtinction;
@@ -29,6 +26,52 @@ layout(location = 3) out vec4 volumePhase;
/* Store volumetric properties into the froxel textures. */
+#ifdef MESH_SHADER
+GlobalData init_globals(void)
+{
+ GlobalData surf;
+ surf.P = worldPosition;
+ surf.N = vec3(0.0);
+ surf.Ng = vec3(0.0);
+ surf.is_strand = false;
+ surf.hair_time = 0.0;
+ surf.hair_thickness = 0.0;
+ surf.hair_strand_id = 0;
+ surf.barycentric_coords = vec2(0.0);
+ surf.barycentric_dists = vec3(0.0);
+ surf.ray_type = RAY_TYPE_CAMERA;
+ surf.ray_depth = 0.0;
+ surf.ray_length = distance(surf.P, cameraPos);
+ return surf;
+}
+
+vec3 coordinate_camera(vec3 P)
+{
+ vec3 vP;
+ vP = transform_point(ViewMatrix, P);
+ vP.z = -vP.z;
+ return vP;
+}
+
+vec3 coordinate_screen(vec3 P)
+{
+ vec3 window = vec3(0.0);
+ window.xy = project_point(ViewProjectionMatrix, P).xy * 0.5 + 0.5;
+ window.xy = window.xy * CameraTexCoFactors.xy + CameraTexCoFactors.zw;
+ return window;
+}
+
+vec3 coordinate_reflect(vec3 P, vec3 N)
+{
+ return vec3(0.0);
+}
+
+vec3 coordinate_incoming(vec3 P)
+{
+ return cameraVec(P);
+}
+#endif
+
void main()
{
ivec3 volume_cell = ivec3(ivec2(gl_FragCoord.xy), slice);
@@ -37,14 +80,12 @@ void main()
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
- volumeObjectLocalCoord = point_world_to_object(worldPosition);
+ volumeOrco = point_world_to_object(worldPosition);
/* TODO: redundant transform */
- volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) /
- (volumeOrcoSize * 2.0);
- volumeObjectLocalCoord = (volumeObjectToTexture * vec4(volumeObjectLocalCoord, 1.0)).xyz;
+ volumeOrco = (volumeOrco - volumeOrcoLoc + volumeOrcoSize) / (volumeOrcoSize * 2.0);
+ volumeOrco = (volumeObjectToTexture * vec4(volumeOrco, 1.0)).xyz;
- if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) ||
- any(greaterThan(volumeObjectLocalCoord, vec3(1.0)))) {
+ if (any(lessThan(volumeOrco, vec3(0.0))) || any(greaterThan(volumeOrco, vec3(1.0)))) {
/* Note: Discard is not an explicit return in Metal prior to versions 2.3.
* adding return after discard ensures consistent behaviour and avoids GPU
* side-effects where control flow continues with undefined values. */
@@ -54,21 +95,25 @@ void main()
#endif
#ifdef CLEAR
- Closure cl = CLOSURE_DEFAULT;
+ volumeScattering = vec4(0.0, 0.0, 0.0, 1.0);
+ volumeExtinction = vec4(0.0, 0.0, 0.0, 1.0);
+ volumeEmissive = vec4(0.0, 0.0, 0.0, 1.0);
+ volumePhase = vec4(0.0, 0.0, 0.0, 0.0);
#else
+# ifdef MESH_SHADER
+ g_data = init_globals();
+ attrib_load();
+# endif
Closure cl = nodetree_exec();
-#endif
-
-#ifdef MESH_SHADER
+# ifdef MESH_SHADER
cl.scatter *= volumeDensityScale;
cl.absorption *= volumeDensityScale;
cl.emission *= volumeDensityScale;
-#endif
+# endif
volumeScattering = vec4(cl.scatter, 1.0);
volumeExtinction = vec4(cl.absorption + cl.scatter, 1.0);
volumeEmissive = vec4(cl.emission, 1.0);
-
/* Do not add phase weight if no scattering. */
if (all(equal(cl.scatter, vec3(0.0)))) {
volumePhase = vec4(0.0);
@@ -76,4 +121,38 @@ void main()
else {
volumePhase = vec4(cl.anisotropy, vec3(1.0));
}
+#endif
+}
+
+vec3 attr_load_orco(vec4 orco)
+{
+ return volumeOrco;
+}
+vec4 attr_load_tangent(vec4 tangent)
+{
+ return vec4(0);
+}
+vec4 attr_load_vec4(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_vec3(vec3 attr)
+{
+ return vec3(0);
+}
+vec2 attr_load_vec2(vec2 attr)
+{
+ return vec2(0);
+}
+float attr_load_float(float attr)
+{
+ return 0.0;
+}
+vec4 attr_load_color(vec4 attr)
+{
+ return vec4(0);
+}
+vec3 attr_load_uv(vec3 attr)
+{
+ return vec3(0);
}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
index 5226da57a06..1269761ffa4 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl
@@ -1,11 +1,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
-#ifdef MESH_SHADER
-/* TODO: tight slices. */
-layout(triangles) in;
-layout(triangle_strip, max_vertices = 3) out;
-#else /* World */
+#ifdef STANDALONE
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
index 527bbd18896..26b60c992e1 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
@@ -11,8 +11,10 @@ uniform sampler3D volumeScattering; /* Result of the scatter step */
uniform sampler3D volumeExtinction;
#ifdef USE_VOLUME_OPTI
-uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalScattering_img;
-uniform layout(r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img;
+uniform layout(r11f_g11f_b10f)
+writeonly restrict image3D finalScattering_img;
+uniform layout(r11f_g11f_b10f)
+writeonly restrict image3D finalTransmittance_img;
vec3 finalScattering;
vec3 finalTransmittance;
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
index b70747ecec3..b574e8cdb4c 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl
@@ -30,8 +30,30 @@ void main()
vPos.w = 1.0;
PASS_RESOURCE_ID
+}
+
+/* Stubs */
+vec2 btdf_lut(float a, float b, float c)
+{
+ return vec2(0.0);
+}
+
+vec2 brdf_lut(float a, float b)
+{
+ return vec2(0.0);
+}
-#ifdef USE_ATTR
- pass_attr(vec3(0.0), mat3(1), mat4(1));
-#endif
+vec3 F_brdf_multi_scatter(vec3 a, vec3 b, vec2 c)
+{
+ return vec3(0.0);
+}
+
+vec3 F_brdf_single_scatter(vec3 a, vec3 b, vec2 c)
+{
+ return vec3(0.0);
+}
+
+float F_eta(float a, float b)
+{
+ return 0.0;
}
diff --git a/source/blender/draw/engines/eevee/shaders/world_vert.glsl b/source/blender/draw/engines/eevee/shaders/world_vert.glsl
new file mode 100644
index 00000000000..29892a7ffb4
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/world_vert.glsl
@@ -0,0 +1,24 @@
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
+
+#pragma BLENDER_REQUIRE(closure_eval_surface_lib.glsl)
+
+in vec2 pos;
+
+RESOURCE_ID_VARYING
+
+void main()
+{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ PASS_RESOURCE_ID
+
+ gl_Position = vec4(pos, 1.0, 1.0);
+ viewPosition = project_point(ProjectionMatrixInverse, vec3(pos, 0.0));
+ worldPosition = project_point(ViewProjectionMatrixInverse, vec3(pos, 0.0));
+ /* Not usable. */
+ viewNormal = vec3(0.0);
+ worldNormal = vec3(0.0);
+}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 1bf67a4f315..712118e8282 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -28,6 +28,7 @@
#include "DNA_world_types.h"
#include "GPU_framebuffer.h"
+#include "GPU_material.h"
#include "GPU_primitive.h"
#include "GPU_shader.h"
#include "GPU_storage_buffer.h"
@@ -197,13 +198,6 @@ void DRW_texture_free(struct GPUTexture *tex);
/* Shaders */
-typedef void (*GPUMaterialEvalCallbackFn)(struct GPUMaterial *mat,
- int options,
- const char **vert_code,
- const char **geom_code,
- const char **frag_lib,
- const char **defines);
-
struct GPUShader *DRW_shader_create_ex(
const char *vert, const char *geom, const char *frag, const char *defines, const char *name);
struct GPUShader *DRW_shader_create_with_lib_ex(const char *vert,
@@ -242,38 +236,20 @@ struct GPUShader *DRW_shader_create_fullscreen_with_shaderlib_ex(const char *fra
#define DRW_shader_create_fullscreen_with_shaderlib(frag, lib, defines) \
DRW_shader_create_fullscreen_with_shaderlib_ex(frag, lib, defines, __func__)
-struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
- const void *engine_type,
- int options,
- bool deferred);
-struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
- const void *engine_type,
- int options,
- bool deferred);
-struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
- struct World *wo,
- struct bNodeTree *ntree,
- const void *engine_type,
- int options,
- bool is_volume_shader,
- const char *vert,
- const char *geom,
- const char *frag_lib,
- const char *defines,
- bool deferred,
- GPUMaterialEvalCallbackFn callback);
-struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
- struct Material *ma,
- struct bNodeTree *ntree,
- const void *engine_type,
- int options,
- bool is_volume_shader,
- const char *vert,
- const char *geom,
- const char *frag_lib,
- const char *defines,
- bool deferred,
- GPUMaterialEvalCallbackFn callback);
+struct GPUMaterial *DRW_shader_from_world(struct World *wo,
+ struct bNodeTree *ntree,
+ const uint64_t shader_id,
+ const bool is_volume_shader,
+ bool deferred,
+ GPUCodegenCallbackFn callback,
+ void *thunk);
+struct GPUMaterial *DRW_shader_from_material(struct Material *ma,
+ struct bNodeTree *ntree,
+ const uint64_t shader_id,
+ const bool is_volume_shader,
+ bool deferred,
+ GPUCodegenCallbackFn callback,
+ void *thunk);
void DRW_shader_free(struct GPUShader *shader);
#define DRW_SHADER_FREE_SAFE(shader) \
do { \
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 0ac8bf91906..aac6f7e58c5 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -306,7 +306,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
if (hair_cache->length_tex) {
- DRW_shgroup_uniform_texture(shgrp, "hairLen", hair_cache->length_tex);
+ DRW_shgroup_uniform_texture(shgrp, "l", hair_cache->length_tex);
}
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 1936aa599ff..9f8a68f81f6 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -417,119 +417,81 @@ GPUShader *DRW_shader_create_fullscreen_with_shaderlib_ex(const char *frag,
return sh;
}
-GPUMaterial *DRW_shader_find_from_world(World *wo,
- const void *engine_type,
- const int options,
- bool deferred)
+GPUMaterial *DRW_shader_from_world(World *wo,
+ struct bNodeTree *ntree,
+ const uint64_t shader_id,
+ const bool is_volume_shader,
+ bool deferred,
+ GPUCodegenCallbackFn callback,
+ void *thunk)
{
- GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
- if (DRW_state_is_image_render() || !deferred) {
- if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
- /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
- * with the shader code and we will resume the compilation from there. */
- return NULL;
- }
- }
- return mat;
-}
-
-GPUMaterial *DRW_shader_find_from_material(Material *ma,
- const void *engine_type,
- const int options,
- bool deferred)
-{
- GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
- if (DRW_state_is_image_render() || !deferred) {
- if (mat != NULL && GPU_material_status(mat) == GPU_MAT_QUEUED) {
- /* XXX Hack : we return NULL so that the engine will call DRW_shader_create_from_XXX
- * with the shader code and we will resume the compilation from there. */
- return NULL;
- }
- }
- return mat;
-}
-
-GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
- World *wo,
- struct bNodeTree *ntree,
- const void *engine_type,
- const int options,
- const bool is_volume_shader,
- const char *vert,
- const char *geom,
- const char *frag_lib,
- const char *defines,
- bool deferred,
- GPUMaterialEvalCallbackFn callback)
-{
- GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render() || !deferred) {
- mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
- }
-
- if (mat == NULL) {
- scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
- mat = GPU_material_from_nodetree(scene,
- NULL,
- ntree,
- &wo->gpumaterial,
- engine_type,
- options,
- is_volume_shader,
- vert,
- geom,
- frag_lib,
- defines,
- wo->id.name,
- callback);
+ Scene *scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
+ GPUMaterial *mat = GPU_material_from_nodetree(scene,
+ NULL,
+ ntree,
+ &wo->gpumaterial,
+ wo->id.name,
+ shader_id,
+ is_volume_shader,
+ false,
+ callback,
+ thunk);
+ if (!DRW_state_is_image_render() && deferred && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* Shader has been already queued. */
+ return mat;
}
- if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ if (GPU_material_status(mat) == GPU_MAT_CREATED) {
+ GPU_material_status_set(mat, GPU_MAT_QUEUED);
drw_deferred_shader_add(mat, deferred);
}
+ if (!deferred && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* Force compilation for shaders already queued. */
+ drw_deferred_shader_add(mat, false);
+ }
return mat;
}
-GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
- Material *ma,
- struct bNodeTree *ntree,
- const void *engine_type,
- const int options,
- const bool is_volume_shader,
- const char *vert,
- const char *geom,
- const char *frag_lib,
- const char *defines,
- bool deferred,
- GPUMaterialEvalCallbackFn callback)
+GPUMaterial *DRW_shader_from_material(Material *ma,
+ struct bNodeTree *ntree,
+ const uint64_t shader_id,
+ const bool is_volume_shader,
+ bool deferred,
+ GPUCodegenCallbackFn callback,
+ void *thunk)
{
- GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render() || !deferred) {
- mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
+ Scene *scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
+ GPUMaterial *mat = GPU_material_from_nodetree(scene,
+ ma,
+ ntree,
+ &ma->gpumaterial,
+ ma->id.name,
+ shader_id,
+ is_volume_shader,
+ false,
+ callback,
+ thunk);
+
+ if (DRW_state_is_image_render()) {
+ /* Do not deferred if doing render. */
+ deferred = false;
}
- if (mat == NULL) {
- scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
- mat = GPU_material_from_nodetree(scene,
- ma,
- ntree,
- &ma->gpumaterial,
- engine_type,
- options,
- is_volume_shader,
- vert,
- geom,
- frag_lib,
- defines,
- ma->id.name,
- callback);
+ if (deferred && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* Shader has been already queued. */
+ return mat;
}
- if (GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ if (GPU_material_status(mat) == GPU_MAT_CREATED) {
+ GPU_material_status_set(mat, GPU_MAT_QUEUED);
drw_deferred_shader_add(mat, deferred);
}
+ if (!deferred && GPU_material_status(mat) == GPU_MAT_QUEUED) {
+ /* Force compilation for shaders already queued. */
+ drw_deferred_shader_add(mat, false);
+ }
return mat;
}
@@ -552,15 +514,15 @@ void DRW_shader_free(GPUShader *shader)
* contains the needed libraries for this shader.
* \{ */
-/* 32 because we use a 32bit bitmap. */
-#define MAX_LIB 32
+/* 64 because we use a 64bit bitmap. */
+#define MAX_LIB 64
#define MAX_LIB_NAME 64
#define MAX_LIB_DEPS 8
struct DRWShaderLibrary {
const char *libs[MAX_LIB];
char libs_name[MAX_LIB][MAX_LIB_NAME];
- uint32_t libs_deps[MAX_LIB];
+ uint64_t libs_deps[MAX_LIB];
};
DRWShaderLibrary *DRW_shader_library_create(void)
@@ -589,23 +551,27 @@ static int drw_shader_library_search(const DRWShaderLibrary *lib, const char *na
}
/* Return bitmap of dependencies. */
-static uint32_t drw_shader_dependencies_get(const DRWShaderLibrary *lib, const char *lib_code)
+static uint64_t drw_shader_dependencies_get(const DRWShaderLibrary *lib,
+ const char *pragma_str,
+ const char *lib_code,
+ const char *UNUSED(lib_name))
{
/* Search dependencies. */
- uint32_t deps = 0;
+ uint pragma_len = strlen(pragma_str);
+ uint64_t deps = 0;
const char *haystack = lib_code;
- while ((haystack = strstr(haystack, "BLENDER_REQUIRE("))) {
- haystack += 16;
+ while ((haystack = strstr(haystack, pragma_str))) {
+ haystack += pragma_len;
int dep = drw_shader_library_search(lib, haystack);
if (dep == -1) {
- char dbg_name[33];
+ char dbg_name[MAX_NAME];
int i = 0;
while ((*haystack != ')') && (i < (sizeof(dbg_name) - 2))) {
dbg_name[i] = *haystack;
haystack++;
i++;
}
- dbg_name[i + 1] = '\0';
+ dbg_name[i] = '\0';
CLOG_INFO(&LOG,
0,
@@ -614,7 +580,7 @@ static uint32_t drw_shader_dependencies_get(const DRWShaderLibrary *lib, const c
dbg_name);
}
else {
- deps |= 1u << (uint32_t)dep;
+ deps |= 1llu << ((uint64_t)dep);
}
}
return deps;
@@ -633,7 +599,8 @@ void DRW_shader_library_add_file(DRWShaderLibrary *lib, const char *lib_code, co
if (index > -1) {
lib->libs[index] = lib_code;
BLI_strncpy(lib->libs_name[index], lib_name, MAX_LIB_NAME);
- lib->libs_deps[index] = drw_shader_dependencies_get(lib, lib_code);
+ lib->libs_deps[index] = drw_shader_dependencies_get(
+ lib, "BLENDER_REQUIRE(", lib_code, lib_name);
}
else {
printf("Error: Too many libraries. Cannot add %s.\n", lib_name);
@@ -643,21 +610,20 @@ void DRW_shader_library_add_file(DRWShaderLibrary *lib, const char *lib_code, co
char *DRW_shader_library_create_shader_string(const DRWShaderLibrary *lib, const char *shader_code)
{
- uint32_t deps = drw_shader_dependencies_get(lib, shader_code);
+ uint64_t deps = drw_shader_dependencies_get(lib, "BLENDER_REQUIRE(", shader_code, "shader code");
DynStr *ds = BLI_dynstr_new();
/* Add all dependencies recursively. */
for (int i = MAX_LIB - 1; i > -1; i--) {
- if (lib->libs[i] && (deps & (1u << (uint32_t)i))) {
+ if (lib->libs[i] && (deps & (1llu << (uint64_t)i))) {
deps |= lib->libs_deps[i];
}
}
/* Concatenate all needed libs into one string. */
- for (int i = 0; i < MAX_LIB; i++) {
- if (deps & 1u) {
+ for (int i = 0; i < MAX_LIB && deps != 0llu; i++, deps >>= 1llu) {
+ if (deps & 1llu) {
BLI_dynstr_append(ds, lib->libs[i]);
}
- deps = deps >> 1;
}
BLI_dynstr_append(ds, shader_code);
diff --git a/source/blender/draw/intern/draw_shader_shared.h b/source/blender/draw/intern/draw_shader_shared.h
index 5fc76bc25e6..58875c0496a 100644
--- a/source/blender/draw/intern/draw_shader_shared.h
+++ b/source/blender/draw/intern/draw_shader_shared.h
@@ -36,16 +36,19 @@ struct ViewInfos {
};
BLI_STATIC_ASSERT_ALIGN(ViewInfos, 16)
+/* Do not override old definitions if the shader uses this header but not shader info. */
+#ifdef USE_GPU_SHADER_CREATE_INFO
/* TODO(@fclem): Mass rename. */
-#define ViewProjectionMatrix drw_view.persmat
-#define ViewProjectionMatrixInverse drw_view.persinv
-#define ViewMatrix drw_view.viewmat
-#define ViewMatrixInverse drw_view.viewinv
-#define ProjectionMatrix drw_view.winmat
-#define ProjectionMatrixInverse drw_view.wininv
-#define clipPlanes drw_view.clip_planes
-#define ViewVecs drw_view.viewvecs
-#define CameraTexCoFactors drw_view.viewcamtexcofac
+# define ViewProjectionMatrix drw_view.persmat
+# define ViewProjectionMatrixInverse drw_view.persinv
+# define ViewMatrix drw_view.viewmat
+# define ViewMatrixInverse drw_view.viewinv
+# define ProjectionMatrix drw_view.winmat
+# define ProjectionMatrixInverse drw_view.wininv
+# define clipPlanes drw_view.clip_planes
+# define ViewVecs drw_view.viewvecs
+# define CameraTexCoFactors drw_view.viewcamtexcofac
+#endif
struct ObjectMatrices {
float4x4 drw_modelMatrix;
diff --git a/source/blender/draw/intern/shaders/common_attribute_lib.glsl b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
new file mode 100644
index 00000000000..99db2929a13
--- /dev/null
+++ b/source/blender/draw/intern/shaders/common_attribute_lib.glsl
@@ -0,0 +1,21 @@
+
+/* Prototype of functions to implement to load attributes data.
+ * Implementation changes based on object data type. */
+
+vec3 attr_load_orco(vec4 orco);
+vec4 attr_load_tangent(vec4 tangent);
+vec3 attr_load_uv(vec3 uv);
+vec4 attr_load_color(vec4 color);
+vec4 attr_load_vec4(vec4 attr);
+vec3 attr_load_vec3(vec3 attr);
+vec2 attr_load_vec2(vec2 attr);
+float attr_load_float(float attr);
+
+vec3 attr_load_orco(samplerBuffer orco);
+vec4 attr_load_tangent(samplerBuffer tangent);
+vec3 attr_load_uv(samplerBuffer uv);
+vec4 attr_load_color(samplerBuffer color);
+vec4 attr_load_vec4(samplerBuffer attr);
+vec3 attr_load_vec3(samplerBuffer attr);
+vec2 attr_load_vec2(samplerBuffer attr);
+float attr_load_float(samplerBuffer attr);
diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl
index 4d0ffaeb40f..1ac26c91b93 100644
--- a/source/blender/draw/intern/shaders/common_math_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_math_lib.glsl
@@ -1,4 +1,8 @@
+/* WORKAROUND: to guard against double include in EEVEE. */
+#ifndef COMMON_MATH_LIB_GLSL
+#define COMMON_MATH_LIB_GLSL
+
/* ---------------------------------------------------------------------- */
/** \name Common Math Utilities
* \{ */
@@ -276,3 +280,5 @@ vec3 hue_gradient(float t)
vec3 p = abs(fract(t + vec3(1.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0);
return (clamp(p - 1.0, 0.0, 1.0));
}
+
+#endif /* COMMON_MATH_LIB_GLSL */
diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl
index a2b8cb4bbd6..4086162a530 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -1,5 +1,10 @@
+
+/* WORKAROUND: to guard against double include in EEVEE. */
+#ifndef COMMON_VIEW_LIB_GLSL
+#define COMMON_VIEW_LIB_GLSL
+
/* Temporary until we fully make the switch. */
-#ifndef USE_GPU_SHADER_CREATE_INFO
+#if !defined(USE_GPU_SHADER_CREATE_INFO)
# define DRW_RESOURCE_CHUNK_LEN 512
@@ -37,7 +42,10 @@ layout(std140) uniform viewBlock
#define cameraForward ViewMatrixInverse[2].xyz
#define cameraPos ViewMatrixInverse[3].xyz
-#define cameraVec(P) ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - P) : cameraForward)
+vec3 cameraVec(vec3 P)
+{
+ return ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - P) : cameraForward);
+}
#define viewCameraVec(vP) ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0))
#ifdef world_clip_planes_calc_clip_distance
@@ -92,14 +100,14 @@ vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos)
}
/* Temporary until we fully make the switch. */
-#ifndef DRW_SHADER_SHARED_H
+#ifndef USE_GPU_SHADER_CREATE_INFO
uniform int drw_resourceChunk;
-#endif /* DRW_SHADER_SHARED_H */
+#endif /* USE_GPU_SHADER_CREATE_INFO */
#ifdef GPU_VERTEX_SHADER
/* Temporary until we fully make the switch. */
-# ifndef DRW_SHADER_SHARED_H
+# ifndef USE_GPU_SHADER_CREATE_INFO
/* clang-format off */
# if defined(IN_PLACE_INSTANCES) || defined(INSTANCED_ATTR) || defined(DRW_LEGACY_MODEL_MATRIX) || defined(GPU_DEPRECATED_AMD_DRIVER)
@@ -121,7 +129,10 @@ uniform int drw_ResourceID;
/* Use this to declare and pass the value if
* the fragment shader uses the resource_id. */
-# ifdef USE_GEOMETRY_SHADER
+# if defined(EEVEE_GENERATED_INTERFACE)
+# define RESOURCE_ID_VARYING
+# define PASS_RESOURCE_ID resourceIDFrag = resource_id;
+# elif defined(USE_GEOMETRY_SHADER)
# define RESOURCE_ID_VARYING flat out int resourceIDGeom;
# define PASS_RESOURCE_ID resourceIDGeom = resource_id;
# else
@@ -129,12 +140,12 @@ uniform int drw_ResourceID;
# define PASS_RESOURCE_ID resourceIDFrag = resource_id;
# endif
-# endif /* DRW_SHADER_SHARED_H */
+# endif /* USE_GPU_SHADER_CREATE_INFO */
#endif /* GPU_VERTEX_SHADER */
/* Temporary until we fully make the switch. */
-#ifdef DRW_SHADER_SHARED_H
+#ifdef USE_GPU_SHADER_CREATE_INFO
/* TODO(fclem): Rename PASS_RESOURCE_ID to DRW_RESOURCE_ID_VARYING_SET */
# if defined(UNIFORM_RESOURCE_ID)
# define resource_id drw_ResourceID
@@ -159,16 +170,23 @@ uniform int drw_ResourceID;
/* If used in a fragment / geometry shader, we pass
* resource_id as varying. */
# ifdef GPU_GEOMETRY_SHADER
-# define RESOURCE_ID_VARYING \
- flat out int resourceIDFrag; \
- flat in int resourceIDGeom[];
+/* TODO(fclem): Remove. This is getting ridiculous. */
+# if !defined(EEVEE_GENERATED_INTERFACE)
+# define RESOURCE_ID_VARYING \
+ flat out int resourceIDFrag; \
+ flat in int resourceIDGeom[];
+# else
+# define RESOURCE_ID_VARYING
+# endif
# define resource_id resourceIDGeom
# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0];
# endif
-# ifdef GPU_FRAGMENT_SHADER
+# if defined(GPU_FRAGMENT_SHADER)
+# if !defined(EEVEE_GENERATED_INTERFACE)
flat in int resourceIDFrag;
+# endif
# define resource_id resourceIDFrag
# endif
#endif
@@ -185,7 +203,9 @@ struct ObjectMatrices {
mat4 drw_modelMatrix;
mat4 drw_modelMatrixInverse;
};
+# endif /* DRW_SHADER_SHARED_H */
+# ifndef USE_GPU_SHADER_CREATE_INFO
layout(std140) uniform modelBlock
{
ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN];
@@ -193,24 +213,24 @@ layout(std140) uniform modelBlock
# define ModelMatrix (drw_matrices[resource_id].drw_modelMatrix)
# define ModelMatrixInverse (drw_matrices[resource_id].drw_modelMatrixInverse)
-# endif /* DRW_SHADER_SHARED_H */
+# endif /* USE_GPU_SHADER_CREATE_INFO */
#else /* GPU_INTEL */
/* Temporary until we fully make the switch. */
-# ifndef DRW_SHADER_SHARED_H
+# ifndef USE_GPU_SHADER_CREATE_INFO
/* Intel GPU seems to suffer performance impact when the model matrix is in UBO storage.
* So for now we just force using the legacy path. */
/* Note that this is also a workaround of a problem on osx (amd or nvidia)
* and older amd driver on windows. */
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixInverse;
-# endif /* DRW_SHADER_SHARED_H */
+# endif /* USE_GPU_SHADER_CREATE_INFO */
#endif
/* Temporary until we fully make the switch. */
-#ifndef DRW_SHADER_SHARED_H
+#ifndef USE_GPU_SHADER_CREATE_INFO
# define resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id)
#endif
@@ -337,3 +357,5 @@ vec3 get_view_vector_from_screen_uv(vec2 uv)
return vec3(0.0, 0.0, 1.0);
}
}
+
+#endif /* COMMON_VIEW_LIB_GLSL */