From 80859a6cb2726a39fb22cb49f06e0355dc9390a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cle=CC=81ment=20Foucault?= Date: Thu, 14 Apr 2022 18:47:58 +0200 Subject: GPU: Make nodetree GLSL Codegen render engine agnostic This commit removes all EEVEE specific code from the `gpu_shader_material*.glsl` files. It defines a clear interface to evaluate the closure nodes leaving more flexibility to the render engine. Some of the long standing workaround are fixed: - bump mapping support is no longer duplicating a lot of node and is instead compiled into a function call. - bump rewiring to Normal socket is no longer needed as we now use a global `g_data.N` for that. Closure sampling with upstread weight eval is now supported if the engine needs it. This also makes all the material GLSL sources use `GPUSource` for better debugging experience. The `GPUFunction` parsing now happens in `GPUSource` creation. The whole `GPUCodegen` now uses the `ShaderCreateInfo` and is object type agnostic. Is has also been rewritten in C++. This patch changes a view behavior for EEVEE: - Mix shader node factor imput is now clamped. - Tangent Vector displacement behavior is now matching cycles. - The chosen BSDF used for SSR might change. - Hair shading may have very small changes on very large hairs when using hair polygon stripes. - ShaderToRGB node will remove any SSR and SSS form a shader. - SSS radius input now is no longer a scaling factor but defines an average radius. The SSS kernel "shape" (radii) are still defined by the socket default values. Appart from the listed changes no other regressions are expected. --- .../blender/draw/engines/eevee/eevee_materials.c | 16 +- source/blender/draw/engines/eevee/eevee_private.h | 20 +- .../draw/engines/eevee/eevee_renderpasses.c | 4 +- source/blender/draw/engines/eevee/eevee_shaders.c | 84 +++--- .../draw/engines/eevee/eevee_shaders_extra.cc | 173 +++++++++++ source/blender/draw/engines/eevee/eevee_volumes.c | 1 + .../eevee/shaders/ambient_occlusion_lib.glsl | 35 +++ .../eevee/shaders/closure_eval_diffuse_lib.glsl | 3 + .../eevee/shaders/closure_eval_glossy_lib.glsl | 3 + .../engines/eevee/shaders/closure_eval_lib.glsl | 15 + .../eevee/shaders/closure_eval_refraction_lib.glsl | 3 + .../eevee/shaders/closure_eval_surface_lib.glsl | 325 +++++++++++++++++++++ .../shaders/closure_eval_translucent_lib.glsl | 3 + .../eevee/shaders/closure_eval_volume_lib.glsl | 113 +++++++ .../engines/eevee/shaders/closure_type_lib.glsl | 252 +++++----------- .../draw/engines/eevee/shaders/eevee_empty.glsl | 7 + .../engines/eevee/shaders/eevee_empty_volume.glsl | 8 + .../eevee/shaders/effect_subsurface_frag.glsl | 3 +- .../eevee/shaders/effect_translucency_frag.glsl | 3 +- .../draw/engines/eevee/shaders/prepass_frag.glsl | 10 +- .../draw/engines/eevee/shaders/prepass_vert.glsl | 35 --- .../draw/engines/eevee/shaders/renderpass_lib.glsl | 21 +- .../draw/engines/eevee/shaders/shadow_vert.glsl | 92 ++++++ .../draw/engines/eevee/shaders/surface_frag.glsl | 141 +++++++-- .../draw/engines/eevee/shaders/surface_lib.glsl | 166 ++++++++++- .../draw/engines/eevee/shaders/surface_vert.glsl | 108 ++++++- .../engines/eevee/shaders/volumetric_frag.glsl | 111 ++++++- .../engines/eevee/shaders/volumetric_geom.glsl | 6 +- .../eevee/shaders/volumetric_integration_frag.glsl | 6 +- .../engines/eevee/shaders/volumetric_vert.glsl | 28 +- .../draw/engines/eevee/shaders/world_vert.glsl | 24 ++ 31 files changed, 1454 insertions(+), 365 deletions(-) create mode 100644 source/blender/draw/engines/eevee/eevee_shaders_extra.cc create mode 100644 source/blender/draw/engines/eevee/shaders/closure_eval_surface_lib.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/closure_eval_volume_lib.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/eevee_empty.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/eevee_empty_volume.glsl delete mode 100644 source/blender/draw/engines/eevee/shaders/prepass_vert.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/world_vert.glsl (limited to 'source/blender/draw/engines') 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(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); +} -- cgit v1.2.3