/* SPDX-License-Identifier: GPL-2.0-or-later * Copyright 2016 Blender Foundation. */ /** \file * \ingroup draw_engine */ #include "DRW_render.h" #include "BKE_lib_id.h" #include "BKE_node.h" #include "BLI_dynstr.h" #include "BLI_string_utils.h" #include "DNA_world_types.h" #include "MEM_guardedalloc.h" #include "GPU_capabilities.h" #include "GPU_material.h" #include "GPU_shader.h" #include "NOD_shader.h" #include "eevee_engine.h" #include "eevee_private.h" static const char *filter_defines = #if defined(IRRADIANCE_SH_L2) "#define IRRADIANCE_SH_L2\n"; #elif defined(IRRADIANCE_HL2) "#define IRRADIANCE_HL2\n"; #endif static struct { /* Lookdev */ struct GPUShader *studiolight_probe_sh; struct GPUShader *studiolight_background_sh; /* Probes */ struct GPUShader *probe_grid_display_sh; struct GPUShader *probe_cube_display_sh; struct GPUShader *probe_planar_display_sh; struct GPUShader *probe_filter_glossy_sh; struct GPUShader *probe_filter_diffuse_sh; struct GPUShader *probe_filter_visibility_sh; struct GPUShader *probe_grid_fill_sh; struct GPUShader *probe_planar_downsample_sh; /* Velocity Resolve */ struct GPUShader *velocity_resolve_sh; /* Temporal Anti Aliasing */ struct GPUShader *taa_resolve_sh; struct GPUShader *taa_resolve_reproject_sh; /* Bloom */ struct GPUShader *bloom_blit_sh[2]; struct GPUShader *bloom_downsample_sh[2]; struct GPUShader *bloom_upsample_sh[2]; struct GPUShader *bloom_resolve_sh[2]; /* Depth Of Field */ struct GPUShader *dof_bokeh_sh; struct GPUShader *dof_setup_sh; struct GPUShader *dof_flatten_tiles_sh; struct GPUShader *dof_dilate_tiles_sh[2]; struct GPUShader *dof_downsample_sh; struct GPUShader *dof_reduce_sh[2]; struct GPUShader *dof_gather_sh[DOF_GATHER_MAX_PASS][2]; struct GPUShader *dof_filter_sh; struct GPUShader *dof_scatter_sh[2][2]; struct GPUShader *dof_resolve_sh[2][2]; /* General purpose Shaders. */ struct GPUShader *lookdev_background; struct GPUShader *update_noise_sh; /* Down-sample Depth */ struct GPUShader *minz_downlevel_sh; struct GPUShader *maxz_downlevel_sh; struct GPUShader *minz_downdepth_sh; struct GPUShader *maxz_downdepth_sh; struct GPUShader *minz_downdepth_layer_sh; struct GPUShader *maxz_downdepth_layer_sh; struct GPUShader *maxz_copydepth_layer_sh; struct GPUShader *minz_copydepth_sh; struct GPUShader *maxz_copydepth_sh; /* Simple Down-sample. */ struct GPUShader *color_copy_sh; struct GPUShader *downsample_sh; struct GPUShader *downsample_cube_sh; /* Mist */ struct GPUShader *mist_sh; /* Motion Blur */ struct GPUShader *motion_blur_sh; struct GPUShader *motion_blur_object_sh; struct GPUShader *motion_blur_hair_sh; struct GPUShader *velocity_tiles_sh; struct GPUShader *velocity_tiles_expand_sh; /* Ground Truth Ambient Occlusion */ struct GPUShader *gtao_sh; struct GPUShader *gtao_layer_sh; struct GPUShader *gtao_debug_sh; /* GGX LUT */ struct GPUShader *ggx_lut_sh; struct GPUShader *ggx_refraction_lut_sh; /* Render Passes */ struct GPUShader *postprocess_sh; struct GPUShader *cryptomatte_sh[2]; /* Screen Space Reflection */ struct GPUShader *reflection_trace; struct GPUShader *reflection_resolve; /* Shadows */ struct GPUShader *shadow_sh; struct GPUShader *shadow_accum_sh; /* Subsurface */ struct GPUShader *sss_sh[3]; /* Volume */ struct GPUShader *volumetric_clear_sh; struct GPUShader *scatter_sh; struct GPUShader *scatter_with_lights_sh; struct GPUShader *volumetric_integration_sh; struct GPUShader *volumetric_resolve_sh[2]; struct GPUShader *volumetric_accum_sh; /* Shader strings */ char *surface_lit_frag; char *surface_prepass_frag; char *surface_geom_barycentric; DRWShaderLibrary *lib; /* LookDev Materials */ Material *glossy_mat; Material *diffuse_mat; Material *error_mat; World *default_world; /* Default Material */ struct { bNodeTree *ntree; bNodeSocketValueRGBA *color_socket; bNodeSocketValueFloat *metallic_socket; bNodeSocketValueFloat *roughness_socket; bNodeSocketValueFloat *specular_socket; } surface; struct { bNodeTree *ntree; bNodeSocketValueRGBA *color_socket; } world; } e_data = {NULL}; /* Engine data */ extern char datatoc_common_hair_lib_glsl[]; 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_codegen_lib_glsl[]; extern char datatoc_ambient_occlusion_lib_glsl[]; extern char datatoc_background_vert_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; 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_lib_glsl[]; extern char datatoc_cryptomatte_frag_glsl[]; extern char datatoc_cryptomatte_vert_glsl[]; extern char datatoc_cubemap_lib_glsl[]; extern char datatoc_default_frag_glsl[]; extern char datatoc_lookdev_world_frag_glsl[]; extern char datatoc_effect_bloom_frag_glsl[]; extern char datatoc_effect_dof_bokeh_frag_glsl[]; extern char datatoc_effect_dof_dilate_tiles_frag_glsl[]; extern char datatoc_effect_dof_downsample_frag_glsl[]; extern char datatoc_effect_dof_filter_frag_glsl[]; extern char datatoc_effect_dof_flatten_tiles_frag_glsl[]; extern char datatoc_effect_dof_gather_frag_glsl[]; extern char datatoc_effect_dof_lib_glsl[]; extern char datatoc_effect_dof_reduce_frag_glsl[]; extern char datatoc_effect_dof_resolve_frag_glsl[]; extern char datatoc_effect_dof_scatter_frag_glsl[]; extern char datatoc_effect_dof_scatter_vert_glsl[]; extern char datatoc_effect_dof_setup_frag_glsl[]; extern char datatoc_effect_downsample_cube_frag_glsl[]; extern char datatoc_effect_downsample_frag_glsl[]; extern char datatoc_effect_gtao_frag_glsl[]; extern char datatoc_effect_minmaxz_frag_glsl[]; extern char datatoc_effect_mist_frag_glsl[]; extern char datatoc_effect_motion_blur_frag_glsl[]; extern char datatoc_effect_reflection_lib_glsl[]; extern char datatoc_effect_reflection_resolve_frag_glsl[]; extern char datatoc_effect_reflection_trace_frag_glsl[]; extern char datatoc_effect_subsurface_frag_glsl[]; extern char datatoc_effect_temporal_aa_glsl[]; extern char datatoc_effect_translucency_frag_glsl[]; extern char datatoc_effect_velocity_resolve_frag_glsl[]; extern char datatoc_effect_velocity_tile_frag_glsl[]; extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lightprobe_cube_display_frag_glsl[]; extern char datatoc_lightprobe_cube_display_vert_glsl[]; extern char datatoc_lightprobe_filter_diffuse_frag_glsl[]; extern char datatoc_lightprobe_filter_glossy_frag_glsl[]; extern char datatoc_lightprobe_filter_visibility_frag_glsl[]; extern char datatoc_lightprobe_geom_glsl[]; extern char datatoc_lightprobe_grid_display_frag_glsl[]; extern char datatoc_lightprobe_grid_display_vert_glsl[]; extern char datatoc_lightprobe_grid_fill_frag_glsl[]; extern char datatoc_lightprobe_lib_glsl[]; extern char datatoc_lightprobe_planar_display_frag_glsl[]; extern char datatoc_lightprobe_planar_display_vert_glsl[]; extern char datatoc_lightprobe_planar_downsample_frag_glsl[]; extern char datatoc_lightprobe_planar_downsample_geom_glsl[]; extern char datatoc_lightprobe_planar_downsample_vert_glsl[]; extern char datatoc_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[]; extern char datatoc_closure_eval_translucent_lib_glsl[]; extern char datatoc_ltc_lib_glsl[]; 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_random_lib_glsl[]; extern char datatoc_raytrace_lib_glsl[]; extern char datatoc_renderpass_lib_glsl[]; extern char datatoc_renderpass_postprocess_frag_glsl[]; extern char datatoc_shadow_accum_frag_glsl[]; extern char datatoc_shadow_frag_glsl[]; extern char datatoc_shadow_vert_glsl[]; extern char datatoc_ssr_lib_glsl[]; extern char datatoc_surface_frag_glsl[]; extern char datatoc_surface_geom_glsl[]; extern char datatoc_surface_lib_glsl[]; extern char datatoc_surface_vert_glsl[]; extern char datatoc_update_noise_frag_glsl[]; extern char datatoc_volumetric_accum_frag_glsl[]; extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_integration_frag_glsl[]; 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 *********** */ static void eevee_shader_library_ensure(void) { if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); /* NOTE: These need to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_math_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_math_geom_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); 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_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); DRW_SHADER_LIB_ADD(e_data.lib, common_utiltex_lib); DRW_SHADER_LIB_ADD(e_data.lib, bsdf_sampling_lib); DRW_SHADER_LIB_ADD(e_data.lib, cubemap_lib); DRW_SHADER_LIB_ADD(e_data.lib, raytrace_lib); DRW_SHADER_LIB_ADD(e_data.lib, ambient_occlusion_lib); DRW_SHADER_LIB_ADD(e_data.lib, octahedron_lib); DRW_SHADER_LIB_ADD(e_data.lib, irradiance_lib); DRW_SHADER_LIB_ADD(e_data.lib, lightprobe_lib); DRW_SHADER_LIB_ADD(e_data.lib, ltc_lib); DRW_SHADER_LIB_ADD(e_data.lib, lights_lib); DRW_SHADER_LIB_ADD(e_data.lib, surface_lib); DRW_SHADER_LIB_ADD(e_data.lib, volumetric_lib); DRW_SHADER_LIB_ADD(e_data.lib, ssr_lib); DRW_SHADER_LIB_ADD(e_data.lib, effect_dof_lib); DRW_SHADER_LIB_ADD(e_data.lib, effect_reflection_lib); DRW_SHADER_LIB_ADD(e_data.lib, closure_type_lib); DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_lib); DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_diffuse_lib); 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); DRW_SHADER_LIB_ADD(e_data.lib, cryptomatte_lib); DRW_SHADER_LIB_ADD(e_data.lib, surface_vert); e_data.surface_lit_frag = DRW_shader_library_create_shader_string(e_data.lib, datatoc_surface_frag_glsl); e_data.surface_prepass_frag = DRW_shader_library_create_shader_string( e_data.lib, datatoc_prepass_frag_glsl); e_data.surface_geom_barycentric = DRW_shader_library_create_shader_string( e_data.lib, datatoc_surface_geom_glsl); } } void EEVEE_shaders_material_shaders_init(void) { eevee_shader_extra_init(); eevee_shader_library_ensure(); } DRWShaderLibrary *EEVEE_shader_lib_get(void) { eevee_shader_library_ensure(); return e_data.lib; } GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void) { if (e_data.probe_filter_glossy_sh == NULL) { e_data.probe_filter_glossy_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_lightprobe_filter_glossy_frag_glsl, e_data.lib, filter_defines); } return e_data.probe_filter_glossy_sh; } GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void) { if (e_data.probe_filter_diffuse_sh == NULL) { e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_lightprobe_filter_diffuse_frag_glsl, e_data.lib, filter_defines); } return e_data.probe_filter_diffuse_sh; } GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void) { if (e_data.probe_filter_visibility_sh == NULL) { e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_lightprobe_filter_visibility_frag_glsl, e_data.lib, filter_defines); } return e_data.probe_filter_visibility_sh; } GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void) { if (e_data.probe_grid_fill_sh == NULL) { e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_lightprobe_grid_fill_frag_glsl, e_data.lib, filter_defines); } return e_data.probe_grid_fill_sh; } GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void) { if (e_data.probe_planar_downsample_sh == NULL) { e_data.probe_planar_downsample_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_planar_downsample_vert_glsl, datatoc_lightprobe_planar_downsample_geom_glsl, datatoc_lightprobe_planar_downsample_frag_glsl, e_data.lib, NULL); } return e_data.probe_planar_downsample_sh; } GPUShader *EEVEE_shaders_studiolight_probe_sh_get(void) { if (e_data.studiolight_probe_sh == NULL) { e_data.studiolight_probe_sh = DRW_shader_create_with_shaderlib(datatoc_background_vert_glsl, NULL, datatoc_lookdev_world_frag_glsl, e_data.lib, SHADER_DEFINES); } return e_data.studiolight_probe_sh; } GPUShader *EEVEE_shaders_studiolight_background_sh_get(void) { if (e_data.studiolight_background_sh == NULL) { e_data.studiolight_background_sh = DRW_shader_create_with_shaderlib( datatoc_background_vert_glsl, NULL, datatoc_lookdev_world_frag_glsl, e_data.lib, "#define LOOKDEV_BG\n" SHADER_DEFINES); } return e_data.studiolight_background_sh; } GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void) { if (e_data.probe_cube_display_sh == NULL) { e_data.probe_cube_display_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_cube_display_vert_glsl, NULL, datatoc_lightprobe_cube_display_frag_glsl, e_data.lib, SHADER_DEFINES); } return e_data.probe_cube_display_sh; } GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void) { if (e_data.probe_grid_display_sh == NULL) { e_data.probe_grid_display_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_grid_display_vert_glsl, NULL, datatoc_lightprobe_grid_display_frag_glsl, e_data.lib, filter_defines); } return e_data.probe_grid_display_sh; } GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void) { if (e_data.probe_planar_display_sh == NULL) { e_data.probe_planar_display_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_planar_display_vert_glsl, NULL, datatoc_lightprobe_planar_display_frag_glsl, e_data.lib, NULL); } return e_data.probe_planar_display_sh; } /* -------------------------------------------------------------------- */ /** \name Down-sampling * \{ */ GPUShader *EEVEE_shaders_effect_color_copy_sh_get(void) { if (e_data.color_copy_sh == NULL) { e_data.color_copy_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_downsample_frag_glsl, e_data.lib, "#define COPY_SRC\n"); } return e_data.color_copy_sh; } GPUShader *EEVEE_shaders_effect_downsample_sh_get(void) { if (e_data.downsample_sh == NULL) { e_data.downsample_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_downsample_frag_glsl, e_data.lib, NULL); } return e_data.downsample_sh; } GPUShader *EEVEE_shaders_effect_downsample_cube_sh_get(void) { if (e_data.downsample_cube_sh == NULL) { e_data.downsample_cube_sh = DRW_shader_create_with_shaderlib( datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_effect_downsample_cube_frag_glsl, e_data.lib, NULL); } return e_data.downsample_cube_sh; } GPUShader *EEVEE_shaders_effect_minz_downlevel_sh_get(void) { if (e_data.minz_downlevel_sh == NULL) { e_data.minz_downlevel_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n"); } return e_data.minz_downlevel_sh; } GPUShader *EEVEE_shaders_effect_maxz_downlevel_sh_get(void) { if (e_data.maxz_downlevel_sh == NULL) { e_data.maxz_downlevel_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n"); } return e_data.maxz_downlevel_sh; } GPUShader *EEVEE_shaders_effect_minz_downdepth_sh_get(void) { if (e_data.minz_downdepth_sh == NULL) { e_data.minz_downdepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n"); } return e_data.minz_downdepth_sh; } GPUShader *EEVEE_shaders_effect_maxz_downdepth_sh_get(void) { if (e_data.maxz_downdepth_sh == NULL) { e_data.maxz_downdepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n"); } return e_data.maxz_downdepth_sh; } GPUShader *EEVEE_shaders_effect_minz_downdepth_layer_sh_get(void) { if (e_data.minz_downdepth_layer_sh == NULL) { e_data.minz_downdepth_layer_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n" "#define LAYERED\n"); } return e_data.minz_downdepth_layer_sh; } GPUShader *EEVEE_shaders_effect_maxz_downdepth_layer_sh_get(void) { if (e_data.maxz_downdepth_layer_sh == NULL) { e_data.maxz_downdepth_layer_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n" "#define LAYERED\n"); } return e_data.maxz_downdepth_layer_sh; } GPUShader *EEVEE_shaders_effect_maxz_copydepth_layer_sh_get(void) { if (e_data.maxz_copydepth_layer_sh == NULL) { e_data.maxz_copydepth_layer_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n" "#define COPY_DEPTH\n" "#define LAYERED\n"); } return e_data.maxz_copydepth_layer_sh; } GPUShader *EEVEE_shaders_effect_minz_copydepth_sh_get(void) { if (e_data.minz_copydepth_sh == NULL) { e_data.minz_copydepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n" "#define COPY_DEPTH\n"); } return e_data.minz_copydepth_sh; } GPUShader *EEVEE_shaders_effect_maxz_copydepth_sh_get(void) { if (e_data.maxz_copydepth_sh == NULL) { e_data.maxz_copydepth_sh = DRW_shader_create_fullscreen(datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n" "#define COPY_DEPTH\n"); } return e_data.maxz_copydepth_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name GGX LUT * \{ */ GPUShader *EEVEE_shaders_ggx_lut_sh_get(void) { if (e_data.ggx_lut_sh == NULL) { e_data.ggx_lut_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_bsdf_lut_frag_glsl, e_data.lib, NULL); } return e_data.ggx_lut_sh; } GPUShader *EEVEE_shaders_ggx_refraction_lut_sh_get(void) { if (e_data.ggx_refraction_lut_sh == NULL) { e_data.ggx_refraction_lut_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_btdf_lut_frag_glsl, e_data.lib, NULL); } return e_data.ggx_refraction_lut_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Mist * \{ */ GPUShader *EEVEE_shaders_effect_mist_sh_get(void) { if (e_data.mist_sh == NULL) { e_data.mist_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_mist_frag_glsl, e_data.lib, "#define FIRST_PASS\n"); } return e_data.mist_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Motion Blur * \{ */ #define TILE_SIZE_STR "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n" GPUShader *EEVEE_shaders_effect_motion_blur_sh_get(void) { if (e_data.motion_blur_sh == NULL) { e_data.motion_blur_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_motion_blur_frag_glsl, e_data.lib, TILE_SIZE_STR); } return e_data.motion_blur_sh; } GPUShader *EEVEE_shaders_effect_motion_blur_object_sh_get(void) { if (e_data.motion_blur_object_sh == NULL) { e_data.motion_blur_object_sh = DRW_shader_create_with_shaderlib( datatoc_object_motion_vert_glsl, NULL, datatoc_object_motion_frag_glsl, e_data.lib, NULL); } return e_data.motion_blur_object_sh; } GPUShader *EEVEE_shaders_effect_motion_blur_hair_sh_get(void) { if (e_data.motion_blur_hair_sh == NULL) { e_data.motion_blur_hair_sh = DRW_shader_create_with_shaderlib(datatoc_object_motion_vert_glsl, NULL, datatoc_object_motion_frag_glsl, e_data.lib, "#define HAIR\n"); } return e_data.motion_blur_hair_sh; } GPUShader *EEVEE_shaders_effect_motion_blur_velocity_tiles_sh_get(void) { if (e_data.velocity_tiles_sh == NULL) { e_data.velocity_tiles_sh = DRW_shader_create_fullscreen(datatoc_effect_velocity_tile_frag_glsl, "#define TILE_GATHER\n" TILE_SIZE_STR); } return e_data.velocity_tiles_sh; } GPUShader *EEVEE_shaders_effect_motion_blur_velocity_tiles_expand_sh_get(void) { if (e_data.velocity_tiles_expand_sh == NULL) { e_data.velocity_tiles_expand_sh = DRW_shader_create_fullscreen( datatoc_effect_velocity_tile_frag_glsl, "#define TILE_EXPANSION\n" TILE_SIZE_STR); } return e_data.velocity_tiles_expand_sh; } #undef TILE_SIZE_STR /** \} */ /* -------------------------------------------------------------------- */ /** \name Ambient Occlusion * \{ */ GPUShader *EEVEE_shaders_effect_ambient_occlusion_sh_get(void) { if (e_data.gtao_sh == NULL) { e_data.gtao_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_gtao_frag_glsl, e_data.lib, NULL); } return e_data.gtao_sh; } GPUShader *EEVEE_shaders_effect_ambient_occlusion_debug_sh_get(void) { if (e_data.gtao_debug_sh == NULL) { e_data.gtao_debug_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_gtao_frag_glsl, e_data.lib, "#define DEBUG_AO\n" "#define ENABLE_DEFERED_AO"); } return e_data.gtao_debug_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Render Passes * \{ */ GPUShader *EEVEE_shaders_renderpasses_post_process_sh_get(void) { if (e_data.postprocess_sh == NULL) { e_data.postprocess_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_renderpass_postprocess_frag_glsl, e_data.lib, NULL); } return e_data.postprocess_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Cryptomatte * \{ */ GPUShader *EEVEE_shaders_cryptomatte_sh_get(bool is_hair) { const int index = is_hair ? 1 : 0; if (e_data.cryptomatte_sh[index] == NULL) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, SHADER_DEFINES); BLI_dynstr_append(ds, "#define attrib_load() \n"); if (is_hair) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } else { BLI_dynstr_append(ds, "#define MESH_SHADER\n"); } char *defines = BLI_dynstr_get_cstring(ds); e_data.cryptomatte_sh[index] = DRW_shader_create_with_shaderlib( datatoc_cryptomatte_vert_glsl, NULL, datatoc_cryptomatte_frag_glsl, e_data.lib, defines); BLI_dynstr_free(ds); MEM_freeN(defines); } return e_data.cryptomatte_sh[index]; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Raytraced Reflections * \{ */ struct GPUShader *EEVEE_shaders_effect_reflection_trace_sh_get(void) { if (e_data.reflection_trace == NULL) { e_data.reflection_trace = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_reflection_trace_frag_glsl, e_data.lib, SHADER_DEFINES "#define STEP_RAYTRACE\n"); } return e_data.reflection_trace; } struct GPUShader *EEVEE_shaders_effect_reflection_resolve_sh_get(void) { if (e_data.reflection_resolve == NULL) { e_data.reflection_resolve = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_reflection_resolve_frag_glsl, e_data.lib, SHADER_DEFINES "#define STEP_RESOLVE\n"); } return e_data.reflection_resolve; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Shadows * \{ */ struct GPUShader *EEVEE_shaders_shadow_sh_get() { if (e_data.shadow_sh == NULL) { e_data.shadow_sh = DRW_shader_create_with_shaderlib( datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, e_data.lib, NULL); } return e_data.shadow_sh; } struct GPUShader *EEVEE_shaders_shadow_accum_sh_get() { if (e_data.shadow_accum_sh == NULL) { e_data.shadow_accum_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_shadow_accum_frag_glsl, e_data.lib, SHADER_DEFINES); } return e_data.shadow_accum_sh; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Subsurface * \{ */ struct GPUShader *EEVEE_shaders_subsurface_first_pass_sh_get() { if (e_data.sss_sh[0] == NULL) { e_data.sss_sh[0] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_subsurface_frag_glsl, e_data.lib, "#define FIRST_PASS\n"); } return e_data.sss_sh[0]; } struct GPUShader *EEVEE_shaders_subsurface_second_pass_sh_get() { if (e_data.sss_sh[1] == NULL) { e_data.sss_sh[1] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_subsurface_frag_glsl, e_data.lib, "#define SECOND_PASS\n"); } return e_data.sss_sh[1]; } struct GPUShader *EEVEE_shaders_subsurface_translucency_sh_get() { if (e_data.sss_sh[2] == NULL) { e_data.sss_sh[2] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_translucency_frag_glsl, e_data.lib, "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES); } return e_data.sss_sh[2]; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Volumes * \{ */ struct GPUShader *EEVEE_shaders_volumes_clear_sh_get() { if (e_data.volumetric_clear_sh == NULL) { e_data.volumetric_clear_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, datatoc_volumetric_frag_glsl, e_data.lib, SHADER_DEFINES "#define STANDALONE\n" "#define VOLUMETRICS\n" "#define CLEAR\n"); } return e_data.volumetric_clear_sh; } struct GPUShader *EEVEE_shaders_volumes_scatter_sh_get() { if (e_data.scatter_sh == NULL) { e_data.scatter_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, datatoc_volumetric_scatter_frag_glsl, e_data.lib, SHADER_DEFINES "#define STANDALONE\n" "#define VOLUMETRICS\n" "#define VOLUME_SHADOW\n"); } return e_data.scatter_sh; } struct GPUShader *EEVEE_shaders_volumes_scatter_with_lights_sh_get() { if (e_data.scatter_with_lights_sh == NULL) { e_data.scatter_with_lights_sh = DRW_shader_create_with_shaderlib( datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, datatoc_volumetric_scatter_frag_glsl, e_data.lib, SHADER_DEFINES "#define STANDALONE\n" "#define VOLUMETRICS\n" "#define VOLUME_LIGHTING\n" "#define VOLUME_SHADOW\n"); } return e_data.scatter_with_lights_sh; } struct GPUShader *EEVEE_shaders_volumes_integration_sh_get() { if (e_data.volumetric_integration_sh == NULL) { e_data.volumetric_integration_sh = DRW_shader_create_with_shaderlib( datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, datatoc_volumetric_integration_frag_glsl, e_data.lib, USE_VOLUME_OPTI ? "#define USE_VOLUME_OPTI\n" "#define STANDALONE\n" SHADER_DEFINES : "#define STANDALONE\n" SHADER_DEFINES); } return e_data.volumetric_integration_sh; } struct GPUShader *EEVEE_shaders_volumes_resolve_sh_get(bool accum) { const int index = accum ? 1 : 0; if (e_data.volumetric_resolve_sh[index] == NULL) { e_data.volumetric_resolve_sh[index] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_volumetric_resolve_frag_glsl, e_data.lib, accum ? "#define VOLUMETRICS_ACCUM\n" SHADER_DEFINES : SHADER_DEFINES); } return e_data.volumetric_resolve_sh[index]; } struct GPUShader *EEVEE_shaders_volumes_accum_sh_get() { if (e_data.volumetric_accum_sh == NULL) { e_data.volumetric_accum_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_volumetric_accum_frag_glsl, e_data.lib, SHADER_DEFINES); } return e_data.volumetric_accum_sh; } /** \} */ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void) { if (e_data.velocity_resolve_sh == NULL) { e_data.velocity_resolve_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_velocity_resolve_frag_glsl, e_data.lib, NULL); } return e_data.velocity_resolve_sh; } GPUShader *EEVEE_shaders_update_noise_sh_get(void) { if (e_data.update_noise_sh == NULL) { e_data.update_noise_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_update_noise_frag_glsl, e_data.lib, NULL); } return e_data.update_noise_sh; } GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects) { GPUShader **sh; const char *define = NULL; if (enabled_effects & EFFECT_TAA_REPROJECT) { sh = &e_data.taa_resolve_reproject_sh; define = "#define USE_REPROJECTION\n"; } else { sh = &e_data.taa_resolve_sh; } if (*sh == NULL) { *sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_temporal_aa_glsl, e_data.lib, define); } return *sh; } /* -------------------------------------------------------------------- */ /** \name Bloom * \{ */ GPUShader *EEVEE_shaders_bloom_blit_get(bool high_quality) { int index = high_quality ? 1 : 0; if (e_data.bloom_blit_sh[index] == NULL) { const char *define = high_quality ? "#define STEP_BLIT\n" "#define HIGH_QUALITY\n" : "#define STEP_BLIT\n"; e_data.bloom_blit_sh[index] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_bloom_frag_glsl, e_data.lib, define); } return e_data.bloom_blit_sh[index]; } GPUShader *EEVEE_shaders_bloom_downsample_get(bool high_quality) { int index = high_quality ? 1 : 0; if (e_data.bloom_downsample_sh[index] == NULL) { const char *define = high_quality ? "#define STEP_DOWNSAMPLE\n" "#define HIGH_QUALITY\n" : "#define STEP_DOWNSAMPLE\n"; e_data.bloom_downsample_sh[index] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_bloom_frag_glsl, e_data.lib, define); } return e_data.bloom_downsample_sh[index]; } GPUShader *EEVEE_shaders_bloom_upsample_get(bool high_quality) { int index = high_quality ? 1 : 0; if (e_data.bloom_upsample_sh[index] == NULL) { const char *define = high_quality ? "#define STEP_UPSAMPLE\n" "#define HIGH_QUALITY\n" : "#define STEP_UPSAMPLE\n"; e_data.bloom_upsample_sh[index] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_bloom_frag_glsl, e_data.lib, define); } return e_data.bloom_upsample_sh[index]; } GPUShader *EEVEE_shaders_bloom_resolve_get(bool high_quality) { int index = high_quality ? 1 : 0; if (e_data.bloom_resolve_sh[index] == NULL) { const char *define = high_quality ? "#define STEP_RESOLVE\n" "#define HIGH_QUALITY\n" : "#define STEP_RESOLVE\n"; e_data.bloom_resolve_sh[index] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_bloom_frag_glsl, e_data.lib, define); } return e_data.bloom_resolve_sh[index]; } /** \} */ /* -------------------------------------------------------------------- */ /** \name Depth of field * \{ */ GPUShader *EEVEE_shaders_depth_of_field_bokeh_get(void) { if (e_data.dof_bokeh_sh == NULL) { e_data.dof_bokeh_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_bokeh_frag_glsl, e_data.lib, DOF_SHADER_DEFINES); } return e_data.dof_bokeh_sh; } GPUShader *EEVEE_shaders_depth_of_field_setup_get(void) { if (e_data.dof_setup_sh == NULL) { e_data.dof_setup_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_setup_frag_glsl, e_data.lib, DOF_SHADER_DEFINES); } return e_data.dof_setup_sh; } GPUShader *EEVEE_shaders_depth_of_field_flatten_tiles_get(void) { if (e_data.dof_flatten_tiles_sh == NULL) { e_data.dof_flatten_tiles_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_flatten_tiles_frag_glsl, e_data.lib, DOF_SHADER_DEFINES); } return e_data.dof_flatten_tiles_sh; } GPUShader *EEVEE_shaders_depth_of_field_dilate_tiles_get(bool b_pass) { int pass = b_pass; if (e_data.dof_dilate_tiles_sh[pass] == NULL) { e_data.dof_dilate_tiles_sh[pass] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_dilate_tiles_frag_glsl, e_data.lib, (pass == 0) ? DOF_SHADER_DEFINES "#define DILATE_MODE_MIN_MAX\n" : DOF_SHADER_DEFINES "#define DILATE_MODE_MIN_ABS\n"); } return e_data.dof_dilate_tiles_sh[pass]; } GPUShader *EEVEE_shaders_depth_of_field_downsample_get(void) { if (e_data.dof_downsample_sh == NULL) { e_data.dof_downsample_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_downsample_frag_glsl, e_data.lib, DOF_SHADER_DEFINES); } return e_data.dof_downsample_sh; } GPUShader *EEVEE_shaders_depth_of_field_reduce_get(bool b_is_copy_pass) { int is_copy_pass = b_is_copy_pass; if (e_data.dof_reduce_sh[is_copy_pass] == NULL) { e_data.dof_reduce_sh[is_copy_pass] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_reduce_frag_glsl, e_data.lib, (is_copy_pass) ? DOF_SHADER_DEFINES "#define COPY_PASS\n" : DOF_SHADER_DEFINES "#define REDUCE_PASS\n"); } return e_data.dof_reduce_sh[is_copy_pass]; } GPUShader *EEVEE_shaders_depth_of_field_gather_get(EEVEE_DofGatherPass pass, bool b_use_bokeh_tx) { int use_bokeh_tx = b_use_bokeh_tx; if (e_data.dof_gather_sh[pass][use_bokeh_tx] == NULL) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, DOF_SHADER_DEFINES); switch (pass) { case DOF_GATHER_FOREGROUND: BLI_dynstr_append(ds, "#define DOF_FOREGROUND_PASS\n"); break; case DOF_GATHER_BACKGROUND: BLI_dynstr_append(ds, "#define DOF_BACKGROUND_PASS\n"); break; case DOF_GATHER_HOLEFILL: BLI_dynstr_append(ds, "#define DOF_BACKGROUND_PASS\n" "#define DOF_HOLEFILL_PASS\n"); break; default: break; } if (use_bokeh_tx) { BLI_dynstr_append(ds, "#define DOF_BOKEH_TEXTURE\n"); } char *define = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); e_data.dof_gather_sh[pass][use_bokeh_tx] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_gather_frag_glsl, e_data.lib, define); MEM_freeN(define); } return e_data.dof_gather_sh[pass][use_bokeh_tx]; } GPUShader *EEVEE_shaders_depth_of_field_filter_get(void) { if (e_data.dof_filter_sh == NULL) { e_data.dof_filter_sh = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_filter_frag_glsl, e_data.lib, DOF_SHADER_DEFINES); } return e_data.dof_filter_sh; } GPUShader *EEVEE_shaders_depth_of_field_scatter_get(bool b_is_foreground, bool b_use_bokeh_tx) { int is_foreground = b_is_foreground; int use_bokeh_tx = b_use_bokeh_tx; if (e_data.dof_scatter_sh[is_foreground][use_bokeh_tx] == NULL) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, DOF_SHADER_DEFINES); BLI_dynstr_append( ds, (is_foreground) ? "#define DOF_FOREGROUND_PASS\n" : "#define DOF_BACKGROUND_PASS\n"); if (use_bokeh_tx) { BLI_dynstr_append(ds, "#define DOF_BOKEH_TEXTURE\n"); } char *define = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); e_data.dof_scatter_sh[is_foreground][use_bokeh_tx] = DRW_shader_create_with_shaderlib( datatoc_effect_dof_scatter_vert_glsl, NULL, datatoc_effect_dof_scatter_frag_glsl, e_data.lib, define); MEM_freeN(define); } return e_data.dof_scatter_sh[is_foreground][use_bokeh_tx]; } GPUShader *EEVEE_shaders_depth_of_field_resolve_get(bool b_use_bokeh_tx, bool b_use_hq_gather) { int use_hq_gather = b_use_hq_gather; int use_bokeh_tx = b_use_bokeh_tx; if (e_data.dof_resolve_sh[use_bokeh_tx][use_hq_gather] == NULL) { DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, DOF_SHADER_DEFINES); BLI_dynstr_append(ds, "#define DOF_RESOLVE_PASS\n"); if (use_bokeh_tx) { BLI_dynstr_append(ds, "#define DOF_BOKEH_TEXTURE\n"); } BLI_dynstr_appendf(ds, "#define DOF_SLIGHT_FOCUS_DENSITY %d\n", use_hq_gather ? 4 : 2); char *define = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); e_data.dof_resolve_sh[use_bokeh_tx][use_hq_gather] = DRW_shader_create_fullscreen_with_shaderlib( datatoc_effect_dof_resolve_frag_glsl, e_data.lib, define); MEM_freeN(define); } return e_data.dof_resolve_sh[use_bokeh_tx][use_hq_gather]; } /** \} */ Material *EEVEE_material_default_diffuse_get(void) { if (!e_data.diffuse_mat) { Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse"); bNodeTree *ntree = ntreeAddTreeEmbedded( NULL, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); ma->use_nodes = true; bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE); bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color"); copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f); bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); nodeAddLink(ntree, bsdf, nodeFindSocket(bsdf, SOCK_OUT, "BSDF"), output, nodeFindSocket(output, SOCK_IN, "Surface")); nodeSetActive(ntree, output); e_data.diffuse_mat = ma; } return e_data.diffuse_mat; } Material *EEVEE_material_default_glossy_get(void) { if (!e_data.glossy_mat) { Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal"); bNodeTree *ntree = ntreeAddTreeEmbedded( NULL, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); ma->use_nodes = true; bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY); bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color"); copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f); bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness"); ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f; bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); nodeAddLink(ntree, bsdf, nodeFindSocket(bsdf, SOCK_OUT, "BSDF"), output, nodeFindSocket(output, SOCK_IN, "Surface")); nodeSetActive(ntree, output); e_data.glossy_mat = ma; } return e_data.glossy_mat; } Material *EEVEE_material_default_error_get(void) { if (!e_data.error_mat) { Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default error"); bNodeTree *ntree = ntreeAddTreeEmbedded( NULL, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); ma->use_nodes = true; /* Use emission and output material to be compatible with both World and Material. */ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color"); copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f); bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); nodeAddLink(ntree, bsdf, nodeFindSocket(bsdf, SOCK_OUT, "Emission"), output, nodeFindSocket(output, SOCK_IN, "Surface")); nodeSetActive(ntree, output); e_data.error_mat = ma; } return e_data.error_mat; } struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma) { /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */ if (!e_data.surface.ntree) { bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED); bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF"); bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface"); nodeAddLink(ntree, bsdf, bsdf_out, output, output_in); nodeSetActive(ntree, output); e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value; e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value; e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value; e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value; e_data.surface.ntree = ntree; } /* Update */ copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b); e_data.surface.metallic_socket->value = ma->metallic; e_data.surface.roughness_socket->value = ma->roughness; e_data.surface.specular_socket->value = ma->spec; return e_data.surface.ntree; } struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo) { /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */ if (!e_data.world.ntree) { bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND); bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD); bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background"); bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface"); nodeAddLink(ntree, bg, bg_out, output, output_in); nodeSetActive(ntree, output); e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value; e_data.world.ntree = ntree; } copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb); return e_data.world.ntree; } World *EEVEE_world_default_get(void) { if (e_data.default_world == NULL) { e_data.default_world = BKE_id_new_nomain(ID_WO, "EEVEEE default world"); copy_v3_fl(&e_data.default_world->horr, 0.0f); e_data.default_world->use_nodes = 0; e_data.default_world->nodetree = NULL; BLI_listbase_clear(&e_data.default_world->gpumaterial); } return e_data.default_world; } static char *eevee_get_defines(int options) { char *str = NULL; DynStr *ds = BLI_dynstr_new(); BLI_dynstr_append(ds, SHADER_DEFINES); if ((options & VAR_WORLD_BACKGROUND) != 0) { BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n"); } if ((options & VAR_MAT_VOLUME) != 0) { BLI_dynstr_append(ds, "#define VOLUMETRICS\n"); } if ((options & VAR_MAT_MESH) != 0) { BLI_dynstr_append(ds, "#define MESH_SHADER\n"); } if ((options & VAR_MAT_DEPTH) != 0) { BLI_dynstr_append(ds, "#define DEPTH_SHADER\n"); } if ((options & VAR_MAT_HAIR) != 0) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } if ((options & VAR_MAT_POINTCLOUD) != 0) { BLI_dynstr_append(ds, "#define POINTCLOUD_SHADER\n"); } if ((options & VAR_WORLD_PROBE) != 0) { BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n"); } if ((options & VAR_MAT_HASH) != 0) { BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n"); } if ((options & VAR_MAT_BLEND) != 0) { BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n"); } if ((options & VAR_MAT_REFRACT) != 0) { BLI_dynstr_append(ds, "#define USE_REFRACTION\n"); } if ((options & VAR_MAT_LOOKDEV) != 0) { BLI_dynstr_append(ds, "#define LOOKDEV\n"); } if ((options & VAR_MAT_HOLDOUT) != 0) { BLI_dynstr_append(ds, "#define HOLDOUT\n"); } str = BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); return str; } static char *eevee_get_vert(int options) { char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { str = 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_world_vert_glsl); } else { str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_surface_vert_glsl); } return str; } static char *eevee_get_geom(int options) { char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_geom_glsl); } return str; } static char *eevee_get_frag(int options) { char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_frag_glsl); } else if ((options & VAR_MAT_DEPTH) != 0) { str = BLI_strdup(e_data.surface_prepass_frag); } else { str = BLI_strdup(e_data.surface_lit_frag); } return str; } static void eevee_material_post_eval(void *UNUSED(thunk), GPUMaterial *mat, GPUCodegenOutput *codegen) { uint64_t options = GPU_material_uuid_get(mat); 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 *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; GPUMaterial *mat = NULL; GPUCodegenCallbackFn cbfn = &eevee_material_post_eval; if (ma) { bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma); 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_from_world(wo, ntree, options, is_volume, deferred, cbfn, NULL); } return mat; } struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options) { Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() : BKE_material_default_surface(); BLI_assert(def_ma->use_nodes && def_ma->nodetree); return eevee_material_get_ex(scene, def_ma, NULL, options, false); } struct GPUMaterial *EEVEE_material_get( EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options) { if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) { options |= VAR_DEFAULT; } /* Meh, implicit option. World probe cannot be deferred because they need * to be rendered immediately. */ const bool deferred = (options & VAR_WORLD_PROBE) == 0; GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred); int status = GPU_material_status(mat); /* Return null material and bypass drawing for volume shaders. */ if ((options & VAR_MAT_VOLUME) && status != GPU_MAT_SUCCESS) { return NULL; } switch (status) { case GPU_MAT_SUCCESS: break; case GPU_MAT_QUEUED: vedata->stl->g_data->queued_shaders_count++; mat = EEVEE_material_default_get(scene, ma, options); break; case GPU_MAT_FAILED: default: ma = EEVEE_material_default_error_get(); mat = eevee_material_get_ex(scene, ma, NULL, options, false); break; } /* Returned material should be ready to be drawn. */ BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS); return mat; } void EEVEE_shaders_free(void) { 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); DRW_SHADER_FREE_SAFE(e_data.lookdev_background); DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_SHADER_FREE_SAFE(e_data.color_copy_sh); DRW_SHADER_FREE_SAFE(e_data.downsample_sh); DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh); DRW_SHADER_FREE_SAFE(e_data.minz_downlevel_sh); DRW_SHADER_FREE_SAFE(e_data.maxz_downlevel_sh); DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_sh); DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_sh); DRW_SHADER_FREE_SAFE(e_data.minz_downdepth_layer_sh); DRW_SHADER_FREE_SAFE(e_data.maxz_downdepth_layer_sh); DRW_SHADER_FREE_SAFE(e_data.maxz_copydepth_layer_sh); DRW_SHADER_FREE_SAFE(e_data.minz_copydepth_sh); DRW_SHADER_FREE_SAFE(e_data.maxz_copydepth_sh); DRW_SHADER_FREE_SAFE(e_data.ggx_lut_sh); DRW_SHADER_FREE_SAFE(e_data.ggx_refraction_lut_sh); DRW_SHADER_FREE_SAFE(e_data.mist_sh); DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh); DRW_SHADER_FREE_SAFE(e_data.motion_blur_object_sh); DRW_SHADER_FREE_SAFE(e_data.motion_blur_hair_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_tiles_expand_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_layer_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_sh); DRW_SHADER_FREE_SAFE(e_data.shadow_accum_sh); DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]); DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]); DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]); DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh); DRW_SHADER_FREE_SAFE(e_data.scatter_sh); DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh[0]); DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh[1]); DRW_SHADER_FREE_SAFE(e_data.volumetric_accum_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_visibility_sh); DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh); DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh); DRW_SHADER_FREE_SAFE(e_data.studiolight_probe_sh); DRW_SHADER_FREE_SAFE(e_data.studiolight_background_sh); DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh); DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh); DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh); DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh); DRW_SHADER_FREE_SAFE(e_data.dof_bokeh_sh); DRW_SHADER_FREE_SAFE(e_data.dof_setup_sh); DRW_SHADER_FREE_SAFE(e_data.dof_flatten_tiles_sh); DRW_SHADER_FREE_SAFE(e_data.dof_dilate_tiles_sh[0]); DRW_SHADER_FREE_SAFE(e_data.dof_dilate_tiles_sh[1]); DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh); DRW_SHADER_FREE_SAFE(e_data.dof_reduce_sh[0]); DRW_SHADER_FREE_SAFE(e_data.dof_reduce_sh[1]); for (int i = 0; i < DOF_GATHER_MAX_PASS; i++) { DRW_SHADER_FREE_SAFE(e_data.dof_gather_sh[i][0]); DRW_SHADER_FREE_SAFE(e_data.dof_gather_sh[i][1]); } DRW_SHADER_FREE_SAFE(e_data.dof_filter_sh); DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh[0][0]); DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh[0][1]); DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh[1][0]); DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh[1][1]); DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh[0][0]); DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh[0][1]); DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh[1][0]); DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh[1][1]); DRW_SHADER_FREE_SAFE(e_data.cryptomatte_sh[0]); DRW_SHADER_FREE_SAFE(e_data.cryptomatte_sh[1]); for (int i = 0; i < 2; i++) { DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[i]); DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[i]); DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[i]); DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[i]); } DRW_SHADER_FREE_SAFE(e_data.reflection_trace); DRW_SHADER_FREE_SAFE(e_data.reflection_resolve); DRW_SHADER_LIB_FREE_SAFE(e_data.lib); if (e_data.default_world) { BKE_id_free(NULL, e_data.default_world); e_data.default_world = NULL; } if (e_data.glossy_mat) { BKE_id_free(NULL, e_data.glossy_mat); e_data.glossy_mat = NULL; } if (e_data.diffuse_mat) { BKE_id_free(NULL, e_data.diffuse_mat); e_data.diffuse_mat = NULL; } if (e_data.error_mat) { BKE_id_free(NULL, e_data.error_mat); e_data.error_mat = NULL; } if (e_data.surface.ntree) { ntreeFreeEmbeddedTree(e_data.surface.ntree); MEM_freeN(e_data.surface.ntree); e_data.surface.ntree = NULL; } if (e_data.world.ntree) { ntreeFreeEmbeddedTree(e_data.world.ntree); MEM_freeN(e_data.world.ntree); e_data.world.ntree = NULL; } }