diff options
Diffstat (limited to 'source/blender/draw')
184 files changed, 3642 insertions, 3408 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 1ddae11999b..f85b03dc517 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -64,6 +64,7 @@ set(SRC intern/draw_color_management.c intern/draw_common.c intern/draw_debug.c + intern/draw_fluid.c intern/draw_hair.c intern/draw_instance_data.c intern/draw_manager.c @@ -143,12 +144,12 @@ set(SRC engines/overlay/overlay_outline.c engines/overlay/overlay_paint.c engines/overlay/overlay_particle.c - engines/overlay/overlay_pointcloud.c engines/overlay/overlay_sculpt.c engines/overlay/overlay_shader.c engines/overlay/overlay_wireframe.c DRW_engine.h + DRW_engine_types.h DRW_select_buffer.h intern/DRW_render.h intern/draw_cache.h @@ -186,11 +187,10 @@ set(LIB ) data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC) -data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC) -data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC) -data_to_c_simple(engines/eevee/shaders/concentric_samples_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/closure_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/common_uniforms_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/common_utiltex_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lights_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC) @@ -205,8 +205,8 @@ data_to_c_simple(engines/eevee/shaders/lightprobe_grid_display_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_grid_fill_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/lightprobe_planar_display_vert.glsl SRC) -data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC) -data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/lookdev_world_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/closure_lit_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_bloom_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) @@ -230,7 +230,6 @@ data_to_c_simple(engines/eevee/shaders/object_motion_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_accum_frag.glsl SRC) - data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC) @@ -241,9 +240,14 @@ data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/cubemap_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/renderpass_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/surface_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/surface_geom.glsl SRC) +data_to_c_simple(engines/eevee/shaders/surface_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/surface_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/volumetric_accum_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC) @@ -271,6 +275,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_material_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_merge_infront_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_hair_vert.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_shader_interface_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_shadow_caps_geom.glsl SRC) @@ -285,8 +290,11 @@ data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC) data_to_c_simple(intern/shaders/common_colormanagement_lib.glsl SRC) data_to_c_simple(intern/shaders/common_globals_lib.glsl SRC) +data_to_c_simple(intern/shaders/common_pointcloud_lib.glsl SRC) data_to_c_simple(intern/shaders/common_hair_lib.glsl SRC) data_to_c_simple(intern/shaders/common_hair_refine_vert.glsl SRC) +data_to_c_simple(intern/shaders/common_math_lib.glsl SRC) +data_to_c_simple(intern/shaders/common_math_geom_lib.glsl SRC) data_to_c_simple(intern/shaders/common_view_lib.glsl SRC) data_to_c_simple(intern/shaders/common_fxaa_lib.glsl SRC) data_to_c_simple(intern/shaders/common_smaa_lib.glsl SRC) @@ -386,8 +394,6 @@ data_to_c_simple(engines/overlay/shaders/paint_weight_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/paint_wire_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/particle_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/particle_frag.glsl SRC) -data_to_c_simple(engines/overlay/shaders/pointcloud_vert.glsl SRC) -data_to_c_simple(engines/overlay/shaders/pointcloud_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/sculpt_mask_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC) @@ -398,6 +404,13 @@ data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC) list(APPEND INC ) +if(WITH_MOD_FLUID) + list(APPEND INC + ../../../intern/mantaflow/extern + ) + add_definitions(-DWITH_FLUID) +endif() + if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 6c835c6d7ae..6db3bb39643 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRW_ENGINE_H__ -#define __DRW_ENGINE_H__ +#pragma once #include "BLI_sys_types.h" /* for bool */ @@ -43,6 +42,7 @@ struct GPUViewport; struct ID; struct Main; struct Object; +struct Render; struct RenderEngine; struct RenderEngineType; struct Scene; @@ -137,6 +137,9 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph struct DRWInstanceDataList *DRW_instance_data_list_create(void); void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist); +void DRW_render_context_enable(struct Render *render); +void DRW_render_context_disable(struct Render *render); + void DRW_opengl_context_create(void); void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); @@ -170,5 +173,3 @@ void DRW_drawdata_free(struct ID *id); #ifdef __cplusplus } #endif - -#endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/DRW_engine_types.h b/source/blender/draw/DRW_engine_types.h index d31bab5a1b5..807f654f559 100644 --- a/source/blender/draw/DRW_engine_types.h +++ b/source/blender/draw/DRW_engine_types.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRW_ENGINE_TYPES_H__ -#define __DRW_ENGINE_TYPES_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -50,5 +49,3 @@ typedef struct DefaultTextureList { #ifdef __cplusplus } #endif - -#endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h index 66dee3a9aa9..43d4005c3a9 100644 --- a/source/blender/draw/DRW_select_buffer.h +++ b/source/blender/draw/DRW_select_buffer.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRW_SELECT_BUFFER_H__ -#define __DRW_SELECT_BUFFER_H__ +#pragma once #include "BLI_sys_types.h" /* for bool and uint */ @@ -126,5 +125,3 @@ uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, void DRW_select_buffer_context_create(struct Base **bases, const uint bases_len, short select_mode); - -#endif /* __DRW_SELECT_BUFFER_H__ */ diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 0dd3cc14234..94c380b3b50 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -165,7 +165,7 @@ static void basic_cache_populate(void *vedata, Object *ob) return; } - bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; const DRWContextState *draw_ctx = DRW_context_state_get(); if (ob != draw_ctx->object_edit) { diff --git a/source/blender/draw/engines/basic/basic_engine.h b/source/blender/draw/engines/basic/basic_engine.h index d17f1c24c37..8ace6f23cdc 100644 --- a/source/blender/draw/engines/basic/basic_engine.h +++ b/source/blender/draw/engines/basic/basic_engine.h @@ -20,9 +20,6 @@ * \ingroup draw_engine */ -#ifndef __BASIC_ENGINE_H__ -#define __BASIC_ENGINE_H__ +#pragma once extern DrawEngineType draw_engine_basic_type; - -#endif /* __BASIC_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 87948f403a0..c475e5287c2 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -28,6 +28,7 @@ #include "BLI_memblock.h" #include "BKE_duplilist.h" +#include "BKE_modifier.h" #include "DEG_depsgraph_query.h" @@ -147,28 +148,46 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData * return ob_step; } -EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, - Object *ob, - bool hair) +static EEVEE_GeometryMotionData *motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, + void *key, + bool hair) { if (mb->geom == NULL) { return NULL; } - - /* Use original data as key to ensure matching accross update. */ - Object *ob_orig = DEG_get_original_object(ob); - - void *key = (char *)ob_orig->data + hair; + key = (char *)key + (int)hair; EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key); if (geom_step == NULL) { geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__); - geom_step->type = (hair) ? EEVEE_HAIR_GEOM_MOTION_DATA : EEVEE_MESH_GEOM_MOTION_DATA; + geom_step->type = hair ? EEVEE_HAIR_GEOM_MOTION_DATA : EEVEE_MESH_GEOM_MOTION_DATA; BLI_ghash_insert(mb->geom, key, geom_step); } - return geom_step; } +EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, Object *ob) +{ + /* Use original data as key to ensure matching accross update. */ + return motion_blur_geometry_data_get(mb, DEG_get_original_object(ob)->data, false); +} + +EEVEE_GeometryMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, + Object *ob, + ModifierData *md) +{ + void *key; + if (md) { + /* Particle system. */ + key = BKE_modifier_get_original(md); + } + else { + /* Hair object. */ + key = DEG_get_original_object(ob)->data; + } + + return motion_blur_geometry_data_get(mb, key, true); +} + /* View Layer data. */ void EEVEE_view_layer_data_free(void *storage) @@ -218,6 +237,11 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) return (EEVEE_ViewLayerData *)DRW_view_layer_engine_data_get(&draw_engine_eevee_type); } +static void eevee_view_layer_init(EEVEE_ViewLayerData *sldata) +{ + sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), NULL); +} + EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer) { EEVEE_ViewLayerData **sldata = (EEVEE_ViewLayerData **)DRW_view_layer_engine_data_ensure_ex( @@ -225,6 +249,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_laye if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData"); + eevee_view_layer_init(*sldata); } return *sldata; @@ -237,6 +262,7 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void) if (*sldata == NULL) { *sldata = MEM_callocN(sizeof(**sldata), "EEVEE_ViewLayerData"); + eevee_view_layer_init(*sldata); } return *sldata; diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index 4a3cc36ddef..05cd6426911 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -54,24 +54,30 @@ extern char datatoc_common_view_lib_glsl[]; static void eevee_create_shader_depth_of_field(const bool use_alpha) { - char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl); - e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen( - frag, + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + + e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_dof_frag_glsl, + lib, use_alpha ? "#define USE_ALPHA_DOF\n" "#define STEP_DOWNSAMPLE\n" : "#define STEP_DOWNSAMPLE\n"); - e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl, - NULL, - frag, - use_alpha ? "#define USE_ALPHA_DOF\n" - "#define STEP_SCATTER\n" : - "#define STEP_SCATTER\n"); - e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag, - use_alpha ? - "#define USE_ALPHA_DOF\n" - "#define STEP_RESOLVE\n" : - "#define STEP_RESOLVE\n"); - MEM_freeN(frag); + + e_data.dof_scatter_sh[use_alpha] = DRW_shader_create_with_shaderlib( + datatoc_effect_dof_vert_glsl, + NULL, + datatoc_effect_dof_frag_glsl, + lib, + use_alpha ? "#define USE_ALPHA_DOF\n" + "#define STEP_SCATTER\n" : + "#define STEP_SCATTER\n"); + + e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_dof_frag_glsl, + lib, + use_alpha ? "#define USE_ALPHA_DOF\n" + "#define STEP_RESOLVE\n" : + "#define STEP_RESOLVE\n"); } int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 8c48ae65d9b..f6e74c6822c 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -486,7 +486,7 @@ void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int le } /** - * Simple down-sampling algorithm for cubemap. Reconstruct mip chain up to mip level. + * Simple down-sampling algorithm for cube-map. Reconstruct mip chain up to mip level. */ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level) { diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index bac96ab1079..d77c6600026 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -32,6 +32,8 @@ #include "DNA_world_types.h" +#include "IMB_imbuf.h" + #include "eevee_private.h" #include "eevee_engine.h" /* own include */ @@ -79,11 +81,6 @@ static void eevee_engine_init(void *ved) GPU_framebuffer_ensure_config(&fbl->main_color_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->color)}); - if (sldata->common_ubo == NULL) { - sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), - &sldata->common_data); - } - /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. * `EEVEE_effects_init` needs to go second for TAA. */ EEVEE_renderpasses_init(vedata); @@ -459,6 +456,9 @@ static void eevee_render_to_image(void *vedata, } EEVEE_PrivateData *g_data = ved->stl->g_data; + EEVEE_render_modules_init(vedata, engine, depsgraph); + + int initial_frame = CFRA; int steps = max_ii(1, scene->eevee.motion_blur_steps); int time_steps_tot = (do_motion_blur) ? steps : 1; g_data->render_tot_samples = divide_ceil_u(scene->eevee.taa_render_samples, time_steps_tot); @@ -480,9 +480,10 @@ static void eevee_render_to_image(void *vedata, } else { EEVEE_motion_blur_step_set(ved, MB_PREV); - RE_engine_frame_set(engine, floorf(time_prev), fractf(time_prev)); + DRW_render_set_time(engine, depsgraph, floorf(time_prev), fractf(time_prev)); + EEVEE_render_modules_init(vedata, engine, depsgraph); + sldata = EEVEE_view_layer_data_ensure(); - EEVEE_render_view_sync(vedata, engine, depsgraph); EEVEE_render_cache_init(sldata, vedata); DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache); @@ -496,9 +497,10 @@ static void eevee_render_to_image(void *vedata, /* Next motion step. */ if (do_motion_blur_fx) { EEVEE_motion_blur_step_set(ved, MB_NEXT); - RE_engine_frame_set(engine, floorf(time_next), fractf(time_next)); + DRW_render_set_time(engine, depsgraph, floorf(time_next), fractf(time_next)); + EEVEE_render_modules_init(vedata, engine, depsgraph); + sldata = EEVEE_view_layer_data_ensure(); - EEVEE_render_view_sync(vedata, engine, depsgraph); EEVEE_render_cache_init(sldata, vedata); DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache); @@ -512,10 +514,11 @@ static void eevee_render_to_image(void *vedata, { if (do_motion_blur) { EEVEE_motion_blur_step_set(ved, MB_CURR); - RE_engine_frame_set(engine, floorf(time_curr), fractf(time_curr)); + DRW_render_set_time(engine, depsgraph, floorf(time_curr), fractf(time_curr)); + EEVEE_render_modules_init(vedata, engine, depsgraph); + sldata = EEVEE_view_layer_data_ensure(); } - EEVEE_render_view_sync(vedata, engine, depsgraph); EEVEE_render_cache_init(sldata, vedata); DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache); @@ -558,6 +561,11 @@ static void eevee_render_to_image(void *vedata, /* Restore original viewport size. */ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]}); + + if (CFRA != initial_frame) { + /* Restore original frame number. This is because the render pipeline expects it. */ + RE_engine_frame_set(engine, initial_frame, 0.0f); + } } static void eevee_engine_free(void) @@ -601,7 +609,7 @@ RenderEngineType DRW_engine_viewport_eevee_type = { NULL, EEVEE_ENGINE, N_("Eevee"), - RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_PREVIEW | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/engines/eevee/eevee_engine.h b/source/blender/draw/engines/eevee/eevee_engine.h index b27d16aa7d8..40784e2980b 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.h +++ b/source/blender/draw/engines/eevee/eevee_engine.h @@ -20,9 +20,6 @@ * \ingroup DNA */ -#ifndef __EEVEE_ENGINE_H__ -#define __EEVEE_ENGINE_H__ +#pragma once extern RenderEngineType DRW_engine_viewport_eevee_type; - -#endif /* __EEVEE_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 78d50a02fc7..38f5536170e 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -53,9 +53,6 @@ #if defined(IRRADIANCE_SH_L2) # define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */ # define IRRADIANCE_SAMPLE_SIZE_Y 4 /* 3 in reality */ -#elif defined(IRRADIANCE_CUBEMAP) -# define IRRADIANCE_SAMPLE_SIZE_X 8 -# define IRRADIANCE_SAMPLE_SIZE_Y 8 #elif defined(IRRADIANCE_HL2) # define IRRADIANCE_SAMPLE_SIZE_X 4 /* 3 in reality */ # define IRRADIANCE_SAMPLE_SIZE_Y 2 @@ -113,7 +110,7 @@ typedef struct EEVEE_LightBake { float samples_ct, invsamples_ct; /** Sampling bias during convolution step. */ float lod_factor; - /** Max cubemap LOD to sample when convolving. */ + /** Max cube-map LOD to sample when convolving. */ float lod_max; /** Number of probes to render + world probe. */ int cube_len, grid_len; @@ -121,7 +118,7 @@ typedef struct EEVEE_LightBake { /* Irradiance grid */ /** Current probe being rendered (UBO data). */ EEVEE_LightGrid *grid; - /** Target cubemap at MIP 0. */ + /** Target cube-map at MIP 0. */ int irr_cube_res; /** Size of the irradiance texture. */ int irr_size[3]; @@ -145,7 +142,7 @@ typedef struct EEVEE_LightBake { /* Reflection probe */ /** Current probe being rendered (UBO data). */ EEVEE_LightProbe *cube; - /** Target cubemap at MIP 0. */ + /** Target cube-map at MIP 0. */ int ref_cube_res; /** Index of the current cube. */ int cube_offset; @@ -206,6 +203,21 @@ static bool eevee_lightcache_version_check(LightCache *lcache) } } +static bool eevee_lightcache_can_be_saved(LightCache *lcache) +{ + if (lcache->grid_tx.data) { + if (MEM_allocN_len(lcache->grid_tx.data) >= INT_MAX) { + return false; + } + } + if (lcache->cube_tx.data) { + if (MEM_allocN_len(lcache->cube_tx.data) >= INT_MAX) { + return false; + } + } + return true; +} + static int eevee_lightcache_irradiance_sample_count(LightCache *lcache) { int total_irr_samples = 0; @@ -231,7 +243,14 @@ void EEVEE_lightcache_info_update(SceneEEVEE *eevee) if (lcache->cube_tx.tex_size[2] > GPU_max_texture_layers()) { BLI_strncpy(eevee->light_cache_info, - TIP_("Error: Light cache is too big for your GPU to be loaded"), + TIP_("Error: Light cache is too big for the GPU to be loaded"), + sizeof(eevee->light_cache_info)); + return; + } + + if (lcache->flag & LIGHTCACHE_INVALID) { + BLI_strncpy(eevee->light_cache_info, + TIP_("Error: Light cache dimensions not supported by the GPU"), sizeof(eevee->light_cache_info)); return; } @@ -242,6 +261,13 @@ void EEVEE_lightcache_info_update(SceneEEVEE *eevee) return; } + if (!eevee_lightcache_can_be_saved(lcache)) { + BLI_strncpy(eevee->light_cache_info, + TIP_("Error: LightCache is too large and will not be saved to disk"), + sizeof(eevee->light_cache_info)); + return; + } + char formatted_mem[15]; BLI_str_format_byte_unit(formatted_mem, eevee_lightcache_memsize_get(lcache), false); @@ -284,7 +310,7 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache, const int grid_len, const int irr_size[3]) { - if (light_cache) { + if (light_cache && !(light_cache->flag & LIGHTCACHE_INVALID)) { /* See if we need the same amount of texture space. */ if ((irr_size[0] == light_cache->grid_tx.tex_size[0]) && (irr_size[1] == light_cache->grid_tx.tex_size[1]) && @@ -346,12 +372,18 @@ LightCache *EEVEE_lightcache_create(const int grid_len, light_cache->cube_mips = MEM_callocN(sizeof(LightCacheTexture) * light_cache->mips_len, "LightCacheTexture"); - for (int mip = 0; mip < light_cache->mips_len; mip++) { - GPU_texture_get_mipmap_size( - light_cache->cube_tx.tex, mip + 1, light_cache->cube_mips[mip].tex_size); + if (light_cache->grid_tx.tex == NULL || light_cache->cube_tx.tex == NULL) { + /* We could not create the requested textures size. Stop baking and do not use the cache. */ + light_cache->flag = LIGHTCACHE_INVALID; } + else { + light_cache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID; - light_cache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID; + for (int mip = 0; mip < light_cache->mips_len; mip++) { + GPU_texture_get_mipmap_size( + light_cache->cube_tx.tex, mip + 1, light_cache->cube_mips[mip].tex_size); + } + } return light_cache; } @@ -379,6 +411,12 @@ static bool eevee_lightcache_static_load(LightCache *lcache) 0, false, NULL); + + if (lcache->grid_tx.tex == NULL) { + lcache->flag |= LIGHTCACHE_NOT_USABLE; + return false; + } + GPU_texture_filter_mode(lcache->grid_tx.tex, true); } @@ -404,6 +442,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache) NULL); } + if (lcache->cube_tx.tex == NULL) { + lcache->flag |= LIGHTCACHE_NOT_USABLE; + return false; + } + for (int mip = 0; mip < lcache->mips_len; mip++) { GPU_texture_add_mipmap( lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data); @@ -423,6 +466,10 @@ bool EEVEE_lightcache_load(LightCache *lcache) return false; } + if (lcache->flag & (LIGHTCACHE_INVALID | LIGHTCACHE_NOT_USABLE)) { + return false; + } + switch (lcache->type) { case LIGHTCACHE_TYPE_STATIC: return eevee_lightcache_static_load(lcache); @@ -484,6 +531,12 @@ void EEVEE_lightcache_free(LightCache *lcache) static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake) { + if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) { + GPU_context_main_lock(); + DRW_opengl_context_enable(); + return; + } + if (lbake->gl_context) { DRW_opengl_render_context_enable(lbake->gl_context); if (lbake->gpu_context == NULL) { @@ -498,6 +551,12 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake) static void eevee_lightbake_context_disable(EEVEE_LightBake *lbake) { + if (GPU_use_main_context_workaround() && !BLI_thread_is_main()) { + DRW_opengl_context_disable(); + GPU_context_main_unlock(); + return; + } + if (lbake->gl_context) { DRW_gpu_render_context_disable(lbake->gpu_context); DRW_opengl_render_context_disable(lbake->gl_context); @@ -593,9 +652,7 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake) if (lbake->lcache == NULL) { lbake->lcache = EEVEE_lightcache_create( lbake->grid_len, lbake->cube_len, lbake->ref_cube_res, lbake->vis_res, lbake->irr_size); - lbake->lcache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | - LIGHTCACHE_UPDATE_GRID; - lbake->lcache->vis_res = lbake->vis_res; + lbake->own_light_cache = true; eevee->light_cache_data = lbake->lcache; @@ -652,7 +709,7 @@ wmJob *EEVEE_lightbake_job_create(struct wmWindowManager *wm, lbake->delay = delay; lbake->frame = frame; - if (lbake->gl_context == NULL) { + if (lbake->gl_context == NULL && !GPU_use_main_context_workaround()) { lbake->gl_context = WM_opengl_context_create(); wm_window_reset_drawable(); } @@ -697,7 +754,7 @@ void *EEVEE_lightbake_job_data_alloc(struct Main *bmain, lbake->mutex = BLI_mutex_alloc(); lbake->frame = frame; - if (run_as_job) { + if (run_as_job && !GPU_use_main_context_workaround()) { lbake->gl_context = WM_opengl_context_create(); wm_window_reset_drawable(); } @@ -804,11 +861,6 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb DRW_view_set_active(view); } - if (sldata->common_ubo == NULL) { - sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), - &sldata->common_data); - } - /* HACK: set txl->color but unset it before Draw Manager frees it. */ txl->color = lbake->rt_color; int viewport_size[2] = { @@ -969,9 +1021,8 @@ static void compute_cell_id(EEVEE_LightGrid *egrid, if (visited_cells == cell_idx) { return; } - else { - visited_cells++; - } + + visited_cells++; } } } @@ -1272,6 +1323,17 @@ void EEVEE_lightbake_job(void *custom_data, short *stop, short *do_update, float * We cannot do it in the main thread. */ eevee_lightbake_context_enable(lbake); eevee_lightbake_create_resources(lbake); + + /* Resource allocation can fail. Early exit in this case. */ + if (lbake->lcache->flag & LIGHTCACHE_INVALID) { + *lbake->stop = 1; + *lbake->do_update = 1; + lbake->lcache->flag &= ~LIGHTCACHE_BAKING; + eevee_lightbake_context_disable(lbake); + eevee_lightbake_delete_resources(lbake); + return; + } + eevee_lightbake_create_render_target(lbake, lbake->rt_res); eevee_lightbake_context_disable(lbake); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h index 0db36ce0c2e..834f0fc8a45 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.h +++ b/source/blender/draw/engines/eevee/eevee_lightcache.h @@ -20,8 +20,7 @@ * \ingroup eevee */ -#ifndef __EEVEE_LIGHTCACHE_H__ -#define __EEVEE_LIGHTCACHE_H__ +#pragma once #include "BLI_sys_types.h" /* for bool */ @@ -62,5 +61,3 @@ struct LightCache *EEVEE_lightcache_create(const int grid_len, void EEVEE_lightcache_free(struct LightCache *lcache); bool EEVEE_lightcache_load(struct LightCache *lcache); void EEVEE_lightcache_info_update(struct SceneEEVEE *eevee); - -#endif /* __EEVEE_LIGHTCACHE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 71c8294d123..47a913640c7 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -23,6 +23,7 @@ #include "DRW_render.h" #include "BLI_rand.h" +#include "BLI_string_utils.h" #include "BLI_utildefines.h" #include "DNA_image_types.h" @@ -161,6 +162,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + vedata->info[0] = '\0'; if (!e_data.hammersley) { EEVEE_shaders_lightprobe_shaders_init(); @@ -176,11 +178,16 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) stl->g_data->light_cache = scene_eval->eevee.light_cache_data; } else { + if (scene_eval->eevee.light_cache_data && + (scene_eval->eevee.light_cache_data->flag & LIGHTCACHE_NOT_USABLE)) { + /* Error message info. */ + BLI_snprintf( + vedata->info, sizeof(vedata->info), "Error: LightCache cannot be loaded on this GPU"); + } + if (!sldata->fallback_lightcache) { #if defined(IRRADIANCE_SH_L2) int grid_res = 4; -#elif defined(IRRADIANCE_CUBEMAP) - int grid_res = 8; #elif defined(IRRADIANCE_HL2) int grid_res = 4; #endif @@ -328,38 +335,28 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat { DRW_PASS_CREATE(psl->probe_background, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); - struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = NULL; + EEVEE_lookdev_cache_init(vedata, sldata, psl->probe_background, pinfo, &grp); - Scene *scene = draw_ctx->scene; - World *wo = scene->world; - - /* LookDev */ - EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo); + if (grp == NULL) { + Scene *scene = draw_ctx->scene; + World *world = (scene->world) ? scene->world : EEVEE_world_default_get(); - if (!grp && wo) { - struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE); + const int options = VAR_WORLD_BACKGROUND | VAR_WORLD_PROBE; + struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, world, options); grp = DRW_shgroup_material_create(gpumat, psl->probe_background); DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); - /* TODO (fclem): remove those (need to clean the GLSL files). */ - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); - DRW_shgroup_call(grp, geom, NULL); } - /* Fallback if shader fails or if not using nodetree. */ - if (grp == NULL) { - grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background); - DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1); - DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); - DRW_shgroup_call(grp, geom, NULL); - } + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } if (DRW_state_draw_support()) { @@ -1114,9 +1111,6 @@ void EEVEE_lightbake_filter_diffuse(EEVEE_ViewLayerData *sldata, /* NOTE : Keep in sync with load_irradiance_cell() */ #if defined(IRRADIANCE_SH_L2) int size[2] = {3, 3}; -#elif defined(IRRADIANCE_CUBEMAP) - int size[2] = {8, 8}; - pinfo->samples_len = 1024.0f; #elif defined(IRRADIANCE_HL2) int size[2] = {3, 2}; pinfo->samples_len = 1024.0f; diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 18365d69514..403a8e2af55 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -97,19 +97,18 @@ static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerD void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, - DRWShadingGroup **r_grp, DRWPass *pass, - World *UNUSED(world), - EEVEE_LightProbesInfo *pinfo) + EEVEE_LightProbesInfo *pinfo, + DRWShadingGroup **r_shgrp) { EEVEE_StorageList *stl = vedata->stl; EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); - View3D *v3d = draw_ctx->v3d; - View3DShading *shading = &v3d->shading; - Scene *scene = draw_ctx->scene; + /* The view will be NULL when rendering previews. */ + const View3D *v3d = draw_ctx->v3d; + const Scene *scene = draw_ctx->scene; const bool probe_render = pinfo != NULL; @@ -150,93 +149,91 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, } if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) { + const View3DShading *shading = &v3d->shading; StudioLight *sl = BKE_studiolight_find(shading->lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE); - if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) { - GPUShader *shader = probe_render ? EEVEE_shaders_default_studiolight_sh_get() : - EEVEE_shaders_background_studiolight_sh_get(); + if (sl == NULL || (sl->flag & STUDIOLIGHT_TYPE_WORLD) == 0) { + return; + } + + GPUShader *shader = probe_render ? EEVEE_shaders_studiolight_probe_sh_get() : + EEVEE_shaders_studiolight_background_sh_get(); - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - int cube_res = scene_eval->eevee.gi_cubemap_resolution; + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + int cube_res = scene_eval->eevee.gi_cubemap_resolution; - /* If one of the component is missing we start from scratch. */ - if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) || - (txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL) || - (g_data->light_cache && g_data->light_cache->ref_res != cube_res)) { - eevee_lookdev_lightcache_delete(vedata); - } + /* If one of the component is missing we start from scratch. */ + if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) || + (txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL) || + (g_data->light_cache && g_data->light_cache->ref_res != cube_res)) { + eevee_lookdev_lightcache_delete(vedata); + } - if (stl->lookdev_lightcache == NULL) { + if (stl->lookdev_lightcache == NULL) { #if defined(IRRADIANCE_SH_L2) - int grid_res = 4; -#elif defined(IRRADIANCE_CUBEMAP) - int grid_res = 8; + int grid_res = 4; #elif defined(IRRADIANCE_HL2) - int grid_res = 4; + int grid_res = 4; #endif - stl->lookdev_lightcache = EEVEE_lightcache_create( - 1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1}); - - /* XXX: Fix memleak. TODO find out why. */ - MEM_SAFE_FREE(stl->lookdev_cube_mips); - - /* We do this to use a special light cache for lookdev. - * This light-cache needs to be per viewport. But we need to - * have correct freeing when the viewport is closed. So we - * need to reference all textures to the txl and the memblocks - * to the stl. */ - stl->lookdev_grid_data = stl->lookdev_lightcache->grid_data; - stl->lookdev_cube_data = stl->lookdev_lightcache->cube_data; - stl->lookdev_cube_mips = stl->lookdev_lightcache->cube_mips; - txl->lookdev_grid_tx = stl->lookdev_lightcache->grid_tx.tex; - txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex; - } - - g_data->light_cache = stl->lookdev_lightcache; - - DRWShadingGroup *grp = *r_grp = DRW_shgroup_create(shader, pass); - axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z); - DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix); - - if (probe_render) { - DRW_shgroup_uniform_float_copy( - grp, "studioLightIntensity", shading->studiolight_intensity); - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); - DRW_shgroup_uniform_texture(grp, "image", sl->equirect_radiance_gputexture); - /* Do not fadeout when doing probe rendering, only when drawing the background */ - DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); - } - else { - float background_alpha = g_data->background_alpha * shading->studiolight_background; - float studiolight_blur = powf(shading->studiolight_blur, 2.5f); - DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha); - DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur); - DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); - } - - DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); - - /* Do we need to recalc the lightprobes? */ - if (g_data->studiolight_index != sl->index || - g_data->studiolight_rot_z != shading->studiolight_rot_z || - g_data->studiolight_intensity != shading->studiolight_intensity || - g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution || - g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp || - g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) { - stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD; - g_data->studiolight_index = sl->index; - g_data->studiolight_rot_z = shading->studiolight_rot_z; - g_data->studiolight_intensity = shading->studiolight_intensity; - g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution; - g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp; - g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality; - } + stl->lookdev_lightcache = EEVEE_lightcache_create( + 1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1}); + + /* XXX: Fix memleak. TODO find out why. */ + MEM_SAFE_FREE(stl->lookdev_cube_mips); + + /* We do this to use a special light cache for lookdev. + * This light-cache needs to be per viewport. But we need to + * have correct freeing when the viewport is closed. So we + * need to reference all textures to the txl and the memblocks + * to the stl. */ + stl->lookdev_grid_data = stl->lookdev_lightcache->grid_data; + stl->lookdev_cube_data = stl->lookdev_lightcache->cube_data; + stl->lookdev_cube_mips = stl->lookdev_lightcache->cube_mips; + txl->lookdev_grid_tx = stl->lookdev_lightcache->grid_tx.tex; + txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex; + } + + g_data->light_cache = stl->lookdev_lightcache; + + DRWShadingGroup *grp = DRW_shgroup_create(shader, pass); + axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z); + DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix); + + if (probe_render) { + /* Avoid artifact with equirectangular mapping. */ + eGPUSamplerState state = (GPU_SAMPLER_FILTER | GPU_SAMPLER_REPEAT_S); + DRW_shgroup_uniform_float_copy(grp, "studioLightIntensity", shading->studiolight_intensity); + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture_ex(grp, "studioLight", sl->equirect_radiance_gputexture, state); + /* Do not fadeout when doing probe rendering, only when drawing the background */ + DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); + } + else { + float background_alpha = g_data->background_alpha * shading->studiolight_background; + float studiolight_blur = powf(shading->studiolight_blur, 2.5f); + DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha); + DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur); + DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx); + } + + /* Common UBOs are setup latter. */ + *r_shgrp = grp; + + /* Do we need to recalc the lightprobes? */ + if (g_data->studiolight_index != sl->index || + g_data->studiolight_rot_z != shading->studiolight_rot_z || + g_data->studiolight_intensity != shading->studiolight_intensity || + g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution || + g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp || + g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) { + stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD; + g_data->studiolight_index = sl->index; + g_data->studiolight_rot_z = shading->studiolight_rot_z; + g_data->studiolight_intensity = shading->studiolight_intensity; + g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution; + g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp; + g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality; } } } diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h index 04049efd758..d5dbf8ce690 100644 --- a/source/blender/draw/engines/eevee/eevee_lut.h +++ b/source/blender/draw/engines/eevee/eevee_lut.h @@ -21,8 +21,7 @@ * \ingroup gpu */ -#ifndef __EEVEE_LUT_H__ -#define __EEVEE_LUT_H__ +#pragma once extern const float ltc_mat_ggx[64 * 64 * 4]; extern const float ltc_mag_ggx[64 * 64 * 2]; @@ -30,5 +29,3 @@ extern const float bsdf_split_sum_ggx[64 * 64 * 2]; extern const float ltc_disk_integral[64 * 64]; extern const float btdf_split_sum_ggx[32][64 * 64]; extern const float blue_noise[64 * 64][4]; - -#endif /* __EEVEE_LUT_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c index 5f20d6fbfb8..9b07a6908c3 100644 --- a/source/blender/draw/engines/eevee/eevee_lut_gen.c +++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c @@ -31,6 +31,8 @@ #include "BLI_rand.h" #include "BLI_string_utils.h" +#include "eevee_private.h" + extern char datatoc_bsdf_lut_frag_glsl[]; extern char datatoc_btdf_lut_frag_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; @@ -45,15 +47,13 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) static float samples_len = 8192.0f; static float inv_samples_len = 1.0f / 8192.0f; - char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); - struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl, - datatoc_lightprobe_geom_glsl, - datatoc_bsdf_lut_frag_glsl, - lib_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n"); + struct GPUShader *sh = DRW_shader_create_with_shaderlib(datatoc_lightprobe_vert_glsl, + datatoc_lightprobe_geom_glsl, + datatoc_bsdf_lut_frag_glsl, + lib, + "#define HAMMERSLEY_SIZE 8192\n"); DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); @@ -76,8 +76,7 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) DRW_draw_pass(pass); float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data); + GPU_framebuffer_read_color(fb, 0, 0, w, h, 3, 0, GPU_DATA_FLOAT, data); printf("{"); for (int i = 0; i < w * h * 3; i += 3) { @@ -106,16 +105,10 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) static float a2 = 0.0f; static float inv_samples_len = 1.0f / 8192.0f; - char *frag_str = BLI_string_joinN( - datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl); - - struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n" - "#define LUT_SIZE 64\n"); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); - MEM_freeN(frag_str); + struct GPUShader *sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_btdf_lut_frag_glsl, lib, "#define HAMMERSLEY_SIZE 8192\n"); DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); @@ -195,4 +188,4 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) MEM_freeN(data); return tex; -}
\ No newline at end of file +} diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 8c17ecd3905..4f97fe99b27 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -56,37 +56,6 @@ static struct { float noise_offsets[3]; } e_data = {NULL}; /* Engine data */ -extern char datatoc_lights_lib_glsl[]; -extern char datatoc_lightprobe_lib_glsl[]; -extern char datatoc_ambient_occlusion_lib_glsl[]; -extern char datatoc_prepass_frag_glsl[]; -extern char datatoc_prepass_vert_glsl[]; -extern char datatoc_default_frag_glsl[]; -extern char datatoc_default_world_frag_glsl[]; -extern char datatoc_ltc_lib_glsl[]; -extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_bsdf_sampling_lib_glsl[]; -extern char datatoc_common_uniforms_lib_glsl[]; -extern char datatoc_common_hair_lib_glsl[]; -extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_irradiance_lib_glsl[]; -extern char datatoc_octahedron_lib_glsl[]; -extern char datatoc_cubemap_lib_glsl[]; -extern char datatoc_lit_surface_frag_glsl[]; -extern char datatoc_lit_surface_vert_glsl[]; -extern char datatoc_raytrace_lib_glsl[]; -extern char datatoc_ssr_lib_glsl[]; -extern char datatoc_shadow_vert_glsl[]; -extern char datatoc_lightprobe_geom_glsl[]; -extern char datatoc_lightprobe_vert_glsl[]; -extern char datatoc_background_vert_glsl[]; -extern char datatoc_update_noise_frag_glsl[]; -extern char datatoc_volumetric_vert_glsl[]; -extern char datatoc_volumetric_geom_glsl[]; -extern char datatoc_volumetric_frag_glsl[]; -extern char datatoc_volumetric_lib_glsl[]; -extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; - typedef struct EeveeMaterialCache { struct DRWShadingGroup *depth_grp; struct DRWShadingGroup *shading_grp; @@ -114,8 +83,8 @@ void EEVEE_material_bind_resources(DRWShadingGroup *shgrp, GPUMaterial *gpumat, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - int *ssr_id, - float *refract_depth, + const int *ssr_id, + const float *refract_depth, bool use_ssrefraction, bool use_alpha_blend) { @@ -238,46 +207,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d DRW_draw_pass(psl->update_noise_pass); } -void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]) -{ - /* view vectors for the corners of the view frustum. - * Can be used to recreate the world space position easily */ - float view_vecs[4][4] = { - {-1.0f, -1.0f, -1.0f, 1.0f}, - {1.0f, -1.0f, -1.0f, 1.0f}, - {-1.0f, 1.0f, -1.0f, 1.0f}, - {-1.0f, -1.0f, 1.0f, 1.0f}, - }; - - /* convert the view vectors to view space */ - const bool is_persp = (winmat[3][3] == 0.0f); - for (int i = 0; i < 4; i++) { - mul_project_m4_v3(invproj, view_vecs[i]); - /* normalized trick see: - * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - if (is_persp) { - /* Divide XY by Z. */ - mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]); - } - } - - /** - * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and - * view_vecs[1] is the vector going from the near-bottom-left corner to - * the far-top-right corner. - * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner - * when Z = 1, and top-left corner if Z = 1. - * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) - * distance from the near plane to the far clip plane. - */ - copy_v4_v4(r_viewvecs[0], view_vecs[0]); - - /* we need to store the differences */ - r_viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0]; - r_viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; - r_viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2]; -} - void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_StorageList *stl, @@ -305,15 +234,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, } { - /* Update view_vecs */ - float invproj[4][4], winmat[4][4]; - DRW_view_winmat_get(NULL, winmat, false); - DRW_view_winmat_get(NULL, invproj, true); - - EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs); - } - - { /* Update noise Framebuffer. */ GPU_framebuffer_ensure_config( &fbl->update_noise_fb, @@ -391,39 +311,28 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); - struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = NULL; + EEVEE_lookdev_cache_init(vedata, sldata, psl->background_ps, NULL, &grp); - Scene *scene = draw_ctx->scene; - World *wo = scene->world; - - EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL); + if (grp == NULL) { + Scene *scene = draw_ctx->scene; + World *world = (scene->world) ? scene->world : EEVEE_world_default_get(); - if (!grp && wo) { - struct GPUMaterial *gpumat = EEVEE_material_get( - vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND); + const int options = VAR_WORLD_BACKGROUND; + struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, world, options); grp = DRW_shgroup_material_create(gpumat, psl->background_ps); DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - /* TODO (fclem): remove those (need to clean the GLSL files). */ - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo); - DRW_shgroup_call(grp, geom, NULL); } - /* Fallback if shader fails or if not using nodetree. */ - if (grp == NULL) { - GPUShader *sh = EEVEE_shaders_default_background_sh_get(); - grp = DRW_shgroup_create(sh, psl->background_ps); - DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1); - DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - DRW_shgroup_call(grp, geom, NULL); - } + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block_ref(grp, "renderpass_block", &stl->g_data->renderpass_ubo); + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } #define EEVEE_PASS_CREATE(pass, state) \ @@ -574,9 +483,8 @@ static EeveeMaterialCache material_opaque(EEVEE_Data *vedata, if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) { return **emc_p; } - else { - *emc_p = emc = BLI_memblock_alloc(sldata->material_cache); - } + + *emc_p = emc = BLI_memblock_alloc(sldata->material_cache); material_shadow(vedata, sldata, ma, is_hair, emc); diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 1cedd334d67..d2f3a13eb7c 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -56,14 +56,10 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; if (e_data.mist_sh == NULL) { - char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_effect_mist_frag_glsl); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); - e_data.mist_sh = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); - - MEM_freeN(frag_str); + e_data.mist_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_mist_frag_glsl, lib, "#define FIRST_PASS\n"); } /* Create FrameBuffer. */ @@ -98,11 +94,11 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } else { - float near = -sldata->common_data.view_vecs[0][2]; - float range = sldata->common_data.view_vecs[1][2]; + float near = DRW_view_near_distance_get(NULL); + float far = DRW_view_far_distance_get(NULL); /* Fallback */ g_data->mist_start = near; - g_data->mist_inv_dist = 1.0f / fabsf(range); + g_data->mist_inv_dist = 1.0f / fabsf(far - near); g_data->mist_falloff = 1.0f; } diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 586ee780f1d..4e49136a6bc 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -37,6 +37,7 @@ #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_screen_types.h" #include "ED_screen.h" @@ -68,27 +69,23 @@ extern char datatoc_common_view_lib_glsl[]; static void eevee_create_shader_motion_blur(void) { - e_data.motion_blur_sh = DRW_shader_create_fullscreen( - datatoc_effect_motion_blur_frag_glsl, - "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n"); - e_data.motion_blur_object_sh = DRW_shader_create_with_lib(datatoc_object_motion_vert_glsl, - NULL, - datatoc_object_motion_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); - e_data.velocity_tiles_sh = DRW_shader_create_fullscreen( - datatoc_effect_velocity_tile_frag_glsl, - "#define TILE_GATHER\n" - "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n"); +#define TILE_SIZE_STR "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n" + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + e_data.motion_blur_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_motion_blur_frag_glsl, lib, TILE_SIZE_STR); + e_data.motion_blur_object_sh = DRW_shader_create_with_shaderlib( + datatoc_object_motion_vert_glsl, NULL, datatoc_object_motion_frag_glsl, lib, NULL); + + e_data.motion_blur_hair_sh = DRW_shader_create_with_shaderlib(datatoc_object_motion_vert_glsl, + NULL, + datatoc_object_motion_frag_glsl, + lib, + "#define HAIR\n"); + + e_data.velocity_tiles_sh = DRW_shader_create_fullscreen(datatoc_effect_velocity_tile_frag_glsl, + "#define TILE_GATHER\n" TILE_SIZE_STR); e_data.velocity_tiles_expand_sh = DRW_shader_create_fullscreen( - datatoc_effect_velocity_tile_frag_glsl, - "#define TILE_EXPANSION\n" - "#define EEVEE_VELOCITY_TILE_SIZE " STRINGIFY(EEVEE_VELOCITY_TILE_SIZE) "\n"); - - char *vert = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_object_motion_vert_glsl); - e_data.motion_blur_hair_sh = DRW_shader_create_with_lib( - vert, NULL, datatoc_object_motion_frag_glsl, datatoc_common_view_lib_glsl, "#define HAIR\n"); - MEM_freeN(vert); + datatoc_effect_velocity_tile_frag_glsl, "#define TILE_EXPANSION\n" TILE_SIZE_STR); } int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -288,8 +285,8 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), /* Store transform */ DRW_hair_duplimat_get(ob, psys, md, mb_data->obmat[mb_step]); - EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get( - &effects->motion_blur, ob, true); + EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_hair_data_get( + &effects->motion_blur, ob, md); if (mb_step == MB_CURR) { /* Fill missing matrices if the object was hidden in previous or next frame. */ @@ -329,10 +326,20 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), return; } - const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0; + RigidBodyOb *rbo = ob->rigidbody_object; + + /* active rigidbody objects only, as only those are affected by sim. */ + const bool has_rigidbody = (rbo && (rbo->type == RBO_TYPE_ACTIVE)); +#if 0 /* For now we assume dupli objects are moving. */ - const bool object_moves = is_dupli || BKE_object_moves_in_time(ob, true); - const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob); + const bool is_dupli = (ob->base_flag & BASE_FROM_DUPLI) != 0; + const bool object_moves = is_dupli || has_rigidbody || BKE_object_moves_in_time(ob, true); +#else + /* BKE_object_moves_in_time does not work in some cases. Better */ + const bool object_moves = true; +#endif + const bool is_deform = BKE_object_is_deform_modified(DRW_context_state_get()->scene, ob) || + (has_rigidbody && (rbo->flag & RBO_FLAG_USE_DEFORM) != 0); if (!(object_moves || is_deform)) { return; @@ -346,8 +353,8 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), /* Store transform */ copy_m4_m4(mb_data->obmat[mb_step], ob->obmat); - EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get( - &effects->motion_blur, ob, false); + EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(&effects->motion_blur, + ob); if (mb_step == MB_CURR) { GPUBatch *batch = DRW_cache_object_surface_get(ob); @@ -363,14 +370,6 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]); } - grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object); - DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); - DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); - DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); - DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1); - - DRW_shgroup_call(grp, batch, ob); - if (mb_geom->use_deform) { EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); if (!oedata->geom_update) { @@ -386,6 +385,21 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata), /* Keep to modify later (after init). */ mb_geom->batch = batch; } + + /* Avoid drawing object that has no motions since object_moves is always true. */ + if (!mb_geom->use_deform && /* Object deformation can happen without transform. */ + equals_m4m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_CURR]) && + equals_m4m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR])) { + return; + } + + grp = DRW_shgroup_create(e_data.motion_blur_object_sh, psl->velocity_object); + DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]); + DRW_shgroup_uniform_mat4(grp, "currModelMatrix", mb_data->obmat[MB_CURR]); + DRW_shgroup_uniform_mat4(grp, "nextModelMatrix", mb_data->obmat[MB_NEXT]); + DRW_shgroup_uniform_bool(grp, "useDeform", &mb_geom->use_deform, 1); + + DRW_shgroup_call(grp, batch, ob); } else if (is_deform) { /* Store vertex position buffer. */ @@ -466,16 +480,15 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata) GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]); break; } + + /* Modify the batch to include the previous & next position. */ + if (i == MB_PREV) { + GPU_batch_vertbuf_add_ex(batch, vbo, true); + mb_geom->vbo[i] = NULL; + } else { - /* Modify the batch to include the previous & next position. */ - if (i == MB_PREV) { - GPU_batch_vertbuf_add_ex(batch, vbo, true); - mb_geom->vbo[i] = NULL; - } - else { - /* This VBO can be reuse by next time step. Don't pass ownership. */ - GPU_batch_vertbuf_add_ex(batch, vbo, false); - } + /* This VBO can be reuse by next time step. Don't pass ownership. */ + GPU_batch_vertbuf_add_ex(batch, vbo, false); } } } diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index a075210967c..1929bbb9b98 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -53,17 +53,14 @@ extern char datatoc_effect_gtao_frag_glsl[]; static void eevee_create_shader_occlusion(void) { - char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_effect_gtao_frag_glsl); - - e_data.gtao_sh = DRW_shader_create_fullscreen(frag_str, NULL); - e_data.gtao_layer_sh = DRW_shader_create_fullscreen(frag_str, "#define LAYERED_DEPTH\n"); - e_data.gtao_debug_sh = DRW_shader_create_fullscreen(frag_str, "#define DEBUG_AO\n"); - - MEM_freeN(frag_str); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + + e_data.gtao_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_gtao_frag_glsl, lib, NULL); + e_data.gtao_layer_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_gtao_frag_glsl, lib, "#define LAYERED_DEPTH\n"); + e_data.gtao_debug_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_gtao_frag_glsl, lib, "#define DEBUG_AO\n"); } int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index a67593773ab..34cd22ad13c 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -20,8 +20,7 @@ * \ingroup DNA */ -#ifndef __EEVEE_PRIVATE_H__ -#define __EEVEE_PRIVATE_H__ +#pragma once #include "DRW_render.h" @@ -29,6 +28,8 @@ #include "DNA_lightprobe_types.h" +#include "GPU_viewport.h" + #include "BKE_camera.h" struct EEVEE_ShadowCasterBuffer; @@ -53,14 +54,11 @@ extern struct DrawEngineType draw_engine_eevee_type; /* Only define one of these. */ // #define IRRADIANCE_SH_L2 -// #define IRRADIANCE_CUBEMAP #define IRRADIANCE_HL2 #define HAMMERSLEY_SIZE 1024 #if defined(IRRADIANCE_SH_L2) # define SHADER_IRRADIANCE "#define IRRADIANCE_SH_L2\n" -#elif defined(IRRADIANCE_CUBEMAP) -# define SHADER_IRRADIANCE "#define IRRADIANCE_CUBEMAP\n" #elif defined(IRRADIANCE_HL2) # define SHADER_IRRADIANCE "#define IRRADIANCE_HL2\n" #endif @@ -166,7 +164,7 @@ enum { VAR_MAT_MESH = (1 << 0), VAR_MAT_VOLUME = (1 << 1), VAR_MAT_HAIR = (1 << 2), - VAR_MAT_PROBE = (1 << 3), + /* VAR_MAT_PROBE = (1 << 3), UNUSED */ VAR_MAT_BLEND = (1 << 4), VAR_MAT_LOOKDEV = (1 << 5), VAR_MAT_HOLDOUT = (1 << 6), @@ -589,7 +587,7 @@ typedef struct EEVEE_ObjectKey { /** Parent object for duplis */ struct Object *parent; /** Dupli objects recursive unique identifier */ - int id[16]; /* 2*MAX_DUPLI_RECUR */ + int id[8]; /* MAX_DUPLI_RECUR */ } EEVEE_ObjectKey; typedef struct EEVEE_ObjectMotionData { @@ -750,7 +748,6 @@ typedef struct EEVEE_EffectsInfo { * - sizeof(bool) == sizeof(int) in GLSL so use int in C */ typedef struct EEVEE_CommonUniformBuffer { float prev_persmat[4][4]; /* mat4 */ - float view_vecs[2][4]; /* vec4[2] */ float mip_ratio[10][4]; /* vec2[10] */ /* Ambient Occlusion */ /* -- 16 byte aligned -- */ @@ -894,6 +891,7 @@ typedef struct EEVEE_Data { EEVEE_TextureList *txl; EEVEE_PassList *psl; EEVEE_StorageList *stl; + char info[GPU_INFO_SIZE]; } EEVEE_Data; typedef struct EEVEE_PrivateData { @@ -913,6 +911,7 @@ typedef struct EEVEE_PrivateData { /* Render Matrices */ float studiolight_matrix[3][3]; float overscan, overscan_pixels; + float camtexcofac[4]; float size_orig[2]; /* Mist Settings */ @@ -971,8 +970,10 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData * Object *ob, bool hair); EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, - Object *ob, - bool hair); + Object *ob); +EEVEE_GeometryMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, + Object *ob, + struct ModifierData *md); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob); EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob); @@ -1004,7 +1005,6 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_materials_free(void); void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]); -void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]); void EEVEE_material_renderpasses_init(EEVEE_Data *vedata); void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); @@ -1012,8 +1012,8 @@ void EEVEE_material_bind_resources(DRWShadingGroup *shgrp, struct GPUMaterial *gpumat, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - int *ssr_id, - float *refract_depth, + const int *ssr_id, + const float *refract_depth, bool use_ssrefraction, bool use_alpha_blend); /* eevee_lights.c */ @@ -1060,15 +1060,14 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]); /* eevee_shaders.c */ void EEVEE_shaders_lightprobe_shaders_init(void); void EEVEE_shaders_material_shaders_init(void); +struct DRWShaderLibrary *EEVEE_shader_lib_get(void); struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void); -struct GPUShader *EEVEE_shaders_probe_default_sh_get(void); struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void); struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void); struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void); struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void); -struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void); -struct GPUShader *EEVEE_shaders_default_background_sh_get(void); -struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void); +struct GPUShader *EEVEE_shaders_studiolight_probe_sh_get(void); +struct GPUShader *EEVEE_shaders_studiolight_background_sh_get(void); struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void); struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void); struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void); @@ -1080,6 +1079,7 @@ struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo); Material *EEVEE_material_default_diffuse_get(void); Material *EEVEE_material_default_glossy_get(void); Material *EEVEE_material_default_error_get(void); +World *EEVEE_world_default_get(void); struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options); struct GPUMaterial *EEVEE_material_get( EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options); @@ -1283,6 +1283,9 @@ bool EEVEE_render_init(EEVEE_Data *vedata, void EEVEE_render_view_sync(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_modules_init(EEVEE_Data *vedata, + struct RenderEngine *engine, + struct Depsgraph *depsgraph); void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_render_cache(void *vedata, struct Object *ob, @@ -1303,10 +1306,9 @@ void EEVEE_render_update_passes(struct RenderEngine *engine, /** eevee_lookdev.c */ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, - DRWShadingGroup **grp, DRWPass *pass, - struct World *world, - EEVEE_LightProbesInfo *pinfo); + EEVEE_LightProbesInfo *pinfo, + DRWShadingGroup **r_shgrp); void EEVEE_lookdev_draw(EEVEE_Data *vedata); /** eevee_engine.c */ @@ -1354,5 +1356,3 @@ static const float cubefacemat[6][4][4] = { {0.0f, 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, }; - -#endif /* __EEVEE_PRIVATE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index f903fa905e8..b6b8833b1da 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -53,11 +53,9 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * EEVEE_StorageList *stl = vedata->stl; EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; - EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); Scene *scene = DEG_get_evaluated_scene(depsgraph); const float *size_orig = DRW_viewport_size_get(); float size_final[2]; - float camtexcofac[4]; /* Init default FB and render targets: * In render mode the default framebuffer is not generated @@ -75,6 +73,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * g_data->valid_double_buffer = 0; copy_v2_v2(g_data->size_orig, size_orig); + float *camtexcofac = g_data->camtexcofac; if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) { g_data->overscan = scene->eevee.overscan / 100.0f; g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan); @@ -125,19 +124,19 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * GPU_framebuffer_ensure_config(&fbl->main_color_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->color)}); - /* Alloc common ubo data. */ - if (sldata->common_ubo == NULL) { - sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), - &sldata->common_data); - } - - EEVEE_render_view_sync(vedata, engine, depsgraph); + return true; +} +void EEVEE_render_modules_init(EEVEE_Data *vedata, + RenderEngine *engine, + struct Depsgraph *depsgraph) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - - DRWView *view = (DRWView *)DRW_view_default_get(); - DRW_view_camtexco_set(view, camtexcofac); + EEVEE_render_view_sync(vedata, engine, depsgraph); /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. * `EEVEE_effects_init` needs to go second for TAA. */ @@ -146,8 +145,6 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * EEVEE_materials_init(sldata, vedata, stl, fbl); EEVEE_shadows_init(sldata); EEVEE_lightprobes_init(sldata, vedata); - - return true; } void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Depsgraph *depsgraph) @@ -160,7 +157,7 @@ void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Dep struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); RE_GetCameraWindow(engine->re, ob_camera_eval, winmat); - RE_GetCameraWindowWithOverscan(engine->re, winmat, g_data->overscan); + RE_GetCameraWindowWithOverscan(engine->re, g_data->overscan, winmat); RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); invert_m4_m4(viewmat, viewinv); @@ -169,10 +166,13 @@ void EEVEE_render_view_sync(EEVEE_Data *vedata, RenderEngine *engine, struct Dep DRW_view_reset(); DRW_view_default_set(view); DRW_view_set_active(view); + + DRW_view_camtexco_set(view, g_data->camtexcofac); } void EEVEE_render_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_view_layer_data_ensure(); EEVEE_bloom_cache_init(sldata, vedata); EEVEE_depth_of_field_cache_init(sldata, vedata); EEVEE_effects_cache_init(sldata, vedata); @@ -267,6 +267,7 @@ static void eevee_render_color_result(RenderLayer *rl, BLI_rcti_size_y(rect), num_channels, 0, + GPU_DATA_FLOAT, rp->rect); } diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index be771d7cf42..089d8b7a287 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -199,12 +199,10 @@ void EEVEE_renderpasses_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0; if (needs_post_processing) { if (e_data.postprocess_sh == NULL) { - char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_renderpass_postprocess_frag_glsl); - e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL); - MEM_freeN(frag_str); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + + e_data.postprocess_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_renderpass_postprocess_frag_glsl, lib, NULL); } DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 32d758dba4b..a1755e60c06 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -48,30 +48,12 @@ static struct { struct GPUTexture *depth_src; } e_data = {{NULL}}; /* Engine data */ -extern char datatoc_ambient_occlusion_lib_glsl[]; -extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_common_uniforms_lib_glsl[]; -extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_bsdf_sampling_lib_glsl[]; -extern char datatoc_octahedron_lib_glsl[]; -extern char datatoc_cubemap_lib_glsl[]; extern char datatoc_effect_ssr_frag_glsl[]; -extern char datatoc_lightprobe_lib_glsl[]; -extern char datatoc_raytrace_lib_glsl[]; static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) { if (e_data.ssr_sh[options] == NULL) { - char *ssr_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_raytrace_lib_glsl, - datatoc_effect_ssr_frag_glsl); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); DynStr *ds_defines = BLI_dynstr_new(); BLI_dynstr_append(ds_defines, SHADER_DEFINES); @@ -91,9 +73,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines); BLI_dynstr_free(ds_defines); - e_data.ssr_sh[options] = DRW_shader_create_fullscreen(ssr_shader_str, ssr_define_str); + e_data.ssr_sh[options] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_ssr_frag_glsl, lib, ssr_define_str); - MEM_freeN(ssr_shader_str); MEM_freeN(ssr_define_str); } diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 09e74c84948..5f125d395d3 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -28,6 +28,8 @@ #include "BLI_dynstr.h" #include "BLI_string_utils.h" +#include "DNA_world_types.h" + #include "MEM_guardedalloc.h" #include "GPU_material.h" @@ -40,19 +42,17 @@ static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n" #if defined(IRRADIANCE_SH_L2) - "#define IRRADIANCE_SH_L2\n" -#elif defined(IRRADIANCE_CUBEMAP) - "#define IRRADIANCE_CUBEMAP\n" + "#define IRRADIANCE_SH_L2\n"; #elif defined(IRRADIANCE_HL2) - "#define IRRADIANCE_HL2\n" + "#define IRRADIANCE_HL2\n"; #endif - "#define NOISE_SIZE 64\n"; static struct { + /* Lookdev */ + struct GPUShader *studiolight_probe_sh; + struct GPUShader *studiolight_background_sh; + /* Probes */ - struct GPUShader *probe_default_sh; - struct GPUShader *probe_default_studiolight_sh; - struct GPUShader *probe_background_studiolight_sh; struct GPUShader *probe_grid_display_sh; struct GPUShader *probe_cube_display_sh; struct GPUShader *probe_planar_display_sh; @@ -70,17 +70,16 @@ static struct { struct GPUShader *taa_resolve_reproject_sh; /* General purpose Shaders. */ - struct GPUShader *default_background; + struct GPUShader *lookdev_background; struct GPUShader *update_noise_sh; /* Shader strings */ - char *frag_shader_lib; - char *vert_shader_str; - char *vert_shadow_shader_str; - char *vert_background_shader_str; - char *vert_volume_shader_str; - char *geom_volume_shader_str; - char *volume_shader_lib; + char *closure_lit_lib; + char *surface_lit_frag; + char *surface_prepass_frag; + char *surface_geom_barycentric; + + DRWShaderLibrary *lib; /* LookDev Materials */ Material *glossy_mat; @@ -88,6 +87,8 @@ static struct { Material *error_mat; + World *default_world; + /* Default Material */ struct { bNodeTree *ntree; @@ -103,16 +104,39 @@ static struct { } world; } e_data = {NULL}; /* Engine data */ -extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_bsdf_sampling_lib_glsl[]; -extern char datatoc_common_uniforms_lib_glsl[]; +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_common_obinfos_lib_glsl[]; extern char datatoc_ambient_occlusion_lib_glsl[]; extern char datatoc_background_vert_glsl[]; -extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_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_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_common_utiltex_lib_glsl[]; extern char datatoc_cubemap_lib_glsl[]; -extern char datatoc_default_world_frag_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_frag_glsl[]; +extern char datatoc_effect_dof_vert_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_ssr_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[]; @@ -131,72 +155,111 @@ 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_lit_surface_frag_glsl[]; -extern char datatoc_lit_surface_vert_glsl[]; +extern char datatoc_closure_lit_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_prepass_vert_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[]; -/* Velocity Resolve */ -extern char datatoc_effect_velocity_resolve_frag_glsl[]; - -/* Temporal Sampling */ -extern char datatoc_effect_temporal_aa_glsl[]; - /* *********** FUNCTIONS *********** */ +static void eevee_shader_library_ensure(void) +{ + if (e_data.lib == NULL) { + e_data.lib = DRW_shader_library_create(); + /* NOTE: Theses needs 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_common_obinfos_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, closure_lib); + DRW_SHADER_LIB_ADD(e_data.lib, ssr_lib); + + /* Add one for each Closure */ + e_data.closure_lit_lib = BLI_string_joinN(datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl, + datatoc_closure_lit_lib_glsl); + + DRW_shader_library_add_file(e_data.lib, e_data.closure_lit_lib, "closure_lit_lib.glsl"); + + 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_lightprobe_shaders_init(void) { BLI_assert(e_data.probe_filter_glossy_sh == NULL); - char *shader_str = NULL; - - shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_lightprobe_filter_glossy_frag_glsl); - - e_data.probe_filter_glossy_sh = DRW_shader_create( - datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines); - - e_data.probe_default_sh = DRW_shader_create_with_lib(datatoc_background_vert_glsl, - NULL, - datatoc_default_world_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); - MEM_freeN(shader_str); + eevee_shader_library_ensure(); - shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_lightprobe_filter_diffuse_frag_glsl); + 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); - e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); + e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_lightprobe_filter_diffuse_frag_glsl, e_data.lib, filter_defines); - MEM_freeN(shader_str); + e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_lightprobe_filter_visibility_frag_glsl, e_data.lib, filter_defines); - shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_lightprobe_filter_visibility_frag_glsl); - - e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); - - MEM_freeN(shader_str); - - e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen(datatoc_lightprobe_grid_fill_frag_glsl, - filter_defines); + e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_lightprobe_grid_fill_frag_glsl, e_data.lib, filter_defines); e_data.probe_planar_downsample_sh = DRW_shader_create( datatoc_lightprobe_planar_downsample_vert_glsl, @@ -207,70 +270,18 @@ void EEVEE_shaders_lightprobe_shaders_init(void) void EEVEE_shaders_material_shaders_init(void) { - e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_raytrace_lib_glsl, - datatoc_ssr_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_ltc_lib_glsl, - datatoc_lights_lib_glsl, - /* Add one for each Closure */ - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_volumetric_lib_glsl); - - e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_ltc_lib_glsl, - datatoc_lights_lib_glsl, - datatoc_volumetric_lib_glsl, - datatoc_volumetric_frag_glsl); - - e_data.vert_shader_str = BLI_string_joinN( - datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl); - - e_data.vert_shadow_shader_str = BLI_string_joinN( - datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl); - - e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_background_vert_glsl); - - e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_vert_glsl); - - e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_geom_glsl); + eevee_shader_library_ensure(); } -GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void) +DRWShaderLibrary *EEVEE_shader_lib_get(void) { - return e_data.probe_filter_glossy_sh; + eevee_shader_library_ensure(); + return e_data.lib; } -GPUShader *EEVEE_shaders_probe_default_sh_get(void) +GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void) { - return e_data.probe_default_sh; + return e_data.probe_filter_glossy_sh; } GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void) @@ -293,59 +304,40 @@ GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void) return e_data.probe_planar_downsample_sh; } -GPUShader *EEVEE_shaders_default_studiolight_sh_get(void) +GPUShader *EEVEE_shaders_studiolight_probe_sh_get(void) { - if (e_data.probe_default_studiolight_sh == NULL) { - e_data.probe_default_studiolight_sh = DRW_shader_create_with_lib( - datatoc_background_vert_glsl, - NULL, - datatoc_default_world_frag_glsl, - datatoc_common_view_lib_glsl, - "#define LOOKDEV\n"); - } - return e_data.probe_default_studiolight_sh; + 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_background_studiolight_sh_get(void) +GPUShader *EEVEE_shaders_studiolight_background_sh_get(void) { - if (e_data.probe_background_studiolight_sh == NULL) { - char *frag_str = BLI_string_joinN(datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_default_world_frag_glsl); - - e_data.probe_background_studiolight_sh = DRW_shader_create_with_lib( + if (e_data.studiolight_background_sh == NULL) { + e_data.studiolight_background_sh = DRW_shader_create_with_shaderlib( datatoc_background_vert_glsl, NULL, - frag_str, - datatoc_common_view_lib_glsl, + datatoc_lookdev_world_frag_glsl, + e_data.lib, "#define LOOKDEV_BG\n" SHADER_DEFINES); - - MEM_freeN(frag_str); } - return e_data.probe_background_studiolight_sh; + return e_data.studiolight_background_sh; } GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void) { if (e_data.probe_cube_display_sh == NULL) { - char *shader_str = BLI_string_joinN(datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_lightprobe_cube_display_frag_glsl); - - char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_lightprobe_cube_display_vert_glsl); - - e_data.probe_cube_display_sh = DRW_shader_create(vert_str, NULL, shader_str, SHADER_DEFINES); - - MEM_freeN(vert_str); - MEM_freeN(shader_str); + 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; } @@ -353,22 +345,12 @@ GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void) GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void) { if (e_data.probe_grid_display_sh == NULL) { - char *shader_str = BLI_string_joinN(datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_lightprobe_grid_display_frag_glsl); - - char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_lightprobe_grid_display_vert_glsl); - - e_data.probe_grid_display_sh = DRW_shader_create(vert_str, NULL, shader_str, filter_defines); - - MEM_freeN(vert_str); - MEM_freeN(shader_str); + 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; } @@ -376,16 +358,12 @@ GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void) GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void) { if (e_data.probe_planar_display_sh == NULL) { - char *vert_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_lightprobe_planar_display_vert_glsl); - - char *shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_lightprobe_planar_display_frag_glsl); - - e_data.probe_planar_display_sh = DRW_shader_create(vert_str, NULL, shader_str, NULL); - - MEM_freeN(vert_str); - MEM_freeN(shader_str); + 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; } @@ -393,34 +371,17 @@ GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void) GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void) { if (e_data.velocity_resolve_sh == NULL) { - char *frag_str = BLI_string_joinN(datatoc_common_uniforms_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_effect_velocity_resolve_frag_glsl); - - e_data.velocity_resolve_sh = DRW_shader_create_fullscreen(frag_str, NULL); - - MEM_freeN(frag_str); + 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_default_background_sh_get(void) -{ - if (e_data.default_background == NULL) { - e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl, - NULL, - datatoc_default_world_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); - } - return e_data.default_background; -} - GPUShader *EEVEE_shaders_update_noise_sh_get(void) { if (e_data.update_noise_sh == NULL) { - e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL); + 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; } @@ -437,13 +398,8 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects) sh = &e_data.taa_resolve_sh; } if (*sh == NULL) { - char *frag_str = BLI_string_joinN(datatoc_common_uniforms_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_effect_temporal_aa_glsl); - - *sh = DRW_shader_create_fullscreen(frag_str, define); - MEM_freeN(frag_str); + *sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_temporal_aa_glsl, e_data.lib, define); } return *sh; @@ -583,6 +539,18 @@ struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo) 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; @@ -605,7 +573,7 @@ static char *eevee_get_defines(int options) if ((options & VAR_MAT_HAIR) != 0) { BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); } - if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) { + if ((options & VAR_WORLD_PROBE) != 0) { BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n"); } if ((options & VAR_MAT_HASH) != 0) { @@ -635,13 +603,13 @@ static char *eevee_get_vert(int options) char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { - str = BLI_strdup(e_data.vert_volume_shader_str); + 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 = BLI_strdup(e_data.vert_background_shader_str); + str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_background_vert_glsl); } else { - str = BLI_strdup(e_data.vert_shader_str); + str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_surface_vert_glsl); } return str; @@ -652,7 +620,7 @@ static char *eevee_get_geom(int options) char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { - str = BLI_strdup(e_data.geom_volume_shader_str); + str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_geom_glsl); } return str; @@ -663,18 +631,36 @@ static char *eevee_get_frag(int options) char *str = NULL; if ((options & VAR_MAT_VOLUME) != 0) { - str = BLI_strdup(e_data.volume_shader_lib); + str = DRW_shader_library_create_shader_string(e_data.lib, datatoc_volumetric_frag_glsl); } else if ((options & VAR_MAT_DEPTH) != 0) { - str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl); + str = BLI_strdup(e_data.surface_prepass_frag); } else { - str = BLI_strdup(e_data.frag_shader_lib); + str = BLI_strdup(e_data.surface_lit_frag); } 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)) +{ + const bool is_hair = (options & VAR_MAT_HAIR) != 0; + const bool is_mesh = (options & VAR_MAT_MESH) != 0; + + /* 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; + } +} + static struct GPUMaterial *eevee_material_get_ex( struct Scene *scene, Material *ma, World *wo, int options, bool deferred) { @@ -702,14 +688,16 @@ static struct GPUMaterial *eevee_material_get_ex( 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); + scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred, cbfn); } 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); + scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred, NULL); } MEM_SAFE_FREE(defines); @@ -764,30 +752,31 @@ struct GPUMaterial *EEVEE_material_get( void EEVEE_shaders_free(void) { - MEM_SAFE_FREE(e_data.frag_shader_lib); - MEM_SAFE_FREE(e_data.vert_shader_str); - MEM_SAFE_FREE(e_data.vert_shadow_shader_str); - MEM_SAFE_FREE(e_data.vert_background_shader_str); - MEM_SAFE_FREE(e_data.vert_volume_shader_str); - MEM_SAFE_FREE(e_data.geom_volume_shader_str); - MEM_SAFE_FREE(e_data.volume_shader_lib); - DRW_SHADER_FREE_SAFE(e_data.default_background); + MEM_SAFE_FREE(e_data.closure_lit_lib); + 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.probe_default_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.probe_default_studiolight_sh); - DRW_SHADER_FREE_SAFE(e_data.probe_background_studiolight_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_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; diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 8c50b26b45f..0da356b75ac 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -42,11 +42,6 @@ static struct { extern char datatoc_shadow_vert_glsl[]; extern char datatoc_shadow_frag_glsl[]; extern char datatoc_shadow_accum_frag_glsl[]; -extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_common_uniforms_lib_glsl[]; -extern char datatoc_bsdf_common_lib_glsl[]; -extern char datatoc_lights_lib_glsl[]; -extern char datatoc_raytrace_lib_glsl[]; void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh) { @@ -65,23 +60,13 @@ void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata) const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if (!e_data.shadow_sh) { - e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl, - NULL, - datatoc_shadow_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); - } + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); - if (!e_data.shadow_accum_sh) { - char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_raytrace_lib_glsl, - datatoc_lights_lib_glsl, - datatoc_shadow_accum_frag_glsl); + e_data.shadow_sh = DRW_shader_create_with_shaderlib( + datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, lib, NULL); - e_data.shadow_accum_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES); - MEM_freeN(frag_str); + e_data.shadow_accum_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_shadow_accum_frag_glsl, lib, SHADER_DEFINES); } if (!sldata->lights) { diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index ef4588f4aca..637c5201afc 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -38,41 +38,19 @@ static struct { struct GPUShader *sss_sh[3]; } e_data = {{NULL}}; /* Engine data */ -extern char datatoc_common_view_lib_glsl[]; -extern char datatoc_common_uniforms_lib_glsl[]; -extern char datatoc_lights_lib_glsl[]; -extern char datatoc_raytrace_lib_glsl[]; -extern char datatoc_octahedron_lib_glsl[]; -extern char datatoc_cubemap_lib_glsl[]; -extern char datatoc_bsdf_sampling_lib_glsl[]; -extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_effect_subsurface_frag_glsl[]; extern char datatoc_effect_translucency_frag_glsl[]; static void eevee_create_shader_subsurface(void) { - char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_effect_subsurface_frag_glsl); - - /* TODO(fclem) remove some of these dependencies. */ - char *frag_translucent_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_raytrace_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_lights_lib_glsl, - datatoc_effect_translucency_frag_glsl); - - e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); - e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"); - e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_translucent_str, - "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES); - - MEM_freeN(frag_translucent_str); - MEM_freeN(frag_str); + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + + e_data.sss_sh[0] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_subsurface_frag_glsl, lib, "#define FIRST_PASS\n"); + e_data.sss_sh[1] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_subsurface_frag_glsl, lib, "#define SECOND_PASS\n"); + e_data.sss_sh[2] = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_effect_translucency_frag_glsl, lib, "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES); } void EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *UNUSED(vedata)) diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 714481c39f1..e184a80d2f6 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -96,7 +96,7 @@ static void invert_cdf(const float cdf[FILTER_CDF_TABLE_SIZE], } /* Evaluate a discrete function table with linear interpolation. */ -static float eval_table(float *table, float x) +static float eval_table(const float *table, float x) { CLAMP(x, 0.0f, 1.0f); x = x * (FILTER_CDF_TABLE_SIZE - 1); @@ -240,9 +240,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); } - effects->taa_total_sample = EEVEE_renderpasses_only_first_sample_pass_active(vedata) ? - 1 : - scene_eval->eevee.taa_samples; + const bool first_sample_only = EEVEE_renderpasses_only_first_sample_pass_active(vedata); + view_is_valid = view_is_valid && !first_sample_only; + effects->taa_total_sample = first_sample_only ? 1 : scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); DRW_view_persmat_get(NULL, persmat, false); @@ -269,7 +269,14 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data } } else { - effects->bypass_drawing = true; + const bool all_shaders_compiled = stl->g_data->queued_shaders_count_prev == 0; + /* Fix Texture painting (see T79370) and shader compilation (see T78520). */ + if (DRW_state_is_navigating() || !all_shaders_compiled) { + effects->taa_current_sample = 1; + } + else { + effects->bypass_drawing = true; + } } return repro_flag | EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER | diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 300022e97a9..57d5e54290e 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -44,16 +44,12 @@ #include "DEG_depsgraph_query.h" -#include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_material.h" #include "GPU_texture.h" #include "eevee_private.h" static struct { - char *volumetric_common_lib; - char *volumetric_common_lights_lib; - struct GPUShader *volumetric_clear_sh; struct GPUShader *scatter_sh; struct GPUShader *scatter_with_lights_sh; @@ -97,57 +93,48 @@ extern char datatoc_common_fullscreen_vert_glsl[]; static void eevee_create_shader_volumes(void) { - e_data.volumetric_common_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_volumetric_lib_glsl); - - e_data.volumetric_common_lights_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lights_lib_glsl, - datatoc_volumetric_lib_glsl); - - e_data.volumetric_clear_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl, - datatoc_volumetric_geom_glsl, - datatoc_volumetric_frag_glsl, - e_data.volumetric_common_lib, - "#define VOLUMETRICS\n" - "#define CLEAR\n"); - e_data.scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl, - datatoc_volumetric_geom_glsl, - datatoc_volumetric_scatter_frag_glsl, - e_data.volumetric_common_lights_lib, - SHADER_DEFINES - "#define VOLUMETRICS\n" - "#define VOLUME_SHADOW\n"); - e_data.scatter_with_lights_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl, - datatoc_volumetric_geom_glsl, - datatoc_volumetric_scatter_frag_glsl, - e_data.volumetric_common_lights_lib, - SHADER_DEFINES - "#define VOLUMETRICS\n" - "#define VOLUME_LIGHTING\n" - "#define VOLUME_SHADOW\n"); - e_data.volumetric_integration_sh = DRW_shader_create_with_lib( + DRWShaderLibrary *lib = EEVEE_shader_lib_get(); + + e_data.volumetric_clear_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_frag_glsl, + lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define CLEAR\n"); + + e_data.scatter_sh = DRW_shader_create_with_shaderlib(datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_scatter_frag_glsl, + lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define VOLUME_SHADOW\n"); + + e_data.scatter_with_lights_sh = DRW_shader_create_with_shaderlib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_scatter_frag_glsl, + lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define VOLUME_LIGHTING\n" + "#define VOLUME_SHADOW\n"); + + 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.volumetric_common_lib, + lib, USE_VOLUME_OPTI ? "#extension GL_ARB_shader_image_load_store: enable\n" "#extension GL_ARB_shading_language_420pack: enable\n" - "#define USE_VOLUME_OPTI\n" : - NULL); - e_data.volumetric_resolve_sh = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl, - NULL, - datatoc_volumetric_resolve_frag_glsl, - e_data.volumetric_common_lib, - NULL); - e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl, - NULL); + "#define USE_VOLUME_OPTI\n" SHADER_DEFINES : + SHADER_DEFINES); + + e_data.volumetric_resolve_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_volumetric_resolve_frag_glsl, lib, SHADER_DEFINES); + e_data.volumetric_accum_sh = DRW_shader_create_fullscreen_with_shaderlib( + datatoc_volumetric_accum_frag_glsl, lib, SHADER_DEFINES); const float density[4] = {1.0f, 1.0f, 1.0f, 1.0f}; e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, density); @@ -259,17 +246,11 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->vol_shadow_steps = 0; } - /* Update view_vecs */ - float invproj[4][4], winmat[4][4]; - DRW_view_winmat_get(NULL, winmat, false); - DRW_view_winmat_get(NULL, invproj, true); - EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs); - if (DRW_view_is_persp_get(NULL)) { float sample_distribution = scene_eval->eevee.volumetric_sample_distribution; sample_distribution = 4.0f * (max_ff(1.0f - sample_distribution, 1e-2f)); - const float clip_start = common_data->view_vecs[0][2]; + const float clip_start = DRW_view_near_distance_get(NULL); /* Negate */ float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f); float far = integration_end = min_ff(-integration_end, near - 1e-4f); @@ -280,8 +261,8 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->vol_depth_param[2] = sample_distribution; } else { - const float clip_start = common_data->view_vecs[0][2]; - const float clip_end = clip_start + common_data->view_vecs[1][2]; + const float clip_start = DRW_view_near_distance_get(NULL); + const float clip_end = DRW_view_far_distance_get(NULL); integration_start = min_ff(integration_end, clip_start); integration_end = max_ff(-integration_end, clip_end); @@ -504,12 +485,7 @@ static bool eevee_volume_object_mesh_init(Scene *scene, #endif if (fds->fluid && (fds->type == FLUID_DOMAIN_TYPE_GAS) /* && show_smoke */) { - if (!(fds->flags & FLUID_DOMAIN_USE_NOISE)) { - GPU_create_smoke(fmd, 0); - } - else if (fds->flags & FLUID_DOMAIN_USE_NOISE) { - GPU_create_smoke(fmd, 1); - } + DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE); BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(fmd)); } @@ -841,16 +817,13 @@ void EEVEE_volumes_free_smoke_textures(void) /* Free Smoke Textures after rendering */ LISTBASE_FOREACH (LinkData *, link, &e_data.smoke_domains) { FluidModifierData *fmd = (FluidModifierData *)link->data; - GPU_free_smoke(fmd); + DRW_smoke_free(fmd); } BLI_freelistN(&e_data.smoke_domains); } void EEVEE_volumes_free(void) { - MEM_SAFE_FREE(e_data.volumetric_common_lib); - MEM_SAFE_FREE(e_data.volumetric_common_lights_lib); - DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter); DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit); 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 57b16418696..2f6f8327f58 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -1,4 +1,7 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(raytrace_lib.glsl) + /* Based on Practical Realtime Strategies for Accurate Indirect Occlusion * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx @@ -24,12 +27,6 @@ #define MAX_SEARCH_ITER 32 #define MAX_LOD 6.0 -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ - uniform sampler2D horizonBuffer; /* aoSettings flags */ @@ -243,6 +240,11 @@ float gtao_multibounce(float visibility, vec3 albedo) return max(x, ((x * a + b) * x + c) * x); } +float specular_occlusion(float NV, float AO, float roughness) +{ + return saturate(pow(NV + AO, roughness) - 1.0 + AO); +} + /* Use the right occlusion */ float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal) { diff --git a/source/blender/draw/engines/eevee/shaders/background_vert.glsl b/source/blender/draw/engines/eevee/shaders/background_vert.glsl index aff8e0857f6..ab5d9a7ebe4 100644 --- a/source/blender/draw/engines/eevee/shaders/background_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/background_vert.glsl @@ -1,17 +1,17 @@ -in vec2 pos; +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) -out vec3 viewPosition; +in vec2 pos; -#ifndef VOLUMETRICS -/* necessary for compilation*/ -out vec3 worldPosition; -out vec3 worldNormal; -out vec3 viewNormal; -#endif +RESOURCE_ID_VARYING void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + + PASS_RESOURCE_ID + gl_Position = vec4(pos, 1.0, 1.0); viewPosition = vec3(pos, -1.0); @@ -22,6 +22,6 @@ void main() #endif #ifdef USE_ATTR - pass_attr(viewPosition); + pass_attr(viewPosition, NormalMatrix, ModelMatrixInverse); #endif } diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index a8b8566edec..deedde64194 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -1,487 +1,7 @@ -#define M_PI 3.14159265358979323846 /* pi */ -#define M_2PI 6.28318530717958647692 /* 2*pi */ -#define M_PI_2 1.57079632679489661923 /* pi/2 */ -#define M_1_PI 0.318309886183790671538 /* 1/pi */ -#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */ -#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */ -#define FLT_MAX 3.402823e+38 +#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#define LUT_SIZE 64 - -/* Buffers */ -uniform sampler2D colorBuffer; -uniform sampler2D depthBuffer; -uniform sampler2D maxzBuffer; -uniform sampler2D minzBuffer; -uniform sampler2DArray planarDepth; - -#define cameraForward ViewMatrixInverse[2].xyz -#define cameraPos ViewMatrixInverse[3].xyz -#define cameraVec \ - ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) -#define viewCameraVec \ - ((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0)) - -/* ------- Structures -------- */ - -/* ------ Lights ----- */ -struct LightData { - vec4 position_influence; /* w : InfluenceRadius (inversed and squared) */ - vec4 color_spec; /* w : Spec Intensity */ - vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */ - vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */ - vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */ - vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Light Type */ -}; - -/* convenience aliases */ -#define l_color color_spec.rgb -#define l_spec color_spec.a -#define l_position position_influence.xyz -#define l_influence position_influence.w -#define l_sizex rightvec_sizex.w -#define l_sizey upvec_sizey.w -#define l_right rightvec_sizex.xyz -#define l_up upvec_sizey.xyz -#define l_forward forwardvec_type.xyz -#define l_type forwardvec_type.w -#define l_spot_size spotdata_radius_shadow.x -#define l_spot_blend spotdata_radius_shadow.y -#define l_radius spotdata_radius_shadow.z -#define l_shadowid spotdata_radius_shadow.w - -/* ------ Shadows ----- */ -#ifndef MAX_CASCADE_NUM -# define MAX_CASCADE_NUM 4 -#endif - -struct ShadowData { - vec4 near_far_bias_id; - vec4 contact_shadow_data; -}; - -struct ShadowCubeData { - mat4 shadowmat; - vec4 position; -}; - -struct ShadowCascadeData { - mat4 shadowmat[MAX_CASCADE_NUM]; - vec4 split_start_distances; - vec4 split_end_distances; - vec4 shadow_vec_id; -}; - -/* convenience aliases */ -#define sh_near near_far_bias_id.x -#define sh_far near_far_bias_id.y -#define sh_bias near_far_bias_id.z -#define sh_data_index near_far_bias_id.w -#define sh_contact_dist contact_shadow_data.x -#define sh_contact_offset contact_shadow_data.y -#define sh_contact_spread contact_shadow_data.z -#define sh_contact_thickness contact_shadow_data.w -#define sh_shadow_vec shadow_vec_id.xyz -#define sh_tex_index shadow_vec_id.w - -/* ------ Render Passes ----- */ -layout(std140) uniform renderpass_block -{ - bool renderPassDiffuse; - bool renderPassDiffuseLight; - bool renderPassGlossy; - bool renderPassGlossyLight; - bool renderPassEmit; - bool renderPassSSSColor; - bool renderPassEnvironment; -}; - -vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light) -{ - return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0); -} - -vec3 render_pass_sss_mask(vec3 sss_color) -{ - 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); -} - -vec3 render_pass_emission_mask(vec3 emission_light) -{ - return renderPassEmit ? emission_light : vec3(0.0); -} - -/* ------- Convenience functions --------- */ - -vec3 mul(mat3 m, vec3 v) -{ - return m * v; -} -mat3 mul(mat3 m1, mat3 m2) -{ - return m1 * m2; -} -vec3 transform_direction(mat4 m, vec3 v) -{ - return mat3(m) * v; -} -vec3 transform_point(mat4 m, vec3 v) -{ - return (m * vec4(v, 1.0)).xyz; -} -vec3 project_point(mat4 m, vec3 v) -{ - vec4 tmp = m * vec4(v, 1.0); - return tmp.xyz / tmp.w; -} - -#define min3(a, b, c) min(a, min(b, c)) -#define min4(a, b, c, d) min(a, min3(b, c, d)) -#define min5(a, b, c, d, e) min(a, min4(b, c, d, e)) -#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f)) -#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g)) -#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h)) -#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i)) - -#define max3(a, b, c) max(a, max(b, c)) -#define max4(a, b, c, d) max(a, max3(b, c, d)) -#define max5(a, b, c, d, e) max(a, max4(b, c, d, e)) -#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f)) -#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g)) -#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h)) -#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i)) - -#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0) -#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0) -#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0) -#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0) -#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0) -#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0) -#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0) - -float min_v2(vec2 v) -{ - return min(v.x, v.y); -} -float min_v3(vec3 v) -{ - return min(v.x, min(v.y, v.z)); -} -float min_v4(vec4 v) -{ - return min(min(v.x, v.y), min(v.z, v.w)); -} -float max_v2(vec2 v) -{ - return max(v.x, v.y); -} -float max_v3(vec3 v) -{ - return max(v.x, max(v.y, v.z)); -} -float max_v4(vec4 v) -{ - return max(max(v.x, v.y), max(v.z, v.w)); -} - -float sum(vec2 v) -{ - return dot(vec2(1.0), v); -} -float sum(vec3 v) -{ - return dot(vec3(1.0), v); -} -float sum(vec4 v) -{ - return dot(vec4(1.0), v); -} - -float avg(vec2 v) -{ - return dot(vec2(1.0 / 2.0), v); -} -float avg(vec3 v) -{ - return dot(vec3(1.0 / 3.0), v); -} -float avg(vec4 v) -{ - return dot(vec4(1.0 / 4.0), v); -} - -float saturate(float a) -{ - return clamp(a, 0.0, 1.0); -} -vec2 saturate(vec2 a) -{ - return clamp(a, 0.0, 1.0); -} -vec3 saturate(vec3 a) -{ - return clamp(a, 0.0, 1.0); -} -vec4 saturate(vec4 a) -{ - return clamp(a, 0.0, 1.0); -} - -float distance_squared(vec2 a, vec2 b) -{ - a -= b; - return dot(a, a); -} -float distance_squared(vec3 a, vec3 b) -{ - a -= b; - return dot(a, a); -} -float len_squared(vec3 a) -{ - return dot(a, a); -} - -float inverse_distance(vec3 V) -{ - return max(1 / length(V), 1e-8); -} - -vec2 mip_ratio_interp(float mip) -{ - float low_mip = floor(mip); - return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip); -} - -/* ------- RNG ------- */ - -float wang_hash_noise(uint s) -{ - s = (s ^ 61u) ^ (s >> 16u); - s *= 9u; - s = s ^ (s >> 4u); - s *= 0x27d4eb2du; - s = s ^ (s >> 15u); - - return fract(float(s) / 4294967296.0); -} - -/* ------- Fast Math ------- */ - -/* [Drobot2014a] Low Level Optimizations for GCN */ -float fast_sqrt(float v) -{ - return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); -} - -vec2 fast_sqrt(vec2 v) -{ - return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); -} - -/* [Eberly2014] GPGPU Programming for Games and Science */ -float fast_acos(float v) -{ - float res = -0.156583 * abs(v) + M_PI_2; - res *= fast_sqrt(1.0 - abs(v)); - return (v >= 0) ? res : M_PI - res; -} - -vec2 fast_acos(vec2 v) -{ - vec2 res = -0.156583 * abs(v) + M_PI_2; - res *= fast_sqrt(1.0 - abs(v)); - v.x = (v.x >= 0) ? res.x : M_PI - res.x; - v.y = (v.y >= 0) ? res.y : M_PI - res.y; - return v; -} - -float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal) -{ - return dot(planenormal, planeorigin - lineorigin); -} - -float line_plane_intersect_dist(vec3 lineorigin, - vec3 linedirection, - vec3 planeorigin, - vec3 planenormal) -{ - return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection); -} - -float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane) -{ - vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz)); - vec3 h = lineorigin - plane_co; - return -dot(plane.xyz, h) / dot(plane.xyz, linedirection); -} - -vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) -{ - float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal); - return lineorigin + linedirection * dist; -} - -vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) -{ - float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); - return lineorigin + linedirection * dist; -} - -float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) -{ - /* aligned plane normal */ - vec3 L = planeorigin - lineorigin; - float diskdist = length(L); - vec3 planenormal = -normalize(L); - return -diskdist / dot(planenormal, linedirection); -} - -vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) -{ - float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin); - if (dist < 0) { - /* if intersection is behind we fake the intersection to be - * really far and (hopefully) not inside the radius of interest */ - dist = 1e16; - } - return lineorigin + linedirection * dist; -} - -float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) -{ - float a = dot(linedirection, linedirection); - float b = dot(linedirection, lineorigin); - float c = dot(lineorigin, lineorigin) - 1; - - float dist = 1e15; - float determinant = b * b - a * c; - if (determinant >= 0) { - dist = (sqrt(determinant) - b) / a; - } - - return dist; -} - -float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) -{ - /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ - */ - vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; - vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; - vec3 furthestplane = max(firstplane, secondplane); - - return min_v3(furthestplane); -} - -/* Return texture coordinates to sample Surface LUT */ -vec2 lut_coords(float cosTheta, float roughness) -{ - float theta = acos(cosTheta); - vec2 coords = vec2(roughness, theta / M_PI_2); - - /* scale and bias coordinates, for correct filtered lookup */ - return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; -} - -vec2 lut_coords_ltc(float cosTheta, float roughness) -{ - vec2 coords = vec2(roughness, sqrt(1.0 - cosTheta)); - - /* scale and bias coordinates, for correct filtered lookup */ - return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; -} - -/* -- Tangent Space conversion -- */ -vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B) -{ - return T * vector.x + B * vector.y + N * vector.z; -} - -vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B) -{ - return vec3(dot(T, vector), dot(B, vector), dot(N, vector)); -} - -void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) -{ - vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - T = normalize(cross(UpVector, N)); - B = cross(N, T); -} - -/* ---- Opengl Depth conversion ---- */ - -float linear_depth(bool is_persp, float z, float zf, float zn) -{ - if (is_persp) { - return (zn * zf) / (z * (zn - zf) + zf); - } - else { - return (z * 2.0 - 1.0) * zf; - } -} - -float buffer_depth(bool is_persp, float z, float zf, float zn) -{ - if (is_persp) { - return (zf * (zn - z)) / (z * (zn - zf)); - } - else { - return (z / (zf * 2.0)) + 0.5; - } -} - -float get_view_z_from_depth(float depth) -{ - if (ProjectionMatrix[3][3] == 0.0) { - float d = 2.0 * depth - 1.0; - return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); - } - else { - return viewVecs[0].z + depth * viewVecs[1].z; - } -} - -float get_depth_from_view_z(float z) -{ - if (ProjectionMatrix[3][3] == 0.0) { - float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; - return d * 0.5 + 0.5; - } - else { - return (z - viewVecs[0].z) / viewVecs[1].z; - } -} - -vec2 get_uvs_from_view(vec3 view) -{ - vec3 ndc = project_point(ProjectionMatrix, view); - return ndc.xy * 0.5 + 0.5; -} - -vec3 get_view_space_from_depth(vec2 uvcoords, float depth) -{ - if (ProjectionMatrix[3][3] == 0.0) { - return vec3(viewVecs[0].xy + uvcoords * viewVecs[1].xy, 1.0) * get_view_z_from_depth(depth); - } - else { - return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz; - } -} - -vec3 get_world_space_from_depth(vec2 uvcoords, float depth) -{ - return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz; -} - -vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness) +vec3 specular_dominant_dir(vec3 N, vec3 V, float roughness) { vec3 R = -reflect(V, N); float smoothness = 1.0 - roughness; @@ -489,13 +9,6 @@ vec3 get_specular_reflection_dominant_dir(vec3 N, vec3 V, float roughness) return normalize(mix(N, R, fac)); } -float specular_occlusion(float NV, float AO, float roughness) -{ - return saturate(pow(NV + AO, roughness) - 1.0 + AO); -} - -/* --- Refraction utils --- */ - float ior_from_f0(float f0) { float f = sqrt(f0); @@ -508,7 +21,7 @@ float f0_from_ior(float eta) return A * A; } -vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior) +vec3 refraction_dominant_dir(vec3 N, vec3 V, float roughness, float ior) { /* TODO: This a bad approximation. Better approximation should fit * the refracted vector and roughness into the best prefiltered reflection @@ -527,128 +40,6 @@ vec3 get_specular_refraction_dominant_dir(vec3 N, vec3 V, float roughness, float return R; } -float get_btdf_lut(sampler2DArray btdf_lut_tex, float NV, float roughness, float ior) -{ - const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE; - - vec3 coords; - /* Try to compensate for the low resolution and interpolation error. */ - coords.x = (ior > 1.0) ? (0.9 + lut_scale_bias_texel_size.z) + - (0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior) : - (0.9 + lut_scale_bias_texel_size.z) * ior * ior; - coords.y = 1.0 - saturate(NV); - coords.xy *= lut_scale_bias_texel_size.x; - coords.xy += lut_scale_bias_texel_size.y; - - const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */ - const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */ - - float mip = roughness * lut_lvl_scale; - float mip_floor = floor(mip); - - coords.z = lut_lvl_ofs + mip_floor + 1.0; - float btdf_high = textureLod(btdf_lut_tex, coords, 0.0).r; - - coords.z -= 1.0; - float btdf_low = textureLod(btdf_lut_tex, coords, 0.0).r; - - float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z); - - return btdf; -} - -/* ---- Encode / Decode Normal buffer data ---- */ -/* From http://aras-p.info/texts/CompactNormalStorage.html - * Using Method #4: Spheremap Transform */ -vec2 normal_encode(vec3 n, vec3 view) -{ - float p = sqrt(n.z * 8.0 + 8.0); - return n.xy / p + 0.5; -} - -vec3 normal_decode(vec2 enc, vec3 view) -{ - vec2 fenc = enc * 4.0 - 2.0; - float f = dot(fenc, fenc); - float g = sqrt(1.0 - f / 4.0); - vec3 n; - n.xy = fenc * g; - n.z = 1 - f / 2; - return n; -} - -/* ---- RGBM (shared multiplier) encoding ---- */ -/* From http://iwasbeingirony.blogspot.fr/2010/06/difference-between-rgbm-and-rgbd.html */ - -/* Higher RGBM_MAX_RANGE gives imprecision issues in low intensity. */ -#define RGBM_MAX_RANGE 512.0 - -vec4 rgbm_encode(vec3 rgb) -{ - float maxRGB = max_v3(rgb); - float M = maxRGB / RGBM_MAX_RANGE; - M = ceil(M * 255.0) / 255.0; - return vec4(rgb / (M * RGBM_MAX_RANGE), M); -} - -vec3 rgbm_decode(vec4 data) -{ - return data.rgb * (data.a * RGBM_MAX_RANGE); -} - -/* ---- RGBE (shared exponent) encoding ---- */ -vec4 rgbe_encode(vec3 rgb) -{ - float maxRGB = max_v3(rgb); - float fexp = ceil(log2(maxRGB)); - return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0); -} - -vec3 rgbe_decode(vec4 data) -{ - float fexp = data.a * 255.0 - 128.0; - return data.rgb * exp2(fexp); -} - -#if 1 -# define irradiance_encode rgbe_encode -# define irradiance_decode rgbe_decode -#else /* No ecoding (when using floating point format) */ -# define irradiance_encode(X) (X).rgbb -# define irradiance_decode(X) (X).rgb -#endif - -/* Irradiance Visibility Encoding */ -#if 1 -vec4 visibility_encode(vec2 accum, float range) -{ - accum /= range; - - vec4 data; - data.x = fract(accum.x); - data.y = floor(accum.x) / 255.0; - data.z = fract(accum.y); - data.w = floor(accum.y) / 255.0; - - return data; -} - -vec2 visibility_decode(vec4 data, float range) -{ - return (data.xz + data.yw * 255.0) * range; -} -#else /* No ecoding (when using floating point format) */ -vec4 visibility_encode(vec2 accum, float range) -{ - return accum.xyxy; -} - -vec2 visibility_decode(vec4 data, float range) -{ - return data.xy; -} -#endif - /* Fresnel monochromatic, perfect mirror */ float F_eta(float eta, float cos_theta) { @@ -766,265 +157,3 @@ float cone_cosine(float r) /* Jimenez 2016 in Practical Realtime Strategies for Accurate Indirect Occlusion*/ return exp2(-3.32193 * r * r); } - -/* --------- Closure ---------- */ - -#ifdef VOLUMETRICS - -struct Closure { - vec3 absorption; - vec3 scatter; - vec3 emission; - float anisotropy; -}; - -Closure nodetree_exec(void); /* Prototype */ - -# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0) - -Closure closure_mix(Closure cl1, Closure cl2, float fac) -{ - Closure cl; - cl.absorption = mix(cl1.absorption, cl2.absorption, fac); - cl.scatter = mix(cl1.scatter, cl2.scatter, fac); - cl.emission = mix(cl1.emission, cl2.emission, fac); - cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac); - return cl; -} - -Closure closure_add(Closure cl1, Closure cl2) -{ - Closure cl; - cl.absorption = cl1.absorption + cl2.absorption; - cl.scatter = cl1.scatter + cl2.scatter; - cl.emission = cl1.emission + cl2.emission; - cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */ - return cl; -} - -Closure closure_emission(vec3 rgb) -{ - Closure cl = CLOSURE_DEFAULT; - cl.emission = rgb; - return cl; -} - -#else /* VOLUMETRICS */ - -struct Closure { - vec3 radiance; - vec3 transmittance; - float holdout; -# ifdef USE_SSS - vec3 sss_irradiance; - vec3 sss_albedo; - float sss_radius; -# endif - vec4 ssr_data; - vec2 ssr_normal; - int flag; -}; - -Closure nodetree_exec(void); /* Prototype */ - -# define FLAG_TEST(flag, val) (((flag) & (val)) != 0) - -# define CLOSURE_SSR_FLAG 1 -# define CLOSURE_SSS_FLAG 2 -# define CLOSURE_HOLDOUT_FLAG 4 - -# ifdef USE_SSS -# define CLOSURE_DEFAULT \ - Closure(vec3(0.0), vec3(0.0), 0.0, vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0) -# else -# define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), 0.0, vec4(0.0), vec2(0.0), 0) -# endif - -uniform int outputSsrId = 1; -uniform int outputSssId = 1; - -void closure_load_ssr_data( - vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int 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, viewVec); - - if (ssr_id == outputSsrId) { - cl.ssr_data = vec4(ssr_spec, roughness); - cl.flag |= CLOSURE_SSR_FLAG; - } -} - -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; - cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0)); - } - else -# endif - { - cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo); - } -} - -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; -} - -/* Breaking this across multiple lines causes issues for some older GLSL compilers. */ -/* clang-format off */ -# if defined(MESH_SHADER) && !defined(DEPTH_SHADER) -/* clang-format on */ -# ifndef USE_ALPHA_BLEND -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 -# else /* USE_ALPHA_BLEND */ -/* Use dual source blending to be able to make a whole range of effects. */ -layout(location = 0, index = 0) out vec4 outRadiance; -layout(location = 0, index = 1) out vec4 outTransmittance; -# endif /* USE_ALPHA_BLEND */ - -# if defined(USE_ALPHA_BLEND) -/* Prototype because this file is included before volumetric_lib.glsl */ -void volumetric_resolve(vec2 frag_uvs, - float frag_depth, - out vec3 transmittance, - out vec3 scattering); -# endif - -# define NODETREE_EXEC -void main() -{ - Closure cl = nodetree_exec(); - - float holdout = saturate(1.0 - cl.holdout); - float transmit = saturate(avg(cl.transmittance)); - float alpha = 1.0 - transmit; - -# ifdef USE_ALPHA_BLEND - vec2 uvs = gl_FragCoord.xy * volCoordScale.zw; - vec3 vol_transmit, vol_scatter; - volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter); - - /* Removes part of the volume scattering that have - * already been added to the destination pixels. - * Since we do that using the blending pipeline we need to account for material transmittance. */ - vol_scatter -= vol_scatter * cl.transmittance; - - cl.radiance = cl.radiance * holdout * vol_transmit + vol_scatter; - outRadiance = vec4(cl.radiance, alpha * holdout); - 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 -# 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 - /* SSRefraction pass is done after the SSS pass. - * In order to not loose 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; -# endif - -# ifdef LOOKDEV - gl_FragDepth = 0.0; -# endif - -# ifndef USE_ALPHA_BLEND - float alpha_div = 1.0 / max(1e-8, alpha); - outRadiance.rgb *= alpha_div; - ssrData.rgb *= alpha_div; -# ifdef USE_SSS - sssAlbedo.rgb *= alpha_div; -# endif -# endif -} - -# endif /* MESH_SHADER */ - -#endif /* VOLUMETRICS */ diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl index f05b3396428..2b2da884fde 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_lut_frag.glsl @@ -1,3 +1,4 @@ +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) out vec4 FragColor; @@ -5,8 +6,8 @@ void main() { vec3 N, T, B, V; - float NV = (1.0 - (clamp(gl_FragCoord.y / BRDF_LUT_SIZE, 1e-4, 0.9999))); - float sqrtRoughness = clamp(gl_FragCoord.x / BRDF_LUT_SIZE, 1e-4, 0.9999); + float NV = (1.0 - (clamp(gl_FragCoord.y / b, 1e-4, 0.9999))); + float sqrtRoughness = clamp(gl_FragCoord.x / LUT_SIZE, 1e-4, 0.9999); float a = sqrtRoughness * sqrtRoughness; float a2 = a * a; diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl index 5f2b719095e..066ea58e2bf 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl @@ -1,6 +1,7 @@ +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) + uniform sampler1D texHammersley; -uniform sampler2D texJitter; uniform float sampleCount; uniform float invSampleCount; @@ -8,8 +9,7 @@ vec2 jitternoise = vec2(0.0); #ifndef UTIL_TEX # define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) + #endif /* UTIL_TEX */ void setup_noise(void) @@ -17,6 +17,11 @@ void setup_noise(void) jitternoise = texelfetch_noise_tex(gl_FragCoord.xy).rg; /* Global variable */ } +vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B) +{ + return T * vector.x + B * vector.y + N * vector.z; +} + #ifdef HAMMERSLEY_SIZE vec3 hammersley_3d(float i, float invsamplenbr) { diff --git a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl index 1389a9763c0..d815d9d4e6b 100644 --- a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl @@ -1,3 +1,4 @@ +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) uniform float a2; @@ -7,8 +8,8 @@ void main() { vec3 N, T, B, V; - float x = gl_FragCoord.x / BRDF_LUT_SIZE; - float y = gl_FragCoord.y / BRDF_LUT_SIZE; + float x = gl_FragCoord.x / LUT_SIZE; + float y = gl_FragCoord.y / LUT_SIZE; /* There is little variation if ior > 1.0 so we * maximize LUT precision for ior < 1.0 */ x = x * 1.1; diff --git a/source/blender/draw/engines/eevee/shaders/closure_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_lib.glsl new file mode 100644 index 00000000000..e572245ace9 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/closure_lib.glsl @@ -0,0 +1,181 @@ + +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(renderpass_lib.glsl) + +#ifndef VOLUMETRICS + +uniform int outputSsrId = 1; +uniform int outputSssId = 1; + +#endif + +struct Closure { +#ifdef VOLUMETRICS + vec3 absorption; + vec3 scatter; + vec3 emission; + float anisotropy; + +#else /* SURFACE */ + 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 +}; + +/* Prototype */ +Closure nodetree_exec(void); + +/* clang-format off */ +/* Avoid multiline 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 + +void closure_load_ssr_data( + vec3 ssr_spec, float roughness, vec3 N, vec3 viewVec, int 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, viewVec); + + if (ssr_id == outputSsrId) { + cl.ssr_data = vec4(ssr_spec, roughness); + cl.flag |= CLOSURE_SSR_FLAG; + } +} + +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; + cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0)); + } + else +# endif + { + cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo); + } +} + +#endif diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl index bc7879763c3..bf33caf9854 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_lit_lib.glsl @@ -1,32 +1,8 @@ -#ifndef LIT_SURFACE_UNIFORM -# define LIT_SURFACE_UNIFORM - -uniform float refractionDepth; - -# ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -# endif /* UTIL_TEX */ - -in vec3 worldPosition; -in vec3 viewPosition; - -in vec3 worldNormal; -in vec3 viewNormal; - -# ifdef HAIR_SHADER -in vec3 hairTangent; /* world space */ -in float hairThickTime; -in float hairThickness; -in float hairTime; -flat in int hairStrandID; - -uniform int hairThicknessRes = 1; -# endif - -#endif /* LIT_SURFACE_UNIFORM */ +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) +#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl) +#pragma BLENDER_REQUIRE(ssr_lib.glsl) /** * AUTO CONFIG @@ -209,7 +185,7 @@ void CLOSURE_NAME(vec3 N vec3 V = cameraVec; - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); /* ---------------------------------------------------------------- */ /* -------------------- SCENE LIGHTS LIGHTING --------------------- */ @@ -328,11 +304,11 @@ void CLOSURE_NAME(vec3 N # endif # ifdef CLOSURE_GLOSSY - vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); + vec3 spec_dir = specular_dominant_dir(N, V, roughnessSquared); # endif # ifdef CLOSURE_CLEARCOAT - vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared); + vec3 C_spec_dir = specular_dominant_dir(C_N, V, C_roughnessSquared); # endif # ifdef CLOSURE_REFRACTION @@ -345,7 +321,7 @@ void CLOSURE_NAME(vec3 N line_plane_intersect( worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition; - vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior); + vec3 refr_dir = refraction_dominant_dir(N, refr_V, roughness, final_ior); # endif # ifdef CLOSURE_REFRACTION @@ -485,7 +461,7 @@ void CLOSURE_NAME(vec3 N # endif # ifdef CLOSURE_REFRACTION - float btdf = get_btdf_lut(utilTex, NV, roughness, ior); + float btdf = get_btdf_lut(NV, roughness, ior); out_refr += refr_accum.rgb * btdf; # endif diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl index 759b4098b37..a6c9eebaff2 100644 --- a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl @@ -2,7 +2,6 @@ layout(std140) uniform common_block { mat4 pastViewProjectionMatrix; - vec4 viewVecs[2]; vec2 mipRatio[10]; /* To correct mip level texel misalignment */ /* Ambient Occlusion */ vec4 aoParameters[2]; @@ -70,3 +69,9 @@ layout(std140) uniform common_block #define ssrQuality ssrParameters.x #define ssrThickness ssrParameters.y #define ssrPixelSize ssrParameters.zw + +vec2 mip_ratio_interp(float mip) +{ + float low_mip = floor(mip); + return mix(mipRatio[int(low_mip)], mipRatio[int(low_mip + 1.0)], mip - low_mip); +} diff --git a/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl new file mode 100644 index 00000000000..95a585f0d9c --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl @@ -0,0 +1,65 @@ + +#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl) + +/* ---------------------------------------------------------------------- */ +/** \name Utiltex + * + * Utiltex is a sampler2DArray that stores a number of useful small utilitary textures and lookup + * tables. + * \{ */ + +uniform sampler2DArray utilTex; + +#define LUT_SIZE 64 + +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) + +/* Return texture coordinates to sample Surface LUT */ +vec2 lut_coords(float cosTheta, float roughness) +{ + float theta = acos(cosTheta); + vec2 coords = vec2(roughness, theta / M_PI_2); + + /* scale and bias coordinates, for correct filtered lookup */ + return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; +} + +vec2 lut_coords_ltc(float cosTheta, float roughness) +{ + vec2 coords = vec2(roughness, sqrt(1.0 - cosTheta)); + + /* scale and bias coordinates, for correct filtered lookup */ + return coords * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; +} + +float get_btdf_lut(float NV, float roughness, float ior) +{ + const vec3 lut_scale_bias_texel_size = vec3((LUT_SIZE - 1.0), 0.5, 1.5) / LUT_SIZE; + + vec3 coords; + /* Try to compensate for the low resolution and interpolation error. */ + coords.x = (ior > 1.0) ? (0.9 + lut_scale_bias_texel_size.z) + + (0.1 - lut_scale_bias_texel_size.z) * f0_from_ior(ior) : + (0.9 + lut_scale_bias_texel_size.z) * ior * ior; + coords.y = 1.0 - saturate(NV); + coords.xy *= lut_scale_bias_texel_size.x; + coords.xy += lut_scale_bias_texel_size.y; + + const float lut_lvl_ofs = 4.0; /* First texture lvl of roughness. */ + const float lut_lvl_scale = 16.0; /* How many lvl of roughness in the lut. */ + + float mip = roughness * lut_lvl_scale; + float mip_floor = floor(mip); + + coords.z = lut_lvl_ofs + mip_floor + 1.0; + float btdf_high = textureLod(utilTex, coords, 0.0).r; + + coords.z -= 1.0; + float btdf_low = textureLod(utilTex, coords, 0.0).r; + + float btdf = (ior == 1.0) ? 1.0 : mix(btdf_low, btdf_high, mip - coords.z); + + return btdf; +} + +/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl b/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl deleted file mode 100644 index 7e0e5945c54..00000000000 --- a/source/blender/draw/engines/eevee/shaders/concentric_samples_lib.glsl +++ /dev/null @@ -1,265 +0,0 @@ -/* Precomputed table of concentric samples. - * Generated using this algorithm http://l2program.co.uk/900/concentric-disk-sampling - * Sorted by radius then by rotation angle. - * This way it's better for cache usage and for - * easily restricting to a certain number of - * sample while still having a circular kernel. */ - -#define CONCENTRIC_SAMPLE_NUM 256 -const vec2 concentric[CONCENTRIC_SAMPLE_NUM] = vec2[CONCENTRIC_SAMPLE_NUM]( - vec2(0.0441941738242, 0.0441941738242), - vec2(-0.0441941738242, -0.0441941738242), - vec2(-0.0441941738242, 0.0441941738242), - vec2(0.0441941738242, -0.0441941738242), - vec2(0.181111092429, 0.0485285709567), - vec2(0.132582521472, 0.132582521472), - vec2(-0.181111092429, 0.0485285709567), - vec2(0.0485285709567, 0.181111092429), - vec2(-0.181111092429, -0.0485285709567), - vec2(-0.0485285709567, 0.181111092429), - vec2(-0.132582521472, -0.132582521472), - vec2(-0.132582521472, 0.132582521472), - vec2(-0.0485285709567, -0.181111092429), - vec2(0.0485285709567, -0.181111092429), - vec2(0.132582521472, -0.132582521472), - vec2(0.181111092429, -0.0485285709567), - vec2(0.308652606436, 0.0488857703251), - vec2(0.278439538809, 0.141872031169), - vec2(0.220970869121, 0.220970869121), - vec2(-0.278439538809, 0.141872031169), - vec2(0.141872031169, 0.278439538809), - vec2(-0.308652606436, 0.0488857703251), - vec2(0.0488857703251, 0.308652606436), - vec2(-0.308652606436, -0.0488857703251), - vec2(-0.0488857703251, 0.308652606436), - vec2(-0.278439538809, -0.141872031169), - vec2(-0.141872031169, 0.278439538809), - vec2(-0.220970869121, -0.220970869121), - vec2(-0.220970869121, 0.220970869121), - vec2(-0.141872031169, -0.278439538809), - vec2(-0.0488857703251, -0.308652606436), - vec2(0.0488857703251, -0.308652606436), - vec2(0.141872031169, -0.278439538809), - vec2(0.220970869121, -0.220970869121), - vec2(0.278439538809, -0.141872031169), - vec2(0.308652606436, -0.0488857703251), - vec2(0.434749091828, 0.0489844582952), - vec2(0.41294895701, 0.144497089605), - vec2(0.370441837162, 0.232764033475), - vec2(0.309359216769, 0.309359216769), - vec2(-0.370441837162, 0.232764033475), - vec2(0.232764033475, 0.370441837162), - vec2(-0.41294895701, 0.144497089605), - vec2(0.144497089605, 0.41294895701), - vec2(-0.434749091828, 0.0489844582952), - vec2(0.0489844582952, 0.434749091828), - vec2(-0.434749091828, -0.0489844582952), - vec2(-0.0489844582952, 0.434749091828), - vec2(-0.41294895701, -0.144497089605), - vec2(-0.144497089605, 0.41294895701), - vec2(-0.370441837162, -0.232764033475), - vec2(-0.232764033475, 0.370441837162), - vec2(-0.309359216769, -0.309359216769), - vec2(-0.309359216769, 0.309359216769), - vec2(-0.232764033475, -0.370441837162), - vec2(-0.144497089605, -0.41294895701), - vec2(-0.0489844582952, -0.434749091828), - vec2(0.0489844582952, -0.434749091828), - vec2(0.144497089605, -0.41294895701), - vec2(0.232764033475, -0.370441837162), - vec2(0.309359216769, -0.309359216769), - vec2(0.370441837162, -0.232764033475), - vec2(0.41294895701, -0.144497089605), - vec2(0.434749091828, -0.0489844582952), - vec2(0.560359517677, 0.0490251052956), - vec2(0.543333277288, 0.14558571287), - vec2(0.509798130208, 0.237722772229), - vec2(0.460773024913, 0.322636745447), - vec2(0.397747564417, 0.397747564417), - vec2(-0.460773024913, 0.322636745447), - vec2(0.322636745447, 0.460773024913), - vec2(-0.509798130208, 0.237722772229), - vec2(0.237722772229, 0.509798130208), - vec2(-0.543333277288, 0.14558571287), - vec2(0.14558571287, 0.543333277288), - vec2(-0.560359517677, 0.0490251052956), - vec2(0.0490251052956, 0.560359517677), - vec2(-0.560359517677, -0.0490251052956), - vec2(-0.0490251052956, 0.560359517677), - vec2(-0.543333277288, -0.14558571287), - vec2(-0.14558571287, 0.543333277288), - vec2(-0.509798130208, -0.237722772229), - vec2(-0.237722772229, 0.509798130208), - vec2(-0.460773024913, -0.322636745447), - vec2(-0.322636745447, 0.460773024913), - vec2(-0.397747564417, -0.397747564417), - vec2(-0.397747564417, 0.397747564417), - vec2(-0.322636745447, -0.460773024913), - vec2(-0.237722772229, -0.509798130208), - vec2(-0.14558571287, -0.543333277288), - vec2(-0.0490251052956, -0.560359517677), - vec2(0.0490251052956, -0.560359517677), - vec2(0.14558571287, -0.543333277288), - vec2(0.237722772229, -0.509798130208), - vec2(0.322636745447, -0.460773024913), - vec2(0.397747564417, -0.397747564417), - vec2(0.460773024913, -0.322636745447), - vec2(0.509798130208, -0.237722772229), - vec2(0.543333277288, -0.14558571287), - vec2(0.560359517677, -0.0490251052956), - vec2(0.685748328795, 0.0490456884495), - vec2(0.671788470355, 0.146138636568), - vec2(0.644152935937, 0.240256623474), - vec2(0.603404305327, 0.32948367837), - vec2(0.550372103135, 0.412003395727), - vec2(0.486135912066, 0.486135912066), - vec2(-0.550372103135, 0.412003395727), - vec2(0.412003395727, 0.550372103135), - vec2(-0.603404305327, 0.32948367837), - vec2(0.32948367837, 0.603404305327), - vec2(-0.644152935937, 0.240256623474), - vec2(0.240256623474, 0.644152935937), - vec2(-0.671788470355, 0.146138636568), - vec2(0.146138636568, 0.671788470355), - vec2(-0.685748328795, 0.0490456884495), - vec2(0.0490456884495, 0.685748328795), - vec2(-0.685748328795, -0.0490456884495), - vec2(-0.0490456884495, 0.685748328795), - vec2(-0.671788470355, -0.146138636568), - vec2(-0.146138636568, 0.671788470355), - vec2(-0.644152935937, -0.240256623474), - vec2(-0.240256623474, 0.644152935937), - vec2(-0.603404305327, -0.32948367837), - vec2(-0.32948367837, 0.603404305327), - vec2(-0.550372103135, -0.412003395727), - vec2(-0.412003395727, 0.550372103135), - vec2(-0.486135912066, -0.486135912066), - vec2(-0.486135912066, 0.486135912066), - vec2(-0.412003395727, -0.550372103135), - vec2(-0.32948367837, -0.603404305327), - vec2(-0.240256623474, -0.644152935937), - vec2(-0.146138636568, -0.671788470355), - vec2(-0.0490456884495, -0.685748328795), - vec2(0.0490456884495, -0.685748328795), - vec2(0.146138636568, -0.671788470355), - vec2(0.240256623474, -0.644152935937), - vec2(0.32948367837, -0.603404305327), - vec2(0.412003395727, -0.550372103135), - vec2(0.486135912066, -0.486135912066), - vec2(0.550372103135, -0.412003395727), - vec2(0.603404305327, -0.32948367837), - vec2(0.644152935937, -0.240256623474), - vec2(0.671788470355, -0.146138636568), - vec2(0.685748328795, -0.0490456884495), - vec2(0.811017637806, 0.0490575291556), - vec2(0.799191174395, 0.146457218224), - vec2(0.775710704038, 0.241721231257), - vec2(0.740918624869, 0.33346040443), - vec2(0.695322283745, 0.420336974019), - vec2(0.639586577995, 0.501084084011), - vec2(0.574524259714, 0.574524259714), - vec2(-0.639586577995, 0.501084084011), - vec2(0.501084084011, 0.639586577995), - vec2(-0.695322283745, 0.420336974019), - vec2(0.420336974019, 0.695322283745), - vec2(-0.740918624869, 0.33346040443), - vec2(0.33346040443, 0.740918624869), - vec2(-0.775710704038, 0.241721231257), - vec2(0.241721231257, 0.775710704038), - vec2(-0.799191174395, 0.146457218224), - vec2(0.146457218224, 0.799191174395), - vec2(-0.811017637806, 0.0490575291556), - vec2(0.0490575291556, 0.811017637806), - vec2(-0.811017637806, -0.0490575291556), - vec2(-0.0490575291556, 0.811017637806), - vec2(-0.799191174395, -0.146457218224), - vec2(-0.146457218224, 0.799191174395), - vec2(-0.775710704038, -0.241721231257), - vec2(-0.241721231257, 0.775710704038), - vec2(-0.740918624869, -0.33346040443), - vec2(-0.33346040443, 0.740918624869), - vec2(-0.695322283745, -0.420336974019), - vec2(-0.420336974019, 0.695322283745), - vec2(-0.639586577995, -0.501084084011), - vec2(-0.501084084011, 0.639586577995), - vec2(-0.574524259714, -0.574524259714), - vec2(-0.574524259714, 0.574524259714), - vec2(-0.501084084011, -0.639586577995), - vec2(-0.420336974019, -0.695322283745), - vec2(-0.33346040443, -0.740918624869), - vec2(-0.241721231257, -0.775710704038), - vec2(-0.146457218224, -0.799191174395), - vec2(-0.0490575291556, -0.811017637806), - vec2(0.0490575291556, -0.811017637806), - vec2(0.146457218224, -0.799191174395), - vec2(0.241721231257, -0.775710704038), - vec2(0.33346040443, -0.740918624869), - vec2(0.420336974019, -0.695322283745), - vec2(0.501084084011, -0.639586577995), - vec2(0.574524259714, -0.574524259714), - vec2(0.639586577995, -0.501084084011), - vec2(0.695322283745, -0.420336974019), - vec2(0.740918624869, -0.33346040443), - vec2(0.775710704038, -0.241721231257), - vec2(0.799191174395, -0.146457218224), - vec2(0.811017637806, -0.0490575291556), - vec2(0.936215188832, 0.0490649589778), - vec2(0.925957819308, 0.146657310975), - vec2(0.905555462146, 0.242642854784), - vec2(0.875231649841, 0.335969952699), - vec2(0.835318616427, 0.425616093506), - vec2(0.786253657449, 0.510599095327), - vec2(0.728574338866, 0.589987866609), - vec2(0.662912607362, 0.662912607362), - vec2(-0.728574338866, 0.589987866609), - vec2(0.589987866609, 0.728574338866), - vec2(-0.786253657449, 0.510599095327), - vec2(0.510599095327, 0.786253657449), - vec2(-0.835318616427, 0.425616093506), - vec2(0.425616093506, 0.835318616427), - vec2(-0.875231649841, 0.335969952699), - vec2(0.335969952699, 0.875231649841), - vec2(-0.905555462146, 0.242642854784), - vec2(0.242642854784, 0.905555462146), - vec2(-0.925957819308, 0.146657310975), - vec2(0.146657310975, 0.925957819308), - vec2(-0.936215188832, 0.0490649589778), - vec2(0.0490649589778, 0.936215188832), - vec2(-0.936215188832, -0.0490649589778), - vec2(-0.0490649589778, 0.936215188832), - vec2(-0.925957819308, -0.146657310975), - vec2(-0.146657310975, 0.925957819308), - vec2(-0.905555462146, -0.242642854784), - vec2(-0.242642854784, 0.905555462146), - vec2(-0.875231649841, -0.335969952699), - vec2(-0.335969952699, 0.875231649841), - vec2(-0.835318616427, -0.425616093506), - vec2(-0.425616093506, 0.835318616427), - vec2(-0.786253657449, -0.510599095327), - vec2(-0.510599095327, 0.786253657449), - vec2(-0.728574338866, -0.589987866609), - vec2(-0.589987866609, 0.728574338866), - vec2(-0.662912607362, -0.662912607362), - vec2(-0.662912607362, 0.662912607362), - vec2(-0.589987866609, -0.728574338866), - vec2(-0.510599095327, -0.786253657449), - vec2(-0.425616093506, -0.835318616427), - vec2(-0.335969952699, -0.875231649841), - vec2(-0.242642854784, -0.905555462146), - vec2(-0.146657310975, -0.925957819308), - vec2(-0.0490649589778, -0.936215188832), - vec2(0.0490649589778, -0.936215188832), - vec2(0.146657310975, -0.925957819308), - vec2(0.242642854784, -0.905555462146), - vec2(0.335969952699, -0.875231649841), - vec2(0.425616093506, -0.835318616427), - vec2(0.510599095327, -0.786253657449), - vec2(0.589987866609, -0.728574338866), - vec2(0.662912607362, -0.662912607362), - vec2(0.728574338866, -0.589987866609), - vec2(0.786253657449, -0.510599095327), - vec2(0.835318616427, -0.425616093506), - vec2(0.875231649841, -0.335969952699), - vec2(0.905555462146, -0.242642854784), - vec2(0.925957819308, -0.146657310975), - vec2(0.936215188832, -0.0490649589778)); diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl deleted file mode 100644 index 1014b25033a..00000000000 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ /dev/null @@ -1,51 +0,0 @@ - -uniform vec3 basecol; -uniform float metallic; -uniform float specular; -uniform float roughness; - -Closure nodetree_exec(void) -{ -#ifdef HAIR_SHADER - vec3 B = normalize(cross(worldNormal, hairTangent)); - float cos_theta; - if (hairThicknessRes == 1) { - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); - /* Random cosine normal distribution on the hair surface. */ - cos_theta = rand.x * 2.0 - 1.0; - } - else { - /* Shade as a cylinder. */ - cos_theta = hairThickTime / hairThickness; - } - float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta)); - vec3 N = normalize(worldNormal * sin_theta + B * cos_theta); - vec3 vN = mat3(ViewMatrix) * N; -#else - vec3 N = normalize(gl_FrontFacing ? worldNormal : -worldNormal); - vec3 vN = normalize(gl_FrontFacing ? viewNormal : -viewNormal); -#endif - - vec3 dielectric = vec3(0.034) * specular * 2.0; - vec3 albedo = mix(basecol, vec3(0.0), metallic); - vec3 f0 = mix(dielectric, basecol, metallic); - vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); - vec3 out_diff, out_spec, ssr_spec; - eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, true, out_diff, out_spec, ssr_spec); - - Closure cl = CLOSURE_DEFAULT; - cl.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) + - render_pass_diffuse_mask(albedo, out_diff * albedo); - closure_load_ssr_data(ssr_spec, roughness, N, viewCameraVec, 1, cl); - -#ifdef LOOKDEV - gl_FragDepth = 0.0; -#endif - -#ifdef HOLDOUT - cl = CLOSURE_DEFAULT; - cl.holdout = 1.0; -#endif - - return cl; -} diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl index d56890769a7..9c1ca17f87c 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -1,4 +1,8 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + uniform sampler2D colorBuffer; uniform sampler2D depthBuffer; @@ -18,9 +22,6 @@ uniform vec4 bokehParams[2]; uniform vec2 nearFar; /* Near & far view depths values */ -#define M_PI 3.1415926535897932384626433832795 -#define M_2PI 6.2831853071795864769252868 - /* -------------- Utils ------------- */ /* divide by sensor size to get the normalized size */ @@ -34,11 +35,6 @@ uniform vec2 nearFar; /* Near & far view depths values */ #define weighted_sum(a, b, c, d, e) \ (a * e.x + b * e.y + c * e.z + d * e.w) / max(1e-6, dot(e, vec4(1.0))); -float max_v4(vec4 v) -{ - return max(max(v.x, v.y), max(v.z, v.w)); -} - vec4 safe_color(vec4 c) { /* Clamp to avoid black square artifacts if a pixel goes NaN. */ diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl index d83b410125a..6e35d4a54ae 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_vert.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + uniform vec4 bokehParams[2]; #define bokeh_rotation bokehParams[0].x @@ -15,8 +17,6 @@ flat out float smoothFac; flat out ivec2 edge; out vec2 particlecoord; -#define M_PI 3.1415926535897932384626433832795 - /* Scatter pass, calculate a triangle covering the CoC. */ void main() { diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl index eea0ce0aae2..47fe21928b3 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl @@ -1,14 +1,34 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl) + /** * This shader only compute maximum horizon angles for each directions. * The final integration is done at the resolve stage with the shading normal. */ -uniform float rotationOffset; - out vec4 FragColor; -#ifdef DEBUG_AO uniform sampler2D normalBuffer; +#ifdef LAYERED_DEPTH +uniform sampler2DArray depthBufferLayered; +uniform int layer; +# define gtao_depthBuffer depthBufferLayered +# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c) + +#else +uniform sampler2D depthBuffer; +# define gtao_depthBuffer depthBuffer +# define gtao_textureLod(a, b, c) textureLod(a, b, c) + +#endif + +uniform float rotationOffset; + +#ifdef DEBUG_AO void main() { @@ -34,18 +54,6 @@ void main() #else -# ifdef LAYERED_DEPTH -uniform sampler2DArray depthBufferLayered; -uniform int layer; -# define gtao_depthBuffer depthBufferLayered -# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c) - -# else -# define gtao_depthBuffer depthBuffer -# define gtao_textureLod(a, b, c) textureLod(a, b, c) - -# endif - void main() { vec2 uvs = saturate(gl_FragCoord.xy / vec2(textureSize(gtao_depthBuffer, 0).xy)); diff --git a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl index edee55a07e0..7331f92ba6d 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_mist_frag.glsl @@ -1,5 +1,10 @@ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + /* Convert depth to Mist factor */ uniform vec3 mistSettings; +uniform sampler2D depthBuffer; #define mistStart mistSettings.x #define mistInvDistance mistSettings.y diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl index fbf507a2e40..3501a4448c5 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) + /* * Based on: * A Fast and Stable Feature-Aware Motion Blur Filter @@ -15,11 +17,6 @@ uniform sampler2D tileMaxBuffer; #define KERNEL 8 -/* TODO(fclem) deduplicate this code. */ -uniform sampler2DArray utilTex; -#define LUT_SIZE 64 -#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) - uniform float depthScale; uniform ivec2 tileBufferSize; uniform vec2 viewportSize; diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl index 598cc3e5183..f8dccb7511a 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -1,4 +1,11 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(raytrace_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) +#pragma BLENDER_REQUIRE(ssr_lib.glsl) + /* Based on Stochastic Screen Space Reflections * https://www.ea.com/frostbite/news/stochastic-screen-space-reflections */ @@ -131,7 +138,7 @@ void main() return; } - vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0); + vec4 rand = texelfetch_noise_tex(halfres_texel); /* Gives *perfect* reflection for very small roughness */ if (roughness < 0.04) { 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 e9da49c9eb9..2a53a4f119f 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -1,4 +1,9 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl) + /* Based on Separable SSS. by Jorge Jimenez and Diego Gutierrez */ #define MAX_SSS_SAMPLES 65 @@ -14,36 +19,16 @@ uniform sampler2D sssIrradiance; uniform sampler2D sssRadius; uniform sampler2D sssAlbedo; -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ - layout(location = 0) out vec4 sssRadiance; -float get_view_z_from_depth(float depth) -{ - if (ProjectionMatrix[3][3] == 0.0) { - float d = 2.0 * depth - 1.0; - return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); - } - else { - return viewVecs[0].z + depth * viewVecs[1].z; - } -} - -#define LUT_SIZE 64 -#define M_PI_2 1.5707963267948966 /* pi/2 */ -#define M_2PI 6.2831853071795865 /* 2*pi */ - 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; - float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r); + float depth = texture(depthBuffer, uvs).r; + float depth_view = get_view_z_from_depth(depth); float rand = texelfetch_noise_tex(gl_FragCoord.xy).r; #ifdef FIRST_PASS diff --git a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl index b44645174bd..28947e971d2 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_temporal_aa.glsl @@ -1,5 +1,11 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +uniform sampler2D colorBuffer; +uniform sampler2D depthBuffer; uniform sampler2D colorHistoryBuffer; + uniform mat4 prevViewProjectionMatrix; out vec4 FragColor; 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 6531ceb8dbe..c85eff92e37 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl @@ -1,11 +1,16 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(lights_lib.glsl) + in vec4 uvcoordsvar; out vec4 FragColor; +uniform sampler2D depthBuffer; uniform sampler1D sssTexProfile; uniform sampler2D sssRadius; - uniform sampler2DArray sssShadowCubes; uniform sampler2DArray sssShadowCascades; @@ -27,12 +32,6 @@ vec3 sss_profile(float s) return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb; } -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ - float light_translucent_power_with_falloff(LightData ld, vec3 N, vec4 l_vector) { float power, falloff; diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl index d927fd78d30..145939cefb2 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_resolve_frag.glsl @@ -1,4 +1,8 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +uniform sampler2D depthBuffer; + uniform mat4 prevViewProjMatrix; uniform mat4 currViewProjMatrixInv; uniform mat4 nextViewProjMatrix; diff --git a/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl index 0eb598521af..f52acaf6f7f 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_velocity_tile_frag.glsl @@ -148,4 +148,4 @@ void main() tileMaxVelocity = encode_velocity(max_motion); } -#endif
\ No newline at end of file +#endif diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl index b1d4de1c682..2274bf8b950 100644 --- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl @@ -1,44 +1,76 @@ -uniform sampler2DArray irradianceGrid; +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl) +#pragma BLENDER_REQUIRE(octahedron_lib.glsl) #define IRRADIANCE_LIB -#ifdef IRRADIANCE_CUBEMAP -struct IrradianceData { - vec3 color; -}; -#elif defined(IRRADIANCE_SH_L2) +/* ---------------------------------------------------------------------- */ +/** \name Structure + * \{ */ + +#if defined(IRRADIANCE_SH_L2) struct IrradianceData { vec3 shcoefs[9]; }; + #else /* defined(IRRADIANCE_HL2) */ struct IrradianceData { vec3 cubesides[3]; }; + #endif -IrradianceData load_irradiance_cell(int cell, vec3 N) +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Resources + * \{ */ + +uniform sampler2DArray irradianceGrid; + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Functions + * \{ */ + +vec4 irradiance_encode(vec3 rgb) { - /* Keep in sync with diffuse_filter_probe() */ + float maxRGB = max_v3(rgb); + float fexp = ceil(log2(maxRGB)); + return vec4(rgb / exp2(fexp), (fexp + 128.0) / 255.0); +} -#if defined(IRRADIANCE_CUBEMAP) +vec3 irradiance_decode(vec4 data) +{ + float fexp = data.a * 255.0 - 128.0; + return data.rgb * exp2(fexp); +} -# define AMBIANT_CUBESIZE 8 - ivec2 cell_co = ivec2(AMBIANT_CUBESIZE); - int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x; - cell_co.x *= cell % cell_per_row; - cell_co.y *= cell / cell_per_row; +vec4 visibility_encode(vec2 accum, float range) +{ + accum /= range; - vec2 texelSize = 1.0 / vec2(AMBIANT_CUBESIZE); + vec4 data; + data.x = fract(accum.x); + data.y = floor(accum.x) / 255.0; + data.z = fract(accum.y); + data.w = floor(accum.y) / 255.0; - vec2 uvs = mapping_octahedron(N, texelSize); - uvs *= vec2(AMBIANT_CUBESIZE) / vec2(textureSize(irradianceGrid, 0)); - uvs += vec2(cell_co) / vec2(textureSize(irradianceGrid, 0)); + return data; +} - IrradianceData ir; - ir.color = texture(irradianceGrid, vec3(uvs, 0.0)).rgb; +vec2 visibility_decode(vec4 data, float range) +{ + return (data.xz + data.yw * 255.0) * range; +} -#elif defined(IRRADIANCE_SH_L2) +IrradianceData load_irradiance_cell(int cell, vec3 N) +{ + /* Keep in sync with diffuse_filter_probe() */ + +#if defined(IRRADIANCE_SH_L2) ivec2 cell_co = ivec2(3, 3); int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x; @@ -164,9 +196,7 @@ vec3 hl2_basis(vec3 N, vec3 cubesides[3]) vec3 compute_irradiance(vec3 N, IrradianceData ird) { -#if defined(IRRADIANCE_CUBEMAP) - return ird.color; -#elif defined(IRRADIANCE_SH_L2) +#if defined(IRRADIANCE_SH_L2) return spherical_harmonics_L2(N, ird.shcoefs); #else /* defined(IRRADIANCE_HL2) */ return hl2_basis(N, ird.cubesides); @@ -178,3 +208,5 @@ vec3 irradiance_from_cell_get(int cell, vec3 ir_dir) IrradianceData ir_data = load_irradiance_cell(cell, ir_dir); return compute_irradiance(ir_dir, ir_data); } + +/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl index 96fe94fc41e..b0da4274a13 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl @@ -1,4 +1,7 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) + flat in int pid; in vec2 quadCoord; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl index db780714091..d06ad553ca4 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_vert.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + /* XXX TODO fix code duplication */ struct CubeData { vec4 position_type; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl index 296c1581545..bf45169ebaa 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl @@ -1,4 +1,8 @@ +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) + uniform samplerCube probeHdr; uniform int probeSize; uniform float lodFactor; @@ -111,32 +115,7 @@ void main() FragColor = vec4(sh, 1.0); #else -# if defined(IRRADIANCE_CUBEMAP) - /* Downside: Need lots of memory for storage, distortion due to octahedral mapping */ - const vec2 map_size = vec2(16.0); - const vec2 texelSize = 1.0 / map_size; - vec2 uvs = mod(gl_FragCoord.xy, map_size) * texelSize; - const float paddingSize = 1.0; - - /* Add a N pixel border to ensure filtering is correct - * for N mipmap levels. */ - uvs = (uvs - texelSize * paddingSize) / (1.0 - 2.0 * texelSize * paddingSize); - - /* edge mirroring : only mirror if directly adjacent - * (not diagonally adjacent) */ - vec2 m = abs(uvs - 0.5) + 0.5; - vec2 f = floor(m); - if (f.x - f.y != 0.0) { - uvs = 1.0 - uvs; - } - - /* clamp to [0-1] */ - uvs = fract(uvs); - - /* get cubemap vector */ - vec3 cubevec = octahedral_to_cubemap_proj(uvs); - -# elif defined(IRRADIANCE_HL2) +# if defined(IRRADIANCE_HL2) /* Downside: very very low resolution (6 texels), bleed lighting because of interpolation */ int x = int(gl_FragCoord.x) % 3; int y = int(gl_FragCoord.y) % 2; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl index 00eb3c7e200..ccb77427ed2 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl @@ -1,4 +1,7 @@ +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) + uniform samplerCube probeHdr; uniform float roughnessSquared; uniform float texelSize; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl index 5d8af21032a..8d7c58a93d5 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl @@ -1,4 +1,8 @@ +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) + uniform samplerCube probeDepth; uniform int outputSize; uniform float lodFactor; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl index f8bc1703c66..009ccf6535e 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl @@ -40,9 +40,6 @@ void main() for (int v = 0; v < 3; v++) { gl_Position = vPos[v]; worldPosition = x_axis[fFace] * vPos[v].x + y_axis[fFace] * vPos[v].y + maj_axes[fFace]; -#ifdef USE_ATTR - pass_attr(v); -#endif EmitVertex(); } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl index f9bcc718a1e..dc5ec1e40f5 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl @@ -1,3 +1,5 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) flat in int cellOffset; in vec2 quadCoord; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl index 4e500db827e..6fefe1319bd 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_vert.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + uniform float sphere_size; uniform int offset; uniform ivec3 grid_resolution; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl index 7cab5146b09..71e4d6e2c4a 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_fill_frag.glsl @@ -6,8 +6,6 @@ void main() { #if defined(IRRADIANCE_SH_L2) const ivec2 data_size = ivec2(3, 3); -#elif defined(IRRADIANCE_CUBEMAP) - const ivec2 data_size = ivec2(8, 8); #elif defined(IRRADIANCE_HL2) const ivec2 data_size = ivec2(3, 2); #endif diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 6c6db88139b..a2e25b83532 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -1,3 +1,12 @@ + +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl) +#pragma BLENDER_REQUIRE(cubemap_lib.glsl) +#pragma BLENDER_REQUIRE(ambient_occlusion_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) + /* ----------- Uniforms --------- */ uniform sampler2DArray probePlanars; @@ -73,12 +82,6 @@ struct GridData { # define MAX_PLANAR 1 #endif -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ - layout(std140) uniform probe_block { CubeData probes_data[MAX_PROBE]; @@ -218,7 +221,7 @@ void fallback_cubemap(vec3 N, inout vec4 spec_accum) { /* Specular probes */ - vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); + vec3 spec_dir = specular_dominant_dir(N, V, roughnessSquared); #ifdef SSR_AO vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); @@ -246,7 +249,6 @@ void fallback_cubemap(vec3 N, } } -#ifdef IRRADIANCE_LIB vec3 probe_evaluate_grid(GridData gd, vec3 W, vec3 N, vec3 localpos) { localpos = localpos * 0.5 + 0.5; @@ -308,5 +310,3 @@ vec3 probe_evaluate_world_diff(vec3 N) { return irradiance_from_cell_get(0, N); } - -#endif /* IRRADIANCE_LIB */ diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl index 2807488db6c..0a53abcb04a 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + uniform sampler2DArray probePlanars; in vec3 worldPosition; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl index 65506e5c7b1..6759c060259 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_vert.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + in vec3 pos; in int probe_id; diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index 3b9d0a8f2bc..949e4d8f04f 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -1,8 +1,76 @@ -uniform sampler2DArrayShadow shadowCubeTexture; -uniform sampler2DArrayShadow shadowCascadeTexture; +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(raytrace_lib.glsl) +#pragma BLENDER_REQUIRE(ltc_lib.glsl) + +#ifndef MAX_CASCADE_NUM +# define MAX_CASCADE_NUM 4 +#endif + +/* ---------------------------------------------------------------------- */ +/** \name Structure + * \{ */ + +struct LightData { + vec4 position_influence; /* w : InfluenceRadius (inversed and squared) */ + vec4 color_spec; /* w : Spec Intensity */ + vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */ + vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */ + vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */ + vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Light Type */ +}; + +/* convenience aliases */ +#define l_color color_spec.rgb +#define l_spec color_spec.a +#define l_position position_influence.xyz +#define l_influence position_influence.w +#define l_sizex rightvec_sizex.w +#define l_sizey upvec_sizey.w +#define l_right rightvec_sizex.xyz +#define l_up upvec_sizey.xyz +#define l_forward forwardvec_type.xyz +#define l_type forwardvec_type.w +#define l_spot_size spotdata_radius_shadow.x +#define l_spot_blend spotdata_radius_shadow.y +#define l_radius spotdata_radius_shadow.z +#define l_shadowid spotdata_radius_shadow.w + +struct ShadowData { + vec4 near_far_bias_id; + vec4 contact_shadow_data; +}; + +struct ShadowCubeData { + mat4 shadowmat; + vec4 position; +}; + +struct ShadowCascadeData { + mat4 shadowmat[MAX_CASCADE_NUM]; + vec4 split_start_distances; + vec4 split_end_distances; + vec4 shadow_vec_id; +}; + +/* convenience aliases */ +#define sh_near near_far_bias_id.x +#define sh_far near_far_bias_id.y +#define sh_bias near_far_bias_id.z +#define sh_data_index near_far_bias_id.w +#define sh_contact_dist contact_shadow_data.x +#define sh_contact_offset contact_shadow_data.y +#define sh_contact_spread contact_shadow_data.z +#define sh_contact_thickness contact_shadow_data.w +#define sh_shadow_vec shadow_vec_id.xyz +#define sh_tex_index shadow_vec_id.w + +/** \} */ -#define LAMPS_LIB +/* ---------------------------------------------------------------------- */ +/** \name Resources + * \{ */ layout(std140) uniform shadow_block { @@ -16,6 +84,15 @@ layout(std140) uniform light_block LightData lights_data[MAX_LIGHT]; }; +uniform sampler2DArrayShadow shadowCubeTexture; +uniform sampler2DArrayShadow shadowCascadeTexture; + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Shadow Functions + * \{ */ + /* type */ #define POINT 0.0 #define SUN 1.0 @@ -133,9 +210,11 @@ float sample_cascade_shadow(int shadow_id, vec3 W) #undef scube #undef scsmd -/* ----------------------------------------------------------- */ -/* --------------------- Light Functions --------------------- */ -/* ----------------------------------------------------------- */ +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Light Functions + * \{ */ /* From Frostbite PBR Course * Distance based attenuation @@ -258,7 +337,6 @@ float light_visibility(LightData ld, l_atten); } -#ifdef USE_LTC float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) { if (ld.l_type == AREA_RECT) { @@ -321,4 +399,5 @@ float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector) return ltc_evaluate_disk(N, V, ltc_matrix(ltc_mat), points); } } -#endif + +/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl index 8c876cf582c..9077b414026 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lookdev_world_frag.glsl @@ -1,20 +1,17 @@ -uniform float backgroundAlpha; -uniform vec3 color; - -out vec4 FragColor; +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) -#if defined(LOOKDEV_BG) || defined(LOOKDEV) +uniform sampler2D studioLight; +uniform float backgroundAlpha; uniform mat3 StudioLightMatrix; -uniform sampler2D image; uniform float studioLightIntensity = 1.0; uniform float studioLightBlur = 0.0; -in vec3 viewPosition; -# ifndef M_PI -# define M_PI 3.14159265358979323846 -# endif +out vec4 FragColor; vec3 background_transform_to_world(vec3 viewvec) { @@ -35,36 +32,20 @@ vec4 node_tex_environment_equirectangular(vec3 co, sampler2D ima) vec3 nco = normalize(co); float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - - /* Fix pole bleeding */ - float width = float(textureSize(ima, 0).x); - float texel_width = 1.0 / width; - v = clamp(v, texel_width, 1.0 - texel_width); - - /* Fix u = 0 seam */ - /* This is caused by texture filtering, since uv don't have smooth derivatives - * at u = 0 or 2PI, hardware filtering is using the smallest mipmap for certain - * texels. So we force the highest mipmap and don't do anisotropic filtering. */ return textureLod(ima, vec2(u, v), 0.0); } -#endif void main() { - vec3 background_color; + vec3 worldvec = background_transform_to_world(viewPosition); + vec3 background_color; #if defined(LOOKDEV_BG) - vec3 worldvec = background_transform_to_world(viewPosition); background_color = probe_evaluate_world_spec(worldvec, studioLightBlur).rgb; - background_color *= studioLightIntensity; - -#elif defined(LOOKDEV) - vec3 worldvec = background_transform_to_world(viewPosition); - background_color = node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image).rgb; - background_color *= studioLightIntensity; - #else - background_color = color; + worldvec = StudioLightMatrix * worldvec; + background_color = node_tex_environment_equirectangular(worldvec, studioLight).rgb; + background_color *= studioLightIntensity; #endif FragColor = vec4(clamp(background_color, vec3(0.0), vec3(1e10)), 1.0) * backgroundAlpha; diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl index dbfc7ad5a71..2750d42a74a 100644 --- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl @@ -8,12 +8,6 @@ #define USE_LTC -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ - /* Diffuse *clipped* sphere integral. */ float diffuse_sphere_integral(float avg_dir_z, float form_factor) { diff --git a/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl index 95cd69ba310..ef96bcbaedb 100644 --- a/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/object_motion_vert.glsl @@ -1,4 +1,7 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) + uniform mat4 currModelMatrix; uniform mat4 prevModelMatrix; uniform mat4 nextModelMatrix; @@ -19,6 +22,8 @@ out vec3 nextWorldPos; void main() { + GPU_INTEL_VERTEX_SHADER_WORKAROUND + #ifdef HAIR bool is_persp = (ProjectionMatrix[3][3] == 0.0); float time, thick_time, thickness; diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl index 9acd8f998f6..34999076f9c 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl @@ -1,4 +1,14 @@ +/* Required by some nodes. */ +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl) +#pragma BLENDER_REQUIRE(closure_lib.glsl) +#pragma BLENDER_REQUIRE(closure_lit_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) + #ifdef USE_ALPHA_HASH /* From the paper "Hashed Alpha Testing" by Chris Wyman and Morgan McGuire */ @@ -56,8 +66,6 @@ float hashed_alpha_threshold(vec3 co) #endif -#define NODETREE_EXEC - void main() { #if defined(USE_ALPHA_HASH) @@ -66,11 +74,9 @@ void main() float opacity = saturate(1.0 - avg(cl.transmittance)); -# if defined(USE_ALPHA_HASH) /* Hashed Alpha Testing */ if (opacity < hashed_alpha_threshold(worldPosition)) { discard; } -# endif #endif } diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl index 2c7e0aca3fb..f650e2eeb8c 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl @@ -1,16 +1,14 @@ +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + #ifndef HAIR_SHADER in vec3 pos; #endif void main() { -#ifdef GPU_INTEL - /* Due to some shader compiler bug, we somewhat - * need to access gl_VertexID to make it work. even - * if it's actually dead code. */ - gl_Position.x = float(gl_VertexID); -#endif + GPU_INTEL_VERTEX_SHADER_WORKAROUND #ifdef HAIR_SHADER float time, thick_time, thickness; @@ -34,5 +32,4 @@ void main() #ifdef CLIP_PLANES gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]); #endif - /* TODO motion vectors */ } diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index f88cfdf3787..39db39f8756 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -1,3 +1,11 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_uniforms_lib.glsl) + +uniform sampler2D maxzBuffer; +uniform sampler2DArray planarDepth; + #define MAX_STEP 256 float sample_depth(vec2 uv, int index, float lod) diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl new file mode 100644 index 00000000000..36cf3cecf40 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/renderpass_lib.glsl @@ -0,0 +1,43 @@ + +/* ---------------------------------------------------------------------- */ +/** \name Resources + * \{ */ + +layout(std140) uniform renderpass_block +{ + bool renderPassDiffuse; + bool renderPassDiffuseLight; + bool renderPassGlossy; + bool renderPassGlossyLight; + bool renderPassEmit; + bool renderPassSSSColor; + bool renderPassEnvironment; +}; + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Functions + * \{ */ + +vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light) +{ + return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0); +} + +vec3 render_pass_sss_mask(vec3 sss_color) +{ + 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); +} + +vec3 render_pass_emission_mask(vec3 emission_light) +{ + return renderPassEmit ? emission_light : vec3(0.0); +} + +/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 361963d5ac3..89a411bc7cb 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -1,3 +1,7 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) + #define PASS_POST_UNDEFINED 0 #define PASS_POST_ACCUMULATED_COLOR 1 #define PASS_POST_ACCUMULATED_LIGHT 2 @@ -9,6 +13,8 @@ uniform int postProcessType; uniform int currentSample; + +uniform sampler2D depthBuffer; uniform sampler2D inputBuffer; uniform sampler2D inputSecondLightBuffer; uniform sampler2D inputColorBuffer; diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl index 860ec9e1727..e0b9d4a60db 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl @@ -1,11 +1,11 @@ -out vec4 fragColor; +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) +#pragma BLENDER_REQUIRE(lights_lib.glsl) + +uniform sampler2D depthBuffer; -#ifndef UTIL_TEX -# define UTIL_TEX -uniform sampler2DArray utilTex; -# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) -#endif /* UTIL_TEX */ +out vec4 fragColor; void main() { diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index c42f905cf7e..0e342938396 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -1,39 +1,23 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) + in vec3 pos; in vec3 nor; -#ifdef MESH_SHADER -out vec3 worldPosition; -out vec3 viewPosition; -out vec3 worldNormal; -out vec3 viewNormal; -#endif - -#ifdef HAIR_SHADER -out vec3 hairTangent; -out float hairThickTime; -out float hairThickness; -out float hairTime; -flat out int hairStrandID; -#endif - void main() { -#ifdef GPU_INTEL - /* Due to some shader compiler bug, we somewhat - * need to access gl_VertexID to make it work. even - * if it's actually dead code. */ - gl_Position.x = float(gl_VertexID); -#endif + GPU_INTEL_VERTEX_SHADER_WORKAROUND #ifdef HAIR_SHADER hairStrandID = hair_get_strand_id(); - vec3 world_pos, binor; + vec3 pos, binor; hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), ModelMatrixInverse, ViewMatrixInverse[3].xyz, ViewMatrixInverse[2].xyz, - world_pos, + pos, hairTangent, binor, hairTime, @@ -41,6 +25,7 @@ void main() hairThickTime); worldNormal = cross(hairTangent, binor); + vec3 world_pos = pos; #else vec3 world_pos = point_object_to_world(pos); #endif @@ -57,7 +42,10 @@ void main() /* No need to normalize since this is just a rotation. */ viewNormal = normal_world_to_view(worldNormal); # ifdef USE_ATTR - pass_attr(pos); +# ifdef HAIR_SHADER + pos = hair_get_strand_pos(); +# endif + pass_attr(pos, NormalMatrix, ModelMatrixInverse); # endif #endif } diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl index 0591b247541..29495e98355 100644 --- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl @@ -1,3 +1,10 @@ + +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl) +#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) +#pragma BLENDER_REQUIRE(raytrace_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) + /* ------------ Refraction ------------ */ #define BTDF_BIAS 0.85 diff --git a/source/blender/draw/engines/eevee/shaders/surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl new file mode 100644 index 00000000000..e746acfdfa3 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/surface_frag.glsl @@ -0,0 +1,89 @@ + +/* Required by some nodes. */ +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) +#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl) + +#pragma BLENDER_REQUIRE(closure_lib.glsl) +#pragma BLENDER_REQUIRE(closure_lit_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) +#pragma BLENDER_REQUIRE(volumetric_lib.glsl) + +#ifdef USE_ALPHA_BLEND +/* Use dual source blending to be able to make a whole range of effects. */ +layout(location = 0, index = 0) out vec4 outRadiance; +layout(location = 0, index = 1) out vec4 outTransmittance; + +#else /* OPAQUE */ +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 + +#endif + +void main() +{ + Closure cl = nodetree_exec(); + + float holdout = saturate(1.0 - cl.holdout); + float transmit = saturate(avg(cl.transmittance)); + float alpha = 1.0 - transmit; + +#ifdef USE_ALPHA_BLEND + vec2 uvs = gl_FragCoord.xy * volCoordScale.zw; + vec3 vol_transmit, vol_scatter; + volumetric_resolve(uvs, gl_FragCoord.z, vol_transmit, vol_scatter); + + /* Removes part of the volume scattering that have + * already been added to the destination pixels. + * Since we do that using the blending pipeline we need to account for material transmittance. */ + vol_scatter -= vol_scatter * cl.transmittance; + + cl.radiance = cl.radiance * holdout * vol_transmit + vol_scatter; + outRadiance = vec4(cl.radiance, alpha * holdout); + 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 +#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 + /* SSRefraction pass is done after the SSS pass. + * In order to not loose 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; +#endif + +#ifndef USE_ALPHA_BLEND + float alpha_div = 1.0 / max(1e-8, alpha); + outRadiance.rgb *= alpha_div; + ssrData.rgb *= alpha_div; +# ifdef USE_SSS + sssAlbedo.rgb *= alpha_div; +# endif +#endif + +#ifdef LOOKDEV + /* Lookdev spheres are rendered in front. */ + gl_FragDepth = 0.0; +#endif +} diff --git a/source/blender/draw/engines/eevee/shaders/surface_geom.glsl b/source/blender/draw/engines/eevee/shaders/surface_geom.glsl new file mode 100644 index 00000000000..ad437dca79a --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/surface_geom.glsl @@ -0,0 +1,46 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) + +layout(triangles) in; +layout(triangle_strip, max_vertices = 3) out; + +RESOURCE_ID_VARYING + +/* Only used to compute barycentric coordinates. */ + +void main() +{ +#ifdef DO_BARYCENTRIC_DISTANCES + dataAttrOut.barycentricDist = calc_barycentric_distances( + dataIn[0].worldPosition, dataIn[1].worldPosition, dataIn[2].worldPosition); +#endif + + PASS_RESOURCE_ID + +#ifdef USE_ATTR + pass_attr(0); +#endif + PASS_SURFACE_INTERFACE(0); + gl_Position = gl_in[0].gl_Position; + gl_ClipDistance[0] = gl_in[0].gl_ClipDistance[0]; + EmitVertex(); + +#ifdef USE_ATTR + pass_attr(1); +#endif + PASS_SURFACE_INTERFACE(1); + gl_Position = gl_in[1].gl_Position; + gl_ClipDistance[0] = gl_in[1].gl_ClipDistance[0]; + EmitVertex(); + +#ifdef USE_ATTR + pass_attr(2); +#endif + PASS_SURFACE_INTERFACE(2); + gl_Position = gl_in[2].gl_Position; + gl_ClipDistance[0] = gl_in[2].gl_ClipDistance[0]; + EmitVertex(); + + EndPrimitive(); +} diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl new file mode 100644 index 00000000000..b93a3a23eff --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl @@ -0,0 +1,43 @@ +/** This describe the entire interface of the shader. */ + +/* Samplers */ +uniform sampler2D colorBuffer; +uniform sampler2D depthBuffer; + +/* Uniforms */ +uniform float refractionDepth; + +#define SURFACE_INTERFACE \ + vec3 worldPosition; \ + vec3 viewPosition; \ + vec3 worldNormal; \ + vec3 viewNormal; + +#ifdef 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; + +#else + +IN_OUT ShaderStageInterface{SURFACE_INTERFACE}; + +#endif + +#ifdef HAIR_SHADER +IN_OUT ShaderHairInterface +{ + /* world space */ + vec3 hairTangent; + float hairThickTime; + float hairThickness; + float hairTime; + flat int hairStrandID; +}; +#endif diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl index 1b94fc2bee1..0ad1393dd70 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_vert.glsl @@ -1,32 +1,20 @@ +#pragma BLENDER_REQUIRE(common_hair_lib.glsl) +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(surface_lib.glsl) + #ifndef HAIR_SHADER in vec3 pos; in vec3 nor; #endif -#ifdef MESH_SHADER -out vec3 worldPosition; -out vec3 viewPosition; -out vec3 worldNormal; -out vec3 viewNormal; -#endif - -#ifdef HAIR_SHADER -out vec3 hairTangent; -out float hairThickTime; -out float hairThickness; -out float hairTime; -flat out int hairStrandID; -#endif +RESOURCE_ID_VARYING void main() { -#ifdef GPU_INTEL - /* Due to some shader compiler bug, we somewhat - * need to access gl_VertexID to make it work. even - * if it's actually dead code. */ - gl_Position.x = float(gl_VertexID); -#endif + GPU_INTEL_VERTEX_SHADER_WORKAROUND + + PASS_RESOURCE_ID #ifdef HAIR_SHADER hairStrandID = hair_get_strand_id(); @@ -63,7 +51,10 @@ void main() /* No need to normalize since this is just a rotation. */ viewNormal = normal_world_to_view(worldNormal); # ifdef USE_ATTR - pass_attr(pos); +# ifdef HAIR_SHADER + pos = hair_get_strand_pos(); +# endif + pass_attr(pos, NormalMatrix, ModelMatrixInverse); # endif #endif } diff --git a/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl index 02ad2170f06..0c01c46c2ba 100644 --- a/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl @@ -1,11 +1,11 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + uniform sampler2D blueNoise; uniform vec3 offsets; out vec4 FragColor; -#define M_2PI 6.28318530717958647692 - void main(void) { vec3 blue_noise = texelFetch(blueNoise, ivec2(gl_FragCoord.xy), 0).xyz; diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index 312fc07054a..bac69ab0355 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -1,9 +1,10 @@ +#pragma BLENDER_REQUIRE(volumetric_lib.glsl) +#pragma BLENDER_REQUIRE(closure_lib.glsl) + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ -#define NODETREE_EXEC - #ifdef MESH_SHADER uniform vec3 volumeOrcoLoc; uniform vec3 volumeOrcoSize; diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl index 96b891c929f..30cda401284 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_geom.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + #ifdef MESH_SHADER /* TODO tight slices */ layout(triangles) in; @@ -12,12 +14,16 @@ in vec4 vPos[]; flat out int slice; +RESOURCE_ID_VARYING + #ifdef MESH_SHADER /* TODO tight slices */ void main() { gl_Layer = slice = int(vPos[0].z); + PASS_RESOURCE_ID + # ifdef USE_ATTR pass_attr(0); # endif @@ -48,6 +54,8 @@ void main() { gl_Layer = slice = int(vPos[0].z); + PASS_RESOURCE_ID + # ifdef USE_ATTR pass_attr(0); # 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 c3c442e7b69..f4276bd61bd 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(volumetric_lib.glsl) + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ @@ -11,9 +13,11 @@ uniform sampler3D volumeExtinction; #ifdef USE_VOLUME_OPTI uniform layout(binding = 0, r11f_g11f_b10f) writeonly restrict image3D finalScattering_img; uniform layout(binding = 1, r11f_g11f_b10f) writeonly restrict image3D finalTransmittance_img; + vec3 finalScattering; vec3 finalTransmittance; #else + flat in int slice; layout(location = 0) out vec3 finalScattering; diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 40eb3da42d1..9b852a57ec4 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -1,4 +1,8 @@ +#pragma BLENDER_REQUIRE(lights_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ @@ -58,7 +62,6 @@ float phase_function(vec3 v, vec3 l, float g) return (1 - sqr_g) / max(1e-8, 4.0 * M_PI * pow(1 + sqr_g - 2 * g * cos_theta, 3.0 / 2.0)); } -#ifdef LAMPS_LIB vec3 light_volume(LightData ld, vec4 l_vector) { float power; @@ -95,7 +98,7 @@ vec3 light_volume(LightData ld, vec4 l_vector) return tint * lum; } -# define VOLUMETRIC_SHADOW_MAX_STEP 32.0 +#define VOLUMETRIC_SHADOW_MAX_STEP 32.0 vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction) { @@ -109,7 +112,7 @@ vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction) vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D volume_extinction) { -# if defined(VOLUME_SHADOW) +#if defined(VOLUME_SHADOW) /* Heterogeneous volume shadows */ float dd = l_vector.w / volShadowSteps; vec3 L = l_vector.xyz * l_vector.w; @@ -120,27 +123,24 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v shadow *= exp(-s_extinction * dd); } return shadow; -# else +#else return vec3(1.0); -# endif /* VOLUME_SHADOW */ +#endif /* VOLUME_SHADOW */ } -#endif -#ifdef IRRADIANCE_LIB vec3 irradiance_volumetric(vec3 wpos) { -# ifdef IRRADIANCE_HL2 +#ifdef IRRADIANCE_HL2 IrradianceData ir_data = load_irradiance_cell(0, vec3(1.0)); vec3 irradiance = ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]; ir_data = load_irradiance_cell(0, vec3(-1.0)); irradiance += ir_data.cubesides[0] + ir_data.cubesides[1] + ir_data.cubesides[2]; irradiance *= 0.16666666; /* 1/6 */ return irradiance; -# else +#else return vec3(0.0); -# endif -} #endif +} uniform sampler3D inScattering; uniform sampler3D inTransmittance; diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl index 1ff7e848c40..6ab21587c9a 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(volumetric_lib.glsl) + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl index 9621fa1cc0d..806f1b5b205 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(volumetric_lib.glsl) + /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl index b96360febb0..b70747ecec3 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl @@ -1,6 +1,10 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + out vec4 vPos; +RESOURCE_ID_VARYING + void main() { /* Generate Triangle : less memory fetches from a VBO */ @@ -25,7 +29,9 @@ void main() vPos.z = float(t_id); vPos.w = 1.0; + PASS_RESOURCE_ID + #ifdef USE_ATTR - pass_attr(vec3(0.0)); + pass_attr(vec3(0.0), mat3(1), mat4(1)); #endif } diff --git a/source/blender/draw/engines/external/external_engine.h b/source/blender/draw/engines/external/external_engine.h index 01edea38ab0..c645fb99e0e 100644 --- a/source/blender/draw/engines/external/external_engine.h +++ b/source/blender/draw/engines/external/external_engine.h @@ -20,9 +20,6 @@ * \ingroup draw_engine */ -#ifndef __EXTERNAL_ENGINE_H__ -#define __EXTERNAL_ENGINE_H__ +#pragma once extern RenderEngineType DRW_engine_viewport_external_type; - -#endif /* __EXTERNAL_ENGINE_H__ */ diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index d97bf9255d2..41a7196cb90 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -106,7 +106,7 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) copy_v3_v3(tgp_ob->plane_mat[3], center); /* Add to corresponding list if is in front. */ - if (ob->dtx & OB_DRAWXRAY) { + if (ob->dtx & OB_DRAW_IN_FRONT) { BLI_LINKS_APPEND(&pd->tobjects_infront, tgp_ob); } else { @@ -132,12 +132,11 @@ static int gpencil_tobject_dist_sort(const void *a, const void *b) if (ob_a->camera_z > ob_b->camera_z) { return 1; } - else if (ob_a->camera_z < ob_b->camera_z) { + if (ob_a->camera_z < ob_b->camera_z) { return -1; } - else { - return 0; - } + + return 0; } void gpencil_object_cache_sort(GPENCIL_PrivateData *pd) @@ -193,7 +192,7 @@ static float gpencil_layer_final_opacity_get(const GPENCIL_PrivateData *pd, if (is_obact && is_fade) { return gpl->opacity * pd->fade_layer_opacity; } - else if (!is_obact && (pd->fade_gp_object_opacity > -1.0f)) { + if (!is_obact && (pd->fade_gp_object_opacity > -1.0f)) { return gpl->opacity * pd->fade_gp_object_opacity; } } @@ -258,7 +257,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, { bGPdata *gpd = (bGPdata *)ob->data; - const bool is_in_front = (ob->dtx & OB_DRAWXRAY); + const bool is_in_front = (ob->dtx & OB_DRAW_IN_FRONT); const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0; const bool overide_vertcol = (pd->v3d_color_type != -1); const bool is_vert_col_mode = (pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) || diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 6e6b35e19ca..51152475a06 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -63,7 +63,7 @@ static struct GPUTexture *gpencil_image_texture_get(Image *image, bool *r_alpha_ ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); if (ibuf != NULL && ibuf->rect != NULL) { - gpu_tex = GPU_texture_from_blender(image, &iuser, ibuf, GL_TEXTURE_2D); + gpu_tex = BKE_image_get_gpu_texture(image, &iuser, ibuf); *r_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL); } BKE_image_release_ibuf(image, ibuf, lock); @@ -359,12 +359,11 @@ static float light_power_get(const Light *la) if (la->type == LA_AREA) { return 1.0f / (4.0f * M_PI); } - else if (la->type == LA_SPOT || la->type == LA_LOCAL) { + if (la->type == LA_SPOT || la->type == LA_LOCAL) { return 1.0f / (4.0f * M_PI * M_PI); } - else { - return 1.0f / M_PI; - } + + return 1.0f / M_PI; } void gpencil_light_pool_populate(GPENCIL_LightPool *lightpool, Object *ob) diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index dded83bacf1..dbad226099e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -525,12 +525,6 @@ static void gpencil_stroke_cache_populate(bGPDlayer *gpl, DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", tex_stroke); iter->tex_stroke = tex_stroke; } - - /* TODO(fclem): This is a quick workaround but - * ideally we should have this as a permanent bind. */ - const bool is_masked = iter->tgp_ob->layers.last->mask_bits != NULL; - GPUTexture **mask_tex = (is_masked) ? &iter->pd->mask_tx : &iter->pd->dummy_tx; - DRW_shgroup_uniform_texture_ref(iter->grp, "gpMaskTexture", mask_tex); } bool do_sbuffer = (iter->do_sbuffer_call == DRAW_NOW); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 7baca28dca3..a406df530fc 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __GPENCIL_ENGINE_H__ -#define __GPENCIL_ENGINE_H__ +#pragma once #include "DNA_gpencil_types.h" @@ -439,5 +438,3 @@ void GPENCIL_render_to_image(void *vedata, void gpencil_light_pool_free(void *storage); void gpencil_material_pool_free(void *storage); GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void); - -#endif /* __GPENCIL_ENGINE_H__ */ diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index bb91bdbe396..c3294f88acf 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -143,9 +143,11 @@ void GPENCIL_render_init(GPENCIL_Data *vedata, int w = BLI_rcti_size_x(rect); int h = BLI_rcti_size_y(rect); if (pix_col) { + GPU_texture_bind(txl->render_color_tx, 0); GPU_texture_update_sub(txl->render_color_tx, GPU_DATA_FLOAT, pix_col, x, y, 0, w, h, 0); } if (pix_z) { + GPU_texture_bind(txl->render_depth_tx, 0); GPU_texture_update_sub(txl->render_depth_tx, GPU_DATA_FLOAT, pix_z, x, y, 0, w, h, 0); } } @@ -235,6 +237,7 @@ static void GPENCIL_render_result_combined(struct RenderLayer *rl, BLI_rcti_size_y(rect), 4, 0, + GPU_DATA_FLOAT, rp->rect); } diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 1e75f6dd5bb..c19bf1e7b50 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -137,24 +137,20 @@ void blend_mode_output( } } -#ifdef GPU_VERTEX_SHADER -# define IN_OUT out -#else -# define IN_OUT in -#endif - -/* Shader interface. */ -IN_OUT vec4 finalColorMul; -IN_OUT vec4 finalColorAdd; -IN_OUT vec3 finalPos; -IN_OUT vec2 finalUvs; -noperspective IN_OUT float strokeThickness; -noperspective IN_OUT float strokeHardeness; -flat IN_OUT vec2 strokeAspect; -flat IN_OUT vec2 strokePt1; -flat IN_OUT vec2 strokePt2; -flat IN_OUT int matFlag; -flat IN_OUT float depth; +IN_OUT ShaderStageInterface +{ + vec4 finalColorMul; + vec4 finalColorAdd; + vec3 finalPos; + vec2 finalUvs; + noperspective float strokeThickness; + noperspective float strokeHardeness; + flat vec2 strokeAspect; + flat vec2 strokePt1; + flat vec2 strokePt2; + flat int matFlag; + flat float depth; +}; #ifdef GPU_FRAGMENT_SHADER @@ -491,7 +487,7 @@ void stroke_vertex() vec2 screen_ofs = miter * y; - /* Reminder: we packed the cap flag into the sign of stength and thickness sign. */ + /* Reminder: we packed the cap flag into the sign of strength and thickness sign. */ if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) || (miter_break && !is_stroke_start && !is_stroke_end)) { screen_ofs += line * x; diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 7ccb5d5a753..1a3bfb9934c 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -178,6 +178,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) #define BUF_INSTANCE DRW_shgroup_call_buffer_instance #define BUF_LINE(grp, format) DRW_shgroup_call_buffer(grp, format, GPU_PRIM_LINES) +#define BUF_POINT(grp, format) DRW_shgroup_call_buffer(grp, format, GPU_PRIM_POINTS) { format = formats->instance_bone; @@ -923,12 +924,11 @@ static float get_bone_wire_thickness(const ArmatureDrawContext *ctx, int bonefla if (ctx->const_color) { return ctx->const_wire; } - else if (boneflag & (BONE_DRAW_ACTIVE | BONE_SELECTED)) { + if (boneflag & (BONE_DRAW_ACTIVE | BONE_SELECTED)) { return 2.0f; } - else { - return 1.0f; - } + + return 1.0f; } static const float *get_bone_wire_color(const ArmatureDrawContext *ctx, @@ -2118,10 +2118,11 @@ static void armature_context_setup(ArmatureDrawContext *ctx, const bool do_envelope_dist, const bool is_edit_mode, const bool is_pose_mode, - float *const_color) + const float *const_color) { const bool is_object_mode = !do_envelope_dist; - const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0 || (pd->armature.do_pose_xray && is_pose_mode); + const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0 || + (pd->armature.do_pose_xray && is_pose_mode); const bool draw_as_wire = (ob->dt < OB_SOLID); const bool is_filled = (!pd->armature.transparent && !draw_as_wire) || !is_object_mode; const bool is_transparent = pd->armature.transparent || (draw_as_wire && !is_object_mode); @@ -2217,13 +2218,13 @@ static bool POSE_is_driven_by_active_armature(Object *ob) } return is_active; } - else { - Object *ob_mesh_deform = BKE_modifiers_is_deformed_by_meshdeform(ob); - if (ob_mesh_deform) { - /* Recursive. */ - return POSE_is_driven_by_active_armature(ob_mesh_deform); - } + + Object *ob_mesh_deform = BKE_modifiers_is_deformed_by_meshdeform(ob); + if (ob_mesh_deform) { + /* Recursive. */ + return POSE_is_driven_by_active_armature(ob_mesh_deform); } + return false; } diff --git a/source/blender/draw/engines/overlay/overlay_edit_curve.c b/source/blender/draw/engines/overlay/overlay_edit_curve.c index 9a79c78c996..6d907646817 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_curve.c +++ b/source/blender/draw/engines/overlay/overlay_edit_curve.c @@ -78,7 +78,7 @@ void OVERLAY_edit_curve_cache_populate(OVERLAY_Data *vedata, Object *ob) { OVERLAY_PrivateData *pd = vedata->stl->pd; bool draw_normals = (pd->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0; - bool do_xray = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; Curve *cu = ob->data; struct GPUBatch *geom; diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index fd872108b00..ebc8a2f97ef 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -270,7 +270,7 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob) struct GPUBatch *geom = NULL; bool draw_as_solid = (ob->dt > OB_WIRE); - bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; bool do_occlude_wire = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0; bool do_show_mesh_analysis = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_STATVIS) != 0; bool fnormals_do = (pd->edit_mesh.flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0; @@ -312,7 +312,7 @@ void OVERLAY_edit_mesh_cache_populate(OVERLAY_Data *vedata, Object *ob) overlay_edit_mesh_add_ob_to_pass(pd, ob, do_in_front); } - pd->edit_mesh.ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0; + pd->edit_mesh.ghost_ob += (ob->dtx & OB_DRAW_IN_FRONT) ? 1 : 0; pd->edit_mesh.edit_ob += 1; if (DRW_state_show_text() && (pd->edit_mesh.flag & OVERLAY_EDIT_TEXT)) { diff --git a/source/blender/draw/engines/overlay/overlay_edit_text.c b/source/blender/draw/engines/overlay/overlay_edit_text.c index 4ee936f5ce6..6ddd0e6d9be 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_text.c +++ b/source/blender/draw/engines/overlay/overlay_edit_text.c @@ -182,7 +182,7 @@ void OVERLAY_edit_text_cache_populate(OVERLAY_Data *vedata, Object *ob) OVERLAY_PrivateData *pd = vedata->stl->pd; Curve *cu = ob->data; struct GPUBatch *geom; - bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f; if ((cu->flag & CU_FAST) || !has_surface) { diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index e76b3c82c1d..bc96a03da31 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -182,7 +182,6 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_motion_path_cache_init(vedata); OVERLAY_outline_cache_init(vedata); OVERLAY_particle_cache_init(vedata); - OVERLAY_pointcloud_cache_init(vedata); OVERLAY_wireframe_cache_init(vedata); } @@ -403,12 +402,6 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) OVERLAY_particle_cache_populate(vedata, ob); } - /* TODO: these should not be overlays, just here for testing since it's - * easier to implement than integrating it into eevee/workbench. */ - if (ob->type == OB_POINTCLOUD) { - OVERLAY_pointcloud_cache_populate(vedata, ob); - } - /* Relationship, object center, bounbox ... */ if (!pd->hide_overlays) { OVERLAY_extra_cache_populate(vedata, ob); @@ -482,7 +475,6 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_armature_draw(vedata); OVERLAY_particle_draw(vedata); OVERLAY_metaball_draw(vedata); - OVERLAY_pointcloud_draw(vedata); OVERLAY_gpencil_draw(vedata); OVERLAY_extra_draw(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_engine.h b/source/blender/draw/engines/overlay/overlay_engine.h index 795e3805037..f9f6ee0511c 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.h +++ b/source/blender/draw/engines/overlay/overlay_engine.h @@ -20,9 +20,6 @@ * \ingroup draw_engine */ -#ifndef __OVERLAY_ENGINE_H__ -#define __OVERLAY_ENGINE_H__ +#pragma once extern DrawEngineType draw_engine_overlay_type; - -#endif /* __OVERLAY_ENGINE_H__ */ diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index c0407345729..c7c4e2b1a3a 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -53,8 +53,6 @@ #include "ED_view3d.h" -#include "GPU_draw.h" - #include "overlay_private.h" #include "draw_common.h" @@ -199,6 +197,9 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) cb->extra_loose_points = grp = DRW_shgroup_create(sh, extra_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + + /* Buffer access for drawing isolated points, matching `extra_lines`. */ + cb->extra_points = BUF_POINT(grp, formats->point_extra); } { format = formats->pos; @@ -230,6 +231,11 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) } } +void OVERLAY_extra_point(OVERLAY_ExtraCallBuffers *cb, const float point[3], const float color[4]) +{ + DRW_buffer_add_entry(cb->extra_points, point, color); +} + void OVERLAY_extra_line_dashed(OVERLAY_ExtraCallBuffers *cb, const float start[3], const float end[3], @@ -250,7 +256,7 @@ void OVERLAY_extra_line(OVERLAY_ExtraCallBuffers *cb, OVERLAY_ExtraCallBuffers *OVERLAY_extra_call_buffer_get(OVERLAY_Data *vedata, Object *ob) { - bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; OVERLAY_PrivateData *pd = vedata->stl->pd; return &pd->extra_call_buffers[do_in_front]; } @@ -539,7 +545,7 @@ static void OVERLAY_forcefield(OVERLAY_ExtraCallBuffers *cb, Object *ob, ViewLay if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path && ob->runtime.curve_cache->path->data) { instdata.size_x = instdata.size_y = instdata.size_z = pd->f_strength; - float pos[3], tmp[3]; + float pos[4], tmp[3]; where_on_path(ob, 0.0f, pos, tmp, NULL, NULL, NULL); copy_v3_v3(instdata.pos, ob->obmat[3]); translate_m4(instdata.mat, pos[0], pos[1], pos[2]); @@ -1012,9 +1018,8 @@ static float camera_offaxis_shiftx_get(Scene *scene, const float width = instdata->corner_x * 2.0f; return delta_shiftx * width; } - else { - return 0.0; - } + + return 0.0; } /** * Draw the stereo 3d support elements (cameras, plane, volume). @@ -1276,6 +1281,19 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, OVERLAY_extra_line_dashed(cb, parent_pos, ob->obmat[3], relation_color); } + /* Drawing the hook lines. */ + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + float center[3]; + mul_v3_m4v3(center, ob->obmat, hmd->cent); + if (hmd->object) { + OVERLAY_extra_line_dashed(cb, hmd->object->obmat[3], center, relation_color); + } + OVERLAY_extra_point(cb, center, relation_color); + } + } + if (ob->rigidbody_constraint) { Object *rbc_ob1 = ob->rigidbody_constraint->ob1; Object *rbc_ob2 = ob->rigidbody_constraint->ob2; @@ -1318,7 +1336,7 @@ static void OVERLAY_relationship_lines(OVERLAY_ExtraCallBuffers *cb, else { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(curcon); - if ((cti && cti->get_constraint_targets) && (curcon->ui_expand_flag && (1 << 0))) { + if ((cti && cti->get_constraint_targets) && (curcon->ui_expand_flag & (1 << 0))) { ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -1356,7 +1374,7 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb, Object *ob, ModifierData *md, Scene *scene, - float *color) + const float *color) { FluidModifierData *fmd = (FluidModifierData *)md; FluidDomainSettings *fds = fmd->domain; @@ -1401,7 +1419,7 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb, line_count /= fds->res[axis]; } - GPU_create_smoke_velocity(fmd); + DRW_smoke_ensure_velocity(fmd); GPUShader *sh = OVERLAY_shader_volume_velocity(use_needle); DRWShadingGroup *grp = DRW_shgroup_create(sh, data->psl->extra_ps[0]); @@ -1431,7 +1449,7 @@ static void OVERLAY_volume_free_smoke_textures(OVERLAY_Data *data) LinkData *link; while ((link = BLI_pophead(&data->stl->pd->smoke_domains))) { FluidModifierData *fmd = (FluidModifierData *)link->data; - GPU_free_smoke_velocity(fmd); + DRW_smoke_free_velocity(fmd); MEM_freeN(link); } } diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c index 4eb4b8ae85b..cfeaf8e1927 100644 --- a/source/blender/draw/engines/overlay/overlay_facing.c +++ b/source/blender/draw/engines/overlay/overlay_facing.c @@ -60,7 +60,7 @@ void OVERLAY_facing_cache_populate(OVERLAY_Data *vedata, Object *ob) const DRWContextState *draw_ctx = DRW_context_state_get(); const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && !DRW_state_is_image_render(); - const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; + const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; if (use_sculpt_pbvh) { DRW_shgroup_call_sculpt(pd->facing_grp[is_xray], ob, false, false); diff --git a/source/blender/draw/engines/overlay/overlay_image.c b/source/blender/draw/engines/overlay/overlay_image.c index a754f7cbd49..06d92f486d0 100644 --- a/source/blender/draw/engines/overlay/overlay_image.c +++ b/source/blender/draw/engines/overlay/overlay_image.c @@ -109,13 +109,12 @@ static eStereoViews camera_background_images_stereo_eye(const Scene *scene, cons if ((scene->r.scemode & R_MULTIVIEW) == 0) { return STEREO_LEFT_ID; } - else if (v3d->stereo3d_camera != STEREO_3D_ID) { + if (v3d->stereo3d_camera != STEREO_3D_ID) { /* show only left or right camera */ return v3d->stereo3d_camera; } - else { - return v3d->multiview_eye; - } + + return v3d->multiview_eye; } static void camera_background_images_stereo_setup(const Scene *scene, @@ -162,9 +161,8 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp /* Frame is out of range, dont show. */ return NULL; } - else { - camera_background_images_stereo_setup(scene, draw_ctx->v3d, image, iuser); - } + + camera_background_images_stereo_setup(scene, draw_ctx->v3d, image, iuser); iuser->scene = draw_ctx->scene; ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); @@ -175,7 +173,7 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp } width = ibuf->x; height = ibuf->y; - tex = GPU_texture_from_blender(image, iuser, ibuf, GL_TEXTURE_2D); + tex = BKE_image_get_gpu_texture(image, iuser, ibuf); BKE_image_release_ibuf(image, ibuf, lock); iuser->scene = NULL; @@ -203,7 +201,7 @@ static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgp } BKE_movieclip_user_set_frame(&bgpic->cuser, ctime); - tex = GPU_texture_from_movieclip(clip, &bgpic->cuser, GL_TEXTURE_2D); + tex = BKE_movieclip_get_gpu_texture(clip, &bgpic->cuser); if (tex == NULL) { return NULL; } @@ -232,7 +230,7 @@ static void OVERLAY_image_free_movieclips_textures(OVERLAY_Data *data) LinkData *link; while ((link = BLI_pophead(&data->stl->pd->bg_movie_clips))) { MovieClip *clip = (MovieClip *)link->data; - GPU_free_texture_movieclip(clip); + BKE_movieclip_free_gputexture(clip); MEM_freeN(link); } } @@ -383,7 +381,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) if (ima != NULL) { ImageUser iuser = *ob->iuser; camera_background_images_stereo_setup(draw_ctx->scene, draw_ctx->v3d, ima, &iuser); - tex = GPU_texture_from_blender(ima, &iuser, NULL, GL_TEXTURE_2D); + tex = BKE_image_get_gpu_texture(ima, &iuser, NULL); if (tex) { size[0] = GPU_texture_orig_width(tex); size[1] = GPU_texture_orig_height(tex); @@ -405,7 +403,7 @@ void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) /* Use the actual depth if we are doing depth tests to determine the distance to the object */ char depth_mode = DRW_state_is_depth() ? OB_EMPTY_IMAGE_DEPTH_DEFAULT : ob->empty_image_depth; DRWPass *pass = NULL; - if ((ob->dtx & OB_DRAWXRAY) != 0) { + if ((ob->dtx & OB_DRAW_IN_FRONT) != 0) { /* Object In Front overrides image empty depth mode. */ pass = psl->image_empties_front_ps; } diff --git a/source/blender/draw/engines/overlay/overlay_metaball.c b/source/blender/draw/engines/overlay/overlay_metaball.c index 76ffbe4cc6b..c10c0a84247 100644 --- a/source/blender/draw/engines/overlay/overlay_metaball.c +++ b/source/blender/draw/engines/overlay/overlay_metaball.c @@ -69,7 +69,7 @@ static void metaball_instance_data_set( void OVERLAY_edit_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob) { - const bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; const bool is_select = DRW_state_is_select(); OVERLAY_PrivateData *pd = vedata->stl->pd; MetaBall *mb = ob->data; @@ -112,7 +112,7 @@ void OVERLAY_edit_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob) void OVERLAY_metaball_cache_populate(OVERLAY_Data *vedata, Object *ob) { - const bool do_in_front = (ob->dtx & OB_DRAWXRAY) != 0; + const bool do_in_front = (ob->dtx & OB_DRAW_IN_FRONT) != 0; OVERLAY_PrivateData *pd = vedata->stl->pd; MetaBall *mb = ob->data; const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index e00ebe12cd6..214322c4adc 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -138,6 +138,11 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata) pd->outlines_grp = grp = DRW_shgroup_create(sh_geom, psl->outlines_prepass_ps); DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); + GPUShader *sh_geom_ptcloud = OVERLAY_shader_outline_prepass_pointcloud(); + + pd->outlines_ptcloud_grp = grp = DRW_shgroup_create(sh_geom_ptcloud, psl->outlines_prepass_ps); + DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); + GPUShader *sh_gpencil = OVERLAY_shader_outline_prepass_gpencil(); pd->outlines_gpencil_grp = grp = DRW_shgroup_create(sh_gpencil, psl->outlines_prepass_ps); @@ -288,6 +293,12 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, return; } + if (ob->type == OB_POINTCLOUD && pd->wireframe_mode) { + /* Looks bad in this case. Could be relaxed if we draw a + * wireframe of some sort in the future. */ + return; + } + if (dupli && !init_dupli) { geom = dupli->outline_geom; shgroup = dupli->outline_shgrp; @@ -307,12 +318,18 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, } if (geom) { - shgroup = pd->outlines_grp; + shgroup = (ob->type == OB_POINTCLOUD) ? pd->outlines_ptcloud_grp : pd->outlines_grp; } } if (shgroup && geom) { - DRW_shgroup_call(shgroup, geom, ob); + if (ob->type == OB_POINTCLOUD) { + /* Draw range to avoid drawcall batching messing up the instance attrib. */ + DRW_shgroup_call_instance_range(shgroup, ob, geom, 0, 0); + } + else { + DRW_shgroup_call(shgroup, geom, ob); + } } if (init_dupli) { diff --git a/source/blender/draw/engines/overlay/overlay_paint.c b/source/blender/draw/engines/overlay/overlay_paint.c index 652d6af54a2..f0a1e77cf05 100644 --- a/source/blender/draw/engines/overlay/overlay_paint.c +++ b/source/blender/draw/engines/overlay/overlay_paint.c @@ -22,6 +22,8 @@ #include "DRW_render.h" +#include "BKE_image.h" + #include "DNA_mesh_types.h" #include "DEG_depsgraph_query.h" @@ -34,7 +36,7 @@ static bool paint_object_is_rendered_transparent(View3D *v3d, Object *ob) if (v3d->shading.type == OB_WIRE) { return true; } - else if (v3d->shading.type == OB_SOLID) { + if (v3d->shading.type == OB_SOLID) { if (v3d->shading.flag & V3D_SHADING_XRAY) { return true; } @@ -42,8 +44,8 @@ static bool paint_object_is_rendered_transparent(View3D *v3d, Object *ob) if (ob && v3d->shading.color_type == V3D_SHADING_OBJECT_COLOR) { return ob->color[3] < 1.0f; } - else if (ob && ob->type == OB_MESH && ob->data && - v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR) { + if (ob && ob->type == OB_MESH && ob->data && + v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR) { Mesh *me = ob->data; for (int i = 0; i < me->totcol; i++) { Material *mat = me->mat[i]; @@ -63,7 +65,7 @@ void OVERLAY_paint_init(OVERLAY_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); pd->painting.in_front = pd->use_in_front && draw_ctx->obact && - (draw_ctx->obact->dtx & OB_DRAWXRAY); + (draw_ctx->obact->dtx & OB_DRAW_IN_FRONT); pd->painting.alpha_blending = paint_object_is_rendered_transparent(draw_ctx->v3d, draw_ctx->obact); } @@ -136,7 +138,7 @@ void OVERLAY_paint_cache_init(OVERLAY_Data *vedata) state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA; DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state); - GPUTexture *tex = GPU_texture_from_blender(imapaint->stencil, NULL, NULL, GL_TEXTURE_2D); + GPUTexture *tex = BKE_image_get_gpu_texture(imapaint->stencil, NULL, NULL); const bool mask_premult = (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL); const bool mask_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) != 0; diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c deleted file mode 100644 index b2a2d44bf73..00000000000 --- a/source/blender/draw/engines/overlay/overlay_pointcloud.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Copyright 2020, Blender Foundation. - */ - -/** \file - * \ingroup draw_engine - */ - -#include "DRW_render.h" - -#include "DEG_depsgraph_query.h" - -#include "DNA_pointcloud_types.h" - -#include "BKE_pointcache.h" - -#include "overlay_private.h" - -/* -------------------------------------------------------------------- */ -/** \name PointCloud - * \{ */ - -void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata) -{ - OVERLAY_PassList *psl = vedata->psl; - OVERLAY_PrivateData *pd = vedata->stl->pd; - GPUShader *sh; - DRWShadingGroup *grp; - - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRW_PASS_CREATE(psl->pointcloud_ps, state | pd->clipping_state); - - sh = OVERLAY_shader_pointcloud_dot(); - pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); -} - -void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob) -{ - OVERLAY_PrivateData *pd = vedata->stl->pd; - - struct GPUBatch *geom = DRW_cache_pointcloud_get_dots(ob); - - const float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - - DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->pointcloud_dots_grp); - DRW_shgroup_uniform_vec4_copy(grp, "color", color); - DRW_shgroup_call(grp, geom, ob); -} - -void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata) -{ - OVERLAY_PassList *psl = vedata->psl; - - DRW_draw_pass(psl->pointcloud_ps); -} - -/** \} */ diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 59fa58c0c03..a8ac2616c02 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -20,8 +20,7 @@ * \ingroup DNA */ -#ifndef __OVERLAY_PRIVATE_H__ -#define __OVERLAY_PRIVATE_H__ +#pragma once #ifdef __APPLE__ # define USE_GEOM_SHADER_WORKAROUND 1 @@ -149,6 +148,7 @@ typedef struct OVERLAY_ExtraCallBuffers { DRWCallBuffer *extra_dashed_lines; DRWCallBuffer *extra_lines; + DRWCallBuffer *extra_points; DRWCallBuffer *field_curve; DRWCallBuffer *field_force; @@ -243,6 +243,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *motion_path_lines_grp; DRWShadingGroup *motion_path_points_grp; DRWShadingGroup *outlines_grp; + DRWShadingGroup *outlines_ptcloud_grp; DRWShadingGroup *outlines_gpencil_grp; DRWShadingGroup *paint_depth_grp; DRWShadingGroup *paint_surf_grp; @@ -387,6 +388,7 @@ typedef struct OVERLAY_InstanceFormats { struct GPUVertFormat *pos; struct GPUVertFormat *pos_color; struct GPUVertFormat *wire_extra; + struct GPUVertFormat *point_extra; } OVERLAY_InstanceFormats; /* Pack data into the last row of the 4x4 matrix. It will be decoded by the vertex shader. */ @@ -480,6 +482,7 @@ void OVERLAY_lightprobe_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_speaker_cache_populate(OVERLAY_Data *vedata, Object *ob); OVERLAY_ExtraCallBuffers *OVERLAY_extra_call_buffer_get(OVERLAY_Data *vedata, Object *ob); +void OVERLAY_extra_point(OVERLAY_ExtraCallBuffers *cb, const float point[3], const float color[4]); void OVERLAY_extra_line_dashed(OVERLAY_ExtraCallBuffers *cb, const float start[3], const float end[3], @@ -550,10 +553,6 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata); void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_particle_draw(OVERLAY_Data *vedata); -void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata); -void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob); -void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata); - void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata); void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_sculpt_draw(OVERLAY_Data *vedata); @@ -610,6 +609,7 @@ GPUShader *OVERLAY_shader_motion_path_vert(void); GPUShader *OVERLAY_shader_uniform_color(void); GPUShader *OVERLAY_shader_outline_prepass(bool use_wire); GPUShader *OVERLAY_shader_outline_prepass_gpencil(void); +GPUShader *OVERLAY_shader_outline_prepass_pointcloud(void); GPUShader *OVERLAY_shader_extra_grid(void); GPUShader *OVERLAY_shader_outline_detect(void); GPUShader *OVERLAY_shader_paint_face(void); @@ -620,7 +620,6 @@ GPUShader *OVERLAY_shader_paint_weight(void); GPUShader *OVERLAY_shader_paint_wire(void); GPUShader *OVERLAY_shader_particle_dot(void); GPUShader *OVERLAY_shader_particle_shape(void); -GPUShader *OVERLAY_shader_pointcloud_dot(void); GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); GPUShader *OVERLAY_shader_wireframe(bool custom_bias); @@ -630,5 +629,3 @@ GPUShader *OVERLAY_shader_xray_fade(void); OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void); void OVERLAY_shader_free(void); - -#endif /* __OVERLAY_PRIVATE_H__ */ diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index edf91c99531..e3cb052890b 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -103,8 +103,6 @@ extern char datatoc_paint_weight_vert_glsl[]; extern char datatoc_paint_wire_vert_glsl[]; extern char datatoc_particle_vert_glsl[]; extern char datatoc_particle_frag_glsl[]; -extern char datatoc_pointcloud_vert_glsl[]; -extern char datatoc_pointcloud_frag_glsl[]; extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_sculpt_mask_frag_glsl[]; extern char datatoc_volume_velocity_vert_glsl[]; @@ -127,6 +125,7 @@ extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_common_fxaa_lib_glsl[]; extern char datatoc_common_smaa_lib_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_pointcloud_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; typedef struct OVERLAY_Shaders { @@ -181,6 +180,7 @@ typedef struct OVERLAY_Shaders { GPUShader *motion_path_vert; GPUShader *outline_prepass; GPUShader *outline_prepass_gpencil; + GPUShader *outline_prepass_pointcloud; GPUShader *outline_prepass_wire; GPUShader *outline_detect; GPUShader *paint_face; @@ -1135,6 +1135,33 @@ GPUShader *OVERLAY_shader_outline_prepass_gpencil(void) return sh_data->outline_prepass_gpencil; } +GPUShader *OVERLAY_shader_outline_prepass_pointcloud(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + if (!sh_data->outline_prepass_pointcloud) { + sh_data->outline_prepass_pointcloud = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg->lib, + datatoc_common_view_lib_glsl, + datatoc_common_pointcloud_lib_glsl, + datatoc_gpu_shader_common_obinfos_lib_glsl, + datatoc_outline_prepass_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_gpencil_common_lib_glsl, + datatoc_outline_prepass_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg->def, + "#define POINTCLOUD\n", + "#define INSTANCED_ATTR\n", + "#define UNIFORM_RESOURCE_ID\n", + NULL}, + }); + } + return sh_data->outline_prepass_pointcloud; +} + GPUShader *OVERLAY_shader_outline_detect(void) { OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; @@ -1306,25 +1333,6 @@ GPUShader *OVERLAY_shader_particle_shape(void) return sh_data->particle_shape; } -GPUShader *OVERLAY_shader_pointcloud_dot(void) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (!sh_data->pointcloud_dot) { - sh_data->pointcloud_dot = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_pointcloud_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_pointcloud_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define USE_DOTS\n", NULL}, - }); - } - return sh_data->pointcloud_dot; -} - GPUShader *OVERLAY_shader_sculpt_mask(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -1468,6 +1476,11 @@ OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) {"pos", DRW_ATTR_FLOAT, 3}, {"colorid", DRW_ATTR_INT, 1}, }); + DRW_shgroup_instance_format(g_formats.point_extra, + { + {"pos", DRW_ATTR_FLOAT, 3}, + {"colorid", DRW_ATTR_INT, 1}, + }); DRW_shgroup_instance_format(g_formats.instance_bone, { {"inst_obmat", DRW_ATTR_FLOAT, 16}, diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index ea45ad5190c..4129983a901 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -102,12 +102,9 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_bool_copy(grp, "isHair", false); pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); - DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f); pd->wires_hair_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); - /* TODO(fclem) texture ref persist */ - DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_bool_copy(grp, "isHair", true); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f); } @@ -134,7 +131,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, ParticleSystem *psys) { OVERLAY_PrivateData *pd = vedata->stl->pd; - const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; + const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; Object *dupli_parent = DRW_object_get_dupli_parent(ob); DupliObject *dupli_object = DRW_object_get_dupli(ob); @@ -170,7 +167,7 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, OVERLAY_PrivateData *pd = vedata->stl->pd; const DRWContextState *draw_ctx = DRW_context_state_get(); const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0; - const bool is_xray = (ob->dtx & OB_DRAWXRAY) != 0; + const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0; const bool is_mesh = ob->type == OB_MESH; const bool is_mesh_verts_only = is_mesh && (((Mesh *)ob->data)->totedge == 0 && ((Mesh *)ob->data)->totvert > 0); @@ -235,10 +232,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, } } - if (use_wire && ob->type == OB_VOLUME) { - /* Volume object as points exception. */ - Volume *volume = ob->data; - if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) { + if (use_wire && ELEM(ob->type, OB_VOLUME, OB_POINTCLOUD)) { + bool draw_as_points = true; + if (ob->type == OB_VOLUME) { + /* Volume object as points exception. */ + Volume *volume = ob->data; + draw_as_points = volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS; + } + + if (draw_as_points) { float *color; OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob); DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl index 0d01f67c6ea..2989e07691f 100644 --- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl @@ -1,4 +1,6 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + uniform sampler2D colorTex; uniform sampler2D depthTex; uniform sampler2D lineTex; diff --git a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl index 380708795e9..0925901a9c9 100644 --- a/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/armature_sphere_solid_frag.glsl @@ -14,19 +14,6 @@ layout(depth_greater) out float gl_FragDepth; layout(location = 0) out vec4 fragColor; layout(location = 1) out vec4 lineOutput; -#define cameraPos ViewMatrixInverse[3].xyz - -float get_depth_from_view_z(float z) -{ - if (ProjectionMatrix[3][3] == 0.0) { - z = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; - } - else { - z = z * ProjectionMatrix[2][2] / (1.0 - ProjectionMatrix[3][2]); - } - return z * 0.5 + 0.5; -} - void main() { const float sphere_radius = 0.05; diff --git a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl index 317e9fe0447..d0b68df0625 100644 --- a/source/blender/draw/engines/overlay/shaders/grid_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/grid_frag.glsl @@ -14,8 +14,6 @@ uniform float meshSize; uniform float lineKernel = 0.0; uniform sampler2D depthBuffer; -#define cameraPos (ViewMatrixInverse[3].xyz) - uniform int gridFlag; #define STEPS_LEN 8 diff --git a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl index 496bb011c74..dd0e771ad93 100644 --- a/source/blender/draw/engines/overlay/shaders/grid_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/grid_vert.glsl @@ -7,8 +7,6 @@ uniform float meshSize; uniform int gridFlag; -#define cameraPos (ViewMatrixInverse[3].xyz) - #define PLANE_XY (1 << 4) #define PLANE_XZ (1 << 5) #define PLANE_YZ (1 << 6) diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl index a2021759196..582a7c6cae2 100644 --- a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl @@ -1,7 +1,7 @@ uniform bool isTransform; -#ifndef USE_GPENCIL +#if !defined(USE_GPENCIL) && !defined(POINTCLOUD) in vec3 pos; #endif @@ -56,7 +56,11 @@ void main() # endif #else +# ifdef POINTCLOUD + vec3 world_pos = pointcloud_get_pos(); +# else vec3 world_pos = point_object_to_world(pos); +# endif gl_Position = point_world_to_ndc(world_pos); # ifdef USE_GEOM vPos = point_world_to_view(world_pos); diff --git a/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl b/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl deleted file mode 100644 index 36928d0c776..00000000000 --- a/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -in vec4 finalColor; - -out vec4 fragColor; - -void main() -{ - float dist = length(gl_PointCoord - vec2(0.5)); - - if (dist > 0.5) { - discard; - } - /* Nice sphere falloff. */ - float intensity = sqrt(1.0 - dist * 2.0) * 0.5 + 0.5; - fragColor = finalColor * vec4(intensity, intensity, intensity, 1.0); -} diff --git a/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl b/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl deleted file mode 100644 index d71ccee5159..00000000000 --- a/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl +++ /dev/null @@ -1,27 +0,0 @@ - -uniform vec4 color; - -/* ---- Per instance Attrs ---- */ -in vec3 pointcloud_pos; -in vec3 pointcloud_radius; - -out vec4 finalColor; - -void main() -{ - vec3 world_pos = point_object_to_world(pointcloud_pos); - - vec3 world_size = abs(mat3(ModelMatrix) * vec3(pointcloud_radius)); - float world_radius = (world_size.x + world_size.y + world_size.z) / 3.0; - - gl_Position = point_world_to_ndc(world_pos); - /* World sized points. */ - gl_PointSize = sizePixel * world_radius * ProjectionMatrix[1][1] * sizeViewport.y / - gl_Position.w; - - finalColor = color; - -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif -} diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c index bb7c947a0b9..8cee6c4ee9f 100644 --- a/source/blender/draw/engines/select/select_engine.c +++ b/source/blender/draw/engines/select/select_engine.c @@ -378,7 +378,7 @@ RenderEngineType DRW_engine_viewport_select_type = { NULL, SELECT_ENGINE, N_("Select ID"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, NULL, NULL, diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h index 79139d9deaf..2b35cf6bee5 100644 --- a/source/blender/draw/engines/select/select_engine.h +++ b/source/blender/draw/engines/select/select_engine.h @@ -20,8 +20,7 @@ * \ingroup draw_engine */ -#ifndef __SELECT_ENGINE_H__ -#define __SELECT_ENGINE_H__ +#pragma once extern DrawEngineType draw_engine_select_type; extern RenderEngineType DRW_engine_viewport_select_type; @@ -30,5 +29,3 @@ struct SELECTID_Context *DRW_select_engine_context_get(void); struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void); struct GPUTexture *DRW_engine_select_texture_get(void); - -#endif /* __SELECT_ENGINE_H__ */ diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h index 1e99a49252e..763d1a0897d 100644 --- a/source/blender/draw/engines/select/select_private.h +++ b/source/blender/draw/engines/select/select_private.h @@ -20,8 +20,7 @@ * \ingroup draw_engine */ -#ifndef __SELECT_PRIVATE_H__ -#define __SELECT_PRIVATE_H__ +#pragma once #define USE_CAGE_OCCLUSION @@ -78,5 +77,3 @@ void select_id_draw_object(void *vedata, uint *r_vert_offset, uint *r_edge_offset, uint *r_face_offset); - -#endif /* __SELECT_PRIVATE_H__ */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl index d8cb4f86f7b..d0d52c8485b 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_cavity_lib.glsl @@ -28,7 +28,7 @@ void cavity_compute(vec2 screenco, return; } - vec3 position = view_position_from_depth(screenco, depth, world_data.viewvecs, ProjectionMatrix); + vec3 position = get_view_space_from_depth(screenco, depth); vec3 normal = workbench_normal_decode(texture(normalBuffer, screenco)); vec2 jitter_co = (screenco * world_data.viewport_size.xy) * world_data.cavity_jitter_scale; @@ -68,8 +68,7 @@ void cavity_compute(vec2 screenco, bool is_background = (s_depth == 1.0); /* This trick provide good edge effect even if no neighbor is found. */ s_depth = (is_background) ? depth : s_depth; - vec3 s_pos = view_position_from_depth( - uvcoords, s_depth, world_data.viewvecs, ProjectionMatrix); + vec3 s_pos = get_view_space_from_depth(uvcoords, s_depth); if (is_background) { s_pos.z -= world_data.cavity_distance; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl index 25eaf003e07..eb61edca6c7 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl @@ -48,7 +48,7 @@ float workbench_float_pair_encode(float v1, float v2) { // const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS); // const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS); - /* Same as above because some compiler are dumb af. and think we use mediump int. */ + /* Same as above because some compiler are very dumb and think we use medium int. */ const int v1_mask = 0x1F; const int v2_mask = 0x7; int iv1 = int(v1 * float(v1_mask)); @@ -60,38 +60,10 @@ void workbench_float_pair_decode(float data, out float v1, out float v2) { // const uint v1_mask = ~(0xFFFFFFFFu << ROUGHNESS_BITS); // const uint v2_mask = ~(0xFFFFFFFFu << METALLIC_BITS); - /* Same as above because some compiler are dumb af. and think we use mediump int. */ + /* Same as above because some compiler are very dumb and think we use medium int. */ const int v1_mask = 0x1F; const int v2_mask = 0x7; int idata = int(data); v1 = float(idata & v1_mask) * (1.0 / float(v1_mask)); v2 = float(idata >> int(ROUGHNESS_BITS)) * (1.0 / float(v2_mask)); } - -vec3 view_vector_from_screen_uv(vec2 uv, vec4 viewvecs[3], mat4 proj_mat) -{ - if (proj_mat[3][3] == 0.0) { - return normalize(viewvecs[0].xyz + vec3(uv, 0.0) * viewvecs[1].xyz); - } - else { - return vec3(0.0, 0.0, 1.0); - } -} - -vec3 view_position_from_depth(vec2 uvcoords, float depth, vec4 viewvecs[3], mat4 proj_mat) -{ - if (proj_mat[3][3] == 0.0) { - /* Perspective */ - float d = 2.0 * depth - 1.0; - - float zview = -proj_mat[3][2] / (d + proj_mat[2][2]); - - return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz); - } - else { - /* Orthographic */ - vec3 offset = vec3(uvcoords, depth); - - return viewvecs[0].xyz + offset * viewvecs[1].xyz; - } -} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl index cdb9823096c..6e10a656fc1 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl @@ -14,7 +14,7 @@ out vec4 fragColor; void main() { /* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */ - vec3 I = view_vector_from_screen_uv(uvcoordsvar.st, world_data.viewvecs, ProjectionMatrix); + vec3 I = get_view_vector_from_screen_uv(uvcoordsvar.st); vec3 N = workbench_normal_decode(texture(normalBuffer, uvcoordsvar.st)); vec4 mat_data = texture(materialBuffer, uvcoordsvar.st); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl index 5f3283e1643..a76a14fa750 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl @@ -5,7 +5,6 @@ struct LightData { }; struct WorldData { - vec4 viewvecs[3]; vec4 viewport_size; vec4 object_outline_color; vec4 shadow_direction_vs; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl index 51007a9f246..71816f6ff6e 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl @@ -1,3 +1,6 @@ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + /** * Separable Hexagonal Bokeh Blur by Colin Barré-Brisebois * https://colinbarrebrisebois.com/2017/04/18/hexagonal-bokeh-blur-revisited-part-1-basic-3-pass-version/ @@ -21,13 +24,6 @@ uniform sampler2D noiseTex; #define dof_distance dofParams.y #define dof_invsensorsize dofParams.z -#define M_PI 3.1415926535897932 /* pi */ - -float max_v4(vec4 v) -{ - return max(max(v.x, v.y), max(v.z, v.w)); -} - #define weighted_sum(a, b, c, d, e, e_sum) \ ((a)*e.x + (b)*e.y + (c)*e.z + (d)*e.w) / max(1e-6, e_sum); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl index 6a7bc185fe9..3e1ea14f47c 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_hair_vert.glsl @@ -90,5 +90,5 @@ void main() packed_rough_metal = workbench_float_pair_encode(roughness, metallic); #endif - object_id = int((uint(resource_id) + 1u) & 0xFFu); + object_id = int(uint(resource_handle) & 0xFFFFu) + 1; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl new file mode 100644 index 00000000000..6f61874b8f5 --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl @@ -0,0 +1,38 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_pointcloud_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_common_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_material_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_image_lib.glsl) + +void main() +{ + vec3 world_pos; + pointcloud_get_pos_and_nor(world_pos, normal_interp); + + normal_interp = normalize(normal_world_to_view(normal_interp)); + + gl_Position = point_world_to_ndc(world_pos); + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif + + uv_interp = vec2(0.0); + +#ifdef OPAQUE_MATERIAL + float metallic, roughness; +#endif + workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); + + if (materialIndex == 0) { + color_interp = vec3(1.0); + } + +#ifdef OPAQUE_MATERIAL + packed_rough_metal = workbench_float_pair_encode(roughness, metallic); +#endif + + object_id = int(uint(resource_handle) & 0xFFFFu) + 1; +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 31e298d1540..1192081caf1 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -36,5 +36,5 @@ void main() packed_rough_metal = workbench_float_pair_encode(roughness, metallic); #endif - object_id = int((uint(resource_id) + 1u) & 0xFFu); + object_id = int(uint(resource_handle) & 0xFFFFu) + 1; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl index 8e2f7ba4735..6bfa351aeb0 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_shader_interface_lib.glsl @@ -1,10 +1,4 @@ -#ifdef GPU_VERTEX_SHADER -# define IN_OUT out -#else -# define IN_OUT in -#endif - IN_OUT ShaderStageInterface { vec3 normal_interp; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl index 3c2d1a9c0c7..fd4d00d96dd 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl @@ -15,7 +15,7 @@ layout(location = 1) out vec4 revealageAccum; layout(location = 2) out uint objectId; /* Special function only to be used with calculate_transparent_weight(). */ -float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat) +float linear_zdepth(float depth, vec4 viewvecs[2], mat4 proj_mat) { if (proj_mat[3][3] == 0.0) { float d = 2.0 * depth - 1.0; @@ -33,7 +33,7 @@ float linear_zdepth(float depth, vec4 viewvecs[3], mat4 proj_mat) */ float calculate_transparent_weight(void) { - float z = linear_zdepth(gl_FragCoord.z, world_data.viewvecs, ProjectionMatrix); + float z = linear_zdepth(gl_FragCoord.z, ViewVecs, ProjectionMatrix); #if 0 /* Eq 10 : Good for surfaces with varying opacity (like particles) */ float a = min(1.0, alpha * 10.0) + 0.01; @@ -57,7 +57,7 @@ void main() { /* Normal and Incident vector are in viewspace. Lighting is evaluated in viewspace. */ vec2 uv_viewport = gl_FragCoord.xy * world_data.viewport_size_inv; - vec3 I = view_vector_from_screen_uv(uv_viewport, world_data.viewvecs, ProjectionMatrix); + vec3 I = get_view_vector_from_screen_uv(uv_viewport); vec3 N = normalize(normal_interp); vec3 color = color_interp; diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index 2920a504062..aa938d80fa3 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -1,4 +1,5 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_view_lib.glsl) #pragma BLENDER_REQUIRE(gpu_shader_common_obinfos_lib.glsl) #pragma BLENDER_REQUIRE(workbench_data_lib.glsl) @@ -33,11 +34,6 @@ float phase_function_isotropic() return 1.0 / (4.0 * M_PI); } -float max_v3(vec3 v) -{ - return max(v.x, max(v.y, v.z)); -} - float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) { /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ @@ -194,10 +190,8 @@ void main() float depth = texelFetch(depthBuffer, ivec2(gl_FragCoord.xy), 0).r; float depth_end = min(depth, gl_FragCoord.z); - vec3 vs_ray_end = view_position_from_depth( - screen_uv, depth_end, world_data.viewvecs, ProjectionMatrix); - vec3 vs_ray_ori = view_position_from_depth( - screen_uv, 0.0, world_data.viewvecs, ProjectionMatrix); + vec3 vs_ray_end = get_view_space_from_depth(screen_uv, depth_end); + vec3 vs_ray_ori = get_view_space_from_depth(screen_uv, 0.0); vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); vs_ray_dir /= abs(vs_ray_dir.z); diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 7b08e97ac31..0d7f4ee660b 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -86,43 +86,6 @@ static WORKBENCH_ViewLayerData *workbench_view_layer_data_ensure_ex(struct ViewL /* \} */ -static void workbench_viewvecs_update(float r_viewvecs[3][4]) -{ - float invproj[4][4]; - const bool is_persp = DRW_view_is_persp_get(NULL); - DRW_view_winmat_get(NULL, invproj, true); - - /* view vectors for the corners of the view frustum. - * Can be used to recreate the world space position easily */ - copy_v4_fl4(r_viewvecs[0], -1.0f, -1.0f, -1.0f, 1.0f); - copy_v4_fl4(r_viewvecs[1], 1.0f, -1.0f, -1.0f, 1.0f); - copy_v4_fl4(r_viewvecs[2], -1.0f, 1.0f, -1.0f, 1.0f); - - /* convert the view vectors to view space */ - for (int i = 0; i < 3; i++) { - mul_m4_v4(invproj, r_viewvecs[i]); - /* normalized trick see: - * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][3]); - if (is_persp) { - mul_v3_fl(r_viewvecs[i], 1.0f / r_viewvecs[i][2]); - } - r_viewvecs[i][3] = 1.0; - } - - /* we need to store the differences */ - r_viewvecs[1][0] -= r_viewvecs[0][0]; - r_viewvecs[1][1] = r_viewvecs[2][1] - r_viewvecs[0][1]; - - /* calculate a depth offset as well */ - if (!is_persp) { - float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; - mul_m4_v4(invproj, vec_far); - mul_v3_fl(vec_far, 1.0f / vec_far[3]); - r_viewvecs[1][2] = vec_far[2] - r_viewvecs[0][2]; - } -} - static void workbench_studiolight_data_update(WORKBENCH_PrivateData *wpd, WORKBENCH_UBO_World *wd) { StudioLight *studiolight = wpd->studio_light; @@ -256,6 +219,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) } else if (XRAY_ENABLED(v3d)) { wpd->shading.xray_alpha = XRAY_ALPHA(v3d); + /* Disable shading options that aren't supported in transparency mode. */ + wpd->shading.flag &= ~(V3D_SHADING_SHADOW | V3D_SHADING_CAVITY | V3D_SHADING_DEPTH_OF_FIELD); } else { wpd->shading.xray_alpha = 1.0f; @@ -309,7 +274,6 @@ void workbench_update_world_ubo(WORKBENCH_PrivateData *wpd) workbench_studiolight_data_update(wpd, &wd); workbench_shadow_data_update(wpd, &wd); workbench_cavity_data_update(wpd, &wd); - workbench_viewvecs_update(wd.viewvecs); DRW_uniformbuffer_update(wpd->world_ubo, &wd); } diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index 0e896c4b7bb..faf64b55c2d 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -112,17 +112,15 @@ int workbench_antialiasing_sample_count_get(WORKBENCH_PrivateData *wpd) /* Only draw using SMAA or no AA when navigating. */ return min_ii(wpd->preferences->viewport_aa, 1); } - else if (DRW_state_is_image_render()) { + if (DRW_state_is_image_render()) { if (draw_ctx->v3d) { return scene->display.viewport_aa; } - else { - return scene->display.render_aa; - } - } - else { - return wpd->preferences->viewport_aa; + + return scene->display.render_aa; } + + return wpd->preferences->viewport_aa; } void workbench_antialiasing_view_updated(WORKBENCH_Data *vedata) @@ -361,53 +359,52 @@ bool workbench_antialiasing_setup(WORKBENCH_Data *vedata) /* TAA accumulation has finish. Just copy the result back */ return false; } - else { - const float *viewport_size = DRW_viewport_size_get(); - const DRWView *default_view = DRW_view_default_get(); - float *transform_offset; - - switch (wpd->taa_sample_len) { - default: - case 5: - transform_offset = e_data.jitter_5[min_ii(wpd->taa_sample, 5)]; - break; - case 8: - transform_offset = e_data.jitter_8[min_ii(wpd->taa_sample, 8)]; - break; - case 11: - transform_offset = e_data.jitter_11[min_ii(wpd->taa_sample, 11)]; - break; - case 16: - transform_offset = e_data.jitter_16[min_ii(wpd->taa_sample, 16)]; - break; - case 32: - transform_offset = e_data.jitter_32[min_ii(wpd->taa_sample, 32)]; - break; - } - - /* construct new matrices from transform delta */ - float winmat[4][4], viewmat[4][4], persmat[4][4]; - DRW_view_winmat_get(default_view, winmat, false); - DRW_view_viewmat_get(default_view, viewmat, false); - DRW_view_persmat_get(default_view, persmat, false); - window_translate_m4(winmat, - persmat, - transform_offset[0] / viewport_size[0], - transform_offset[1] / viewport_size[1]); - - if (wpd->view) { - /* When rendering just update the view. This avoids recomputing the culling. */ - DRW_view_update_sub(wpd->view, viewmat, winmat); - } - else { - /* TAA is not making a big change to the matrices. - * Reuse the main view culling by creating a sub-view. */ - wpd->view = DRW_view_create_sub(default_view, viewmat, winmat); - } - DRW_view_set_active(wpd->view); - return true; + const float *viewport_size = DRW_viewport_size_get(); + const DRWView *default_view = DRW_view_default_get(); + float *transform_offset; + + switch (wpd->taa_sample_len) { + default: + case 5: + transform_offset = e_data.jitter_5[min_ii(wpd->taa_sample, 5)]; + break; + case 8: + transform_offset = e_data.jitter_8[min_ii(wpd->taa_sample, 8)]; + break; + case 11: + transform_offset = e_data.jitter_11[min_ii(wpd->taa_sample, 11)]; + break; + case 16: + transform_offset = e_data.jitter_16[min_ii(wpd->taa_sample, 16)]; + break; + case 32: + transform_offset = e_data.jitter_32[min_ii(wpd->taa_sample, 32)]; + break; + } + + /* construct new matrices from transform delta */ + float winmat[4][4], viewmat[4][4], persmat[4][4]; + DRW_view_winmat_get(default_view, winmat, false); + DRW_view_viewmat_get(default_view, viewmat, false); + DRW_view_persmat_get(default_view, persmat, false); + + window_translate_m4(winmat, + persmat, + transform_offset[0] / viewport_size[0], + transform_offset[1] / viewport_size[1]); + + if (wpd->view) { + /* When rendering just update the view. This avoids recomputing the culling. */ + DRW_view_update_sub(wpd->view, viewmat, winmat); + } + else { + /* TAA is not making a big change to the matrices. + * Reuse the main view culling by creating a sub-view. */ + wpd->view = DRW_view_create_sub(default_view, viewmat, winmat); } + DRW_view_set_active(wpd->view); + return true; } void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index c8dde4d513b..53119723fab 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -130,6 +130,17 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd, } } +BLI_INLINE void workbench_object_drawcall(DRWShadingGroup *grp, struct GPUBatch *geom, Object *ob) +{ + if (ob->type == OB_POINTCLOUD) { + /* Draw range to avoid drawcall batching messing up the instance attrib. */ + DRW_shgroup_call_instance_range(grp, ob, geom, 0, 0); + } + else { + DRW_shgroup_call(grp, geom, ob); + } +} + static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object *ob) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -145,7 +156,7 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object SET_FLAG_FROM_TEST(state, imapaint->interp == IMAGEPAINT_INTERP_LINEAR, GPU_SAMPLER_FILTER); DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, state); - DRW_shgroup_call(grp, geom, ob); + workbench_object_drawcall(grp, geom, ob); } } else { @@ -157,7 +168,7 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object continue; } DRWShadingGroup *grp = workbench_image_setup(wpd, ob, i + 1, NULL, NULL, 0); - DRW_shgroup_call(grp, geoms[i], ob); + workbench_object_drawcall(grp, geoms[i], ob); } } } @@ -180,7 +191,12 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, geom = DRW_cache_mesh_surface_vertpaint_get(ob); } else { - geom = DRW_cache_mesh_surface_sculptcolors_get(ob); + if (U.experimental.use_sculpt_vertex_colors) { + geom = DRW_cache_mesh_surface_sculptcolors_get(ob); + } + else { + geom = DRW_cache_mesh_surface_vertpaint_get(ob); + } } } else { @@ -189,7 +205,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, if (geom) { DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, r_transp); - DRW_shgroup_call(grp, geom, ob); + workbench_object_drawcall(grp, geom, ob); } } else { @@ -202,7 +218,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, continue; } DRWShadingGroup *grp = workbench_material_setup(wpd, ob, i + 1, color_type, r_transp); - DRW_shgroup_call(grp, geoms[i], ob); + workbench_object_drawcall(grp, geoms[i], ob); } } } @@ -261,8 +277,15 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd, } } else if (color_type == V3D_SHADING_VERTEX_COLOR) { - if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) { - color_type = V3D_SHADING_OBJECT_COLOR; + if (U.experimental.use_sculpt_vertex_colors) { + if ((me == NULL) || !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) { + color_type = V3D_SHADING_OBJECT_COLOR; + } + } + else { + if ((me == NULL) || !CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) { + color_type = V3D_SHADING_OBJECT_COLOR; + } } } @@ -438,7 +461,7 @@ void workbench_cache_finish(void *ved) /* TODO don't free reuse next redraw. */ for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { + for (int k = 0; k < WORKBENCH_DATATYPE_MAX; k++) { if (wpd->prepass[i][j][k].material_hash) { BLI_ghash_free(wpd->prepass[i][j][k].material_hash, NULL, NULL); wpd->prepass[i][j][k].material_hash = NULL; @@ -618,7 +641,7 @@ RenderEngineType DRW_engine_viewport_workbench_type = { NULL, WORKBENCH_ENGINE, N_("Workbench"), - RE_INTERNAL | RE_USE_STEREO_VIEWPORT, + RE_INTERNAL | RE_USE_STEREO_VIEWPORT | RE_USE_GPU_CONTEXT, NULL, &DRW_render_to_image, NULL, diff --git a/source/blender/draw/engines/workbench/workbench_engine.h b/source/blender/draw/engines/workbench/workbench_engine.h index eee53fcde07..8fd427c2683 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.h +++ b/source/blender/draw/engines/workbench/workbench_engine.h @@ -20,9 +20,6 @@ * \ingroup draw_engine */ -#ifndef __WORKBENCH_ENGINE_H__ -#define __WORKBENCH_ENGINE_H__ +#pragma once extern RenderEngineType DRW_engine_viewport_workbench_type; - -#endif /* __WORKBENCH_ENGINE_H__ */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index d6d3ff8610b..2ed63bac853 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -162,13 +162,13 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, eV3DShadingColorType color_type, - bool hair, + eWORKBENCH_DataType datatype, bool *r_transp) { Image *ima = NULL; ImageUser *iuser = NULL; eGPUSamplerState sampler; - const bool infront = (ob->dtx & OB_DRAWXRAY) != 0; + const bool infront = (ob->dtx & OB_DRAW_IN_FRONT) != 0; if (color_type == V3D_SHADING_TEXTURE_COLOR) { workbench_material_get_image(ob, mat_nr, &ima, &iuser, &sampler); @@ -180,7 +180,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, switch (color_type) { case V3D_SHADING_TEXTURE_COLOR: { - return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, hair); + return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, datatype); } case V3D_SHADING_MATERIAL_COLOR: { /* For now, we use the same ubo for material and object coloring but with different indices. @@ -191,7 +191,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Material *ma = workbench_object_material_get(ob, mat_nr); const bool transp = wpd->shading.xray_alpha < 1.0f || ma->a < 1.0f; - WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][hair]; + WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype]; if (r_transp && transp) { *r_transp = true; @@ -216,7 +216,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, } case V3D_SHADING_VERTEX_COLOR: { const bool transp = wpd->shading.xray_alpha < 1.0f; - DRWShadingGroup *grp = wpd->prepass[transp][infront][hair].vcol_shgrp; + DRWShadingGroup *grp = wpd->prepass[transp][infront][datatype].vcol_shgrp; return grp; } default: { @@ -231,15 +231,15 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, workbench_material_ubo_data(wpd, ob, NULL, &wpd->material_ubo_data_curr[mat_id], color_type); const bool transp = wpd->shading.xray_alpha < 1.0f || ob->color[3] < 1.0f; - DRWShadingGroup *grp = wpd->prepass[transp][infront][hair].common_shgrp; + DRWShadingGroup **grp = &wpd->prepass[transp][infront][datatype].common_shgrp; if (resource_changed) { - grp = DRW_shgroup_create_sub(grp); - DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); + *grp = DRW_shgroup_create_sub(*grp); + DRW_shgroup_uniform_block(*grp, "material_block", wpd->material_ubo_curr); } if (r_transp && transp) { *r_transp = true; } - return grp; + return *grp; } } } @@ -251,7 +251,7 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Image *ima, ImageUser *iuser, eGPUSamplerState sampler, - bool hair) + eWORKBENCH_DataType datatype) { GPUTexture *tex = NULL, *tex_tile_data = NULL; @@ -261,11 +261,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, if (ima) { if (ima->source == IMA_SRC_TILED) { - tex = GPU_texture_from_blender(ima, iuser, NULL, GL_TEXTURE_2D_ARRAY); - tex_tile_data = GPU_texture_from_blender(ima, iuser, NULL, GL_TEXTURE_1D_ARRAY); + tex = BKE_image_get_gpu_tiles(ima, iuser, NULL); + tex_tile_data = BKE_image_get_gpu_tilemap(ima, iuser, NULL); } else { - tex = GPU_texture_from_blender(ima, iuser, NULL, GL_TEXTURE_2D); + tex = BKE_image_get_gpu_texture(ima, iuser, NULL); } } @@ -273,9 +273,9 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, tex = wpd->dummy_image_tx; } - const bool infront = (ob->dtx & OB_DRAWXRAY) != 0; + const bool infront = (ob->dtx & OB_DRAW_IN_FRONT) != 0; const bool transp = wpd->shading.xray_alpha < 1.0f; - WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][hair]; + WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype]; DRWShadingGroup **grp_tex = NULL; /* A hashmap stores image shgroups to pack all similar drawcalls together. */ diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c index 27d5b71f35c..738f4a67471 100644 --- a/source/blender/draw/engines/workbench/workbench_opaque.c +++ b/source/blender/draw/engines/workbench/workbench_opaque.c @@ -59,10 +59,10 @@ void workbench_opaque_engine_init(WORKBENCH_Data *data) }); } -void workbench_opaque_cache_init(WORKBENCH_Data *data) +void workbench_opaque_cache_init(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = data->psl; - WORKBENCH_PrivateData *wpd = data->stl->wpd; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = vedata->stl->wpd; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); struct GPUShader *sh; DRWShadingGroup *grp; @@ -84,31 +84,31 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data) pass = psl->opaque_ps; } - for (int hair = 0; hair < 2; hair++) { - wpd->prepass[opaque][infront][hair].material_hash = BLI_ghash_ptr_new(__func__); + for (eWORKBENCH_DataType data = 0; data < WORKBENCH_DATATYPE_MAX; data++) { + wpd->prepass[opaque][infront][data].material_hash = BLI_ghash_ptr_new(__func__); - sh = workbench_shader_opaque_get(wpd, hair); + sh = workbench_shader_opaque_get(wpd, data); - wpd->prepass[opaque][infront][hair].common_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].common_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", -1); DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - sh = workbench_shader_opaque_image_get(wpd, hair, false); + sh = workbench_shader_opaque_image_get(wpd, data, false); - wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].image_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - sh = workbench_shader_opaque_image_get(wpd, hair, true); + sh = workbench_shader_opaque_image_get(wpd, data, true); - wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index ee9960ea0ef..4a6dadc32fd 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -20,8 +20,7 @@ * \ingroup draw_engine */ -#ifndef __WORKBENCH_PRIVATE_H__ -#define __WORKBENCH_PRIVATE_H__ +#pragma once #include "BKE_studiolight.h" @@ -71,6 +70,14 @@ struct RenderEngine; struct RenderLayer; struct rcti; +typedef enum eWORKBENCH_DataType { + WORKBENCH_DATATYPE_MESH = 0, + WORKBENCH_DATATYPE_HAIR, + WORKBENCH_DATATYPE_POINTCLOUD, + + WORKBENCH_DATATYPE_MAX, +} eWORKBENCH_DataType; + typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *opaque_fb; struct GPUFrameBuffer *opaque_infront_fb; @@ -168,7 +175,6 @@ typedef struct WORKBENCH_UBO_Material { } WORKBENCH_UBO_Material; typedef struct WORKBENCH_UBO_World { - float viewvecs[3][4]; float viewport_size[2], viewport_size_inv[2]; float object_outline_color[4]; float shadow_direction_vs[4]; @@ -293,8 +299,8 @@ typedef struct WORKBENCH_PrivateData { /** Object IDs buffer for curvature & outline. */ struct GPUTexture *object_id_tx; - /** Pre-pass information for each draw types [transparent][infront][hair]. */ - WORKBENCH_Prepass prepass[2][2][2]; + /** Pre-pass information for each draw types [transparent][infront][datatype]. */ + WORKBENCH_Prepass prepass[2][2][WORKBENCH_DATATYPE_MAX]; /* Materials */ /** Copy of vldata->material_ubo for faster access. */ @@ -393,14 +399,16 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data); void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const bool has_transp_mat); /* workbench_shader.c */ -GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair); -GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled); +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data); +GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType data, + bool tiled); GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd); GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData *wpd); -GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, bool hair); +GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data); GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd, - bool hair, + eWORKBENCH_DataType data, bool tiled); GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd); @@ -455,7 +463,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, eV3DShadingColorType color_type, - bool hair, + eWORKBENCH_DataType datatype, bool *r_transp); DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, @@ -463,17 +471,20 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Image *ima, ImageUser *iuser, eGPUSamplerState sampler, - bool hair); + eWORKBENCH_DataType datatype); + +#define WORKBENCH_OBJECT_DATATYPE(ob) \ + ((ob->type == OB_POINTCLOUD) ? WORKBENCH_DATATYPE_POINTCLOUD : WORKBENCH_DATATYPE_MESH) #define workbench_material_setup(wpd, ob, mat_nr, color_type, r_transp) \ - workbench_material_setup_ex(wpd, ob, mat_nr, color_type, false, r_transp) + workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_OBJECT_DATATYPE(ob), r_transp) #define workbench_image_setup(wpd, ob, mat_nr, ima, iuser, interp) \ - workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, false) + workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_OBJECT_DATATYPE(ob)) #define workbench_material_hair_setup(wpd, ob, mat_nr, color_type) \ - workbench_material_setup_ex(wpd, ob, mat_nr, color_type, true, 0) + workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_DATATYPE_HAIR, 0) #define workbench_image_hair_setup(wpd, ob, mat_nr, ima, iuser, interp) \ - workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, true) + workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_HAIR) /* workbench_data.c */ void workbench_private_data_init(WORKBENCH_PrivateData *wpd); @@ -508,5 +519,3 @@ void workbench_render(void *ved, void workbench_render_update_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer); - -#endif diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c index 9e66bcb07f4..77e16327a43 100644 --- a/source/blender/draw/engines/workbench/workbench_render.c +++ b/source/blender/draw/engines/workbench/workbench_render.c @@ -212,6 +212,7 @@ void workbench_render(void *ved, RenderEngine *engine, RenderLayer *render_layer BLI_rcti_size_y(rect), 4, 0, + GPU_DATA_FLOAT, rp->rect); workbench_render_result_z(render_layer, viewname, rect); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 99366779b22..aab3cef00e6 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -28,12 +28,16 @@ #include "workbench_engine.h" #include "workbench_private.h" +extern char datatoc_common_math_lib_glsl[]; +extern char datatoc_common_math_geom_lib_glsl[]; extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_pointcloud_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; extern char datatoc_common_smaa_lib_glsl[]; extern char datatoc_workbench_prepass_vert_glsl[]; extern char datatoc_workbench_prepass_hair_vert_glsl[]; +extern char datatoc_workbench_prepass_pointcloud_vert_glsl[]; extern char datatoc_workbench_prepass_frag_glsl[]; extern char datatoc_workbench_effect_cavity_frag_glsl[]; @@ -74,7 +78,6 @@ extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; /* Maximum number of variations. */ #define MAX_LIGHTING 3 #define MAX_COLOR 3 -#define MAX_GEOM 2 enum { VOLUME_SH_SLICE = 0, @@ -85,8 +88,9 @@ enum { #define VOLUME_SH_MAX (1 << (VOLUME_SH_CUBIC + 1)) static struct { - struct GPUShader *opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_GEOM][MAX_COLOR]; - struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_GEOM][MAX_LIGHTING][MAX_COLOR]; + struct GPUShader *opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX][MAX_COLOR]; + struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX] + [MAX_LIGHTING][MAX_COLOR]; struct GPUShader *opaque_composite_sh[MAX_LIGHTING]; struct GPUShader *oit_resolve_sh; @@ -117,8 +121,11 @@ void workbench_shader_library_ensure(void) if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); /* NOTE: Theses needs 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_pointcloud_lib); DRW_SHADER_LIB_ADD(e_data.lib, gpu_shader_common_obinfos_lib); DRW_SHADER_LIB_ADD(e_data.lib, workbench_shader_interface_lib); DRW_SHADER_LIB_ADD(e_data.lib, workbench_common_lib); @@ -177,15 +184,18 @@ static int workbench_color_index(WORKBENCH_PrivateData *UNUSED(wpd), bool textur return (textured) ? (tiled ? 2 : 1) : 0; } -static GPUShader *workbench_shader_get_ex( - WORKBENCH_PrivateData *wpd, bool transp, bool hair, bool textured, bool tiled) +static GPUShader *workbench_shader_get_ex(WORKBENCH_PrivateData *wpd, + bool transp, + eWORKBENCH_DataType datatype, + bool textured, + bool tiled) { int color = workbench_color_index(wpd, textured, tiled); int light = wpd->shading.light; BLI_assert(light < MAX_LIGHTING); struct GPUShader **shader = - (transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][hair][light][color] : - &e_data.opaque_prepass_sh_cache[wpd->sh_cfg][hair][color]; + (transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][datatype][light][color] : + &e_data.opaque_prepass_sh_cache[wpd->sh_cfg][datatype][color]; if (*shader == NULL) { char *defines = workbench_build_defines(wpd, textured, tiled, false, false); @@ -194,8 +204,11 @@ static GPUShader *workbench_shader_get_ex( datatoc_workbench_prepass_frag_glsl; char *frag_src = DRW_shader_library_create_shader_string(e_data.lib, frag_file); - char *vert_file = hair ? datatoc_workbench_prepass_hair_vert_glsl : - datatoc_workbench_prepass_vert_glsl; + char *vert_file = (datatype == WORKBENCH_DATATYPE_HAIR) ? + datatoc_workbench_prepass_hair_vert_glsl : + ((datatype == WORKBENCH_DATATYPE_POINTCLOUD) ? + datatoc_workbench_prepass_pointcloud_vert_glsl : + datatoc_workbench_prepass_vert_glsl); char *vert_src = DRW_shader_library_create_shader_string(e_data.lib, vert_file); const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[wpd->sh_cfg]; @@ -207,6 +220,10 @@ static GPUShader *workbench_shader_get_ex( defines, transp ? "#define TRANSPARENT_MATERIAL\n" : "#define OPAQUE_MATERIAL\n", + (datatype == WORKBENCH_DATATYPE_POINTCLOUD) ? + "#define UNIFORM_RESOURCE_ID\n" + "#define INSTANCED_ATTR\n" : + NULL, NULL}, }); @@ -217,26 +234,29 @@ static GPUShader *workbench_shader_get_ex( return *shader; } -GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair) +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType datatype) { - return workbench_shader_get_ex(wpd, false, hair, false, false); + return workbench_shader_get_ex(wpd, false, datatype, false, false); } -GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled) +GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType datatype, + bool tiled) { - return workbench_shader_get_ex(wpd, false, hair, true, tiled); + return workbench_shader_get_ex(wpd, false, datatype, true, tiled); } -GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, bool hair) +GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType datatype) { - return workbench_shader_get_ex(wpd, true, hair, false, false); + return workbench_shader_get_ex(wpd, true, datatype, false, false); } GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd, - bool hair, + eWORKBENCH_DataType datatype, bool tiled) { - return workbench_shader_get_ex(wpd, true, hair, true, tiled); + return workbench_shader_get_ex(wpd, true, datatype, true, tiled); } GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd) diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c index 1c40a350300..5eff056846c 100644 --- a/source/blender/draw/engines/workbench/workbench_transparent.c +++ b/source/blender/draw/engines/workbench/workbench_transparent.c @@ -83,10 +83,10 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd, } } -void workbench_transparent_cache_init(WORKBENCH_Data *data) +void workbench_transparent_cache_init(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = data->psl; - WORKBENCH_PrivateData *wpd = data->stl->wpd; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = vedata->stl->wpd; struct GPUShader *sh; DRWShadingGroup *grp; @@ -105,30 +105,30 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data) pass = psl->transp_accum_ps; } - for (int hair = 0; hair < 2; hair++) { - wpd->prepass[transp][infront][hair].material_hash = BLI_ghash_ptr_new(__func__); + for (eWORKBENCH_DataType data = 0; data < WORKBENCH_DATATYPE_MAX; data++) { + wpd->prepass[transp][infront][data].material_hash = BLI_ghash_ptr_new(__func__); - sh = workbench_shader_transparent_get(wpd, hair); + sh = workbench_shader_transparent_get(wpd, data); - wpd->prepass[transp][infront][hair].common_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].common_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", -1); workbench_transparent_lighting_uniforms(wpd, grp); - wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ - sh = workbench_shader_transparent_image_get(wpd, hair, false); + sh = workbench_shader_transparent_image_get(wpd, data, false); - wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].image_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); - sh = workbench_shader_transparent_image_get(wpd, hair, true); + sh = workbench_shader_transparent_image_get(wpd, data, true); - wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index 8e345f8275b..d3c4d51dbd4 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -38,8 +38,6 @@ #include "BKE_volume.h" #include "BKE_volume_render.h" -#include "GPU_draw.h" - void workbench_volume_engine_init(WORKBENCH_Data *vedata) { WORKBENCH_TextureList *txl = vedata->txl; @@ -79,13 +77,10 @@ static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata, wpd->volumes_do = true; if (fds->use_coba) { - GPU_create_smoke_coba_field(fmd); - } - else if (!(fds->flags & FLUID_DOMAIN_USE_NOISE)) { - GPU_create_smoke(fmd, 0); + DRW_smoke_ensure_coba_field(fmd); } - else if (fds->flags & FLUID_DOMAIN_USE_NOISE) { - GPU_create_smoke(fmd, 1); + else { + DRW_smoke_ensure(fmd, fds->flags & FLUID_DOMAIN_USE_NOISE); } if ((!fds->use_coba && (fds->tex_density == NULL && fds->tex_color == NULL)) || @@ -293,7 +288,7 @@ void workbench_volume_draw_finish(WORKBENCH_Data *vedata) * all viewport in a redraw at least. */ LISTBASE_FOREACH (LinkData *, link, &wpd->smoke_domains) { FluidModifierData *fmd = (FluidModifierData *)link->data; - GPU_free_smoke(fmd); + DRW_smoke_free(fmd); } BLI_freelistN(&wpd->smoke_domains); } diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 555043ab408..956bddfb357 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -22,8 +22,7 @@ /* This is the Render Functions used by Realtime engines to draw with OpenGL */ -#ifndef __DRW_RENDER_H__ -#define __DRW_RENDER_H__ +#pragma once #include "DRW_engine_types.h" @@ -198,12 +197,28 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo); } while (0) /* Shaders */ + +#ifndef __GPU_MATERIAL_H__ +/* FIXME: Meh avoid including all GPUMaterial. */ +typedef void (*GPUMaterialEvalCallbackFn)(struct GPUMaterial *mat, + int options, + const char **vert_code, + const char **geom_code, + const char **frag_lib, + const char **defines); +#endif + struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines); struct GPUShader *DRW_shader_create_with_lib( const char *vert, const char *geom, const char *frag, const char *lib, const char *defines); +struct GPUShader *DRW_shader_create_with_shaderlib(const char *vert, + const char *geom, + const char *frag, + const DRWShaderLibrary *lib, + const char *defines); struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert, const char *geom, const char *defines, @@ -211,6 +226,9 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert, const char **varying_names, const int varying_count); struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines); +struct GPUShader *DRW_shader_create_fullscreen_with_shaderlib(const char *frag, + const DRWShaderLibrary *lib, + const char *defines); struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, const int options, @@ -229,7 +247,8 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, const char *geom, const char *frag_lib, const char *defines, - bool deferred); + bool deferred, + GPUMaterialEvalCallbackFn callback); struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, struct Material *ma, struct bNodeTree *ntree, @@ -240,7 +259,8 @@ struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, const char *geom, const char *frag_lib, const char *defines, - bool deferred); + bool deferred, + GPUMaterialEvalCallbackFn callback); void DRW_shader_free(struct GPUShader *shader); #define DRW_SHADER_FREE_SAFE(shader) \ do { \ @@ -257,7 +277,8 @@ void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const ch #define DRW_SHADER_LIB_ADD(lib, lib_name) \ DRW_shader_library_add_file(lib, datatoc_##lib_name##_glsl, STRINGIFY(lib_name) ".glsl") -char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code); +char *DRW_shader_library_create_shader_string(const DRWShaderLibrary *lib, + const char *shader_code); void DRW_shader_library_free(DRWShaderLibrary *lib); #define DRW_SHADER_LIB_FREE_SAFE(lib) \ @@ -623,7 +644,11 @@ void DRW_render_object_iter(void *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph)); void DRW_render_instance_buffer_finish(void); -void DRW_render_viewport_size_set(int size[2]); +void DRW_render_set_time(struct RenderEngine *engine, + struct Depsgraph *depsgraph, + int frame, + float subframe); +void DRW_render_viewport_size_set(const int size[2]); void DRW_custom_pipeline(DrawEngineType *draw_engine_type, struct Depsgraph *depsgraph, @@ -727,5 +752,3 @@ typedef struct DRWContextState { } DRWContextState; const DRWContextState *DRW_context_state_get(void); - -#endif /* __DRW_RENDER_H__ */ diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 9f30cd85957..b36a177c19f 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -829,7 +829,7 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob) case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_pointcloud_batch_cache_get_dots(ob); case OB_VOLUME: return DRW_cache_volume_face_wireframe_get(ob); case OB_GPENCIL: { @@ -880,7 +880,7 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob) case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_cache_pointcloud_surface_get(ob); case OB_VOLUME: return NULL; default: @@ -958,7 +958,7 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob, case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_cache_pointcloud_surface_shaded_get(ob, gpumat_array, gpumat_array_len); case OB_VOLUME: return NULL; default: @@ -2909,9 +2909,8 @@ GPUBatch *DRW_cache_curve_edge_wire_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wire_edge(cu); - } + + return DRW_curve_batch_cache_get_wire_edge(cu); } GPUBatch *DRW_cache_curve_edge_normal_get(Object *ob) @@ -2947,9 +2946,8 @@ GPUBatch *DRW_cache_curve_surface_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface(mesh_eval); } - else { - return DRW_curve_batch_cache_get_triangles_with_normals(cu); - } + + return DRW_curve_batch_cache_get_triangles_with_normals(cu); } GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob) @@ -2961,11 +2959,10 @@ GPUBatch *DRW_cache_curve_loose_edges_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - /* TODO */ - UNUSED_VARS(cu); - return NULL; - } + + /* TODO */ + UNUSED_VARS(cu); + return NULL; } GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob) @@ -2977,9 +2974,8 @@ GPUBatch *DRW_cache_curve_face_wireframe_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wireframes_face(cu); - } + + return DRW_curve_batch_cache_get_wireframes_face(cu); } GPUBatch *DRW_cache_curve_edge_detection_get(Object *ob, bool *r_is_manifold) @@ -2990,9 +2986,8 @@ GPUBatch *DRW_cache_curve_edge_detection_get(Object *ob, bool *r_is_manifold) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold); } - else { - return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); - } + + return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); } /* Return list of batches */ @@ -3007,9 +3002,8 @@ GPUBatch **DRW_cache_curve_surface_shaded_get(Object *ob, if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); } - else { - return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); - } + + return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); } /** \} */ @@ -3061,12 +3055,11 @@ GPUBatch *DRW_cache_text_edge_wire_get(Object *ob) if (!has_surface) { return NULL; } - else if (mesh_eval != NULL) { + if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wire_edge(cu); - } + + return DRW_curve_batch_cache_get_wire_edge(cu); } GPUBatch *DRW_cache_text_surface_get(Object *ob) @@ -3080,9 +3073,8 @@ GPUBatch *DRW_cache_text_surface_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface(mesh_eval); } - else { - return DRW_curve_batch_cache_get_triangles_with_normals(cu); - } + + return DRW_curve_batch_cache_get_triangles_with_normals(cu); } GPUBatch *DRW_cache_text_edge_detection_get(Object *ob, bool *r_is_manifold) @@ -3096,9 +3088,8 @@ GPUBatch *DRW_cache_text_edge_detection_get(Object *ob, bool *r_is_manifold) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold); } - else { - return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); - } + + return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); } GPUBatch *DRW_cache_text_loose_edges_get(Object *ob) @@ -3112,9 +3103,8 @@ GPUBatch *DRW_cache_text_loose_edges_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wire_edge(cu); - } + + return DRW_curve_batch_cache_get_wire_edge(cu); } GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob) @@ -3128,9 +3118,8 @@ GPUBatch *DRW_cache_text_face_wireframe_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wireframes_face(cu); - } + + return DRW_curve_batch_cache_get_wireframes_face(cu); } GPUBatch **DRW_cache_text_surface_shaded_get(Object *ob, @@ -3146,9 +3135,8 @@ GPUBatch **DRW_cache_text_surface_shaded_get(Object *ob, if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); } - else { - return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); - } + + return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); } /** \} */ @@ -3166,9 +3154,8 @@ GPUBatch *DRW_cache_surf_surface_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface(mesh_eval); } - else { - return DRW_curve_batch_cache_get_triangles_with_normals(cu); - } + + return DRW_curve_batch_cache_get_triangles_with_normals(cu); } GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob) @@ -3180,9 +3167,8 @@ GPUBatch *DRW_cache_surf_edge_wire_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wire_edge(cu); - } + + return DRW_curve_batch_cache_get_wire_edge(cu); } GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob) @@ -3194,9 +3180,8 @@ GPUBatch *DRW_cache_surf_face_wireframe_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_wireframes_face(mesh_eval); } - else { - return DRW_curve_batch_cache_get_wireframes_face(cu); - } + + return DRW_curve_batch_cache_get_wireframes_face(cu); } GPUBatch *DRW_cache_surf_edge_detection_get(Object *ob, bool *r_is_manifold) @@ -3207,9 +3192,8 @@ GPUBatch *DRW_cache_surf_edge_detection_get(Object *ob, bool *r_is_manifold) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_edge_detection(mesh_eval, r_is_manifold); } - else { - return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); - } + + return DRW_curve_batch_cache_get_edge_detection(cu, r_is_manifold); } GPUBatch *DRW_cache_surf_loose_edges_get(Object *ob) @@ -3221,11 +3205,10 @@ GPUBatch *DRW_cache_surf_loose_edges_get(Object *ob) if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_loose_edges(mesh_eval); } - else { - /* TODO */ - UNUSED_VARS(cu); - return NULL; - } + + /* TODO */ + UNUSED_VARS(cu); + return NULL; } /* Return list of batches */ @@ -3240,9 +3223,8 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(Object *ob, if (mesh_eval != NULL) { return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); } - else { - return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); - } + + return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); } /** \} */ @@ -3289,9 +3271,16 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob) GPUBatch *DRW_cache_pointcloud_get_dots(Object *object) { + BLI_assert(object->type == OB_POINTCLOUD); return DRW_pointcloud_batch_cache_get_dots(object); } +GPUBatch *DRW_cache_pointcloud_surface_get(Object *object) +{ + BLI_assert(object->type == OB_POINTCLOUD); + return DRW_pointcloud_batch_cache_get_surface(object); +} + /* -------------------------------------------------------------------- */ /** \name Volume * \{ */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 2f289bf4110..2a7448ce877 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_CACHE_H__ -#define __DRAW_CACHE_H__ +#pragma once struct GPUBatch; struct GPUMaterial; @@ -215,6 +214,7 @@ struct GPUBatch *DRW_cache_hair_edge_detection_get(struct Object *ob, bool *r_is /* PointCloud */ struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj); +struct GPUBatch *DRW_cache_pointcloud_surface_get(struct Object *obj); /* Volume */ typedef struct DRWVolumeGrid { @@ -250,5 +250,3 @@ struct GPUBatch *DRW_cache_gpencil_face_wireframe_get(struct Object *ob); struct bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(struct Object *ob); void DRW_cache_gpencil_sbuffer_clear(struct Object *ob); - -#endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index 302f9a0d3a8..2653b3127ae 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_CACHE_EXTRACT_H__ -#define __DRAW_CACHE_EXTRACT_H__ +#pragma once struct TaskGraph; @@ -60,6 +59,10 @@ typedef struct DRW_MeshCDMask { * modifiers could remove it. (see T68857) */ uint32_t edit_uv : 1; } DRW_MeshCDMask; +/* Keep `DRW_MeshCDMask` struct within an `uint64_t`. + * bit-wise and atomic operations are used to compare and update the struct. + * See `mesh_cd_layers_type_*` functions. */ +BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint64_t), "DRW_MeshCDMask exceeds 64 bits") typedef enum eMRIterType { MR_ITER_LOOPTRI = 1 << 0, @@ -166,8 +169,7 @@ typedef enum DRWBatchFlag { MBC_WIRE_EDGES = (1 << 23), MBC_WIRE_LOOPS = (1 << 24), MBC_WIRE_LOOPS_UVS = (1 << 25), - MBC_SURF_PER_MAT = (1 << 26), - MBC_SKIN_ROOTS = (1 << 27), + MBC_SKIN_ROOTS = (1 << 26), } DRWBatchFlag; #define MBC_EDITUV \ @@ -266,5 +268,3 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, const Scene *scene, const ToolSettings *ts, const bool use_hide); - -#endif /* __DRAW_CACHE_EXTRACT_H__ */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 98da668f78f..a1d2a7eeb4a 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -474,10 +474,9 @@ BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *e if (vert_coords != NULL) { return vert_coords[BM_elem_index_get(eve)]; } - else { - UNUSED_VARS(mr); - return eve->co; - } + + UNUSED_VARS(mr); + return eve->co; } BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve) @@ -486,10 +485,9 @@ BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *e if (vert_normals != NULL) { return vert_normals[BM_elem_index_get(eve)]; } - else { - UNUSED_VARS(mr); - return eve->no; - } + + UNUSED_VARS(mr); + return eve->no; } BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa) @@ -498,10 +496,9 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e if (poly_normals != NULL) { return poly_normals[BM_elem_index_get(efa)]; } - else { - UNUSED_VARS(mr); - return efa->no; - } + + UNUSED_VARS(mr); + return efa->no; } /** \} */ @@ -890,12 +887,15 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data MeshExtract_Tri_Data *data = _data; GPU_indexbuf_build_in_place(&data->elb, ibo); /* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */ + /* The `surface_per_mat` tests are there when object shading type is set to Wire or Bounds. In + * these cases there isn't a surface per material. */ if (mr->use_final_mesh && mr->cache->surface_per_mat && mr->cache->surface_per_mat[0]) { - BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo); for (int i = 0; i < mr->mat_len; i++) { /* Multiply by 3 because these are triangle indices. */ - const int start = data->tri_mat_start[i] * 3; - const int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3; + const int mat_start = data->tri_mat_start[i]; + const int mat_end = data->tri_mat_end[i]; + const int start = mat_start * 3; + const int len = (mat_end - mat_start) * 3; GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len); /* WARNING: We modify the #GPUBatch here! */ GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true); @@ -2534,26 +2534,28 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) } /* Sculpt Vertex Colors */ - for (int i = 0; i < 8; i++) { - if (svcol_layers & (1 << i)) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); - GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - - BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); - GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "c"); - } - if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { - GPU_vertformat_alias_add(&format, "ac"); - } - /* Gather number of auto layers. */ - /* We only do `vcols` that are not overridden by `uvs`. */ - if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_alias_add(&format, attr_name); + if (U.experimental.use_sculpt_vertex_colors) { + for (int i = 0; i < 8; i++) { + if (svcol_layers & (1 << i)) { + char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; + const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i); + GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); + + BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name); + GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) { + GPU_vertformat_alias_add(&format, "ac"); + } + /* Gather number of auto layers. */ + /* We only do `vcols` that are not overridden by `uvs`. */ + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) { + BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); + GPU_vertformat_alias_add(&format, attr_name); + } } } } @@ -2599,7 +2601,7 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) } } - if (svcol_layers & (1 << i)) { + if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) { if (mr->extract_type == MR_EXTRACT_BMESH) { int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i); BMIter f_iter; @@ -2932,7 +2934,7 @@ static float evaluate_vertex_weight(const MDeformVert *dvert, const DRW_MeshWeig if ((wstate->defgroup_active < 0) && (wstate->defgroup_len > 0)) { return -2.0f; } - else if (dvert == NULL) { + if (dvert == NULL) { return (wstate->alert_mode != OB_DRAW_GROUPUSER_NONE) ? -1.0f : 0.0f; } @@ -4291,7 +4293,7 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp) /* non-manifold edge, yet... */ continue; } - else if (*pval != NULL) { + if (*pval != NULL) { const float *f1_no = mr->poly_normals[mp_index]; const float *f2_no = *pval; angle = angle_normalized_v3v3(f1_no, f2_no); @@ -4384,10 +4386,6 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf) GPUVertBuf *vbo = buf; GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, mr->poly_len); - if (!mr->use_subsurf_fdots) { - /* Clear so we can accumulate on it. */ - memset(vbo->data, 0x0, mr->poly_len * vbo->format.stride); - } return vbo->data; } @@ -4396,12 +4394,20 @@ static void extract_fdots_pos_iter_poly_bm(const MeshRenderData *mr, void *data) { float(*center)[3] = data; - EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + + EXTRACT_POLY_FOREACH_BM_BEGIN(f, f_index, params, mr) { - float w = 1.0f / (float)l->f->len; - madd_v3_v3fl(center[BM_elem_index_get(l->f)], bm_vert_co_get(mr, l->v), w); + float *co = center[f_index]; + zero_v3(co); + + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(co, bm_vert_co_get(mr, l_iter->v)); + } while ((l_iter = l_iter->next) != l_first); + mul_v3_fl(co, 1.0f / (float)f->len); } - EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); + EXTRACT_POLY_FOREACH_BM_END; } static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, @@ -4409,20 +4415,34 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr, void *data) { float(*center)[3] = (float(*)[3])data; - EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) - { - const MVert *mv = &mr->mvert[ml->v]; - if (mr->use_subsurf_fdots) { + const MVert *mvert = mr->mvert; + const MLoop *mloop = mr->mloop; + + if (mr->use_subsurf_fdots) { + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + const MVert *mv = &mr->mvert[ml->v]; if (mv->flag & ME_VERT_FACEDOT) { copy_v3_v3(center[mp_index], mv->co); } } - else { - float w = 1.0f / (float)mp->totloop; - madd_v3_v3fl(center[mp_index], mv->co, w); + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; + } + else { + EXTRACT_POLY_FOREACH_MESH_BEGIN(mp, mp_index, params, mr) + { + float *co = center[mp_index]; + zero_v3(co); + + const MLoop *ml = &mloop[mp->loopstart]; + for (int i = 0; i < mp->totloop; i++, ml++) { + const MVert *mv = &mvert[ml->v]; + add_v3_v3(center[mp_index], mv->co); + } + mul_v3_fl(co, 1.0f / (float)mp->totloop); } + EXTRACT_POLY_FOREACH_MESH_END; } - EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; } static const MeshExtract extract_fdots_pos = { diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 5cf1c24af0b..784e52cfa17 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_CACHE_IMPL_H__ -#define __DRAW_CACHE_IMPL_H__ +#pragma once struct GPUBatch; struct GPUIndexBuf; @@ -144,6 +143,10 @@ int DRW_hair_material_count_get(struct Hair *hair); int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud); struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob); +struct GPUBatch *DRW_pointcloud_batch_cache_get_surface(struct Object *ob); +struct GPUBatch **DRW_cache_pointcloud_surface_shaded_get(struct Object *ob, + struct GPUMaterial **gpumat_array, + uint gpumat_array_len); /* Volume */ int DRW_volume_material_count_get(struct Volume *volume); @@ -250,5 +253,3 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object * struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); - -#endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 53e04fb61ee..0ab14574fa6 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -135,9 +135,8 @@ static GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra) gpencil_batch_cache_clear(cache); return gpencil_batch_cache_init(ob, cfra); } - else { - return cache; - } + + return cache; } void DRW_gpencil_batch_cache_dirty_tag(bGPdata *gpd) @@ -150,7 +149,6 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd) gpencil_batch_cache_clear(gpd->runtime.gpencil_cache); MEM_SAFE_FREE(gpd->runtime.gpencil_cache); gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - return; } /** \} */ @@ -273,7 +271,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts, int v, bool is_endpoint) { - /* Note: we use the sign of stength and thickness to pass cap flag. */ + /* Note: we use the sign of strength and thickness to pass cap flag. */ const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND); const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND); gpStrokeVert *vert = &verts[v]; diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c index 66a67d6b8fe..0f80b5159a7 100644 --- a/source/blender/draw/intern/draw_cache_impl_lattice.c +++ b/source/blender/draw/intern/draw_cache_impl_lattice.c @@ -83,10 +83,9 @@ static int lattice_render_verts_len_get(Lattice *lt) if ((lt->flag & LT_OUTSIDE) == 0) { return vert_len_calc(u, v, w); } - else { - /* TODO remove internal coords */ - return vert_len_calc(u, v, w); - } + + /* TODO remove internal coords */ + return vert_len_calc(u, v, w); } static int lattice_render_edges_len_get(Lattice *lt) @@ -102,10 +101,9 @@ static int lattice_render_edges_len_get(Lattice *lt) if ((lt->flag & LT_OUTSIDE) == 0) { return edge_len_calc(u, v, w); } - else { - /* TODO remove internal coords */ - return edge_len_calc(u, v, w); - } + + /* TODO remove internal coords */ + return edge_len_calc(u, v, w); } /* ---------------------------------------------------------------------- */ @@ -252,12 +250,11 @@ static bool lattice_batch_cache_valid(Lattice *lt) if (cache->is_dirty) { return false; } - else { - if ((cache->dims.u_len != lt->pntsu) || (cache->dims.v_len != lt->pntsv) || - (cache->dims.w_len != lt->pntsw) || - ((cache->show_only_outside != ((lt->flag & LT_OUTSIDE) != 0)))) { - return false; - } + + if ((cache->dims.u_len != lt->pntsu) || (cache->dims.v_len != lt->pntsv) || + (cache->dims.w_len != lt->pntsw) || + ((cache->show_only_outside != ((lt->flag & LT_OUTSIDE) != 0)))) { + return false; } return true; diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index ea1717f0684..d6faeb16583 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -74,22 +74,30 @@ static void mesh_batch_cache_clear(Mesh *me); /* Return true is all layers in _b_ are inside _a_. */ BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b); + return (*((uint64_t *)&a) & *((uint64_t *)&b)) == *((uint64_t *)&b); } BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b) { - return *((uint32_t *)&a) == *((uint32_t *)&b); + return *((uint64_t *)&a) == *((uint64_t *)&b); } BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) { - atomic_fetch_and_or_uint32((uint32_t *)a, *(uint32_t *)&b); + uint32_t *a_p = (uint32_t *)a; + uint32_t *b_p = (uint32_t *)&b; + atomic_fetch_and_or_uint32(a_p, *b_p); + atomic_fetch_and_or_uint32(a_p + 1, *(b_p + 1)); } BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a) { - *((uint32_t *)a) = 0; + *((uint64_t *)a) = 0; +} + +BLI_INLINE const Mesh *editmesh_final_or_this(const Mesh *me) +{ + return (me->edit_mesh && me->edit_mesh->mesh_eval_final) ? me->edit_mesh->mesh_eval_final : me; } static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used) @@ -129,7 +137,7 @@ BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { - const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); if (layer != -1) { @@ -139,7 +147,7 @@ static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { - const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV); if (layer != -1) { @@ -149,7 +157,7 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { - const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR); @@ -160,7 +168,7 @@ static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_us static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { - const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_ldata = &me_final->ldata; int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); @@ -173,7 +181,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, struct GPUMaterial **gpumat_array, int gpumat_array_len) { - const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + const Mesh *me_final = editmesh_final_or_this(me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); @@ -200,14 +208,17 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, type = CD_MTFACE; if (layer == -1) { - layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name); - type = CD_MCOL; + if (U.experimental.use_sculpt_vertex_colors) { + layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); + type = CD_PROP_COLOR; + } } if (layer == -1) { - layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); - type = CD_PROP_COLOR; + layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name); + type = CD_MCOL; } + #if 0 /* Tangents are always from UV's - this will never happen. */ if (layer == -1) { layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name); @@ -257,13 +268,26 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, } case CD_PROP_COLOR: { /* Sculpt Vertex Colors */ + bool use_mloop_cols = false; if (layer == -1) { layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name) : CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR); + /* Fallback to Vertex Color data */ + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) : + CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL); + use_mloop_cols = true; + } } if (layer != -1) { - cd_used.sculpt_vcol |= (1 << layer); + if (use_mloop_cols) { + cd_used.vcol |= (1 << layer); + } + else { + cd_used.sculpt_vcol |= (1 << layer); + } } break; } @@ -508,14 +532,26 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache, } } -static void mesh_batch_cache_discard_shaded_batches(MeshBatchCache *cache) +static void mesh_batch_cache_request_surface_batches(MeshBatchCache *cache) { + mesh_batch_cache_add_request(cache, MBC_SURFACE); + DRW_batch_request(&cache->batch.surface); + if (cache->surface_per_mat) { + for (int i = 0; i < cache->mat_len; i++) { + DRW_batch_request(&cache->surface_per_mat[i]); + } + } +} + +static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache) +{ + GPU_BATCH_DISCARD_SAFE(cache->batch.surface); if (cache->surface_per_mat) { for (int i = 0; i < cache->mat_len; i++) { GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]); } } - cache->batch_ready &= ~MBC_SURF_PER_MAT; + cache->batch_ready &= ~MBC_SURFACE; } static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) @@ -527,7 +563,7 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco); } - mesh_batch_cache_discard_shaded_batches(cache); + mesh_batch_cache_discard_surface_batches(cache); mesh_cd_layers_type_clear(&cache->cd_used); MEM_SAFE_FREE(cache->surface_per_mat); @@ -567,10 +603,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) cache->cd_used.edit_uv = 0; /* Discard other batches that uses vbo.uv */ - mesh_batch_cache_discard_shaded_batches(cache); - - GPU_BATCH_DISCARD_SAFE(cache->batch.surface); - cache->batch_ready &= ~MBC_SURFACE; + mesh_batch_cache_discard_surface_batches(cache); } static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache) @@ -632,12 +665,8 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) GPU_BATCH_DISCARD_SAFE(cache->batch.surface); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_edges); - if (cache->surface_per_mat) { - for (int i = 0; i < cache->mat_len; i++) { - GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]); - } - } - cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT); + mesh_batch_cache_discard_surface_batches(cache); + cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS); break; case BKE_MESH_BATCH_DIRTY_ALL: cache->is_dirty = true; @@ -763,8 +792,8 @@ GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - mesh_batch_cache_add_request(cache, MBC_SURFACE); - return DRW_batch_request(&cache->batch.surface); + mesh_batch_cache_request_surface_batches(cache); + return cache->batch.surface; } GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me) @@ -774,9 +803,8 @@ GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me) if (cache->no_loose_wire) { return NULL; } - else { - return DRW_batch_request(&cache->batch.loose_edges); - } + + return DRW_batch_request(&cache->batch.loose_edges); } GPUBatch *DRW_mesh_batch_cache_get_surface_weights(Mesh *me) @@ -822,23 +850,15 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, BLI_assert(gpumat_array_len == cache->mat_len); mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); - - mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT); - - for (int i = 0; i < cache->mat_len; i++) { - DRW_batch_request(&cache->surface_per_mat[i]); - } + mesh_batch_cache_request_surface_batches(cache); return cache->surface_per_mat; } GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT); texpaint_request_active_uv(cache, me); - for (int i = 0; i < cache->mat_len; i++) { - DRW_batch_request(&cache->surface_per_mat[i]); - } + mesh_batch_cache_request_surface_batches(cache); return cache->surface_per_mat; } @@ -846,24 +866,24 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_uv(cache, me); - mesh_batch_cache_add_request(cache, MBC_SURFACE); - return DRW_batch_request(&cache->batch.surface); + mesh_batch_cache_request_surface_batches(cache); + return cache->batch.surface; } GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); texpaint_request_active_vcol(cache, me); - mesh_batch_cache_add_request(cache, MBC_SURFACE); - return DRW_batch_request(&cache->batch.surface); + mesh_batch_cache_request_surface_batches(cache); + return cache->batch.surface; } GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); sculpt_request_active_vcol(cache, me); - mesh_batch_cache_add_request(cache, MBC_SURFACE); - return DRW_batch_request(&cache->batch.surface); + mesh_batch_cache_request_surface_batches(cache); + return cache->batch.surface; } int DRW_mesh_material_count_get(Mesh *me) @@ -881,8 +901,7 @@ GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ - mesh_batch_cache_add_request(cache, MBC_SURFACE); - DRW_batch_request(&cache->batch.surface); + mesh_batch_cache_request_surface_batches(cache); DRW_vbo_request(NULL, &cache->final.vbo.pos_nor); return cache->final.vbo.pos_nor; @@ -1103,6 +1122,40 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) mesh_cd_layers_type_clear(&cache->cd_used_over_time); } +#ifdef DEBUG +/* Sanity check function to test if all requested batches are available. */ +static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + /* Make sure all requested batches have been setup. */ + /* Note: The next line creates a different scheduling than during release builds what can lead to + * some issues (See T77867 where we needed to disable this function in order to debug what was + * happening in release builds). */ + BLI_task_graph_work_and_wait(task_graph); + for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { + BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); + } + for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) { + BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i])); + } + for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) { + BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i])); + } + for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) { + BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i])); + } + for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) { + BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i])); + } + for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) { + BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i])); + } + for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) { + BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i])); + } +} +#endif + /* Can be called for any surface type. Mesh *me is the final mesh. */ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, Object *ob, @@ -1123,10 +1176,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, /* Early out */ if (cache->batch_requested == 0) { #ifdef DEBUG - goto check; -#else - return; + drw_mesh_batch_cache_check_available(task_graph, me); #endif + return; } /* Sanity check. */ @@ -1151,30 +1203,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, } } - /* HACK: if MBC_SURF_PER_MAT is requested and ibo.tris is already available, it won't have it's - * index ranges initialized. So discard ibo.tris in order to recreate it. - * This needs to happen before saved_elem_ranges is populated. */ - if ((batch_requested & MBC_SURF_PER_MAT) != 0 && (cache->batch_ready & MBC_SURF_PER_MAT) == 0) { - FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { - GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris); - } - /* Clear all batches that reference ibo.tris. */ - GPU_BATCH_CLEAR_SAFE(cache->batch.surface); - GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights); - GPU_BATCH_CLEAR_SAFE(cache->batch.edit_mesh_analysis); - GPU_BATCH_CLEAR_SAFE(cache->batch.edit_triangles); - GPU_BATCH_CLEAR_SAFE(cache->batch.edit_lnor); - GPU_BATCH_CLEAR_SAFE(cache->batch.edit_selection_faces); - for (int i = 0; i < cache->mat_len; i++) { - GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]); - } - - cache->batch_ready &= ~(MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_MESH_ANALYSIS | - MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR | MBC_EDIT_SELECTION_FACES); - } - if (batch_requested & - (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA | + (MBC_SURFACE | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) { /* Modifiers will only generate an orco layer if the mesh is deformed. */ if (cache->cd_needed.orco != 0) { @@ -1227,7 +1257,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]); } GPU_BATCH_CLEAR_SAFE(cache->batch.surface); - cache->batch_ready &= ~(MBC_SURFACE | MBC_SURF_PER_MAT); + cache->batch_ready &= ~(MBC_SURFACE); mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); } @@ -1243,9 +1273,11 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv); + GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_edituv_data); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_lines); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_points); + GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_fdots); } /* We only clear the batches as they may already have been * referenced. */ @@ -1263,10 +1295,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, /* Second chance to early out */ if ((batch_requested & ~cache->batch_ready) == 0) { #ifdef DEBUG - goto check; -#else - return; + drw_mesh_batch_cache_check_available(task_graph, me); #endif + return; } cache->batch_ready |= batch_requested; @@ -1518,32 +1549,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, ts, use_hide); #ifdef DEBUG -check: - /* Make sure all requested batches have been setup. */ - /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and - * additional looping.*/ - BLI_task_graph_work_and_wait(task_graph); - for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { - BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); - } - for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) { - BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i])); - } - for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) { - BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i])); - } - for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) { - BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i])); - } - for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) { - BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i])); - } - for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) { - BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i])); - } - for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) { - BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i])); - } + drw_mesh_batch_cache_check_available(task_graph, me); #endif } diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 331a1f80bec..3ecdbff1e96 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -128,9 +128,8 @@ static bool particle_batch_cache_valid(ParticleSystem *psys) if (cache->is_dirty == false) { return true; } - else { - return false; - } + + return false; return true; } @@ -647,14 +646,13 @@ static float particle_key_weight(const ParticleData *particle, int strand, float if (t == 1.0) { return hkeys[part->totkey - 1].weight; } - else { - float interp = t / edit_key_seg_t; - int index = (int)interp; - interp -= floorf(interp); /* Time between 2 edit key */ - float s1 = hkeys[index].weight; - float s2 = hkeys[index + 1].weight; - return s1 + interp * (s2 - s1); - } + + float interp = t / edit_key_seg_t; + int index = (int)interp; + interp -= floorf(interp); /* Time between 2 edit key */ + float s1 = hkeys[index].weight; + float s2 = hkeys[index + 1].weight; + return s1 + interp * (s2 - s1); } static int particle_batch_cache_fill_segments_edit( diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.c b/source/blender/draw/intern/draw_cache_impl_pointcloud.c index 53939b35285..06cedb9f72c 100644 --- a/source/blender/draw/intern/draw_cache_impl_pointcloud.c +++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.c @@ -28,6 +28,7 @@ #include "MEM_guardedalloc.h" #include "BLI_math_base.h" +#include "BLI_math_vector.h" #include "BLI_utildefines.h" #include "DNA_object_types.h" @@ -45,11 +46,18 @@ static void pointcloud_batch_cache_clear(PointCloud *pointcloud); /* PointCloud GPUBatch Cache */ typedef struct PointCloudBatchCache { - GPUVertBuf *pos; - GPUBatch *batch; + GPUVertBuf *pos; /* Position and radius. */ + GPUVertBuf *geom; /* Instanced geometry for each point in the cloud (small sphere). */ + GPUIndexBuf *geom_indices; + + GPUBatch *dots; + GPUBatch *surface; + GPUBatch **surface_per_mat; /* settings to determine if cache is invalid */ bool is_dirty; + + int mat_len; } PointCloudBatchCache; /* GPUBatch cache management. */ @@ -57,7 +65,14 @@ typedef struct PointCloudBatchCache { static bool pointcloud_batch_cache_valid(PointCloud *pointcloud) { PointCloudBatchCache *cache = pointcloud->batch_cache; - return (cache && cache->is_dirty == false); + + if (cache == NULL) { + return false; + } + if (cache->mat_len != DRW_pointcloud_material_count_get(pointcloud)) { + return false; + } + return cache->is_dirty == false; } static void pointcloud_batch_cache_init(PointCloud *pointcloud) @@ -71,6 +86,10 @@ static void pointcloud_batch_cache_init(PointCloud *pointcloud) memset(cache, 0, sizeof(*cache)); } + cache->mat_len = DRW_pointcloud_material_count_get(pointcloud); + cache->surface_per_mat = MEM_callocN(sizeof(GPUBatch *) * cache->mat_len, + "pointcloud suface_per_mat"); + cache->is_dirty = false; } @@ -109,8 +128,18 @@ static void pointcloud_batch_cache_clear(PointCloud *pointcloud) return; } - GPU_BATCH_DISCARD_SAFE(cache->batch); + GPU_BATCH_DISCARD_SAFE(cache->dots); + GPU_BATCH_DISCARD_SAFE(cache->surface); GPU_VERTBUF_DISCARD_SAFE(cache->pos); + GPU_VERTBUF_DISCARD_SAFE(cache->geom); + GPU_INDEXBUF_DISCARD_SAFE(cache->geom_indices); + + if (cache->surface_per_mat) { + for (int i = 0; i < cache->mat_len; i++) { + GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]); + } + } + MEM_SAFE_FREE(cache->surface_per_mat); } void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud) @@ -126,35 +155,84 @@ static void pointcloud_batch_cache_ensure_pos(Object *ob, PointCloudBatchCache * } PointCloud *pointcloud = ob->data; + const bool has_radius = pointcloud->radius != NULL; static GPUVertFormat format = {0}; - static uint pos_id; - static uint radius_id; + static GPUVertFormat format_no_radius = {0}; + static uint pos; if (format.attr_len == 0) { /* initialize vertex format */ - pos_id = GPU_vertformat_attr_add(&format, "pointcloud_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - radius_id = GPU_vertformat_attr_add( - &format, "pointcloud_radius", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + /* From the opengl wiki: + * Note that size does not have to exactly match the size used by the vertex shader. If the + * vertex shader has fewer components than the attribute provides, then the extras are ignored. + * If the vertex shader has more components than the array provides, the extras are given + * values from the vector (0, 0, 0, 1) for the missing XYZW components. + */ + pos = GPU_vertformat_attr_add(&format_no_radius, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); } - GPU_VERTBUF_DISCARD_SAFE(cache->pos); - cache->pos = GPU_vertbuf_create_with_format(&format); + cache->pos = GPU_vertbuf_create_with_format(has_radius ? &format : &format_no_radius); GPU_vertbuf_data_alloc(cache->pos, pointcloud->totpoint); - GPU_vertbuf_attr_fill(cache->pos, pos_id, pointcloud->co); - if (pointcloud->radius) { - GPU_vertbuf_attr_fill(cache->pos, radius_id, pointcloud->radius); - } - else if (pointcloud->totpoint) { - /* TODO: optimize for constant radius by not including in vertex buffer at all? */ - float *radius = MEM_malloc_arrayN(pointcloud->totpoint, sizeof(float), __func__); + if (has_radius) { + float(*vbo_data)[4] = (float(*)[4])cache->pos->data; for (int i = 0; i < pointcloud->totpoint; i++) { - /* TODO: add default radius to PointCloud data structure. */ - radius[i] = 0.01f; + copy_v3_v3(vbo_data[i], pointcloud->co[i]); + /* TODO(fclem) remove multiplication here. Here only for keeping the size correct for now. */ + vbo_data[i][3] = pointcloud->radius[i] * 100.0f; } - GPU_vertbuf_attr_fill(cache->pos, radius_id, radius); - MEM_freeN(radius); } + else { + GPU_vertbuf_attr_fill(cache->pos, pos, pointcloud->co); + } +} + +static const float half_octahedron_normals[5][3] = { + {0.0f, 0.0f, 1.0f}, + {1.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, +}; + +static const uint half_octahedron_tris[4][3] = { + {0, 1, 2}, + {0, 2, 3}, + {0, 3, 4}, + {0, 4, 1}, +}; + +static void pointcloud_batch_cache_ensure_geom(Object *UNUSED(ob), PointCloudBatchCache *cache) +{ + if (cache->geom != NULL) { + return; + } + + static GPUVertFormat format = {0}; + static uint pos; + if (format.attr_len == 0) { + /* initialize vertex format */ + pos = GPU_vertformat_attr_add(&format, "pos_inst", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_alias_add(&format, "nor"); + } + + cache->geom = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(cache->geom, ARRAY_SIZE(half_octahedron_normals)); + + GPU_vertbuf_attr_fill(cache->geom, pos, half_octahedron_normals); + + GPUIndexBufBuilder builder; + GPU_indexbuf_init(&builder, + GPU_PRIM_TRIS, + ARRAY_SIZE(half_octahedron_tris), + ARRAY_SIZE(half_octahedron_normals)); + + for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) { + GPU_indexbuf_add_tri_verts(&builder, UNPACK3(half_octahedron_tris[i])); + } + + cache->geom_indices = GPU_indexbuf_build(&builder); } GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) @@ -162,12 +240,48 @@ GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) PointCloud *pointcloud = ob->data; PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); - if (cache->batch == NULL) { + if (cache->dots == NULL) { pointcloud_batch_cache_ensure_pos(ob, cache); - cache->batch = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, NULL); + cache->dots = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, NULL); + } + + return cache->dots; +} + +GPUBatch *DRW_pointcloud_batch_cache_get_surface(Object *ob) +{ + PointCloud *pointcloud = ob->data; + PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + + if (cache->surface == NULL) { + pointcloud_batch_cache_ensure_pos(ob, cache); + pointcloud_batch_cache_ensure_geom(ob, cache); + + cache->surface = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); + GPU_batch_instbuf_add_ex(cache->surface, cache->pos, false); + } + + return cache->surface; +} + +GPUBatch **DRW_cache_pointcloud_surface_shaded_get(Object *ob, + struct GPUMaterial **UNUSED(gpumat_array), + uint gpumat_array_len) +{ + PointCloud *pointcloud = ob->data; + PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + BLI_assert(cache->mat_len == gpumat_array_len); + UNUSED_VARS(gpumat_array_len); + + if (cache->surface_per_mat[0] == NULL) { + pointcloud_batch_cache_ensure_pos(ob, cache); + pointcloud_batch_cache_ensure_geom(ob, cache); + + cache->surface_per_mat[0] = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); + GPU_batch_instbuf_add_ex(cache->surface_per_mat[0], cache->pos, false); } - return cache->batch; + return cache->surface_per_mat; } int DRW_pointcloud_material_count_get(PointCloud *pointcloud) diff --git a/source/blender/draw/intern/draw_cache_impl_volume.c b/source/blender/draw/intern/draw_cache_impl_volume.c index 9c2c075ab4f..e07f5b33d58 100644 --- a/source/blender/draw/intern/draw_cache_impl_volume.c +++ b/source/blender/draw/intern/draw_cache_impl_volume.c @@ -266,7 +266,7 @@ static DRWVolumeGrid *volume_grid_cache_get(Volume *volume, NULL); GPU_texture_bind(cache_grid->texture, 0); - GPU_texture_swizzle_channel_auto(cache_grid->texture, channels); + GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1"); GPU_texture_wrap_mode(cache_grid->texture, false, false); GPU_texture_unbind(cache_grid->texture); diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h index 67f44b5fb0c..bb3a908c6c5 100644 --- a/source/blender/draw/intern/draw_cache_inline.h +++ b/source/blender/draw/intern/draw_cache_inline.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_CACHE_INLINE_H__ -#define __DRAW_CACHE_INLINE_H__ +#pragma once #include "GPU_batch.h" #include "MEM_guardedalloc.h" @@ -110,5 +109,3 @@ BLI_INLINE bool DRW_vbo_requested(GPUVertBuf *vbo) { return (vbo != NULL && vbo->format.attr_len == 0); } - -#endif /* __DRAW_CACHE_INLINE_H__ */ diff --git a/source/blender/draw/intern/draw_color_management.h b/source/blender/draw/intern/draw_color_management.h index 9d83eccdce9..3150ec72138 100644 --- a/source/blender/draw/intern/draw_color_management.h +++ b/source/blender/draw/intern/draw_color_management.h @@ -20,9 +20,6 @@ * \ingroup draw */ -#ifndef __DRAW_COLOR_MANAGEMENT_H__ -#define __DRAW_COLOR_MANAGEMENT_H__ +#pragma once void DRW_transform_none(struct GPUTexture *tex); - -#endif /* __DRAW_COLOR_MANAGEMENT_H__ */ diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index aa8dd2f7fa4..0f26a8ddc09 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -22,6 +22,7 @@ #include "DRW_render.h" +#include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -31,8 +32,6 @@ #include "BKE_global.h" #include "BKE_object.h" -#include "BIF_glutil.h" - #include "draw_common.h" #if 0 @@ -280,7 +279,7 @@ DRWView *DRW_view_create_with_zoffset(const DRWView *parent_view, viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1])); } - winmat[3][2] -= bglPolygonOffsetCalc((float *)winmat, viewdist, offset); + winmat[3][2] -= GPU_polygon_offset_calc(winmat, viewdist, offset); return DRW_view_create_sub(parent_view, viewmat, winmat); } @@ -456,11 +455,11 @@ bool DRW_object_is_flat(Object *ob, int *r_axis) *r_axis = 0; return true; } - else if (dim[1] == 0.0f) { + if (dim[1] == 0.0f) { *r_axis = 1; return true; } - else if (dim[2] == 0.0f) { + if (dim[2] == 0.0f) { *r_axis = 2; return true; } diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 81c0e97a1a8..6060dce47ac 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -20,15 +20,16 @@ * \ingroup draw */ -#ifndef __DRAW_COMMON_H__ -#define __DRAW_COMMON_H__ +#pragma once struct DRWPass; struct DRWShadingGroup; struct GPUMaterial; struct ModifierData; +struct FluidModifierData; struct Object; struct ParticleSystem; +struct RegionView3D; struct ViewLayer; #define UBO_FIRST_COLOR colorWire @@ -159,14 +160,14 @@ void DRW_globals_update(void); void DRW_globals_free(void); struct DRWView *DRW_view_create_with_zoffset(const struct DRWView *parent_view, - const RegionView3D *rv3d, + const struct RegionView3D *rv3d, float offset); int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color); float *DRW_color_background_blend_get(int theme_id); -bool DRW_object_is_flat(Object *ob, int *r_axis); -bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis); +bool DRW_object_is_flat(struct Object *ob, int *r_axis); +bool DRW_object_axis_orthogonal_to_view(struct Object *ob, int axis); /* draw_hair.c */ @@ -188,6 +189,16 @@ void DRW_hair_init(void); void DRW_hair_update(void); void DRW_hair_free(void); +/* draw_fluid.c */ + +/* Fluid simulation. */ +void DRW_smoke_ensure(struct FluidModifierData *fmd, int highres); +void DRW_smoke_ensure_coba_field(struct FluidModifierData *fmd); +void DRW_smoke_ensure_velocity(struct FluidModifierData *fmd); + +void DRW_smoke_free(struct FluidModifierData *fmd); +void DRW_smoke_free_velocity(struct FluidModifierData *fmd); + /* draw_common.c */ struct DRW_Global { /** If needed, contains all global/Theme colors @@ -203,5 +214,3 @@ struct DRW_Global { struct GPUUniformBuffer *view_ubo; }; extern struct DRW_Global G_draw; - -#endif /* __DRAW_COMMON_H__ */ diff --git a/source/blender/draw/intern/draw_debug.h b/source/blender/draw/intern/draw_debug.h index e7404b17384..149825974d4 100644 --- a/source/blender/draw/intern/draw_debug.h +++ b/source/blender/draw/intern/draw_debug.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_DEBUG_H__ -#define __DRAW_DEBUG_H__ +#pragma once struct BoundBox; @@ -34,5 +33,3 @@ void DRW_debug_m4(const float m[4][4]); void DRW_debug_m4_as_bbox(const float m[4][4], const float color[4], const bool invert); void DRW_debug_bbox(const BoundBox *bbox, const float color[4]); void DRW_debug_sphere(const float center[3], const float radius, const float color[4]); - -#endif /* __DRAW_DEBUG_H__ */ diff --git a/source/blender/draw/intern/draw_fluid.c b/source/blender/draw/intern/draw_fluid.c new file mode 100644 index 00000000000..33311dc698f --- /dev/null +++ b/source/blender/draw/intern/draw_fluid.c @@ -0,0 +1,419 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + * + * GPU fluid drawing functions. + */ + +#include <string.h> + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_fluid_types.h" +#include "DNA_modifier_types.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_colorband.h" + +#include "GPU_texture.h" + +#include "draw_common.h" /* Own include. */ + +#ifdef WITH_FLUID +# include "manta_fluid_API.h" +#endif + +/* -------------------------------------------------------------------- */ +/** \name Private API + * \{ */ + +#ifdef WITH_FLUID + +enum { + TFUNC_FLAME_SPECTRUM = 0, + TFUNC_COLOR_RAMP = 1, +}; + +# define TFUNC_WIDTH 256 + +static void create_flame_spectrum_texture(float *data) +{ +# define FIRE_THRESH 7 +# define MAX_FIRE_ALPHA 0.06f +# define FULL_ON_FIRE 100 + + float *spec_pixels = (float *)MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), + "spec_pixels"); + + blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000); + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + for (int k = 0; k < TFUNC_WIDTH; k++) { + int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4; + if (k >= FIRE_THRESH) { + spec_pixels[index] = (data[k * 4]); + spec_pixels[index + 1] = (data[k * 4 + 1]); + spec_pixels[index + 2] = (data[k * 4 + 2]); + spec_pixels[index + 3] = MAX_FIRE_ALPHA * + ((k > FULL_ON_FIRE) ? + 1.0f : + (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); + } + else { + zero_v4(&spec_pixels[index]); + } + } + } + } + + memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH); + + MEM_freeN(spec_pixels); + +# undef FIRE_THRESH +# undef MAX_FIRE_ALPHA +# undef FULL_ON_FIRE +} + +static void create_color_ramp(const struct ColorBand *coba, float *data) +{ + for (int i = 0; i < TFUNC_WIDTH; i++) { + BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]); + straight_to_premul_v4(&data[i * 4]); + } +} + +static GPUTexture *create_transfer_function(int type, const struct ColorBand *coba) +{ + float *data = (float *)MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__); + + switch (type) { + case TFUNC_FLAME_SPECTRUM: + create_flame_spectrum_texture(data); + break; + case TFUNC_COLOR_RAMP: + create_color_ramp(coba, data); + break; + } + + GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_SRGB8_A8, data, NULL); + + MEM_freeN(data); + + return tex; +} + +static void swizzle_texture_channel_single(GPUTexture *tex) +{ + /* Swizzle texture channels so that we get useful RGBA values when sampling + * a texture with fewer channels, e.g. when using density as color. */ + GPU_texture_bind(tex, 0); + GPU_texture_swizzle_set(tex, "rrr1"); + GPU_texture_unbind(tex); +} + +static GPUTexture *create_field_texture(FluidDomainSettings *fds) +{ + float *field = NULL; + + switch (fds->coba_field) { + case FLUID_DOMAIN_FIELD_DENSITY: + field = manta_smoke_get_density(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_HEAT: + field = manta_smoke_get_heat(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_FUEL: + field = manta_smoke_get_fuel(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_REACT: + field = manta_smoke_get_react(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_FLAME: + field = manta_smoke_get_flame(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_VELOCITY_X: + field = manta_get_velocity_x(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_VELOCITY_Y: + field = manta_get_velocity_y(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_VELOCITY_Z: + field = manta_get_velocity_z(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_COLOR_R: + field = manta_smoke_get_color_r(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_COLOR_G: + field = manta_smoke_get_color_g(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_COLOR_B: + field = manta_smoke_get_color_b(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_FORCE_X: + field = manta_get_force_x(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_FORCE_Y: + field = manta_get_force_y(fds->fluid); + break; + case FLUID_DOMAIN_FIELD_FORCE_Z: + field = manta_get_force_z(fds->fluid); + break; + default: + return NULL; + } + + GPUTexture *tex = GPU_texture_create_nD( + UNPACK3(fds->res), 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); + + swizzle_texture_channel_single(tex); + return tex; +} + +static GPUTexture *create_density_texture(FluidDomainSettings *fds, int highres) +{ + int *dim = (highres) ? fds->res_noise : fds->res; + + float *data; + if (highres) { + data = manta_noise_get_density(fds->fluid); + } + else { + data = manta_smoke_get_density(fds->fluid); + } + + GPUTexture *tex = GPU_texture_create_nD( + UNPACK3(dim), 3, data, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); + + swizzle_texture_channel_single(tex); + + return tex; +} + +static GPUTexture *create_color_texture(FluidDomainSettings *fds, int highres) +{ + const bool has_color = (highres) ? manta_noise_has_colors(fds->fluid) : + manta_smoke_has_colors(fds->fluid); + + if (!has_color) { + return NULL; + } + + int cell_count = (highres) ? manta_noise_get_cells(fds->fluid) : fds->total_cells; + int *dim = (highres) ? fds->res_noise : fds->res; + float *data = (float *)MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture"); + + if (data == NULL) { + return NULL; + } + + if (highres) { + manta_noise_get_rgba(fds->fluid, data, 0); + } + else { + manta_smoke_get_rgba(fds->fluid, data, 0); + } + + GPUTexture *tex = GPU_texture_create_nD( + dim[0], dim[1], dim[2], 3, data, GPU_RGBA8, GPU_DATA_FLOAT, 0, true, NULL); + + MEM_freeN(data); + + return tex; +} + +static GPUTexture *create_flame_texture(FluidDomainSettings *fds, int highres) +{ + float *source = NULL; + const bool has_fuel = (highres) ? manta_noise_has_fuel(fds->fluid) : + manta_smoke_has_fuel(fds->fluid); + int *dim = (highres) ? fds->res_noise : fds->res; + + if (!has_fuel) { + return NULL; + } + + if (highres) { + source = manta_noise_get_flame(fds->fluid); + } + else { + source = manta_smoke_get_flame(fds->fluid); + } + + GPUTexture *tex = GPU_texture_create_nD( + dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); + + swizzle_texture_channel_single(tex); + + return tex; +} + +#endif /* WITH_FLUID */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public API + * \{ */ + +void DRW_smoke_free(FluidModifierData *fmd) +{ + if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) { + if (fmd->domain->tex_density) { + GPU_texture_free(fmd->domain->tex_density); + fmd->domain->tex_density = NULL; + } + + if (fmd->domain->tex_color) { + GPU_texture_free(fmd->domain->tex_color); + fmd->domain->tex_color = NULL; + } + + if (fmd->domain->tex_shadow) { + GPU_texture_free(fmd->domain->tex_shadow); + fmd->domain->tex_shadow = NULL; + } + + if (fmd->domain->tex_flame) { + GPU_texture_free(fmd->domain->tex_flame); + fmd->domain->tex_flame = NULL; + } + + if (fmd->domain->tex_flame_coba) { + GPU_texture_free(fmd->domain->tex_flame_coba); + fmd->domain->tex_flame_coba = NULL; + } + + if (fmd->domain->tex_coba) { + GPU_texture_free(fmd->domain->tex_coba); + fmd->domain->tex_coba = NULL; + } + + if (fmd->domain->tex_field) { + GPU_texture_free(fmd->domain->tex_field); + fmd->domain->tex_field = NULL; + } + } +} + +void DRW_smoke_ensure_coba_field(FluidModifierData *fmd) +{ +#ifndef WITH_FLUID + UNUSED_VARS(fmd); +#else + if (fmd->type & MOD_FLUID_TYPE_DOMAIN) { + FluidDomainSettings *fds = fmd->domain; + + if (!fds->tex_field) { + fds->tex_field = create_field_texture(fds); + } + if (!fds->tex_coba) { + fds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, fds->coba); + } + } +#endif +} + +void DRW_smoke_ensure(FluidModifierData *fmd, int highres) +{ +#ifndef WITH_FLUID + UNUSED_VARS(fmd, highres); +#else + if (fmd->type & MOD_FLUID_TYPE_DOMAIN) { + FluidDomainSettings *fds = fmd->domain; + + if (!fds->tex_density) { + fds->tex_density = create_density_texture(fds, highres); + } + if (!fds->tex_color) { + fds->tex_color = create_color_texture(fds, highres); + } + if (!fds->tex_flame) { + fds->tex_flame = create_flame_texture(fds, highres); + } + if (!fds->tex_flame_coba && fds->tex_flame) { + fds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL); + } + if (!fds->tex_shadow) { + fds->tex_shadow = GPU_texture_create_nD(UNPACK3(fds->res), + 3, + manta_smoke_get_shadow(fds->fluid), + GPU_R8, + GPU_DATA_FLOAT, + 0, + true, + NULL); + } + } +#endif /* WITH_FLUID */ +} + +void DRW_smoke_ensure_velocity(FluidModifierData *fmd) +{ +#ifndef WITH_FLUID + UNUSED_VARS(fmd); +#else + if (fmd->type & MOD_FLUID_TYPE_DOMAIN) { + FluidDomainSettings *fds = fmd->domain; + + const float *vel_x = manta_get_velocity_x(fds->fluid); + const float *vel_y = manta_get_velocity_y(fds->fluid); + const float *vel_z = manta_get_velocity_z(fds->fluid); + + if (ELEM(NULL, vel_x, vel_y, vel_z)) { + return; + } + + if (!fds->tex_velocity_x) { + fds->tex_velocity_x = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_x, NULL); + fds->tex_velocity_y = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_y, NULL); + fds->tex_velocity_z = GPU_texture_create_3d(UNPACK3(fds->res), GPU_R16F, vel_z, NULL); + } + } +#endif /* WITH_FLUID */ +} + +/* TODO Unify with the other DRW_smoke_free. */ +void DRW_smoke_free_velocity(FluidModifierData *fmd) +{ + if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) { + if (fmd->domain->tex_velocity_x) { + GPU_texture_free(fmd->domain->tex_velocity_x); + } + + if (fmd->domain->tex_velocity_y) { + GPU_texture_free(fmd->domain->tex_velocity_y); + } + + if (fmd->domain->tex_velocity_z) { + GPU_texture_free(fmd->domain->tex_velocity_z); + } + + fmd->domain->tex_velocity_x = NULL; + fmd->domain->tex_velocity_y = NULL; + fmd->domain->tex_velocity_z = NULL; + } +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 6cfba0e2a78..cbdcbbf9090 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -343,7 +343,7 @@ void DRW_hair_update(void) DRW_draw_pass_subset(g_tf_pass, pr_call->shgrp, pr_call->shgrp); /* Readback result to main memory. */ - GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, data); + GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, GPU_DATA_FLOAT, data); /* Upload back to VBO. */ GPU_vertbuf_use(pr_call->vbo); glBufferSubData(GL_ARRAY_BUFFER, diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h index b599ad389c1..33abae156cc 100644 --- a/source/blender/draw/intern/draw_hair_private.h +++ b/source/blender/draw/intern/draw_hair_private.h @@ -21,8 +21,7 @@ * \ingroup draw */ -#ifndef __DRAW_HAIR_PRIVATE_H__ -#define __DRAW_HAIR_PRIVATE_H__ +#pragma once #define MAX_LAYER_NAME_CT 4 /* u0123456789, u, au, a0123456789 */ #define MAX_LAYER_NAME_LEN GPU_MAX_SAFE_ATTR_NAME + 2 @@ -92,5 +91,3 @@ bool hair_ensure_procedural_data(struct Object *object, struct ParticleHairCache **r_hair_cache, int subdiv, int thickness_res); - -#endif /* __DRAW_HAIR_PRIVATE_H__ */ diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h index f891d380ee3..e562d99097e 100644 --- a/source/blender/draw/intern/draw_instance_data.h +++ b/source/blender/draw/intern/draw_instance_data.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_INSTANCE_DATA_H__ -#define __DRAW_INSTANCE_DATA_H__ +#pragma once #include "BLI_compiler_attrs.h" #include "BLI_sys_types.h" @@ -55,5 +54,3 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist); void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist); void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist); void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist); - -#endif /* __DRAW_INSTANCE_DATA_H__ */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 3e42c4cdb23..d03b5107bb6 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -369,7 +369,7 @@ void DRW_engine_viewport_data_size_get( } /* WARNING: only use for custom pipeline. 99% of the time, you don't want to use this. */ -void DRW_render_viewport_size_set(int size[2]) +void DRW_render_viewport_size_set(const int size[2]) { DST.size[0] = size[0]; DST.size[1] = size[1]; @@ -792,9 +792,8 @@ DrawDataList *DRW_drawdatalist_from_id(ID *id) IdDdtTemplate *idt = (IdDdtTemplate *)id; return &idt->drawdata; } - else { - return NULL; - } + + return NULL; } DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type) @@ -1658,26 +1657,9 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph Scene *scene = DEG_get_evaluated_scene(depsgraph); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RenderEngineType *engine_type = engine->type; - RenderData *r = &scene->r; Render *render = engine->re; - /* Changing Context */ - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } + DRW_render_context_enable(render); /* Reset before using it. */ drw_state_prepare_clean_for_draw(&DST); @@ -1696,7 +1678,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph drw_context_state_init(); DST.viewport = GPU_viewport_create(); - const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100}; + const int size[2] = {engine->resolution_x, engine->resolution_y}; GPU_viewport_size_set(DST.viewport, size); drw_viewport_var_init(); @@ -1729,14 +1711,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph /* Restore Drawing area. */ GPU_framebuffer_restore(); - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } + DRW_render_context_disable(render); DST.buffer_finish_called = false; } @@ -1749,24 +1724,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) DrawEngineType *draw_engine_type = engine_type->draw_engine; Render *render = engine->re; - if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); - } - - void *re_gl_context = RE_gl_context_get(render); - void *re_gpu_context = NULL; - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_opengl_render_context_enable(re_gl_context); - /* We need to query gpu context after a gl context has been bound. */ - re_gpu_context = RE_gpu_context_get(render); - DRW_gpu_render_context_enable(re_gpu_context); - } - else { - DRW_opengl_context_enable(); - } - /* IMPORTANT: We don't support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ @@ -1793,9 +1750,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) ViewportEngineData *data = drw_viewport_engine_data_ensure(draw_engine_type); - /* set default viewport */ - glViewport(0, 0, size[0], size[1]); - /* Main rendering. */ rctf view_rect; rcti render_rect; @@ -1809,12 +1763,15 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Reset state before drawing */ DRW_state_reset(); + /* set default viewport */ + GPU_viewport(0, 0, size[0], size[1]); + /* Init render result. */ RenderResult *render_result = RE_engine_begin_result(engine, 0, 0, - (int)size[0], - (int)size[1], + size[0], + size[1], view_layer->name, /* RR_ALL_VIEWS */ NULL); @@ -1842,15 +1799,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) /* Reset state after drawing */ DRW_state_reset(); - - /* Changing Context */ - if (re_gl_context != NULL) { - DRW_gpu_render_context_disable(re_gpu_context); - DRW_opengl_render_context_disable(re_gl_context); - } - else { - DRW_opengl_context_disable(); - } } void DRW_render_object_iter( @@ -2004,13 +1952,21 @@ void DRW_render_instance_buffer_finish(void) drw_resource_buffer_finish(DST.vmempool); } +/* WARNING: Changing frame might free the ViewLayerEngineData */ +void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe) +{ + RE_engine_frame_set(engine, frame, subframe); + DST.draw_ctx.scene = DEG_get_evaluated_scene(depsgraph); + DST.draw_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph); +} + /** * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing). */ void DRW_draw_select_loop(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, - bool UNUSED(use_obedit_skip), + bool use_obedit_skip, bool draw_surface, bool UNUSED(use_nearest), const rcti *rect, @@ -2023,7 +1979,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); Object *obact = OBACT(view_layer); - Object *obedit = OBEDIT_FROM_OBACT(obact); + Object *obedit = use_obedit_skip ? NULL : OBEDIT_FROM_OBACT(obact); #ifndef USE_GPU_SELECT UNUSED_VARS(scene, view_layer, v3d, region, rect); #else @@ -2469,12 +2425,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons #endif } -/** See #DRW_shgroup_world_clip_planes_from_rv3d. */ -static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4]) -{ - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); -} - /** * Clears the Depth Buffer and draws only the specified object. */ @@ -2497,7 +2447,7 @@ void DRW_draw_depth_object( const float(*world_clip_planes)[4] = NULL; if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - ED_view3d_clipping_set(rv3d); + GPU_clip_distances(6); ED_view3d_clipping_local(rv3d, object->obmat); world_clip_planes = rv3d->clip_local; } @@ -2525,7 +2475,7 @@ void DRW_draw_depth_object( GPU_SHADER_CFG_DEFAULT; GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); if (world_clip_planes != NULL) { - draw_world_clip_planes_from_rv3d(batch, world_clip_planes); + GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]); } GPU_batch_draw(batch); @@ -2536,7 +2486,7 @@ void DRW_draw_depth_object( } if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - ED_view3d_clipping_disable(); + GPU_clip_distances(0); } GPU_matrix_set(rv3d->viewmat); @@ -2769,6 +2719,54 @@ void DRW_engines_free(void) DRW_opengl_context_disable(); } +void DRW_render_context_enable(Render *render) +{ + if (G.background && DST.gl_context == NULL) { + WM_init_opengl(); + } + + if (GPU_use_main_context_workaround()) { + GPU_context_main_lock(); + DRW_opengl_context_enable(); + return; + } + + void *re_gl_context = RE_gl_context_get(render); + + /* Changing Context */ + if (re_gl_context != NULL) { + DRW_opengl_render_context_enable(re_gl_context); + /* We need to query gpu context after a gl context has been bound. */ + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_enable(re_gpu_context); + } + else { + DRW_opengl_context_enable(); + } +} + +void DRW_render_context_disable(Render *render) +{ + if (GPU_use_main_context_workaround()) { + DRW_opengl_context_disable(); + GPU_context_main_unlock(); + return; + } + + void *re_gl_context = RE_gl_context_get(render); + + if (re_gl_context != NULL) { + void *re_gpu_context = NULL; + re_gpu_context = RE_gpu_context_get(render); + DRW_gpu_render_context_disable(re_gpu_context); + DRW_opengl_render_context_disable(re_gl_context); + } + else { + DRW_opengl_context_disable(); + } +} + /** \} */ /** \name Init/Exit (DRW_opengl_ctx) @@ -2855,7 +2853,7 @@ void DRW_opengl_context_disable_ex(bool restore) void DRW_opengl_context_enable(void) { if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); + WM_init_opengl(); } DRW_opengl_context_enable_ex(true); } @@ -2909,8 +2907,8 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context)) * switch to it just to submit the final frame, which has notable performance impact. * * We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to - * work from the main thread, which is tricky to get working too. The preferable solution would be - * using a separate thread for VR drawing where a single context can stay active. */ + * work from the main thread, which is tricky to get working too. The preferable solution would + * be using a separate thread for VR drawing where a single context can stay active. */ void *DRW_xr_opengl_context_get(void) { return DST.gl_context; diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 31a2dd7f0fe..92a01cbbe04 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -22,8 +22,7 @@ /* Private functions / structs of the draw manager */ -#ifndef __DRAW_MANAGER_H__ -#define __DRAW_MANAGER_H__ +#pragma once #include "DRW_engine.h" #include "DRW_render.h" @@ -380,6 +379,7 @@ typedef struct DRWViewUboStorage { float wininv[4][4]; float clipplanes[6][4]; + float viewvecs[2][4]; /* Should not be here. Not view dependent (only main view). */ float viewcamtexcofac[4]; } DRWViewUboStorage; @@ -583,7 +583,7 @@ void drw_state_set(DRWState state); void drw_debug_draw(void); void drw_debug_init(void); -eDRWCommandType command_type_get(uint64_t *command_type_bits, int index); +eDRWCommandType command_type_get(const uint64_t *command_type_bits, int index); void drw_batch_cache_validate(Object *ob); void drw_batch_cache_generate_requested(struct Object *ob); @@ -595,5 +595,3 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool); GPUBatch *drw_cache_procedural_points_get(void); GPUBatch *drw_cache_procedural_lines_get(void); GPUBatch *drw_cache_procedural_triangles_get(void); - -#endif /* __DRAW_MANAGER_H__ */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 3d83b918757..661a27c10b7 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -594,28 +594,26 @@ static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup, DRWResourceHandle handle = 0; return handle; } - else { - return drw_resource_handle_new(obmat, NULL); - } + + return drw_resource_handle_new(obmat, NULL); } - else { - if (DST.ob_handle == 0) { - DST.ob_handle = drw_resource_handle_new(obmat, ob); - DST.ob_state_obinfo_init = false; - } - if (shgroup->objectinfo) { - if (!DST.ob_state_obinfo_init) { - DST.ob_state_obinfo_init = true; - DRWObjectInfos *ob_infos = DRW_memblock_elem_from_handle(DST.vmempool->obinfos, - &DST.ob_handle); + if (DST.ob_handle == 0) { + DST.ob_handle = drw_resource_handle_new(obmat, ob); + DST.ob_state_obinfo_init = false; + } - drw_call_obinfos_init(ob_infos, ob); - } - } + if (shgroup->objectinfo) { + if (!DST.ob_state_obinfo_init) { + DST.ob_state_obinfo_init = true; + DRWObjectInfos *ob_infos = DRW_memblock_elem_from_handle(DST.vmempool->obinfos, + &DST.ob_handle); - return DST.ob_handle; + drw_call_obinfos_init(ob_infos, ob); + } } + + return DST.ob_handle; } static void command_type_set(uint64_t *command_type_bits, int index, eDRWCommandType type) @@ -623,7 +621,7 @@ static void command_type_set(uint64_t *command_type_bits, int index, eDRWCommand command_type_bits[index / 16] |= ((uint64_t)type) << ((index % 16) * 4); } -eDRWCommandType command_type_get(uint64_t *command_type_bits, int index) +eDRWCommandType command_type_get(const uint64_t *command_type_bits, int index) { return ((command_type_bits[index / 16] >> ((index % 16) * 4)) & 0xF); } @@ -793,10 +791,10 @@ void DRW_shgroup_call_range( drw_command_draw_range(shgroup, geom, handle, v_sta, v_ct); } +/* A count of 0 instance will use the default number of instance in the batch. */ void DRW_shgroup_call_instance_range( DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct) { - BLI_assert(i_ct > 0); BLI_assert(geom != NULL); if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, NULL, DST.select_id); @@ -1292,13 +1290,10 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass } static void drw_shgroup_material_texture(DRWShadingGroup *grp, - GPUMaterialTexture *tex, + GPUTexture *gputex, const char *name, - eGPUSamplerState state, - int textarget) + eGPUSamplerState state) { - GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget); - DRW_shgroup_uniform_texture_ex(grp, name, gputex, state); GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images); @@ -1314,15 +1309,16 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial LISTBASE_FOREACH (GPUMaterialTexture *, tex, &textures) { if (tex->ima) { /* Image */ + GPUTexture *gputex; if (tex->tiled_mapping_name[0]) { - drw_shgroup_material_texture( - grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY); - drw_shgroup_material_texture( - grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY); + gputex = BKE_image_get_gpu_tiles(tex->ima, tex->iuser, NULL); + drw_shgroup_material_texture(grp, gputex, tex->sampler_name, tex->sampler_state); + gputex = BKE_image_get_gpu_tilemap(tex->ima, tex->iuser, NULL); + drw_shgroup_material_texture(grp, gputex, tex->tiled_mapping_name, tex->sampler_state); } else { - drw_shgroup_material_texture( - grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D); + gputex = BKE_image_get_gpu_texture(tex->ima, tex->iuser, NULL); + drw_shgroup_material_texture(grp, gputex, tex->sampler_name, tex->sampler_state); } } else if (tex->colorband) { @@ -1656,6 +1652,52 @@ static void draw_view_matrix_state_update(DRWViewUboStorage *storage, mul_m4_m4m4(storage->persmat, winmat, viewmat); invert_m4_m4(storage->persinv, storage->persmat); + + const bool is_persp = (winmat[3][3] == 0.0f); + + /* Near clip distance. */ + storage->viewvecs[0][3] = (is_persp) ? -winmat[3][2] / (winmat[2][2] - 1.0f) : + -(winmat[3][2] + 1.0f) / winmat[2][2]; + + /* Far clip distance. */ + storage->viewvecs[1][3] = (is_persp) ? -winmat[3][2] / (winmat[2][2] + 1.0f) : + -(winmat[3][2] - 1.0f) / winmat[2][2]; + + /* view vectors for the corners of the view frustum. + * Can be used to recreate the world space position easily */ + float view_vecs[4][3] = { + {-1.0f, -1.0f, -1.0f}, + {1.0f, -1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, + {-1.0f, -1.0f, 1.0f}, + }; + + /* convert the view vectors to view space */ + for (int i = 0; i < 4; i++) { + mul_project_m4_v3(storage->wininv, view_vecs[i]); + /* normalized trick see: + * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ + if (is_persp) { + /* Divide XY by Z. */ + mul_v2_fl(view_vecs[i], 1.0f / view_vecs[i][2]); + } + } + + /** + * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and + * view_vecs[1] is the vector going from the near-bottom-left corner to + * the far-top-right corner. + * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner + * when Z = 1, and top-left corner if Z = 1. + * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) + * distance from the near plane to the far clip plane. + */ + copy_v3_v3(storage->viewvecs[0], view_vecs[0]); + + /* we need to store the differences */ + storage->viewvecs[1][0] = view_vecs[1][0] - view_vecs[0][0]; + storage->viewvecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; + storage->viewvecs[1][2] = view_vecs[3][2] - view_vecs[0][2]; } /* Create a view with culling. */ @@ -1860,9 +1902,8 @@ float DRW_view_near_distance_get(const DRWView *view) if (DRW_view_is_persp_get(view)) { return -projmat[3][2] / (projmat[2][2] - 1.0f); } - else { - return -(projmat[3][2] + 1.0f) / projmat[2][2]; - } + + return -(projmat[3][2] + 1.0f) / projmat[2][2]; } float DRW_view_far_distance_get(const DRWView *view) @@ -1873,9 +1914,8 @@ float DRW_view_far_distance_get(const DRWView *view) if (DRW_view_is_persp_get(view)) { return -projmat[3][2] / (projmat[2][2] + 1.0f); } - else { - return -(projmat[3][2] - 1.0f) / projmat[2][2]; - } + + return -(projmat[3][2] - 1.0f) / projmat[2][2]; } void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse) @@ -1982,18 +2022,16 @@ static int pass_shgroup_dist_sort(const void *a, const void *b) if (shgrp_a->z_sorting.distance < shgrp_b->z_sorting.distance) { return 1; } - else if (shgrp_a->z_sorting.distance > shgrp_b->z_sorting.distance) { + if (shgrp_a->z_sorting.distance > shgrp_b->z_sorting.distance) { return -1; } - else { - /* If distances are the same, keep original order. */ - if (shgrp_a->z_sorting.original_index > shgrp_b->z_sorting.original_index) { - return -1; - } - else { - return 0; - } + + /* If distances are the same, keep original order. */ + if (shgrp_a->z_sorting.original_index > shgrp_b->z_sorting.original_index) { + return -1; } + + return 0; } /* ------------------ Shading group sorting --------------------- */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 59b4e9af14e..4b63ea89e44 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -98,12 +98,7 @@ void drw_state_set(DRWState state) { int test; if ((test = CHANGED_TO(DRW_STATE_WRITE_DEPTH))) { - if (test == 1) { - glDepthMask(GL_TRUE); - } - else { - glDepthMask(GL_FALSE); - } + GPU_depth_mask(test == 1); } } @@ -142,10 +137,10 @@ void drw_state_set(DRWState state) int test; if ((test = CHANGED_TO(DRW_STATE_WRITE_COLOR))) { if (test == 1) { - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + GPU_color_mask(true, true, true, true); } else { - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + GPU_color_mask(false, false, false, false); } } } @@ -355,14 +350,10 @@ void drw_state_set(DRWState state) int test; if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) { if (test == 1) { - for (int i = 0; i < DST.view_active->clip_planes_len; i++) { - glEnable(GL_CLIP_DISTANCE0 + i); - } + GPU_clip_distances(DST.view_active->clip_planes_len); } else { - for (int i = 0; i < MAX_CLIP_PLANES; i++) { - glDisable(GL_CLIP_DISTANCE0 + i); - } + GPU_clip_distances(0); } } } @@ -455,6 +446,7 @@ void DRW_state_reset(void) DRW_state_reset_ex(DRW_STATE_DEFAULT); GPU_texture_unbind_all(); + GPU_uniformbuffer_unbind_all(); /* Should stay constant during the whole rendering. */ GPU_point_size(5); @@ -526,7 +518,7 @@ static bool draw_culling_box_test(const float (*frustum_planes)[4], const BoundB * Go to next plane. */ break; } - else if (v == 7) { + if (v == 7) { /* 8 points behind this plane. */ return false; } @@ -678,8 +670,7 @@ BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom) DST.batch = geom; - GPU_batch_program_set_no_use( - geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader)); + GPU_batch_set_shader_no_bind(geom, shgroup->shader); geom->program_in_use = true; /* XXX hacking #GPUBatch */ @@ -782,10 +773,11 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup) DRWPass *parent_pass = DRW_memblock_elem_from_handle(DST.vmempool->passes, &shgroup->pass_handle); - printf("Pass : %s, Shader : %s, Block : %s\n", + printf("Pass : %s, Shader : %s, Block : %s, Binding %d\n", parent_pass->name, shgroup->shader->name, - blockname); + blockname, + binding); } } # endif @@ -1003,9 +995,8 @@ static void draw_call_single_do(DRWShadingGroup *shgroup, draw_select_buffer(shgroup, state, batch, &handle); return; } - else { - GPU_select_load_id(state->select_id); - } + + GPU_select_load_id(state->select_id); } draw_geometry_execute(shgroup, @@ -1115,6 +1106,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) /* Unbinding can be costly. Skip in normal condition. */ if (G.debug & G_DEBUG_GPU) { GPU_texture_unbind_all(); + GPU_uniformbuffer_unbind_all(); } } GPU_shader_bind(shgroup->shader); diff --git a/source/blender/draw/intern/draw_manager_profiling.h b/source/blender/draw/intern/draw_manager_profiling.h index 3da6a4c8b1c..3842bdffaff 100644 --- a/source/blender/draw/intern/draw_manager_profiling.h +++ b/source/blender/draw/intern/draw_manager_profiling.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_MANAGER_PROFILING_H__ -#define __DRAW_MANAGER_PROFILING_H__ +#pragma once struct rcti; @@ -36,5 +35,3 @@ void DRW_stats_query_start(const char *name); void DRW_stats_query_end(void); void DRW_stats_draw(const rcti *rect); - -#endif /* __DRAW_MANAGER_PROFILING_H__ */ diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 6304b707cb9..1c260721efb 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -34,6 +34,7 @@ #include "DEG_depsgraph_query.h" +#include "GPU_extensions.h" #include "GPU_material.h" #include "GPU_shader.h" @@ -91,10 +92,13 @@ static void drw_deferred_shader_queue_free(ListBase *queue) } } -static void drw_deferred_shader_compilation_exec(void *custom_data, - short *stop, - short *do_update, - float *progress) +static void drw_deferred_shader_compilation_exec( + void *custom_data, + /* Cannot be const, this function implements wm_jobs_start_callback. + * NOLINTNEXTLINE: readability-non-const-parameter. */ + short *stop, + short *do_update, + float *progress) { DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; void *gl_context = comp->gl_context; @@ -103,6 +107,12 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, BLI_assert(gl_context != NULL); #endif + const bool use_main_context_workaround = GPU_use_main_context_workaround(); + if (use_main_context_workaround) { + BLI_assert(gl_context == DST.gl_context); + GPU_context_main_lock(); + } + WM_opengl_context_activate(gl_context); while (true) { @@ -151,6 +161,9 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, } WM_opengl_context_release(gl_context); + if (use_main_context_workaround) { + GPU_context_main_unlock(); + } } static void drw_deferred_shader_compilation_free(void *custom_data) @@ -193,6 +206,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) GPU_material_compile(mat); return; } + const bool use_main_context = GPU_use_main_context_workaround(); + const bool job_own_context = !use_main_context; DRWDeferredShader *dsh = MEM_callocN(sizeof(DRWDeferredShader), "Deferred Shader"); @@ -224,7 +239,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) if (old_comp->gl_context) { comp->gl_context = old_comp->gl_context; old_comp->own_context = false; - comp->own_context = true; + comp->own_context = job_own_context; } } @@ -232,9 +247,14 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred) /* Create only one context. */ if (comp->gl_context == NULL) { - comp->gl_context = WM_opengl_context_create(); - WM_opengl_context_activate(DST.gl_context); - comp->own_context = true; + if (use_main_context) { + comp->gl_context = DST.gl_context; + } + else { + comp->gl_context = WM_opengl_context_create(); + WM_opengl_context_activate(DST.gl_context); + } + comp->own_context = job_own_context; } WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free); @@ -325,6 +345,26 @@ GPUShader *DRW_shader_create_with_lib( return sh; } +GPUShader *DRW_shader_create_with_shaderlib(const char *vert, + const char *geom, + const char *frag, + const DRWShaderLibrary *lib, + const char *defines) +{ + GPUShader *sh; + char *vert_with_lib = DRW_shader_library_create_shader_string(lib, vert); + char *frag_with_lib = DRW_shader_library_create_shader_string(lib, frag); + char *geom_with_lib = (geom) ? DRW_shader_library_create_shader_string(lib, geom) : NULL; + + sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, __func__); + + MEM_SAFE_FREE(vert_with_lib); + MEM_SAFE_FREE(frag_with_lib); + MEM_SAFE_FREE(geom_with_lib); + + return sh; +} + GPUShader *DRW_shader_create_with_transform_feedback(const char *vert, const char *geom, const char *defines, @@ -349,6 +389,22 @@ GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines) datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__); } +GPUShader *DRW_shader_create_fullscreen_with_shaderlib(const char *frag, + const DRWShaderLibrary *lib, + const char *defines) +{ + + GPUShader *sh; + char *vert = datatoc_common_fullscreen_vert_glsl; + char *frag_with_lib = DRW_shader_library_create_shader_string(lib, frag); + + sh = GPU_shader_create(vert, frag_with_lib, NULL, NULL, defines, __func__); + + MEM_SAFE_FREE(frag_with_lib); + + return sh; +} + GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, const int options, @@ -391,7 +447,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, const char *geom, const char *frag_lib, const char *defines, - bool deferred) + bool deferred, + GPUMaterialEvalCallbackFn callback) { GPUMaterial *mat = NULL; if (DRW_state_is_image_render() || !deferred) { @@ -411,7 +468,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, geom, frag_lib, defines, - wo->id.name); + wo->id.name, + callback); } if (GPU_material_status(mat) == GPU_MAT_QUEUED) { @@ -431,7 +489,8 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, const char *geom, const char *frag_lib, const char *defines, - bool deferred) + bool deferred, + GPUMaterialEvalCallbackFn callback) { GPUMaterial *mat = NULL; if (DRW_state_is_image_render() || !deferred) { @@ -451,7 +510,8 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, geom, frag_lib, defines, - ma->id.name); + ma->id.name, + callback); } if (GPU_material_status(mat) == GPU_MAT_QUEUED) { @@ -502,7 +562,7 @@ void DRW_shader_library_free(DRWShaderLibrary *lib) MEM_SAFE_FREE(lib); } -static int drw_shader_library_search(DRWShaderLibrary *lib, const char *name) +static int drw_shader_library_search(const DRWShaderLibrary *lib, const char *name) { for (int i = 0; i < MAX_LIB; i++) { if (lib->libs[i]) { @@ -518,18 +578,28 @@ static int drw_shader_library_search(DRWShaderLibrary *lib, const char *name) } /* Return bitmap of dependencies. */ -static uint32_t drw_shader_dependencies_get(DRWShaderLibrary *lib, char *lib_code) +static uint32_t drw_shader_dependencies_get(const DRWShaderLibrary *lib, const char *lib_code) { /* Search dependencies. */ uint32_t deps = 0; - char *haystack = lib_code; + const char *haystack = lib_code; while ((haystack = strstr(haystack, "BLENDER_REQUIRE("))) { haystack += 16; int dep = drw_shader_library_search(lib, haystack); if (dep == -1) { + char dbg_name[32]; + int i = 0; + while ((haystack[0] != ')') && (i < 31)) { + dbg_name[i] = haystack[0]; + haystack++; + i++; + } + dbg_name[i + 1] = '\0'; + printf( - "Error: Dependency not found.\n" - "This might be due to bad lib ordering.\n"); + "Error: Dependency not found: %s\n" + "This might be due to bad lib ordering.\n", + dbg_name); BLI_assert(0); } else { @@ -562,7 +632,7 @@ void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const ch /* Return an allocN'ed string containing the shader code with its dependencies prepended. * Caller must free the string with MEM_freeN after use. */ -char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code) +char *DRW_shader_library_create_shader_string(const DRWShaderLibrary *lib, const char *shader_code) { uint32_t deps = drw_shader_dependencies_get(lib, shader_code); diff --git a/source/blender/draw/intern/draw_manager_text.c b/source/blender/draw/intern/draw_manager_text.c index f4601fe4f48..b3c4c97715e 100644 --- a/source/blender/draw/intern/draw_manager_text.c +++ b/source/blender/draw/intern/draw_manager_text.c @@ -38,6 +38,7 @@ #include "DNA_view3d_types.h" #include "GPU_matrix.h" +#include "GPU_state.h" #include "ED_screen.h" #include "ED_view3d.h" @@ -149,8 +150,9 @@ void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) if (tot) { int col_pack_prev = 0; + /* Disable clipping for text */ if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - ED_view3d_clipping_disable(); + GPU_clip_distances(0); } float original_proj[4][4]; @@ -188,7 +190,7 @@ void DRW_text_cache_draw(DRWTextStore *dt, ARegion *region, struct View3D *v3d) GPU_matrix_projection_set(original_proj); if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { - ED_view3d_clipping_enable(); + GPU_clip_distances(6); } } } diff --git a/source/blender/draw/intern/draw_manager_text.h b/source/blender/draw/intern/draw_manager_text.h index 66ef2379e38..f6dff335f1f 100644 --- a/source/blender/draw/intern/draw_manager_text.h +++ b/source/blender/draw/intern/draw_manager_text.h @@ -20,8 +20,7 @@ * \ingroup draw */ -#ifndef __DRAW_MANAGER_TEXT_H__ -#define __DRAW_MANAGER_TEXT_H__ +#pragma once struct ARegion; struct DRWTextStore; @@ -58,5 +57,3 @@ enum { /* draw_manager.c */ struct DRWTextStore *DRW_text_cache_ensure(void); - -#endif /* __DRAW_MANAGER_TEXT_H__ */ diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 77b0462303d..b94a6db3bad 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -61,6 +61,10 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format) void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags) { + if (tex == NULL) { + return; + } + if (flags & DRW_TEX_MIPMAP) { GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER); GPU_texture_bind(tex, 0); @@ -119,7 +123,6 @@ GPUTexture *DRW_texture_create_cube(int w, { GPUTexture *tex = GPU_texture_create_cube(w, format, fpixels, NULL); drw_texture_set_parameters(tex, flags); - return tex; } @@ -128,7 +131,6 @@ GPUTexture *DRW_texture_create_cube_array( { GPUTexture *tex = GPU_texture_create_cube_array(w, d, format, fpixels, NULL); drw_texture_set_parameters(tex, flags); - return tex; } diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c index 558d5441136..ee5561e1e38 100644 --- a/source/blender/draw/intern/draw_select_buffer.c +++ b/source/blender/draw/intern/draw_select_buffer.c @@ -84,14 +84,15 @@ uint *DRW_select_buffer_read(struct Depsgraph *depsgraph, GPUFrameBuffer *select_id_fb = DRW_engine_select_framebuffer_get(); GPU_framebuffer_bind(select_id_fb); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(rect_clamp.xmin, - rect_clamp.ymin, - BLI_rcti_size_x(&rect_clamp), - BLI_rcti_size_y(&rect_clamp), - GL_RED_INTEGER, - GL_UNSIGNED_INT, - r_buf); + GPU_framebuffer_read_color(select_id_fb, + rect_clamp.xmin, + rect_clamp.ymin, + BLI_rcti_size_x(&rect_clamp), + BLI_rcti_size_y(&rect_clamp), + 1, + 0, + GPU_DATA_UNSIGNED_INT, + r_buf); if (!BLI_rcti_compare(rect, &rect_clamp)) { /* The rect has been clamped so you need to realign the buffer and fill in the blanks */ @@ -394,7 +395,7 @@ uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, int center_x = width / 2; int center_y = height / 2; - /* Manhatten distance in keeping with other screen-based selection. */ + /* Manhattan distance in keeping with other screen-based selection. */ *dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y)); /* Indices start at 1 here. */ diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c index 06026d51faf..1458ff5341c 100644 --- a/source/blender/draw/intern/draw_view.c +++ b/source/blender/draw/intern/draw_view.c @@ -88,7 +88,7 @@ static bool is_cursor_visible(const DRWContextState *draw_ctx, Scene *scene, Vie /* no exception met? then don't draw cursor! */ return false; } - else if (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL) { + if (draw_ctx->object_mode & OB_MODE_WEIGHT_GPENCIL) { /* grease pencil hide always in some modes */ return false; } @@ -103,9 +103,9 @@ void DRW_draw_cursor(void) Scene *scene = draw_ctx->scene; ViewLayer *view_layer = draw_ctx->view_layer; - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); + GPU_color_mask(true, true, true, true); + GPU_depth_mask(false); + GPU_depth_test(false); if (is_cursor_visible(draw_ctx, scene, view_layer)) { int co[2]; @@ -184,8 +184,7 @@ void DRW_draw_cursor(void) GPUBatch *cursor_batch = DRW_cache_cursor_get(is_aligned); GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_FLAT_COLOR); - GPU_batch_program_set( - cursor_batch, GPU_shader_get_program(shader), GPU_shader_get_interface(shader)); + GPU_batch_set_shader(cursor_batch, shader); GPU_batch_draw(cursor_batch); @@ -217,5 +216,5 @@ void DRW_draw_gizmo_2d(void) WM_gizmomap_draw(region->gizmo_map, draw_ctx->evil_C, WM_GIZMOMAP_DRAWSTEP_2D); - glDepthMask(GL_TRUE); + GPU_depth_mask(true); } diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h index 04f7d2bbabb..a01a2d0dcce 100644 --- a/source/blender/draw/intern/draw_view.h +++ b/source/blender/draw/intern/draw_view.h @@ -20,13 +20,10 @@ * \ingroup draw */ -#ifndef __DRAW_VIEW_H__ -#define __DRAW_VIEW_H__ +#pragma once void DRW_draw_region_info(void); void DRW_clear_background(void); void DRW_draw_cursor(void); void DRW_draw_gizmo_3d(void); void DRW_draw_gizmo_2d(void); - -#endif /* __DRAW_VIEW_H__ */ diff --git a/source/blender/draw/intern/shaders/common_hair_lib.glsl b/source/blender/draw/intern/shaders/common_hair_lib.glsl index ffff631e34b..8684d82f228 100644 --- a/source/blender/draw/intern/shaders/common_hair_lib.glsl +++ b/source/blender/draw/intern/shaders/common_hair_lib.glsl @@ -95,7 +95,7 @@ void hair_get_interp_attrs( * For final drawing, the vertex index and the number of vertex per segment */ -#ifndef HAIR_PHASE_SUBDIV +#if !defined(HAIR_PHASE_SUBDIV) && defined(GPU_VERTEX_SHADER) int hair_get_strand_id(void) { return gl_VertexID / (hairStrandsRes * hairThicknessRes); @@ -206,4 +206,24 @@ vec3 hair_get_strand_pos(void) return texelFetch(hairPointBuffer, id).point_position; } +vec2 hair_get_barycentric(void) +{ + /* To match cycles without breaking into individual segment we encode if we need to invert + * the first component into the second component. We invert if the barycentricTexCo.y + * is NOT 0.0 or 1.0. */ + int id = hair_get_base_id(); + return vec2(float((id % 2) == 1), float(((id % 4) % 3) > 0)); +} + #endif + +/* To be fed the result of hair_get_barycentric from vertex shader. */ +vec2 hair_resolve_barycentric(vec2 vert_barycentric) +{ + if (fract(vert_barycentric.y) != 0.0) { + return vec2(vert_barycentric.x, 0.0); + } + else { + return vec2(1.0 - vert_barycentric.x, 0.0); + } +} diff --git a/source/blender/draw/intern/shaders/common_math_geom_lib.glsl b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl new file mode 100644 index 00000000000..643d7e7d942 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl @@ -0,0 +1,119 @@ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +/* ---------------------------------------------------------------------- */ +/** \name Math intersection & projection functions. + * \{ */ + +float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal) +{ + return dot(planenormal, planeorigin - lineorigin); +} + +float line_plane_intersect_dist(vec3 lineorigin, + vec3 linedirection, + vec3 planeorigin, + vec3 planenormal) +{ + return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection); +} + +float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane) +{ + vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz)); + vec3 h = lineorigin - plane_co; + return -dot(plane.xyz, h) / dot(plane.xyz, linedirection); +} + +vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) +{ + float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal); + return lineorigin + linedirection * dist; +} + +vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) +{ + float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); + return lineorigin + linedirection * dist; +} + +float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +{ + /* aligned plane normal */ + vec3 L = planeorigin - lineorigin; + float diskdist = length(L); + vec3 planenormal = -normalize(L); + return -diskdist / dot(planenormal, linedirection); +} + +vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +{ + float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin); + if (dist < 0) { + /* if intersection is behind we fake the intersection to be + * really far and (hopefully) not inside the radius of interest */ + dist = 1e16; + } + return lineorigin + linedirection * dist; +} + +float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) +{ + float a = dot(linedirection, linedirection); + float b = dot(linedirection, lineorigin); + float c = dot(lineorigin, lineorigin) - 1; + + float dist = 1e15; + float determinant = b * b - a * c; + if (determinant >= 0) { + dist = (sqrt(determinant) - b) / a; + } + + return dist; +} + +float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) +{ + /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ + */ + vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; + vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; + vec3 furthestplane = max(firstplane, secondplane); + + return min_v3(furthestplane); +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Other useful functions. + * \{ */ + +void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) +{ + vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + T = normalize(cross(UpVector, N)); + B = cross(N, T); +} + +/* ---- Encode / Decode Normal buffer data ---- */ +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec2 normal_encode(vec3 n, vec3 view) +{ + float p = sqrt(n.z * 8.0 + 8.0); + return n.xy / p + 0.5; +} + +vec3 normal_decode(vec2 enc, vec3 view) +{ + vec2 fenc = enc * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc * g; + n.z = 1 - f / 2; + return n; +} + +/** \} */ diff --git a/source/blender/draw/intern/shaders/common_math_lib.glsl b/source/blender/draw/intern/shaders/common_math_lib.glsl new file mode 100644 index 00000000000..a82e0b5a5e9 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_math_lib.glsl @@ -0,0 +1,130 @@ + +/* ---------------------------------------------------------------------- */ +/** \name Common Math Utilities + * \{ */ + +#define M_PI 3.14159265358979323846 /* pi */ +#define M_2PI 6.28318530717958647692 /* 2*pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_1_PI 0.318309886183790671538 /* 1/pi */ +#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */ +#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */ +#define FLT_MAX 3.402823e+38 + +vec3 mul(mat3 m, vec3 v) +{ + return m * v; +} +mat3 mul(mat3 m1, mat3 m2) +{ + return m1 * m2; +} +vec3 transform_direction(mat4 m, vec3 v) +{ + return mat3(m) * v; +} +vec3 transform_point(mat4 m, vec3 v) +{ + return (m * vec4(v, 1.0)).xyz; +} +vec3 project_point(mat4 m, vec3 v) +{ + vec4 tmp = m * vec4(v, 1.0); + return tmp.xyz / tmp.w; +} + +#define min3(a, b, c) min(a, min(b, c)) +#define min4(a, b, c, d) min(a, min3(b, c, d)) +#define min5(a, b, c, d, e) min(a, min4(b, c, d, e)) +#define min6(a, b, c, d, e, f) min(a, min5(b, c, d, e, f)) +#define min7(a, b, c, d, e, f, g) min(a, min6(b, c, d, e, f, g)) +#define min8(a, b, c, d, e, f, g, h) min(a, min7(b, c, d, e, f, g, h)) +#define min9(a, b, c, d, e, f, g, h, i) min(a, min8(b, c, d, e, f, g, h, i)) + +#define max3(a, b, c) max(a, max(b, c)) +#define max4(a, b, c, d) max(a, max3(b, c, d)) +#define max5(a, b, c, d, e) max(a, max4(b, c, d, e)) +#define max6(a, b, c, d, e, f) max(a, max5(b, c, d, e, f)) +#define max7(a, b, c, d, e, f, g) max(a, max6(b, c, d, e, f, g)) +#define max8(a, b, c, d, e, f, g, h) max(a, max7(b, c, d, e, f, g, h)) +#define max9(a, b, c, d, e, f, g, h, i) max(a, max8(b, c, d, e, f, g, h, i)) + +#define avg3(a, b, c) (a + b + c) * (1.0 / 3.0) +#define avg4(a, b, c, d) (a + b + c + d) * (1.0 / 4.0) +#define avg5(a, b, c, d, e) (a + b + c + d + e) * (1.0 / 5.0) +#define avg6(a, b, c, d, e, f) (a + b + c + d + e + f) * (1.0 / 6.0) +#define avg7(a, b, c, d, e, f, g) (a + b + c + d + e + f + g) * (1.0 / 7.0) +#define avg8(a, b, c, d, e, f, g, h) (a + b + c + d + e + f + g + h) * (1.0 / 8.0) +#define avg9(a, b, c, d, e, f, g, h, i) (a + b + c + d + e + f + g + h + i) * (1.0 / 9.0) + +/* clang-format off */ +float min_v2(vec2 v) { return min(v.x, v.y); } +float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); } +float min_v4(vec4 v) { return min(min(v.x, v.y), min(v.z, v.w)); } +float max_v2(vec2 v) { return max(v.x, v.y); } +float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); } +float max_v4(vec4 v) { return max(max(v.x, v.y), max(v.z, v.w)); } + +float sum(vec2 v) { return dot(vec2(1.0), v); } +float sum(vec3 v) { return dot(vec3(1.0), v); } +float sum(vec4 v) { return dot(vec4(1.0), v); } + +float avg(vec2 v) { return dot(vec2(1.0 / 2.0), v); } +float avg(vec3 v) { return dot(vec3(1.0 / 3.0), v); } +float avg(vec4 v) { return dot(vec4(1.0 / 4.0), v); } +/* clang-format on */ + +#define saturate(a) clamp(a, 0.0, 1.0) + +float distance_squared(vec2 a, vec2 b) +{ + a -= b; + return dot(a, a); +} + +float distance_squared(vec3 a, vec3 b) +{ + a -= b; + return dot(a, a); +} + +float len_squared(vec3 a) +{ + return dot(a, a); +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Fast Math + * \{ */ + +/* [Drobot2014a] Low Level Optimizations for GCN */ +float fast_sqrt(float v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +vec2 fast_sqrt(vec2 v) +{ + return intBitsToFloat(0x1fbd1df5 + (floatBitsToInt(v) >> 1)); +} + +/* [Eberly2014] GPGPU Programming for Games and Science */ +float fast_acos(float v) +{ + float res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + return (v >= 0) ? res : M_PI - res; +} + +vec2 fast_acos(vec2 v) +{ + vec2 res = -0.156583 * abs(v) + M_PI_2; + res *= fast_sqrt(1.0 - abs(v)); + v.x = (v.x >= 0) ? res.x : M_PI - res.x; + v.y = (v.y >= 0) ? res.y : M_PI - res.y; + return v; +} + +/** \} */ diff --git a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl new file mode 100644 index 00000000000..625e8bb1ff8 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl @@ -0,0 +1,39 @@ + +/* NOTE: To be used with UNIFORM_RESOURCE_ID and INSTANCED_ATTR as define. */ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec4 pos; /* Position and radius. */ + +/* ---- Instanced attribs ---- */ + +in vec3 pos_inst; +in vec3 nor; + +mat3 pointcloud_get_facing_matrix(vec3 p) +{ + mat3 facing_mat; + facing_mat[2] = normalize(ViewMatrixInverse[3].xyz - p); + facing_mat[1] = normalize(cross(ViewMatrixInverse[0].xyz, facing_mat[2])); + facing_mat[0] = cross(facing_mat[1], facing_mat[2]); + return facing_mat; +} + +/* Return world position and normal. */ +void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor) +{ + vec3 p = point_object_to_world(pos.xyz); + mat3 facing_mat = pointcloud_get_facing_matrix(p); + + float radius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0)); + /* TODO(fclem) remove multiplication here. Here only for keeping the size correct for now. */ + radius *= 0.01; + outpos = p + (facing_mat * pos_inst) * radius; + outnor = facing_mat * nor; +} + +vec3 pointcloud_get_pos(void) +{ + vec3 outpos, outnor; + pointcloud_get_pos_and_nor(outpos, outnor); + return outpos; +} diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 1054f4d11c9..a55d2cd8c1a 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -14,10 +14,24 @@ layout(std140) uniform viewBlock vec4 clipPlanes[6]; + /* View frustum corners [NDC(-1.0, -1.0, -1.0) & NDC(1.0, 1.0, 1.0)]. + * Fourth components are near and far values. */ + vec4 ViewVecs[2]; + /* TODO move it elsewhere. */ vec4 CameraTexCoFactors; }; +#define ViewNear (ViewVecs[0].w) +#define ViewFar (ViewVecs[1].w) + +#define cameraForward ViewMatrixInverse[2].xyz +#define cameraPos ViewMatrixInverse[3].xyz +#define cameraVec \ + ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) +#define viewCameraVec \ + ((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0)) + #ifdef world_clip_planes_calc_clip_distance # undef world_clip_planes_calc_clip_distance # define world_clip_planes_calc_clip_distance(p) \ @@ -100,10 +114,13 @@ uniform int resourceId; /* Use this to declare and pass the value if * the fragment shader uses the resource_id. */ -# define RESOURCE_ID_VARYING flat out int resourceIDFrag; -# define RESOURCE_ID_VARYING_GEOM flat out int resourceIDGeom; -# define PASS_RESOURCE_ID resourceIDFrag = resource_id; -# define PASS_RESOURCE_ID_GEOM resourceIDGeom = resource_id; +# ifdef USE_GEOMETRY_SHADER +# define RESOURCE_ID_VARYING flat out int resourceIDGeom; +# define PASS_RESOURCE_ID resourceIDGeom = resource_id; +# else +# define RESOURCE_ID_VARYING flat out int resourceIDFrag; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# endif #endif /* If used in a fragment / geometry shader, we pass @@ -114,7 +131,7 @@ uniform int resourceId; flat in int resourceIDGeom[]; # define resource_id resourceIDGeom -# define PASS_RESOURCE_ID(i) resourceIDFrag = resource_id[i]; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0]; #endif #ifdef GPU_FRAGMENT_SHADER @@ -167,10 +184,14 @@ uniform mat4 ModelMatrixInverse; * Note: This is only valid because we are only using the mat3 of the ViewMatrixInverse. * ViewMatrix * transpose(ModelMatrixInverse) **/ -#define normal_object_to_view(n) (mat3(ViewMatrix) * (transpose(mat3(ModelMatrixInverse)) * n)) -#define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n) -#define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n) +#define NormalMatrix transpose(mat3(ModelMatrixInverse)) +#define NormalMatrixInverse transpose(mat3(ModelMatrix)) + +#define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n)) +#define normal_object_to_world(n) (NormalMatrix * n) +#define normal_world_to_object(n) (NormalMatrixInverse * n) #define normal_world_to_view(n) (mat3(ViewMatrix) * n) +#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) #define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)) #define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) @@ -194,3 +215,78 @@ uniform mat4 ModelMatrixInverse; #define DRW_BASE_FROM_DUPLI (1 << 2) #define DRW_BASE_FROM_SET (1 << 3) #define DRW_BASE_ACTIVE (1 << 4) + +/* ---- Opengl Depth conversion ---- */ + +float linear_depth(bool is_persp, float z, float zf, float zn) +{ + if (is_persp) { + return (zn * zf) / (z * (zn - zf) + zf); + } + else { + return (z * 2.0 - 1.0) * zf; + } +} + +float buffer_depth(bool is_persp, float z, float zf, float zn) +{ + if (is_persp) { + return (zf * (zn - z)) / (z * (zn - zf)); + } + else { + return (z / (zf * 2.0)) + 0.5; + } +} + +float get_view_z_from_depth(float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + float d = 2.0 * depth - 1.0; + return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); + } + else { + return ViewVecs[0].z + depth * ViewVecs[1].z; + } +} + +float get_depth_from_view_z(float z) +{ + if (ProjectionMatrix[3][3] == 0.0) { + float d = (-ProjectionMatrix[3][2] / z) - ProjectionMatrix[2][2]; + return d * 0.5 + 0.5; + } + else { + return (z - ViewVecs[0].z) / ViewVecs[1].z; + } +} + +vec2 get_uvs_from_view(vec3 view) +{ + vec4 ndc = ProjectionMatrix * vec4(view, 1.0); + return (ndc.xy / ndc.w) * 0.5 + 0.5; +} + +vec3 get_view_space_from_depth(vec2 uvcoords, float depth) +{ + if (ProjectionMatrix[3][3] == 0.0) { + return vec3(ViewVecs[0].xy + uvcoords * ViewVecs[1].xy, 1.0) * get_view_z_from_depth(depth); + } + else { + return ViewVecs[0].xyz + vec3(uvcoords, depth) * ViewVecs[1].xyz; + } +} + +vec3 get_world_space_from_depth(vec2 uvcoords, float depth) +{ + return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz; +} + +vec3 get_view_vector_from_screen_uv(vec2 uv) +{ + if (ProjectionMatrix[3][3] == 0.0) { + return normalize(vec3(ViewVecs[0].xy + uv * ViewVecs[1].xy, 1.0)); + } + else { + return vec3(0.0, 0.0, 1.0); + } +} diff --git a/source/blender/draw/intern/smaa_textures.h b/source/blender/draw/intern/smaa_textures.h index 43b29340cac..7556f3a1952 100644 --- a/source/blender/draw/intern/smaa_textures.h +++ b/source/blender/draw/intern/smaa_textures.h @@ -26,8 +26,7 @@ * SOFTWARE. */ -#ifndef __SMAA_TEXTURES_H__ -#define __SMAA_TEXTURES_H__ +#pragma once #define AREATEX_WIDTH 160 #define AREATEX_HEIGHT 560 @@ -15083,4 +15082,3 @@ static const unsigned char searchTexBytes[] = { /* clang-format off */ -#endif /* __SMAA_TEXTURES_H__ */ |