Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2018-01-30 00:53:32 +0300
committerJulian Eisel <eiseljulian@gmail.com>2018-01-30 01:24:11 +0300
commit3f0871dfcfbb1dda15c176dba92d36639305385a (patch)
treede7ffeeef7a99fc6103d413ebfa564596811087d /source/blender/draw
parent53d94dafc474380651fc529f9c03f84ce7142b13 (diff)
parent1fe2b4bf608b22ae4513051e01cf45e5012c2409 (diff)
Merge branch 'blender2.8' into topbar
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt7
-rw-r--r--source/blender/draw/DRW_engine.h21
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c1
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c103
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c106
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c25
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c107
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c217
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c334
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c393
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut.h515
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c371
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c82
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c115
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h231
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c278
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c181
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c31
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c119
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c232
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl164
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl26
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl123
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl55
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl49
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl410
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl13
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl43
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl48
-rw-r--r--source/blender/draw/engines/eevee/shaders/ltc_lib.glsl426
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/ssr_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl37
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl22
-rw-r--r--source/blender/draw/engines/external/external_engine.c1
-rw-r--r--source/blender/draw/intern/DRW_render.h39
-rw-r--r--source/blender/draw/intern/draw_armature.c96
-rw-r--r--source/blender/draw/intern/draw_cache.c257
-rw-r--r--source/blender/draw/intern/draw_cache.h8
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h14
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c156
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c338
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c9
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c7
-rw-r--r--source/blender/draw/intern/draw_common.c35
-rw-r--r--source/blender/draw/intern/draw_common.h22
-rw-r--r--source/blender/draw/intern/draw_instance_data.c226
-rw-r--r--source/blender/draw/intern/draw_instance_data.h41
-rw-r--r--source/blender/draw/intern/draw_manager.c716
-rw-r--r--source/blender/draw/intern/draw_view.c34
-rw-r--r--source/blender/draw/intern/draw_view.h5
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c1
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c37
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c1
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c1
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c1
-rw-r--r--source/blender/draw/modes/edit_surface_mode.c1
-rw-r--r--source/blender/draw/modes/edit_text_mode.c1
-rw-r--r--source/blender/draw/modes/object_mode.c106
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c1
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c1
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c1
-rw-r--r--source/blender/draw/modes/particle_mode.c1
-rw-r--r--source/blender/draw/modes/pose_mode.c1
-rw-r--r--source/blender/draw/modes/sculpt_mode.c1
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl14
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl79
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl40
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl13
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl66
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl14
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_frag.glsl9
86 files changed, 4890 insertions, 2488 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 8339b6b8720..1bff4b875ce 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -62,6 +62,7 @@ set(SRC
intern/draw_cache_impl_metaball.c
intern/draw_cache_impl_particles.c
intern/draw_common.c
+ intern/draw_instance_data.c
intern/draw_manager.c
intern/draw_manager_text.c
intern/draw_manager_profiling.c
@@ -93,6 +94,7 @@ set(SRC
engines/eevee/eevee_materials.c
engines/eevee/eevee_motion_blur.c
engines/eevee/eevee_occlusion.c
+ engines/eevee/eevee_render.c
engines/eevee/eevee_screen_raytrace.c
engines/eevee/eevee_subsurface.c
engines/eevee/eevee_temporal_sampling.c
@@ -104,6 +106,7 @@ set(SRC
intern/draw_cache.h
intern/draw_cache_impl.h
intern/draw_common.h
+ intern/draw_instance_data.h
intern/draw_manager_text.h
intern/draw_manager_profiling.h
intern/draw_view.h
@@ -133,6 +136,7 @@ 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/common_uniforms_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lamps_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)
@@ -181,6 +185,7 @@ 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/ltc_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/volumetric_geom.glsl SRC)
@@ -202,6 +207,7 @@ data_to_c_simple(modes/shaders/edit_mesh_overlay_mix_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_mesh_overlay_facefill_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_curve_overlay_handle_geom.glsl SRC)
data_to_c_simple(modes/shaders/edit_curve_overlay_loosevert_vert.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_frag.glsl SRC)
data_to_c_simple(modes/shaders/edit_lattice_overlay_loosevert_vert.glsl SRC)
@@ -216,7 +222,6 @@ data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_lightprobe_grid_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_prim_vert.glsl SRC)
-data_to_c_simple(modes/shaders/object_particle_prim_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_particle_dot_frag.glsl SRC)
data_to_c_simple(modes/shaders/paint_texture_frag.glsl SRC)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index ba0f8681f10..c4946e2a4b8 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -30,6 +30,7 @@ struct ARegion;
struct CollectionEngineSettings;
struct Depsgraph;
struct DRWPass;
+struct DRWInstanceDataList;
struct Main;
struct Material;
struct Scene;
@@ -44,6 +45,8 @@ struct ViewportEngineData;
struct View3D;
struct rcti;
struct GPUOffScreen;
+struct GPUViewport;
+struct RenderEngine;
struct RenderEngineType;
struct WorkSpace;
@@ -65,6 +68,7 @@ typedef struct DefaultTextureList {
void DRW_engines_register(void);
void DRW_engines_free(void);
+bool DRW_engine_render_support(struct DrawEngineType *draw_engine_type);
void DRW_engine_register(struct DrawEngineType *draw_engine_type);
void DRW_engine_viewport_data_size_get(
const void *engine_type,
@@ -72,6 +76,7 @@ void DRW_engine_viewport_data_size_get(
typedef struct DRWUpdateContext {
struct Main *bmain;
+ struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
struct ARegion *ar;
@@ -84,28 +89,32 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, struct ID *id);
void DRW_draw_view(const struct bContext *C);
void DRW_draw_render_loop_ex(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
struct RenderEngineType *engine_type,
struct ARegion *ar, struct View3D *v3d,
const struct bContext *evil_C);
void DRW_draw_render_loop(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d);
void DRW_draw_render_loop_offscreen(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
struct RenderEngineType *engine_type,
struct ARegion *ar, struct View3D *v3d,
- struct GPUOffScreen *ofs);
+ const bool draw_background,
+ struct GPUOffScreen *ofs,
+ struct GPUViewport *viewport);
void DRW_draw_select_loop(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d,
bool use_obedit_skip, bool use_nearest, const struct rcti *rect);
void DRW_draw_depth_loop(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
struct ARegion *ar, struct View3D *v3d);
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);
+struct DRWInstanceDataList *DRW_instance_data_list_create(void);
+void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist);
/* Mode engines initialization */
void OBJECT_collection_settings_create(struct IDProperty *properties);
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 10dfe7b5996..31a431e3001 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -264,6 +264,7 @@ DrawEngineType draw_engine_basic_type = {
&basic_draw_scene,
NULL,
NULL,
+ NULL,
};
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index 01f89ae6b1c..d2bf164efdc 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -183,6 +183,7 @@ typedef struct CLAY_PrivateData {
DRWShadingGroup *depth_shgrp_cull;
DRWShadingGroup *depth_shgrp_cull_select;
DRWShadingGroup *depth_shgrp_cull_active;
+ bool enable_ao;
} CLAY_PrivateData; /* Transient data */
/* Functions */
@@ -317,7 +318,7 @@ static struct GPUTexture *create_jitter_texture(int num_samples)
jitter[i][2] = bn * num_samples_inv;
}
- UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx);
+ UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral);
return DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
}
@@ -607,7 +608,7 @@ static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material *
return id;
}
-static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo)
+static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_needs_ao)
{
IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
@@ -622,6 +623,12 @@ static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo)
float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+ if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) &&
+ (ssao_distance > 0.0))
+ {
+ *r_needs_ao = true;
+ }
+
memset(r_ubo, 0x0, sizeof(*r_ubo));
r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
@@ -667,7 +674,7 @@ static DRWShadingGroup *CLAY_object_shgrp_get(
DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps;
CLAY_UBO_Material mat_ubo_test;
- ubo_mat_from_object(ob, &mat_ubo_test);
+ ubo_mat_from_object(ob, &mat_ubo_test, &stl->g_data->enable_ao);
int id = mat_in_ubo(stl->storage, &mat_ubo_test);
@@ -712,6 +719,9 @@ static void clay_cache_init(void *vedata)
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
}
+ /* Disable AO unless a material needs it. */
+ stl->g_data->enable_ao = false;
+
/* Depth Pass */
{
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
@@ -746,12 +756,45 @@ static void clay_cache_init(void *vedata)
}
}
+static void clay_cache_populate_particles(void *vedata, Object *ob)
+{
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+
+ if (ob != obedit) {
+ for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
+ draw_as = PART_DRAW_DOT;
+ }
+
+ static float mat[4][4];
+ unit_m4(mat);
+
+ if (draw_as == PART_DRAW_PATH) {
+ struct Gwn_Batch *geom = DRW_cache_particles_get_hair(psys, NULL);
+ DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
+ DRW_shgroup_call_add(hair_shgrp, geom, mat);
+ }
+ }
+ }
+ }
+}
+
static void clay_cache_populate(void *vedata, Object *ob)
{
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- DRWShadingGroup *clay_shgrp, *hair_shgrp;
+ DRWShadingGroup *clay_shgrp;
if (!DRW_object_is_renderable(ob))
return;
@@ -764,6 +807,15 @@ static void clay_cache_populate(void *vedata, Object *ob)
}
}
+ /* Handle particles first in case the emitter itself shouldn't be rendered. */
+ if (ob->type == OB_MESH) {
+ clay_cache_populate_particles(vedata, ob);
+ }
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
@@ -797,33 +849,6 @@ static void clay_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
}
}
-
- if (ob->type == OB_MESH) {
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
-
- if (ob != obedit) {
- for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, false)) {
- ParticleSettings *part = psys->part;
- int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
-
- if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
- draw_as = PART_DRAW_DOT;
- }
-
- static float mat[4][4];
- unit_m4(mat);
-
- if (draw_as == PART_DRAW_PATH) {
- geom = DRW_cache_particles_get_hair(psys, NULL);
- hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
- DRW_shgroup_call_add(hair_shgrp, geom, mat);
- }
- }
- }
- }
- }
}
static void clay_cache_finish(void *vedata)
@@ -836,18 +861,25 @@ static void clay_cache_finish(void *vedata)
static void clay_draw_scene(void *vedata)
{
-
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
/* Pass 1 : Depth pre-pass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ if (stl->g_data->enable_ao) {
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ }
+ else {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ DRW_pass_state_set(psl->clay_pass, state);
+ DRW_pass_state_set(psl->clay_pass_flat, state);
+ }
/* Pass 2 : Duplicate depth */
/* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
- if (DRW_state_is_fbo()) {
+ if (DRW_state_is_fbo() && stl->g_data->enable_ao) {
/* attach temp textures */
DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0);
@@ -917,6 +949,7 @@ DrawEngineType draw_engine_clay_type = {
&clay_draw_scene,
NULL,
NULL,
+ NULL,
};
RenderEngineType DRW_engine_viewport_clay_type = {
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index d5582a498a4..c6e5f645f10 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -45,13 +45,17 @@ static void eevee_view_layer_data_free(void *storage)
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
- BLI_freelistN(&sldata->shadow_casters);
+ MEM_SAFE_FREE(sldata->shcasters_buffers[0].shadow_casters);
+ MEM_SAFE_FREE(sldata->shcasters_buffers[0].flags);
+ MEM_SAFE_FREE(sldata->shcasters_buffers[1].shadow_casters);
+ MEM_SAFE_FREE(sldata->shcasters_buffers[1].flags);
/* Probes */
MEM_SAFE_FREE(sldata->probes);
DRW_UBO_FREE_SAFE(sldata->probe_ubo);
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
+ DRW_UBO_FREE_SAFE(sldata->common_ubo);
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
@@ -59,24 +63,6 @@ static void eevee_view_layer_data_free(void *storage)
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool);
DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt);
-
- /* Volumetrics */
- MEM_SAFE_FREE(sldata->volumetrics);
-}
-
-static void eevee_lamp_data_free(void *storage)
-{
- EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)storage;
-
- MEM_SAFE_FREE(led->storage);
- BLI_freelistN(&led->shadow_caster_list);
-}
-
-static void eevee_lightprobe_data_free(void *storage)
-{
- EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)storage;
-
- BLI_freelistN(&ped->captured_object_list);
}
EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
@@ -97,59 +83,95 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void)
return *sldata;
}
+/* Object data. */
+
+static void eevee_object_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)engine_data;
+ eevee_data->shadow_caster_id = -1;
+}
+
EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
{
+ if (ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)) {
+ return NULL;
+ }
return (EEVEE_ObjectEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob)
{
- EEVEE_ObjectEngineData **oedata = (EEVEE_ObjectEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, NULL);
+ BLI_assert(!ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP));
+ return (EEVEE_ObjectEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_ObjectEngineData),
+ eevee_object_data_init,
+ NULL);
+}
- if (*oedata == NULL) {
- *oedata = MEM_callocN(sizeof(**oedata), "EEVEE_ObjectEngineData");
- }
+/* Light probe data. */
+
+static void eevee_lightprobe_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data;
+ ped->need_full_update = true;
+ ped->need_update = true;
+}
- return *oedata;
+static void eevee_lightprobe_data_free(ObjectEngineData *engine_data)
+{
+ EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data;
+
+ BLI_freelistN(&ped->captured_object_list);
}
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob)
{
+ if (ob->type != OB_LIGHTPROBE) {
+ return NULL;
+ }
return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob)
{
- EEVEE_LightProbeEngineData **pedata = (EEVEE_LightProbeEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, &eevee_lightprobe_data_free);
+ BLI_assert(ob->type == OB_LIGHTPROBE);
+ return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_LightProbeEngineData),
+ &eevee_lightprobe_data_init,
+ &eevee_lightprobe_data_free);
+}
- if (*pedata == NULL) {
- *pedata = MEM_callocN(sizeof(**pedata), "EEVEE_LightProbeEngineData");
- (*pedata)->need_full_update = true;
- (*pedata)->need_update = true;
- }
+/* Lamp data. */
- return *pedata;
+static void eevee_lamp_data_init(ObjectEngineData *engine_data)
+{
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)engine_data;
+ led->need_update = true;
+ led->prev_cube_shadow_id = -1;
}
EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob)
{
+ if (ob->type != OB_LAMP) {
+ return NULL;
+ }
return (EEVEE_LampEngineData *)DRW_object_engine_data_get(
ob, &draw_engine_eevee_type);
}
EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob)
{
- EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_ensure(
- ob, &draw_engine_eevee_type, &eevee_lamp_data_free);
-
- if (*ledata == NULL) {
- *ledata = MEM_callocN(sizeof(**ledata), "EEVEE_LampEngineData");
- (*ledata)->need_update = true;
- }
-
- return *ledata;
+ BLI_assert(ob->type == OB_LAMP);
+ return (EEVEE_LampEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_eevee_type,
+ sizeof(EEVEE_LampEngineData),
+ eevee_lamp_data_init,
+ NULL);
}
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 ef7e6412fc4..f5fc79aba4f 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -45,6 +45,7 @@
#include "BKE_screen.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "eevee_private.h"
#include "GPU_extensions.h"
@@ -74,7 +75,7 @@ static void eevee_create_shader_depth_of_field(void)
datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n");
}
-int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -87,16 +88,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
if (BKE_collection_engine_property_value_get_bool(props, "dof_enable")) {
Scene *scene = draw_ctx->scene;
- View3D *v3d = draw_ctx->v3d;
RegionView3D *rv3d = draw_ctx->rv3d;
if (!e_data.dof_downsample_sh) {
eevee_create_shader_depth_of_field();
}
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (camera) {
const float *viewport_size = DRW_viewport_size_get();
- Camera *cam = (Camera *)v3d->camera->data;
+ Camera *cam = (Camera *)camera->data;
/* Retreive Near and Far distance */
effects->dof_near_far[0] = -cam->clipsta;
@@ -125,12 +125,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
&fbl->dof_down_fb, &draw_engine_eevee_type,
buffer_size[0], buffer_size[1], tex_down, 3);
- DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
+ /* Go full 32bits for rendering and reduce the color artifacts. */
+ DRWTextureFormat fb_format = DRW_state_is_image_render() ? DRW_TEX_RGBA_32 : DRW_TEX_RGBA_16;
+
+ DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, fb_format, DRW_TEX_FILTER};
DRW_framebuffer_init(
&fbl->dof_scatter_far_fb, &draw_engine_eevee_type,
buffer_size[0], buffer_size[1], &tex_scatter_far, 1);
- DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER};
+ DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, fb_format, DRW_TEX_FILTER};
DRW_framebuffer_init(
&fbl->dof_scatter_near_fb, &draw_engine_eevee_type,
buffer_size[0], buffer_size[1], &tex_scatter_near, 1);
@@ -142,7 +145,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
float rotation = cam->gpu_dof.rotation;
float ratio = 1.0f / cam->gpu_dof.ratio;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- float focus_dist = BKE_camera_object_dof_distance(v3d->camera);
+ float focus_dist = BKE_camera_object_dof_distance(camera);
float focal_len = cam->lens;
UNUSED_VARS(rotation, ratio);
@@ -158,9 +161,13 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
float focal_len_scaled = scale_camera * focal_len;
float sensor_scaled = scale_camera * sensor;
+ if (rv3d != NULL) {
+ sensor_scaled *= rv3d->viewcamtexcofac[0];
+ }
+
effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
effects->dof_params[1] = -focus_dist;
- effects->dof_params[2] = viewport_size[0] / (rv3d->viewcamtexcofac[0] * sensor_scaled);
+ effects->dof_params[2] = viewport_size[0] / sensor_scaled;
effects->dof_bokeh[0] = blades;
effects->dof_bokeh[1] = rotation;
effects->dof_bokeh[2] = ratio;
@@ -213,7 +220,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
DRW_shgroup_call_add(grp, quad, NULL);
- psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL);
/* This create an empty batch of N triangles to be positioned
* by the vertex shader 0.4ms against 6ms with instancing */
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 703369a86ee..c1ac085230e 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -27,10 +27,9 @@
#include "DRW_render.h"
-#include "BKE_global.h" /* for G.debug_value */
-
#include "eevee_private.h"
#include "GPU_texture.h"
+#include "GPU_extensions.h"
static struct {
/* Downsample Depth */
@@ -77,36 +76,31 @@ static void eevee_create_shader_downsample(void)
"#define MAX_PASS\n");
e_data.minz_downdepth_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
- "#define MIN_PASS\n"
- "#define INPUT_DEPTH\n");
+ "#define MIN_PASS\n");
e_data.maxz_downdepth_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
- "#define MAX_PASS\n"
- "#define INPUT_DEPTH\n");
+ "#define MAX_PASS\n");
e_data.minz_downdepth_layer_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
"#define MIN_PASS\n"
- "#define LAYERED\n"
- "#define INPUT_DEPTH\n");
+ "#define LAYERED\n");
e_data.maxz_downdepth_layer_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
"#define MAX_PASS\n"
- "#define LAYERED\n"
- "#define INPUT_DEPTH\n");
+ "#define LAYERED\n");
e_data.minz_copydepth_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
"#define MIN_PASS\n"
- "#define INPUT_DEPTH\n"
"#define COPY_DEPTH\n");
e_data.maxz_copydepth_sh = DRW_shader_create_fullscreen(
datatoc_effect_minmaxz_frag_glsl,
"#define MAX_PASS\n"
- "#define INPUT_DEPTH\n"
"#define COPY_DEPTH\n");
}
-void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
@@ -126,9 +120,9 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
effects = stl->effects;
effects->enabled_effects = 0;
- effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata);
- effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata);
+ effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata);
@@ -154,10 +148,17 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* MinMax Pyramid
*/
DRWFboTexture texmax = {&txl->maxzbuffer, DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP};
+
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ /* Intel gpu seems to have problem rendering to only depth format */
+ texmax.format = DRW_TEX_R_32;
+ }
+
DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type,
- (int)viewport_size[0] / 2, (int)viewport_size[1] / 2,
+ max_ii((int)viewport_size[0] / 2, 1), max_ii((int)viewport_size[1] / 2, 1),
&texmax, 1);
+
/**
* Compute Mipmap texel alignement.
*/
@@ -167,8 +168,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
mip_size[0] = floorf(fmaxf(1.0f, mip_size[0] / 2.0f));
mip_size[1] = floorf(fmaxf(1.0f, mip_size[1] / 2.0f));
}
- stl->g_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0])))));
- stl->g_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1])))));
+ common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0])))));
+ common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1])))));
}
@@ -207,12 +208,17 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
- EEVEE_EffectsInfo *effects = stl->effects;
+ int downsample_write = DRW_STATE_WRITE_DEPTH;
+
+ /* Intel gpu seems to have problem rendering to only depth format.
+ * Use color texture instead. */
+ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) {
+ downsample_write = DRW_STATE_WRITE_COLOR;
+ }
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
@@ -220,7 +226,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
DRW_shgroup_call_add(grp, quad, NULL);
}
@@ -239,39 +245,39 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
DRWShadingGroup *grp;
#if 0 /* Not used for now */
- psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &stl->g_data->minzbuffer);
DRW_shgroup_call_add(grp, quad, NULL);
#endif
- psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &txl->maxzbuffer);
DRW_shgroup_call_add(grp, quad, NULL);
/* Copy depth buffer to halfres top level of HiZ */
#if 0 /* Not used for now */
- psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.minz_downdepth_sh, psl->minz_downdepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
#endif
- psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
#if 0 /* Not used for now */
- psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.minz_downdepth_layer_sh, psl->minz_downdepth_layer_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
DRW_shgroup_call_add(grp, quad, NULL);
#endif
- psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
@@ -279,13 +285,13 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
/* Copy depth buffer to halfres top level of HiZ */
#if 0 /* Not used for now */
- psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.minz_copydepth_sh, psl->minz_copydepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
#endif
- psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
+ psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_call_add(grp, quad, NULL);
@@ -392,13 +398,12 @@ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_
DRW_stats_group_end();
}
-void EEVEE_draw_effects(EEVEE_Data *vedata)
+void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* only once per frame after the first post process */
@@ -419,39 +424,9 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
EEVEE_depth_of_field_draw(vedata);
EEVEE_bloom_draw(vedata);
- /* Restore default framebuffer */
- DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
- DRW_framebuffer_bind(dfbl->default_fb);
-
- /* Tonemapping */
- DRW_transform_to_display(effects->source_buffer);
-
- /* Debug : Ouput buffer to view. */
- switch (G.debug_value) {
- case 1:
- if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
- break;
- case 2:
- if (stl->g_data->ssr_hit_output[0]) DRW_transform_to_display(stl->g_data->ssr_hit_output[0]);
- break;
- case 3:
- if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input);
- break;
- case 4:
- if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input);
- break;
- case 5:
- if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
- break;
- case 6:
- if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug);
- break;
- case 7:
- if (txl->sss_data) DRW_transform_to_display(txl->sss_data);
- break;
- default:
- break;
- }
+ /* Save the final texture and framebuffer for final transformation or read. */
+ effects->final_tx = effects->source_buffer;
+ effects->final_fb = (effects->target_buffer != fbl->main) ? fbl->main : fbl->effect_fb;
/* If no post processes is enabled, buffers are still not swapped, do it now. */
SWAP_DOUBLE_BUFFERS();
@@ -466,7 +441,7 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
}
/* Record pers matrix for the next frame. */
- DRW_viewport_matrix_get(stl->g_data->prev_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_get(sldata->common_data.prev_persmat, DRW_MAT_PERS);
/* Update double buffer status if render mode. */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a20b1afe3d4..8e74f3344dd 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -29,9 +29,13 @@
#include "BLI_rand.h"
#include "BKE_object.h"
+#include "BKE_global.h" /* for G.debug_value */
+#include "BKE_screen.h"
#include "DNA_world_types.h"
+#include "ED_screen.h"
+
#include "GPU_material.h"
#include "GPU_glew.h"
@@ -52,11 +56,16 @@ static void eevee_engine_init(void *ved)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ Object *camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL;
+
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
- stl->g_data->background_alpha = 1.0f;
+ stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
@@ -66,14 +75,17 @@ static void eevee_engine_init(void *ved)
(int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
- /* EEVEE_effects_init needs to go first for TAA */
- EEVEE_effects_init(sldata, vedata);
+ if (sldata->common_ubo == NULL) {
+ sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
+ }
- EEVEE_materials_init(stl);
+ /* EEVEE_effects_init needs to go first for TAA */
+ EEVEE_effects_init(sldata, vedata, camera);
+ EEVEE_materials_init(sldata, stl, fbl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
- if (stl->effects->taa_current_sample > 1) {
+ if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
/* XXX otherwise it would break the other engines. */
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
@@ -113,22 +125,17 @@ static void eevee_cache_populate(void *vedata, Object *ob)
}
}
- if (ELEM(ob->type, OB_MESH)) {
- if (!BKE_object_is_visible(ob)) {
- return;
- }
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
EEVEE_materials_cache_populate(vedata, sldata, ob);
const bool cast_shadow = true;
if (cast_shadow) {
- if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
- /* TODO: Special case for dupli objects because we cannot save the object pointer. */
- }
- else {
- BLI_addtail(&sldata->shadow_casters, BLI_genericNodeN(ob));
- }
+ EEVEE_lights_cache_shcaster_object_add(sldata, ob);
}
}
else if (ob->type == OB_LIGHTPROBE) {
@@ -140,12 +147,7 @@ static void eevee_cache_populate(void *vedata, Object *ob)
}
}
else if (ob->type == OB_LAMP) {
- if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
- /* TODO: Special case for dupli objects because we cannot save the object pointer. */
- }
- else {
- EEVEE_lights_cache_add(sldata, ob);
- }
+ EEVEE_lights_cache_add(sldata, ob);
}
}
@@ -158,46 +160,47 @@ static void eevee_cache_finish(void *vedata)
EEVEE_lightprobes_cache_finish(sldata, vedata);
}
-static void eevee_draw_scene(void *vedata)
+/* As renders in an HDR offscreen buffer, we need draw everything once
+ * during the background pass. This way the other drawing callback between
+ * the background and the scene pass are visible.
+ * Note: we could break it up in two passes using some depth test
+ * to reduce the fillrate */
+static void eevee_draw_background(void *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
/* Default framebuffer and texture */
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
/* Number of iteration: needed for all temporal effect (SSR, TAA)
* when using opengl render. */
int loop_ct = DRW_state_is_image_render() ? 4 : 1;
- static float rand = 0.0f;
-
- /* XXX temp for denoising render. TODO plug number of samples here */
- if (DRW_state_is_image_render()) {
- rand += 1.0f / 16.0f;
- rand = rand - floorf(rand);
-
- /* Set jitter offset */
- EEVEE_update_util_texture(rand);
- }
- else if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && (stl->effects->taa_current_sample > 1)) {
- double r;
- BLI_halton_1D(2, 0.0, stl->effects->taa_current_sample - 1, &r);
-
- /* Set jitter offset */
- /* PERF This is killing perf ! */
- EEVEE_update_util_texture((float)r);
- }
-
while (loop_ct--) {
+ unsigned int primes[3] = {2, 3, 7};
+ double offset[3] = {0.0, 0.0, 0.0};
+ double r[3];
+
+ if (DRW_state_is_image_render() ||
+ ((stl->effects->enabled_effects & EFFECT_TAA) != 0))
+ {
+ BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
+ EEVEE_update_noise(psl, fbl, r);
+ }
/* Refresh Probes */
DRW_stats_group_start("Probes Refresh");
EEVEE_lightprobes_refresh(sldata, vedata);
DRW_stats_group_end();
+ /* Update common buffer after probe rendering. */
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
/* Refresh shadows */
DRW_stats_group_start("Shadows");
EEVEE_draw_shadows(sldata, psl);
@@ -207,9 +210,19 @@ static void eevee_draw_scene(void *vedata)
DRW_framebuffer_texture_detach(dtxl->depth);
DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
DRW_framebuffer_bind(fbl->main);
- DRW_framebuffer_clear(false, true, true, NULL, 1.0f);
+ if (DRW_state_draw_background()) {
+ DRW_framebuffer_clear(false, true, true, NULL, 1.0f);
+ }
+ else {
+ /* We need to clear the alpha chanel in this case. */
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ DRW_framebuffer_clear(true, true, true, clear_col, 1.0f);
+ }
- if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && stl->effects->taa_current_sample > 1) {
+ if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
+ (stl->effects->taa_current_sample > 1) &&
+ !DRW_state_is_image_render())
+ {
DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
@@ -227,12 +240,14 @@ static void eevee_draw_scene(void *vedata)
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
DRW_stats_group_end();
- EEVEE_occlusion_compute(sldata, vedata);
+ EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
EEVEE_volumes_compute(sldata, vedata);
/* Shading pass */
DRW_stats_group_start("Shading");
- DRW_draw_pass(psl->background_pass);
+ if (DRW_state_draw_background()) {
+ DRW_draw_pass(psl->background_pass);
+ }
EEVEE_draw_default_passes(psl);
DRW_draw_pass(psl->material_pass);
EEVEE_subsurface_data_render(sldata, vedata);
@@ -261,10 +276,10 @@ static void eevee_draw_scene(void *vedata)
/* Post Process */
DRW_stats_group_start("Post FX");
- EEVEE_draw_effects(vedata);
+ EEVEE_draw_effects(sldata, vedata);
DRW_stats_group_end();
- if (stl->effects->taa_current_sample > 1) {
+ if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
@@ -272,6 +287,43 @@ static void eevee_draw_scene(void *vedata)
}
}
+ /* Restore default framebuffer */
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
+ DRW_framebuffer_bind(dfbl->default_fb);
+
+ /* Tonemapping */
+ DRW_transform_to_display(stl->effects->final_tx);
+
+ /* Debug : Ouput buffer to view. */
+ switch (G.debug_value) {
+ case 1:
+ if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer);
+ break;
+ case 2:
+ if (stl->g_data->ssr_pdf_output) DRW_transform_to_display(stl->g_data->ssr_pdf_output);
+ break;
+ case 3:
+ if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input);
+ break;
+ case 4:
+ if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input);
+ break;
+ case 5:
+ if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer);
+ break;
+ case 6:
+ if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug);
+ break;
+ case 7:
+ if (txl->gtao_horizons) DRW_transform_to_display(txl->gtao_horizons);
+ break;
+ case 8:
+ if (txl->sss_data) DRW_transform_to_display(txl->sss_data);
+ break;
+ default:
+ break;
+ }
+
EEVEE_volumes_free_smoke_textures();
stl->g_data->view_updated = false;
@@ -285,24 +337,50 @@ static void eevee_view_update(void *vedata)
}
}
-static void eevee_id_update(void *UNUSED(vedata), ID *id)
+static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
- const ID_Type id_type = GS(id->name);
- if (id_type == ID_OB) {
- Object *object = (Object *)id;
- EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
- if (ped != NULL) {
- ped->need_full_update = true;
- }
- EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
- if (led != NULL) {
- led->need_update = true;
- }
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
- if (oedata != NULL) {
- oedata->need_update = true;
- }
+ /* This is a bit mask of components which update is to be ignored. */
+ const int ignore_updates = ID_RECALC_COLLECTIONS;
+ const int allowed_updates = ~ignore_updates;
+ EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
+ if (ped != NULL && (ped->engine_data.recalc & allowed_updates) != 0) {
+ ped->need_full_update = true;
+ ped->engine_data.recalc = 0;
}
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object);
+ if (led != NULL && (led->engine_data.recalc & allowed_updates) != 0) {
+ led->need_update = true;
+ led->engine_data.recalc = 0;
+ }
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object);
+ if (oedata != NULL && (oedata->engine_data.recalc & allowed_updates) != 0) {
+ oedata->need_update = true;
+ oedata->engine_data.recalc = 0;
+ }
+}
+
+static void eevee_id_update(void *vedata, ID *id)
+{
+ /* Handle updates based on ID type. */
+ switch (GS(id->name)) {
+ case ID_OB:
+ eevee_id_object_update(vedata, (Object *)id);
+ break;
+ default:
+ /* pass */
+ break;
+ }
+}
+
+static void eevee_render_to_image(void *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ EEVEE_render_init(vedata, engine, depsgraph);
+
+ DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache);
+ /* Actually do the rendering. */
+ EEVEE_render_draw(vedata, engine, depsgraph);
+ /* Write outputs to RenderResult. */
+ EEVEE_render_output(vedata, engine, depsgraph);
}
static void eevee_engine_free(void)
@@ -340,7 +418,8 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro
BKE_collection_engine_property_add_int(props, "gi_cubemap_resolution", 512);
BKE_collection_engine_property_add_int(props, "gi_visibility_resolution", 32);
- BKE_collection_engine_property_add_int(props, "taa_samples", 8);
+ BKE_collection_engine_property_add_int(props, "taa_samples", 16);
+ BKE_collection_engine_property_add_int(props, "taa_render_samples", 64);
BKE_collection_engine_property_add_bool(props, "sss_enable", false);
BKE_collection_engine_property_add_int(props, "sss_samples", 7);
@@ -350,7 +429,6 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro
BKE_collection_engine_property_add_bool(props, "ssr_enable", false);
BKE_collection_engine_property_add_bool(props, "ssr_refraction", false);
BKE_collection_engine_property_add_bool(props, "ssr_halfres", true);
- BKE_collection_engine_property_add_int(props, "ssr_ray_count", 1);
BKE_collection_engine_property_add_float(props, "ssr_quality", 0.25f);
BKE_collection_engine_property_add_float(props, "ssr_max_roughness", 0.5f);
BKE_collection_engine_property_add_float(props, "ssr_thickness", 0.2f);
@@ -371,12 +449,10 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro
BKE_collection_engine_property_add_bool(props, "gtao_enable", false);
BKE_collection_engine_property_add_bool(props, "gtao_use_bent_normals", true);
- BKE_collection_engine_property_add_bool(props, "gtao_denoise", true);
BKE_collection_engine_property_add_bool(props, "gtao_bounce", true);
BKE_collection_engine_property_add_float(props, "gtao_distance", 0.2f);
BKE_collection_engine_property_add_float(props, "gtao_factor", 1.0f);
BKE_collection_engine_property_add_float(props, "gtao_quality", 0.25f);
- BKE_collection_engine_property_add_int(props, "gtao_samples", 2);
BKE_collection_engine_property_add_bool(props, "dof_enable", false);
BKE_collection_engine_property_add_float(props, "bokeh_max_size", 100.0f);
@@ -411,16 +487,17 @@ DrawEngineType draw_engine_eevee_type = {
&eevee_cache_init,
&eevee_cache_populate,
&eevee_cache_finish,
- &eevee_draw_scene,
- NULL, //&EEVEE_draw_scene
+ &eevee_draw_background,
+ NULL, /* Everything is drawn in the background pass (see comment on function) */
&eevee_view_update,
&eevee_id_update,
+ &eevee_render_to_image,
};
RenderEngineType DRW_engine_viewport_eevee_type = {
NULL, NULL,
EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL, NULL,
&eevee_layer_collection_settings_create,
&eevee_view_layer_settings_create,
&draw_engine_eevee_type,
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index d7ccc1a5336..7403da737dd 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -26,7 +26,7 @@
#include "DRW_render.h"
#include "BLI_utildefines.h"
-#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "BLI_rand.h"
#include "DNA_world_types.h"
@@ -83,7 +83,6 @@ static struct {
struct GPUTexture *cube_face_minmaxz;
int update_world;
- bool world_ready_to_shade;
} e_data = {NULL}; /* Engine data */
extern char datatoc_background_vert_glsl[];
@@ -107,6 +106,7 @@ extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern GlobalsUboStorage ts;
@@ -204,12 +204,11 @@ static void lightprobe_shaders_init(void)
char *shader_str = NULL;
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_glossy_frag_glsl);
- shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ shader_str = BLI_string_joinN(
+ 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);
@@ -219,36 +218,33 @@ static void lightprobe_shaders_init(void)
MEM_freeN(shader_str);
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_diffuse_frag_glsl);
- shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ shader_str = BLI_string_joinN(
+ 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_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines);
MEM_freeN(shader_str);
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_visibility_frag_glsl);
- shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ shader_str = BLI_string_joinN(
+ 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);
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_grid_display_frag_glsl);
- shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ shader_str = BLI_string_joinN(
+ datatoc_octahedron_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);
e_data.probe_grid_display_sh = DRW_shader_create(
datatoc_lightprobe_grid_display_vert_glsl, NULL, shader_str, filter_defines);
@@ -258,13 +254,12 @@ static void lightprobe_shaders_init(void)
e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen(
datatoc_lightprobe_grid_fill_frag_glsl, filter_defines);
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_cube_display_frag_glsl);
- shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ shader_str = BLI_string_joinN(
+ datatoc_octahedron_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_lightprobe_cube_display_frag_glsl);
e_data.probe_cube_display_sh = DRW_shader_create(
datatoc_lightprobe_cube_display_vert_glsl, NULL, shader_str, NULL);
@@ -286,6 +281,7 @@ static void lightprobe_shaders_init(void)
void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata))
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
bool update_all = false;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -298,15 +294,16 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
if (!sldata->probes) {
sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo");
- sldata->probes->specular_toggle = true;
- sldata->probes->ssr_toggle = true;
- sldata->probes->sss_toggle = true;
sldata->probes->grid_initialized = false;
sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL);
sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL);
sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL);
}
+ common_data->spec_toggle = true;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+
int prop_bounce_num = BKE_collection_engine_property_value_get_int(props, "gi_diffuse_bounces");
if (sldata->probes->num_bounce != prop_bounce_num) {
sldata->probes->num_bounce = prop_bounce_num;
@@ -325,8 +322,8 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda
}
int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution");
- if (sldata->probes->irradiance_vis_size != visibility_res) {
- sldata->probes->irradiance_vis_size = visibility_res;
+ if (common_data->prb_irradiance_vis_size != visibility_res) {
+ common_data->prb_irradiance_vis_size = visibility_res;
update_all = true;
}
@@ -370,6 +367,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->do_cube_update = false;
pinfo->num_cube = 1; /* at least one for the world */
pinfo->num_grid = 1;
pinfo->num_planar = 0;
@@ -391,7 +389,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
float *col = ts.colorBackground;
if (wo) {
col = &wo->horr;
- if (wo->update_flag != 0) {
+ if (wo->update_flag != 0 || pinfo->prev_world != wo) {
e_data.update_world |= PROBE_UPDATE_ALL;
pinfo->updated_bounce = 0;
pinfo->grid_initialized = false;
@@ -413,6 +411,14 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
col = pink;
}
}
+
+ pinfo->prev_world = wo;
+ }
+ else if (pinfo->prev_world) {
+ pinfo->prev_world = NULL;
+ e_data.update_world |= PROBE_UPDATE_ALL;
+ pinfo->updated_bounce = 0;
+ pinfo->grid_initialized = false;
}
/* Fallback if shader fails or if not using nodetree. */
@@ -430,14 +436,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom);
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "roughnessSquared", &sldata->probes->roughness, 1);
- DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
- DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
- DRW_shgroup_uniform_float(grp, "texelSize", &sldata->probes->texel_size, 1);
- DRW_shgroup_uniform_float(grp, "paddingSize", &sldata->probes->padding_size, 1);
- DRW_shgroup_uniform_int(grp, "Layer", &sldata->probes->layer, 1);
+ DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
+ DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1);
+ DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
@@ -450,14 +457,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_diffuse_sh, psl->probe_diffuse_compute);
#ifdef IRRADIANCE_SH_L2
- DRW_shgroup_uniform_int(grp, "probeSize", &sldata->probes->shres, 1);
+ DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1);
#else
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1);
- DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1);
+ DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
#endif
+ DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt);
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
@@ -468,14 +476,14 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute);
- DRW_shgroup_uniform_int(grp, "outputSize", &sldata->probes->shres, 1);
- DRW_shgroup_uniform_float(grp, "visibilityRange", &sldata->probes->visibility_range, 1);
- DRW_shgroup_uniform_float(grp, "visibilityBlur", &sldata->probes->visibility_blur, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1);
- DRW_shgroup_uniform_float(grp, "storedTexelSize", &sldata->probes->texel_size, 1);
- DRW_shgroup_uniform_float(grp, "nearClip", &sldata->probes->near_clip, 1);
- DRW_shgroup_uniform_float(grp, "farClip", &sldata->probes->far_clip, 1);
+ DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1);
+ DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1);
+ DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1);
+ DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1);
+ DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt);
@@ -502,8 +510,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */
DRW_shgroup_attrib_float(grp, "probe_location", 3);
DRW_shgroup_attrib_float(grp, "sphere_size", 1);
- DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
geom = DRW_cache_quad_get();
grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom);
@@ -518,7 +526,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom);
DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &stl->effects->ssr_firefly_fac, 1);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
}
}
@@ -551,7 +559,6 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
ped->need_update = true;
ped->probe_id = 0;
-
if (probe->type == LIGHTPROBE_TYPE_GRID) {
ped->updated_cells = 0;
ped->updated_lvl = 0;
@@ -567,6 +574,8 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
ped->probe_id = 0;
}
+ pinfo->do_cube_update |= ped->need_update;
+
if (probe->type == LIGHTPROBE_TYPE_CUBE) {
pinfo->probes_cube_ref[pinfo->num_cube] = ob;
pinfo->num_cube++;
@@ -685,8 +694,7 @@ static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_
eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
/* Debug Display */
- if (BKE_object_is_visible(ob) &&
- DRW_state_draw_support() &&
+ if (DRW_state_draw_support() &&
(probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
{
DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat);
@@ -734,8 +742,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
invert_m4(eprobe->parallaxmat);
/* Debug Display */
- if (BKE_object_is_visible(ob) &&
- DRW_state_draw_support() &&
+ if (DRW_state_draw_support() &&
(probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
{
ped->probe_size = probe->data_draw_size * 0.1f;
@@ -816,8 +823,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
len_v3(egrid->increment_z)) + 1.0f;
/* Debug Display */
- if (BKE_object_is_visible(ob) &&
- DRW_state_draw_support() &&
+ if (DRW_state_draw_support() &&
(probe->flag & LIGHTPROBE_FLAG_SHOW_DATA))
{
struct Gwn_Batch *geom = DRW_cache_sphere_get();
@@ -837,6 +843,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis
void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
Object *ob;
@@ -854,7 +861,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
int irr_size[3];
- irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
+ irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, irr_size);
if ((irr_size[0] != pinfo->cache_irradiance_size[0]) ||
(irr_size[1] != pinfo->cache_irradiance_size[1]) ||
@@ -880,8 +887,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
/* Tag probes to refresh */
e_data.update_world |= PROBE_UPDATE_CUBE;
- e_data.world_ready_to_shade = false;
- pinfo->num_render_cube = 0;
+ common_data->prb_num_render_cube = 0;
pinfo->cache_num_cube = pinfo->num_cube;
for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) {
@@ -913,7 +919,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2],
irradiance_format, DRW_TEX_FILTER, NULL);
}
- pinfo->num_render_grid = 0;
+ common_data->prb_num_render_grid = 0;
pinfo->updated_bounce = 0;
pinfo->grid_initialized = false;
e_data.update_world |= PROBE_UPDATE_GRID;
@@ -925,9 +931,9 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
- if (pinfo->num_render_grid > pinfo->num_grid) {
+ if (common_data->prb_num_render_grid > pinfo->num_grid) {
/* This can happen when deleting a probe. */
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
}
EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl);
@@ -944,23 +950,26 @@ static void downsample_planar(void *vedata, int level)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
const float *size = DRW_viewport_size_get();
- copy_v2_v2(stl->g_data->texel_size, size);
+ copy_v2_v2(stl->g_data->planar_texel_size, size);
for (int i = 0; i < level - 1; ++i) {
- stl->g_data->texel_size[0] /= 2.0f;
- stl->g_data->texel_size[1] /= 2.0f;
- min_ff(floorf(stl->g_data->texel_size[0]), 1.0f);
- min_ff(floorf(stl->g_data->texel_size[1]), 1.0f);
+ stl->g_data->planar_texel_size[0] /= 2.0f;
+ stl->g_data->planar_texel_size[1] /= 2.0f;
+ min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f);
+ min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f);
}
- invert_v2(stl->g_data->texel_size);
+ invert_v2(stl->g_data->planar_texel_size);
DRW_draw_pass(psl->probe_planar_downsample_ps);
}
/* Glossy filter probe_rt to probe_pool at index probe_idx */
-static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx)
+static void glossy_filter_probe(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx, float intensity)
{
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->intensity_fac = intensity;
+
/* Max lod used from the render target probe */
pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f;
@@ -1023,7 +1032,7 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
CLAMP_MIN(mipsize, 1);
}
/* For shading, save max level of the octahedron map */
- pinfo->lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
+ sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f;
/* reattach to have a valid framebuffer. */
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
@@ -1032,12 +1041,15 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
/* Diffuse filter probe_rt to irradiance_pool at index probe_idx */
static void diffuse_filter_probe(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset,
- float clipsta, float clipend, float vis_range, float vis_blur)
+ float clipsta, float clipend, float vis_range, float vis_blur, float intensity)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ pinfo->intensity_fac = intensity;
+
int pool_size[3];
- irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
+ irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, pool_size);
/* find cell position on the virtual 3D texture */
/* NOTE : Keep in sync with load_irradiance_cell() */
@@ -1081,23 +1093,24 @@ static void diffuse_filter_probe(
/* Compute visibility */
pinfo->samples_ct = 512.0f; /* TODO refine */
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
- pinfo->shres = pinfo->irradiance_vis_size;
+ pinfo->shres = common_data->prb_irradiance_vis_size;
pinfo->visibility_range = vis_range;
pinfo->visibility_blur = vis_blur;
pinfo->near_clip = -clipsta;
pinfo->far_clip = -clipend;
- pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size;
+ pinfo->texel_size = 1.0f / (float)common_data->prb_irradiance_vis_size;
- int cell_per_col = pool_size[1] / pinfo->irradiance_vis_size;
- cell_per_row = pool_size[0] / pinfo->irradiance_vis_size;
- x = pinfo->irradiance_vis_size * (offset % cell_per_row);
- y = pinfo->irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
+ int cell_per_col = pool_size[1] / common_data->prb_irradiance_vis_size;
+ cell_per_row = pool_size[0] / common_data->prb_irradiance_vis_size;
+ x = common_data->prb_irradiance_vis_size * (offset % cell_per_row);
+ y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col);
int layer = 1 + ((offset / cell_per_row) / cell_per_col);
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0);
- DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size);
+ DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, common_data->prb_irradiance_vis_size,
+ common_data->prb_irradiance_vis_size);
DRW_draw_pass(psl->probe_visibility_compute);
}
@@ -1116,24 +1129,13 @@ static void render_scene_to_probe(
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- float winmat[4][4], wininv[4][4], posmat[4][4], tmp_ao_dist, tmp_ao_samples, tmp_ao_settings;
+ float winmat[4][4], wininv[4][4], posmat[4][4];
unit_m4(posmat);
/* Move to capture position */
negate_v3_v3(posmat[3], pos);
- /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
- sldata->probes->specular_toggle = false;
- sldata->probes->ssr_toggle = false;
- sldata->probes->sss_toggle = false;
-
- /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */
- tmp_ao_dist = stl->effects->ao_dist;
- tmp_ao_samples = stl->effects->ao_samples;
- tmp_ao_settings = stl->effects->ao_settings;
- stl->effects->ao_settings = 0.0f; /* Disable AO */
-
/* 1 - Render to each cubeface individually.
* We do this instead of using geometry shader because a) it's faster,
* b) it's easier than fixing the nodetree shaders (for view dependant effects). */
@@ -1149,6 +1151,9 @@ static void render_scene_to_probe(
stl->g_data->minzbuffer = e_data.depth_placeholder;
txl->maxzbuffer = e_data.depth_placeholder;
+ /* Update common uniforms */
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
/* Detach to rebind the right cubeface. */
DRW_framebuffer_bind(sldata->probe_fb);
DRW_framebuffer_texture_detach(sldata->probe_rt);
@@ -1210,15 +1215,9 @@ static void render_scene_to_probe(
DRW_viewport_matrix_override_unset(DRW_MAT_WININV);
/* Restore */
- pinfo->specular_toggle = true;
- pinfo->ssr_toggle = true;
- pinfo->sss_toggle = true;
txl->planar_pool = tmp_planar_pool;
stl->g_data->minzbuffer = tmp_minz;
txl->maxzbuffer = tmp_maxz;
- stl->effects->ao_dist = tmp_ao_dist;
- stl->effects->ao_samples = tmp_ao_samples;
- stl->effects->ao_settings = tmp_ao_settings;
}
static void render_scene_to_planar(
@@ -1257,11 +1256,6 @@ static void render_scene_to_planar(
DRW_framebuffer_clear(false, true, false, NULL, 1.0);
- /* Turn off ssr to avoid black specular */
- /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
- sldata->probes->ssr_toggle = false;
- sldata->probes->sss_toggle = false;
-
/* Avoid using the texture attached to framebuffer when rendering. */
/* XXX */
GPUTexture *tmp_planar_pool = txl->planar_pool;
@@ -1279,7 +1273,7 @@ static void render_scene_to_planar(
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
/* Compute GTAO Horizons */
- EEVEE_occlusion_compute(sldata, vedata);
+ EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer);
/* Rebind Planar FB */
DRW_framebuffer_bind(fbl->planarref_fb);
@@ -1293,8 +1287,6 @@ static void render_scene_to_planar(
DRW_state_clip_planes_reset();
/* Restore */
- sldata->probes->ssr_toggle = true;
- sldata->probes->sss_toggle = true;
txl->planar_pool = tmp_planar_pool;
txl->planar_depth = tmp_planar_depth;
DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
@@ -1380,27 +1372,25 @@ static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float loc
static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
render_world_to_probe(sldata, psl);
if (e_data.update_world & PROBE_UPDATE_CUBE) {
- glossy_filter_probe(sldata, vedata, psl, 0);
+ glossy_filter_probe(sldata, vedata, psl, 0, 1.0);
+ common_data->prb_num_render_cube = 1;
}
if (e_data.update_world & PROBE_UPDATE_GRID) {
- diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0);
+ diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
DRW_framebuffer_texture_detach(sldata->probe_pool);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0);
DRW_draw_pass(psl->probe_grid_fill);
DRW_framebuffer_texture_detach(sldata->irradiance_rt);
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ common_data->prb_num_render_grid = 1;
}
e_data.update_world = 0;
- if (!e_data.world_ready_to_shade) {
- e_data.world_ready_to_shade = true;
- pinfo->num_render_cube = 1;
- pinfo->num_render_grid = 1;
- }
DRW_viewport_request_redraw();
}
@@ -1432,36 +1422,53 @@ static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEV
static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_TextureList *txl = vedata->txl;
Object *ob;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
+
+ if (pinfo->num_planar == 0) {
+ return;
+ }
+
+ /* Temporary Remove all planar reflections (avoid lag effect). */
+ common_data->prb_num_planar = 0;
+ /* Turn off ssr to avoid black specular */
+ /* TODO : Enable SSR in planar reflections? (Would be very heavy) */
+ common_data->ssr_toggle = false;
+ common_data->sss_toggle = false;
+
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+
for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
if (!ped->need_update) {
continue;
}
- /* Temporary Remove all planar reflections (avoid lag effect). */
- int tmp_num_planar = pinfo->num_planar;
- pinfo->num_planar = 0;
render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset);
- /* Restore */
- pinfo->num_planar = tmp_num_planar;
ped->need_update = false;
ped->probe_id = i;
}
+
+ /* Restore */
+ common_data->prb_num_planar = pinfo->num_planar;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+
/* If there is at least one planar probe */
if (pinfo->num_planar > 0 && (vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) {
const int max_lod = 9;
DRW_stats_group_start("Planar Probe Downsample");
DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata);
/* For shading, save max level of the planar map */
- pinfo->lod_planar_max = (float)(max_lod);
+ common_data->prb_lod_planar_max = (float)(max_lod);
DRW_stats_group_end();
}
}
static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -1473,11 +1480,11 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
}
LightProbe *prb = (LightProbe *)ob->data;
render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend);
- glossy_filter_probe(sldata, vedata, psl, i);
+ glossy_filter_probe(sldata, vedata, psl, i, prb->intensity);
ped->need_update = false;
ped->probe_id = i;
if (!ped->ready_to_shade) {
- pinfo->num_render_cube++;
+ common_data->prb_num_render_cube++;
ped->ready_to_shade = true;
}
#if 0
@@ -1488,13 +1495,13 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve
stl->effects->taa_current_sample = 1;
/* Only do one probe per frame */
- lightprobes_refresh_planar(sldata, vedata);
return;
}
}
static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -1506,7 +1513,6 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
/* Only compute probes if not navigating or in playback */
struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
if (((rv3d->rflag & RV3D_NAVIGATING) != 0) || ED_screen_animation_no_scrub(wm) != NULL) {
- lightprobes_refresh_planar(sldata, vedata);
return;
}
}
@@ -1515,7 +1521,7 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
/* Reflection probes depend on diffuse lighting thus on irradiance grid,
* so update them first. */
while (pinfo->updated_bounce < pinfo->num_bounce) {
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
/* TODO(sergey): This logic can be split into smaller functions. */
for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) {
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob);
@@ -1559,16 +1565,16 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
lightprobe_cell_world_location_get(egrid, grid_loc, pos);
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
/* Temporary Remove all probes. */
- int tmp_num_render_grid = pinfo->num_render_grid;
- int tmp_num_render_cube = pinfo->num_render_cube;
- int tmp_num_planar = pinfo->num_planar;
+ int tmp_num_render_grid = common_data->prb_num_render_grid;
+ int tmp_num_render_cube = common_data->prb_num_render_cube;
+ int tmp_num_planar = common_data->prb_num_planar;
float tmp_level_bias = egrid->level_bias;
- pinfo->num_render_cube = 0;
- pinfo->num_planar = 0;
+ common_data->prb_num_render_cube = 0;
+ common_data->prb_num_planar = 0;
/* Use light from previous bounce when capturing radiance. */
if (pinfo->updated_bounce == 0) {
/* But not on first bounce. */
- pinfo->num_render_grid = 0;
+ common_data->prb_num_render_grid = 0;
}
else {
/* Remove bias */
@@ -1577,14 +1583,15 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
}
render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend);
diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id,
- prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur);
+ prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur,
+ prb->intensity);
/* To see what is going on. */
SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt);
/* Restore */
- pinfo->num_render_cube = tmp_num_render_cube;
+ common_data->prb_num_render_cube = tmp_num_render_cube;
pinfo->num_planar = tmp_num_planar;
if (pinfo->updated_bounce == 0) {
- pinfo->num_render_grid = tmp_num_render_grid;
+ common_data->prb_num_render_grid = tmp_num_render_grid;
}
else {
egrid->level_bias = tmp_level_bias;
@@ -1608,12 +1615,11 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
DRW_viewport_request_redraw();
/* Do not let this frame accumulate. */
stl->effects->taa_current_sample = 1;
- lightprobes_refresh_planar(sldata, vedata);
return;
}
pinfo->updated_bounce++;
- pinfo->num_render_grid = pinfo->num_grid;
+ common_data->prb_num_render_grid = pinfo->num_grid;
if (pinfo->updated_bounce < pinfo->num_bounce) {
/* Retag all grids to update for next bounce */
@@ -1641,13 +1647,39 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_
void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_LightProbesInfo *pinfo = sldata->probes;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
+ common_data->spec_toggle = false;
+ common_data->ssr_toggle = false;
+ common_data->sss_toggle = false;
+
+ /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */
+ float tmp_ao_dist = common_data->ao_dist;
+ float tmp_ao_settings = common_data->ao_settings;
+ common_data->ao_settings = 0.0f;
+ common_data->ao_dist = 0.0f;
+
/* Render world in priority */
if (e_data.update_world) {
lightprobes_refresh_world(sldata, vedata);
}
- else if (true) { /* TODO if at least one probe needs refresh */
+ else if (pinfo->do_cube_update || (pinfo->updated_bounce < pinfo->num_bounce)) {
lightprobes_refresh_all_no_world(sldata, vedata);
}
+
+ /* Restore */
+ common_data->spec_toggle = true;
+ common_data->ssr_toggle = true;
+ common_data->sss_toggle = true;
+ common_data->ao_dist = tmp_ao_dist;
+ common_data->ao_settings = tmp_ao_settings;
+
+ lightprobes_refresh_planar(sldata, vedata);
+
+ /* Disable SSR if we cannot read previous frame */
+ common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer;
}
void EEVEE_lightprobes_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 22465c04cfa..69b58bf9670 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -32,28 +32,7 @@
#include "eevee_engine.h"
#include "eevee_private.h"
-/* Theses are the structs stored inside Objects.
- * It works with even if the object is in multiple layers
- * because we don't get the same "Object *" for each layer. */
-typedef struct EEVEE_LightData {
- short light_id, shadow_id;
-} EEVEE_LightData;
-
-typedef struct EEVEE_ShadowCubeData {
- short light_id, shadow_id, cube_id, layer_id;
-} EEVEE_ShadowCubeData;
-
-typedef struct EEVEE_ShadowCascadeData {
- short light_id, shadow_id, cascade_id, layer_id;
- float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
- float radius[MAX_CASCADE_NUM];
-} EEVEE_ShadowCascadeData;
-
-typedef struct ShadowCaster {
- struct ShadowCaster *next, *prev;
- void *ob;
- bool prune;
-} ShadowCaster;
+#define SHADOW_CASTER_ALLOC_CHUNK 16
static struct {
struct GPUShader *shadow_sh;
@@ -70,6 +49,48 @@ extern char datatoc_shadow_store_frag_glsl[];
extern char datatoc_shadow_copy_frag_glsl[];
extern char datatoc_concentric_samples_lib_glsl[];
+/* Prototype */
+static void eevee_light_setup(Object *ob, EEVEE_Light *evli);
+
+/* *********** LIGHT BITS *********** */
+static void lightbits_set_single(EEVEE_LightBits *bitf, unsigned int idx, bool val)
+{
+ if (val) {
+ bitf->fields[idx / 8] |= (1 << (idx % 8));
+ }
+ else {
+ bitf->fields[idx / 8] &= ~(1 << (idx % 8));
+ }
+}
+
+static void lightbits_set_all(EEVEE_LightBits *bitf, bool val)
+{
+ memset(bitf, (val) ? 0xFF : 0x00, sizeof(EEVEE_LightBits));
+}
+
+static void lightbits_or(EEVEE_LightBits *r, const EEVEE_LightBits *v)
+{
+ for (int i = 0; i < MAX_LIGHTBITS_FIELDS; ++i) {
+ r->fields[i] |= v->fields[i];
+ }
+}
+
+static bool lightbits_get(const EEVEE_LightBits *r, unsigned int idx)
+{
+ return r->fields[idx / 8] & (1 << (idx % 8));
+}
+
+static void lightbits_convert(EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, unsigned int table_length)
+{
+ for (int i = 0; i < table_length; ++i) {
+ if (lightbits_get(bitf, i) != 0) {
+ if (light_bit_conv_table[i] >= 0) {
+ r->fields[i / 8] |= (1 << (i % 8));
+ }
+ }
+ }
+}
+
/* *********** FUNCTIONS *********** */
void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
@@ -96,7 +117,8 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
store_shadow_shader_str,
"#define ESM\n");
e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- store_shadow_shader_str, "#define ESM\n"
+ store_shadow_shader_str,
+ "#define ESM\n"
"#define CSM\n");
e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen(
@@ -114,7 +136,8 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
"#define ESM\n"
"#define COPY\n");
e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen(
- datatoc_shadow_copy_frag_glsl, "#define ESM\n"
+ datatoc_shadow_copy_frag_glsl,
+ "#define ESM\n"
"#define COPY\n"
"#define CSM\n");
@@ -134,8 +157,21 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL);
+
+ for (int i = 0; i < 2; ++i) {
+ sldata->shcasters_buffers[i].shadow_casters = MEM_callocN(sizeof(EEVEE_ShadowCaster) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_ShadowCaster buf");
+ sldata->shcasters_buffers[i].flags = MEM_callocN(sizeof(sldata->shcasters_buffers[0].flags) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_shcast_buffer flags buf");
+ sldata->shcasters_buffers[i].alloc_count = SHADOW_CASTER_ALLOC_CHUNK;
+ sldata->shcasters_buffers[i].count = 0;
+ }
+
+ sldata->lamps->shcaster_frontbuffer = &sldata->shcasters_buffers[0];
+ sldata->lamps->shcaster_backbuffer = &sldata->shcasters_buffers[1];
}
+ /* Flip buffers */
+ SWAP(EEVEE_ShadowCasterBuffer *, sldata->lamps->shcaster_frontbuffer, sldata->lamps->shcaster_backbuffer);
+
int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method");
int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size");
int sh_high_bitdepth = BKE_collection_engine_property_value_get_int(props, "shadow_high_bitdepth");
@@ -173,6 +209,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
{
EEVEE_LampsInfo *linfo = sldata->lamps;
+ linfo->shcaster_frontbuffer->count = 0;
linfo->num_light = 0;
linfo->num_layer = 0;
linfo->gpu_cube_ct = linfo->gpu_cascade_ct = linfo->gpu_shadow_ct = 0;
@@ -180,6 +217,11 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
+ memset(linfo->new_shadow_id, -1, sizeof(linfo->new_shadow_id));
+
+ /* Shadow Casters: Reset flags. */
+ memset(linfo->shcaster_backbuffer->flags, (char)SHADOW_CASTER_PRUNED, linfo->shcaster_backbuffer->alloc_count);
+ memset(linfo->shcaster_frontbuffer->flags, 0x00, linfo->shcaster_frontbuffer->alloc_count);
{
psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR);
@@ -239,9 +281,6 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
"Shadow Cascade Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
}
-
- /* Reset shadow casters list */
- BLI_freelistN(&sldata->shadow_casters);
}
void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
@@ -250,14 +289,27 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Step 1 find all lamps in the scene and setup them */
if (linfo->num_light >= MAX_LIGHT) {
- printf("Too much lamps in the scene !!!\n");
- linfo->num_light = MAX_LIGHT - 1;
+ printf("Too many lamps in the scene !!!\n");
}
else {
Lamp *la = (Lamp *)ob->data;
+ EEVEE_Light *evli = linfo->light_data + linfo->num_light;
+ eevee_light_setup(ob, evli);
+
+ /* We do not support shadowmaps for dupli lamps. */
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ linfo->num_light++;
+ return;
+ }
+
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
- MEM_SAFE_FREE(led->storage);
+ /* Save previous shadow id. */
+ int prev_cube_sh_id = led->prev_cube_shadow_id;
+
+ /* Default light without shadows */
+ led->data.ld.shadow_id = -1;
+ led->prev_cube_shadow_id = -1;
if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
if (la->type == LA_SUN) {
@@ -268,13 +320,11 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Save Light object. */
linfo->shadow_cascade_ref[linfo->cpu_cascade_ct] = ob;
- /* Create storage and store indices. */
- EEVEE_ShadowCascadeData *data = MEM_mallocN(
- sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData");
+ /* Store indices. */
+ EEVEE_ShadowCascadeData *data = &led->data.scad;
data->shadow_id = linfo->gpu_shadow_ct;
data->cascade_id = linfo->gpu_cascade_ct;
data->layer_id = linfo->num_layer;
- led->storage = data;
/* Increment indices. */
linfo->gpu_shadow_ct += 1;
@@ -291,13 +341,24 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
/* Save Light object. */
linfo->shadow_cube_ref[linfo->cpu_cube_ct] = ob;
- /* Create storage and store indices. */
- EEVEE_ShadowCubeData *data = MEM_mallocN(
- sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
+ /* For light update tracking. */
+ if ((prev_cube_sh_id >= 0) &&
+ (prev_cube_sh_id < linfo->shcaster_backbuffer->count))
+ {
+ linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_ct;
+ }
+ led->prev_cube_shadow_id = linfo->cpu_cube_ct;
+
+ /* Saving lamp bounds for later. */
+ BLI_assert(linfo->cpu_cube_ct >= 0 && linfo->cpu_cube_ct < MAX_LIGHT);
+ copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_ct].center, ob->obmat[3]);
+ linfo->shadow_bounds[linfo->cpu_cube_ct].radius = la->clipend;
+
+ EEVEE_ShadowCubeData *data = &led->data.scd;
+ /* Store indices. */
data->shadow_id = linfo->gpu_shadow_ct;
data->cube_id = linfo->gpu_cube_ct;
data->layer_id = linfo->num_layer;
- led->storage = data;
/* Increment indices. */
linfo->gpu_shadow_ct += 1;
@@ -309,13 +370,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob)
}
}
- /* Default light without shadows */
- if (!led->storage) {
- led->storage = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
- ((EEVEE_LightData *)led->storage)->shadow_id = -1;
- }
-
- ((EEVEE_LightData *)led->storage)->light_id = linfo->num_light;
+ led->data.ld.light_id = linfo->num_light;
linfo->light_ref[linfo->num_light] = ob;
linfo->num_light++;
}
@@ -362,11 +417,75 @@ void EEVEE_lights_cache_shcaster_material_add(
DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM);
}
+/* Make that object update shadow casting lamps inside its influence bounding box. */
+void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object *ob)
+{
+ if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
+ /* TODO: Special case for dupli objects because we cannot save the object pointer. */
+ return;
+ }
+
+ EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
+ EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
+ int past_id = oedata->shadow_caster_id;
+
+ /* Update flags in backbuffer. */
+ if (past_id > -1 && past_id < backbuffer->count) {
+ backbuffer->flags[past_id] &= ~SHADOW_CASTER_PRUNED;
+
+ if (oedata->need_update) {
+ backbuffer->flags[past_id] |= SHADOW_CASTER_UPDATED;
+ }
+ }
+
+ /* Update id. */
+ oedata->shadow_caster_id = frontbuffer->count++;
+
+ /* Make sure shadow_casters is big enough. */
+ if (oedata->shadow_caster_id >= frontbuffer->alloc_count) {
+ frontbuffer->alloc_count += SHADOW_CASTER_ALLOC_CHUNK;
+ frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
+ frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
+ }
+
+ EEVEE_ShadowCaster *shcaster = frontbuffer->shadow_casters + oedata->shadow_caster_id;
+
+ if (oedata->need_update) {
+ frontbuffer->flags[oedata->shadow_caster_id] = SHADOW_CASTER_UPDATED;
+ }
+
+ /* Update World AABB in frontbuffer. */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ for (int i = 0; i < 8; ++i) {
+ float vec[3];
+ copy_v3_v3(vec, bb->vec[i]);
+ mul_m4_v3(ob->obmat, vec);
+ minmax_v3v3_v3(min, max, vec);
+ }
+
+ EEVEE_BoundBox *aabb = &shcaster->bbox;
+ add_v3_v3v3(aabb->center, min, max);
+ mul_v3_fl(aabb->center, 0.5f);
+ sub_v3_v3v3(aabb->halfdim, aabb->center, max);
+
+ aabb->halfdim[0] = fabsf(aabb->halfdim[0]);
+ aabb->halfdim[1] = fabsf(aabb->halfdim[1]);
+ aabb->halfdim[2] = fabsf(aabb->halfdim[2]);
+
+ oedata->need_update = false;
+}
+
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
{
EEVEE_LampsInfo *linfo = sldata->lamps;
DRWTextureFormat shadow_pool_format = DRW_TEX_R_32;
+ sldata->common_data.la_num_light = linfo->num_light;
+
/* Setup enough layers. */
/* Free textures if number mismatch. */
if (linfo->num_layer != linfo->cache_num_layer) {
@@ -428,11 +547,8 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
}
/* Update buffer with lamp data */
-static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
{
- /* TODO only update if data changes */
- EEVEE_LightData *evld = led->storage;
- EEVEE_Light *evli = linfo->light_data + evld->light_id;
Lamp *la = (Lamp *)ob->data;
float mat[4][4], scale[3], power;
@@ -485,13 +601,14 @@ static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngi
}
else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */
- M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
+ M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
/* for point lights (a.k.a radius == 0.0) */
// power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
}
else {
- power = 1.0f;
+ power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(r²*Pi) */
+ 12.5f; /* XXX : Empirical, Fit cycles power */
}
mul_v3_fl(evli->color, power * la->energy);
@@ -504,7 +621,7 @@ static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngi
static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
{
- EEVEE_ShadowCubeData *sh_data = (EEVEE_ShadowCubeData *)led->storage;
+ EEVEE_ShadowCubeData *sh_data = &led->data.scd;
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id;
@@ -598,7 +715,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
int sh_nbr = 1; /* TODO : MSM */
int cascade_nbr = la->cascade_count;
- EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage;
+ EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
@@ -783,128 +900,86 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
}
/* Used for checking if object is inside the shadow volume. */
-static bool cube_bbox_intersect(const float cube_center[3], float cube_half_dim, const BoundBox *bb, float (*obmat)[4])
+static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_BoundBox *bb)
{
- float min[3], max[4], tmp[4][4];
- unit_m4(tmp);
- translate_m4(tmp, -cube_center[0], -cube_center[1], -cube_center[2]);
- mul_m4_m4m4(tmp, tmp, obmat);
-
- /* Just simple AABB intersection test in world space. */
- INIT_MINMAX(min, max);
- for (int i = 0; i < 8; ++i) {
- float vec[3];
- copy_v3_v3(vec, bb->vec[i]);
- mul_m4_v3(tmp, vec);
- minmax_v3v3_v3(min, max, vec);
- }
+ /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */
+ /* TODO test speed with AABB vs Sphere. */
+ bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius);
+ bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius);
+ bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius);
- if (MAX3(max[0], max[1], max[2]) < -cube_half_dim) return false;
- if (MIN3(min[0], min[1], min[2]) > cube_half_dim) return false;
-
- return true;
+ return x && y && z;
}
-static ShadowCaster *search_object_in_list(ListBase *list, Object *ob)
+void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
{
- for (ShadowCaster *ldata = list->first; ldata; ldata = ldata->next) {
- if (ldata->ob == ob)
- return ldata;
+ EEVEE_LampsInfo *linfo = sldata->lamps;
+ Object *ob;
+ int i;
+ char *flag;
+ EEVEE_ShadowCaster *shcaster;
+ EEVEE_BoundSphere *bsphere;
+ EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer;
+ EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer;
+
+ EEVEE_LightBits update_bits = {{0}};
+ if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) {
+ /* Update all lights. */
+ lightbits_set_all(&update_bits, true);
}
-
- return NULL;
-}
-
-static void delete_pruned_shadowcaster(EEVEE_LampEngineData *led)
-{
- ShadowCaster *next;
- for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = next) {
- next = ldata->next;
- if (ldata->prune == true) {
- led->need_update = true;
- BLI_freelinkN(&led->shadow_caster_list, ldata);
+ else {
+ /* Search for deleted shadow casters and if shcaster WAS in shadow radius. */
+ /* No need to run this if we already update all lamps. */
+ EEVEE_LightBits past_bits = {{0}};
+ EEVEE_LightBits curr_bits = {{0}};
+ shcaster = backbuffer->shadow_casters;
+ flag = backbuffer->flags;
+ for (i = 0; i < backbuffer->count; ++i, ++flag, ++shcaster) {
+ /* If the shadowcaster has been deleted or updated. */
+ if (*flag != 0) {
+ /* Add the lamps that were intersecting with its BBox. */
+ lightbits_or(&past_bits, &shcaster->bits);
+ }
}
+ /* Convert old bits to new bits and add result to final update bits. */
+ /* NOTE: This might be overkill since all lights are tagged to refresh if
+ * the light count changes. */
+ lightbits_convert(&curr_bits, &past_bits, linfo->new_shadow_id, MAX_LIGHT);
+ lightbits_or(&update_bits, &curr_bits);
}
-}
-static void light_tag_shadow_update(Object *lamp, Object *ob)
-{
- Lamp *la = lamp->data;
- EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp);
-
- bool is_inside_range = cube_bbox_intersect(lamp->obmat[3], la->clipend, BKE_object_boundbox_get(ob), ob->obmat);
- ShadowCaster *ldata = search_object_in_list(&led->shadow_caster_list, ob);
-
- if (is_inside_range) {
- if (ldata == NULL) {
- /* Object was not a shadow caster previously but is now. Add it. */
- ldata = MEM_callocN(sizeof(ShadowCaster), "ShadowCaster");
- ldata->ob = ob;
- BLI_addtail(&led->shadow_caster_list, ldata);
- led->need_update = true;
+ /* Search for updates in current shadow casters. */
+ shcaster = frontbuffer->shadow_casters;
+ flag = frontbuffer->flags;
+ for (i = 0; i < frontbuffer->count; i++, flag++, shcaster++) {
+ /* Run intersection checks to fill the bitfields. */
+ bsphere = linfo->shadow_bounds;
+ for (int j = 0; j < linfo->cpu_cube_ct; j++, bsphere++) {
+ bool iter = sphere_bbox_intersect(bsphere, &shcaster->bbox);
+ lightbits_set_single(&shcaster->bits, j, iter);
}
- else {
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
- if (oedata->need_update) {
- led->need_update = true;
- }
+ /* Only add to final bits if objects has been updated. */
+ if (*flag != 0) {
+ lightbits_or(&update_bits, &shcaster->bits);
}
- ldata->prune = false;
}
- else if (ldata != NULL) {
- /* Object was a shadow caster previously and is not anymore. Remove it. */
- led->need_update = true;
- BLI_freelinkN(&led->shadow_caster_list, ldata);
- }
-}
-
-static void eevee_lights_shcaster_updated(EEVEE_ViewLayerData *sldata, Object *ob)
-{
- Object *lamp;
- EEVEE_LampsInfo *linfo = sldata->lamps;
-
- /* Iterate over all shadow casting lamps to see if
- * each of them needs update because of this object */
- for (int i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
- light_tag_shadow_update(lamp, ob);
- }
- EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob);
- oedata->need_update = false;
-}
-
-void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
-{
- EEVEE_LampsInfo *linfo = sldata->lamps;
- Object *ob;
- int i;
- /* Prune shadow casters to remove if object does not exists anymore (unprune them if object exists) */
- Object *lamp;
- for (i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
- EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp);
+ /* Setup shadow cube in UBO and tag for update if necessary. */
+ for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) {
+ EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
- if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) {
+ eevee_shadow_cube_setup(ob, linfo, led);
+ if (lightbits_get(&update_bits, i) != 0) {
led->need_update = true;
}
-
- for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = ldata->next) {
- ldata->prune = true;
- }
}
- for (LinkData *ldata = sldata->shadow_casters.first; ldata; ldata = ldata->next) {
- eevee_lights_shcaster_updated(sldata, ldata->data);
- }
-
- for (i = 0; (ob = linfo->light_ref[i]) && (i < MAX_LIGHT); i++) {
- EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
- eevee_light_setup(ob, linfo, led);
- }
-
- for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
- EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
- eevee_shadow_cube_setup(ob, linfo, led);
- delete_pruned_shadowcaster(led);
+ /* Resize shcasters buffers if too big. */
+ if (frontbuffer->alloc_count - frontbuffer->count > SHADOW_CASTER_ALLOC_CHUNK) {
+ frontbuffer->alloc_count = (frontbuffer->count / SHADOW_CASTER_ALLOC_CHUNK) * SHADOW_CASTER_ALLOC_CHUNK;
+ frontbuffer->alloc_count += (frontbuffer->count % SHADOW_CASTER_ALLOC_CHUNK != 0) ? SHADOW_CASTER_ALLOC_CHUNK : 0;
+ frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
+ frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count);
}
}
@@ -932,7 +1007,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
}
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
- EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
+ EEVEE_ShadowCubeData *evscd = &led->data.scd;
srd->clip_near = la->clipsta;
srd->clip_far = la->clipend;
@@ -1010,7 +1085,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
Lamp *la = (Lamp *)ob->data;
- EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->storage;
+ EEVEE_ShadowCascadeData *evscd = &led->data.scad;
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
eevee_shadow_cascade_setup(ob, linfo, led);
diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h
index d706110351e..3c2ffeb11a7 100644
--- a/source/blender/draw/engines/eevee/eevee_lut.h
+++ b/source/blender/draw/engines/eevee/eevee_lut.h
@@ -3345,6 +3345,521 @@ static float bsdf_split_sum_ggx[64 * 64 * 2] = {
0.626953f, 0.023544f, 0.616699f, 0.022186f, 0.605957f, 0.020920f, 0.594727f, 0.019730f
};
+static float ltc_disk_integral[64 * 64] = {
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.015873f, 0.047619f, 0.079365f, 0.111111f, 0.142857f, 0.174603f, 0.206349f, 0.238095f,
+ 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000148f, 0.002454f, 0.008675f, 0.019560f,
+ 0.035433f, 0.056294f, 0.081819f, 0.111259f, 0.142857f, 0.174603f, 0.206349f, 0.238095f,
+ 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000002f, 0.000761f, 0.003673f, 0.009403f, 0.018333f, 0.030683f,
+ 0.046556f, 0.065952f, 0.088768f, 0.114784f, 0.143618f, 0.174606f, 0.206349f, 0.238095f,
+ 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000039f, 0.000969f, 0.003703f, 0.008684f, 0.016189f, 0.026395f, 0.039409f,
+ 0.055282f, 0.074014f, 0.095554f, 0.119795f, 0.146560f, 0.175573f, 0.206388f, 0.238095f,
+ 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000047f, 0.000895f, 0.003265f, 0.007514f, 0.013873f, 0.022495f, 0.033483f, 0.046897f,
+ 0.062770f, 0.081102f, 0.101860f, 0.124985f, 0.150372f, 0.177868f, 0.207245f, 0.238143f,
+ 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000028f,
+ 0.000695f, 0.002655f, 0.006230f, 0.011623f, 0.018976f, 0.028384f, 0.039915f, 0.053606f,
+ 0.069479f, 0.087534f, 0.107749f, 0.130087f, 0.154481f, 0.180833f, 0.209005f, 0.238791f,
+ 0.269869f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000465f,
+ 0.002017f, 0.004975f, 0.009533f, 0.015821f, 0.023934f, 0.033937f, 0.045874f, 0.059772f,
+ 0.075645f, 0.093493f, 0.113302f, 0.135045f, 0.158678f, 0.184136f, 0.211325f, 0.240113f,
+ 0.270306f, 0.301594f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.001426f,
+ 0.003823f, 0.007642f, 0.013012f, 0.020025f, 0.028745f, 0.039218f, 0.051475f, 0.065535f,
+ 0.081408f, 0.099094f, 0.118583f, 0.139856f, 0.162882f, 0.187615f, 0.213991f, 0.241918f,
+ 0.271267f, 0.301847f, 0.333333f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000109f, 0.000921f, 0.002807f,
+ 0.005966f, 0.010528f, 0.016585f, 0.024200f, 0.033420f, 0.044278f, 0.056796f, 0.070988f,
+ 0.086861f, 0.104415f, 0.123643f, 0.144531f, 0.167057f, 0.191188f, 0.216878f, 0.244062f,
+ 0.272649f, 0.302509f, 0.333442f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000524f, 0.001947f, 0.004511f,
+ 0.008351f, 0.013561f, 0.020206f, 0.028332f, 0.037974f, 0.049155f, 0.061892f, 0.076194f,
+ 0.092067f, 0.109511f, 0.128520f, 0.149085f, 0.171189f, 0.194809f, 0.219910f, 0.246447f,
+ 0.274352f, 0.303535f, 0.333857f, 0.365104f, 0.396826f, 0.428572f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000242f, 0.001250f, 0.003275f, 0.006463f,
+ 0.010913f, 0.016693f, 0.023849f, 0.032418f, 0.042423f, 0.053881f, 0.066805f, 0.081201f,
+ 0.097074f, 0.114424f, 0.133246f, 0.153534f, 0.175275f, 0.198453f, 0.223042f, 0.249009f,
+ 0.276304f, 0.304862f, 0.334584f, 0.365322f, 0.396826f, 0.428571f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000074f, 0.000716f, 0.002252f, 0.004848f, 0.008610f,
+ 0.013608f, 0.019894f, 0.027502f, 0.036458f, 0.046780f, 0.058480f, 0.071567f, 0.086045f,
+ 0.101918f, 0.119186f, 0.137845f, 0.157891f, 0.179316f, 0.202106f, 0.226243f, 0.251704f,
+ 0.278451f, 0.306436f, 0.335586f, 0.365796f, 0.396900f, 0.428571f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000006f, 0.000342f, 0.001437f, 0.003492f, 0.006624f, 0.010911f,
+ 0.016406f, 0.023146f, 0.031157f, 0.040457f, 0.051059f, 0.062972f, 0.076203f, 0.090753f,
+ 0.106626f, 0.123822f, 0.142337f, 0.162170f, 0.183314f, 0.205760f, 0.229496f, 0.254502f,
+ 0.280753f, 0.308212f, 0.336825f, 0.366517f, 0.397167f, 0.428578f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000114f, 0.000820f, 0.002381f, 0.004935f, 0.008569f, 0.013339f,
+ 0.019286f, 0.026437f, 0.034810f, 0.044418f, 0.055271f, 0.067375f, 0.080733f, 0.095348f,
+ 0.111221f, 0.128352f, 0.146740f, 0.166382f, 0.187276f, 0.209413f, 0.232786f, 0.257382f,
+ 0.283181f, 0.310156f, 0.338269f, 0.367461f, 0.397646f, 0.428685f, 0.460318f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000014f, 0.000390f, 0.001503f, 0.003525f, 0.006554f, 0.010655f, 0.015872f,
+ 0.022233f, 0.029758f, 0.038460f, 0.048347f, 0.059427f, 0.071702f, 0.085175f, 0.099848f,
+ 0.115721f, 0.132794f, 0.151067f, 0.170538f, 0.191204f, 0.213063f, 0.236107f, 0.260329f,
+ 0.285714f, 0.312243f, 0.339887f, 0.368604f, 0.398329f, 0.428961f, 0.460331f, 0.492064f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000130f, 0.000845f, 0.002376f, 0.004845f, 0.008325f, 0.012864f, 0.018495f,
+ 0.025237f, 0.033105f, 0.042107f, 0.052249f, 0.063534f, 0.075965f, 0.089543f, 0.104269f,
+ 0.120142f, 0.137163f, 0.155330f, 0.174645f, 0.195106f, 0.216710f, 0.239454f, 0.263332f,
+ 0.288336f, 0.314451f, 0.341658f, 0.369924f, 0.399202f, 0.429416f, 0.460447f, 0.492064f,
+ 0.523809f, 0.555555f, 0.587301f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000016f, 0.000391f, 0.001475f, 0.003423f, 0.006322f, 0.010230f, 0.015179f, 0.021195f,
+ 0.028290f, 0.036474f, 0.045752f, 0.056128f, 0.067602f, 0.080176f, 0.093850f, 0.108623f,
+ 0.124496f, 0.141469f, 0.159541f, 0.178713f, 0.198985f, 0.220355f, 0.242823f, 0.266385f,
+ 0.291036f, 0.316767f, 0.343563f, 0.371402f, 0.400248f, 0.430047f, 0.460709f, 0.492079f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000123f, 0.000807f, 0.002272f, 0.004628f, 0.007942f, 0.012253f, 0.017589f, 0.023963f,
+ 0.031387f, 0.039864f, 0.049398f, 0.059990f, 0.071638f, 0.084344f, 0.098106f, 0.112923f,
+ 0.128796f, 0.145725f, 0.163709f, 0.182749f, 0.202847f, 0.224001f, 0.246214f, 0.269482f,
+ 0.293805f, 0.319176f, 0.345587f, 0.373021f, 0.401454f, 0.430844f, 0.461125f, 0.492187f,
+ 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f,
+ 0.000356f, 0.001378f, 0.003225f, 0.005979f, 0.009689f, 0.014384f, 0.020083f, 0.026795f,
+ 0.034525f, 0.043276f, 0.053047f, 0.063839f, 0.075649f, 0.088476f, 0.102320f, 0.117178f,
+ 0.133051f, 0.149939f, 0.167841f, 0.186760f, 0.206696f, 0.227650f, 0.249625f, 0.272620f,
+ 0.296636f, 0.321671f, 0.347718f, 0.374768f, 0.402804f, 0.431796f, 0.461695f, 0.492420f,
+ 0.523822f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f,
+ 0.000725f, 0.002097f, 0.004323f, 0.007463f, 0.011553f, 0.016613f, 0.022655f, 0.029684f,
+ 0.037702f, 0.046708f, 0.056701f, 0.067680f, 0.079640f, 0.092581f, 0.106501f, 0.121397f,
+ 0.137270f, 0.154120f, 0.171946f, 0.190751f, 0.210537f, 0.231305f, 0.253057f, 0.275797f,
+ 0.299525f, 0.324242f, 0.349947f, 0.376633f, 0.404289f, 0.432895f, 0.462415f, 0.492788f,
+ 0.523909f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000005f, 0.000296f,
+ 0.001231f, 0.002960f, 0.005558f, 0.009072f, 0.013526f, 0.018933f, 0.025299f, 0.032627f,
+ 0.040916f, 0.050162f, 0.060364f, 0.071517f, 0.083619f, 0.096666f, 0.110656f, 0.125588f,
+ 0.141461f, 0.158275f, 0.176031f, 0.194730f, 0.214374f, 0.234967f, 0.256512f, 0.279011f,
+ 0.302468f, 0.326887f, 0.352266f, 0.378605f, 0.405897f, 0.434130f, 0.463277f, 0.493295f,
+ 0.524106f, 0.555561f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000068f, 0.000613f,
+ 0.001874f, 0.003958f, 0.006921f, 0.010796f, 0.015599f, 0.021336f, 0.028011f, 0.035623f,
+ 0.044167f, 0.053640f, 0.064038f, 0.075355f, 0.087589f, 0.100736f, 0.114793f, 0.129759f,
+ 0.145632f, 0.162412f, 0.180101f, 0.198700f, 0.218213f, 0.238641f, 0.259989f, 0.282262f,
+ 0.305464f, 0.329599f, 0.354670f, 0.380678f, 0.407622f, 0.435493f, 0.464275f, 0.493938f,
+ 0.524422f, 0.555624f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000223f, 0.001054f,
+ 0.002649f, 0.005086f, 0.008406f, 0.012629f, 0.017766f, 0.023820f, 0.030789f, 0.038669f,
+ 0.047455f, 0.057143f, 0.067726f, 0.079199f, 0.091558f, 0.104798f, 0.118918f, 0.133915f,
+ 0.149788f, 0.166537f, 0.184164f, 0.202669f, 0.222056f, 0.242329f, 0.263492f, 0.285551f,
+ 0.308510f, 0.332376f, 0.357153f, 0.382845f, 0.409454f, 0.436977f, 0.465404f, 0.494713f,
+ 0.524864f, 0.555779f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, 0.000486f, 0.001621f,
+ 0.003553f, 0.006338f, 0.010004f, 0.014565f, 0.020024f, 0.026380f, 0.033629f, 0.041765f,
+ 0.050782f, 0.060673f, 0.071431f, 0.083052f, 0.095529f, 0.108859f, 0.123038f, 0.138065f,
+ 0.153938f, 0.170657f, 0.188224f, 0.206640f, 0.225909f, 0.246035f, 0.267022f, 0.288878f,
+ 0.311607f, 0.335216f, 0.359713f, 0.385103f, 0.411390f, 0.438576f, 0.466656f, 0.495617f,
+ 0.525431f, 0.556041f, 0.587338f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000149f, 0.000861f, 0.002312f,
+ 0.004581f, 0.007709f, 0.011713f, 0.016599f, 0.022367f, 0.029014f, 0.036531f, 0.044912f,
+ 0.054148f, 0.064233f, 0.075158f, 0.086918f, 0.099507f, 0.112922f, 0.127157f, 0.142212f,
+ 0.158085f, 0.174776f, 0.192287f, 0.210619f, 0.229775f, 0.249761f, 0.270582f, 0.292243f,
+ 0.314753f, 0.338118f, 0.362347f, 0.387447f, 0.413424f, 0.440284f, 0.468027f, 0.496645f,
+ 0.526122f, 0.556417f, 0.587451f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000355f, 0.001353f, 0.003126f,
+ 0.005730f, 0.009194f, 0.013526f, 0.018728f, 0.024795f, 0.031720f, 0.039494f, 0.048109f,
+ 0.057555f, 0.067824f, 0.078909f, 0.090802f, 0.103499f, 0.116993f, 0.131282f, 0.146364f,
+ 0.162237f, 0.178902f, 0.196358f, 0.214610f, 0.233660f, 0.253512f, 0.274174f, 0.295650f,
+ 0.317950f, 0.341081f, 0.365053f, 0.389874f, 0.415553f, 0.442098f, 0.469512f, 0.497794f,
+ 0.526935f, 0.556908f, 0.587657f, 0.619060f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000083f, 0.000665f, 0.001962f, 0.004059f,
+ 0.006997f, 0.010790f, 0.015442f, 0.020949f, 0.027304f, 0.034497f, 0.042518f, 0.051358f,
+ 0.061005f, 0.071451f, 0.082688f, 0.094709f, 0.107507f, 0.121078f, 0.135419f, 0.150526f,
+ 0.166399f, 0.183038f, 0.200443f, 0.218618f, 0.237566f, 0.257291f, 0.277800f, 0.299100f,
+ 0.321199f, 0.344106f, 0.367830f, 0.392383f, 0.417774f, 0.444013f, 0.471107f, 0.499060f,
+ 0.527869f, 0.557517f, 0.587966f, 0.619130f, 0.650794f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000233f, 0.001082f, 0.002688f, 0.005111f,
+ 0.008377f, 0.012493f, 0.017456f, 0.023260f, 0.029893f, 0.037345f, 0.045604f, 0.054659f,
+ 0.064499f, 0.075115f, 0.086498f, 0.098641f, 0.111537f, 0.125182f, 0.139571f, 0.154703f,
+ 0.170576f, 0.187190f, 0.204547f, 0.222648f, 0.241498f, 0.261101f, 0.281465f, 0.302595f,
+ 0.324501f, 0.347192f, 0.370679f, 0.394973f, 0.420085f, 0.446027f, 0.472810f, 0.500441f,
+ 0.528921f, 0.558244f, 0.588384f, 0.619281f, 0.650795f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000033f, 0.000477f, 0.001611f, 0.003532f, 0.006280f,
+ 0.009869f, 0.014301f, 0.019568f, 0.025659f, 0.032563f, 0.040265f, 0.048753f, 0.058016f,
+ 0.068042f, 0.078821f, 0.090344f, 0.102604f, 0.115594f, 0.129309f, 0.143745f, 0.158901f,
+ 0.174774f, 0.191365f, 0.208674f, 0.226705f, 0.245461f, 0.264947f, 0.285170f, 0.306137f,
+ 0.327857f, 0.350341f, 0.373598f, 0.397642f, 0.422485f, 0.448139f, 0.474619f, 0.501933f,
+ 0.530089f, 0.559087f, 0.588913f, 0.619525f, 0.650826f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000130f, 0.000821f, 0.002252f, 0.004491f, 0.007562f,
+ 0.011472f, 0.016213f, 0.021776f, 0.028147f, 0.035312f, 0.043256f, 0.051966f, 0.061430f,
+ 0.071635f, 0.082571f, 0.094229f, 0.106602f, 0.119682f, 0.133465f, 0.147947f, 0.163125f,
+ 0.178998f, 0.195566f, 0.212830f, 0.230793f, 0.249459f, 0.268832f, 0.288920f, 0.309730f,
+ 0.331271f, 0.353554f, 0.376590f, 0.400391f, 0.424973f, 0.450347f, 0.476531f, 0.503535f,
+ 0.531372f, 0.560047f, 0.589554f, 0.619869f, 0.650923f, 0.682540f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000005f, 0.000309f, 0.001270f, 0.003008f, 0.005566f, 0.008959f,
+ 0.013183f, 0.018228f, 0.024080f, 0.030723f, 0.038142f, 0.046321f, 0.055246f, 0.064903f,
+ 0.075281f, 0.086369f, 0.098158f, 0.110639f, 0.123806f, 0.137655f, 0.152180f, 0.167380f,
+ 0.183253f, 0.199799f, 0.217020f, 0.234918f, 0.253496f, 0.272761f, 0.292719f, 0.313377f,
+ 0.334745f, 0.356833f, 0.379654f, 0.403221f, 0.427548f, 0.452651f, 0.478545f, 0.505246f,
+ 0.532768f, 0.561122f, 0.590309f, 0.620318f, 0.651102f, 0.682545f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000053f, 0.000579f, 0.001828f, 0.003878f, 0.006757f, 0.010468f,
+ 0.015002f, 0.020344f, 0.026479f, 0.033388f, 0.041054f, 0.049461f, 0.058594f, 0.068440f,
+ 0.078985f, 0.090220f, 0.102134f, 0.114721f, 0.127972f, 0.141884f, 0.156451f, 0.171672f,
+ 0.187545f, 0.204070f, 0.221249f, 0.239083f, 0.257578f, 0.276738f, 0.296569f, 0.317080f,
+ 0.338281f, 0.360181f, 0.382794f, 0.406133f, 0.430213f, 0.455050f, 0.480662f, 0.507065f,
+ 0.534278f, 0.562313f, 0.591180f, 0.620875f, 0.651373f, 0.682593f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000000f, 0.000169f, 0.000949f, 0.002497f, 0.004864f, 0.008063f, 0.012089f,
+ 0.016929f, 0.022563f, 0.028974f, 0.036142f, 0.044049f, 0.052678f, 0.062014f, 0.072042f,
+ 0.082750f, 0.094127f, 0.106164f, 0.118852f, 0.132185f, 0.146157f, 0.160766f, 0.176007f,
+ 0.191880f, 0.208385f, 0.225523f, 0.243296f, 0.261709f, 0.280767f, 0.300476f, 0.320845f,
+ 0.341883f, 0.363601f, 0.386011f, 0.409128f, 0.432967f, 0.457545f, 0.482881f, 0.508992f,
+ 0.535899f, 0.563619f, 0.592165f, 0.621544f, 0.651743f, 0.682709f, 0.714286f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000010f, 0.000368f, 0.001423f, 0.003279f, 0.005966f, 0.009485f, 0.013824f,
+ 0.018964f, 0.024886f, 0.031567f, 0.038988f, 0.047130f, 0.055975f, 0.065508f, 0.075714f,
+ 0.086580f, 0.098095f, 0.110251f, 0.123038f, 0.136450f, 0.150482f, 0.165129f, 0.180390f,
+ 0.196263f, 0.212748f, 0.229847f, 0.247561f, 0.265895f, 0.284854f, 0.304445f, 0.324675f,
+ 0.345555f, 0.367095f, 0.389309f, 0.412210f, 0.435814f, 0.460138f, 0.485203f, 0.511028f,
+ 0.537634f, 0.565041f, 0.593268f, 0.622327f, 0.652217f, 0.682907f, 0.714296f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000068f, 0.000658f, 0.002006f, 0.004178f, 0.007186f, 0.011024f, 0.015672f,
+ 0.021109f, 0.027312f, 0.034259f, 0.041928f, 0.050300f, 0.059356f, 0.069081f, 0.079460f,
+ 0.090480f, 0.102130f, 0.114400f, 0.127284f, 0.140772f, 0.154862f, 0.169548f, 0.184828f,
+ 0.200701f, 0.217167f, 0.234227f, 0.251884f, 0.270141f, 0.289004f, 0.308479f, 0.328575f,
+ 0.349301f, 0.370668f, 0.392689f, 0.415379f, 0.438754f, 0.462830f, 0.487630f, 0.513173f,
+ 0.539482f, 0.566579f, 0.594488f, 0.623226f, 0.652800f, 0.683198f, 0.714354f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000000f, 0.000196f, 0.001048f, 0.002702f, 0.005194f, 0.008526f, 0.012680f, 0.017635f,
+ 0.023365f, 0.029846f, 0.037053f, 0.044965f, 0.053561f, 0.062824f, 0.072737f, 0.083284f,
+ 0.094454f, 0.106236f, 0.118619f, 0.131595f, 0.145159f, 0.159305f, 0.174028f, 0.189327f,
+ 0.205200f, 0.221647f, 0.238670f, 0.256270f, 0.274453f, 0.293222f, 0.312585f, 0.332550f,
+ 0.353126f, 0.374324f, 0.396158f, 0.418641f, 0.441790f, 0.465624f, 0.490163f, 0.515429f,
+ 0.541445f, 0.568236f, 0.595828f, 0.624242f, 0.653496f, 0.683588f, 0.714482f, 0.746032f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000012f, 0.000407f, 0.001545f, 0.003514f, 0.006332f, 0.009987f, 0.014457f, 0.019715f,
+ 0.025734f, 0.032488f, 0.039952f, 0.048102f, 0.056919f, 0.066384f, 0.076480f, 0.087193f,
+ 0.098509f, 0.110419f, 0.122912f, 0.135980f, 0.149617f, 0.163817f, 0.178577f, 0.193894f,
+ 0.209767f, 0.226196f, 0.243182f, 0.260728f, 0.278837f, 0.297515f, 0.316768f, 0.336605f,
+ 0.357034f, 0.378067f, 0.399717f, 0.421998f, 0.444928f, 0.468523f, 0.492806f, 0.517798f,
+ 0.543525f, 0.570012f, 0.597288f, 0.625379f, 0.654307f, 0.684084f, 0.714693f, 0.746044f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000074f, 0.000713f, 0.002152f, 0.004446f, 0.007592f, 0.011571f, 0.016356f, 0.021915f,
+ 0.028220f, 0.035243f, 0.042959f, 0.051344f, 0.060377f, 0.070040f, 0.080316f, 0.091191f,
+ 0.102651f, 0.114686f, 0.127286f, 0.140443f, 0.154151f, 0.168405f, 0.183201f, 0.198536f,
+ 0.214409f, 0.230820f, 0.247770f, 0.265263f, 0.283301f, 0.301889f, 0.321035f, 0.340746f,
+ 0.361032f, 0.381904f, 0.403374f, 0.425457f, 0.448169f, 0.471530f, 0.495561f, 0.520284f,
+ 0.545725f, 0.571911f, 0.598873f, 0.626640f, 0.655239f, 0.684692f, 0.714999f, 0.746106f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f,
+ 0.000208f, 0.001121f, 0.002877f, 0.005501f, 0.008979f, 0.013283f, 0.018380f, 0.024238f,
+ 0.030826f, 0.038115f, 0.046079f, 0.054695f, 0.063941f, 0.073799f, 0.084252f, 0.095285f,
+ 0.106886f, 0.119044f, 0.131749f, 0.144994f, 0.158772f, 0.173078f, 0.187908f, 0.203261f,
+ 0.219134f, 0.235527f, 0.252443f, 0.269883f, 0.287851f, 0.306352f, 0.325393f, 0.344981f,
+ 0.365126f, 0.385839f, 0.407132f, 0.429020f, 0.451520f, 0.474651f, 0.498433f, 0.522890f,
+ 0.548048f, 0.573936f, 0.600584f, 0.628027f, 0.656295f, 0.685417f, 0.715406f, 0.746240f,
+ 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000011f,
+ 0.000427f, 0.001638f, 0.003724f, 0.006685f, 0.010497f, 0.015125f, 0.020534f, 0.026688f,
+ 0.033557f, 0.041109f, 0.049318f, 0.058161f, 0.067617f, 0.077666f, 0.088293f, 0.099482f,
+ 0.111221f, 0.123499f, 0.136308f, 0.149639f, 0.163485f, 0.177843f, 0.192707f, 0.208077f,
+ 0.223950f, 0.240326f, 0.257208f, 0.274596f, 0.292496f, 0.310911f, 0.329849f, 0.349316f,
+ 0.369323f, 0.389880f, 0.410999f, 0.432696f, 0.454987f, 0.477890f, 0.501426f, 0.525620f,
+ 0.550498f, 0.576089f, 0.602427f, 0.629544f, 0.657479f, 0.686264f, 0.715924f, 0.746459f,
+ 0.777789f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000071f,
+ 0.000744f, 0.002274f, 0.004698f, 0.008002f, 0.012149f, 0.017102f, 0.022822f, 0.029271f,
+ 0.036417f, 0.044229f, 0.052681f, 0.061749f, 0.071411f, 0.081649f, 0.092447f, 0.103790f,
+ 0.115665f, 0.128062f, 0.140972f, 0.154387f, 0.168301f, 0.182709f, 0.197608f, 0.212994f,
+ 0.228867f, 0.245227f, 0.262074f, 0.279412f, 0.297244f, 0.315575f, 0.334412f, 0.353760f,
+ 0.373631f, 0.394034f, 0.414983f, 0.436491f, 0.458575f, 0.481253f, 0.504547f, 0.528481f,
+ 0.553081f, 0.578377f, 0.604404f, 0.631197f, 0.658795f, 0.687238f, 0.716559f, 0.746776f,
+ 0.777849f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000205f,
+ 0.001168f, 0.003033f, 0.005806f, 0.009456f, 0.013942f, 0.019220f, 0.025250f, 0.031992f,
+ 0.039414f, 0.047484f, 0.056176f, 0.065466f, 0.075333f, 0.085757f, 0.096724f, 0.108218f,
+ 0.120227f, 0.132741f, 0.145751f, 0.159249f, 0.173230f, 0.187687f, 0.202619f, 0.218021f,
+ 0.233894f, 0.250238f, 0.267052f, 0.284341f, 0.302106f, 0.320354f, 0.339090f, 0.358322f,
+ 0.378059f, 0.398311f, 0.419090f, 0.440412f, 0.462292f, 0.484748f, 0.507802f, 0.531477f,
+ 0.555802f, 0.580805f, 0.606522f, 0.632990f, 0.660250f, 0.688346f, 0.717319f, 0.747200f,
+ 0.777982f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000427f,
+ 0.001710f, 0.003925f, 0.007054f, 0.011055f, 0.015881f, 0.021485f, 0.027824f, 0.034859f,
+ 0.042554f, 0.050881f, 0.059811f, 0.069321f, 0.079390f, 0.089998f, 0.101132f, 0.112775f,
+ 0.124917f, 0.137547f, 0.150655f, 0.164236f, 0.178281f, 0.192788f, 0.207752f, 0.223171f,
+ 0.239044f, 0.255371f, 0.272153f, 0.289393f, 0.307093f, 0.325259f, 0.343896f, 0.363012f,
+ 0.382617f, 0.402719f, 0.423332f, 0.444469f, 0.466146f, 0.488383f, 0.511199f, 0.534618f,
+ 0.558668f, 0.583380f, 0.608787f, 0.634929f, 0.661849f, 0.689594f, 0.718211f, 0.747742f,
+ 0.778205f, 0.809530f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000059f, 0.000754f,
+ 0.002379f, 0.004956f, 0.008449f, 0.012806f, 0.017974f, 0.023905f, 0.030553f, 0.037879f,
+ 0.045847f, 0.054429f, 0.063595f, 0.073323f, 0.083592f, 0.094384f, 0.105682f, 0.117474f,
+ 0.129747f, 0.142491f, 0.155697f, 0.169358f, 0.183469f, 0.198024f, 0.213020f, 0.228455f,
+ 0.244329f, 0.260639f, 0.277389f, 0.294580f, 0.312216f, 0.330300f, 0.348840f, 0.367842f,
+ 0.387315f, 0.407270f, 0.427717f, 0.448671f, 0.470149f, 0.492167f, 0.514746f, 0.537911f,
+ 0.561688f, 0.586108f, 0.611206f, 0.637022f, 0.663599f, 0.690989f, 0.719242f, 0.748411f,
+ 0.778531f, 0.809583f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000187f, 0.001196f,
+ 0.003184f, 0.006136f, 0.010000f, 0.014716f, 0.020230f, 0.026488f, 0.033445f, 0.041062f,
+ 0.049303f, 0.058138f, 0.067540f, 0.077485f, 0.087953f, 0.098926f, 0.110388f, 0.122327f,
+ 0.134729f, 0.147587f, 0.160889f, 0.174631f, 0.188806f, 0.203409f, 0.218437f, 0.233888f,
+ 0.249761f, 0.266056f, 0.282774f, 0.299917f, 0.317488f, 0.335493f, 0.353936f, 0.372825f,
+ 0.392168f, 0.411976f, 0.432259f, 0.453032f, 0.474310f, 0.496111f, 0.518456f, 0.541367f,
+ 0.564872f, 0.589001f, 0.613789f, 0.639277f, 0.665510f, 0.692539f, 0.720422f, 0.749216f,
+ 0.778974f, 0.809711f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000409f, 0.001767f,
+ 0.004137f, 0.007474f, 0.011716f, 0.016797f, 0.022657f, 0.029244f, 0.036512f, 0.044420f,
+ 0.052933f, 0.062021f, 0.071657f, 0.081819f, 0.092485f, 0.103638f, 0.115263f, 0.127348f,
+ 0.139880f, 0.152849f, 0.166248f, 0.180070f, 0.194308f, 0.208958f, 0.224018f, 0.239485f,
+ 0.255359f, 0.271638f, 0.288324f, 0.305419f, 0.322927f, 0.340851f, 0.359199f, 0.377975f,
+ 0.397189f, 0.416851f, 0.436971f, 0.457564f, 0.478644f, 0.500229f, 0.522339f, 0.544997f,
+ 0.568230f, 0.592068f, 0.616546f, 0.641705f, 0.667590f, 0.694255f, 0.721760f, 0.750168f,
+ 0.779545f, 0.809933f, 0.841272f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000041f, 0.000744f, 0.002481f,
+ 0.005248f, 0.008982f, 0.013608f, 0.019058f, 0.025269f, 0.032188f, 0.039767f, 0.047967f,
+ 0.056752f, 0.066093f, 0.075963f, 0.086340f, 0.097203f, 0.108537f, 0.120325f, 0.132554f,
+ 0.145215f, 0.158296f, 0.171790f, 0.185691f, 0.199993f, 0.214691f, 0.229782f, 0.245265f,
+ 0.261138f, 0.277401f, 0.294056f, 0.311104f, 0.328548f, 0.346394f, 0.364645f, 0.383310f,
+ 0.402396f, 0.421912f, 0.441870f, 0.462283f, 0.483165f, 0.504535f, 0.526410f, 0.548816f,
+ 0.571776f, 0.595323f, 0.619489f, 0.644317f, 0.669852f, 0.696148f, 0.723267f, 0.751280f,
+ 0.780258f, 0.810268f, 0.841311f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000156f, 0.001209f, 0.003349f,
+ 0.006531f, 0.010672f, 0.015691f, 0.021515f, 0.028080f, 0.035332f, 0.043225f, 0.051717f,
+ 0.060775f, 0.070370f, 0.080474f, 0.091067f, 0.102128f, 0.113641f, 0.125591f, 0.137965f,
+ 0.150754f, 0.163947f, 0.177537f, 0.191516f, 0.205881f, 0.220626f, 0.235749f, 0.251248f,
+ 0.267121f, 0.283368f, 0.299992f, 0.316992f, 0.334374f, 0.352140f, 0.370296f, 0.388849f,
+ 0.407807f, 0.427178f, 0.446974f, 0.467207f, 0.487892f, 0.509046f, 0.530687f, 0.552839f,
+ 0.575527f, 0.598780f, 0.622634f, 0.647128f, 0.672308f, 0.698231f, 0.724958f, 0.752563f,
+ 0.781127f, 0.810733f, 0.841426f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000374f, 0.001821f, 0.004389f,
+ 0.008001f, 0.012559f, 0.017979f, 0.024182f, 0.031106f, 0.038695f, 0.046903f, 0.055690f,
+ 0.065023f, 0.074872f, 0.085211f, 0.096020f, 0.107279f, 0.118971f, 0.131084f, 0.143604f,
+ 0.156521f, 0.169825f, 0.183510f, 0.197569f, 0.211997f, 0.226789f, 0.241944f, 0.257458f,
+ 0.273331f, 0.289563f, 0.306154f, 0.323108f, 0.340426f, 0.358113f, 0.376175f, 0.394616f,
+ 0.413445f, 0.432671f, 0.452305f, 0.472358f, 0.492845f, 0.513783f, 0.535189f, 0.557087f,
+ 0.579500f, 0.602459f, 0.625997f, 0.650154f, 0.674976f, 0.700518f, 0.726845f, 0.754032f,
+ 0.782167f, 0.811344f, 0.841644f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000719f, 0.002598f, 0.005618f,
+ 0.009675f, 0.014663f, 0.020490f, 0.027080f, 0.034367f, 0.042297f, 0.050824f, 0.059909f,
+ 0.069517f, 0.079622f, 0.090198f, 0.101224f, 0.112682f, 0.124555f, 0.136831f, 0.149496f,
+ 0.162542f, 0.175958f, 0.189739f, 0.203877f, 0.218368f, 0.233208f, 0.248393f, 0.263923f,
+ 0.279796f, 0.296012f, 0.312573f, 0.329479f, 0.346734f, 0.364342f, 0.382307f, 0.400637f,
+ 0.419337f, 0.438418f, 0.457889f, 0.477761f, 0.498050f, 0.518770f, 0.539940f, 0.561581f,
+ 0.583718f, 0.606380f, 0.629599f, 0.653415f, 0.677874f, 0.703030f, 0.728948f, 0.755706f,
+ 0.783396f, 0.812121f, 0.841989f, 0.873035f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000114f, 0.001215f, 0.003561f, 0.007056f,
+ 0.011574f, 0.017003f, 0.023248f, 0.030232f, 0.037888f, 0.046164f, 0.055014f, 0.064399f,
+ 0.074287f, 0.084650f, 0.095464f, 0.106709f, 0.118367f, 0.130423f, 0.142862f, 0.155674f,
+ 0.168849f, 0.182378f, 0.196255f, 0.210473f, 0.225027f, 0.239915f, 0.255132f, 0.270678f,
+ 0.286551f, 0.302751f, 0.319280f, 0.336138f, 0.353330f, 0.370858f, 0.388728f, 0.406944f,
+ 0.425515f, 0.444449f, 0.463756f, 0.483447f, 0.503535f, 0.524036f, 0.544968f, 0.566350f,
+ 0.588208f, 0.610569f, 0.633466f, 0.656936f, 0.681025f, 0.705788f, 0.731289f, 0.757606f,
+ 0.784834f, 0.813085f, 0.842485f, 0.873130f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000324f, 0.001887f, 0.004735f, 0.008727f,
+ 0.013724f, 0.019607f, 0.026280f, 0.033666f, 0.041699f, 0.050326f, 0.059504f, 0.069194f,
+ 0.079365f, 0.089989f, 0.101045f, 0.112512f, 0.124372f, 0.136611f, 0.149216f, 0.162176f,
+ 0.175482f, 0.189125f, 0.203098f, 0.217396f, 0.232015f, 0.246950f, 0.262200f, 0.277761f,
+ 0.293634f, 0.309819f, 0.326315f, 0.343126f, 0.360254f, 0.377701f, 0.395474f, 0.413577f,
+ 0.432018f, 0.450804f, 0.469944f, 0.489451f, 0.509337f, 0.529617f, 0.550307f, 0.571428f,
+ 0.593003f, 0.615059f, 0.637628f, 0.660746f, 0.684460f, 0.708820f, 0.733893f, 0.759756f,
+ 0.786505f, 0.814259f, 0.843157f, 0.873340f, 0.904762f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000683f, 0.002764f, 0.006148f, 0.010661f,
+ 0.016155f, 0.022506f, 0.029620f, 0.037417f, 0.045835f, 0.054821f, 0.064333f, 0.074333f,
+ 0.084792f, 0.095683f, 0.106984f, 0.118675f, 0.130741f, 0.143166f, 0.155939f, 0.169049f,
+ 0.182487f, 0.196245f, 0.210317f, 0.224697f, 0.239380f, 0.254364f, 0.269646f, 0.285223f,
+ 0.301096f, 0.317265f, 0.333729f, 0.350491f, 0.367554f, 0.384920f, 0.402594f, 0.420582f,
+ 0.438891f, 0.457527f, 0.476499f, 0.495820f, 0.515500f, 0.535555f, 0.556000f, 0.576855f,
+ 0.598143f, 0.619888f, 0.642123f, 0.664883f, 0.688211f, 0.712160f, 0.736792f, 0.762186f,
+ 0.788439f, 0.815672f, 0.844034f, 0.873699f, 0.904765f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000066f, 0.001228f, 0.003880f, 0.007835f, 0.012895f,
+ 0.018905f, 0.025742f, 0.033309f, 0.041530f, 0.050342f, 0.059696f, 0.069550f, 0.079868f,
+ 0.090620f, 0.101783f, 0.113333f, 0.125254f, 0.137529f, 0.150144f, 0.163088f, 0.176351f,
+ 0.189924f, 0.203799f, 0.217970f, 0.232433f, 0.247182f, 0.262216f, 0.277530f, 0.293124f,
+ 0.308997f, 0.325149f, 0.341581f, 0.358294f, 0.375290f, 0.392573f, 0.410148f, 0.428019f,
+ 0.446192f, 0.464676f, 0.483478f, 0.502608f, 0.522079f, 0.541905f, 0.562100f, 0.582684f,
+ 0.603677f, 0.625106f, 0.646998f, 0.669390f, 0.692324f, 0.715849f, 0.740028f, 0.764937f,
+ 0.790673f, 0.817358f, 0.845150f, 0.874244f, 0.904828f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.002001f, 0.005278f, 0.009840f, 0.015475f,
+ 0.022025f, 0.029365f, 0.037402f, 0.046060f, 0.055280f, 0.065013f, 0.075218f, 0.085861f,
+ 0.096916f, 0.108356f, 0.120163f, 0.132319f, 0.144808f, 0.157618f, 0.170737f, 0.184155f,
+ 0.197866f, 0.211861f, 0.226134f, 0.240682f, 0.255499f, 0.270583f, 0.285931f, 0.301542f,
+ 0.317415f, 0.333550f, 0.349948f, 0.366610f, 0.383539f, 0.400738f, 0.418210f, 0.435961f,
+ 0.453997f, 0.472324f, 0.490951f, 0.509887f, 0.529144f, 0.548735f, 0.568674f, 0.588979f,
+ 0.609671f, 0.630773f, 0.652314f, 0.674328f, 0.696854f, 0.719942f, 0.743651f, 0.768057f,
+ 0.793253f, 0.819363f, 0.846547f, 0.875017f, 0.905021f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000000f, 0.000642f, 0.003053f, 0.007010f, 0.012219f, 0.018462f,
+ 0.025577f, 0.033444f, 0.041970f, 0.051082f, 0.060724f, 0.070849f, 0.081417f, 0.092397f,
+ 0.103763f, 0.115491f, 0.127562f, 0.139960f, 0.152670f, 0.165679f, 0.178979f, 0.192558f,
+ 0.206410f, 0.220529f, 0.234907f, 0.249542f, 0.264428f, 0.279564f, 0.294947f, 0.310575f,
+ 0.326448f, 0.342566f, 0.358929f, 0.375540f, 0.392399f, 0.409511f, 0.426878f, 0.444506f,
+ 0.462400f, 0.480566f, 0.499013f, 0.517749f, 0.536785f, 0.556134f, 0.575809f, 0.595827f,
+ 0.616207f, 0.636973f, 0.658150f, 0.679772f, 0.701876f, 0.724509f, 0.747730f, 0.771609f,
+ 0.796240f, 0.821743f, 0.848280f, 0.876069f, 0.905404f, 0.936508f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000020f, 0.001278f, 0.004450f, 0.009147f, 0.015050f, 0.021937f,
+ 0.029649f, 0.038068f, 0.047106f, 0.056694f, 0.066777f, 0.077310f, 0.088257f, 0.099588f,
+ 0.111277f, 0.123304f, 0.135650f, 0.148299f, 0.161237f, 0.174455f, 0.187941f, 0.201687f,
+ 0.215687f, 0.229933f, 0.244420f, 0.259145f, 0.274103f, 0.289293f, 0.304711f, 0.320357f,
+ 0.336230f, 0.352330f, 0.368658f, 0.385214f, 0.402002f, 0.419023f, 0.436282f, 0.453782f,
+ 0.471529f, 0.489528f, 0.507788f, 0.526317f, 0.545124f, 0.564221f, 0.583621f, 0.603341f,
+ 0.623397f, 0.643812f, 0.664611f, 0.685824f, 0.707488f, 0.729646f, 0.752354f, 0.775680f,
+ 0.799715f, 0.824574f, 0.850417f, 0.877466f, 0.906040f, 0.936528f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000183f, 0.002253f, 0.006282f, 0.011786f, 0.018436f, 0.026011f,
+ 0.034358f, 0.043364f, 0.052944f, 0.063033f, 0.073580f, 0.084544f, 0.095889f, 0.107588f,
+ 0.119617f, 0.131957f, 0.144591f, 0.157503f, 0.170682f, 0.184117f, 0.197799f, 0.211720f,
+ 0.225873f, 0.240253f, 0.254854f, 0.269673f, 0.284707f, 0.299953f, 0.315408f, 0.331073f,
+ 0.346946f, 0.363028f, 0.379318f, 0.395818f, 0.412530f, 0.429457f, 0.446602f, 0.463968f,
+ 0.481561f, 0.499386f, 0.517450f, 0.535761f, 0.554328f, 0.573162f, 0.592275f, 0.611681f,
+ 0.631398f, 0.651445f, 0.671845f, 0.692628f, 0.713827f, 0.735484f, 0.757650f, 0.780390f,
+ 0.803789f, 0.827960f, 0.853056f, 0.879298f, 0.907014f, 0.936691f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.000617f, 0.003679f, 0.008674f, 0.015068f, 0.022531f, 0.030851f,
+ 0.039880f, 0.049515f, 0.059675f, 0.070300f, 0.081343f, 0.092764f, 0.104533f, 0.116624f,
+ 0.129015f, 0.141687f, 0.154626f, 0.167818f, 0.181252f, 0.194918f, 0.208807f, 0.222913f,
+ 0.237229f, 0.251750f, 0.266473f, 0.281392f, 0.296505f, 0.311811f, 0.327306f, 0.342991f,
+ 0.358864f, 0.374925f, 0.391176f, 0.407616f, 0.424249f, 0.441076f, 0.458100f, 0.475324f,
+ 0.492754f, 0.510394f, 0.528251f, 0.546331f, 0.564644f, 0.583198f, 0.602005f, 0.621078f,
+ 0.640434f, 0.660089f, 0.680066f, 0.700390f, 0.721094f, 0.742215f, 0.763800f, 0.785912f,
+ 0.808628f, 0.832055f, 0.856338f, 0.881690f, 0.908441f, 0.937125f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000000f, 0.001477f, 0.005732f, 0.011826f, 0.019212f, 0.027573f, 0.036710f,
+ 0.046487f, 0.056807f, 0.067598f, 0.078806f, 0.090386f, 0.102304f, 0.114532f, 0.127047f,
+ 0.139828f, 0.152861f, 0.166130f, 0.179624f, 0.193332f, 0.207247f, 0.221360f, 0.235666f,
+ 0.250158f, 0.264832f, 0.279684f, 0.294711f, 0.309911f, 0.325280f, 0.340819f, 0.356524f,
+ 0.372397f, 0.388438f, 0.404645f, 0.421022f, 0.437569f, 0.454287f, 0.471181f, 0.488253f,
+ 0.505507f, 0.522947f, 0.540580f, 0.558412f, 0.576449f, 0.594701f, 0.613178f, 0.631892f,
+ 0.650856f, 0.670088f, 0.689606f, 0.709434f, 0.729600f, 0.750138f, 0.771093f, 0.792519f,
+ 0.814488f, 0.837097f, 0.860481f, 0.884842f, 0.910494f, 0.937985f, 0.968254f, 1.000000f,
+ 0.000000f, 0.000096f, 0.003012f, 0.008704f, 0.016071f, 0.024590f, 0.033968f, 0.044025f,
+ 0.054641f, 0.065728f, 0.077225f, 0.089081f, 0.101260f, 0.113731f, 0.126469f, 0.139454f,
+ 0.152670f, 0.166101f, 0.179736f, 0.193565f, 0.207578f, 0.221769f, 0.236130f, 0.250656f,
+ 0.265343f, 0.280187f, 0.295183f, 0.310330f, 0.325624f, 0.341065f, 0.356650f, 0.372380f,
+ 0.388253f, 0.404269f, 0.420430f, 0.436735f, 0.453187f, 0.469786f, 0.486536f, 0.503439f,
+ 0.520498f, 0.537717f, 0.555102f, 0.572657f, 0.590390f, 0.608307f, 0.626419f, 0.644733f,
+ 0.663264f, 0.682025f, 0.701032f, 0.720308f, 0.739875f, 0.759764f, 0.780014f, 0.800673f,
+ 0.821803f, 0.843492f, 0.865860f, 0.889087f, 0.913466f, 0.939520f, 0.968350f, 1.000000f,
+ 0.000000f, 0.000727f, 0.005696f, 0.013170f, 0.022074f, 0.031940f, 0.042520f, 0.053660f,
+ 0.065258f, 0.077243f, 0.089562f, 0.102175f, 0.115050f, 0.128164f, 0.141495f, 0.155026f,
+ 0.168745f, 0.182639f, 0.196699f, 0.210915f, 0.225282f, 0.239792f, 0.254440f, 0.269223f,
+ 0.284135f, 0.299174f, 0.314337f, 0.329622f, 0.345026f, 0.360549f, 0.376189f, 0.391946f,
+ 0.407819f, 0.423808f, 0.439914f, 0.456137f, 0.472479f, 0.488940f, 0.505523f, 0.522230f,
+ 0.539064f, 0.556028f, 0.573125f, 0.590361f, 0.607741f, 0.625270f, 0.642957f, 0.660809f,
+ 0.678836f, 0.697050f, 0.715465f, 0.734098f, 0.752968f, 0.772101f, 0.791529f, 0.811290f,
+ 0.831438f, 0.852044f, 0.873210f, 0.895090f, 0.917932f, 0.942204f, 0.968981f, 1.000000f,
+ 0.000000f, 0.002796f, 0.010764f, 0.020645f, 0.031576f, 0.043202f, 0.055340f, 0.067877f,
+ 0.080740f, 0.093877f, 0.107250f, 0.120832f, 0.134598f, 0.148533f, 0.162620f, 0.176849f,
+ 0.191210f, 0.205694f, 0.220294f, 0.235005f, 0.249820f, 0.264737f, 0.279751f, 0.294859f,
+ 0.310058f, 0.325346f, 0.340721f, 0.356181f, 0.371725f, 0.387353f, 0.403063f, 0.418854f,
+ 0.434727f, 0.450682f, 0.466718f, 0.482837f, 0.499038f, 0.515324f, 0.531695f, 0.548153f,
+ 0.564700f, 0.581338f, 0.598070f, 0.614900f, 0.631830f, 0.648865f, 0.666011f, 0.683273f,
+ 0.700659f, 0.718176f, 0.735834f, 0.753646f, 0.771625f, 0.789790f, 0.808162f, 0.826771f,
+ 0.845654f, 0.864863f, 0.884472f, 0.904592f, 0.925407f, 0.947271f, 0.971050f, 1.000000f,
+ 0.000000f, 0.015873f, 0.031746f, 0.047619f, 0.063492f, 0.079365f, 0.095238f, 0.111111f,
+ 0.126984f, 0.142857f, 0.158730f, 0.174603f, 0.190476f, 0.206349f, 0.222222f, 0.238095f,
+ 0.253968f, 0.269841f, 0.285714f, 0.301587f, 0.317460f, 0.333333f, 0.349206f, 0.365079f,
+ 0.380952f, 0.396825f, 0.412698f, 0.428571f, 0.444444f, 0.460317f, 0.476190f, 0.492063f,
+ 0.507937f, 0.523810f, 0.539683f, 0.555556f, 0.571429f, 0.587302f, 0.603175f, 0.619048f,
+ 0.634921f, 0.650794f, 0.666667f, 0.682540f, 0.698413f, 0.714286f, 0.730159f, 0.746032f,
+ 0.761905f, 0.777778f, 0.793651f, 0.809524f, 0.825397f, 0.841270f, 0.857143f, 0.873016f,
+ 0.888889f, 0.904762f, 0.920635f, 0.936508f, 0.952381f, 0.968254f, 0.984127f, 1.000000f
+};
+
static float btdf_split_sum_ggx[32][64 * 64] = {
{
0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f,
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index c25ab1e7859..84627e03137 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -28,6 +28,8 @@
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_alloca.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "BKE_particle.h"
#include "BKE_paint.h"
@@ -51,16 +53,18 @@ static struct {
struct GPUShader *default_prepass_sh;
struct GPUShader *default_prepass_clip_sh;
struct GPUShader *default_lit[VAR_MAT_MAX];
-
struct GPUShader *default_background;
+ struct GPUShader *update_noise_sh;
/* 64*64 array texture containing all LUTs and other utilitarian arrays.
* Packing enables us to same precious textures slots. */
struct GPUTexture *util_tex;
+ struct GPUTexture *noise_tex;
unsigned int sss_count;
- float viewvecs[2][4];
+ float alpha_hash_offset;
+ float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
extern char datatoc_lamps_lib_glsl[];
@@ -76,6 +80,7 @@ extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
@@ -87,6 +92,7 @@ extern char datatoc_shadow_geom_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[];
@@ -105,13 +111,9 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
static float samples_ct = 8192.0f;
static float inv_samples_ct = 1.0f / 8192.0f;
- char *lib_str = NULL;
-
- DynStr *ds_vert = BLI_dynstr_new();
- BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
- lib_str = BLI_dynstr_get_cstring(ds_vert);
- BLI_dynstr_free(ds_vert);
+ char *lib_str = BLI_string_joinN(
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl);
struct GPUShader *sh = DRW_shader_create_with_lib(
datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str,
@@ -167,14 +169,10 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
static float a2 = 0.0f;
static float inv_samples_ct = 1.0f / 8192.0f;
- char *frag_str = NULL;
-
- DynStr *ds_vert = BLI_dynstr_new();
- BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_vert, datatoc_btdf_lut_frag_glsl);
- frag_str = BLI_dynstr_get_cstring(ds_vert);
- BLI_dynstr_free(ds_vert);
+ 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"
@@ -352,77 +350,67 @@ static char *eevee_get_volume_defines(int options)
**/
static void add_standard_uniforms(
DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
- int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend, bool use_sss)
+ int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend)
{
- if (ssr_id == NULL || !vedata->stl->g_data->valid_double_buffer) {
+ if (ssr_id == NULL) {
static int no_ssr = -1.0f;
ssr_id = &no_ssr;
}
+
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_int(shgrp, "light_count", &sldata->lamps->num_light, 1);
- DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_render_cube, 1);
- DRW_shgroup_uniform_int(shgrp, "grid_count", &sldata->probes->num_render_grid, 1);
- DRW_shgroup_uniform_int(shgrp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_bool(shgrp, "specToggle", &sldata->probes->specular_toggle, 1);
- DRW_shgroup_uniform_bool(shgrp, "ssrToggle", &sldata->probes->ssr_toggle, 1);
- DRW_shgroup_uniform_float(shgrp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
- DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
- DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
- DRW_shgroup_uniform_int(shgrp, "irradianceVisibilitySize", &sldata->probes->irradiance_vis_size, 1);
- DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
- DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
- DRW_shgroup_uniform_vec2(shgrp, "mipRatio[0]", (float *)vedata->stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(shgrp, "ssrParameters", &vedata->stl->effects->ssr_quality, 1);
-
- if (refract_depth != NULL) {
- DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
+
+ /* TODO if glossy or diffuse bsdf */
+ if (true) {
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
+ DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
+
+ if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
+ }
+ else {
+ /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
+ DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
+ }
}
- if (use_ssrefraction) {
- DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
- DRW_shgroup_uniform_float(shgrp, "borderFadeFactor", &vedata->stl->effects->ssr_border_fac, 1);
- DRW_shgroup_uniform_float(shgrp, "maxRoughness", &vedata->stl->effects->ssr_max_roughness, 1);
- DRW_shgroup_uniform_int(shgrp, "rayCount", &vedata->stl->effects->ssr_ray_count, 1);
+ /* TODO if diffuse bsdf */
+ if (true) {
+ DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
}
- if (vedata->stl->effects->use_ao) {
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons);
- DRW_shgroup_uniform_ivec2(shgrp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1);
+ /* TODO if glossy bsdf */
+ if (true) {
+ DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
}
- else {
- /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &sldata->shadow_pool);
+
+ if (use_ssrefraction) {
+ BLI_assert(refract_depth != NULL);
+ DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
}
- if (vedata->stl->effects->use_volumetrics && use_alpha_blend) {
+ if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 &&
+ use_alpha_blend)
+ {
/* Do not use history buffers as they already have been swapped */
DRW_shgroup_uniform_buffer(shgrp, "inScattering", &vedata->txl->volume_scatter);
DRW_shgroup_uniform_buffer(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
- DRW_shgroup_uniform_vec2(shgrp, "volume_uv_ratio", (float *)sldata->volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(shgrp, "volume_param", (float *)sldata->volumetrics->depth_param, 1);
- }
-
- if (use_sss) {
- DRW_shgroup_uniform_bool(shgrp, "sssToggle", &sldata->probes->sss_toggle, 1);
}
}
static void create_default_shader(int options)
{
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
- BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
- char *frag_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ char *frag_str = BLI_string_joinN(
+ e_data.frag_shader_lib,
+ datatoc_default_frag_glsl);
char *defines = eevee_get_defines(options);
@@ -432,11 +420,13 @@ static void create_default_shader(int options)
MEM_freeN(frag_str);
}
-void EEVEE_update_util_texture(float offset)
+static void eevee_init_noise_texture(void)
{
+ e_data.noise_tex = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, 0, (float *)blue_noise);
+}
- /* TODO: split this into 2 functions : one for init,
- * and the other one that updates the noise with the offset. */
+static void eevee_init_util_texture(void)
+{
const int layers = 3 + 16;
float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels");
float (*texels_layer)[4] = texels;
@@ -451,19 +441,16 @@ void EEVEE_update_util_texture(float offset)
texels_layer[i][0] = bsdf_split_sum_ggx[i * 2 + 0];
texels_layer[i][1] = bsdf_split_sum_ggx[i * 2 + 1];
texels_layer[i][2] = ltc_mag_ggx[i];
+ texels_layer[i][3] = ltc_disk_integral[i];
}
texels_layer += 64 * 64;
/* Copy blue noise in 3rd layer */
for (int i = 0; i < 64 * 64; i++) {
- float noise;
- noise = fmod(blue_noise[i][0] + offset, 1.0f);
- texels_layer[i][0] = noise;
-
- noise = fmod(blue_noise[i][1] + offset, 1.0f);
- texels_layer[i][1] = noise * 0.5f + 0.5f;
- texels_layer[i][2] = cosf(noise * 2.0f * M_PI);
- texels_layer[i][3] = sinf(noise * 2.0f * M_PI);
+ texels_layer[i][0] = blue_noise[i][0];
+ texels_layer[i][1] = blue_noise[i][1];
+ texels_layer[i][2] = cosf(blue_noise[i][1] * 2.0f * M_PI);
+ texels_layer[i][3] = sinf(blue_noise[i][1] * 2.0f * M_PI);
}
texels_layer += 64 * 64;
@@ -478,62 +465,72 @@ void EEVEE_update_util_texture(float offset)
texels_layer += 64 * 64;
}
- if (e_data.util_tex == NULL) {
- e_data.util_tex = DRW_texture_create_2D_array(
- 64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels);
- }
- else {
- DRW_texture_update(e_data.util_tex, (float *)texels);
- }
+ e_data.util_tex = DRW_texture_create_2D_array(
+ 64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels);
MEM_freeN(texels);
}
-void EEVEE_materials_init(EEVEE_StorageList *stl)
+void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3])
+{
+ e_data.noise_offsets[0] = offsets[0];
+ e_data.noise_offsets[1] = offsets[1];
+ e_data.noise_offsets[2] = offsets[2];
+
+ /* Attach & detach because we don't currently support multiple FB per texture,
+ * and this would be the case for multiple viewport. */
+ DRW_framebuffer_texture_layer_attach(fbl->update_noise_fb, e_data.util_tex, 0, 2, 0);
+ DRW_framebuffer_bind(fbl->update_noise_fb);
+ DRW_draw_pass(psl->update_noise_pass);
+ DRW_framebuffer_texture_detach(e_data.util_tex);
+}
+
+void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl)
{
if (!e_data.frag_shader_lib) {
char *frag_str = NULL;
/* Shaders */
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ssr_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
- for (int i = 0; i < 7; ++i) {
- /* Add one for each Closure */
- BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
- }
- BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
- e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl);
- e_data.volume_shader_lib = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
- BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
- frag_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ e_data.frag_shader_lib = BLI_string_joinN(
+ 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_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_bsdf_direct_lib_glsl,
+ datatoc_lamps_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_volumetric_lib_glsl);
+
+ e_data.volume_shader_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_bsdf_direct_lib_glsl,
+ datatoc_lamps_lib_glsl,
+ datatoc_volumetric_lib_glsl,
+ datatoc_volumetric_frag_glsl);
+
+ frag_str = BLI_string_joinN(
+ e_data.frag_shader_lib,
+ datatoc_default_frag_glsl);
e_data.default_background = DRW_shader_create(
datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl,
@@ -549,16 +546,32 @@ void EEVEE_materials_init(EEVEE_StorageList *stl)
MEM_freeN(frag_str);
- EEVEE_update_util_texture(0.0f);
+ e_data.update_noise_sh = DRW_shader_create_fullscreen(
+ datatoc_update_noise_frag_glsl, NULL);
+
+ eevee_init_util_texture();
+ eevee_init_noise_texture();
}
+ /* Alpha hash scale: Non-flickering size if we are not refining the render. */
+ if (!DRW_state_is_image_render() &&
+ (((stl->effects->enabled_effects & EFFECT_TAA) == 0) ||
+ (stl->effects->taa_current_sample == 1)))
{
- /* Update viewvecs */
- const bool is_persp = DRW_viewport_is_persp_get();
+ e_data.alpha_hash_offset = 0.0f;
+ }
+ else {
+ double r;
+ BLI_halton_1D(5, 0.0, stl->effects->taa_current_sample, &r);
+ e_data.alpha_hash_offset = (float)r;
+ }
+
+ {
+ /* Update view_vecs */
float invproj[4][4], winmat[4][4];
/* view vectors for the corners of the view frustum.
* Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
+ float view_vecs[3][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}
@@ -567,31 +580,39 @@ void EEVEE_materials_init(EEVEE_StorageList *stl)
/* invert the view matrix */
DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
invert_m4_m4(invproj, winmat);
+ const bool is_persp = (winmat[3][3] == 0.0f);
/* convert the view vectors to view space */
for (int i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
+ mul_m4_v4(invproj, view_vecs[i]);
/* normalized trick see:
* http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][3]);
if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
+ mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][2]);
+ view_vecs[i][3] = 1.0;
}
- copy_v4_v4(stl->g_data->viewvecs[0], viewvecs[0]);
- copy_v4_v4(stl->g_data->viewvecs[1], viewvecs[1]);
+ copy_v4_v4(sldata->common_data.view_vecs[0], view_vecs[0]);
+ copy_v4_v4(sldata->common_data.view_vecs[1], view_vecs[1]);
/* we need to store the differences */
- stl->g_data->viewvecs[1][0] -= viewvecs[0][0];
- stl->g_data->viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+ sldata->common_data.view_vecs[1][0] -= view_vecs[0][0];
+ sldata->common_data.view_vecs[1][1] = view_vecs[2][1] - view_vecs[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]);
- stl->g_data->viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+ sldata->common_data.view_vecs[1][2] = vec_far[2] - view_vecs[0][2];
+ }
+ }
+
+ {
+ /* Update noise Framebuffer. */
+ if (fbl->update_noise_fb == NULL) {
+ fbl->update_noise_fb = DRW_framebuffer_create();
}
}
}
@@ -652,6 +673,7 @@ struct GPUMaterial *EEVEE_material_mesh_get(
struct Scene *scene, Material *ma, EEVEE_Data *vedata,
bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
@@ -659,9 +681,9 @@ struct GPUMaterial *EEVEE_material_mesh_get(
if (use_multiply) options |= VAR_MAT_MULT;
if (use_refract) options |= VAR_MAT_REFRACT;
if (use_sss) options |= VAR_MAT_SSS;
- if (use_sss && vedata->stl->effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED;
+ if (use_sss && effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED;
if (use_translucency) options |= VAR_MAT_TRANSLUC;
- if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+ if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME;
options |= eevee_material_shadow_option(shadow_method);
@@ -728,11 +750,9 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(
char *defines = eevee_get_defines(options);
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
- BLI_dynstr_append(ds_frag, datatoc_prepass_frag_glsl);
- char *frag_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ char *frag_str = BLI_string_joinN(
+ e_data.frag_shader_lib,
+ datatoc_prepass_frag_glsl);
mat = GPU_material_from_nodetree(
scene, ma->nodetree, &ma->gpumaterial, engine, options,
@@ -779,6 +799,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass,
bool is_hair, bool is_flat_normal, bool use_blend, bool use_ssr, int shadow_method)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
static int ssr_id;
ssr_id = (use_ssr) ? 1 : -1;
int options = VAR_MAT_MESH;
@@ -786,7 +807,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
if (is_hair) options |= VAR_MAT_HAIR;
if (is_flat_normal) options |= VAR_MAT_FLAT;
if (use_blend) options |= VAR_MAT_BLEND;
- if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME;
+ if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME;
options |= eevee_material_shadow_option(shadow_method);
@@ -795,7 +816,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
}
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend);
return shgrp;
}
@@ -825,7 +846,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false);
}
return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
@@ -836,19 +857,6 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- {
- const DRWContextState *draw_ctx = DRW_context_state_get();
- ViewLayer *view_layer = draw_ctx->view_layer;
- IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
- /* Global AO Switch*/
- stl->effects->use_ao = BKE_collection_engine_property_value_get_bool(props, "gtao_enable");
- stl->effects->use_bent_normals = BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals");
- /* SSR switch */
- stl->effects->use_ssr = BKE_collection_engine_property_value_get_bool(props, "ssr_enable");
- /* Volumetrics */
- stl->effects->use_volumetrics = BKE_collection_engine_property_value_get_bool(props, "volumetric_enable");
- }
-
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
@@ -951,6 +959,15 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE;
psl->transparent_pass = DRW_pass_create("Material Transparent Pass", state);
}
+
+ {
+ psl->update_noise_pass = DRW_pass_create("Update Noise Pass", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
+ DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
+ DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
+ DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ }
+
}
#define ADD_SHGROUP_CALL(shgrp, ob, geom) do { \
@@ -979,6 +996,7 @@ static void material_opaque(
bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth,
struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth, struct DRWShadingGroup **shgrp_depth_clip)
{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -991,9 +1009,11 @@ static void material_opaque(
float *rough_p = &ma->gloss_mir;
const bool use_gpumat = (ma->use_nodes && ma->nodetree);
- const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
- const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0);
+ const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
+ const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) &&
+ ((effects->enabled_effects & EFFECT_SSS) != 0);
+ const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -1021,8 +1041,8 @@ static void material_opaque(
if (*shgrp) {
static int no_ssr = -1;
static int first_ssr = 1;
- int *ssr_id = (stl->effects->use_ssr && !use_refract) ? &first_ssr : &no_ssr;
- add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false, use_sss);
+ int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr;
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false);
if (use_sss) {
struct GPUTexture *sss_tex_profile = NULL;
@@ -1037,7 +1057,7 @@ static void material_opaque(
}
DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1);
- EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile);
+ EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile);
e_data.sss_count++;
}
}
@@ -1067,19 +1087,24 @@ static void material_opaque(
}
if (*shgrp_depth != NULL) {
- add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false, false);
+ add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false);
if (ma->blend_method == MA_BM_CLIP) {
DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1);
DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1);
}
+ else if (ma->blend_method == MA_BM_HASHED) {
+ DRW_shgroup_uniform_float(*shgrp_depth, "hashAlphaOffset", &e_data.alpha_hash_offset, 1);
+ DRW_shgroup_uniform_float(*shgrp_depth_clip, "hashAlphaOffset", &e_data.alpha_hash_offset, 1);
+ }
}
}
}
/* Fallback to default shader */
if (*shgrp == NULL) {
- *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, stl->effects->use_ssr, linfo->shadow_method);
+ bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
+ *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, use_ssr, linfo->shadow_method);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1131,7 +1156,7 @@ static void material_transparent(
if (*shgrp) {
static int ssr_id = -1; /* TODO transparent SSR */
bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0;
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend, false);
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend);
}
else {
/* Shader failed : pink color */
@@ -1217,7 +1242,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
const bool is_default_mode_shader = is_sculpt_mode;
/* First get materials for this mesh. */
- if (ELEM(ob->type, OB_MESH)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol));
struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len);
@@ -1335,7 +1360,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
}
/* Volumetrics */
- if (vedata->stl->effects->use_volumetrics && use_volume_material) {
+ if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) {
EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
}
}
@@ -1383,7 +1408,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
if (shgrp) {
- add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false, false);
+ add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false);
BLI_ghash_insert(material_hash, ma, shgrp);
@@ -1401,7 +1426,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld
/* Fallback to default shader */
if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, stl->effects->use_ssr, sldata->lamps->shadow_method);
+ bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, use_ssr,
+ sldata->lamps->shadow_method);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
@@ -1438,7 +1465,9 @@ void EEVEE_materials_free(void)
DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
+ DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
}
void EEVEE_draw_default_passes(EEVEE_PassList *psl)
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index d5e0a05f9ed..037bbe3b6c9 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -40,6 +40,7 @@
#include "ED_screen.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "eevee_private.h"
#include "GPU_texture.h"
@@ -52,7 +53,11 @@ static struct {
extern char datatoc_effect_motion_blur_frag_glsl[];
static void eevee_motion_blur_camera_get_matrix_at_time(
- const bContext *C, Scene *scene, ARegion *ar, RegionView3D *rv3d, View3D *v3d, Object *camera, float time, float r_mat[4][4])
+ Scene *scene,
+ ARegion *ar, RegionView3D *rv3d, View3D *v3d,
+ Object *camera,
+ float time,
+ float r_mat[4][4])
{
EvaluationContext eval_ctx;
float obmat[4][4];
@@ -63,7 +68,19 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
memcpy(&camdata_cpy, camera->data, sizeof(camdata_cpy));
cam_cpy.data = &camdata_cpy;
- CTX_data_eval_ctx(C, &eval_ctx);
+ /* NOTE: Mode corresponds to old usage of eval_ctx from viewport (which was
+ * actually coming from bmain). It was always DAG_EVAL_VIEWPORT. For F12
+ * render this should be DAG_EVAL_RENDER, but the whole hack is to be
+ * reconsidered first anyway.
+ */
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ DEG_evaluation_context_init_from_scene(
+ &eval_ctx,
+ scene,
+ draw_ctx->view_layer,
+ draw_ctx->engine_type,
+ DAG_EVAL_VIEWPORT);
+ eval_ctx.ctime = time;
/* Past matrix */
/* FIXME : This is a temporal solution that does not take care of parent animations */
@@ -76,27 +93,15 @@ static void eevee_motion_blur_camera_get_matrix_at_time(
CameraParams params;
BKE_camera_params_init(&params);
- /* copy of BKE_camera_params_from_view3d */
- {
- params.lens = v3d->lens;
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
-
- /* camera view */
+ if (v3d != NULL) {
+ BKE_camera_params_from_view3d(&params, draw_ctx->depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ }
+ else {
BKE_camera_params_from_object(&params, &cam_cpy);
-
- params.zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
-
- params.offsetx = 2.0f * rv3d->camdx * params.zoom;
- params.offsety = 2.0f * rv3d->camdy * params.zoom;
-
- params.shiftx *= params.zoom;
- params.shifty *= params.zoom;
-
- params.zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params.zoom;
+ BKE_camera_params_compute_viewplane(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
- BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
BKE_camera_params_compute_matrix(&params);
/* FIXME Should be done per view (MULTIVIEW) */
@@ -110,7 +115,7 @@ static void eevee_create_shader_motion_blur(void)
e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
}
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
@@ -121,34 +126,51 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
View3D *v3d = draw_ctx->v3d;
RegionView3D *rv3d = draw_ctx->rv3d;
ARegion *ar = draw_ctx->ar;
- IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer,
+ COLLECTION_MODE_NONE,
+ RE_engine_id_BLENDER_EEVEE);
- if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable") && (draw_ctx->evil_C != NULL)) {
+ if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable")) {
/* Update Motion Blur Matrices */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (camera) {
float persmat[4][4];
float ctime = BKE_scene_frame_get(scene);
float delta = BKE_collection_engine_property_value_get_float(props, "motion_blur_shutter");
+ Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, camera);
/* Current matrix */
- eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime, effects->current_ndc_to_world);
+ eevee_motion_blur_camera_get_matrix_at_time(scene,
+ ar, rv3d, v3d,
+ camera_object,
+ ctime,
+ effects->current_ndc_to_world);
/* Viewport Matrix */
DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
/* Only continue if camera is not being keyed */
- if (compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f)) {
-
+ if (DRW_state_is_image_render() ||
+ compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f))
+ {
/* Past matrix */
- eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime - delta, effects->past_world_to_ndc);
+ eevee_motion_blur_camera_get_matrix_at_time(scene,
+ ar, rv3d, v3d,
+ camera_object,
+ ctime - delta,
+ effects->past_world_to_ndc);
#if 0 /* for future high quality blur */
/* Future matrix */
- eevee_motion_blur_camera_get_matrix_at_time(scene, ar, rv3d, v3d, v3d->camera, ctime + delta, effects->future_world_to_ndc);
+ eevee_motion_blur_camera_get_matrix_at_time(scene,
+ ar, rv3d, v3d,
+ camera_object,
+ ctime + delta,
+ effects->future_world_to_ndc);
#endif
invert_m4(effects->current_ndc_to_world);
- effects->motion_blur_samples = BKE_collection_engine_property_value_get_int(props, "motion_blur_samples");
+ effects->motion_blur_samples = BKE_collection_engine_property_value_get_int(props,
+ "motion_blur_samples");
if (!e_data.motion_blur_sh) {
eevee_create_shader_motion_blur();
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index c1dde385284..9da438e825f 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -27,7 +27,7 @@
#include "DRW_render.h"
-#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "DNA_anim_types.h"
@@ -38,38 +38,43 @@
static struct {
/* Ground Truth Ambient Occlusion */
struct GPUShader *gtao_sh;
+ struct GPUShader *gtao_layer_sh;
struct GPUShader *gtao_debug_sh;
+ struct GPUTexture *src_depth;
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_effect_gtao_frag_glsl[];
static void eevee_create_shader_occlusion(void)
{
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_effect_gtao_frag_glsl);
- char *frag_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ char *frag_str = BLI_string_joinN(
+ 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);
}
-int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
- EEVEE_EffectsInfo *effects = stl->effects;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
- IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer,
+ COLLECTION_MODE_NONE,
+ RE_engine_id_BLENDER_EEVEE);
if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) {
const float *viewport_size = DRW_viewport_size_get();
@@ -79,48 +84,24 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata
eevee_create_shader_occlusion();
}
- effects->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
- effects->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor");
- effects->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality");
- effects->ao_samples = BKE_collection_engine_property_value_get_int(props, "gtao_samples");
- effects->ao_samples_inv = 1.0f / effects->ao_samples;
+ common_data->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
+ common_data->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor");
+ common_data->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality");
- effects->ao_settings = 1.0; /* USE_AO */
+ common_data->ao_settings = 1.0; /* USE_AO */
if (BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals")) {
- effects->ao_settings += 2.0; /* USE_BENT_NORMAL */
+ common_data->ao_settings += 2.0; /* USE_BENT_NORMAL */
}
if (BKE_collection_engine_property_value_get_bool(props, "gtao_denoise")) {
- effects->ao_settings += 4.0; /* USE_DENOISE */
- }
-
- effects->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
-
- effects->ao_texsize[0] = ((int)viewport_size[0]);
- effects->ao_texsize[1] = ((int)viewport_size[1]);
-
- /* Round up to multiple of 2 */
- if ((effects->ao_texsize[0] & 0x1) != 0) {
- effects->ao_texsize[0] += 1;
+ common_data->ao_settings += 4.0; /* USE_DENOISE */
}
- if ((effects->ao_texsize[1] & 0x1) != 0) {
- effects->ao_texsize[1] += 1;
- }
-
- CLAMP(effects->ao_samples, 1, 32);
- if (effects->hori_tex_layers != effects->ao_samples) {
- DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
- }
-
- if (txl->gtao_horizons == NULL) {
- effects->hori_tex_layers = effects->ao_samples;
- txl->gtao_horizons = DRW_texture_create_2D_array((int)viewport_size[0], (int)viewport_size[1], effects->hori_tex_layers, DRW_TEX_RG_8, 0, NULL);
- }
+ common_data->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce");
- DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RG_8, 0};
+ DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RGBA_8, 0};
DRW_framebuffer_init(&fbl->gtao_fb, &draw_engine_eevee_type,
- effects->ao_texsize[0], effects->ao_texsize[1],
+ (int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
if (G.debug_value == 6) {
@@ -137,12 +118,12 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata
/* Cleanup */
DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
- effects->ao_settings = 0.0f;
+ common_data->ao_settings = 0.0f;
return 0;
}
-void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
@@ -166,51 +147,54 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
**/
psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_float(grp, "sampleNbr", &stl->effects->ao_sample_nbr, 1);
- DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1);
+ DRW_shgroup_uniform_buffer(grp, "depthBuffer", &effects->ao_src_depth);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
+ DRW_shgroup_uniform_buffer(grp, "depthBufferLayered", &effects->ao_src_depth);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call_add(grp, quad, NULL);
if (G.debug_value == 6) {
psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2);
- DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, quad, NULL);
}
}
}
-void EEVEE_occlusion_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+void EEVEE_occlusion_compute(
+ EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_stats_group_start("GTAO Horizon Scan");
- for (effects->ao_sample_nbr = 0.0;
- effects->ao_sample_nbr < effects->ao_samples;
- ++effects->ao_sample_nbr)
- {
- DRW_framebuffer_texture_detach(txl->gtao_horizons);
- DRW_framebuffer_texture_layer_attach(fbl->gtao_fb, txl->gtao_horizons, 0, (int)effects->ao_sample_nbr, 0);
- DRW_framebuffer_bind(fbl->gtao_fb);
+ effects->ao_src_depth = depth_src;
+ effects->ao_depth_layer = layer;
+ DRW_framebuffer_bind(fbl->gtao_fb);
+
+ if (layer >= 0) {
+ DRW_draw_pass(psl->ao_horizon_search_layer);
+ }
+ else {
DRW_draw_pass(psl->ao_horizon_search);
}
@@ -247,5 +231,6 @@ void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
void EEVEE_occlusion_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.gtao_sh);
+ DRW_SHADER_FREE_SAFE(e_data.gtao_layer_sh);
DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh);
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 98fc6d6a6e4..218de6ddd88 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -27,6 +27,8 @@
#define __EEVEE_PRIVATE_H__
struct Object;
+struct EEVEE_BoundSphere;
+struct EEVEE_ShadowCasterBuffer;
extern struct DrawEngineType draw_engine_eevee_type;
@@ -127,6 +129,14 @@ enum {
SHADOW_METHOD_MAX = 3,
};
+typedef struct EEVEE_BoundSphere {
+ float center[3], radius;
+} EEVEE_BoundSphere;
+
+typedef struct EEVEE_BoundBox {
+ float center[3], halfdim[3];
+} EEVEE_BoundBox;
+
typedef struct EEVEE_PassList {
/* Shadows */
struct DRWPass *shadow_pass;
@@ -148,6 +158,7 @@ typedef struct EEVEE_PassList {
/* Effects */
struct DRWPass *ao_horizon_search;
+ struct DRWPass *ao_horizon_search_layer;
struct DRWPass *ao_horizon_debug;
struct DRWPass *motion_blur;
struct DRWPass *bloom_blit;
@@ -195,6 +206,7 @@ typedef struct EEVEE_PassList {
struct DRWPass *refract_pass;
struct DRWPass *transparent_pass;
struct DRWPass *background_pass;
+ struct DRWPass *update_noise_pass;
} EEVEE_PassList;
typedef struct EEVEE_FramebufferList {
@@ -217,6 +229,8 @@ typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *screen_tracing_fb;
struct GPUFrameBuffer *refract_fb;
+ struct GPUFrameBuffer *update_noise_fb;
+
struct GPUFrameBuffer *planarref_fb;
struct GPUFrameBuffer *main;
@@ -237,6 +251,7 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */
struct GPUTexture *ssr_normal_input;
struct GPUTexture *ssr_specrough_input;
+ struct GPUTexture *ssr_hit_output;
struct GPUTexture *refract_color;
struct GPUTexture *volume_prop_scattering;
@@ -310,17 +325,23 @@ typedef struct EEVEE_ShadowRender {
float shadow_inv_samples_ct;
} EEVEE_ShadowRender;
-/* ************ VOLUME DATA ************ */
-typedef struct EEVEE_VolumetricsInfo {
- float integration_step_count, shadow_step_count, sample_distribution, light_clamp;
- float integration_start, integration_end;
- float depth_param[3], history_alpha;
- bool use_lights, use_volume_shadows;
- int froxel_tex_size[3];
- float inv_tex_size[3];
- float volume_coord_scale[2];
- float jitter[3];
-} EEVEE_VolumetricsInfo;
+/* This is just a really long bitflag with special function to access it. */
+#define MAX_LIGHTBITS_FIELDS (MAX_LIGHT / 8)
+typedef struct EEVEE_LightBits {
+ unsigned char fields[MAX_LIGHTBITS_FIELDS];
+} EEVEE_LightBits;
+
+typedef struct EEVEE_ShadowCaster {
+ struct EEVEE_LightBits bits;
+ struct EEVEE_BoundBox bbox;
+} EEVEE_ShadowCaster;
+
+typedef struct EEVEE_ShadowCasterBuffer {
+ struct EEVEE_ShadowCaster *shadow_casters;
+ char *flags;
+ unsigned int alloc_count;
+ unsigned int count;
+} EEVEE_ShadowCasterBuffer;
/* ************ LIGHT DATA ************* */
typedef struct EEVEE_LampsInfo {
@@ -346,8 +367,20 @@ typedef struct EEVEE_LampsInfo {
struct EEVEE_Shadow shadow_data[MAX_SHADOW];
struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE];
struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
+ /* Lights tracking */
+ int new_shadow_id[MAX_LIGHT]; /* To be able to convert old bitfield to new bitfield */
+ struct EEVEE_BoundSphere shadow_bounds[MAX_LIGHT]; /* Tighly packed light bounds */
+ /* Pointers only. */
+ struct EEVEE_ShadowCasterBuffer *shcaster_frontbuffer;
+ struct EEVEE_ShadowCasterBuffer *shcaster_backbuffer;
} EEVEE_LampsInfo;
+/* EEVEE_LampsInfo->shadow_casters_flag */
+enum {
+ SHADOW_CASTER_PRUNED = (1 << 0),
+ SHADOW_CASTER_UPDATED = (1 << 1),
+};
+
/* EEVEE_LampsInfo->update_flag */
enum {
LIGHT_UPDATE_SHADOW_CUBE = (1 << 0),
@@ -395,11 +428,9 @@ typedef struct EEVEE_LightProbesInfo {
int num_bounce;
int cubemap_res;
int target_size;
- int irradiance_vis_size;
int grid_initialized;
- /* Actual number of probes that have datas. */
- int num_render_cube;
- int num_render_grid;
+ struct World *prev_world;
+ bool do_cube_update;
/* For rendering probes */
float probemat[6][4][4];
int layer;
@@ -414,11 +445,8 @@ typedef struct EEVEE_LightProbesInfo {
float lod_rt_max, lod_cube_max, lod_planar_max;
float visibility_range;
float visibility_blur;
+ float intensity_fac;
int shres;
- int shnbr;
- bool specular_toggle;
- bool ssr_toggle;
- bool sss_toggle;
/* List of probes in the scene. */
/* XXX This is fragile, can get out of sync quickly. */
struct Object *probes_cube_ref[MAX_PROBE];
@@ -441,30 +469,18 @@ enum {
typedef struct EEVEE_EffectsInfo {
int enabled_effects;
bool swap_double_buffer;
-
/* SSSS */
int sss_sample_count;
- float sss_jitter_threshold;
bool sss_separate_albedo;
-
/* Volumetrics */
- bool use_volumetrics;
int volume_current_sample;
-
/* SSR */
- bool use_ssr;
bool reflection_trace_full;
- bool ssr_use_normalization;
- int ssr_ray_count;
- float ssr_firefly_fac;
- float ssr_border_fac;
- float ssr_max_roughness;
- float ssr_quality;
- float ssr_thickness;
- float ssr_pixelsize[2];
-
+ int ssr_neighbor_ofs;
+ int ssr_halfres_ofs[2];
/* Temporal Anti Aliasing */
int taa_current_sample;
+ int taa_render_sample;
int taa_total_sample;
float taa_alpha;
bool prev_drw_support;
@@ -473,27 +489,19 @@ typedef struct EEVEE_EffectsInfo {
float overide_persinv[4][4];
float overide_winmat[4][4];
float overide_wininv[4][4];
-
/* Ambient Occlusion */
- bool use_ao, use_bent_normals;
- float ao_dist, ao_samples, ao_factor, ao_samples_inv;
- float ao_offset, ao_bounce_fac, ao_quality, ao_settings;
- float ao_sample_nbr;
- int ao_texsize[2], hori_tex_layers;
-
+ int ao_depth_layer;
+ struct GPUTexture *ao_src_depth; /* pointer copy */
/* Motion Blur */
float current_ndc_to_world[4][4];
float past_world_to_ndc[4][4];
- float tmp_mat[4][4];
int motion_blur_samples;
-
/* Depth Of Field */
float dof_near_far[2];
float dof_params[3];
float dof_bokeh[4];
float dof_layer_select[2];
int dof_target_size[2];
-
/* Bloom */
int bloom_iteration_ct;
float source_texel_size[2];
@@ -506,10 +514,11 @@ typedef struct EEVEE_EffectsInfo {
float unf_source_texel_size[2];
struct GPUTexture *unf_source_buffer; /* pointer copy */
struct GPUTexture *unf_base_buffer; /* pointer copy */
-
/* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */
struct GPUTexture *source_buffer; /* latest updated texture */
struct GPUFrameBuffer *target_buffer; /* next target to render to */
+ struct GPUTexture *final_tx; /* Final color to transform to display color space. */
+ struct GPUFrameBuffer *final_fb; /* Framebuffer with final_tx as attachement. */
} EEVEE_EffectsInfo;
enum {
@@ -527,6 +536,58 @@ enum {
EFFECT_SSS = (1 << 11),
};
+/* ***************** COMMON DATA **************** */
+
+/* Common uniform buffer containing all "constant" data over the whole drawing pipeline. */
+/* !! CAUTION !!
+ * - [i]vec3 need to be paded to [i]vec4 (even in ubo declaration).
+ * - Make sure that [i]vec4 start at a multiple of 16 bytes.
+ * - Arrays of vec2/vec3 are padded as arrays of vec4.
+ * - 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 -- */
+ float ao_dist, pad1, ao_factor, pad2; /* vec4 */
+ float ao_offset, ao_bounce_fac, ao_quality, ao_settings; /* vec4 */
+ /* Volumetric */
+ /* -- 16 byte aligned -- */
+ int vol_tex_size[3], pad3; /* ivec3 */
+ float vol_depth_param[3], pad4; /* vec3 */
+ float vol_inv_tex_size[3], pad5; /* vec3 */
+ float vol_jitter[3], pad6; /* vec3 */
+ float vol_coord_scale[2], pad7[2]; /* vec2 */
+ /* -- 16 byte aligned -- */
+ float vol_history_alpha; /* float */
+ float vol_light_clamp; /* float */
+ float vol_shadow_steps; /* float */
+ int vol_use_lights; /* bool */
+ /* Screen Space Reflections */
+ /* -- 16 byte aligned -- */
+ float ssr_quality, ssr_thickness, ssr_pixelsize[2]; /* vec4 */
+ float ssr_border_fac; /* float */
+ float ssr_max_roughness; /* float */
+ float ssr_firefly_fac; /* float */
+ float ssr_brdf_bias; /* float */
+ int ssr_toggle; /* bool */
+ /* SubSurface Scattering */
+ float sss_jitter_threshold; /* float */
+ int sss_toggle; /* bool */
+ /* Specular */
+ int spec_toggle; /* bool */
+ /* Lamps */
+ int la_num_light; /* int */
+ /* Probes */
+ int prb_num_planar; /* int */
+ int prb_num_render_cube; /* int */
+ int prb_num_render_grid; /* int */
+ int prb_irradiance_vis_size; /* int */
+ float prb_lod_cube_max; /* float */
+ float prb_lod_planar_max; /* float */
+} EEVEE_CommonUniformBuffer;
+
/* ************** SCENE LAYER DATA ************** */
typedef struct EEVEE_ViewLayerData {
/* Lamps */
@@ -546,7 +607,7 @@ typedef struct EEVEE_ViewLayerData {
struct GPUTexture *shadow_cascade_blur;
struct GPUTexture *shadow_pool;
- struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */
+ struct EEVEE_ShadowCasterBuffer shcasters_buffers[2];
/* Probes */
struct EEVEE_LightProbesInfo *probes;
@@ -564,20 +625,45 @@ typedef struct EEVEE_ViewLayerData {
struct GPUTexture *irradiance_pool;
struct GPUTexture *irradiance_rt;
- struct ListBase probe_queue; /* List of probes to update */
-
- /* Volumetrics */
- struct EEVEE_VolumetricsInfo *volumetrics;
+ /* Common Uniform Buffer */
+ struct EEVEE_CommonUniformBuffer common_data;
+ struct GPUUniformBuffer *common_ubo;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
+typedef struct EEVEE_LightData {
+ short light_id, shadow_id;
+} EEVEE_LightData;
+
+typedef struct EEVEE_ShadowCubeData {
+ short light_id, shadow_id, cube_id, layer_id;
+} EEVEE_ShadowCubeData;
+
+typedef struct EEVEE_ShadowCascadeData {
+ short light_id, shadow_id, cascade_id, layer_id;
+ float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
+ float radius[MAX_CASCADE_NUM];
+} EEVEE_ShadowCascadeData;
+
+/* Theses are the structs stored inside Objects.
+ * It works with even if the object is in multiple layers
+ * because we don't get the same "Object *" for each layer. */
typedef struct EEVEE_LampEngineData {
+ ObjectEngineData engine_data;
+
bool need_update;
- struct ListBase shadow_caster_list;
- void *storage; /* either EEVEE_LightData, EEVEE_ShadowCubeData, EEVEE_ShadowCascadeData */
+ /* This needs to be out of the union to avoid undefined behaviour. */
+ short prev_cube_shadow_id;
+ union {
+ struct EEVEE_LightData ld;
+ struct EEVEE_ShadowCubeData scd;
+ struct EEVEE_ShadowCascadeData scad;
+ } data;
} EEVEE_LampEngineData;
typedef struct EEVEE_LightProbeEngineData {
+ ObjectEngineData engine_data;
+
/* NOTE: need_full_update is set by dependency graph when the probe or it's
* object is updated. This triggers full probe update, including it's
* "progressive" GI refresh.
@@ -606,7 +692,10 @@ typedef struct EEVEE_LightProbeEngineData {
} EEVEE_LightProbeEngineData;
typedef struct EEVEE_ObjectEngineData {
+ ObjectEngineData engine_data;
+
bool need_update;
+ unsigned int shadow_caster_id;
} EEVEE_ObjectEngineData;
/* *********************************** */
@@ -635,18 +724,18 @@ typedef struct EEVEE_PrivateData {
struct GHash *material_hash;
struct GHash *hair_material_hash;
struct GPUTexture *minzbuffer;
- struct GPUTexture *ssr_hit_output[4];
+ struct GPUTexture *ssr_pdf_output;
struct GPUTexture *gtao_horizons_debug;
float background_alpha; /* TODO find a better place for this. */
- float viewvecs[2][4];
/* For planar probes */
- float texel_size[2];
- /* To correct mip level texel mis-alignement */
- float mip_ratio[10][2]; /* TODO put in a UBO */
+ float planar_texel_size[2];
/* For double buffering */
bool view_updated;
bool valid_double_buffer;
- float prev_persmat[4][4];
+ /* Render Matrices */
+ float persmat[4][4], persinv[4][4];
+ float viewmat[4][4], viewinv[4][4];
+ float winmat[4][4], wininv[4][4];
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
@@ -661,7 +750,7 @@ EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
-void EEVEE_materials_init(EEVEE_StorageList *stl);
+void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_Data *vedata);
void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob);
void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
@@ -676,7 +765,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material
struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method);
void EEVEE_materials_free(void);
void EEVEE_draw_default_passes(EEVEE_PassList *psl);
-void EEVEE_update_util_texture(float offset);
+void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3]);
/* eevee_lights.c */
void EEVEE_lights_init(EEVEE_ViewLayerData *sldata);
@@ -688,6 +777,7 @@ void EEVEE_lights_cache_shcaster_material_add(
EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl,
struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob,
float (*obmat)[4], float *alpha_threshold);
+void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata);
void EEVEE_lights_update(EEVEE_ViewLayerData *sldata);
void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
@@ -702,7 +792,7 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lightprobes_free(void);
/* eevee_depth_of_field.c */
-int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_depth_of_field_draw(EEVEE_Data *vedata);
void EEVEE_depth_of_field_free(void);
@@ -716,7 +806,7 @@ void EEVEE_bloom_free(void);
/* eevee_occlusion.c */
int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_occlusion_free(void);
@@ -730,19 +820,22 @@ void EEVEE_screen_raytrace_free(void);
/* eevee_subsurface.c */
int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
+void EEVEE_subsurface_add_pass(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_free(void);
/* eevee_motion_blur.c */
-int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_motion_blur_draw(EEVEE_Data *vedata);
void EEVEE_motion_blur_free(void);
/* eevee_temporal_sampling.c */
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_temporal_sampling_matrices_calc(
+ EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2]);
void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata);
void EEVEE_temporal_sampling_free(void);
@@ -757,15 +850,21 @@ void EEVEE_volumes_free_smoke_textures(void);
void EEVEE_volumes_free(void);
/* eevee_effects.c */
-void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera);
void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level);
void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_draw_effects(EEVEE_Data *vedata);
+void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_effects_free(void);
+/* eevee_ */
+void EEVEE_render_init(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+void EEVEE_render_output(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph);
+
/* Shadow Matrix */
static const float texcomat[4][4] = { /* From NDC to TexCo */
{0.5f, 0.0f, 0.0f, 0.0f},
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
new file mode 100644
index 00000000000..a020887e420
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * 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.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee_render.c
+ * \ingroup draw_engine
+ */
+
+/**
+ * Render functions for final render outputs.
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "BLI_rand.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+
+#include "RE_pipeline.h"
+
+#include "eevee_private.h"
+
+void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph)
+{
+ EEVEE_Data *vedata = (EEVEE_Data *)ved;
+ EEVEE_PassList *psl = vedata->psl;
+ 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 *viewport_size = DRW_viewport_size_get();
+
+ /* Init default FB and render targets:
+ * In render mode the default framebuffer is not generated
+ * because there is no viewport. So we need to manually create it or
+ * not use it. For code clarity we just allocate it make use of it. */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* NOTE : use 32 bit format for precision in render mode. */
+ DRWFboTexture dtex = {&dtxl->depth, DRW_TEX_DEPTH_24_STENCIL_8, 0};
+ DRW_framebuffer_init(&dfbl->default_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &dtex, 1);
+
+ DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_32, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
+ DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+
+ /* Alloc transient data. */
+ if (!stl->g_data) {
+ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
+ }
+ EEVEE_PrivateData *g_data = stl->g_data;
+ g_data->background_alpha = 1.0f; /* TODO option */
+ g_data->valid_double_buffer = 0;
+
+ /* Alloc common ubo data. */
+ if (sldata->common_ubo == NULL) {
+ sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
+ }
+
+ /* Set the pers & view matrix. */
+ struct Object *camera = RE_GetCamera(engine->re);
+ float frame = BKE_scene_frame_get(scene);
+ RE_GetCameraWindow(engine->re, camera, frame, g_data->winmat);
+ RE_GetCameraModelMatrix(engine->re, camera, g_data->viewinv);
+
+ invert_m4_m4(g_data->viewmat, g_data->viewinv);
+ mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat);
+ invert_m4_m4(g_data->persinv, g_data->persmat);
+ invert_m4_m4(g_data->wininv, g_data->winmat);
+
+ DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
+
+ /* EEVEE_effects_init needs to go first for TAA */
+ EEVEE_effects_init(sldata, vedata, camera);
+ EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_lights_init(sldata);
+ EEVEE_lightprobes_init(sldata, vedata);
+
+ /* INIT CACHE */
+ EEVEE_bloom_cache_init(sldata, vedata);
+ EEVEE_depth_of_field_cache_init(sldata, vedata);
+ EEVEE_effects_cache_init(sldata, vedata);
+ EEVEE_lightprobes_cache_init(sldata, vedata);
+ EEVEE_lights_cache_init(sldata, psl);
+ EEVEE_materials_cache_init(vedata);
+ EEVEE_motion_blur_cache_init(sldata, vedata);
+ EEVEE_occlusion_cache_init(sldata, vedata);
+ EEVEE_screen_raytrace_cache_init(sldata, vedata);
+ EEVEE_subsurface_cache_init(sldata, vedata);
+ EEVEE_temporal_sampling_cache_init(sldata, vedata);
+ EEVEE_volumes_cache_init(sldata, vedata);
+}
+
+void EEVEE_render_cache(
+ void *vedata, struct Object *ob,
+ struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
+{
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
+ EEVEE_materials_cache_populate(vedata, sldata, ob);
+
+ const bool cast_shadow = true;
+
+ if (cast_shadow) {
+ EEVEE_lights_cache_shcaster_object_add(sldata, ob);
+ }
+ }
+ else if (ob->type == OB_LIGHTPROBE) {
+ EEVEE_lightprobes_cache_add(sldata, ob);
+ }
+ else if (ob->type == OB_LAMP) {
+ EEVEE_lights_cache_add(sldata, ob);
+ }
+}
+
+void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph))
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ EEVEE_PrivateData *g_data = stl->g_data;
+
+ /* FINISH CACHE */
+ EEVEE_materials_cache_finish(vedata);
+ EEVEE_lights_cache_finish(sldata);
+ EEVEE_lightprobes_cache_finish(sldata, vedata);
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ unsigned int render_samples = BKE_collection_engine_property_value_get_int(props, "taa_render_samples");
+
+ while (render_samples-- > 0) {
+ float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.6f};
+ unsigned int primes[3] = {2, 3, 7};
+ double offset[3] = {0.0, 0.0, 0.0};
+ double r[3];
+
+ BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r);
+ EEVEE_update_noise(psl, fbl, r);
+ EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, r);
+
+ /* Refresh Probes & shadows */
+ EEVEE_lightprobes_refresh(sldata, vedata);
+ DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
+ EEVEE_draw_shadows(sldata, psl);
+
+ DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
+ DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
+
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ DRW_framebuffer_bind(fbl->main);
+ DRW_framebuffer_clear(true, true, true, clear_col, 1.0f);
+ /* Depth prepass */
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ /* Create minmax texture */
+ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
+ EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
+ EEVEE_volumes_compute(sldata, vedata);
+ /* Shading pass */
+ DRW_draw_pass(psl->background_pass);
+ EEVEE_draw_default_passes(psl);
+ DRW_draw_pass(psl->material_pass);
+ EEVEE_subsurface_data_render(sldata, vedata);
+ /* Effects pre-transparency */
+ EEVEE_subsurface_compute(sldata, vedata);
+ EEVEE_reflection_compute(sldata, vedata);
+ EEVEE_occlusion_draw_debug(sldata, vedata);
+ DRW_draw_pass(psl->probe_display);
+ EEVEE_refraction_compute(sldata, vedata);
+ /* Opaque refraction */
+ DRW_draw_pass(psl->refract_depth_pass);
+ DRW_draw_pass(psl->refract_depth_pass_cull);
+ DRW_draw_pass(psl->refract_pass);
+ /* Volumetrics Resolve Opaque */
+ EEVEE_volumes_resolve(sldata, vedata);
+ /* Transparent */
+ DRW_pass_sort_shgroup_z(psl->transparent_pass);
+ DRW_draw_pass(psl->transparent_pass);
+ /* Post Process */
+ EEVEE_draw_effects(sldata, vedata);
+ }
+}
+
+void EEVEE_render_output(EEVEE_Data *vedata, RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ ViewLayer *view_layer = draw_ctx->view_layer;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ const char *viewname = NULL;
+ const float *render_size = DRW_viewport_size_get();
+
+ /* Combined */
+ RenderResult *rr = RE_engine_begin_result(engine, 0, 0, (int)render_size[0], (int)render_size[1], NULL, viewname);
+ RenderLayer *rl = rr->layers.first;
+ RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname);
+
+ DRW_framebuffer_bind(stl->effects->final_fb);
+ DRW_framebuffer_read_data(0, 0, (int)render_size[0], (int)render_size[1], 4, 0, rp->rect);
+
+ if (view_layer->passflag & SCE_PASS_Z) {
+ rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname);
+
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
+ DRW_framebuffer_bind(fbl->main);
+ DRW_framebuffer_read_depth(0, 0, (int)render_size[0], (int)render_size[1], rp->rect);
+
+ bool is_persp = DRW_viewport_is_persp_get();
+
+ /* Convert ogl depth [0..1] to view Z [near..far] */
+ for (int i = 0; i < (int)render_size[0] * (int)render_size[1]; ++i) {
+ if (rp->rect[i] == 1.0f ) {
+ rp->rect[i] = 1e10f; /* Background */
+ }
+ else {
+ if (is_persp) {
+ rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
+ rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]);
+ }
+ else {
+ rp->rect[i] = -common_data->view_vecs[0][2] + rp->rect[i] * -common_data->view_vecs[1][2];
+ }
+ }
+ }
+ }
+
+ RE_engine_end_result(engine, rr, false, false, false);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 35669968337..2917bfd1236 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -28,15 +28,16 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "eevee_private.h"
#include "GPU_texture.h"
/* SSR shader variations */
enum {
- SSR_SAMPLES = (1 << 0) | (1 << 1),
- SSR_RESOLVE = (1 << 2),
- SSR_FULL_TRACE = (1 << 3),
+ SSR_RESOLVE = (1 << 0),
+ SSR_FULL_TRACE = (1 << 1),
+ SSR_AO = (1 << 3),
SSR_MAX_SHADER = (1 << 4),
};
@@ -50,6 +51,7 @@ static struct {
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_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[];
@@ -60,22 +62,18 @@ extern char datatoc_raytrace_lib_glsl[];
static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
{
if (e_data.ssr_sh[options] == NULL) {
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_effect_ssr_frag_glsl);
- char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- int samples = (SSR_SAMPLES & options) + 1;
+ char *ssr_shader_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_effect_ssr_frag_glsl);
DynStr *ds_defines = BLI_dynstr_new();
BLI_dynstr_appendf(ds_defines, SHADER_DEFINES);
- BLI_dynstr_appendf(ds_defines, "#define RAY_COUNT %d\n", samples);
if (options & SSR_RESOLVE) {
BLI_dynstr_appendf(ds_defines, "#define STEP_RESOLVE\n");
}
@@ -86,6 +84,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
if (options & SSR_FULL_TRACE) {
BLI_dynstr_appendf(ds_defines, "#define FULLRES\n");
}
+ if (options & SSR_AO) {
+ BLI_dynstr_appendf(ds_defines, "#define SSR_AO\n");
+ }
char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
BLI_dynstr_free(ds_defines);
@@ -98,8 +99,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options)
return e_data.ssr_sh[options];
}
-int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
@@ -108,11 +110,13 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
- IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
+ IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer,
+ COLLECTION_MODE_NONE,
+ RE_engine_id_BLENDER_EEVEE);
/* Compute pixel size, (shared with contact shadows) */
- copy_v2_v2(effects->ssr_pixelsize, viewport_size);
- invert_v2(effects->ssr_pixelsize);
+ copy_v2_v2(common_data->ssr_pixelsize, viewport_size);
+ invert_v2(common_data->ssr_pixelsize);
if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) {
const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction");
@@ -120,24 +124,27 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
if (use_refraction) {
DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
- DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], &tex, 1);
+ DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
}
- effects->ssr_ray_count = BKE_collection_engine_property_value_get_int(props, "ssr_ray_count");
+ bool prev_trace_full = effects->reflection_trace_full;
effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres");
- effects->ssr_use_normalization = BKE_collection_engine_property_value_get_bool(props, "ssr_normalize_weight");
- effects->ssr_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "ssr_quality");
- effects->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
- effects->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
- effects->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac");
- effects->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness");
-
- if (effects->ssr_firefly_fac < 1e-8f) {
- effects->ssr_firefly_fac = FLT_MAX;
+ common_data->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
+ common_data->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade");
+ common_data->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac");
+ common_data->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness");
+ common_data->ssr_quality = 1.0f - 0.95f * BKE_collection_engine_property_value_get_float(props, "ssr_quality");
+ common_data->ssr_brdf_bias = 0.1f + common_data->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */
+
+ if (common_data->ssr_firefly_fac < 1e-8f) {
+ common_data->ssr_firefly_fac = FLT_MAX;
}
- /* Important, can lead to breakage otherwise. */
- CLAMP(effects->ssr_ray_count, 1, 4);
+ if (prev_trace_full != effects->reflection_trace_full) {
+ DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
+ }
const int divisor = (effects->reflection_trace_full) ? 1 : 2;
int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
@@ -147,7 +154,8 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
/* TODO create one texture layer per lobe */
if (txl->ssr_specrough_input == NULL) {
DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8;
- txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL);
+ txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1],
+ specrough_format, 0, NULL);
}
/* Reattach textures to the right buffer (because we are alternating between buffers) */
@@ -156,15 +164,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0);
/* Raytracing output */
- /* TODO try integer format for hit coord to increase precision */
- DRWFboTexture tex_output[4] = {
- {&stl->g_data->ssr_hit_output[0], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
- {&stl->g_data->ssr_hit_output[1], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
- {&stl->g_data->ssr_hit_output[2], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
- {&stl->g_data->ssr_hit_output[3], DRW_TEX_RGBA_16, DRW_TEX_TEMP},
- };
+ /* (AMD or Intel) For some reason DRW_TEX_TEMP with DRW_TEX_RG_16I
+ * creates problems when toggling ssr_halfres. Texture is not read correctly (black output).
+ * So using a persistent buffer instead. */
+ DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, DRW_TEX_RG_16I, 0},
+ {&stl->g_data->ssr_pdf_output, DRW_TEX_R_16, DRW_TEX_TEMP}};
- DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, effects->ssr_ray_count);
+ DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type,
+ tracing_res[0], tracing_res[1],
+ tex_output, 2);
/* Enable double buffering to be able to read previous frame color */
return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0);
@@ -172,10 +180,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input);
+ DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
- for (int i = 0; i < 4; ++i) {
- stl->g_data->ssr_hit_output[i] = NULL;
- }
+ stl->g_data->ssr_pdf_output = NULL;
return 0;
}
@@ -191,7 +198,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
if ((effects->enabled_effects & EFFECT_SSR) != 0) {
int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0;
- options |= (effects->ssr_ray_count - 1);
+ options |= ((effects->enabled_effects & EFFECT_GTAO) != 0) ? SSR_AO : 0;
struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options);
struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options);
@@ -214,15 +221,14 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_vec4(grp, "ssrParameters", &effects->ssr_quality, 1);
- DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ if (!effects->reflection_trace_full) {
+ DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
+ }
DRW_shgroup_call_add(grp, quad, NULL);
psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
@@ -230,41 +236,19 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
+ DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
+ DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth);
+ DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output);
+ DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output);
DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer);
- DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1);
- DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1);
- DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10);
- DRW_shgroup_uniform_float(grp, "borderFadeFactor", &effects->ssr_border_fac, 1);
- DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1);
- DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1);
- DRW_shgroup_uniform_float(grp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool);
- DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool);
- DRW_shgroup_uniform_buffer(grp, "hitBuffer0", &stl->g_data->ssr_hit_output[0]);
- if (effects->ssr_ray_count > 1) {
- DRW_shgroup_uniform_buffer(grp, "hitBuffer1", &stl->g_data->ssr_hit_output[1]);
- }
- if (effects->ssr_ray_count > 2) {
- DRW_shgroup_uniform_buffer(grp, "hitBuffer2", &stl->g_data->ssr_hit_output[2]);
- }
- if (effects->ssr_ray_count > 3) {
- DRW_shgroup_uniform_buffer(grp, "hitBuffer3", &stl->g_data->ssr_hit_output[3]);
- }
-
- DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &effects->ao_dist, 2);
- if (effects->use_ao) {
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
+ if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons);
- DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1);
- }
- else {
- /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &sldata->shadow_pool);
}
DRW_shgroup_call_add(grp, quad, NULL);
@@ -301,22 +285,39 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v
e_data.depth_src = dtxl->depth;
DRW_stats_group_start("SSR");
-
- for (int i = 0; i < effects->ssr_ray_count; ++i) {
- DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_hit_output[i], i, 0);
- }
+ DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_pdf_output, 1, 0);
DRW_framebuffer_bind(fbl->screen_tracing_fb);
/* Raytrace. */
DRW_draw_pass(psl->ssr_raytrace);
- for (int i = 0; i < effects->ssr_ray_count; ++i) {
- DRW_framebuffer_texture_detach(stl->g_data->ssr_hit_output[i]);
- }
+ DRW_framebuffer_texture_detach(stl->g_data->ssr_pdf_output);
EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9);
/* Resolve at fullres */
+ int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample;
+ /* Doing a neighbor shift only after a few iteration. We wait for a prime number of cycles to avoid
+ * noise correlation. This reduces variance faster. */
+ effects->ssr_neighbor_ofs = ((sample / 5) % 8) * 4;
+ switch ((sample / 11) % 4) {
+ case 0:
+ effects->ssr_halfres_ofs[0] = 0;
+ effects->ssr_halfres_ofs[1] = 0;
+ break;
+ case 1:
+ effects->ssr_halfres_ofs[0] = 0;
+ effects->ssr_halfres_ofs[1] = 1;
+ break;
+ case 2:
+ effects->ssr_halfres_ofs[0] = 1;
+ effects->ssr_halfres_ofs[1] = 0;
+ break;
+ case 4:
+ effects->ssr_halfres_ofs[0] = 1;
+ effects->ssr_halfres_ofs[1] = 1;
+ break;
+ }
DRW_framebuffer_texture_detach(dtxl->depth);
DRW_framebuffer_texture_detach(txl->ssr_normal_input);
DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 4efdfb0fb84..17da4a18b78 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -27,7 +27,7 @@
#include "DRW_render.h"
-#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "eevee_private.h"
#include "GPU_texture.h"
@@ -36,18 +36,26 @@ static struct {
struct GPUShader *sss_sh[3];
} e_data = {NULL}; /* Engine data */
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
static void eevee_create_shader_subsurface(void)
{
- e_data.sss_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define FIRST_PASS\n");
- e_data.sss_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n");
- e_data.sss_sh[2] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n"
- "#define USE_SEP_ALBEDO\n");
+ char *frag_str = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_effect_subsurface_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_str, "#define SECOND_PASS\n"
+ "#define USE_SEP_ALBEDO\n");
+
+ MEM_freeN(frag_str);
}
-int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -60,8 +68,8 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedat
if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) {
effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2;
- effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo");
+ common_data->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold");
/* Shaders */
if (!e_data.sss_sh[0]) {
@@ -117,7 +125,8 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
}
}
-void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
+void EEVEE_subsurface_add_pass(
+ EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile)
{
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
@@ -127,23 +136,21 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur);
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
DRW_shgroup_call_add(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 5faac4c42cc..24b8117b6f5 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -44,6 +44,23 @@ static void eevee_create_shader_temporal_sampling(void)
e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL);
}
+void EEVEE_temporal_sampling_matrices_calc(
+ EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2])
+{
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* TODO Blackman-Harris filter */
+
+ window_translate_m4(
+ effects->overide_winmat, persmat,
+ ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0],
+ ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]);
+
+ mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
+ invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
+ invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
+}
+
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -51,14 +68,21 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ /* Reset for each "redraw". When rendering using ogl render,
+ * we accumulate the redraw inside the drawing loop in eevee_draw_background().
+ * But we do NOT accumulate between "redraw" (as in full draw manager drawloop)
+ * because the opengl render already does that. */
+ effects->taa_render_sample = 1;
+
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE);
- if (BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 &&
+ if ((BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 &&
/* FIXME the motion blur camera evaluation is tagging view_updated
* thus making the TAA always reset and never stopping rendering. */
- (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0)
+ (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) ||
+ DRW_state_is_image_render())
{
const float *viewport_size = DRW_viewport_size_get();
float persmat[4][4], viewmat[4][4];
@@ -79,40 +103,41 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN);
- view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
- copy_m4_m4(effects->prev_drw_persmat, persmat);
+ /* The view is jittered by the oglrenderer. So avoid testing in this case. */
+ if (!DRW_state_is_image_render()) {
+ view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
+ copy_m4_m4(effects->prev_drw_persmat, persmat);
+ }
/* Prevent ghosting from probe data. */
view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support());
effects->prev_drw_support = DRW_state_draw_support();
- if (view_is_valid &&
- ((effects->taa_total_sample == 0) ||
- (effects->taa_current_sample < effects->taa_total_sample)))
+ if (((effects->taa_total_sample == 0) || (effects->taa_current_sample < effects->taa_total_sample)) ||
+ DRW_state_is_image_render())
{
- effects->taa_current_sample += 1;
-
- effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
-
- double ht_point[2];
- double ht_offset[2] = {0.0, 0.0};
- unsigned int ht_primes[2] = {2, 3};
-
- BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
-
- window_translate_m4(
- effects->overide_winmat, persmat,
- ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0],
- ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]);
-
- mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
- invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
- invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
-
- DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV);
+ if (view_is_valid) {
+ /* OGL render already jitter the camera. */
+ if (!DRW_state_is_image_render()) {
+ effects->taa_current_sample += 1;
+
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ unsigned int ht_primes[2] = {2, 3};
+
+ BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
+
+ EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point);
+
+ DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV);
+ }
+ }
+ else {
+ effects->taa_current_sample = 1;
+ }
}
else {
effects->taa_current_sample = 1;
@@ -127,6 +152,8 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER;
}
+ effects->taa_current_sample = 1;
+
/* Cleanup to release memory */
DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->depth_double_buffer_fb);
@@ -162,11 +189,21 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
if ((effects->enabled_effects & EFFECT_TAA) != 0) {
if (effects->taa_current_sample != 1) {
+ if (DRW_state_is_image_render()) {
+ /* See EEVEE_temporal_sampling_init() for more details. */
+ effects->taa_alpha = 1.0f / (float)(effects->taa_render_sample);
+ }
+ else {
+ effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample);
+ }
+
DRW_framebuffer_bind(fbl->effect_fb);
DRW_draw_pass(psl->taa_resolve);
/* Restore the depth from sample 1. */
- DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false);
+ if (!DRW_state_is_image_render()) {
+ DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false);
+ }
/* Special Swap */
SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer);
@@ -179,15 +216,25 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
/* Save the depth buffer for the next frame.
* This saves us from doing anything special
* in the other mode engines. */
- DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false);
+ if (!DRW_state_is_image_render()) {
+ DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false);
+ }
}
- if ((effects->taa_total_sample == 0) ||
- (effects->taa_current_sample < effects->taa_total_sample))
- {
- DRW_viewport_request_redraw();
+ /* Make each loop count when doing a render. */
+ if (DRW_state_is_image_render()) {
+ effects->taa_render_sample += 1;
+ effects->taa_current_sample += 1;
+ }
+ else {
+ if ((effects->taa_total_sample == 0) ||
+ (effects->taa_current_sample < effects->taa_total_sample))
+ {
+ DRW_viewport_request_redraw();
+ }
}
}
+
}
void EEVEE_temporal_sampling_free(void)
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index dae4503dc32..a960682e8c9 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -27,8 +27,8 @@
#include "DRW_render.h"
-#include "BLI_dynstr.h"
#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "DNA_object_force.h"
#include "DNA_smoke_types.h"
@@ -51,6 +51,7 @@ static struct {
struct GPUShader *volumetric_clear_sh;
struct GPUShader *volumetric_scatter_sh;
+ struct GPUShader *volumetric_scatter_with_lamps_sh;
struct GPUShader *volumetric_integration_sh;
struct GPUShader *volumetric_resolve_sh;
@@ -63,6 +64,7 @@ static struct {
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
+extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lamps_lib_glsl[];
@@ -77,21 +79,19 @@ extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
static void eevee_create_shader_volumes(void)
{
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
- e_data.volumetric_common_lib = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
-
- ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl);
- e_data.volumetric_common_lamps_lib = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ e_data.volumetric_common_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_volumetric_lib_glsl);
+
+ e_data.volumetric_common_lamps_lib = BLI_string_joinN(
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_direct_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lamps_lib_glsl,
+ datatoc_volumetric_lib_glsl);
e_data.volumetric_clear_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
@@ -108,6 +108,15 @@ static void eevee_create_shader_volumes(void)
SHADER_DEFINES
"#define VOLUMETRICS\n"
"#define VOLUME_SHADOW\n");
+ e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib(
+ datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_scatter_frag_glsl,
+ e_data.volumetric_common_lamps_lib,
+ SHADER_DEFINES
+ "#define VOLUMETRICS\n"
+ "#define VOLUME_LIGHTING\n"
+ "#define VOLUME_SHADOW\n");
e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
@@ -125,6 +134,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
ViewLayer *view_layer = draw_ctx->view_layer;
@@ -141,29 +151,23 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
eevee_create_shader_volumes();
}
- if (sldata->volumetrics == NULL) {
- sldata->volumetrics = MEM_callocN(sizeof(EEVEE_VolumetricsInfo), "EEVEE_VolumetricsInfo");
- }
-
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
-
int tile_size = BKE_collection_engine_property_value_get_int(props, "volumetric_tile_size");
/* Find Froxel Texture resolution. */
- int froxel_tex_size[3];
+ int tex_size[3];
- froxel_tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
- froxel_tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
- froxel_tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
+ tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
+ tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
+ tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1);
- volumetrics->volume_coord_scale[0] = viewport_size[0] / (float)(tile_size * froxel_tex_size[0]);
- volumetrics->volume_coord_scale[1] = viewport_size[1] / (float)(tile_size * froxel_tex_size[1]);
+ common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
+ common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
/* TODO compute snap to maxZBuffer for clustered rendering */
- if ((volumetrics->froxel_tex_size[0] != froxel_tex_size[0]) ||
- (volumetrics->froxel_tex_size[1] != froxel_tex_size[1]) ||
- (volumetrics->froxel_tex_size[2] != froxel_tex_size[2]))
+ if ((common_data->vol_tex_size[0] != tex_size[0]) ||
+ (common_data->vol_tex_size[1] != tex_size[1]) ||
+ (common_data->vol_tex_size[2] != tex_size[2]))
{
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
@@ -176,38 +180,46 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
- volumetrics->froxel_tex_size[0] = froxel_tex_size[0];
- volumetrics->froxel_tex_size[1] = froxel_tex_size[1];
- volumetrics->froxel_tex_size[2] = froxel_tex_size[2];
+ common_data->vol_tex_size[0] = tex_size[0];
+ common_data->vol_tex_size[1] = tex_size[1];
+ common_data->vol_tex_size[2] = tex_size[2];
- volumetrics->inv_tex_size[0] = 1.0f / (float)(volumetrics->froxel_tex_size[0]);
- volumetrics->inv_tex_size[1] = 1.0f / (float)(volumetrics->froxel_tex_size[1]);
- volumetrics->inv_tex_size[2] = 1.0f / (float)(volumetrics->froxel_tex_size[2]);
+ common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
+ common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
+ common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
}
/* Like frostbite's paper, 5% blend of the new frame. */
- volumetrics->history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
+ common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
if (txl->volume_prop_scattering == NULL) {
/* Volume properties: We evaluate all volumetric objects
* and store their final properties into each froxel */
- txl->volume_prop_scattering = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_extinction = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_emission = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_prop_phase = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RG_16, DRW_TEX_FILTER, NULL);
/* Volume scattering: We compute for each froxel the
* Scattered light towards the view. We also resolve temporal
* super sampling during this stage. */
- txl->volume_scatter = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
/* Final integration: We compute for each froxel the
* amount of scattered light and extinction coef at this
* given depth. We use theses textures as double buffer
* for the volumetric history. */
- txl->volume_scatter_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
+ txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2],
+ DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL);
}
/* Temporal Super sampling jitter */
@@ -225,7 +237,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
if (do_taa) {
- volumetrics->history_alpha = 0.0f;
+ common_data->vol_history_alpha = 0.0f;
current_sample = effects->taa_current_sample - 1;
effects->volume_current_sample = -1;
}
@@ -238,9 +250,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point);
- volumetrics->jitter[0] = (float)ht_point[0];
- volumetrics->jitter[1] = (float)ht_point[1];
- volumetrics->jitter[2] = (float)ht_point[2];
+ common_data->vol_jitter[0] = (float)ht_point[0];
+ common_data->vol_jitter[1] = (float)ht_point[1];
+ common_data->vol_jitter[2] = (float)ht_point[2];
/* Framebuffer setup */
DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
@@ -249,63 +261,64 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol, 4);
DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
{&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol_scat, 2);
DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER},
{&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}};
DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type,
- (int)froxel_tex_size[0], (int)froxel_tex_size[1],
+ (int)tex_size[0], (int)tex_size[1],
tex_vol_integ, 2);
- volumetrics->integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
- volumetrics->integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
- volumetrics->sample_distribution = 4.0f * (1.00001f - BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution"));
- volumetrics->use_volume_shadows = BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows");
- volumetrics->light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
+ float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start");
+ float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end");
+ common_data->vol_light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp");
- if (volumetrics->use_volume_shadows) {
- volumetrics->shadow_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+ common_data->vol_shadow_steps = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples");
+ if (BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows")) {
}
else {
- volumetrics->shadow_step_count = 0;
+ common_data->vol_shadow_steps = 0;
}
if (DRW_viewport_is_persp_get()) {
- const float clip_start = stl->g_data->viewvecs[0][2];
+ float sample_distribution = BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution");
+ sample_distribution = 4.0f * (1.00001f - sample_distribution);
+
+ const float clip_start = common_data->view_vecs[0][2];
/* Negate */
- float near = volumetrics->integration_start = min_ff(-volumetrics->integration_start, clip_start - 1e-4f);
- float far = volumetrics->integration_end = min_ff(-volumetrics->integration_end, near - 1e-4f);
+ float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
+ float far = integration_end = min_ff(-integration_end, near - 1e-4f);
- volumetrics->depth_param[0] = (far - near * exp2(1.0f / volumetrics->sample_distribution)) / (far - near);
- volumetrics->depth_param[1] = (1.0f - volumetrics->depth_param[0]) / near;
- volumetrics->depth_param[2] = volumetrics->sample_distribution;
+ common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near);
+ common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
+ common_data->vol_depth_param[2] = sample_distribution;
}
else {
- const float clip_start = stl->g_data->viewvecs[0][2];
- const float clip_end = stl->g_data->viewvecs[1][2];
- volumetrics->integration_start = min_ff(volumetrics->integration_end, clip_start);
- volumetrics->integration_end = max_ff(-volumetrics->integration_end, clip_end);
-
- volumetrics->depth_param[0] = volumetrics->integration_start;
- volumetrics->depth_param[1] = volumetrics->integration_end;
- volumetrics->depth_param[2] = 1.0f / (volumetrics->integration_end - volumetrics->integration_start);
+ const float clip_start = common_data->view_vecs[0][2];
+ const float clip_end = common_data->view_vecs[1][2];
+ integration_start = min_ff(integration_end, clip_start);
+ integration_end = max_ff(-integration_end, clip_end);
+
+ common_data->vol_depth_param[0] = integration_start;
+ common_data->vol_depth_param[1] = integration_end;
+ common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
}
/* Disable clamp if equal to 0. */
- if (volumetrics->light_clamp == 0.0) {
- volumetrics->light_clamp = FLT_MAX;
+ if (common_data->vol_light_clamp == 0.0) {
+ common_data->vol_light_clamp = FLT_MAX;
}
- volumetrics->use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
+ common_data->vol_use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights");
return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
}
@@ -332,12 +345,11 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_StorageList *stl = vedata->stl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
- static int zero = 0;
DRWShadingGroup *grp;
/* Quick breakdown of the Volumetric rendering:
@@ -374,65 +386,59 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (wo != NULL && wo->use_nodes && wo->nodetree) {
struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
- grp = DRW_shgroup_material_empty_tri_batch_create(mat, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+ grp = DRW_shgroup_material_empty_tri_batch_create(mat,
+ psl->volumetric_world_ps,
+ common_data->vol_tex_size[2]);
if (grp) {
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
}
else {
/* If no world or volume material is present just clear the buffer with this drawcall */
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh,
+ psl->volumetric_world_ps,
+ common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
/* Volumetric Objects */
- psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR |
+ DRW_STATE_ADDITIVE);
+ struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh
+ : e_data.volumetric_scatter_sh;
psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_scatter_sh, psl->volumetric_scatter_ps, volumetrics->froxel_tex_size[2]);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
- DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_int(grp, "light_count", (volumetrics->use_lights) ? &sldata->lamps->num_light : &zero, 1);
+ grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps,
+ common_data->vol_tex_size[2]);
DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool);
DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool);
- DRW_shgroup_uniform_float(grp, "volume_light_clamp", &volumetrics->light_clamp, 1);
- DRW_shgroup_uniform_float(grp, "volume_shadows_steps", &volumetrics->shadow_step_count, 1);
- DRW_shgroup_uniform_float(grp, "volume_history_alpha", &volumetrics->history_alpha, 1);
DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_prop_scattering);
DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_prop_extinction);
DRW_shgroup_uniform_buffer(grp, "volumeEmission", &txl->volume_prop_emission);
DRW_shgroup_uniform_buffer(grp, "volumePhase", &txl->volume_prop_phase);
DRW_shgroup_uniform_buffer(grp, "historyScattering", &txl->volume_scatter_history);
DRW_shgroup_uniform_buffer(grp, "historyTransmittance", &txl->volume_transmittance_history);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps, volumetrics->froxel_tex_size[2]);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
+ grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
+ psl->volumetric_integration_ps,
+ common_data->vol_tex_size[2]);
DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_transmittance);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
DRW_shgroup_uniform_buffer(grp, "inScattering", &txl->volume_scatter);
DRW_shgroup_uniform_buffer(grp, "inTransmittance", &txl->volume_transmittance);
DRW_shgroup_uniform_buffer(grp, "inSceneColor", &e_data.color_src);
DRW_shgroup_uniform_buffer(grp, "inSceneDepth", &e_data.depth_src);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -442,7 +448,6 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
float *texcoloc = NULL;
float *texcosize = NULL;
struct ModifierData *md = NULL;
- EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics;
Material *ma = give_current_material(ob, 1);
if (ma == NULL) {
@@ -451,7 +456,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
- DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, volumetrics->froxel_tex_size[2]);
+ DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
/* Making sure it's updated. */
invert_m4_m4(ob->imat, ob->obmat);
@@ -459,14 +464,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
if (grp) {
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
- DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
- DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1);
- DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1);
- DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1);
}
/* Smoke Simulation */
@@ -576,6 +577,7 @@ void EEVEE_volumes_free(void)
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
+ DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
}
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 5ec72833379..55f66f5500a 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -30,87 +30,18 @@
#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 vec4 aoParameters[2];
-uniform sampler2DArray horizonBuffer;
-
-/* Cannot use textureSize(horizonBuffer) when rendering to it */
-uniform ivec2 aoHorizonTexSize;
-
-#define aoDistance aoParameters[0].x
-#define aoSamples aoParameters[0].y
-#define aoFactor aoParameters[0].z
-#define aoInvSamples aoParameters[0].w
-
-#define aoOffset aoParameters[1].x /* UNUSED */
-#define aoBounceFac aoParameters[1].y
-#define aoQuality aoParameters[1].z
-#define aoSettings aoParameters[1].w
+uniform sampler2D horizonBuffer;
+/* aoSettings flags */
#define USE_AO 1
#define USE_BENT_NORMAL 2
#define USE_DENOISE 4
-vec2 pack_horizons(vec2 v) { return v * 0.5 + 0.5; }
-vec2 unpack_horizons(vec2 v) { return v * 2.0 - 1.0; }
-
-/* Returns the texel coordinate in horizonBuffer
- * for a given fullscreen coord */
-ivec2 get_hr_co(ivec2 fs_co)
-{
- bvec2 quarter = notEqual(fs_co & ivec2(1), ivec2(0));
-
- ivec2 hr_co = fs_co / 2;
- hr_co += ivec2(quarter) * (aoHorizonTexSize / 2);
-
- return hr_co;
-}
-
-/* Returns the texel coordinate in fullscreen (depthBuffer)
- * for a given horizonBuffer coord */
-ivec2 get_fs_co(ivec2 hr_co)
-{
- hr_co *= 2;
- bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize);
-
- hr_co -= ivec2(quarter) * (aoHorizonTexSize - 1);
-
- return hr_co;
-}
-
-/* Returns the phi angle in horizonBuffer
- * for a given horizonBuffer coord */
-float get_phi(ivec2 hr_co, ivec2 fs_co, float sample)
-{
- bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize / 2);
- ivec2 tex_co = ((int(aoSettings) & USE_DENOISE) != 0) ? hr_co - ivec2(quarter) * (aoHorizonTexSize / 2) : fs_co;
- float blue_noise = texture(utilTex, vec3((vec2(tex_co) + 0.5) / LUT_SIZE, 2.0)).r;
-
- float phi = sample * aoInvSamples;
-
- if ((int(aoSettings) & USE_DENOISE) != 0) {
- /* Interleaved jitter for spatial 2x2 denoising */
- phi += 0.25 * aoInvSamples * (float(quarter.x) + 2.0 * float(quarter.y));
- blue_noise *= 0.25;
- }
- /* Blue noise is scaled to cover the rest of the range. */
- phi += aoInvSamples * blue_noise;
- phi *= M_PI;
-
- return phi;
-}
-
-/* Returns direction jittered offset for a given fullscreen coord */
-float get_offset(ivec2 fs_co, float sample)
-{
- float offset = sample * aoInvSamples;
-
- /* Interleaved jitter for spatial 2x2 denoising */
- offset += 0.25 * dot(vec2(1.0), vec2(fs_co & 1));
- offset += texture(utilTex, vec3((vec2(fs_co / 2) + 0.5 + 16.0) / LUT_SIZE, 2.0)).r;
- return offset;
-}
+vec4 pack_horizons(vec4 v) { return v * 0.5 + 0.5; }
+vec4 unpack_horizons(vec4 v) { return v * 2.0 - 1.0; }
/* Returns maximum screen distance an AO ray can travel for a given view depth */
vec2 get_max_dir(float view_depth)
@@ -120,6 +51,13 @@ vec2 get_max_dir(float view_depth)
return vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * max_dist;
}
+vec2 get_ao_dir(float jitter)
+{
+ /* Only half a turn because we integrate in slices. */
+ jitter *= M_PI;
+ return vec2(cos(jitter), sin(jitter));
+}
+
void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h)
{
co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */
@@ -161,10 +99,8 @@ void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float
h = mix(h, max(h, s_h.w), blend.w);
}
-vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir)
+vec2 search_horizon_sweep(vec2 t_phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir)
{
- vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
-
max_dir *= max_v2(abs(t_phi));
/* Convert to pixel space. */
@@ -214,11 +150,8 @@ vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_
return h;
}
-void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibility, inout vec3 bent_normal)
+void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibility, inout vec3 bent_normal)
{
- /* TODO OPTI Could be precomputed. */
- vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
-
/* Projecting Normal to Plane P defined by t_phi and omega_o */
vec3 np = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */
vec3 t = vec3(-t_phi, 0.0);
@@ -251,71 +184,43 @@ void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibili
bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5);
}
-void denoise_ao(vec3 normal, float frag_depth, inout float visibility, inout vec3 bent_normal)
+void gtao_deferred(vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal)
{
- vec2 d_sign = vec2(ivec2(gl_FragCoord.xy) & 1) - 0.5;
-
- if ((int(aoSettings) & USE_DENOISE) == 0) {
- d_sign *= 0.0;
- }
-
- /* 2x2 Bilateral Filter using derivatives. */
- vec2 n_step = step(-0.2, -abs(vec2(length(dFdx(normal)), length(dFdy(normal)))));
- vec2 z_step = step(-0.1, -abs(vec2(dFdx(frag_depth), dFdy(frag_depth))));
-
- visibility -= dFdx(visibility) * d_sign.x * z_step.x * n_step.x;
- visibility -= dFdy(visibility) * d_sign.y * z_step.y * n_step.y;
+ /* Fetch early, hide latency! */
+ vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0);
- bent_normal -= dFdx(bent_normal) * d_sign.x * z_step.x * n_step.x;
- bent_normal -= dFdy(bent_normal) * d_sign.y * z_step.y * n_step.y;
-}
-
-void gtao_deferred(vec3 normal, vec3 position, float frag_depth, out float visibility, out vec3 bent_normal)
-{
+ vec4 dirs;
+ dirs.xy = get_ao_dir(noise.x * 0.5);
+ dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5);
vec2 uvs = get_uvs_from_view(position);
- vec4 texel_size = vec4(-1.0, -1.0, 1.0, 1.0) / vec2(textureSize(depthBuffer, 0)).xyxy;
-
- ivec2 fs_co = ivec2(gl_FragCoord.xy);
- ivec2 hr_co = get_hr_co(fs_co);
-
bent_normal = vec3(0.0);
visibility = 0.0;
- for (float i = 0.0; i < MAX_PHI_STEP; i++) {
- if (i >= aoSamples) break;
+ horizons = unpack_horizons(horizons);
- vec2 horiz = unpack_horizons(texelFetch(horizonBuffer, ivec3(hr_co, int(i)), 0).rg);
- float phi = get_phi(hr_co, fs_co, i);
+ integrate_slice(normal, dirs.xy, horizons.xy, visibility, bent_normal);
+ integrate_slice(normal, dirs.zw, horizons.zw, visibility, bent_normal);
- integrate_slice(normal, phi, horiz.xy, visibility, bent_normal);
- }
+ visibility *= 0.5; /* We integrated 2 slices. */
- visibility *= aoInvSamples;
bent_normal = normalize(bent_normal);
}
-void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility, out vec3 bent_normal)
+void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3 bent_normal)
{
vec2 uvs = get_uvs_from_view(position);
-
- float homcco = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
- float max_dist = aoDistance / homcco; /* Search distance */
- vec2 max_dir = max_dist * vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]);
+ vec2 max_dir = get_max_dir(position.z);
+ vec2 dir = get_ao_dir(noise.x);
bent_normal = vec3(0.0);
visibility = 0.0;
- for (float i = 0.0; i < MAX_PHI_STEP; i++) {
- if (i >= aoSamples) break;
-
- float phi = M_PI * (i + noise.x) * aoInvSamples;
- vec2 horizons = search_horizon_sweep(phi, position, uvs, noise.g, max_dir);
-
- integrate_slice(normal, phi, horizons, visibility, bent_normal);
- }
+ /* Only trace in 2 directions. May lead to a darker result but since it's mostly for
+ * alpha blended objects that will have overdraw, we limit the performance impact. */
+ vec2 horizons = search_horizon_sweep(dir, position, uvs, noise.y, max_dir);
+ integrate_slice(normal, dir, horizons, visibility, bent_normal);
- visibility *= aoInvSamples;
bent_normal = normalize(bent_normal);
}
@@ -337,7 +242,7 @@ float gtao_multibounce(float visibility, vec3 albedo)
}
/* Use the right occlusion */
-float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, out vec3 bent_normal)
+float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal)
{
#ifndef USE_REFRACTION
if ((int(aoSettings) & USE_AO) > 0) {
@@ -345,11 +250,10 @@ float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, ou
vec3 vnor = mat3(ViewMatrix) * N;
#ifdef ENABLE_DEFERED_AO
- gtao_deferred(vnor, vpos, gl_FragCoord.z, visibility, bent_normal);
+ gtao_deferred(vnor, vpos, rand, gl_FragCoord.z, visibility, bent_normal);
#else
- gtao(vnor, vpos, randuv, visibility, bent_normal);
+ gtao(vnor, vpos, rand, visibility, bent_normal);
#endif
- denoise_ao(vnor, gl_FragCoord.z, visibility, bent_normal);
/* Prevent some problems down the road. */
visibility = max(1e-3, visibility);
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 37ed2235c6f..68299fe7546 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -11,7 +11,6 @@
uniform mat4 ProjectionMatrix;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ViewMatrixInverse;
-uniform vec4 viewvecs[2];
#ifndef SHADOW_SHADER
uniform mat4 ViewMatrix;
#else
@@ -31,8 +30,6 @@ flat in int shFace; /* Shadow layer we are rendering to. */
#define ViewMatrix FaceViewMatrix[shFace]
#endif
-uniform vec2 mipRatio[10];
-
/* Buffers */
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
@@ -125,6 +122,10 @@ float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
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 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 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); }
@@ -300,7 +301,7 @@ float get_view_z_from_depth(float depth)
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
- return viewvecs[0].z + depth * viewvecs[1].z;
+ return viewVecs[0].z + depth * viewVecs[1].z;
}
}
@@ -311,7 +312,7 @@ float get_depth_from_view_z(float z)
return d * 0.5 + 0.5;
}
else {
- return (z - viewvecs[0].z) / viewvecs[1].z;
+ return (z - viewVecs[0].z) / viewVecs[1].z;
}
}
@@ -324,10 +325,10 @@ vec2 get_uvs_from_view(vec3 view)
vec3 get_view_space_from_depth(vec2 uvcoords, float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
- return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * get_view_z_from_depth(depth);
+ return (viewVecs[0].xyz + vec3(uvcoords, 0.0) * viewVecs[1].xyz) * get_view_z_from_depth(depth);
}
else {
- return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz;
+ return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz;
}
}
@@ -545,7 +546,7 @@ vec3 F_schlick(vec3 f0, float cos_theta)
/* Fresnel approximation for LTC area lights (not MRP) */
vec3 F_area(vec3 f0, vec2 lut)
{
- vec2 fac = normalize(lut.xy);
+ vec2 fac = normalize(lut.xy); /* XXX FIXME this does not work!!! */
/* Unreal specular matching : if specular color is below 2% intensity,
* treat as shadowning */
@@ -691,7 +692,6 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
}
else {
cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
- cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */
cl.ssr_normal = cl2.ssr_normal;
cl.ssr_id = cl2.ssr_id;
}
@@ -739,12 +739,10 @@ Closure closure_add(Closure cl1, Closure cl2)
#endif
#endif
cl.radiance = cl1.radiance + cl2.radiance;
- cl.opacity = cl1.opacity + cl2.opacity;
+ cl.opacity = saturate(cl1.opacity + cl2.opacity);
return cl;
}
-uniform bool sssToggle;
-
#if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY)
layout(location = 0) out vec4 fragColor;
#ifdef USE_SSS
@@ -774,6 +772,10 @@ vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth);
void main()
{
Closure cl = nodetree_exec();
+#ifndef USE_ALPHA_BLEND
+ /* Prevent alpha hash material writing into alpha channel. */
+ cl.opacity = 1.0;
+#endif
#if defined(USE_ALPHA_BLEND_VOLUMETRICS)
/* XXX fragile, better use real viewport resolution */
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
index ae03f22ac14..ddc7327334c 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
@@ -28,56 +28,30 @@ float direct_diffuse_sun(LightData ld, vec3 N)
return bsdf;
}
-/* From Frostbite PBR Course
- * Analytical irradiance from a sphere with correct horizon handling
- * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
+#ifdef USE_LTC
float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector)
{
- float dist = l_vector.w;
- vec3 L = l_vector.xyz / dist;
- float radius = max(ld.l_sizex, 0.0001);
- float costheta = clamp(dot(N, L), -0.999, 0.999);
- float h = min(ld.l_radius / dist , 0.9999);
- float h2 = h*h;
- float costheta2 = costheta * costheta;
- float bsdf;
-
- if (costheta2 > h2) {
- bsdf = M_PI * h2 * clamp(costheta, 0.0, 1.0);
- }
- else {
- float sintheta = sqrt(1.0 - costheta2);
- float x = sqrt(1.0 / h2 - 1.0);
- float y = -x * (costheta / sintheta);
- float sinthetasqrty = sintheta * sqrt(1.0 - y * y);
- bsdf = (costheta * acos(y) - x * sinthetasqrty) * h2 + atan(sinthetasqrty / x);
- }
-
- bsdf = max(bsdf, 0.0);
- bsdf *= M_1_PI2;
+ float NL = dot(N, l_vector.xyz / l_vector.w);
- return bsdf;
+ return ltc_evaluate_disk_simple(ld.l_radius / l_vector.w, NL);
}
-#ifdef USE_LTC
float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector)
{
vec3 corners[4];
- corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
- corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
- corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
- corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+ corners[0] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey);
+ corners[1] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey);
+ corners[2] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey);
+ corners[3] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey);
- float bsdf = ltc_evaluate(N, V, mat3(1.0), corners);
- bsdf *= M_1_2PI;
- return bsdf;
+ return ltc_evaluate_quad(corners, N);
}
-#endif
-#if 0
-float direct_diffuse_unit_disc(vec3 N, vec3 L)
+float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V)
{
+ float NL = dot(N, -ld.l_forward);
+ return ltc_evaluate_disk_simple(ld.l_radius, NL);
}
#endif
@@ -106,47 +80,27 @@ vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0)
#ifdef USE_LTC
vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
{
- vec3 L = l_vector.xyz / l_vector.w;
- vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughness);
- vec3 P = line_aligned_plane_intersect(vec3(0.0), spec_dir, l_vector.xyz);
-
- vec3 Px = normalize(P - l_vector.xyz) * ld.l_radius;
- vec3 Py = cross(Px, L);
+ roughness = clamp(roughness, 0.0008, 0.999); /* Fix low roughness artifacts. */
vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
mat3 ltc_mat = ltc_matrix(ltc_lut);
-// #define HIGHEST_QUALITY
-#ifdef HIGHEST_QUALITY
- vec3 Pxy1 = normalize( Px + Py) * ld.l_radius;
- vec3 Pxy2 = normalize(-Px + Py) * ld.l_radius;
-
- /* counter clockwise */
- vec3 points[8];
- points[0] = l_vector.xyz + Px;
- points[1] = l_vector.xyz - Pxy2;
- points[2] = l_vector.xyz - Py;
- points[3] = l_vector.xyz - Pxy1;
- points[4] = l_vector.xyz - Px;
- points[5] = l_vector.xyz + Pxy2;
- points[6] = l_vector.xyz + Py;
- points[7] = l_vector.xyz + Pxy1;
- float bsdf = ltc_evaluate_circle(N, V, ltc_mat, points);
-#else
- vec3 points[4];
- points[0] = l_vector.xyz + Px;
- points[1] = l_vector.xyz - Py;
- points[2] = l_vector.xyz - Px;
- points[3] = l_vector.xyz + Py;
- float bsdf = ltc_evaluate(N, V, ltc_mat, points);
- /* sqrt(pi/2) difference between square and disk area */
- bsdf *= 1.25331413731;
-#endif
+ /* Make orthonormal basis. */
+ vec3 L = l_vector.xyz / l_vector.w;
+ vec3 Px, Py;
+ make_orthonormal_basis(L, Px, Py);
+ Px *= ld.l_radius;
+ Py *= ld.l_radius;
+ vec3 points[3];
+ points[0] = l_vector.xyz - Px - Py;
+ points[1] = l_vector.xyz + Px - Py;
+ points[2] = l_vector.xyz + Px + Py;
+
+ float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points);
bsdf *= brdf_lut.b; /* Bsdf intensity */
- bsdf *= M_1_2PI * M_1_PI;
vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
@@ -165,19 +119,38 @@ vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float rou
vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
mat3 ltc_mat = ltc_matrix(ltc_lut);
- float bsdf = ltc_evaluate(N, V, ltc_mat, corners);
+
+ ltc_transform_quad(N, V, ltc_mat, corners);
+ float bsdf = ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0));
bsdf *= brdf_lut.b; /* Bsdf intensity */
- bsdf *= M_1_2PI;
vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
return spec;
}
-#endif
-#if 0
-float direct_ggx_disc(vec3 N, vec3 L)
+vec3 direct_ggx_unit_disc(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0)
{
+ roughness = clamp(roughness, 0.0004, 0.999); /* Fix low roughness artifacts. */
+
+ vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
+ vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
+ vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
+ mat3 ltc_mat = ltc_matrix(ltc_lut);
+ vec3 Px = ld.l_right * ld.l_radius;
+ vec3 Py = ld.l_up * ld.l_radius;
+
+ vec3 points[3];
+ points[0] = -ld.l_forward - Px - Py;
+ points[1] = -ld.l_forward + Px - Py;
+ points[2] = -ld.l_forward + Px + Py;
+
+ float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points);
+ bsdf *= brdf_lut.b; /* Bsdf intensity */
+
+ vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
+
+ return spec;
}
#endif \ No newline at end of file
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 13586619fe9..e5c0cb9c9c9 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
@@ -9,12 +9,12 @@ 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)
{
- jitternoise = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).rg; /* Global variable */
- jitternoise.g = (jitternoise.g - 0.5) * 2.0;
+ jitternoise = texelfetch_noise_tex(gl_FragCoord.xy).rg; /* Global variable */
}
#ifdef HAMMERSLEY_SIZE
diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
new file mode 100644
index 00000000000..37106fc32bd
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
@@ -0,0 +1,55 @@
+
+layout(std140) uniform common_block {
+ mat4 pastViewProjectionMatrix;
+ vec4 viewVecs[2];
+ vec2 mipRatio[10]; /* To correct mip level texel mis-alignement */
+ /* Ambient Occlusion */
+ vec4 aoParameters[2];
+ /* Volumetric */
+ ivec4 volTexSize;
+ vec4 volDepthParameters; /* Parameters to the volume Z equation */
+ vec4 volInvTexSize;
+ vec4 volJitter;
+ vec4 volCoordScale; /* To convert volume uvs to screen uvs */
+ float volHistoryAlpha;
+ float volLightClamp;
+ float volShadowSteps;
+ bool volUseLights;
+ /* Screen Space Reflections */
+ vec4 ssrParameters;
+ float ssrBorderFac;
+ float ssrMaxRoughness;
+ float ssrFireflyFac;
+ float ssrBrdfBias;
+ bool ssrToggle;
+ /* SubSurface Scattering */
+ float sssJitterThreshold;
+ bool sssToggle;
+ /* Specular */
+ bool specToggle;
+ /* Lamps */
+ int laNumLight;
+ /* Probes */
+ int prbNumPlanar;
+ int prbNumRenderCube;
+ int prbNumRenderGrid;
+ int prbIrradianceVisSize;
+ float prbLodCubeMax;
+ float prbLodPlanarMax;
+};
+
+/* aoParameters */
+#define aoDistance aoParameters[0].x
+#define aoSamples aoParameters[0].y /* UNUSED */
+#define aoFactor aoParameters[0].z
+#define aoInvSamples aoParameters[0].w /* UNUSED */
+
+#define aoOffset aoParameters[1].x /* UNUSED */
+#define aoBounceFac aoParameters[1].y
+#define aoQuality aoParameters[1].z
+#define aoSettings aoParameters[1].w
+
+/* ssrParameters */
+#define ssrQuality ssrParameters.x
+#define ssrThickness ssrParameters.y
+#define ssrPixelSize ssrParameters.zw \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index 45c5c88e763..6d941ae6ec3 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -11,7 +11,7 @@ Closure nodetree_exec(void)
vec3 f0 = mix(dielectric, basecol, metallic);
vec3 N = (gl_FrontFacing) ? worldNormal : -worldNormal;
vec3 out_diff, out_spec, ssr_spec;
- eevee_closure_default(N, albedo, f0, 0, roughness, 1.0, out_diff, out_spec, ssr_spec);
+ eevee_closure_default(N, albedo, f0, 1, roughness, 1.0, out_diff, out_spec, ssr_spec);
Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0);
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 1c63051c65b..32edf709d88 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
@@ -12,8 +12,8 @@ uniform sampler2D normalBuffer;
void main()
{
- vec4 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xyxy;
- vec2 uvs = saturate(gl_FragCoord.xy * texel_size.xy);
+ vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy;
+ vec2 uvs = saturate(gl_FragCoord.xy * texel_size);
float depth = textureLod(depthBuffer, uvs, 0.0).r;
@@ -23,28 +23,32 @@ void main()
vec3 bent_normal;
float visibility;
-#if 1
- gtao_deferred(normal, viewPosition, depth, visibility, bent_normal);
-#else
- vec2 rand = vec2((1.0 / 4.0) * float((int(gl_FragCoord.y) & 0x1) * 2 + (int(gl_FragCoord.x) & 0x1)), 0.5);
- rand = fract(rand.x + texture(utilTex, vec3(floor(gl_FragCoord.xy * 0.5) / LUT_SIZE, 2.0)).rg);
- gtao(normal, viewPosition, rand, visibility, bent_normal);
-#endif
- denoise_ao(normal, depth, visibility, bent_normal);
+
+ vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy);
+
+ gtao_deferred(normal, viewPosition, noise, depth, visibility, bent_normal);
FragColor = vec4(visibility);
}
#else
-uniform float sampleNbr;
+
+#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()
{
- ivec2 hr_co = ivec2(gl_FragCoord.xy);
- ivec2 fs_co = get_fs_co(hr_co);
-
- vec2 uvs = saturate((vec2(fs_co) + 0.5) / vec2(textureSize(depthBuffer, 0)));
- float depth = textureLod(depthBuffer, uvs, 0.0).r;
+ vec2 uvs = saturate(gl_FragCoord.xy / vec2(textureSize(gtao_depthBuffer, 0).xy));
+ float depth = gtao_textureLod(gtao_depthBuffer, uvs, 0.0).r;
if (depth == 1.0) {
/* Do not trace for background */
@@ -56,14 +60,17 @@ void main()
depth = saturate(depth - 3e-6); /* Tweaked for 24bit depth buffer. */
vec3 viewPosition = get_view_space_from_depth(uvs, depth);
-
- float phi = get_phi(hr_co, fs_co, sampleNbr);
- float offset = get_offset(fs_co, sampleNbr);
+ vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy);
vec2 max_dir = get_max_dir(viewPosition.z);
+ vec4 dirs;
+ dirs.xy = get_ao_dir(noise.x * 0.5);
+ dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5);
- FragColor.xy = search_horizon_sweep(phi, viewPosition, uvs, offset, max_dir);
+ /* Search in 4 directions. */
+ FragColor.xy = search_horizon_sweep(dirs.xy, viewPosition, uvs, noise.y, max_dir);
+ FragColor.zw = search_horizon_sweep(dirs.zw, viewPosition, uvs, noise.y, max_dir);
/* Resize output for integer texture. */
- FragColor = pack_horizons(FragColor.xy).xyxy;
+ FragColor = pack_horizons(FragColor);
}
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
index ce6f3568cdf..65d3970a82a 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl
@@ -23,6 +23,10 @@ uniform sampler2D depthBuffer;
#define minmax(a, b) max(a, b)
#endif
+#ifdef GPU_INTEL
+out vec4 fragColor;
+#endif
+
void main()
{
ivec2 texelPos = ivec2(gl_FragCoord.xy);
@@ -61,5 +65,10 @@ void main()
}
#endif
+#ifdef GPU_INTEL
+ /* Use color format instead of 24bit depth texture */
+ fragColor = vec4(val);
+#else
gl_FragDepth = val;
+#endif
} \ No newline at end of file
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 1a01db3a1a3..73e284570cd 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
@@ -57,7 +57,7 @@ void main()
float inc = 2.0 * inv_samples;
float i = -1.0 + noise;
- FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ FragColor = vec4(0.0);
for (int j = 0; j < samples && j < MAX_SAMPLE; j++) {
FragColor += textureLod(colorBuffer, uvcoordsvar.xy + motion * i, 0.0) * inv_samples;
i += inc;
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 2dc8dfa0d1c..aa88e365d93 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -5,80 +5,78 @@
#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 */
-#define BRDF_BIAS 0.7
#define MAX_MIP 9.0
-uniform float fireflyFactor;
-uniform float maxRoughness;
+uniform ivec2 halfresOffset;
+
+ivec2 encode_hit_data(vec2 hit_pos, bool has_hit, bool is_planar)
+{
+ ivec2 hit_data = ivec2(saturate(hit_pos) * 32767.0); /* 16bit signed int limit */
+ hit_data.x *= (is_planar) ? -1 : 1;
+ hit_data.y *= (has_hit) ? 1 : -1;
+ return hit_data;
+}
+
+vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar)
+{
+ is_planar = (hit_data.x < 0);
+ has_hit = (hit_data.y > 0);
+ return vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */
+}
#ifdef STEP_RAYTRACE
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
-uniform int planar_count;
-uniform float noiseOffset;
-
-layout(location = 0) out vec4 hitData0;
-layout(location = 1) out vec4 hitData1;
-layout(location = 2) out vec4 hitData2;
-layout(location = 3) out vec4 hitData3;
+layout(location = 0) out ivec2 hitData;
+layout(location = 1) out float pdfData;
-vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ofs)
+void do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec4 rand)
{
- float pdf, NH;
- float jitter = fract(rand.x + ofs);
-
- /* Importance sampling bias */
- rand.x = mix(rand.x, 0.0, BRDF_BIAS);
-
- vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
- pdf = pdf_ggx_reflect(NH, a2);
+ float NH;
+ vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */
+ float pdf = pdf_ggx_reflect(NH, a2);
vec3 R = reflect(-V, H);
R = reflect(R, planeNormal);
/* If ray is bad (i.e. going below the plane) regenerate. */
if (dot(R, planeNormal) > 0.0) {
- vec3 H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
+ vec3 H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
pdf = pdf_ggx_reflect(NH, a2);
R = reflect(-V, H);
R = reflect(R, planeNormal);
}
- pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
- pdf *= -1.0; /* Tag as planar ray. */
+ pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */
/* Since viewspace hit position can land behind the camera in this case,
* we save the reflected view position (visualize it as the hit position
* below the reflection plane). This way it's garanted that the hit will
* be in front of the camera. That let us tag the bad rays with a negative
* sign in the Z component. */
- vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, jitter, ssrQuality, a2, false);
+ vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, rand.y, ssrQuality, a2, false);
- return vec4(hit_pos, pdf);
+ hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), true);
}
-vec4 do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec3 rand, float ofs)
+void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec4 rand)
{
- float pdf, NH;
- float jitter = fract(rand.x + ofs);
-
- /* Importance sampling bias */
- rand.x = mix(rand.x, 0.0, BRDF_BIAS);
-
- vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
- pdf = pdf_ggx_reflect(NH, a2);
+ float NH;
+ vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */
+ float pdf = pdf_ggx_reflect(NH, a2);
vec3 R = reflect(-V, H);
- pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */
+ pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */
- vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, a2, true);
+ vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, a2, true);
- return vec4(hit_pos, pdf);
+ hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), false);
}
void main()
@@ -87,20 +85,22 @@ void main()
ivec2 fullres_texel = ivec2(gl_FragCoord.xy);
ivec2 halfres_texel = fullres_texel;
#else
- ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2;
+ ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2 + halfresOffset;
ivec2 halfres_texel = ivec2(gl_FragCoord.xy);
#endif
float depth = texelFetch(depthBuffer, fullres_texel, 0).r;
+ /* Default: not hits. */
+ hitData = encode_hit_data(vec2(0.5), false, false);
+ pdfData = 0.0;
+
/* Early out */
+ /* We can't do discard because we don't clear the render target. */
if (depth == 1.0)
- discard;
+ return;
- vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
-#ifndef FULLRES
- uvs *= 2.0;
-#endif
+ vec2 uvs = vec2(fullres_texel) / vec2(textureSize(depthBuffer, 0));
/* Using view space */
vec3 viewPosition = get_view_space_from_depth(uvs, depth);
@@ -112,18 +112,24 @@ void main()
/* Early out */
if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0)
- discard;
+ return;
float roughness = speccol_roughness.a;
float roughnessSquared = max(1e-3, roughness * roughness);
float a2 = roughnessSquared * roughnessSquared;
- if (roughness > maxRoughness + 0.2) {
- hitData0 = hitData1 = hitData2 = hitData3 = vec4(0.0);
+ /* Early out */
+ if (roughness > ssrMaxRoughness + 0.2)
return;
- }
- vec3 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0).rba;
+ vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0);
+
+ /* Gives *perfect* reflection for very small roughness */
+ if (roughness < 0.04) {
+ rand.xzw *= 0.0;
+ }
+ /* Importance sampling bias */
+ rand.x = mix(rand.x, 0.0, ssrBrdfBias);
vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
vec3 wN = transform_direction(ViewMatrixInverse, N);
@@ -132,7 +138,7 @@ void main()
make_orthonormal_basis(N, T, B); /* Generate tangent space */
/* Planar Reflections */
- for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) {
PlanarData pd = planars_data[i];
float fade = probe_attenuation_planar(pd, worldPosition, wN, 0.0);
@@ -144,31 +150,12 @@ void main()
tracePosition = transform_point(ViewMatrix, tracePosition);
vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal);
- hitData0 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand, 0.0);
-#if (RAY_COUNT > 1)
- hitData1 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT));
-#endif
-#if (RAY_COUNT > 2)
- hitData2 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT));
-#endif
-#if (RAY_COUNT > 3)
- hitData3 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT));
-#endif
+ do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand);
return;
}
}
- /* TODO : Raytrace together if textureGather is supported. */
- hitData0 = do_ssr(V, N, T, B, viewPosition, a2, rand, 0.0);
-#if (RAY_COUNT > 1)
- hitData1 = do_ssr(V, N, T, B, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT));
-#endif
-#if (RAY_COUNT > 2)
- hitData2 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT));
-#endif
-#if (RAY_COUNT > 3)
- hitData3 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT));
-#endif
+ do_ssr(V, N, T, B, viewPosition, a2, rand);
}
#else /* STEP_RESOLVE */
@@ -177,30 +164,42 @@ uniform sampler2D prevColorBuffer; /* previous frame */
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
-uniform sampler2D hitBuffer0;
-uniform sampler2D hitBuffer1;
-uniform sampler2D hitBuffer2;
-uniform sampler2D hitBuffer3;
+uniform isampler2D hitBuffer;
+uniform sampler2D pdfBuffer;
+
+uniform int neighborOffset;
-uniform int probe_count;
-uniform int planar_count;
+const ivec2 neighbors[32] = ivec2[32](
+ ivec2( 0, 0), ivec2( 1, 1), ivec2(-2, 0), ivec2( 0, -2),
+ ivec2( 0, 0), ivec2( 1, -1), ivec2(-2, 0), ivec2( 0, 2),
+ ivec2( 0, 0), ivec2(-1, -1), ivec2( 2, 0), ivec2( 0, 2),
+ ivec2( 0, 0), ivec2(-1, 1), ivec2( 2, 0), ivec2( 0, -2),
-uniform mat4 PastViewProjectionMatrix;
+ ivec2( 0, 0), ivec2( 2, 2), ivec2(-2, 2), ivec2( 0, -1),
+ ivec2( 0, 0), ivec2( 2, -2), ivec2(-2, -2), ivec2( 0, 1),
+ ivec2( 0, 0), ivec2(-2, -2), ivec2(-2, 2), ivec2( 1, 0),
+ ivec2( 0, 0), ivec2( 2, 2), ivec2( 2, -2), ivec2(-1, 0)
+);
out vec4 fragColor;
-void fallback_cubemap(vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum)
+void fallback_cubemap(
+ vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum)
{
/* Specular probes */
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
+ vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, 1.0, rand.rg, bent_normal);
+#ifdef SSR_AO
+ float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal);
final_ao = specular_occlusion(dot(N, V), final_ao, roughness);
+#else
+ const float final_ao = 1.0;
+#endif
/* Starts at 1 because 0 is world probe */
- for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) {
+ for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, W);
@@ -251,90 +250,177 @@ float brightness(vec3 c)
vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
{
/* TODO real reprojection with motion vectors, etc... */
- return project_point(PastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
+ return project_point(pastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
}
-vec4 get_ssr_sample(
- sampler2D hitBuffer, PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared,
- float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel,
- inout float weight_acc)
+float get_sample_depth(vec2 hit_co, bool is_planar, float planar_index)
{
- vec4 hit_co_pdf = texelFetch(hitBuffer, target_texel, 0).rgba;
- bool has_hit = (hit_co_pdf.z > 0.0);
- bool is_planar = (hit_co_pdf.w < 0.0);
- hit_co_pdf.z = abs(hit_co_pdf.z);
- hit_co_pdf.w = abs(hit_co_pdf.w);
-
- /* Hit position in world space. */
- hit_co_pdf.xyz = get_view_space_from_depth(hit_co_pdf.xy, hit_co_pdf.z);
- vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz);
+ if (is_planar) {
+ return textureLod(planarDepth, vec3(hit_co, planar_index), 0.0).r;
+ }
+ else {
+ return textureLod(depthBuffer, hit_co, 0.0).r;
+ }
+}
- vec2 ref_uvs;
+vec3 get_hit_vector(
+ vec3 hit_pos, PlanarData pd, vec3 worldPosition, vec3 N, vec3 V, bool is_planar,
+ inout vec2 hit_co, inout float mask)
+{
vec3 hit_vec;
- float mask = 1.0;
+
if (is_planar) {
/* Reflect back the hit position to have it in non-reflected world space */
vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq);
hit_vec = hit_pos - trace_pos;
hit_vec = reflect(hit_vec, pd.pl_normal);
- ref_uvs = project_point(ProjectionMatrix, hit_co_pdf.xyz).xy * 0.5 + 0.5;
}
else {
/* Find hit position in previous frame. */
- ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
+ mask = screen_border_mask(gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0)));
+ hit_co = get_reprojected_reflection(hit_pos, worldPosition, N);
hit_vec = hit_pos - worldPosition;
- mask = screen_border_mask(gl_FragCoord.xy / texture_size);
}
- mask = min(mask, screen_border_mask(ref_uvs));
- mask *= float(has_hit);
- float hit_dist = max(1e-8, length(hit_vec));
- vec3 L = hit_vec / hit_dist;
+ mask = min(mask, screen_border_mask(hit_co));
+ return hit_vec;
+}
- float cone_footprint = hit_dist * cone_tan;
+vec3 get_scene_color(vec2 ref_uvs, float mip, float planar_index, bool is_planar)
+{
+ if (is_planar) {
+ return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, prbLodPlanarMax)).rgb;
+ }
+ else {
+ return textureLod(prevColorBuffer, ref_uvs, mip).rgb;
+ }
+}
+
+vec4 get_ssr_samples(
+ vec4 hit_pdf, ivec4 hit_data[2],
+ PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V,
+ float roughnessSquared, float cone_tan, vec2 source_uvs,
+ inout float weight_acc)
+{
+ bvec4 is_planar, has_hit;
+ vec4 hit_co[2];
+ hit_co[0].xy = decode_hit_data(hit_data[0].xy, has_hit.x, is_planar.x);
+ hit_co[0].zw = decode_hit_data(hit_data[0].zw, has_hit.y, is_planar.y);
+ hit_co[1].xy = decode_hit_data(hit_data[1].xy, has_hit.z, is_planar.z);
+ hit_co[1].zw = decode_hit_data(hit_data[1].zw, has_hit.w, is_planar.w);
+
+ vec4 hit_depth;
+ hit_depth.x = get_sample_depth(hit_co[0].xy, is_planar.x, planar_index);
+ hit_depth.y = get_sample_depth(hit_co[0].zw, is_planar.y, planar_index);
+ hit_depth.z = get_sample_depth(hit_co[1].xy, is_planar.z, planar_index);
+ hit_depth.w = get_sample_depth(hit_co[1].zw, is_planar.w, planar_index);
+
+ /* Hit position in view space. */
+ vec3 hit_view[4];
+ hit_view[0] = get_view_space_from_depth(hit_co[0].xy, hit_depth.x);
+ hit_view[1] = get_view_space_from_depth(hit_co[0].zw, hit_depth.y);
+ hit_view[2] = get_view_space_from_depth(hit_co[1].xy, hit_depth.z);
+ hit_view[3] = get_view_space_from_depth(hit_co[1].zw, hit_depth.w);
+
+ vec4 homcoord = vec4(hit_view[0].z, hit_view[1].z, hit_view[2].z, hit_view[3].z);
+ homcoord = ProjectionMatrix[2][3] * homcoord + ProjectionMatrix[3][3];
+
+ /* Hit position in world space. */
+ vec3 hit_pos[4];
+ hit_pos[0] = transform_point(ViewMatrixInverse, hit_view[0]);
+ hit_pos[1] = transform_point(ViewMatrixInverse, hit_view[1]);
+ hit_pos[2] = transform_point(ViewMatrixInverse, hit_view[2]);
+ hit_pos[3] = transform_point(ViewMatrixInverse, hit_view[3]);
+
+ /* Get actual hit vector and hit coordinate (from last frame). */
+ vec4 mask = vec4(1.0);
+ hit_pos[0] = get_hit_vector(hit_pos[0], pd, worldPosition, N, V, is_planar.x, hit_co[0].xy, mask.x);
+ hit_pos[1] = get_hit_vector(hit_pos[1], pd, worldPosition, N, V, is_planar.y, hit_co[0].zw, mask.y);
+ hit_pos[2] = get_hit_vector(hit_pos[2], pd, worldPosition, N, V, is_planar.z, hit_co[1].xy, mask.z);
+ hit_pos[3] = get_hit_vector(hit_pos[3], pd, worldPosition, N, V, is_planar.w, hit_co[1].zw, mask.w);
+
+ vec4 hit_dist;
+ hit_dist.x = length(hit_pos[0]);
+ hit_dist.y = length(hit_pos[1]);
+ hit_dist.z = length(hit_pos[2]);
+ hit_dist.w = length(hit_pos[3]);
+ hit_dist = max(vec4(1e-8), hit_dist);
+
+ /* Normalize */
+ hit_pos[0] /= hit_dist.x;
+ hit_pos[1] /= hit_dist.y;
+ hit_pos[2] /= hit_dist.z;
+ hit_pos[3] /= hit_dist.w;
/* Compute cone footprint in screen space. */
- float homcoord = ProjectionMatrix[2][3] * hit_co_pdf.z + ProjectionMatrix[3][3];
- cone_footprint = BRDF_BIAS * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
+ vec4 cone_footprint = hit_dist * cone_tan;
+ cone_footprint = ssrBrdfBias * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
/* Estimate a cone footprint to sample a corresponding mipmap level. */
- float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, MAX_MIP);
+ vec4 mip = log2(cone_footprint * max_v2(vec2(textureSize(depthBuffer, 0))));
+ mip = clamp(mip, 0.0, MAX_MIP);
/* Correct UVs for mipmaping mis-alignment */
- ref_uvs *= mip_ratio_interp(mip);
+ hit_co[0].xy *= mip_ratio_interp(mip.x);
+ hit_co[0].zw *= mip_ratio_interp(mip.y);
+ hit_co[1].xy *= mip_ratio_interp(mip.z);
+ hit_co[1].zw *= mip_ratio_interp(mip.w);
/* Slide 54 */
- float bsdf = bsdf_ggx(N, L, V, roughnessSquared);
- float weight = step(1e-8, hit_co_pdf.w) * bsdf / max(1e-8, hit_co_pdf.w);
- weight_acc += weight;
+ vec4 bsdf;
+ bsdf.x = bsdf_ggx(N, hit_pos[0], V, roughnessSquared);
+ bsdf.y = bsdf_ggx(N, hit_pos[1], V, roughnessSquared);
+ bsdf.z = bsdf_ggx(N, hit_pos[2], V, roughnessSquared);
+ bsdf.w = bsdf_ggx(N, hit_pos[3], V, roughnessSquared);
- vec3 sample;
- if (is_planar) {
- sample = textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, lodPlanarMax)).rgb;
- }
- else {
- sample = textureLod(prevColorBuffer, ref_uvs, mip).rgb;
- }
+ vec4 weight = step(1e-8, hit_pdf) * bsdf / max(vec4(1e-8), hit_pdf);
- /* Clamped brightness. */
- float luma = max(1e-8, brightness(sample));
- sample *= 1.0 - max(0.0, luma - fireflyFactor) / luma;
+ vec3 sample[4];
+ sample[0] = get_scene_color(hit_co[0].xy, mip.x, planar_index, is_planar.x);
+ sample[1] = get_scene_color(hit_co[0].zw, mip.y, planar_index, is_planar.y);
+ sample[2] = get_scene_color(hit_co[1].xy, mip.z, planar_index, is_planar.z);
+ sample[3] = get_scene_color(hit_co[1].zw, mip.w, planar_index, is_planar.w);
- /* Do not add light if ray has failed. */
- sample *= float(has_hit);
+ /* Clamped brightness. */
+ vec4 luma;
+ luma.x = brightness(sample[0]);
+ luma.y = brightness(sample[1]);
+ luma.z = brightness(sample[2]);
+ luma.w = brightness(sample[3]);
+ luma = max(vec4(1e-8), luma);
+ luma = 1.0 - max(vec4(0.0), luma - ssrFireflyFac) / luma;
+
+ sample[0] *= luma.x;
+ sample[1] *= luma.y;
+ sample[2] *= luma.z;
+ sample[3] *= luma.w;
/* Protection against NaNs in the history buffer.
* This could be removed if some previous pass has already
* sanitized the input. */
- if (any(isnan(sample))) {
- sample = vec3(0.0);
- weight = 0.0;
+ if (any(isnan(sample[0]))) {
+ sample[0] = vec3(0.0); weight.x = 0.0;
+ }
+ if (any(isnan(sample[1]))) {
+ sample[1] = vec3(0.0); weight.y = 0.0;
+ }
+ if (any(isnan(sample[2]))) {
+ sample[2] = vec3(0.0); weight.z = 0.0;
+ }
+ if (any(isnan(sample[3]))) {
+ sample[3] = vec3(0.0); weight.w = 0.0;
}
- return vec4(sample, mask) * weight;
-}
+ weight_acc += sum(weight);
-#define NUM_NEIGHBORS 4
+ /* Do not add light if ray has failed. */
+ vec4 accum;
+ accum = vec4(sample[0], mask.x) * weight.x * float(has_hit.x);
+ accum += vec4(sample[1], mask.y) * weight.y * float(has_hit.y);
+ accum += vec4(sample[2], mask.z) * weight.z * float(has_hit.z);
+ accum += vec4(sample[3], mask.w) * weight.w * float(has_hit.w);
+ return accum;
+}
void main()
{
@@ -344,9 +430,7 @@ void main()
#else
ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
#endif
- vec2 texture_size = vec2(textureSize(depthBuffer, 0));
- vec2 uvs = gl_FragCoord.xy / texture_size;
- vec3 rand = texelFetch(utilTex, ivec3(fullres_texel % LUT_SIZE, 2), 0).rba;
+ vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
float depth = textureLod(depthBuffer, uvs, 0.0).r;
@@ -366,10 +450,24 @@ void main()
if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0)
discard;
+ /* TODO optimize with textureGather */
+ /* Doing these fetches early to hide latency. */
+ vec4 hit_pdf;
+ hit_pdf.x = texelFetch(pdfBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).r;
+ hit_pdf.y = texelFetch(pdfBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).r;
+ hit_pdf.z = texelFetch(pdfBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).r;
+ hit_pdf.w = texelFetch(pdfBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).r;
+
+ ivec4 hit_data[2];
+ hit_data[0].xy = texelFetch(hitBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).rg;
+ hit_data[0].zw = texelFetch(hitBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).rg;
+ hit_data[1].xy = texelFetch(hitBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).rg;
+ hit_data[1].zw = texelFetch(hitBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).rg;
+
/* Find Planar Reflections affecting this pixel */
PlanarData pd;
float planar_index;
- for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) {
pd = planars_data[i];
float fade = probe_attenuation_planar(pd, worldPosition, N, 0.0);
@@ -390,55 +488,21 @@ void main()
float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos;
cone_tan *= mix(saturate(dot(N, -V) * 2.0), 1.0, roughness); /* Elongation fit */
- vec2 source_uvs = project_point(PastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5;
+ vec2 source_uvs = project_point(pastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5;
vec4 ssr_accum = vec4(0.0);
float weight_acc = 0.0;
- const ivec2 neighbors[9] = ivec2[9](
- ivec2(0, 0),
-
- ivec2(0, 1),
- ivec2(-1, -1), ivec2(1, -1),
-
- ivec2(-1, 1), ivec2(1, 1),
- ivec2(0, -1),
-
- ivec2(-1, 0), ivec2(1, 0)
- );
- ivec2 invert_neighbor;
- invert_neighbor.x = ((fullres_texel.x & 0x1) == 0) ? 1 : -1;
- invert_neighbor.y = ((fullres_texel.y & 0x1) == 0) ? 1 : -1;
-
- if (roughness < maxRoughness + 0.2) {
- for (int i = 0; i < NUM_NEIGHBORS; i++) {
- ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor;
-
- ssr_accum += get_ssr_sample(hitBuffer0, pd, planar_index, worldPosition, N, V,
- roughnessSquared, cone_tan, source_uvs,
- texture_size, target_texel, weight_acc);
-#if (RAY_COUNT > 1)
- ssr_accum += get_ssr_sample(hitBuffer1, pd, planar_index, worldPosition, N, V,
- roughnessSquared, cone_tan, source_uvs,
- texture_size, target_texel, weight_acc);
-#endif
-#if (RAY_COUNT > 2)
- ssr_accum += get_ssr_sample(hitBuffer2, pd, planar_index, worldPosition, N, V,
- roughnessSquared, cone_tan, source_uvs,
- texture_size, target_texel, weight_acc);
-#endif
-#if (RAY_COUNT > 3)
- ssr_accum += get_ssr_sample(hitBuffer3, pd, planar_index, worldPosition, N, V,
- roughnessSquared, cone_tan, source_uvs,
- texture_size, target_texel, weight_acc);
-#endif
- }
+
+ if (roughness < ssrMaxRoughness + 0.2) {
+ ssr_accum += get_ssr_samples(hit_pdf, hit_data, pd, planar_index, worldPosition, N, V,
+ roughnessSquared, cone_tan, source_uvs, weight_acc);
}
/* Compute SSR contribution */
if (weight_acc > 0.0) {
ssr_accum /= weight_acc;
/* fade between 0.5 and 1.0 roughness */
- ssr_accum.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ ssr_accum.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
accumulate_light(ssr_accum.rgb, ssr_accum.a, spec_accum);
}
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 88e71a060c5..184eac54c26 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl
@@ -8,16 +8,19 @@ layout(std140) uniform sssProfile {
int sss_samples;
};
-uniform float jitterThreshold;
uniform sampler2D depthBuffer;
uniform sampler2D sssData;
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 */
out vec4 FragColor;
uniform mat4 ProjectionMatrix;
-uniform vec4 viewvecs[2];
float get_view_z_from_depth(float depth)
{
@@ -26,7 +29,7 @@ float get_view_z_from_depth(float depth)
return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
}
else {
- return viewvecs[0].z + depth * viewvecs[1].z;
+ return viewVecs[0].z + depth * viewVecs[1].z;
}
}
@@ -41,7 +44,7 @@ void main(void)
vec4 sss_data = texture(sssData, uvs).rgba;
float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r);
- float rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2), 0).r;
+ float rand = texelfetch_noise_tex(gl_FragCoord.xy).r;
#ifdef FIRST_PASS
float angle = M_2PI * rand + M_PI_2;
vec2 dir = vec2(1.0, 0.0);
@@ -61,7 +64,7 @@ void main(void)
vec3 accum = sss_data.rgb * kernel[0].rgb;
for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) {
- vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand);
+ vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand);
vec3 color = texture(sssData, sample_uv).rgb;
float sample_depth = texture(depthBuffer, sample_uv).r;
sample_depth = get_view_z_from_depth(sample_depth);
diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
index 76d20486d3d..132cc16fcbd 100644
--- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl
@@ -1,6 +1,5 @@
uniform sampler2DArray irradianceGrid;
-uniform int irradianceVisibilitySize;
#define IRRADIANCE_LIB
@@ -81,8 +80,8 @@ IrradianceData load_irradiance_cell(int cell, vec3 N)
float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range)
{
/* Keep in sync with diffuse_filter_probe() */
- ivec2 cell_co = ivec2(irradianceVisibilitySize);
- ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / irradianceVisibilitySize;
+ ivec2 cell_co = ivec2(prbIrradianceVisSize);
+ ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / prbIrradianceVisSize;
cell_co.x *= (cell % cell_per_row_col.x);
cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y;
float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y);
@@ -90,8 +89,8 @@ float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed
vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
vec2 co = vec2(cell_co) * texel_size;
- vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize)));
- uv *= vec2(irradianceVisibilitySize) * texel_size;
+ vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(prbIrradianceVisSize)));
+ uv *= vec2(prbIrradianceVisSize) * texel_size;
vec4 data = texture(irradianceGrid, vec3(co + uv, layer));
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
index 933f056c401..1c7956bb807 100644
--- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -161,7 +161,7 @@ float light_visibility(LightData ld, vec3 W,
float x = dot(ld.l_right, lL) / ld.l_sizex;
float y = dot(ld.l_up, lL) / ld.l_sizey;
- float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+ float ellipse = inversesqrt(1.0 + x * x + y * y);
float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
@@ -203,14 +203,13 @@ float light_visibility(LightData ld, vec3 W,
vec3 T, B;
make_orthonormal_basis(L.xyz / L.w, T, B);
- vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
- /* XXX This is a hack to not have noise correlation artifacts.
- * A better solution to have better noise is welcome. */
- rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_contact_spread;
+ vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
+ /* WATCH THIS : This still seems to have correlation artifacts for low samples. */
+ rand.zw *= fast_sqrt(rand.y) * data.sh_contact_spread;
/* We use the full l_vector.xyz so that the spread is minimize
* if the shading point is further away from the light source */
- vec3 ray_dir = L.xyz + T * rand.y + B * rand.z;
+ vec3 ray_dir = L.xyz + T * rand.z + B * rand.w;
ray_dir = transform_direction(ViewMatrix, ray_dir);
ray_dir = normalize(ray_dir);
vec3 ray_origin = viewPosition + viewNormal * data.sh_contact_offset;
@@ -235,8 +234,7 @@ float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
{
#ifdef USE_LTC
if (ld.l_type == SUN) {
- /* TODO disk area light */
- return direct_diffuse_sun(ld, N);
+ return direct_diffuse_unit_disc(ld, N, V);
}
else if (ld.l_type == AREA) {
return direct_diffuse_rectangle(ld, N, V, l_vector);
@@ -258,8 +256,7 @@ vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness
{
#ifdef USE_LTC
if (ld.l_type == SUN) {
- /* TODO disk area light */
- return direct_ggx_sun(ld, N, V, roughness, f0);
+ return direct_ggx_unit_disc(ld, N, V, roughness, f0);
}
else if (ld.l_type == AREA) {
return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0);
@@ -298,9 +295,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
{
#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS)
return vec3(0.0);
-#endif
-
-#ifndef VOLUMETRICS
+#else
vec3 vis = vec3(1.0);
/* Only shadowed light can produce translucency */
@@ -313,14 +308,13 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
vec3 T, B;
make_orthonormal_basis(L.xyz / L.w, T, B);
- vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
- /* XXX This is a hack to not have noise correlation artifacts.
- * A better solution to have better noise is welcome. */
- rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_blur;
+ vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
+ /* WATCH THIS : This still seems to have correlation artifacts for low samples. */
+ rand.zw *= fast_sqrt(rand.y) * data.sh_blur;
/* We use the full l_vector.xyz so that the spread is minimize
* if the shading point is further away from the light source */
- W = W + T * rand.y + B * rand.z;
+ W = W + T * rand.z + B * rand.w;
if (ld.l_type == SUN) {
ShadowCascadeData scd = shadows_cascade_data[int(data.sh_data_start)];
@@ -374,19 +368,24 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
/* TODO : put this out of the shader. */
float falloff;
if (ld.l_type == AREA) {
- vis *= 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI);
+ vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
+ vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
vis /= (l_vector.w * l_vector.w);
falloff = dot(N, l_vector.xyz / l_vector.w);
}
else if (ld.l_type == SUN) {
+ vis *= (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/
+ vis *= M_2PI * 0.78; /* Matching cycles with point light. */
+ vis *= 0.082; /* XXX ad hoc, empirical */
falloff = dot(N, -ld.l_forward);
}
else {
- vis *= 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI);
+ vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0);
+ vis *= 1.5; /* XXX ad hoc, empirical */
vis /= (l_vector.w * l_vector.w);
falloff = dot(N, l_vector.xyz / l_vector.w);
}
- vis *= M_1_PI; /* Normalize */
+ // vis *= M_1_PI; /* Normalize */
/* Applying profile */
vis *= sss_profile(abs(delta) / scale);
@@ -400,7 +399,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale)
float x = dot(ld.l_right, lL) / ld.l_sizex;
float y = dot(ld.l_up, lL) / ld.l_sizey;
- float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+ float ellipse = inversesqrt(1.0 + x * x + y * y);
float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
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 fc0b5b9548b..d10f4bc0d42 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
@@ -11,5 +11,5 @@ void main()
? normalize(cameraPos - worldPosition)
: cameraForward;
vec3 N = normalize(worldNormal);
- FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, lodCubeMax).rgb, 1.0);
+ FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, prbLodCubeMax).rgb, 1.0);
}
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 eb4315c93a3..b19ee7a9ea3 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
@@ -3,6 +3,7 @@ uniform samplerCube probeHdr;
uniform int probeSize;
uniform float lodFactor;
uniform float lodMax;
+uniform float intensityFac;
in vec3 worldPosition;
@@ -192,6 +193,6 @@ void main()
}
}
- FragColor = irradiance_encode(out_radiance / weight);
+ FragColor = irradiance_encode(intensityFac * out_radiance / weight);
#endif
} \ No newline at end of file
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 33714c5293c..3aec3ce4642 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
@@ -5,6 +5,7 @@ uniform float texelSize;
uniform float lodFactor;
uniform float lodMax;
uniform float paddingSize;
+uniform float intensityFac;
in vec3 worldPosition;
@@ -82,5 +83,5 @@ void main() {
}
}
- FragColor = vec4(out_radiance / weight, 1.0);
+ FragColor = vec4(intensityFac * out_radiance / weight, 1.0);
} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
index e914228aded..429f6ea92e4 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl
@@ -1,10 +1,7 @@
/* ----------- Uniforms --------- */
uniform sampler2DArray probePlanars;
-uniform float lodPlanarMax;
-
uniform sampler2DArray probeCubes;
-uniform float lodCubeMax;
/* ----------- Structures --------- */
@@ -162,12 +159,12 @@ vec3 probe_evaluate_cube(float id, CubeData cd, vec3 W, vec3 R, float roughness)
float fac = saturate(original_roughness * 2.0 - 1.0);
R = mix(intersection, R, fac * fac);
- return textureLod_octahedron(probeCubes, vec4(R, id), roughness * lodCubeMax, lodCubeMax).rgb;
+ return textureLod_octahedron(probeCubes, vec4(R, id), roughness * prbLodCubeMax, prbLodCubeMax).rgb;
}
vec3 probe_evaluate_world_spec(vec3 R, float roughness)
{
- return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * lodCubeMax, lodCubeMax).rgb;
+ return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * prbLodCubeMax, prbLodCubeMax).rgb;
}
vec3 probe_evaluate_planar(
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 6ecaf0a627b..cc66b477da0 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -2,19 +2,12 @@
#ifndef LIT_SURFACE_UNIFORM
#define LIT_SURFACE_UNIFORM
-uniform int light_count;
-uniform int probe_count;
-uniform int grid_count;
-uniform int planar_count;
-
-uniform bool specToggle;
-uniform bool ssrToggle;
-
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;
@@ -28,9 +21,6 @@ in vec3 worldNormal;
in vec3 viewNormal;
#endif
-uniform float maxRoughness;
-uniform int rayCount;
-
#endif /* LIT_SURFACE_UNIFORM */
/** AUTO CONFIG
@@ -176,7 +166,7 @@ void CLOSURE_NAME(
vec3 V = cameraVec;
- vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0));
+ vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
/* ---------------------------------------------------------------- */
/* -------------------- SCENE LAMPS LIGHTING ---------------------- */
@@ -187,7 +177,7 @@ void CLOSURE_NAME(
norm_view = normalize(cross(norm_view, N)); /* Normal facing view */
#endif
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */
@@ -266,7 +256,7 @@ void CLOSURE_NAME(
/* Planar Reflections */
/* ---------------------------- */
- for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) {
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar && spec_accum.a < 0.999; ++i) {
PlanarData pd = planars_data[i];
/* Fade on geometric normal. */
@@ -312,17 +302,11 @@ void CLOSURE_NAME(
/* Screen Space Refraction */
/* ---------------------------- */
#ifdef USE_REFRACTION
- if (ssrToggle && roughness < maxRoughness + 0.2) {
+ if (ssrToggle && roughness < ssrMaxRoughness + 0.2) {
/* Find approximated position of the 2nd refraction event. */
vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition;
-
- float ray_ofs = 1.0 / float(rayCount);
- vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw, 0.0);
- if (rayCount > 1) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
- if (rayCount > 2) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
- if (rayCount > 3) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
- trans /= float(rayCount);
- trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
+ vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand);
+ trans.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
accumulate_light(trans.rgb, trans.a, refr_accum);
}
#endif
@@ -342,7 +326,7 @@ void CLOSURE_NAME(
#endif
/* Starts at 1 because 0 is world probe */
- for (int i = 1; ACCUM.a < 0.999 && i < probe_count && i < MAX_PROBE; ++i) {
+ for (int i = 1; ACCUM.a < 0.999 && i < prbNumRenderCube && i < MAX_PROBE; ++i) {
CubeData cd = probes_data[i];
float fade = probe_attenuation_cube(cd, worldPosition);
@@ -402,7 +386,7 @@ void CLOSURE_NAME(
/* ---------------------------- */
#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
vec3 bent_normal;
- float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal);
+ float final_ao = occlusion_compute(N, viewPosition, ao, rand, bent_normal);
#endif
@@ -417,12 +401,14 @@ void CLOSURE_NAME(
/* This factor is outputed to be used by SSR in order
* to match the intensity of the regular reflections. */
ssr_spec = F_ibl(f0, brdf_lut);
- if (!(ssrToggle && ssr_id == outputSsrId)) {
- /* The SSR pass recompute the occlusion to not apply it to the SSR */
- ssr_spec *= specular_occlusion(NV, final_ao, roughness);
+ float spec_occlu = specular_occlusion(NV, final_ao, roughness);
+
+ /* The SSR pass recompute the occlusion to not apply it to the SSR */
+ if (ssrToggle && ssr_id == outputSsrId) {
+ spec_occlu = 1.0;
}
- out_spec += spec_accum.rgb * ssr_spec * float(specToggle);
+ out_spec += spec_accum.rgb * ssr_spec * spec_occlu * float(specToggle);
#endif
#ifdef CLOSURE_REFRACTION
@@ -452,7 +438,7 @@ void CLOSURE_NAME(
/* Irradiance Grids */
/* ---------------------------- */
/* Start at 1 because 0 is world irradiance */
- for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) {
+ for (int i = 1; i < MAX_GRID && i < prbNumRenderGrid && diff_accum.a < 0.999; ++i) {
GridData gd = grids_data[i];
vec3 localpos;
@@ -467,7 +453,7 @@ void CLOSURE_NAME(
/* ---------------------------- */
/* World Diffuse */
/* ---------------------------- */
- if (diff_accum.a < 0.999 && grid_count > 0) {
+ if (diff_accum.a < 0.999 && prbNumRenderGrid > 0) {
vec3 diff = probe_evaluate_world_diff(bent_normal);
accumulate_light(diff, 1.0, diff_accum);
}
diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
index ffaa81c3638..5c62cb19152 100644
--- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
@@ -1,150 +1,140 @@
-/* Mainly From https://eheitzresearch.wordpress.com/415-2/ */
+/**
+ * Adapted from :
+ * Real-Time Polygonal-Light Shading with Linearly Transformed Cosines.
+ * Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt.
+ * ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016.
+ * Project page: https://eheitzresearch.wordpress.com/415-2/
+ **/
#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 */
-/* from Real-Time Area Lighting: a Journey from Research to Production
- * Stephen Hill and Eric Heitz */
-float edge_integral(vec3 p1, vec3 p2)
+/* Diffuse *clipped* sphere integral. */
+float diffuse_sphere_integral_lut(float avg_dir_z, float form_factor)
{
-#if 0
- /* more accurate replacement of acos */
- float x = dot(p1, p2);
- float y = abs(x);
+ vec2 uv = vec2(avg_dir_z * 0.5 + 0.5, form_factor);
+ uv = uv * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
- float a = 5.42031 + (3.12829 + 0.0902326 * y) * y;
- float b = 3.45068 + (4.18814 + y) * y;
- float theta_sintheta = a / b;
-
- if (x < 0.0) {
- theta_sintheta = (M_PI / sqrt(1.0 - x * x)) - theta_sintheta;
- }
- vec3 u = cross(p1, p2);
- return theta_sintheta * dot(u, N);
-#endif
- float cos_theta = dot(p1, p2);
- cos_theta = clamp(cos_theta, -0.9999, 0.9999);
+ return texture(utilTex, vec3(uv, 1.0)).w;
+}
- float theta = acos(cos_theta);
- vec3 u = normalize(cross(p1, p2));
- return theta * cross(p1, p2).z / sin(theta);
+float diffuse_sphere_integral_cheap(float avg_dir_z, float form_factor)
+{
+ return max((form_factor * form_factor + avg_dir_z) / (form_factor + 1.0), 0.0);
}
-int clip_quad_to_horizon(inout vec3 L[5])
+/**
+ * An extended version of the implementation from
+ * "How to solve a cubic equation, revisited"
+ * http://momentsingraphics.de/?p=105
+ **/
+vec3 solve_cubic(vec4 coefs)
{
- /* detect clipping config */
- int config = 0;
- if (L[0].z > 0.0) config += 1;
- if (L[1].z > 0.0) config += 2;
- if (L[2].z > 0.0) config += 4;
- if (L[3].z > 0.0) config += 8;
+ /* Normalize the polynomial */
+ coefs.xyz /= coefs.w;
+ /* Divide middle coefficients by three */
+ coefs.yz /= 3.0;
- /* clip */
- int n = 0;
+ float A = coefs.w;
+ float B = coefs.z;
+ float C = coefs.y;
+ float D = coefs.x;
- if (config == 0)
- {
- /* clip all */
- }
- else if (config == 1) /* V1 clip V2 V3 V4 */
- {
- n = 3;
- L[1] = -L[1].z * L[0] + L[0].z * L[1];
- L[2] = -L[3].z * L[0] + L[0].z * L[3];
- }
- else if (config == 2) /* V2 clip V1 V3 V4 */
- {
- n = 3;
- L[0] = -L[0].z * L[1] + L[1].z * L[0];
- L[2] = -L[2].z * L[1] + L[1].z * L[2];
- }
- else if (config == 3) /* V1 V2 clip V3 V4 */
- {
- n = 4;
- L[2] = -L[2].z * L[1] + L[1].z * L[2];
- L[3] = -L[3].z * L[0] + L[0].z * L[3];
- }
- else if (config == 4) /* V3 clip V1 V2 V4 */
- {
- n = 3;
- L[0] = -L[3].z * L[2] + L[2].z * L[3];
- L[1] = -L[1].z * L[2] + L[2].z * L[1];
- }
- else if (config == 5) /* V1 V3 clip V2 V4) impossible */
- {
- n = 0;
- }
- else if (config == 6) /* V2 V3 clip V1 V4 */
- {
- n = 4;
- L[0] = -L[0].z * L[1] + L[1].z * L[0];
- L[3] = -L[3].z * L[2] + L[2].z * L[3];
- }
- else if (config == 7) /* V1 V2 V3 clip V4 */
- {
- n = 5;
- L[4] = -L[3].z * L[0] + L[0].z * L[3];
- L[3] = -L[3].z * L[2] + L[2].z * L[3];
- }
- else if (config == 8) /* V4 clip V1 V2 V3 */
- {
- n = 3;
- L[0] = -L[0].z * L[3] + L[3].z * L[0];
- L[1] = -L[2].z * L[3] + L[3].z * L[2];
- L[2] = L[3];
- }
- else if (config == 9) /* V1 V4 clip V2 V3 */
- {
- n = 4;
- L[1] = -L[1].z * L[0] + L[0].z * L[1];
- L[2] = -L[2].z * L[3] + L[3].z * L[2];
- }
- else if (config == 10) /* V2 V4 clip V1 V3) impossible */
- {
- n = 0;
- }
- else if (config == 11) /* V1 V2 V4 clip V3 */
- {
- n = 5;
- L[4] = L[3];
- L[3] = -L[2].z * L[3] + L[3].z * L[2];
- L[2] = -L[2].z * L[1] + L[1].z * L[2];
- }
- else if (config == 12) /* V3 V4 clip V1 V2 */
+ /* Compute the Hessian and the discriminant */
+ vec3 delta = vec3(
+ -coefs.z*coefs.z + coefs.y,
+ -coefs.y*coefs.z + coefs.x,
+ dot(vec2(coefs.z, -coefs.y), coefs.xy)
+ );
+
+ /* Discriminant */
+ float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy);
+
+ vec2 xlc, xsc;
+
+ /* Algorithm A */
{
- n = 4;
- L[1] = -L[1].z * L[2] + L[2].z * L[1];
- L[0] = -L[0].z * L[3] + L[3].z * L[0];
+ float A_a = 1.0;
+ float C_a = delta.x;
+ float D_a = -2.0 * B * delta.x + delta.y;
+
+ /* Take the cubic root of a normalized complex number */
+ float theta = atan(sqrt(discr), -D_a) / 3.0;
+
+ float x_1a = 2.0 * sqrt(-C_a) * cos(theta);
+ float x_3a = 2.0 * sqrt(-C_a) * cos(theta + (2.0 / 3.0) * M_PI);
+
+ float xl;
+ if ((x_1a + x_3a) > 2.0 * B) {
+ xl = x_1a;
+ }
+ else {
+ xl = x_3a;
+ }
+
+ xlc = vec2(xl - B, A);
}
- else if (config == 13) /* V1 V3 V4 clip V2 */
+
+ /* Algorithm D */
{
- n = 5;
- L[4] = L[3];
- L[3] = L[2];
- L[2] = -L[1].z * L[2] + L[2].z * L[1];
- L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ float A_d = D;
+ float C_d = delta.z;
+ float D_d = -D * delta.y + 2.0 * C * delta.z;
+
+ /* Take the cubic root of a normalized complex number */
+ float theta = atan(D * sqrt(discr), -D_d) / 3.0;
+
+ float x_1d = 2.0 * sqrt(-C_d) * cos(theta);
+ float x_3d = 2.0 * sqrt(-C_d) * cos(theta + (2.0 / 3.0) * M_PI);
+
+ float xs;
+ if (x_1d + x_3d < 2.0 * C)
+ xs = x_1d;
+ else
+ xs = x_3d;
+
+ xsc = vec2(-D, xs + C);
}
- else if (config == 14) /* V2 V3 V4 clip V1 */
- {
- n = 5;
- L[4] = -L[0].z * L[3] + L[3].z * L[0];
- L[0] = -L[0].z * L[1] + L[1].z * L[0];
+
+ float E = xlc.y * xsc.y;
+ float F = -xlc.x * xsc.y - xlc.y * xsc.x;
+ float G = xlc.x * xsc.x;
+
+ vec2 xmc = vec2(C * F - B * G, -B * F + C * E);
+
+ vec3 root = vec3(xsc.x / xsc.y,
+ xmc.x / xmc.y,
+ xlc.x / xlc.y);
+
+ if (root.x < root.y && root.x < root.z) {
+ root.xyz = root.yxz;
}
- else if (config == 15) /* V1 V2 V3 V4 */
- {
- n = 4;
+ else if (root.z < root.x && root.z < root.y) {
+ root.xyz = root.xzy;
}
- if (n == 3)
- L[3] = L[0];
- if (n == 4)
- L[4] = L[0];
+ return root;
+}
+
+/* from Real-Time Area Lighting: a Journey from Research to Production
+ * Stephen Hill and Eric Heitz */
+vec3 edge_integral_vec(vec3 v1, vec3 v2)
+{
+ float x = dot(v1, v2);
+ float y = abs(x);
+
+ float a = 0.8543985 + (0.4965155 + 0.0145206 * y) * y;
+ float b = 3.4175940 + (4.1616724 + y) * y;
+ float v = a / b;
- return n;
+ float theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt(max(1.0 - x * x, 1e-7)) - v;
+
+ return cross(v1, v2) * theta_sintheta;
}
mat3 ltc_matrix(vec4 lut)
@@ -159,7 +149,7 @@ mat3 ltc_matrix(vec4 lut)
return Minv;
}
-float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4])
+void ltc_transform_quad(vec3 N, vec3 V, mat3 Minv, inout vec3 corners[4])
{
/* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
V = normalize(V + 1e-8);
@@ -172,42 +162,51 @@ float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4])
/* rotate area light in (T1, T2, R) basis */
Minv = Minv * transpose(mat3(T1, T2, N));
- /* polygon (allocate 5 vertices for clipping) */
- vec3 L[5];
- L[0] = Minv * corners[0];
- L[1] = Minv * corners[1];
- L[2] = Minv * corners[2];
- L[3] = Minv * corners[3];
-
- int n = clip_quad_to_horizon(L);
-
- if (n == 0)
- return 0.0;
-
- /* project onto sphere */
- L[0] = normalize(L[0]);
- L[1] = normalize(L[1]);
- L[2] = normalize(L[2]);
- L[3] = normalize(L[3]);
- L[4] = normalize(L[4]);
-
- /* integrate */
- float sum = 0.0;
-
- sum += edge_integral(L[0], L[1]);
- sum += edge_integral(L[1], L[2]);
- sum += edge_integral(L[2], L[3]);
- if (n >= 4)
- sum += edge_integral(L[3], L[4]);
- if (n == 5)
- sum += edge_integral(L[4], L[0]);
-
- return abs(sum);
+ /* Apply LTC inverse matrix. */
+ corners[0] = normalize(Minv * corners[0]);
+ corners[1] = normalize(Minv * corners[1]);
+ corners[2] = normalize(Minv * corners[2]);
+ corners[3] = normalize(Minv * corners[3]);
}
-/* Aproximate circle with an octogone */
-#define LTC_CIRCLE_RES 8
-float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES])
+/* If corners have already pass through ltc_transform_quad(), then N **MUST** be vec3(0.0, 0.0, 1.0),
+ * corresponding to the Up axis of the shading basis. */
+float ltc_evaluate_quad(vec3 corners[4], vec3 N)
+{
+ /* Approximation using a sphere of the same solid angle than the quad.
+ * Finding the clipped sphere diffuse integral is easier than clipping the quad. */
+ vec3 avg_dir;
+ avg_dir = edge_integral_vec(corners[0], corners[1]);
+ avg_dir += edge_integral_vec(corners[1], corners[2]);
+ avg_dir += edge_integral_vec(corners[2], corners[3]);
+ avg_dir += edge_integral_vec(corners[3], corners[0]);
+
+ float form_factor = length(avg_dir);
+ float avg_dir_z = dot(N, avg_dir / form_factor);
+
+#if 1 /* use tabulated horizon-clipped sphere */
+ return form_factor * diffuse_sphere_integral_lut(avg_dir_z, form_factor);
+#else /* Less accurate version, a bit cheaper. */
+ return form_factor * diffuse_sphere_integral_cheap(avg_dir_z, form_factor);
+#endif
+}
+
+/* If disk does not need to be transformed and is already front facing. */
+float ltc_evaluate_disk_simple(float disk_radius, float NL)
+{
+ float r_sqr = disk_radius * disk_radius;
+ float one_r_sqr = 1.0 + r_sqr;
+ float form_factor = r_sqr * inversesqrt(one_r_sqr * one_r_sqr);
+
+#if 1 /* use tabulated horizon-clipped sphere */
+ return form_factor * diffuse_sphere_integral_lut(NL, form_factor);
+#else /* Less accurate version, a bit cheaper. */
+ return form_factor * diffuse_sphere_integral_cheap(NL, form_factor);
+#endif
+}
+
+/* disk_points are WS vectors from the shading point to the disk "bounding domain" */
+float ltc_evaluate_disk(vec3 N, vec3 V, mat3 Minv, vec3 disk_points[3])
{
/* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */
V = normalize(V + 1e-8);
@@ -218,23 +217,106 @@ float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES])
T2 = cross(N, T1);
/* rotate area light in (T1, T2, R) basis */
- Minv = Minv * transpose(mat3(T1, T2, N));
+ mat3 R = transpose(mat3(T1, T2, N));
- for (int i = 0; i < LTC_CIRCLE_RES; ++i) {
- p[i] = Minv * p[i];
- /* clip to horizon */
- p[i].z = max(0.0, p[i].z);
- /* project onto sphere */
- p[i] = normalize(p[i]);
- }
+ /* Intermediate step: init ellipse. */
+ vec3 L_[3];
+ L_[0] = mul(R, disk_points[0]);
+ L_[1] = mul(R, disk_points[1]);
+ L_[2] = mul(R, disk_points[2]);
+
+ vec3 C = 0.5 * (L_[0] + L_[2]);
+ vec3 V1 = 0.5 * (L_[1] - L_[2]);
+ vec3 V2 = 0.5 * (L_[1] - L_[0]);
+
+ /* Transform ellipse by Minv. */
+ C = Minv * C;
+ V1 = Minv * V1;
+ V2 = Minv * V2;
+
+ /* Compute eigenvectors of new ellipse. */
- /* integrate */
- float sum = 0.0;
- for (int i = 0; i < LTC_CIRCLE_RES - 1; ++i) {
- sum += edge_integral(p[i], p[i + 1]);
+ float d11 = dot(V1, V1);
+ float d22 = dot(V2, V2);
+ float d12 = dot(V1, V2);
+ float a, b; /* Eigenvalues */
+ const float threshold = 0.0007; /* Can be adjusted. Fix artifacts. */
+ if (abs(d12) / sqrt(d11 * d22) > threshold) {
+ float tr = d11 + d22;
+ float det = -d12 * d12 + d11 * d22;
+
+ /* use sqrt matrix to solve for eigenvalues */
+ det = sqrt(det);
+ float u = 0.5 * sqrt(tr - 2.0 * det);
+ float v = 0.5 * sqrt(tr + 2.0 * det);
+ float e_max = (u + v);
+ float e_min = (u - v);
+ e_max *= e_max;
+ e_min *= e_min;
+
+ vec3 V1_, V2_;
+ if (d11 > d22) {
+ V1_ = d12 * V1 + (e_max - d11) * V2;
+ V2_ = d12 * V1 + (e_min - d11) * V2;
+ }
+ else {
+ V1_ = d12 * V2 + (e_max - d22) * V1;
+ V2_ = d12 * V2 + (e_min - d22) * V1;
+ }
+
+ a = 1.0 / e_max;
+ b = 1.0 / e_min;
+ V1 = normalize(V1_);
+ V2 = normalize(V2_);
}
- sum += edge_integral(p[LTC_CIRCLE_RES - 1], p[0]);
+ else {
+ a = 1.0 / d11;
+ b = 1.0 / d22;
+ V1 *= sqrt(a);
+ V2 *= sqrt(b);
+ }
+
+ /* Now find front facing ellipse with same solid angle. */
- return max(0.0, sum);
+ vec3 V3 = normalize(cross(V1, V2));
+ if (dot(C, V3) < 0.0)
+ V3 *= -1.0;
+
+ float L = dot(V3, C);
+ float x0 = dot(V1, C) / L;
+ float y0 = dot(V2, C) / L;
+
+ a *= L*L;
+ b *= L*L;
+
+ float c0 = a * b;
+ float c1 = a * b * (1.0 + x0 * x0 + y0 * y0) - a - b;
+ float c2 = 1.0 - a * (1.0 + x0 * x0) - b * (1.0 + y0 * y0);
+ float c3 = 1.0;
+
+ vec3 roots = solve_cubic(vec4(c0, c1, c2, c3));
+ float e1 = roots.x;
+ float e2 = roots.y;
+ float e3 = roots.z;
+
+ vec3 avg_dir = vec3(a * x0 / (a - e2), b * y0 / (b - e2), 1.0);
+
+ mat3 rotate = mat3(V1, V2, V3);
+
+ avg_dir = rotate * avg_dir;
+ avg_dir = normalize(avg_dir);
+
+ /* L1, L2 are the extends of the front facing ellipse. */
+ float L1 = sqrt(-e2/e3);
+ float L2 = sqrt(-e2/e1);
+
+ /* Find the sphere and compute lighting. */
+ float form_factor = max(0.0, L1 * L2 * inversesqrt((1.0 + L1 * L1) * (1.0 + L2 * L2)));
+
+#if 1 /* use tabulated horizon-clipped sphere */
+ return form_factor * diffuse_sphere_integral_lut(avg_dir.z, form_factor);
+#else /* Less accurate version, a bit cheaper. */
+ return form_factor * diffuse_sphere_integral_cheap(avg_dir.z, form_factor);
+#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index f921d56e3bc..1c0e65f0613 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -10,14 +10,15 @@ float hash3d(vec3 a) {
return hash(vec2(hash(a.xy), a.z));
}
-//uniform float hashScale;
-float hashScale = 0.001;
+uniform float hashAlphaOffset;
float hashed_alpha_threshold(vec3 co)
{
+ const float hash_scale = 1.0; /* Roughly in pixel */
+
/* Find the discretized derivatives of our coordinates. */
float max_deriv = max(length(dFdx(co)), length(dFdy(co)));
- float pix_scale = 1.0 / (hashScale * max_deriv);
+ float pix_scale = 1.0 / (hash_scale * max_deriv);
/* Find two nearest log-discretized noise scales. */
float pix_scale_log = log2(pix_scale);
@@ -53,7 +54,8 @@ float hashed_alpha_threshold(vec3 co)
/* Avoids threshold == 0. */
threshold = clamp(threshold, 1.0e-6, 1.0);
- return threshold;
+ /* Jitter the threshold for TAA accumulation. */
+ return fract(threshold + hashAlphaOffset);
}
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
index c593081ce91..cb75731b7da 100644
--- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -1,13 +1,5 @@
#define MAX_STEP 256
-uniform vec4 ssrParameters;
-
-#define ssrQuality ssrParameters.x
-#define ssrThickness ssrParameters.y
-#define ssrPixelSize ssrParameters.zw
-
-uniform float borderFadeFactor;
-
float sample_depth(vec2 uv, int index, float lod)
{
#ifdef PLANAR_PROBE_RAYTRACE
@@ -233,7 +225,7 @@ vec3 raycast(
float screen_border_mask(vec2 hit_co)
{
const float margin = 0.003;
- float atten = borderFadeFactor + margin; /* Screen percentage */
+ float atten = ssrBorderFac + margin; /* Screen percentage */
hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co));
float screenfade = hit_co.x * hit_co.y;
diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
index 92287d2ecbc..6c7bfeb6b82 100644
--- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl
@@ -2,10 +2,9 @@
#define BTDF_BIAS 0.85
-vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec3 rand, float ofs)
+vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec4 rand)
{
float a2 = max(5e-6, roughnessSquared * roughnessSquared);
- float jitter = fract(rand.x + ofs);
/* Importance sampling bias */
rand.x = mix(rand.x, 0.0, BTDF_BIAS);
@@ -13,12 +12,12 @@ vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float
vec3 T, B;
float NH;
make_orthonormal_basis(N, T, B);
- vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */
+ vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */
float pdf = pdf_ggx_reflect(NH, a2);
/* If ray is bad (i.e. going below the plane) regenerate. */
if (F_eta(ior, dot(H, V)) < 1.0) {
- H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
+ H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */
pdf = pdf_ggx_reflect(NH, a2);
}
@@ -33,7 +32,7 @@ vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float
R = transform_direction(ViewMatrix, R);
- vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, roughnessSquared, false);
+ vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, roughnessSquared, false);
if ((hit_pos.z > 0.0) && (F_eta(ior, dot(H, V)) < 1.0)) {
hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z);
diff --git a/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl
new file mode 100644
index 00000000000..13ffe02eb0d
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl
@@ -0,0 +1,18 @@
+
+uniform sampler2D blueNoise;
+uniform vec3 offsets;
+
+out vec4 FragColor;
+
+#define M_2PI 6.28318530717958647692
+
+void main(void)
+{
+ vec2 blue_noise = texelFetch(blueNoise, ivec2(gl_FragCoord.xy), 0).xy;
+
+ float noise = fract(blue_noise.y + offsets.z);
+ FragColor.x = fract(blue_noise.x + offsets.x);
+ FragColor.y = fract(blue_noise.y + offsets.y);
+ FragColor.z = cos(noise * M_2PI);
+ FragColor.w = sin(noise * M_2PI);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 00e01e753f9..3a293647f84 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -4,9 +4,6 @@
#define NODETREE_EXEC
-uniform ivec3 volumeTextureSize;
-uniform vec3 volume_jitter;
-
#ifdef MESH_SHADER
uniform mat4 volumeObjectMatrix;
uniform vec3 volumeOrcoLoc;
@@ -33,7 +30,7 @@ layout(location = 3) out vec4 volumePhase;
void main()
{
ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
- vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volumeTextureSize);
+ vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz);
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
worldPosition = transform_point(ViewMatrixInverse, viewPosition);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
index 1376c53d633..1a8167c2830 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl
@@ -2,22 +2,16 @@
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
-uniform float volume_light_clamp;
-
-uniform vec3 volume_param; /* Parameters to the volume Z equation */
-
-uniform vec2 volume_uv_ratio; /* To convert volume uvs to screen uvs */
-
/* Volume slice to view space depth. */
float volume_z_to_view_z(float z)
{
if (ProjectionMatrix[3][3] == 0.0) {
/* Exponential distribution */
- return (exp2(z / volume_param.z) - volume_param.x) / volume_param.y;
+ return (exp2(z / volDepthParameters.z) - volDepthParameters.x) / volDepthParameters.y;
}
else {
/* Linear distribution */
- return mix(volume_param.x, volume_param.y, z);
+ return mix(volDepthParameters.x, volDepthParameters.y, z);
}
}
@@ -25,11 +19,11 @@ float view_z_to_volume_z(float depth)
{
if (ProjectionMatrix[3][3] == 0.0) {
/* Exponential distribution */
- return volume_param.z * log2(depth * volume_param.y + volume_param.x);
+ return volDepthParameters.z * log2(depth * volDepthParameters.y + volDepthParameters.x);
}
else {
/* Linear distribution */
- return (depth - volume_param.x) * volume_param.z;
+ return (depth - volDepthParameters.x) * volDepthParameters.z;
}
}
@@ -38,7 +32,7 @@ vec3 volume_to_ndc(vec3 cos)
{
cos.z = volume_z_to_view_z(cos.z);
cos.z = get_depth_from_view_z(cos.z);
- cos.xy /= volume_uv_ratio;
+ cos.xy /= volCoordScale.xy;
return cos;
}
@@ -46,7 +40,7 @@ vec3 ndc_to_volume(vec3 cos)
{
cos.z = get_view_z_from_depth(cos.z);
cos.z = view_z_to_volume_z(cos.z);
- cos.xy *= volume_uv_ratio;
+ cos.xy *= volCoordScale.xy;
return cos;
}
@@ -71,14 +65,17 @@ vec3 light_volume(LightData ld, vec4 l_vector)
/* TODO : Area lighting ? */
/* XXX : Removing Area Power. */
/* TODO : put this out of the shader. */
+ /* See eevee_light_setup(). */
if (ld.l_type == AREA) {
- power = 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI);
+ power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0);
+ power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */
}
else if (ld.l_type == SUN) {
- power = 1.0;
+ power = (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/
+ power *= M_2PI * 0.78; /* Matching cycles with point light. */
}
else {
- power = 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI);
+ power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0);
}
/* OPTI: find a better way than calculating this on the fly */
@@ -87,15 +84,13 @@ vec3 light_volume(LightData ld, vec4 l_vector)
power /= (l_vector.w * l_vector.w);
- lum = min(lum * power, volume_light_clamp);
+ lum = min(lum * power, volLightClamp);
return tint * lum;
}
#define VOLUMETRIC_SHADOW_MAX_STEP 32.0
-uniform float volume_shadows_steps;
-
vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction)
{
/* Waiting for proper volume shadowmaps and out of frustum shadow map. */
@@ -110,11 +105,11 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v
{
#if defined(VOLUME_SHADOW)
/* Heterogeneous volume shadows */
- float dd = l_vector.w / volume_shadows_steps;
+ float dd = l_vector.w / volShadowSteps;
vec3 L = l_vector.xyz * l_vector.w;
vec3 shadow = vec3(1.0);
- for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volume_shadows_steps - 0.1); s += 1.0) {
- vec3 pos = ray_wpos + L * (s / volume_shadows_steps);
+ for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) {
+ vec3 pos = ray_wpos + L * (s / volShadowSteps);
vec3 s_extinction = participating_media_extinction(pos, volume_extinction);
shadow *= exp(-s_extinction * dd);
}
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 ea402ff3d99..fcbb6661b14 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl
@@ -13,28 +13,20 @@ uniform sampler3D volumePhase;
uniform sampler3D historyScattering;
uniform sampler3D historyTransmittance;
-uniform vec3 volume_jitter;
-uniform float volume_history_alpha;
-uniform int light_count;
-uniform mat4 PastViewProjectionMatrix;
-
flat in int slice;
layout(location = 0) out vec4 outScattering;
layout(location = 1) out vec4 outTransmittance;
-#define VOLUME_LIGHTING
-
void main()
{
- vec3 volume_tex_size = vec3(textureSize(volumeScattering, 0));
ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice);
/* Emission */
outScattering = texelFetch(volumeEmission, volume_cell, 0);
outTransmittance = texelFetch(volumeExtinction, volume_cell, 0);
vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb;
- vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volume_tex_size);
+ vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz);
vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z);
vec3 wdir = cameraVec;
@@ -45,7 +37,7 @@ void main()
outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic();
#ifdef VOLUME_LIGHTING /* Lights */
- for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
@@ -63,16 +55,16 @@ void main()
/* Temporal supersampling */
/* Note : this uses the cell non-jittered position (texel center). */
- vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) / volume_tex_size);
+ vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) * volInvTexSize.xyz);
vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z);
- vec3 prev_ndc = project_point(PastViewProjectionMatrix, wpos);
+ vec3 prev_ndc = project_point(pastViewProjectionMatrix, wpos);
vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5);
- if ((volume_history_alpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) {
+ if ((volHistoryAlpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) {
vec4 h_Scattering = texture(historyScattering, prev_volume);
vec4 h_Transmittance = texture(historyTransmittance, prev_volume);
- outScattering = mix(outScattering, h_Scattering, volume_history_alpha);
- outTransmittance = mix(outTransmittance, h_Transmittance, volume_history_alpha);
+ outScattering = mix(outScattering, h_Scattering, volHistoryAlpha);
+ outTransmittance = mix(outTransmittance, h_Transmittance, volHistoryAlpha);
}
/* Catch NaNs */
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 851d0ef9eb7..ec0141953fe 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -218,6 +218,7 @@ DrawEngineType draw_engine_external_type = {
&external_draw_scene,
NULL,
NULL,
+ NULL,
};
/* Note: currently unused, we should not register unless we want to see this when debugging the view. */
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 0753dbc7a1a..528495b8710 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -139,6 +139,8 @@ typedef struct DrawEngineType {
void (*view_update)(void *vedata);
void (*id_update)(void *vedata, struct ID *id);
+
+ void (*render_to_image)(void *vedata, struct RenderEngine *engine, struct Depsgraph *graph);
} DrawEngineType;
#ifndef __DRW_ENGINE_H__
@@ -157,7 +159,9 @@ typedef struct DefaultTextureList {
#endif
/* Textures */
-
+/* NOTE naming in this struct is broken.
+ * There should either be suffixes for Normalized int formats or float formats.
+ * Right now every 8bit texture is Normalized int and others are Floating point. */
typedef enum {
DRW_TEX_RGBA_8,
DRW_TEX_RGBA_16,
@@ -168,6 +172,7 @@ typedef enum {
DRW_TEX_RGB_32,
DRW_TEX_RG_8,
DRW_TEX_RG_16,
+ DRW_TEX_RG_16I,
DRW_TEX_RG_32,
DRW_TEX_R_8,
DRW_TEX_R_16,
@@ -226,12 +231,14 @@ typedef struct DRWFboTexture {
DRWTextureFlag flag;
} DRWFboTexture;
+struct GPUFrameBuffer *DRW_framebuffer_create(void);
void DRW_framebuffer_init(
struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
DRWFboTexture textures[MAX_FBO_TEX], int textures_len);
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slot, float *data);
+void DRW_framebuffer_read_depth(int x, int y, int w, int h, float *data);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
void DRW_framebuffer_texture_layer_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip);
void DRW_framebuffer_cubeface_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip);
@@ -290,6 +297,7 @@ typedef enum {
DRW_STATE_MULTIPLY = (1 << 16),
DRW_STATE_TRANSMISSION = (1 << 17),
DRW_STATE_CLIP_PLANES = (1 << 18),
+ DRW_STATE_ADDITIVE_FULL = (1 << 19), /* Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */
DRW_STATE_WRITE_STENCIL = (1 << 27),
DRW_STATE_STENCIL_EQUAL = (1 << 28),
@@ -326,10 +334,6 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
const void *array[] = {__VA_ARGS__}; \
DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \
} while (0)
-/* Use this only to make your instances selectable. */
-#define DRW_shgroup_call_dynamic_add_empty(shgroup) do { \
- DRW_shgroup_call_dynamic_add_array(shgroup, NULL, 0); \
-} while (0)
/* Use this to set a high number of instances. */
void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count);
@@ -341,13 +345,14 @@ void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int si
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex);
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo);
void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex);
-void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize);
void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize);
+/* Boolean are expected to be 4bytes longs for opengl! */
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
@@ -356,6 +361,7 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_foreach_shgroup(DRWPass *pass, void (*callback)(void *userData, DRWShadingGroup *shgrp), void *userData);
void DRW_pass_sort_shgroup_z(DRWPass *pass);
@@ -383,19 +389,29 @@ struct DefaultTextureList *DRW_viewport_texture_list_get(void);
void DRW_viewport_request_redraw(void);
+void DRW_render_to_image(struct RenderEngine *re, struct Depsgraph *depsgraph);
+void DRW_render_object_iter(
+ void *vedata, struct RenderEngine *engine, struct Depsgraph *graph,
+ void (*callback)(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *graph));
+
/* ViewLayers */
void *DRW_view_layer_engine_data_get(DrawEngineType *engine_type);
void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*callback)(void *storage));
/* Objects */
-void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
-void **DRW_object_engine_data_ensure(
- Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage));
+ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type);
+ObjectEngineData *DRW_object_engine_data_ensure(
+ Object *ob,
+ DrawEngineType *engine_type,
+ size_t size,
+ ObjectEngineDataInitCb init_cb,
+ ObjectEngineDataFreeCb free_cb);
struct LampEngineData *DRW_lamp_engine_data_ensure(Object *ob, struct RenderEngineType *engine_type);
void DRW_lamp_engine_data_free(struct LampEngineData *led);
/* Settings */
bool DRW_object_is_renderable(struct Object *ob);
+bool DRW_check_object_visible_within_active_context(struct Object *ob);
bool DRW_object_is_flat_normal(const struct Object *ob);
int DRW_object_is_mode_shade(const struct Object *ob);
@@ -431,6 +447,9 @@ bool DRW_state_is_image_render(void);
bool DRW_state_is_scene_render(void);
bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
+bool DRW_state_draw_background(void);
+
+enum eDepsObjectIteratorMode DRW_iterator_mode_get(void);
struct DRWTextStore *DRW_state_text_cache_get(void);
@@ -448,6 +467,8 @@ typedef struct DRWContextState {
struct RenderEngineType *engine_type;
+ struct Depsgraph *depsgraph;
+
/* Last resort (some functions take this as an arg so we can't easily avoid).
* May be NULL when used for selection or depth buffer. */
const struct bContext *evil_C;
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index c7a88f7689e..09fe3d68651 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -102,20 +102,22 @@ static void drw_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const
{
if (g_data.bone_octahedral_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_octahedral_get();
- g_data.bone_octahedral_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ g_data.bone_octahedral_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_solid, final_bonemat, color);
}
static void drw_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_octahedral_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
- g_data.bone_octahedral_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_octahedral_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_wire, final_bonemat, color);
}
/* Box / B-Bone */
@@ -123,20 +125,22 @@ static void drw_shgroup_bone_box_solid(const float (*bone_mat)[4], const float c
{
if (g_data.bone_box_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_box_get();
- g_data.bone_box_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ g_data.bone_box_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, color);
}
static void drw_shgroup_bone_box_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_box_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_box_wire_outline_get();
- g_data.bone_box_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_box_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_box_wire, final_bonemat, color);
}
/* Wire */
@@ -144,10 +148,11 @@ static void drw_shgroup_bone_wire_wire(const float (*bone_mat)[4], const float c
{
if (g_data.bone_wire_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_wire_wire_outline_get();
- g_data.bone_wire_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_wire_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_wire_wire, final_bonemat, color);
}
/* Envelope */
@@ -159,10 +164,11 @@ static void drw_shgroup_bone_envelope_distance(
if (g_data.bone_envelope_distance == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_distance_outline_get();
/* Note: bone_wire draw pass is not really working, think we need another one here? */
- g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom, g_data.ob->obmat);
+ g_data.bone_envelope_distance = shgroup_instance_bone_envelope_wire(g_data.pass_bone_envelope, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, bone_mat, color, radius_head, radius_tail, distance);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_distance, final_bonemat, color, radius_head, radius_tail, distance);
}
}
@@ -172,10 +178,11 @@ static void drw_shgroup_bone_envelope_solid(
{
if (g_data.bone_envelope_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_solid_get();
- g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(g_data.pass_bone_solid, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, bone_mat, color, radius_head, radius_tail);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid, final_bonemat, color, radius_head, radius_tail);
}
static void drw_shgroup_bone_envelope_wire(
@@ -184,10 +191,11 @@ static void drw_shgroup_bone_envelope_wire(
{
if (g_data.bone_envelope_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_wire_outline_get();
- g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_envelope_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, bone_mat, color, radius_head, radius_tail, distance);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
static void drw_shgroup_bone_envelope_head_wire(
@@ -196,10 +204,11 @@ static void drw_shgroup_bone_envelope_head_wire(
{
if (g_data.bone_envelope_head_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_envelope_head_wire_outline_get();
- g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_envelope_head_wire = shgroup_instance_bone_envelope_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, bone_mat, color, radius_head, radius_tail, distance);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_envelope_head_wire, final_bonemat, color, radius_head, radius_tail, distance);
}
/* Custom (geometry) */
@@ -209,8 +218,10 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4], const floa
/* grr, not re-using instances! */
struct Gwn_Batch *geom = DRW_cache_object_surface_get(custom);
if (geom) {
- DRWShadingGroup *shgrp_geom_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
- DRW_shgroup_call_dynamic_add(shgrp_geom_solid, bone_mat, color);
+ DRWShadingGroup *shgrp_geom_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, color);
}
}
@@ -219,8 +230,10 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4], const float
/* grr, not re-using instances! */
struct Gwn_Batch *geom = DRW_cache_object_wire_outline_get(custom);
if (geom) {
- DRWShadingGroup *shgrp_geom_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
- DRW_shgroup_call_dynamic_add(shgrp_geom_wire, bone_mat, color);
+ DRWShadingGroup *shgrp_geom_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, color);
}
}
@@ -229,20 +242,22 @@ static void drw_shgroup_bone_point_solid(const float (*bone_mat)[4], const float
{
if (g_data.bone_point_solid == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_point_get();
- g_data.bone_point_solid = shgroup_instance_objspace_solid(g_data.pass_bone_solid, geom, g_data.ob->obmat);
+ g_data.bone_point_solid = shgroup_instance_solid(g_data.pass_bone_solid, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, color);
}
static void drw_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
{
if (g_data.bone_point_wire == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_point_wire_outline_get();
- g_data.bone_point_wire = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_point_wire = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, color);
}
/* Axes */
@@ -250,10 +265,11 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4], const float color[
{
if (g_data.bone_axes == NULL) {
struct Gwn_Batch *geom = DRW_cache_bone_arrows_get();
- g_data.bone_axes = shgroup_instance_objspace_wire(g_data.pass_bone_wire, geom, g_data.ob->obmat);
+ g_data.bone_axes = shgroup_instance_wire(g_data.pass_bone_wire, geom);
}
-
- DRW_shgroup_call_dynamic_add(g_data.bone_axes, bone_mat, color);
+ float final_bonemat[4][4];
+ mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
+ DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color);
}
/* Relationship lines */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 8010a232f89..3b4180c0375 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -65,6 +65,7 @@ static struct DRWShapeCache {
Gwn_Batch *drw_field_tube_limit;
Gwn_Batch *drw_field_cone_limit;
Gwn_Batch *drw_lamp;
+ Gwn_Batch *drw_lamp_shadows;
Gwn_Batch *drw_lamp_sunrays;
Gwn_Batch *drw_lamp_area;
Gwn_Batch *drw_lamp_hemi;
@@ -87,6 +88,7 @@ static struct DRWShapeCache {
Gwn_Batch *drw_bone_point_wire;
Gwn_Batch *drw_bone_arrows;
Gwn_Batch *drw_camera;
+ Gwn_Batch *drw_camera_frame;
Gwn_Batch *drw_camera_tria;
Gwn_Batch *drw_camera_focus;
Gwn_Batch *drw_particle_cross;
@@ -520,6 +522,12 @@ Gwn_Batch **DRW_cache_object_surface_material_get(
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ case OB_CURVE:
+ return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ case OB_SURF:
+ return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ case OB_FONT:
+ return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
default:
return NULL;
}
@@ -1007,14 +1015,14 @@ Gwn_Batch *DRW_cache_lamp_get(void)
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
- for (int a = 0; a < NSEGMENTS; a++) {
- v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
- v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v);
+ for (int a = 0; a < NSEGMENTS * 2; a += 2) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
- v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
- v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v);
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
}
SHC.drw_lamp = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
@@ -1023,12 +1031,44 @@ Gwn_Batch *DRW_cache_lamp_get(void)
#undef NSEGMENTS
}
+Gwn_Batch *DRW_cache_lamp_shadows_get(void)
+{
+#define NSEGMENTS 10
+ if (!SHC.drw_lamp_shadows) {
+ float v[2];
+
+ /* Position Only 3D format */
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ GWN_vertbuf_data_alloc(vbo, NSEGMENTS * 2);
+
+ for (int a = 0; a < NSEGMENTS * 2; a += 2) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS * 2));
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a + 1, v);
+ }
+
+ SHC.drw_lamp_shadows = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_lamp_shadows;
+#undef NSEGMENTS
+}
+
Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
{
if (!SHC.drw_lamp_sunrays) {
float v[2], v1[2], v2[2];
- /* Position Only 3D format */
+ /* Position Only 2D format */
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
@@ -1036,17 +1076,21 @@ Gwn_Batch *DRW_cache_lamp_sunrays_get(void)
}
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 16);
+ GWN_vertbuf_data_alloc(vbo, 32);
for (int a = 0; a < 8; a++) {
v[0] = sinf((2.0f * M_PI * a) / 8.0f);
v[1] = cosf((2.0f * M_PI * a) / 8.0f);
- mul_v2_v2fl(v1, v, 1.2f);
- mul_v2_v2fl(v2, v, 2.5f);
+ mul_v2_v2fl(v1, v, 1.6f);
+ mul_v2_v2fl(v2, v, 1.9f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 1, v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2, v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 2 + 1, v2);
+ mul_v2_v2fl(v1, v, 2.2f);
+ mul_v2_v2fl(v2, v, 2.5f);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 2, v1);
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, a * 4 + 3, v2);
}
SHC.drw_lamp_sunrays = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
@@ -1846,7 +1890,7 @@ Gwn_Batch *DRW_cache_bone_envelope_distance_outline_get(void)
const float x = cosf(alpha);
const float y = -sinf(alpha);
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){x, y, head_tail, 1.0f});
if (is_headtail_transition) {
@@ -1880,7 +1924,7 @@ Gwn_Batch *DRW_cache_bone_envelope_wire_outline_get(void)
/* Two lines between head and tail circles. */
/* Encoded lines, vertex shader gives them final correct value. */
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 0.0f, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ 1.0f, 0.0f, 1.0f, 0.0f});
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){-1.0f, 0.0f, 0.0f, 0.0f});
@@ -1916,7 +1960,7 @@ Gwn_Batch *DRW_cache_bone_envelope_head_wire_outline_get(void)
const float x = cosf(alpha);
const float y = -sinf(alpha);
- /* { X, Y, head/tail, inner/outer border } */
+ /* { X, Y, head/tail, inner/outer border } */
GWN_vertbuf_attr_set(vbo, pos_id, v_idx++, (const float[4]){ x, y, 0.0f, 0.0f});
}
@@ -1996,97 +2040,139 @@ Gwn_Batch *DRW_cache_bone_arrows_get(void)
/** \name Camera
* \{ */
+/**
+ * We could make these more generic functions.
+ * although filling 1d lines is not common.
+ *
+ * \note Use x coordinate to identify the vertex the vertex shader take care to place it appropriately.
+ */
+
+static const float camera_coords_frame_bounds[5] = {
+ 0.0f, /* center point */
+ 1.0f, /* + X + Y */
+ 2.0f, /* + X - Y */
+ 3.0f, /* - X - Y */
+ 4.0f, /* - X + Y */
+};
+
+static const float camera_coords_frame_tri[3] = {
+ 5.0f, /* tria + X */
+ 6.0f, /* tria - X */
+ 7.0f, /* tria + Y */
+};
+
+/** Draw a loop of lines. */
+static void camera_fill_lines_loop_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 0, i_prev = coords_len - 1; i < coords_len; i_prev = i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i_prev];
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+/** Fan lines out from the first vertex. */
+static void camera_fill_lines_fan_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 1; i < coords_len; i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[0];
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+/** Simply fill the array. */
+static void camera_fill_array_fl_v1(
+ Gwn_VertBufRaw *pos_step,
+ const float *coords, const uint coords_len)
+{
+ for (uint i = 0; i < coords_len; i++) {
+ *((float *)GWN_vertbuf_raw_step(pos_step)) = coords[i];
+ }
+}
+
+
Gwn_Batch *DRW_cache_camera_get(void)
{
if (!SHC.drw_camera) {
- float v0 = 0.0f; /* Center point */
- float v1 = 1.0f; /* + X + Y */
- float v2 = 2.0f; /* + X - Y */
- float v3 = 3.0f; /* - X - Y */
- float v4 = 4.0f; /* - X + Y */
- float v5 = 5.0f; /* tria + X */
- float v6 = 6.0f; /* tria - X */
- float v7 = 7.0f; /* tria + Y */
- int v_idx = 0;
-
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
- /* use x coordinate to identify the vertex
- * the vertex shader take care to place it
- * appropriatelly */
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
}
/* Vertices */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 22);
-
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+ const int vbo_len_capacity = 22;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+ /* camera cone (from center to frame) */
+ camera_fill_lines_fan_fl_v1(&pos_step, camera_coords_frame_bounds, ARRAY_SIZE(camera_coords_frame_bounds));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+ /* camera frame (skip center) */
+ camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v0);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+ /* camera triangle (above the frame) */
+ camera_fill_lines_loop_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- /* camera frame */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v2);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
+ SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_camera;
+}
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v3);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
+Gwn_Batch *DRW_cache_camera_frame_get(void)
+{
+ if (!SHC.drw_camera_frame) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v4);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v1);
+ static Gwn_VertFormat format = { 0 };
+ static struct { uint pos; } attr_id;
+ if (format.attrib_ct == 0) {
+ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
+ }
- /* tria */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
+ /* Vertices */
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
+ const int vbo_len_capacity = 8;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+ /* camera frame (skip center) */
+ camera_fill_lines_loop_fl_v1(&pos_step, &camera_coords_frame_bounds[1], ARRAY_SIZE(camera_coords_frame_bounds) - 1);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
- SHC.drw_camera = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ SHC.drw_camera_frame = GWN_batch_create_ex(GWN_PRIM_LINES, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
- return SHC.drw_camera;
+ return SHC.drw_camera_frame;
}
Gwn_Batch *DRW_cache_camera_tria_get(void)
{
if (!SHC.drw_camera_tria) {
- float v5 = 5.0f; /* tria + X */
- float v6 = 6.0f; /* tria - X */
- float v7 = 7.0f; /* tria + Y */
- int v_idx = 0;
-
static Gwn_VertFormat format = { 0 };
static struct { uint pos; } attr_id;
if (format.attrib_ct == 0) {
- /* use x coordinate to identify the vertex
- * the vertex shader take care to place it
- * appropriatelly */
attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
}
/* Vertices */
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- GWN_vertbuf_data_alloc(vbo, 6);
+ const int vbo_len_capacity = 3;
+ GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
+ Gwn_VertBufRaw pos_step;
+ GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
+
+ /* camera triangle (above the frame) */
+ camera_fill_array_fl_v1(&pos_step, camera_coords_frame_tri, ARRAY_SIZE(camera_coords_frame_tri));
- /* tria */
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v5);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v6);
- GWN_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, &v7);
+ BLI_assert(vbo_len_capacity == GWN_vertbuf_raw_used(&pos_step));
SHC.drw_camera_tria = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo, NULL, GWN_BATCH_OWNS_VBO);
}
@@ -2334,6 +2420,16 @@ Gwn_Batch *DRW_cache_curve_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
+/* Return list of batches */
+Gwn_Batch **DRW_cache_curve_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ BLI_assert(ob->type == OB_CURVE);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -2372,6 +2468,17 @@ Gwn_Batch *DRW_cache_text_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
+Gwn_Batch **DRW_cache_text_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ BLI_assert(ob->type == OB_FONT);
+ struct Curve *cu = ob->data;
+ if (cu->editfont && (cu->flag & CU_FAST)) {
+ return NULL;
+ }
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+}
+
Gwn_Batch *DRW_cache_text_cursor_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
@@ -2401,6 +2508,16 @@ Gwn_Batch *DRW_cache_surf_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
+/* Return list of batches */
+Gwn_Batch **DRW_cache_surf_surface_shaded_get(
+ Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
+{
+ BLI_assert(ob->type == OB_SURF);
+
+ struct Curve *cu = ob->data;
+ return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 35ac8f4a35d..c039bb8883d 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -70,6 +70,7 @@ struct Gwn_Batch *DRW_cache_field_cone_limit_get(void);
/* Lamps */
struct Gwn_Batch *DRW_cache_lamp_get(void);
+struct Gwn_Batch *DRW_cache_lamp_shadows_get(void);
struct Gwn_Batch *DRW_cache_lamp_sunrays_get(void);
struct Gwn_Batch *DRW_cache_lamp_area_get(void);
struct Gwn_Batch *DRW_cache_lamp_hemi_get(void);
@@ -78,6 +79,7 @@ struct Gwn_Batch *DRW_cache_lamp_spot_square_get(void);
/* Camera */
struct Gwn_Batch *DRW_cache_camera_get(void);
+struct Gwn_Batch *DRW_cache_camera_frame_get(void);
struct Gwn_Batch *DRW_cache_camera_tria_get(void);
/* Speaker */
@@ -130,6 +132,8 @@ void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
/* Curve */
struct Gwn_Batch *DRW_cache_curve_surface_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_curve_surface_shaded_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct Gwn_Batch *DRW_cache_curve_surface_verts_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
/* edit-mode */
@@ -140,12 +144,16 @@ struct Gwn_Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
/* Font */
struct Gwn_Batch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_text_surface_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_text_surface_shaded_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* edit-mode */
struct Gwn_Batch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_text_select_overlay_get(struct Object *ob);
/* Surface */
struct Gwn_Batch *DRW_cache_surf_surface_get(struct Object *ob);
+struct Gwn_Batch **DRW_cache_surf_surface_shaded_get(
+ struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Lattice */
struct Gwn_Batch *DRW_cache_lattice_verts_get(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index c998282ae1f..0b18f3a257f 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -29,14 +29,16 @@
struct CurveCache;
struct GPUMaterial;
struct Gwn_Batch;
+struct Gwn_IndexBuf;
+struct Gwn_VertBuf;
struct ListBase;
-struct MetaBall;
struct ModifierData;
struct ParticleSystem;
struct Curve;
struct Lattice;
struct Mesh;
+struct MetaBall;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
@@ -62,6 +64,9 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache);
+struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
+ struct Curve *cu, struct CurveCache *ob_curve_cache,
+ struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Metaball */
struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
@@ -71,7 +76,12 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
/* DispList */
-struct Gwn_Batch *BLI_displist_batch_calc_surface(struct ListBase *lb);
+struct Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb);
+struct Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb);
+struct Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
+ struct ListBase *lb, uint gpumat_array_len);
+struct Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
+ struct ListBase *lb, uint gpumat_array_len);
/* Lattice */
struct Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index e6e52fe4579..3939ea062e9 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -40,9 +40,22 @@
#include "GPU_batch.h"
+#include "UI_resources.h"
+
#include "draw_cache_impl.h" /* own include */
-#define SELECT 1
+#define SELECT 1
+#define ACTIVE_NURB 1 << 7 /* last char bite */
+#define HANDLE_SEL_OFFSET (TH_HANDLE_SEL_FREE - TH_HANDLE_FREE)
+
+/* Used as values of `color_id` in `edit_curve_overlay_handle_geom.glsl` */
+enum {
+ COLOR_NURB_ULINE_ID = TH_HANDLE_SEL_AUTOCLAMP - TH_HANDLE_FREE + 1,
+ COLOR_NURB_SEL_ULINE_ID,
+ COLOR_ACTIVE_SPLINE,
+
+ TOT_HANDLE_COL,
+};
/**
* TODO
@@ -126,7 +139,8 @@ static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_
nr -= skip;
}
#else
- normal_len += max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+ /* Same as loop above */
+ normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0);
#endif
}
return normal_len;
@@ -310,7 +324,11 @@ typedef struct CurveBatchCache {
} overlay;
struct {
+ Gwn_VertBuf *verts;
+ Gwn_IndexBuf *triangles_in_order;
+ Gwn_Batch **shaded_triangles;
Gwn_Batch *batch;
+ int mat_len;
} surface;
/* 3d text */
@@ -340,6 +358,10 @@ static bool curve_batch_cache_valid(Curve *cu)
return false;
}
+ if (cache->is_dirty) {
+ return false;
+ }
+
if (cache->is_editmode != ((cu->editnurb != NULL) || (cu->editfont != NULL))) {
return false;
}
@@ -358,16 +380,6 @@ static bool curve_batch_cache_valid(Curve *cu)
}
}
- if (cache->is_dirty == false) {
- return true;
- }
- else {
- /* TODO: check number of vertices/edges? */
- if (cache->is_editmode) {
- return false;
- }
- }
-
return true;
}
@@ -444,6 +456,14 @@ static void curve_batch_cache_clear(Curve *cu)
GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
+ GWN_VERTBUF_DISCARD_SAFE(cache->surface.verts);
+ GWN_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
+ if (cache->surface.shaded_triangles) {
+ for (int i = 0; i < cache->surface.mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
+ }
+ }
+ MEM_SAFE_FREE(cache->surface.shaded_triangles);
GWN_BATCH_DISCARD_SAFE(cache->surface.batch);
/* don't own vbo & elems */
@@ -735,47 +755,50 @@ static void curve_batch_cache_create_overlay_batches(Curve *cu)
int vbo_len_used = 0;
GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
int i = 0;
- for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next) {
+ for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, i++) {
+ const bool is_active_nurb = (i == cu->actnu);
+
if (nu->bezt) {
int a = 0;
for (const BezTriple *bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
if (bezt->hide == false) {
- const bool is_active = (i == rdata->actvert);
- char vflag;
-
- vflag = (bezt->f1 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[0]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
- vbo_len_used += 1;
+ char col_id;
- /* same vertex twice, only check different selection */
- for (int j = 0; j < 2; j++) {
- vflag = ((j ? bezt->f3 : bezt->f1) & SELECT) ?
- (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
+ for (int j = 0; j < 2; j += 1) {
+ /* same vertex twice, only check different selection */
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[1]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
vbo_len_used += 1;
- }
- vflag = (bezt->f3 & SELECT) ? (is_active ? VFLAG_VERTEX_ACTIVE : VFLAG_VERTEX_SELECTED) : 0;
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[2]);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
- vbo_len_used += 1;
+ col_id = (&bezt->h1)[j];
+ if ((&bezt->f1)[j * 2] & SELECT) {
+ col_id += HANDLE_SEL_OFFSET;
+ }
+ if (is_active_nurb) {
+ col_id |= ACTIVE_NURB;
+ }
+
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bezt->vec[j * 2]);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
+ vbo_len_used += 1;
+ }
}
- i += 1;
}
}
else if (nu->bp) {
int a = 1;
for (const BPoint *bp_prev = nu->bp, *bp_curr = &nu->bp[1]; a < nu->pntsu; a++, bp_prev = bp_curr++) {
if ((bp_prev->hide == false) && (bp_curr->hide == false)) {
- char vflag;
- vflag = ((bp_prev->f1 & SELECT) && (bp_curr->f1 & SELECT)) ? VFLAG_VERTEX_SELECTED : 0;
+ char col_id = ((bp_prev->f1 & SELECT) && (bp_curr->f1 & SELECT)) ? COLOR_NURB_SEL_ULINE_ID : COLOR_NURB_ULINE_ID;
+
+ if (is_active_nurb) {
+ col_id |= ACTIVE_NURB;
+ }
+
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_prev->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
vbo_len_used += 1;
+
GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, bp_curr->vec);
- GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &vflag);
+ GWN_vertbuf_attr_set(vbo, attr_id.data, vbo_len_used, &col_id);
vbo_len_used += 1;
}
@@ -796,8 +819,18 @@ static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata,
{
BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
if (cache->surface.batch == NULL) {
- cache->surface.batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
+ ListBase *lb = &rdata->ob_curve_cache->disp;
+
+ if (cache->surface.verts == NULL) {
+ cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
+ }
+ if (cache->surface.triangles_in_order == NULL) {
+ cache->surface.triangles_in_order = DRW_displist_indexbuf_calc_triangles_in_order(lb);
+ }
+ cache->surface.batch = GWN_batch_create(
+ GWN_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order);
}
+
return cache->surface.batch;
}
@@ -997,6 +1030,55 @@ Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
return cache->surface.batch;
}
+Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
+ struct Curve *cu, struct CurveCache *ob_curve_cache,
+ struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
+{
+ CurveBatchCache *cache = curve_batch_cache_get(cu);
+
+ if (cache->surface.mat_len != gpumat_array_len) {
+ /* TODO: deduplicate code */
+ if (cache->surface.shaded_triangles) {
+ for (int i = 0; i < cache->surface.mat_len; ++i) {
+ GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
+ }
+ }
+ MEM_SAFE_FREE(cache->surface.shaded_triangles);
+ }
+
+ if (cache->surface.shaded_triangles == NULL) {
+ CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
+ ListBase *lb = &rdata->ob_curve_cache->disp;
+
+ cache->surface.mat_len = gpumat_array_len;
+ if (cu->flag & CU_UV_ORCO) {
+ cache->surface.shaded_triangles = DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
+ lb, gpumat_array_len);
+ }
+ else {
+ cache->surface.shaded_triangles = MEM_mallocN(
+ sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__);
+ Gwn_IndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
+ lb, gpumat_array_len);
+
+ if (cache->surface.verts == NULL) {
+ cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
+ }
+
+ for (int i = 0; i < gpumat_array_len; ++i) {
+ cache->surface.shaded_triangles[i] = GWN_batch_create_ex(
+ GWN_PRIM_TRIS, cache->surface.verts, el[i], GWN_BATCH_OWNS_INDEX);
+ }
+
+ MEM_freeN(el); /* Save `el` in cache? */
+ }
+
+ curve_render_data_free(rdata);
+ }
+
+ return cache->surface.shaded_triangles;
+}
+
/* -------------------------------------------------------------------- */
@@ -1033,4 +1115,4 @@ Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(Curve *cu)
return cache->text.cursor;
}
-/** \} */ \ No newline at end of file
+/** \} */
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 96386f82faf..627fb38d9d6 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_alloca.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
@@ -86,13 +87,39 @@ static int curve_render_surface_tri_len_get(const ListBase *lb)
return tri_len;
}
-Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
+static void displist_indexbufbuilder_set(Gwn_IndexBufBuilder *elb, const DispList *dl, const int ofs)
{
- const int tri_len = curve_render_surface_tri_len_get(lb);
- if (tri_len == 0) {
- return NULL;
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const int *idx = dl->index;
+ if (dl->type == DL_INDEX3) {
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 3) {
+ GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
+ }
+ }
+ else if (dl->type == DL_SURF) {
+ const int i_end = dl->totindex;
+ for (int i = 0; i < i_end; i++, idx += 4) {
+ GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs);
+ GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[3] + ofs, idx[2] + ofs);
+ }
+ }
+ else {
+ BLI_assert(dl->type == DL_INDEX4);
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 4) {
+ GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+
+ if (idx[2] != idx[3]) {
+ GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+ }
+ }
+ }
}
+}
+Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
+{
static Gwn_VertFormat format = { 0 };
static struct { uint pos, nor; } attr_id;
if (format.attrib_ct == 0) {
@@ -101,74 +128,271 @@ Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
}
- const int vert_len = curve_render_surface_vert_len_get(lb);
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- {
- const int vbo_len_capacity = vert_len;
- int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- BKE_displist_normals_add(lb);
-
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- const bool ndata_is_single = dl->type == DL_INDEX3;
- if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
- const float *fp_co = dl->verts;
- const float *fp_no = dl->nors;
- const int vbo_end = vbo_len_used + dl_vert_len(dl);
- while (vbo_len_used < vbo_end) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
- if (fp_no) {
- GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
- if (ndata_is_single == false) {
- fp_no += 3;
- }
+ GWN_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb));
+
+ BKE_displist_normals_add(lb);
+
+ int vbo_len_used = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ const bool ndata_is_single = dl->type == DL_INDEX3;
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const float *fp_co = dl->verts;
+ const float *fp_no = dl->nors;
+ const int vbo_end = vbo_len_used + dl_vert_len(dl);
+ while (vbo_len_used < vbo_end) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
+ if (fp_no) {
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
+ if (ndata_is_single == false) {
+ fp_no += 3;
}
- fp_co += 3;
- vbo_len_used += 1;
}
+ fp_co += 3;
+ vbo_len_used += 1;
}
}
}
- {
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+ return vbo;
+}
- int ofs = 0;
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
- const int *idx = dl->index;
- if (dl->type == DL_INDEX3) {
- const int i_end = dl->parts;
- for (int i = 0; i < i_end; i++, idx += 3) {
- GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
- }
+Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
+{
+ const int tri_len = curve_render_surface_tri_len_get(lb);
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
+
+ int ofs = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ displist_indexbufbuilder_set(&elb, dl, ofs);
+ ofs += dl_vert_len(dl);
+ }
+
+ return GWN_indexbuf_build(&elb);
+}
+
+Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
+{
+ Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__);
+ Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
+
+ const int tri_len = curve_render_surface_tri_len_get(lb);
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+ int i;
+
+ /* Init each index buffer builder */
+ for (i = 0; i < gpumat_array_len; i++) {
+ GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len);
+ }
+
+ /* calc each index buffer builder */
+ int ofs = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ displist_indexbufbuilder_set(&elb[dl->col], dl, ofs);
+ ofs += dl_vert_len(dl);
+ }
+
+ /* build each indexbuf */
+ for (i = 0; i < gpumat_array_len; i++) {
+ shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
+ }
+
+ return shaded_triangles_in_order;
+}
+
+static void displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ Gwn_VertBufRaw *pos_step, Gwn_VertBufRaw *nor_step, Gwn_VertBufRaw *uv_step,
+ const float v1[3], const float v2[3], const float v3[3],
+ const float n1[3], const float n2[3], const float n3[3],
+ const float uv1[2], const float uv2[2], const float uv3[2])
+{
+ copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v1);
+ copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n1);
+ copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv1);
+
+ copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v2);
+ copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n2);
+ copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv2);
+
+ copy_v3_v3(GWN_vertbuf_raw_step(pos_step), v3);
+ copy_v3_v3(GWN_vertbuf_raw_step(nor_step), n3);
+ copy_v2_v2(GWN_vertbuf_raw_step(uv_step), uv3);
+}
+
+Gwn_Batch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(ListBase *lb, uint gpumat_array_len)
+{
+ static Gwn_VertFormat shaded_triangles_format = { 0 };
+ static struct { uint pos, nor, uv; } attr_id;
+
+ if (shaded_triangles_format.attrib_ct == 0) {
+ /* initialize vertex format */
+ attr_id.pos = GWN_vertformat_attr_add(&shaded_triangles_format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.nor = GWN_vertformat_attr_add(&shaded_triangles_format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ attr_id.uv = GWN_vertformat_attr_add(&shaded_triangles_format, "u", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ }
+
+ Gwn_Batch **shaded_triangles = MEM_mallocN(sizeof(*shaded_triangles) * gpumat_array_len, __func__);
+
+ Gwn_VertBuf **vbo = BLI_array_alloca(vbo, gpumat_array_len);
+ uint *vbo_len_capacity = BLI_array_alloca(vbo_len_capacity, gpumat_array_len);
+
+ Gwn_VertBufRaw *pos_step, *nor_step, *uv_step;
+ pos_step = BLI_array_alloca(pos_step, gpumat_array_len);
+ nor_step = BLI_array_alloca(nor_step, gpumat_array_len);
+ uv_step = BLI_array_alloca(uv_step, gpumat_array_len);
+
+ /* Create each vertex buffer */
+ for (int i = 0; i < gpumat_array_len; i++) {
+ vbo[i] = GWN_vertbuf_create_with_format(&shaded_triangles_format);
+ vbo_len_capacity[i] = 0;
+ }
+
+ /* Calc `vbo_len_capacity` */
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ vbo_len_capacity[dl->col] += dl_tri_len(dl) * 3;
+ }
+
+ /* Alloc each vertex buffer and get each raw data */
+ for (int i = 0; i < gpumat_array_len; i++) {
+ GWN_vertbuf_data_alloc(vbo[i], vbo_len_capacity[i]);
+ GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.pos, &pos_step[i]);
+ GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.nor, &nor_step[i]);
+ GWN_vertbuf_attr_get_raw_data(vbo[i], attr_id.uv, &uv_step[i]);
+ }
+
+ BKE_displist_normals_add(lb);
+
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const int col = dl->col;
+ const float(*verts)[3] = (float(*)[3])dl->verts;
+ const float(*nors)[3] = (float(*)[3])dl->nors;
+ const int *idx = dl->index;
+ float uv[4][2];
+
+ if (dl->type == DL_INDEX3) {
+ const float x_max = (float)(dl->nr - 1);
+ uv[0][1] = uv[1][1] = uv[2][1] = 0.0f;
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 3) {
+ uv[0][0] = idx[0] / x_max;
+ uv[1][0] = idx[2] / x_max;
+ uv[2][0] = idx[1] / x_max;
+
+ displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ &pos_step[col], &nor_step[col], &uv_step[col],
+ verts[idx[0]], verts[idx[2]], verts[idx[1]],
+ nors[idx[0]], nors[idx[2]], nors[idx[1]],
+ uv[0], uv[1], uv[2]);
}
- else if (dl->type == DL_SURF) {
- const int i_end = dl->totindex;
- for (int i = 0; i < i_end; i++, idx += 4) {
- GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
- GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+ }
+ else if (dl->type == DL_SURF) {
+ uint quad[4];
+ for (int a = 0; a < dl->parts; a++) {
+ if ((dl->flag & DL_CYCL_V) == 0 && a == dl->parts - 1) {
+ break;
}
- }
- else {
- BLI_assert(dl->type == DL_INDEX4);
- const int i_end = dl->parts;
- for (int i = 0; i < i_end; i++, idx += 4) {
- GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
-
- if (idx[2] != idx[3]) {
- GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
+
+ int b;
+ if (dl->flag & DL_CYCL_U) {
+ quad[0] = dl->nr * a;
+ quad[3] = quad[0] + dl->nr - 1;
+ quad[1] = quad[0] + dl->nr;
+ quad[2] = quad[3] + dl->nr;
+ b = 0;
+ }
+ else {
+ quad[3] = dl->nr * a;
+ quad[0] = quad[3] + 1;
+ quad[2] = quad[3] + dl->nr;
+ quad[1] = quad[0] + dl->nr;
+ b = 1;
+ }
+ if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
+ quad[1] -= dl->parts * dl->nr;
+ quad[2] -= dl->parts * dl->nr;
+ }
+
+ for (; b < dl->nr; b++) {
+ int orco_sizeu = dl->nr - 1;
+ int orco_sizev = dl->parts - 1;
+
+ /* exception as handled in convertblender.c too */
+ if (dl->flag & DL_CYCL_U) {
+ orco_sizeu++;
+ }
+ if (dl->flag & DL_CYCL_V) {
+ orco_sizev++;
+ }
+
+ for (int i = 0; i < 4; i++) {
+ /* find uv based on vertex index into grid array */
+ uv[i][0] = (quad[i] / dl->nr) / (float)orco_sizev;
+ uv[i][1] = (quad[i] % dl->nr) / (float)orco_sizeu;
+
+ /* cyclic correction */
+ if ((i == 1 || i == 2) && uv[i][0] == 0.0f) {
+ uv[i][0] = 1.0f;
+ }
+ if ((i == 0 || i == 1) && uv[i][1] == 0.0f) {
+ uv[i][1] = 1.0f;
+ }
}
+
+ displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ &pos_step[col], &nor_step[col], &uv_step[col],
+ verts[quad[0]], verts[quad[1]], verts[quad[2]],
+ nors[quad[0]], nors[quad[1]], nors[quad[2]],
+ uv[0], uv[1], uv[2]);
+
+ displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ &pos_step[col], &nor_step[col], &uv_step[col],
+ verts[quad[0]], verts[quad[2]], verts[quad[3]],
+ nors[quad[0]], nors[quad[2]], nors[quad[3]],
+ uv[0], uv[2], uv[3]);
+
+ quad[2] = quad[1];
+ quad[1]++;
+ quad[3] = quad[0];
+ quad[0]++;
+ }
+ }
+ }
+ else {
+ BLI_assert(dl->type == DL_INDEX4);
+ uv[0][0] = uv[0][1] = uv[1][0] = uv[3][1] = 0.0f;
+ uv[1][1] = uv[2][0] = uv[2][1] = uv[3][0] = 1.0f;
+
+ const int i_end = dl->parts;
+ for (int i = 0; i < i_end; i++, idx += 4) {
+ displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ &pos_step[col], &nor_step[col], &uv_step[col],
+ verts[idx[0]], verts[idx[1]], verts[idx[2]],
+ nors[idx[0]], nors[idx[1]], nors[idx[2]],
+ uv[0], uv[1], uv[2]);
+
+ if (idx[2] != idx[3]) {
+ displist_vertbuf_attr_set_tri_pos_normals_and_uv(
+ &pos_step[col], &nor_step[col], &uv_step[col],
+ verts[idx[0]], verts[idx[2]], verts[idx[3]],
+ nors[idx[0]], nors[idx[2]], nors[idx[3]],
+ uv[0], uv[2], uv[3]);
}
}
- ofs += dl_vert_len(dl);
}
}
+ }
- return GWN_batch_create_ex(
- GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb),
- GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
+ for (int i = 0; i < gpumat_array_len; i++) {
+ uint vbo_len_used = GWN_vertbuf_raw_used(&pos_step[i]);
+ if (vbo_len_capacity[i] != vbo_len_used) {
+ GWN_vertbuf_data_resize(vbo[i], vbo_len_used);
+ }
+ shaded_triangles[i] = GWN_batch_create_ex(GWN_PRIM_TRIS, vbo[i], NULL, GWN_BATCH_OWNS_VBO);
}
+
+ return shaded_triangles;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index 20698fe6592..eed408de3cd 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -41,7 +41,7 @@
#include "BKE_lattice.h"
#include "BKE_deform.h"
-#include "BKE_texture.h"
+#include "BKE_colorband.h"
#include "GPU_batch.h"
@@ -260,7 +260,7 @@ static void lattice_render_data_weight_col_get(const LatticeRenderData *rdata, c
float weight = defvert_find_weight(rdata->dvert + vert_idx, actdef);
if (U.flag & USER_CUSTOM_RANGE) {
- do_colorband(&U.coba_weight, weight, r_col);
+ BKE_colorband_evaluate(&U.coba_weight, weight, r_col);
}
else {
rgb_from_weight(r_col, weight);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 8cd0c13faec..b44c5b8a20b 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -48,7 +48,7 @@
#include "BKE_editmesh_tangent.h"
#include "BKE_mesh.h"
#include "BKE_mesh_tangent.h"
-#include "BKE_texture.h"
+#include "BKE_colorband.h"
#include "bmesh.h"
@@ -1097,7 +1097,7 @@ static void mesh_render_data_ensure_vert_weight_color(MeshRenderData *rdata, con
const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
float weight = defvert_find_weight(dvert, defgroup);
if (U.flag & USER_CUSTOM_RANGE) {
- do_colorband(&U.coba_weight, weight, vweight[i]);
+ BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
}
else {
rgb_from_weight(vweight[i], weight);
@@ -1113,7 +1113,7 @@ static void mesh_render_data_ensure_vert_weight_color(MeshRenderData *rdata, con
for (int i = 0; i < rdata->vert_len; i++) {
float weight = defvert_find_weight(&rdata->dvert[i], defgroup);
if (U.flag & USER_CUSTOM_RANGE) {
- do_colorband(&U.coba_weight, weight, vweight[i]);
+ BKE_colorband_evaluate(&U.coba_weight, weight, vweight[i]);
}
else {
rgb_from_weight(vweight[i], weight);
@@ -2167,11 +2167,10 @@ static Gwn_VertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag(
}
}
const int vbo_len_used = vidx;
+ BLI_assert(vbo_len_used <= vbo_len_capacity);
if (vbo_len_used != vbo_len_capacity) {
GWN_vertbuf_data_resize(vbo, vbo_len_used);
}
- BLI_assert(vbo_len_capacity == vbo_len_used);
- UNUSED_VARS_NDEBUG(vbo_len_used);
}
return cache->ed_fcenter_pos_with_nor_and_sel;
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index e2dba8e626e..f01e7b929f8 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -132,7 +132,12 @@ Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
if (cache->batch == NULL) {
- cache->batch = BLI_displist_batch_calc_surface(&ob->curve_cache->disp);
+ ListBase *lb = &ob->curve_cache->disp;
+ cache->batch = GWN_batch_create_ex(
+ GWN_PRIM_TRIS,
+ DRW_displist_vertbuf_calc_pos_with_normals(lb),
+ DRW_displist_indexbuf_calc_triangles_in_order(lb),
+ GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
}
return cache->batch;
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index b52c8e280b3..0eb97a54ba5 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -31,7 +31,7 @@
#include "UI_resources.h"
#include "BKE_global.h"
-#include "BKE_texture.h"
+#include "BKE_colorband.h"
#include "draw_common.h"
@@ -81,6 +81,21 @@ void DRW_globals_update(void)
UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot);
UI_GetThemeColor4fv(TH_BACK, ts.colorBackground);
+ /* Curve */
+ UI_GetThemeColor4fv(TH_HANDLE_FREE, ts.colorHandleFree);
+ UI_GetThemeColor4fv(TH_HANDLE_AUTO, ts.colorHandleAuto);
+ UI_GetThemeColor4fv(TH_HANDLE_VECT, ts.colorHandleVect);
+ UI_GetThemeColor4fv(TH_HANDLE_ALIGN, ts.colorHandleAlign);
+ UI_GetThemeColor4fv(TH_HANDLE_AUTOCLAMP, ts.colorHandleAutoclamp);
+ UI_GetThemeColor4fv(TH_HANDLE_SEL_FREE, ts.colorHandleSelFree);
+ UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTO, ts.colorHandleSelAuto);
+ UI_GetThemeColor4fv(TH_HANDLE_SEL_VECT, ts.colorHandleSelVect);
+ UI_GetThemeColor4fv(TH_HANDLE_SEL_ALIGN, ts.colorHandleSelAlign);
+ UI_GetThemeColor4fv(TH_HANDLE_SEL_AUTOCLAMP, ts.colorHandleSelAutoclamp);
+ UI_GetThemeColor4fv(TH_NURB_ULINE, ts.colorNurbUline);
+ UI_GetThemeColor4fv(TH_NURB_SEL_ULINE, ts.colorNurbSelUline);
+ UI_GetThemeColor4fv(TH_ACTIVE_SPLINE, ts.colorActiveSpline);
+
/* Grid */
UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid);
/* emphasise division lines lighter instead of darker, if background is darker than grid */
@@ -130,7 +145,7 @@ void DRW_globals_update(void)
ramp.data[2].r = 1.0f;
ramp.data[2].pos = 1.0f;
- colorband_table_RGBA(&ramp, &colors, &col_size);
+ BKE_colorband_evaluate_table_rgba(&ramp, &colors, &col_size);
if (globals_ramp) {
GPU_texture_free(globals_ramp);
@@ -200,7 +215,7 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Gwn_Batch *g
return grp;
}
-DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct Gwn_Batch *geom)
{
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR);
@@ -208,20 +223,18 @@ DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Gwn_Batch
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
DRW_shgroup_attrib_float(grp, "color", 4);
- DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;
}
-DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
DRW_shgroup_attrib_float(grp, "color", 4);
- DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
return grp;
}
@@ -308,8 +321,8 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Gwn_Batch
DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
- static bool True = true;
- static bool False = false;
+ static const int True = true;
+ static const int False = false;
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
DRW_shgroup_attrib_float(grp, "color", 3);
@@ -321,7 +334,7 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Gwn_Batch *geom)
return grp;
}
-DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_Batch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE);
@@ -331,12 +344,11 @@ DRWShadingGroup *shgroup_instance_bone_envelope_wire(DRWPass *pass, struct Gwn_B
DRW_shgroup_attrib_float(grp, "radius_head", 1);
DRW_shgroup_attrib_float(grp, "radius_tail", 1);
DRW_shgroup_attrib_float(grp, "distance", 1);
- DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
return grp;
}
-DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4])
+DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_Batch *geom)
{
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID);
@@ -346,7 +358,6 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_
DRW_shgroup_attrib_float(grp, "color", 4);
DRW_shgroup_attrib_float(grp, "radius_head", 1);
DRW_shgroup_attrib_float(grp, "radius_tail", 1);
- DRW_shgroup_uniform_mat4(grp, "ObjectModelMatrix", (float *)obmat);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
return grp;
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 0bdb79b3a40..cfd88effd15 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -72,6 +72,20 @@ typedef struct GlobalsUboStorage {
float colorBackground[4];
+ float colorHandleFree[4];
+ float colorHandleAuto[4];
+ float colorHandleVect[4];
+ float colorHandleAlign[4];
+ float colorHandleAutoclamp[4];
+ float colorHandleSelFree[4];
+ float colorHandleSelAuto[4];
+ float colorHandleSelVect[4];
+ float colorHandleSelAlign[4];
+ float colorHandleSelAutoclamp[4];
+ float colorNurbUline[4];
+ float colorNurbSelUline[4];
+ float colorActiveSpline[4];
+
float colorGrid[4];
float colorGridEmphasise[4];
float colorGridAxisX[4];
@@ -92,8 +106,8 @@ struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, fl
struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, float color[4]);
struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, float color[4]);
struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct Gwn_Batch *geom, float *size);
-struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
-struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_image_plane(struct DRWPass *pass, struct Gwn_Batch *geom);
@@ -102,8 +116,8 @@ struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Gwn_Batch
struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom);
+struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom);
struct DRWShadingGroup *shgroup_instance_mball_helpers(struct DRWPass *pass, struct Gwn_Batch *geom);
int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color);
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
new file mode 100644
index 00000000000..e7ce4374d1c
--- /dev/null
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * 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.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_instance_data.c
+ * \ingroup draw
+ */
+
+/**
+ * DRW Instance Data Manager
+ * This is a special memory manager that keeps memory blocks ready to send as vbo data in one continuous allocation.
+ * This way we avoid feeding gawain each instance data one by one and unecessary memcpy.
+ * Since we loose which memory block was used each DRWShadingGroup we need to redistribute them in the same order/size
+ * to avoid to realloc each frame.
+ * This is why DRWInstanceDatas are sorted in a list for each different data size.
+ **/
+
+#include "draw_instance_data.h"
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+
+#define MAX_INSTANCE_DATA_SIZE 32 /* Can be adjusted for more */
+
+struct DRWInstanceData {
+ struct DRWInstanceData *next;
+ bool used; /* If this data is used or not. */
+ size_t chunk_size; /* Current size of the whole chunk. */
+ size_t data_size; /* Size of one instance data. */
+ size_t instance_group; /* How many instance to allocate at a time. */
+ size_t offset; /* Offset to the next instance data. */
+ float *memchunk; /* Should be float no matter what. */
+};
+
+struct DRWInstanceDataList {
+ /* Linked lists for all possible data pool size */
+ /* Not entirely sure if we should separate them in the first place.
+ * This is done to minimize the reattribution misses. */
+ DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE];
+ DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE];
+};
+
+/* -------------------------------------------------------------------- */
+
+/** \name Instance Data (DRWInstanceData)
+ * \{ */
+
+static DRWInstanceData *drw_instance_data_create(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group)
+{
+ DRWInstanceData *idata = MEM_mallocN(sizeof(DRWInstanceData), "DRWInstanceData");
+ idata->next = NULL;
+ idata->used = true;
+ idata->data_size = attrib_size;
+ idata->instance_group = instance_group;
+ idata->chunk_size = idata->data_size * instance_group;
+ idata->offset = 0;
+ idata->memchunk = MEM_mallocN(idata->chunk_size * sizeof(float), "DRWInstanceData memchunk");
+
+ BLI_assert(attrib_size > 0);
+
+ /* Push to linked list. */
+ if (idatalist->idata_head[attrib_size-1] == NULL) {
+ idatalist->idata_head[attrib_size-1] = idata;
+ }
+ else {
+ idatalist->idata_tail[attrib_size-1]->next = idata;
+ }
+ idatalist->idata_tail[attrib_size-1] = idata;
+
+ return idata;
+}
+
+static void DRW_instance_data_free(DRWInstanceData *idata)
+{
+ MEM_freeN(idata->memchunk);
+}
+
+/**
+ * Return a pointer to the next instance data space.
+ * DO NOT SAVE/REUSE THIS POINTER after the next call
+ * to this function since the chunk may have been
+ * reallocated.
+ **/
+void *DRW_instance_data_next(DRWInstanceData *idata)
+{
+ idata->offset += idata->data_size;
+
+ /* Check if chunk is large enough. realloc otherwise. */
+ if (idata->offset > idata->chunk_size) {
+ idata->chunk_size += idata->data_size * idata->instance_group;
+ idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float));
+ }
+
+ return idata->memchunk + (idata->offset - idata->data_size);
+}
+
+void *DRW_instance_data_get(DRWInstanceData *idata)
+{
+ return (void *)idata->memchunk;
+}
+
+DRWInstanceData *DRW_instance_data_request(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group)
+{
+ BLI_assert(attrib_size > 0 && attrib_size <= MAX_INSTANCE_DATA_SIZE);
+
+ DRWInstanceData *idata = idatalist->idata_head[attrib_size - 1];
+
+ /* Search for an unused data chunk. */
+ for (; idata; idata = idata->next) {
+ if (idata->used == false) {
+ idata->used = true;
+ return idata;
+ }
+ }
+
+ return drw_instance_data_create(idatalist, attrib_size, instance_group);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Instance Data List (DRWInstanceDataList)
+ * \{ */
+
+DRWInstanceDataList *DRW_instance_data_list_create(void)
+{
+ return MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
+}
+
+void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata, *next_idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
+ next_idata = idata->next;
+ DRW_instance_data_free(idata);
+ MEM_freeN(idata);
+ }
+ idatalist->idata_head[i] = NULL;
+ idatalist->idata_tail[i] = NULL;
+ }
+}
+
+void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
+ idata->used = false;
+ idata->offset = 0;
+ }
+ }
+}
+
+void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata, *next_idata;
+
+ /* Remove unused data blocks and sanitize each list. */
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ idatalist->idata_tail[i] = NULL;
+ for (idata = idatalist->idata_head[i]; idata; idata = next_idata) {
+ next_idata = idata->next;
+ if (idata->used == false) {
+ if (idatalist->idata_head[i] == idata) {
+ idatalist->idata_head[i] = next_idata;
+ }
+ else {
+ /* idatalist->idata_tail[i] is garanteed not to be null in this case. */
+ idatalist->idata_tail[i]->next = next_idata;
+ }
+ DRW_instance_data_free(idata);
+ MEM_freeN(idata);
+ }
+ else {
+ if (idatalist->idata_tail[i] != NULL) {
+ idatalist->idata_tail[i]->next = idata;
+ }
+ idatalist->idata_tail[i] = idata;
+ }
+ }
+ }
+}
+
+void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist)
+{
+ DRWInstanceData *idata;
+
+ for (int i = 0; i < MAX_INSTANCE_DATA_SIZE; ++i) {
+ for (idata = idatalist->idata_head[i]; idata; idata = idata->next) {
+ /* Rounding up to nearest chunk size to compare. */
+ size_t fac = idata->data_size * idata->instance_group;
+ size_t tmp = idata->offset + fac - 1;
+ size_t rounded_offset = tmp - tmp % fac;
+ if (rounded_offset < idata->chunk_size) {
+ idata->chunk_size = rounded_offset;
+ idata->memchunk = MEM_reallocN(idata->memchunk, idata->chunk_size * sizeof(float));
+ }
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
new file mode 100644
index 00000000000..637c0e3cc24
--- /dev/null
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * 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.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_instance_data.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_INSTANCE_DATA_H__
+#define __DRAW_INSTANCE_DATA_H__
+
+typedef struct DRWInstanceData DRWInstanceData;
+typedef struct DRWInstanceDataList DRWInstanceDataList;
+
+void *DRW_instance_data_next(DRWInstanceData *idata);
+void *DRW_instance_data_get(DRWInstanceData *idata);
+DRWInstanceData *DRW_instance_data_request(
+ DRWInstanceDataList *idatalist, unsigned int attrib_size, unsigned int instance_group);
+
+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 264fc079e42..55195b88c05 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -25,14 +25,15 @@
#include <stdio.h>
-#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_mempool.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BIF_glutil.h"
+#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
@@ -47,10 +48,12 @@
#include "DRW_render.h"
#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
#include "DNA_view3d_types.h"
#include "DNA_screen_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "DNA_meta_types.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -85,6 +88,8 @@
/* only for callbacks */
#include "draw_cache_impl.h"
+#include "draw_instance_data.h"
+
#include "draw_mode_engines.h"
#include "engines/clay/clay_engine.h"
#include "engines/eevee/eevee_engine.h"
@@ -180,19 +185,8 @@ struct DRWUniform {
const void *value;
};
-typedef struct DRWAttrib {
- struct DRWAttrib *prev;
- char name[MAX_ATTRIB_NAME];
- int location;
- int format_id;
- int size; /* number of component */
- int type;
-} DRWAttrib;
-
struct DRWInterface {
DRWUniform *uniforms; /* DRWUniform, single-linked list */
- DRWAttrib *attribs; /* DRWAttrib, single-linked list */
- DRWAttrib *attribs_first; /* First added attrib to traverse in the right order */
int attribs_count;
int attribs_stride;
int attribs_size[16];
@@ -218,6 +212,12 @@ struct DRWInterface {
/* Dynamic batch */
Gwn_Batch *instance_batch; /* contains instances attributes */
GLuint instance_vbo; /* same as instance_batch but generated from DRWCalls */
+ struct DRWInstanceData *inst_data;
+#ifdef USE_GPU_SELECT
+ struct DRWInstanceData *inst_selectid;
+ /* Override for single object instances. */
+ int override_selectid;
+#endif
int instance_count;
Gwn_VertFormat vbo_format;
};
@@ -259,12 +259,6 @@ typedef struct DRWCallGenerate {
void *user_data;
} DRWCallGenerate;
-typedef struct DRWCallDynamic {
- DRWCallHeader head;
-
- const void *data[MAX_ATTRIB_COUNT];
-} DRWCallDynamic;
-
struct DRWShadingGroup {
struct DRWShadingGroup *next;
@@ -309,22 +303,15 @@ enum {
DRW_CALL_DYNAMIC,
};
-/* only 16 bits long */
-enum {
- STENCIL_SELECT = (1 << 0),
- STENCIL_ACTIVE = (1 << 1),
-};
-
/** Render State: No persistent data between draw calls. */
static struct DRWGlobalState {
/* Cache generation */
ViewportMemoryPool *vmempool;
DRWUniform *last_uniform;
- DRWAttrib *last_attrib;
DRWCall *last_call;
DRWCallGenerate *last_callgenerate;
- DRWCallDynamic *last_calldynamic;
DRWShadingGroup *last_shgroup;
+ DRWInstanceDataList *idatalist;
/* Rendering state */
GPUShader *shader;
@@ -351,6 +338,7 @@ static struct DRWGlobalState {
unsigned int is_depth : 1;
unsigned int is_image_render : 1;
unsigned int is_scene_render : 1;
+ unsigned int draw_background : 1;
} options;
/* Current rendering context */
@@ -409,6 +397,7 @@ static void drw_texture_get_format(
case DRW_TEX_RGB_11_11_10: *r_data_type = GPU_R11F_G11F_B10F; break;
case DRW_TEX_RG_8: *r_data_type = GPU_RG8; break;
case DRW_TEX_RG_16: *r_data_type = GPU_RG16F; break;
+ case DRW_TEX_RG_16I: *r_data_type = GPU_RG16I; break;
case DRW_TEX_RG_32: *r_data_type = GPU_RG32F; break;
case DRW_TEX_R_8: *r_data_type = GPU_R8; break;
case DRW_TEX_R_16: *r_data_type = GPU_R16F; break;
@@ -442,6 +431,7 @@ static void drw_texture_get_format(
break;
case DRW_TEX_RG_8:
case DRW_TEX_RG_16:
+ case DRW_TEX_RG_16I:
case DRW_TEX_RG_32:
*r_channels = 2;
break;
@@ -594,24 +584,11 @@ GPUShader *DRW_shader_create_with_lib(
char *frag_with_lib = NULL;
char *geom_with_lib = NULL;
- DynStr *ds_vert = BLI_dynstr_new();
- BLI_dynstr_append(ds_vert, lib);
- BLI_dynstr_append(ds_vert, vert);
- vert_with_lib = BLI_dynstr_get_cstring(ds_vert);
- BLI_dynstr_free(ds_vert);
-
- DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, lib);
- BLI_dynstr_append(ds_frag, frag);
- frag_with_lib = BLI_dynstr_get_cstring(ds_frag);
- BLI_dynstr_free(ds_frag);
+ vert_with_lib = BLI_string_joinN(lib, vert);
+ frag_with_lib = BLI_string_joinN(lib, frag);
if (geom) {
- DynStr *ds_geom = BLI_dynstr_new();
- BLI_dynstr_append(ds_geom, lib);
- BLI_dynstr_append(ds_geom, geom);
- geom_with_lib = BLI_dynstr_get_cstring(ds_geom);
- BLI_dynstr_free(ds_geom);
+ geom_with_lib = BLI_string_joinN(lib, geom);
}
sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines);
@@ -682,12 +659,14 @@ static void drw_interface_create(DRWInterface *interface, GPUShader *shader)
interface->attribs_stride = 0;
interface->instance_vbo = 0;
interface->instance_batch = NULL;
+ interface->inst_data = NULL;
+ interface->uniforms = NULL;
+#ifdef USE_GPU_SELECT
+ interface->inst_selectid = NULL;
+ interface->override_selectid = -1;
+#endif
memset(&interface->vbo_format, 0, sizeof(Gwn_VertFormat));
-
- interface->uniforms = NULL;
- interface->attribs = NULL;
- interface->attribs_first = NULL;
}
@@ -725,14 +704,22 @@ static void drw_interface_uniform(DRWShadingGroup *shgroup, const char *name,
shgroup->interface.uniforms = uni;
}
-static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType type, int size, bool dummy)
+static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRWAttribType UNUSED(type), int size, bool dummy)
{
- DRWAttrib *attrib = BLI_mempool_alloc(DST.vmempool->attribs);
+ unsigned int attrib_id = shgroup->interface.attribs_count;
GLuint program = GPU_shader_get_program(shgroup->shader);
- attrib->location = glGetAttribLocation(program, name);
- attrib->type = type;
- attrib->size = size;
+ shgroup->interface.attribs_loc[attrib_id] = glGetAttribLocation(program, name);
+ shgroup->interface.attribs_size[attrib_id] = size;
+ shgroup->interface.attribs_stride += size;
+ shgroup->interface.attribs_count += 1;
+
+ if (shgroup->type != DRW_SHG_INSTANCE) {
+ BLI_assert(size <= 4); /* Matrices are not supported by Gawain. */
+ GWN_vertformat_attr_add(&shgroup->interface.vbo_format, name, GWN_COMP_F32, size, GWN_FETCH_FLOAT);
+ }
+
+ BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
/* Adding attribute even if not found for now (to keep memory alignment).
* Should ideally take vertex format automatically from batch eventually */
@@ -747,23 +734,6 @@ static void drw_interface_attrib(DRWShadingGroup *shgroup, const char *name, DRW
#else
UNUSED_VARS(dummy);
#endif
-
- BLI_assert(BLI_strnlen(name, 32) < 32);
- BLI_strncpy(attrib->name, name, 32);
-
- shgroup->interface.attribs_count += 1;
- BLI_assert(shgroup->interface.attribs_count < MAX_ATTRIB_COUNT);
-
- /* Prepend */
- if (shgroup->interface.attribs == NULL) {
- shgroup->interface.attribs = attrib;
- shgroup->interface.attribs_first = attrib;
- }
- else {
- shgroup->interface.attribs->prev = attrib;
- shgroup->interface.attribs = attrib;
- }
- attrib->prev = NULL;
}
/** \} */
@@ -847,16 +817,10 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
else {
switch (input->type) {
case GPU_FLOAT:
- DRW_shgroup_uniform_float(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC2:
- DRW_shgroup_uniform_vec2(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC3:
- DRW_shgroup_uniform_vec3(grp, input->shadername, (float *)input->dynamicvec, 1);
- break;
case GPU_VEC4:
- DRW_shgroup_uniform_vec4(grp, input->shadername, (float *)input->dynamicvec, 1);
+ /* Should already be in the material ubo. */
break;
case GPU_MAT3:
DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
@@ -961,14 +925,6 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
GWN_BATCH_DISCARD_SAFE(shgroup->batch_geom);
}
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
-{
- BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
- BLI_assert(shgroup->interface.instance_batch == NULL);
-
- shgroup->interface.instance_batch = instances;
-}
-
#define CALL_PREPEND(shgroup, call) { \
if (shgroup->calls == NULL) { \
shgroup->calls = call; \
@@ -981,10 +937,25 @@ void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *inst
call->head.prev = NULL; \
} ((void)0)
+void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *instances)
+{
+ BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
+ BLI_assert(shgroup->interface.instance_batch == NULL);
+
+ shgroup->interface.instance_batch = instances;
+
+#ifdef USE_GPU_SELECT
+ DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ call->head.select_id = g_DRW_select_id;
+
+ CALL_PREPEND(shgroup, call);
+#endif
+}
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
{
BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
@@ -1006,6 +977,7 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obm
void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, Object *ob)
{
BLI_assert(geom != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
@@ -1027,6 +999,7 @@ void DRW_shgroup_call_generate_add(
float (*obmat)[4])
{
BLI_assert(geometry_fn != NULL);
+ BLI_assert(shgroup->type == DRW_SHG_NORMAL);
DRWCallGenerate *call = BLI_mempool_alloc(DST.vmempool->calls_generate);
@@ -1070,43 +1043,30 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup, const void *at
DRWInterface *interface = &shgroup->interface;
#ifdef USE_GPU_SELECT
- if ((G.f & G_PICKSEL) && (interface->instance_count > 0)) {
- DRWShadingGroup *original_shgroup = shgroup;
- shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
- memcpy(shgroup, original_shgroup, sizeof(DRWShadingGroup));
-
- shgroup->calls = NULL;
- shgroup->calls_first = NULL;
-
- interface = &shgroup->interface;
- interface->instance_count = 0;
-
- /* Append */
- if (shgroup->pass_parent->shgroups != NULL) {
- shgroup->pass_parent->shgroups_last->next = shgroup;
- }
- else {
- shgroup->pass_parent->shgroups = shgroup;
+ if (G.f & G_PICKSEL) {
+ if (interface->inst_selectid == NULL) {
+ interface->inst_selectid = DRW_instance_data_request(DST.idatalist, 1, 128);
}
- shgroup->pass_parent->shgroups_last = shgroup;
- shgroup->next = NULL;
+
+ int *select_id = DRW_instance_data_next(interface->inst_selectid);
+ *select_id = g_DRW_select_id;
}
#endif
- DRWCallDynamic *call = BLI_mempool_alloc(DST.vmempool->calls_dynamic);
-
- CALL_PREPEND(shgroup, call);
-
BLI_assert(attr_len == interface->attribs_count);
UNUSED_VARS_NDEBUG(attr_len);
- call->head.type = DRW_CALL_DYNAMIC;
-#ifdef USE_GPU_SELECT
- call->head.select_id = g_DRW_select_id;
-#endif
+ if (interface->attribs_stride > 0) {
+ if (interface->inst_data == NULL) {
+ interface->inst_data = DRW_instance_data_request(DST.idatalist, interface->attribs_stride, 16);
+ }
+
+ float *data = DRW_instance_data_next(interface->inst_data);
- if (interface->attribs_count != 0) {
- memcpy((void *)call->data, attr, sizeof(void *) * interface->attribs_count);
+ for (int i = 0; i < interface->attribs_count; ++i) {
+ memcpy(data, attr[i], sizeof(float) * interface->attribs_size[i]);
+ data = data + interface->attribs_size[i];
+ }
}
interface->instance_count += 1;
@@ -1117,8 +1077,15 @@ void DRW_shgroup_set_instance_count(DRWShadingGroup *shgroup, int count)
{
DRWInterface *interface = &shgroup->interface;
+ BLI_assert(interface->instance_count == 0);
BLI_assert(interface->attribs_count == 0);
+#ifdef USE_GPU_SELECT
+ if (G.f & G_PICKSEL) {
+ interface->override_selectid = g_DRW_select_id;
+ }
+#endif
+
interface->instance_count = count;
}
@@ -1161,7 +1128,7 @@ void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, GPUT
drw_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, tex, 0, 1);
}
-void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize)
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
{
drw_interface_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize);
}
@@ -1234,32 +1201,13 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
return;
/* Upload Data */
- if (interface->vbo_format.attrib_ct == 0) {
- for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev) {
- BLI_assert(attrib->size <= 4); /* matrices have no place here for now */
- if (attrib->type == DRW_ATTRIB_FLOAT) {
- attrib->format_id = GWN_vertformat_attr_add(
- &interface->vbo_format, attrib->name, GWN_COMP_F32, attrib->size, GWN_FETCH_FLOAT);
- }
- else if (attrib->type == DRW_ATTRIB_INT) {
- attrib->format_id = GWN_vertformat_attr_add(
- &interface->vbo_format, attrib->name, GWN_COMP_I8, attrib->size, GWN_FETCH_INT);
- }
- else {
- BLI_assert(false);
- }
- }
- }
-
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&interface->vbo_format);
- GWN_vertbuf_data_alloc(vbo, nbr);
-
- int j = 0;
- for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev, j++) {
- int i = 0;
- for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
- GWN_vertbuf_attr_set(vbo, attrib->format_id, j, call->data[i]);
- }
+ if (interface->inst_data) {
+ GWN_vertbuf_data_set(vbo, nbr, DRW_instance_data_get(interface->inst_data), false);
+ } else {
+ /* Use unitialized memory. This is for dummy vertex buffers. */
+ /* XXX TODO do not alloc at all. */
+ GWN_vertbuf_data_alloc(vbo, nbr);
}
/* TODO make the batch dynamic instead of freeing it every times */
@@ -1271,10 +1219,9 @@ static void shgroup_dynamic_batch(DRWShadingGroup *shgroup)
static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
{
- int i = 0;
- int offset = 0;
DRWInterface *interface = &shgroup->interface;
int buffer_size = 0;
+ void *data = NULL;
if (interface->instance_batch != NULL) {
return;
@@ -1289,26 +1236,8 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
return;
}
- /* only once */
- if (interface->attribs_stride == 0) {
- for (DRWAttrib *attrib = interface->attribs_first; attrib; attrib = attrib->prev, i++) {
- BLI_assert(attrib->type == DRW_ATTRIB_FLOAT); /* Only float for now */
- interface->attribs_stride += attrib->size;
- interface->attribs_size[i] = attrib->size;
- interface->attribs_loc[i] = attrib->location;
- }
- }
-
/* Gather Data */
buffer_size = sizeof(float) * interface->attribs_stride * interface->instance_count;
- float *data = MEM_mallocN(buffer_size, "Instance VBO data");
-
- for (DRWCallDynamic *call = shgroup->calls_first; call; call = call->head.prev) {
- for (int j = 0; j < interface->attribs_count; ++j) {
- memcpy(data + offset, call->data[j], sizeof(float) * interface->attribs_size[j]);
- offset += interface->attribs_size[j];
- }
- }
/* TODO poke mike to add this to gawain */
if (interface->instance_vbo) {
@@ -1316,11 +1245,13 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
interface->instance_vbo = 0;
}
+ if (interface->inst_data) {
+ data = DRW_instance_data_get(interface->inst_data);
+ }
+
glGenBuffers(1, &interface->instance_vbo);
glBindBuffer(GL_ARRAY_BUFFER, interface->instance_vbo);
glBufferData(GL_ARRAY_BUFFER, buffer_size, data, GL_STATIC_DRAW);
-
- MEM_freeN(data);
}
static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
@@ -1359,6 +1290,11 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
return pass;
}
+void DRW_pass_state_set(DRWPass *pass, DRWState state)
+{
+ pass->state = state;
+}
+
void DRW_pass_free(DRWPass *pass)
{
for (DRWShadingGroup *shgroup = pass->shgroups; shgroup; shgroup = shgroup->next) {
@@ -1597,14 +1533,16 @@ static void drw_state_set(DRWState state)
{
int test;
if (CHANGED_ANY_STORE_VAR(
- DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION,
+ DRW_STATE_BLEND | DRW_STATE_ADDITIVE | DRW_STATE_MULTIPLY | DRW_STATE_TRANSMISSION |
+ DRW_STATE_ADDITIVE_FULL,
test))
{
if (test) {
glEnable(GL_BLEND);
if ((state & DRW_STATE_BLEND) != 0) {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, /* RGB */
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
}
else if ((state & DRW_STATE_MULTIPLY) != 0) {
glBlendFunc(GL_DST_COLOR, GL_ZERO);
@@ -1613,7 +1551,13 @@ static void drw_state_set(DRWState state)
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
}
else if ((state & DRW_STATE_ADDITIVE) != 0) {
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ /* Do not let alpha accumulate but premult the source RGB by it. */
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, /* RGB */
+ GL_ZERO, GL_ONE); /* Alpha */
+ }
+ else if ((state & DRW_STATE_ADDITIVE_FULL) != 0) {
+ /* Let alpha accumulate. */
+ glBlendFunc(GL_ONE, GL_ONE);
}
else {
BLI_assert(0);
@@ -1839,28 +1783,37 @@ static void draw_geometry_prepare(
GPU_shader_uniform_vector(shgroup->shader, interface->clipplanes, 4, DST.num_clip_planes, (float *)DST.clip_planes_eq);
}
-static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
+static void draw_geometry_execute_ex(
+ DRWShadingGroup *shgroup, Gwn_Batch *geom, unsigned int start, unsigned int count)
{
DRWInterface *interface = &shgroup->interface;
/* step 2 : bind vertex array & draw */
GWN_batch_program_set(geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
if (interface->instance_batch) {
+ /* Used for Particles. Cannot do partial drawing. */
GWN_batch_draw_stupid_instanced_with_batch(geom, interface->instance_batch);
}
else if (interface->instance_vbo) {
GWN_batch_draw_stupid_instanced(
- geom, interface->instance_vbo, interface->instance_count, interface->attribs_count,
+ geom, interface->instance_vbo, start, count, interface->attribs_count,
interface->attribs_stride, interface->attribs_size, interface->attribs_loc);
}
else {
- GWN_batch_draw_stupid(geom);
+ GWN_batch_draw_stupid(geom, start, count);
}
/* XXX this just tells gawain we are done with the shader.
* This does not unbind the shader. */
GWN_batch_program_unset(geom);
}
-static void draw_geometry(DRWShadingGroup *shgroup, Gwn_Batch *geom, const float (*obmat)[4], ID *ob_data)
+static void draw_geometry_execute(DRWShadingGroup *shgroup, Gwn_Batch *geom)
+{
+ draw_geometry_execute_ex(shgroup, geom, 0, 0);
+}
+
+static void draw_geometry(
+ DRWShadingGroup *shgroup, Gwn_Batch *geom, const float (*obmat)[4], ID *ob_data,
+ unsigned int start, unsigned int count)
{
float *texcoloc = NULL;
float *texcosize = NULL;
@@ -1870,15 +1823,31 @@ static void draw_geometry(DRWShadingGroup *shgroup, Gwn_Batch *geom, const float
case ID_ME:
BKE_mesh_texspace_get_reference((Mesh *)ob_data, NULL, &texcoloc, NULL, &texcosize);
break;
+ case ID_CU:
+ {
+ Curve *cu = (Curve *)ob_data;
+ if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_curve_texspace_calc(cu);
+ }
+ texcoloc = cu->loc;
+ texcosize = cu->size;
+ break;
+ }
+ case ID_MB:
+ {
+ MetaBall *mb = (MetaBall *)ob_data;
+ texcoloc = mb->loc;
+ texcosize = mb->size;
+ break;
+ }
default:
- /* TODO, curve, metaball? */
break;
}
}
draw_geometry_prepare(shgroup, obmat, texcoloc, texcosize);
- draw_geometry_execute(shgroup, geom);
+ draw_geometry_execute_ex(shgroup, geom, start, count);
}
static void bind_texture(GPUTexture *tex)
@@ -2012,15 +1981,39 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
GPU_select_load_id((_call)->head.select_id); \
} ((void)0)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_call_last, _call_first) \
- if ((G.f & G_PICKSEL) && _call_first) { \
- BLI_assert(_call_first && (_call_first == _call_last)); \
- GPU_select_load_id(((DRWCall *)_call_first)->head.select_id); \
- } ((void)0)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
+ _start = 0; \
+ _count = _shgroup->interface.instance_count; \
+ int *select_id = NULL; \
+ if (G.f & G_PICKSEL) { \
+ if (_shgroup->interface.override_selectid == -1) { \
+ select_id = DRW_instance_data_get(_shgroup->interface.inst_selectid); \
+ switch (_shgroup->type) { \
+ case DRW_SHG_TRIANGLE_BATCH: _count = 3; break; \
+ case DRW_SHG_LINE_BATCH: _count = 2; break; \
+ default: _count = 1; break; \
+ } \
+ } \
+ else { \
+ GPU_select_load_id(_shgroup->interface.override_selectid); \
+ } \
+ } \
+ while (_start < _shgroup->interface.instance_count) { \
+ if (select_id) { \
+ GPU_select_load_id(select_id[_start]); \
+ }
+
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \
+ _start += _count; \
+ }
#else
# define GPU_SELECT_LOAD_IF_PICKSEL(call)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(call, _call_first)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
+# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
+ _start = 0; \
+ _count = _shgroup->interface.instance_count;
+
#endif
/* Rendering Calls */
@@ -2032,14 +2025,28 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
if (shgroup->type == DRW_SHG_INSTANCE &&
(interface->instance_count > 0 || interface->instance_batch != NULL))
{
- GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
- draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data);
+ if (interface->instance_batch != NULL) {
+ GPU_SELECT_LOAD_IF_PICKSEL((DRWCall *)shgroup->calls_first);
+ draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, 0, 0);
+ }
+ else {
+ unsigned int count, start;
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
+ {
+ draw_geometry(shgroup, shgroup->instance_geom, obmat, shgroup->instance_data, start, count);
+ }
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
+ }
}
else {
/* Some dynamic batch can have no geom (no call to aggregate) */
if (shgroup->batch_geom) {
- GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup->calls, shgroup->calls_first);
- draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL);
+ unsigned int count, start;
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST(shgroup, start, count)
+ {
+ draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL, start, count);
+ }
+ GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count)
}
}
}
@@ -2055,7 +2062,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
GPU_SELECT_LOAD_IF_PICKSEL(call);
if (call->head.type == DRW_CALL_SINGLE) {
- draw_geometry(shgroup, call->geometry, call->obmat, call->ob_data);
+ draw_geometry(shgroup, call->geometry, call->obmat, call->ob_data, 0, 0);
}
else {
BLI_assert(call->head.type == DRW_CALL_GENERATE);
@@ -2195,9 +2202,7 @@ bool DRW_object_is_renderable(Object *ob)
Scene *scene = DST.draw_ctx.scene;
Object *obedit = scene->obedit;
- if (!BKE_object_is_visible(ob)) {
- return false;
- }
+ BLI_assert(BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE));
if (ob->type == OB_MESH) {
if (ob == obedit) {
@@ -2216,6 +2221,18 @@ bool DRW_object_is_renderable(Object *ob)
return true;
}
+/**
+ * Return whether this object is visible depending if
+ * we are rendering or drawing in the viewport.
+ */
+bool DRW_check_object_visible_within_active_context(Object *ob)
+{
+ const eObjectVisibilityCheck mode = DRW_state_is_scene_render() ?
+ OB_VISIBILITY_CHECK_FOR_RENDER :
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+ return BKE_object_is_visible(ob, mode);
+}
+
bool DRW_object_is_flat_normal(const Object *ob)
{
if (ob->type == OB_MESH) {
@@ -2227,7 +2244,6 @@ bool DRW_object_is_flat_normal(const Object *ob)
return true;
}
-
/**
* Return true if the object has its own draw mode.
* Caller must check this is active */
@@ -2266,6 +2282,7 @@ static GPUTextureFormat convert_tex_format(
case DRW_TEX_R_32: *r_channels = 1; return GPU_R32F;
case DRW_TEX_RG_8: *r_channels = 2; return GPU_RG8;
case DRW_TEX_RG_16: *r_channels = 2; return GPU_RG16F;
+ case DRW_TEX_RG_16I: *r_channels = 2; return GPU_RG16I;
case DRW_TEX_RG_32: *r_channels = 2; return GPU_RG32F;
case DRW_TEX_RGBA_8: *r_channels = 4; return GPU_RGBA8;
case DRW_TEX_RGBA_16: *r_channels = 4; return GPU_RGBA16F;
@@ -2281,11 +2298,17 @@ static GPUTextureFormat convert_tex_format(
}
}
+struct GPUFrameBuffer *DRW_framebuffer_create(void)
+{
+ return GPU_framebuffer_create();
+}
+
void DRW_framebuffer_init(
struct GPUFrameBuffer **fb, void *engine_type, int width, int height,
DRWFboTexture textures[MAX_FBO_TEX], int textures_len)
{
BLI_assert(textures_len <= MAX_FBO_TEX);
+ BLI_assert(width > 0 && height > 0);
bool create_fb = false;
int color_attachment = -1;
@@ -2298,6 +2321,7 @@ void DRW_framebuffer_init(
for (int i = 0; i < textures_len; ++i) {
int channels;
bool is_depth;
+ bool create_tex = false;
DRWFboTexture fbotex = textures[i];
bool is_temp = (fbotex.flag & DRW_TEX_TEMP) != 0;
@@ -2310,16 +2334,18 @@ void DRW_framebuffer_init(
*fbotex.tex = GPU_viewport_texture_pool_query(
DST.viewport, engine_type, width, height, channels, gpu_format);
}
- else if (create_fb) {
+ else {
*fbotex.tex = GPU_texture_create_2D_custom(
width, height, channels, gpu_format, NULL, NULL);
+ create_tex = true;
}
}
- if (create_fb) {
- if (!is_depth) {
- ++color_attachment;
- }
+ if (!is_depth) {
+ ++color_attachment;
+ }
+
+ if (create_fb || create_tex) {
drw_texture_set_parameters(*fbotex.tex, fbotex.flag);
GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment, 0);
}
@@ -2339,7 +2365,9 @@ void DRW_framebuffer_init(
}
}
- GPU_framebuffer_bind(DST.default_framebuffer);
+ if (DST.default_framebuffer != NULL) {
+ GPU_framebuffer_bind(DST.default_framebuffer);
+ }
}
}
@@ -2387,6 +2415,14 @@ void DRW_framebuffer_read_data(int x, int y, int w, int h, int channels, int slo
glReadPixels(x, y, w, h, type, GL_FLOAT, data);
}
+void DRW_framebuffer_read_depth(int x, int y, int w, int h, float *data)
+{
+ GLenum type = GL_DEPTH_COMPONENT;
+
+ glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */
+ glReadPixels(x, y, w, h, type, GL_FLOAT, data);
+}
+
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
{
GPU_framebuffer_texture_attach(fb, tex, slot, mip);
@@ -2437,18 +2473,22 @@ void DRW_transform_to_display(GPUTexture *tex)
bool use_ocio = false;
- {
+ /* View transform is already applied for offscreen, don't apply again, see: T52046 */
+ if (!(DST.options.is_image_render && !DST.options.is_scene_render)) {
Scene *scene = DST.draw_ctx.scene;
- /* View transform is already applied for offscreen, don't apply again, see: T52046 */
- ColorManagedViewSettings *view_settings =
- (DST.options.is_image_render && !DST.options.is_scene_render) ?
- NULL : &scene->view_settings;
use_ocio = IMB_colormanagement_setup_glsl_draw_from_space(
- view_settings, &scene->display_settings, NULL, dither, false);
+ &scene->view_settings, &scene->display_settings, NULL, dither, false);
}
if (!use_ocio) {
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB);
+ /* View transform is already applied for offscreen, don't apply again, see: T52046 */
+ if (DST.options.is_image_render && !DST.options.is_scene_render) {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB);
+ }
immUniform1i("image", 0);
}
@@ -2541,12 +2581,13 @@ static void drw_viewport_cache_resize(void)
if (DST.vmempool != NULL) {
BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_count(DST.vmempool->calls));
BLI_mempool_clear_ex(DST.vmempool->calls_generate, BLI_mempool_count(DST.vmempool->calls_generate));
- BLI_mempool_clear_ex(DST.vmempool->calls_dynamic, BLI_mempool_count(DST.vmempool->calls_dynamic));
BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_count(DST.vmempool->shgroups));
BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_count(DST.vmempool->uniforms));
- BLI_mempool_clear_ex(DST.vmempool->attribs, BLI_mempool_count(DST.vmempool->attribs));
BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_count(DST.vmempool->passes));
}
+
+ DRW_instance_data_list_free_unused(DST.idatalist);
+ DRW_instance_data_list_resize(DST.idatalist);
}
/* It also stores viewport variable to an immutable place: DST
@@ -2575,21 +2616,18 @@ static void drw_viewport_var_init(void)
if (DST.vmempool->calls_generate == NULL) {
DST.vmempool->calls_generate = BLI_mempool_create(sizeof(DRWCallGenerate), 0, 512, 0);
}
- if (DST.vmempool->calls_dynamic == NULL) {
- DST.vmempool->calls_dynamic = BLI_mempool_create(sizeof(DRWCallDynamic), 0, 512, 0);
- }
if (DST.vmempool->shgroups == NULL) {
DST.vmempool->shgroups = BLI_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0);
}
if (DST.vmempool->uniforms == NULL) {
DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0);
}
- if (DST.vmempool->attribs == NULL) {
- DST.vmempool->attribs = BLI_mempool_create(sizeof(DRWAttrib), 0, 256, 0);
- }
if (DST.vmempool->passes == NULL) {
DST.vmempool->passes = BLI_mempool_create(sizeof(DRWPass), 0, 64, 0);
}
+
+ DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
+ DRW_instance_data_list_reset(DST.idatalist);
}
else {
DST.size[0] = 0;
@@ -2598,14 +2636,17 @@ static void drw_viewport_var_init(void)
DST.default_framebuffer = NULL;
DST.vmempool = NULL;
}
- /* Refresh DST.screenvecs */
- copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
- copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
- normalize_v3(DST.screenvecs[0]);
- normalize_v3(DST.screenvecs[1]);
- /* Refresh DST.pixelsize */
- DST.pixsize = rv3d->pixsize;
+ if (rv3d != NULL) {
+ /* Refresh DST.screenvecs */
+ copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
+ copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
+ normalize_v3(DST.screenvecs[0]);
+ normalize_v3(DST.screenvecs[1]);
+
+ /* Refresh DST.pixelsize */
+ DST.pixsize = rv3d->pixsize;
+ }
/* Reset facing */
DST.frontface = GL_CCW;
@@ -2636,6 +2677,7 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
copy_m4_m4(mat, viewport_matrix_override.mat[type]);
}
else {
+ BLI_assert(rv3d != NULL); /* Can't use this in render mode. */
switch (type) {
case DRW_MAT_PERS:
copy_m4_m4(mat, rv3d->persmat);
@@ -2676,7 +2718,16 @@ void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type)
bool DRW_viewport_is_persp_get(void)
{
RegionView3D *rv3d = DST.draw_ctx.rv3d;
- return rv3d->is_persp;
+ if (rv3d) {
+ return rv3d->is_persp;
+ }
+ else {
+ if (viewport_matrix_override.override[DRW_MAT_WIN]) {
+ return viewport_matrix_override.mat[DRW_MAT_WIN][3][3] == 0.0f;
+ }
+ }
+ BLI_assert(0);
+ return false;
}
DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
@@ -2737,33 +2788,40 @@ void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*cal
/** \name Objects (DRW_object)
* \{ */
-void *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
{
for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
if (oed->engine_type == engine_type) {
- return oed->storage;
+ return oed;
}
}
return NULL;
}
-void **DRW_object_engine_data_ensure(
- Object *ob, DrawEngineType *engine_type, void (*callback)(void *storage))
+ObjectEngineData *DRW_object_engine_data_ensure(
+ Object *ob,
+ DrawEngineType *engine_type,
+ size_t size,
+ ObjectEngineDataInitCb init_cb,
+ ObjectEngineDataFreeCb free_cb)
{
- ObjectEngineData *oed;
-
- for (oed = ob->drawdata.first; oed; oed = oed->next) {
- if (oed->engine_type == engine_type) {
- return &oed->storage;
- }
+ BLI_assert(size >= sizeof(ObjectEngineData));
+ /* Try to re-use existing data. */
+ ObjectEngineData *oed = DRW_object_engine_data_get(ob, engine_type);
+ if (oed != NULL) {
+ return oed;
}
-
- oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
+ /* Allocate new data. */
+ oed = MEM_callocN(size, "ObjectEngineData");
oed->engine_type = engine_type;
- oed->free = callback;
+ oed->free = free_cb;
+ /* Perform user-side initialization, if needed. */
+ if (init_cb != NULL) {
+ init_cb(oed);
+ }
+ /* Register in the list. */
BLI_addtail(&ob->drawdata, oed);
-
- return &oed->storage;
+ return oed;
}
/* XXX There is definitly some overlap between this and DRW_object_engine_data_ensure.
@@ -2833,6 +2891,10 @@ static void drw_engines_cache_populate(Object *ob)
DrawEngineType *engine = link->data;
ViewportEngineData *data = DRW_viewport_engine_data_ensure(engine);
+ if (engine->id_update) {
+ engine->id_update(data, &ob->id);
+ }
+
if (engine->cache_populate) {
engine->cache_populate(data, ob);
}
@@ -2870,7 +2932,9 @@ static void drw_engines_draw_background(void)
}
/* No draw_background found, doing default background */
- DRW_draw_background();
+ if (DRW_state_draw_background()) {
+ DRW_draw_background();
+ }
}
static void drw_engines_draw_scene(void)
@@ -3244,6 +3308,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
ARegion *ar = update_ctx->ar;
View3D *v3d = update_ctx->v3d;
RegionView3D *rv3d = ar->regiondata;
+ Depsgraph *depsgraph = update_ctx->depsgraph;
Scene *scene = update_ctx->scene;
ViewLayer *view_layer = update_ctx->view_layer;
@@ -3257,7 +3322,8 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
DST.viewport = rv3d->viewport;
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, NULL,
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph,
+ NULL,
};
drw_engines_enable(scene, view_layer, engine_type);
@@ -3293,6 +3359,7 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
ARegion *ar = update_ctx->ar;
View3D *v3d = update_ctx->v3d;
RegionView3D *rv3d = ar->regiondata;
+ Depsgraph *depsgraph = update_ctx->depsgraph;
Scene *scene = update_ctx->scene;
ViewLayer *view_layer = update_ctx->view_layer;
if (rv3d->viewport == NULL) {
@@ -3302,7 +3369,7 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
memset(&DST, 0x0, sizeof(DST));
DST.viewport = rv3d->viewport;
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, NULL,
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, NULL,
};
drw_engines_enable(scene, view_layer, engine_type);
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
@@ -3328,14 +3395,14 @@ void DRW_notify_id_update(const DRWUpdateContext *update_ctx, ID *id)
* for each relevant engine / mode engine. */
void DRW_draw_view(const bContext *C)
{
- struct Depsgraph *graph = CTX_data_depsgraph(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
RenderEngineType *engine_type = CTX_data_engine_type(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
/* Reset before using it. */
memset(&DST, 0x0, sizeof(DST));
- DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, C);
+ DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, C);
}
/**
@@ -3343,13 +3410,13 @@ void DRW_draw_view(const bContext *C)
* Need to reset DST before calling this function
*/
void DRW_draw_render_loop_ex(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
RenderEngineType *engine_type,
ARegion *ar, View3D *v3d,
const bContext *evil_C)
{
- Scene *scene = DEG_get_evaluated_scene(graph);
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
DST.draw_ctx.evil_C = evil_C;
@@ -3361,7 +3428,7 @@ void DRW_draw_render_loop_ex(
GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash());
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type,
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph,
/* reuse if caller sets */
DST.draw_ctx.evil_C,
@@ -3378,18 +3445,16 @@ void DRW_draw_render_loop_ex(
/* Init engines */
drw_engines_init();
- /* TODO : tag to refresh by the deps graph */
- /* ideally only refresh when objects are added/removed */
- /* or render properties / materials change */
+ /* Cache filling */
{
PROFILE_START(stime);
drw_engines_cache_init();
- DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_ALL);
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_END
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
drw_engines_cache_finish();
PROFILE_END_ACCUM(DST.cache_time, stime);
@@ -3399,6 +3464,7 @@ void DRW_draw_render_loop_ex(
/* Start Drawing */
DRW_state_reset();
+
drw_engines_draw_background();
/* WIP, single image drawn over the camera view (replace) */
@@ -3413,10 +3479,8 @@ void DRW_draw_render_loop_ex(
}
}
- extern void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame);
if (do_bg_image) {
- view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, true);
}
@@ -3439,16 +3503,20 @@ void DRW_draw_render_loop_ex(
if (DST.draw_ctx.evil_C) {
/* needed so manipulator isn't obscured */
glDisable(GL_DEPTH_TEST);
- DRW_draw_manipulator();
- glEnable(GL_DEPTH_TEST);
+ DRW_draw_manipulator_3d();
DRW_draw_region_info();
+
+ /* Draw 2D after region info so we can draw on top of the camera passepartout overlay.
+ * 'DRW_draw_region_info' sets the projection in pixel-space. */
+ DRW_draw_manipulator_2d();
+ glEnable(GL_DEPTH_TEST);
}
DRW_stats_reset();
if (do_bg_image) {
- view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, true);
}
if (G.debug_value > 20) {
@@ -3468,21 +3536,23 @@ void DRW_draw_render_loop_ex(
}
void DRW_draw_render_loop(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
ARegion *ar, View3D *v3d)
{
/* Reset before using it. */
memset(&DST, 0x0, sizeof(DST));
- Scene *scene = DEG_get_evaluated_scene(graph);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
- DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, NULL);
+ DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL);
}
+/* @viewport CAN be NULL, in this case we create one. */
void DRW_draw_render_loop_offscreen(
- struct Depsgraph *graph, RenderEngineType *engine_type,
- ARegion *ar, View3D *v3d, GPUOffScreen *ofs)
+ struct Depsgraph *depsgraph, RenderEngineType *engine_type,
+ ARegion *ar, View3D *v3d, const bool draw_background, GPUOffScreen *ofs,
+ GPUViewport *viewport)
{
RegionView3D *rv3d = ar->regiondata;
@@ -3490,20 +3560,28 @@ void DRW_draw_render_loop_offscreen(
void *backup_viewport = rv3d->viewport;
{
/* backup (_never_ use rv3d->viewport) */
- rv3d->viewport = GPU_viewport_create_from_offscreen(ofs);
+ if (viewport == NULL) {
+ rv3d->viewport = GPU_viewport_create_from_offscreen(ofs);
+ }
+ else {
+ rv3d->viewport = viewport;
+ }
}
/* Reset before using it. */
memset(&DST, 0x0, sizeof(DST));
DST.options.is_image_render = true;
- DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, NULL);
+ DST.options.draw_background = draw_background;
+ DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, NULL);
/* restore */
{
- /* don't free data owned by 'ofs' */
- GPU_viewport_clear_from_offscreen(rv3d->viewport);
- GPU_viewport_free(rv3d->viewport);
- MEM_freeN(rv3d->viewport);
+ if (viewport == NULL) {
+ /* don't free data owned by 'ofs' */
+ GPU_viewport_clear_from_offscreen(rv3d->viewport);
+ GPU_viewport_free(rv3d->viewport);
+ MEM_freeN(rv3d->viewport);
+ }
rv3d->viewport = backup_viewport;
}
@@ -3512,17 +3590,81 @@ void DRW_draw_render_loop_offscreen(
GPU_offscreen_bind(ofs, false);
}
+void DRW_render_to_image(RenderEngine *re, struct Depsgraph *depsgraph)
+{
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ RenderEngineType *engine_type = re->type;
+ DrawEngineType *draw_engine_type = engine_type->draw_engine;
+ RenderData *r = &scene->r;
+
+ /* Reset before using it. */
+ memset(&DST, 0x0, sizeof(DST));
+ DST.options.is_image_render = true;
+
+ DST.draw_ctx = (DRWContextState){
+ NULL, NULL, NULL, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, NULL
+ };
+
+ DST.viewport = GPU_viewport_create();
+ const int size[2] = {(r->size * r->xsch) / 100, (r->size * r->ysch) / 100};
+ GPU_viewport_size_set(DST.viewport, size);
+
+ drw_viewport_var_init();
+
+ ViewportEngineData *data = DRW_viewport_engine_data_ensure(draw_engine_type);
+
+ /* set default viewport */
+ gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+ glViewport(0, 0, size[0], size[1]);
+
+ engine_type->draw_engine->render_to_image(data, re, depsgraph);
+
+ /* TODO grease pencil */
+
+ GPU_viewport_free(DST.viewport);
+ MEM_freeN(DST.viewport);
+
+ DRW_state_reset();
+ /* FIXME GL_DEPTH_TEST is enabled by default but it seems
+ * to trigger some bad behaviour / artifacts if it's turned
+ * on at this point. */
+ glDisable(GL_DEPTH_TEST);
+
+ /* Restore Drawing area. */
+ gpuPopAttrib();
+ glEnable(GL_SCISSOR_TEST);
+ GPU_framebuffer_restore();
+
+#ifdef DEBUG
+ /* Avoid accidental reuse. */
+ memset(&DST, 0xFF, sizeof(DST));
+#endif
+}
+
+void DRW_render_object_iter(
+ void *vedata, RenderEngine *engine, struct Depsgraph *depsgraph,
+ void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
+{
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
+ {
+ callback(vedata, ob, engine, depsgraph);
+ }
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
+}
+
/**
* object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing).
*/
void DRW_draw_select_loop(
- struct Depsgraph *graph,
+ struct Depsgraph *depsgraph,
ARegion *ar, View3D *v3d,
bool UNUSED(use_obedit_skip), bool UNUSED(use_nearest), const rcti *rect)
{
- Scene *scene = DEG_get_evaluated_scene(graph);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
#ifndef USE_GPU_SELECT
UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
#else
@@ -3573,7 +3715,7 @@ void DRW_draw_select_loop(
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, (bContext *)NULL,
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, (bContext *)NULL,
};
drw_viewport_var_init();
@@ -3584,7 +3726,7 @@ void DRW_draw_select_loop(
/* Init engines */
drw_engines_init();
- /* TODO : tag to refresh by the deps graph */
+ /* TODO : tag to refresh by the dependency graph */
/* ideally only refresh when objects are added/removed */
/* or render properties / materials change */
if (cache_is_dirty) {
@@ -3594,7 +3736,10 @@ void DRW_draw_select_loop(
drw_engines_cache_populate(scene->obedit);
}
else {
- DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_DUPLI)
+ DEG_OBJECT_ITER(depsgraph, ob, DRW_iterator_mode_get(),
+ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI)
{
if ((ob->base_flag & BASE_SELECTABLED) != 0) {
DRW_select_load_id(ob->select_color);
@@ -3634,12 +3779,12 @@ void DRW_draw_select_loop(
* object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
*/
void DRW_draw_depth_loop(
- Depsgraph *graph,
+ Depsgraph *depsgraph,
ARegion *ar, View3D *v3d)
{
- Scene *scene = DEG_get_evaluated_scene(graph);
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
- ViewLayer *view_layer = DEG_get_evaluated_view_layer(graph);
+ ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
/* backup (_never_ use rv3d->viewport) */
@@ -3669,7 +3814,7 @@ void DRW_draw_depth_loop(
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
DST.draw_ctx = (DRWContextState){
- ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, (bContext *)NULL,
+ ar, rv3d, v3d, scene, view_layer, OBACT(view_layer), engine_type, depsgraph, (bContext *)NULL,
};
drw_viewport_var_init();
@@ -3680,17 +3825,17 @@ void DRW_draw_depth_loop(
/* Init engines */
drw_engines_init();
- /* TODO : tag to refresh by the deps graph */
+ /* TODO : tag to refresh by the dependency graph */
/* ideally only refresh when objects are added/removed */
/* or render properties / materials change */
if (cache_is_dirty) {
drw_engines_cache_init();
- DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_FLAG_ALL)
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE(depsgraph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
- DEG_OBJECT_ITER_END
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
drw_engines_cache_finish();
}
@@ -3736,7 +3881,7 @@ void DRW_state_dfdy_factors_get(float dfdyfac[2])
*/
bool DRW_state_is_fbo(void)
{
- return (DST.default_framebuffer != NULL);
+ return ((DST.default_framebuffer != NULL) || DST.options.is_image_render);
}
/**
@@ -3772,6 +3917,15 @@ bool DRW_state_is_scene_render(void)
}
/**
+ * Gives you the iterator mode to use for depsgraph.
+ */
+eDepsObjectIteratorMode DRW_iterator_mode_get(void)
+{
+ return DRW_state_is_scene_render() ? DEG_ITER_OBJECT_MODE_RENDER :
+ DEG_ITER_OBJECT_MODE_VIEWPORT;
+}
+
+/**
* Should text draw in this mode?
*/
bool DRW_state_show_text(void)
@@ -3793,6 +3947,17 @@ bool DRW_state_draw_support(void)
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0);
}
+/**
+ * Whether we should render the background
+ */
+bool DRW_state_draw_background(void)
+{
+ if (DRW_state_is_image_render() == false) {
+ return true;
+ }
+ return DST.options.draw_background;
+}
+
/** \} */
@@ -3814,6 +3979,11 @@ const DRWContextState *DRW_context_state_get(void)
/** \name Init/Exit (DRW_engines)
* \{ */
+bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
+{
+ return draw_engine_type->render_to_image;
+}
+
void DRW_engine_register(DrawEngineType *draw_engine_type)
{
BLI_addtail(&DRW_engines, draw_engine_type);
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
index 474d6ac8769..391c29e511f 100644
--- a/source/blender/draw/intern/draw_view.c
+++ b/source/blender/draw/intern/draw_view.c
@@ -715,16 +715,13 @@ void DRW_draw_cursor(void)
/* **************************** 3D Manipulator ******************************** */
-void DRW_draw_manipulator(void)
+void DRW_draw_manipulator_3d(void)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
v3d->zbuf = false;
ARegion *ar = draw_ctx->ar;
-
- /* TODO, only draws 3D manipulators right now, need to see how 2D drawing will work in new viewport */
-
/* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
/* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
* later become _IN_SCENE (and draw _3D separate) */
@@ -732,25 +729,18 @@ void DRW_draw_manipulator(void)
ar->manipulator_map, draw_ctx->evil_C,
WM_MANIPULATORMAP_DRAWSTEP_3D);
- /* We may want to split this into a separate pass.
- * or maintain a stage in the draw manager where all pixel-space drawing happens. */
- {
- float original_proj[4][4];
- gpuGetProjectionMatrix(original_proj);
- wmOrtho2_region_pixelspace(ar);
-
- gpuPushMatrix();
- gpuLoadIdentity();
-
- glDepthMask(GL_FALSE);
+}
- WM_manipulatormap_draw(
- ar->manipulator_map, draw_ctx->evil_C,
- WM_MANIPULATORMAP_DRAWSTEP_2D);
+void DRW_draw_manipulator_2d(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ View3D *v3d = draw_ctx->v3d;
+ v3d->zbuf = false;
+ ARegion *ar = draw_ctx->ar;
- glDepthMask(GL_TRUE);
+ WM_manipulatormap_draw(
+ ar->manipulator_map, draw_ctx->evil_C,
+ WM_MANIPULATORMAP_DRAWSTEP_2D);
- gpuPopMatrix();
- gpuLoadProjectionMatrix(original_proj);
- }
+ glDepthMask(GL_TRUE);
}
diff --git a/source/blender/draw/intern/draw_view.h b/source/blender/draw/intern/draw_view.h
index b400ceeffa2..203420483a7 100644
--- a/source/blender/draw/intern/draw_view.h
+++ b/source/blender/draw/intern/draw_view.h
@@ -30,6 +30,7 @@ void DRW_draw_grid(void);
void DRW_draw_region_info(void);
void DRW_draw_background(void);
void DRW_draw_cursor(void);
-void DRW_draw_manipulator(void);
+void DRW_draw_manipulator_3d(void);
+void DRW_draw_manipulator_2d(void);
-#endif /* __DRAW_VIEW_H__ */ \ No newline at end of file
+#endif /* __DRAW_VIEW_H__ */
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
index 4deb4f86692..3c0c33b1daa 100644
--- a/source/blender/draw/modes/edit_armature_mode.c
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -154,4 +154,5 @@ DrawEngineType draw_engine_edit_armature_type = {
NULL,
&EDIT_ARMATURE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index 1ecf1a60a35..54a1bd79572 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -45,10 +45,12 @@ extern struct GlobalsUboStorage ts; /* draw_common.c */
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[];
extern char datatoc_edit_curve_overlay_frag_glsl[];
+extern char datatoc_edit_curve_overlay_handle_geom_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
+extern char datatoc_gpu_shader_flat_color_frag_glsl[];
/* *********** LISTS *********** */
/* All lists are per viewport specific datas.
@@ -158,7 +160,11 @@ static void EDIT_CURVE_engine_init(void *vedata)
}
if (!e_data.overlay_edge_sh) {
- e_data.overlay_edge_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ e_data.overlay_edge_sh = DRW_shader_create_with_lib(
+ datatoc_edit_curve_overlay_loosevert_vert_glsl,
+ datatoc_edit_curve_overlay_handle_geom_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
}
if (!e_data.overlay_vert_sh) {
@@ -182,27 +188,36 @@ static void EDIT_CURVE_cache_init(void *vedata)
}
{
+ DRWShadingGroup *grp;
+
/* Center-Line (wire) */
psl->wire_pass = DRW_pass_create(
"Curve Wire",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE);
- stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+
+ grp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorWireEdit, 1);
+ stl->g_data->wire_shgrp = grp;
- /* TODO: following handle theme colors,
- * For now use overlay vert shader for handles (we want them colored):
- * TH_NURB_ULINE, TH_NURB_SEL_ULINE, TH_HANDLE_* */
psl->overlay_edge_pass = DRW_pass_create(
"Curve Handle Overlay",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_WIRE);
- /* TODO: following handle theme colors,
- * For now use overlay vert shader for handles (we want them colored) */
- stl->g_data->overlay_edge_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_edge_pass);
+
+ grp = DRW_shgroup_create(e_data.overlay_edge_sh, psl->overlay_edge_pass);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ stl->g_data->overlay_edge_shgrp = grp;
+
psl->overlay_vert_pass = DRW_pass_create(
"Curve Vert Overlay",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT);
- stl->g_data->overlay_vert_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass);
+
+ grp = DRW_shgroup_create(e_data.overlay_vert_sh, psl->overlay_vert_pass);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
+ DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+ stl->g_data->overlay_vert_shgrp = grp;
}
}
@@ -293,7 +308,8 @@ static void EDIT_CURVE_draw_scene(void *vedata)
* Mostly used for freeing shaders */
static void EDIT_CURVE_engine_free(void)
{
- // DRW_SHADER_FREE_SAFE(custom_shader);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_edge_sh);
+ DRW_SHADER_FREE_SAFE(e_data.overlay_vert_sh);
}
/* Create collection settings here.
@@ -331,4 +347,5 @@ DrawEngineType draw_engine_edit_curve_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_CURVE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
index ff4c557326e..e676677ff97 100644
--- a/source/blender/draw/modes/edit_lattice_mode.c
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -294,4 +294,5 @@ DrawEngineType draw_engine_edit_lattice_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_LATTICE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index 1a8c03e3933..29ba658f79d 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -610,4 +610,5 @@ DrawEngineType draw_engine_edit_mesh_type = {
NULL,
&EDIT_MESH_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
index a83f5ae33bc..78ceaf8b6f1 100644
--- a/source/blender/draw/modes/edit_metaball_mode.c
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -248,4 +248,5 @@ DrawEngineType draw_engine_edit_metaball_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_METABALL_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c
index 4e60c4abff5..8f0371925db 100644
--- a/source/blender/draw/modes/edit_surface_mode.c
+++ b/source/blender/draw/modes/edit_surface_mode.c
@@ -266,4 +266,5 @@ DrawEngineType draw_engine_edit_surface_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_SURFACE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index b375bad84b5..60f28d89f4b 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -309,4 +309,5 @@ DrawEngineType draw_engine_edit_text_type = {
NULL, /* draw_background but not needed by mode engines */
&EDIT_TEXT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 91b64818eff..f27f41c3d2a 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -61,6 +61,8 @@
#include "draw_manager_text.h"
#include "draw_common.h"
+#include "DEG_depsgraph_query.h"
+
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
extern struct GPUTexture *globals_ramp; /* draw_common.c */
extern GlobalsUboStorage ts;
@@ -74,11 +76,11 @@ extern char datatoc_object_empty_image_frag_glsl[];
extern char datatoc_object_empty_image_vert_glsl[];
extern char datatoc_object_lightprobe_grid_vert_glsl[];
extern char datatoc_object_particle_prim_vert_glsl[];
-extern char datatoc_object_particle_prim_frag_glsl[];
extern char datatoc_object_particle_dot_vert_glsl[];
extern char datatoc_object_particle_dot_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
+extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
@@ -184,6 +186,7 @@ typedef struct OBJECT_PrivateData {
/* Camera */
DRWShadingGroup *camera;
+ DRWShadingGroup *camera_frame;
DRWShadingGroup *camera_tria;
DRWShadingGroup *camera_focus;
DRWShadingGroup *camera_clip;
@@ -328,12 +331,12 @@ static void OBJECT_engine_init(void *vedata)
if (!e_data.part_prim_sh) {
e_data.part_prim_sh = DRW_shader_create(
- datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl, NULL);
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL);
}
if (!e_data.part_axis_sh) {
e_data.part_axis_sh = DRW_shader_create(
- datatoc_object_particle_prim_vert_glsl, NULL, datatoc_object_particle_prim_frag_glsl,
+ datatoc_object_particle_prim_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl,
"#define USE_AXIS\n");
}
@@ -506,8 +509,14 @@ static void OBJECT_engine_init(void *vedata)
e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS;
}
- float dist = (rv3d->persp == RV3D_CAMOB && v3d->camera)
- ? ((Camera *)v3d->camera)->clipend : v3d->far;
+ float dist;
+ if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
+ dist = ((Camera *)camera_object)->clipend;
+ }
+ else {
+ dist = v3d->far;
+ }
e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */
e_data.grid_settings[1] = grid_res; /* gridResolution */
@@ -749,8 +758,9 @@ static void OBJECT_cache_init(void *vedata)
DRWState state = DRW_STATE_WRITE_COLOR;
struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get();
static float alphaOcclu = 0.35f;
- static bool bTrue = true;
- static bool bFalse = false;
+ /* Reminder : bool uniforms need to be 4 bytes. */
+ static const int bTrue = true;
+ static const int bFalse = false;
psl->outlines_search = DRW_pass_create("Outlines Detect Pass", state);
@@ -920,6 +930,9 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_camera_get();
stl->g_data->camera = shgroup_camera_instance(psl->non_meshes, geom);
+ geom = DRW_cache_camera_frame_get();
+ stl->g_data->camera_frame = shgroup_camera_instance(psl->non_meshes, geom);
+
geom = DRW_cache_camera_tria_get();
stl->g_data->camera_tria = shgroup_camera_instance(psl->non_meshes, geom);
@@ -977,6 +990,7 @@ static void OBJECT_cache_init(void *vedata)
geom = DRW_cache_lamp_get();
stl->g_data->lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+ geom = DRW_cache_lamp_shadows_get();
stl->g_data->lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow);
geom = DRW_cache_lamp_sunrays_get();
@@ -1110,15 +1124,22 @@ static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, ViewLayer *vie
int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);
static float zero = 0.0f;
- float **la_mats = (float **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
- if (*la_mats == NULL) {
- /* we need 2 matrices */
- *la_mats = MEM_mallocN(sizeof(float) * 16 * 2, "Lamp Object Mode Matrices");
- }
+ typedef struct LampEngineData {
+ ObjectEngineData engine_data;
+ float shape_mat[4][4];
+ float spot_blend_mat[4][4];
+ } LampEngineData;
+
+ LampEngineData *lamp_engine_data =
+ (LampEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_object_type,
+ sizeof(LampEngineData),
+ NULL,
+ NULL);
- float (*shapemat)[4], (*spotblendmat)[4];
- shapemat = (float (*)[4])(*la_mats);
- spotblendmat = (float (*)[4])(*la_mats + 16);
+ float (*shapemat)[4] = lamp_engine_data->shape_mat;
+ float (*spotblendmat)[4] = lamp_engine_data->spot_blend_mat;
/* Don't draw the center if it's selected or active */
if (theme_id == TH_GROUP)
@@ -1213,9 +1234,11 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
+ RegionView3D *rv3d = draw_ctx->rv3d;
Camera *cam = ob->data;
const bool is_active = (ob == v3d->camera);
+ const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
float *color;
DRW_object_wire_theme_get(ob, view_layer, &color);
@@ -1228,7 +1251,7 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale,
asp, shift, &drawsize, vec);
- // /* Frame coords */
+ /* Frame coords */
copy_v2_v2(cam->drwcorners[0], vec[0]);
copy_v2_v2(cam->drwcorners[1], vec[1]);
copy_v2_v2(cam->drwcorners[2], vec[2]);
@@ -1243,13 +1266,23 @@ static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, ViewLayer *v
cam->drwtria[1][0] = shift[0];
cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
- DRW_shgroup_call_dynamic_add(stl->g_data->camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
-
- /* Active cam */
- if (is_active) {
+ if (look_through) {
+ /* Only draw the frame. */
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_frame, color, cam->drwcorners,
+ &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
+ else {
DRW_shgroup_call_dynamic_add(
- stl->g_data->camera_tria, color,
- cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ stl->g_data->camera, color, cam->drwcorners,
+ &cam->drwdepth, cam->drwtria, ob->obmat);
+
+ /* Active cam */
+ if (is_active) {
+ DRW_shgroup_call_dynamic_add(
+ stl->g_data->camera_tria, color,
+ cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
}
/* draw the rest in normalize object space */
@@ -1455,13 +1488,13 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
DRW_object_wire_theme_get(ob, view_layer, &color);
- OBJECT_LightProbeEngineData *prb_data;
- OBJECT_LightProbeEngineData **prb_data_pt = (OBJECT_LightProbeEngineData **)DRW_object_engine_data_ensure(ob, &draw_engine_object_type, NULL);
- if (*prb_data_pt == NULL) {
- *prb_data_pt = MEM_mallocN(sizeof(OBJECT_LightProbeEngineData), "Probe Clip distances Matrices");
- }
-
- prb_data = *prb_data_pt;
+ OBJECT_LightProbeEngineData *prb_data =
+ (OBJECT_LightProbeEngineData *)DRW_object_engine_data_ensure(
+ ob,
+ &draw_engine_object_type,
+ sizeof(OBJECT_LightProbeEngineData),
+ NULL,
+ NULL);
if ((DRW_state_is_select() || do_outlines) && ((prb->flag & LIGHTPROBE_FLAG_SHOW_DATA) != 0)) {
@@ -1499,9 +1532,6 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
sub_v3_v3(prb_data->increment_z, prb_data->corner);
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.lightprobe_grid_sh, psl->lightprobes, DRW_cache_sphere_get());
- /* Dummy call just to save select ID */
- DRW_shgroup_call_dynamic_add_empty(grp);
- /* Then overide the instance count */
DRW_shgroup_set_instance_count(grp, prb->grid_resolution_x * prb->grid_resolution_y * prb->grid_resolution_z);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_vec3(grp, "corner", prb_data->corner, 1);
@@ -1648,7 +1678,7 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob)
{
- if (ob->parent && BKE_object_is_visible(ob->parent)) {
+ if (ob->parent && DRW_check_object_visible_within_active_context(ob->parent)) {
DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]);
DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]);
}
@@ -1763,7 +1793,12 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
View3D *v3d = draw_ctx->v3d;
int theme_id = TH_UNDEFINED;
- if (!BKE_object_is_visible(ob)) {
+ /* Handle particles first in case the emitter itself shouldn't be rendered. */
+ if (ob->type == OB_MESH) {
+ OBJECT_cache_populate_particles(ob, psl);
+ }
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
return;
}
@@ -1804,8 +1839,6 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
}
}
-
- OBJECT_cache_populate_particles(ob, psl);
break;
}
case OB_SURF:
@@ -2011,4 +2044,5 @@ DrawEngineType draw_engine_object_type = {
NULL,
&OBJECT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index b49da0cba2f..2a5eabd08fa 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -414,4 +414,5 @@ DrawEngineType draw_engine_paint_texture_type = {
NULL, /* draw_background but not needed by mode engines */
&PAINT_TEXTURE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index e430fca5742..835fefdee26 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -213,4 +213,5 @@ DrawEngineType draw_engine_paint_vertex_type = {
NULL,
&PAINT_VERTEX_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
index e139b4af97f..3cc2ad63ed4 100644
--- a/source/blender/draw/modes/paint_weight_mode.c
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -251,4 +251,5 @@ DrawEngineType draw_engine_paint_weight_type = {
NULL,
&PAINT_WEIGHT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
index 6a3e53a72c2..0d0758971d5 100644
--- a/source/blender/draw/modes/particle_mode.c
+++ b/source/blender/draw/modes/particle_mode.c
@@ -261,4 +261,5 @@ DrawEngineType draw_engine_particle_type = {
NULL, /* draw_background but not needed by mode engines */
&PARTICLE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
index 1c2acd56085..560773f2d05 100644
--- a/source/blender/draw/modes/pose_mode.c
+++ b/source/blender/draw/modes/pose_mode.c
@@ -195,4 +195,5 @@ DrawEngineType draw_engine_pose_type = {
NULL,
&POSE_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index d9f1f5ebe91..d8c5bae522b 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -302,4 +302,5 @@ DrawEngineType draw_engine_sculpt_type = {
NULL, /* draw_background but not needed by mode engines */
&SCULPT_draw_scene,
NULL,
+ NULL,
};
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
index dc36d252926..0c14c1e7db0 100644
--- a/source/blender/draw/modes/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -37,6 +37,20 @@ layout(std140) uniform globalsBlock {
vec4 colorBackground;
+ vec4 colorHandleFree;
+ vec4 colorHandleAuto;
+ vec4 colorHandleVect;
+ vec4 colorHandleAlign;
+ vec4 colorHandleAutoclamp;
+ vec4 colorHandleSelFree;
+ vec4 colorHandleSelAuto;
+ vec4 colorHandleSelVect;
+ vec4 colorHandleSelAlign;
+ vec4 colorHandleSelAutoclamp;
+ vec4 colorNurbUline;
+ vec4 colorNurbSelUline;
+ vec4 colorActiveSpline;
+
vec4 colorGrid;
vec4 colorGridEmphasise;
vec4 colorGridAxisX;
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl
new file mode 100644
index 00000000000..419a25f91b4
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_geom.glsl
@@ -0,0 +1,79 @@
+
+#define ACTIVE_NURB 1 << 7 /* Keep the same value of `ACTIVE_NURB` in `draw_cache_imp_curve.c` */
+
+layout(lines) in;
+layout(line_strip, max_vertices = 6) out;
+
+uniform vec2 viewportSize;
+
+flat in int vertFlag[];
+
+flat out vec4 finalColor;
+
+void main()
+{
+ /* TODO: vertex size */
+
+ vec4 v1 = gl_in[0].gl_Position;
+ vec4 v2 = gl_in[1].gl_Position;
+
+ int is_active_nurb = vertFlag[1] & ACTIVE_NURB;
+ int color_id = vertFlag[1] ^ is_active_nurb;
+
+ if (is_active_nurb != 0) {
+ /* draw the outline. */
+ vec2 v1_2 = v2.xy - v1.xy;
+ vec2 offset;
+
+ if (abs(v1_2.x * viewportSize.x) < abs(v1_2.y * viewportSize.y)) {
+ offset = vec2(2.0 / viewportSize.x, 0.0);
+ }
+ else {
+ offset = vec2(0.0, 2.0 / viewportSize.y);
+ }
+
+ finalColor = colorActiveSpline;
+
+ gl_Position = v1;
+ gl_Position.xy += offset * v1.w;
+ EmitVertex();
+
+ gl_Position = v2;
+ gl_Position.xy += offset * v2.w;
+ EmitVertex();
+
+ EndPrimitive();
+
+ gl_Position = v1;
+ gl_Position.xy -= offset * v1.w;
+ EmitVertex();
+
+ gl_Position = v2;
+ gl_Position.xy -= offset * v2.w;
+ EmitVertex();
+
+ EndPrimitive();
+ }
+
+ if (color_id == 0) finalColor = colorHandleFree;
+ else if (color_id == 1) finalColor = colorHandleAuto;
+ else if (color_id == 2) finalColor = colorHandleVect;
+ else if (color_id == 3) finalColor = colorHandleAlign;
+ else if (color_id == 4) finalColor = colorHandleAutoclamp;
+ else if (color_id == 5) finalColor = colorHandleSelFree;
+ else if (color_id == 6) finalColor = colorHandleSelAuto;
+ else if (color_id == 7) finalColor = colorHandleSelVect;
+ else if (color_id == 8) finalColor = colorHandleSelAlign;
+ else if (color_id == 9) finalColor = colorHandleSelAutoclamp;
+ else if (color_id == 10) finalColor = colorNurbUline;
+ else if (color_id == 11) finalColor = colorNurbSelUline;
+ else finalColor = colorVertexSelect;
+
+ gl_Position = v1;
+ EmitVertex();
+
+ gl_Position = v2;
+ EmitVertex();
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
index 049333c8e4f..23b794d9b8b 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_frag.glsl
@@ -10,7 +10,7 @@ flat in int faceActive;
out vec4 FragColor;
-const mat4 stipple_matrix = mat4(
+const vec4 stipple_matrix[4] = vec4[4](
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
index ed7421c1b1d..cf1051b70b3 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_frag.glsl
@@ -5,12 +5,16 @@
/* This shader follows the principles of
* http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+/* This is not perfect. Only a subset of intel gpus are affected.
+ * This fix have some performance impact.
+ * TODO Refine the range to only affect GPUs. */
+
uniform float faceAlphaMod;
flat in vec3 edgesCrease;
flat in vec3 edgesBweight;
-flat in ivec3 flag;
flat in vec4 faceColor;
+flat in ivec3 flag;
flat in int clipCase;
#ifdef VERTEX_SELECTION
in vec3 vertexColor;
@@ -28,16 +32,16 @@ in float facing;
* in the first 2 components of the first vec4.
* This needs noperspective interpolation.
* The rest is filled with vertex screen positions.
- * eData1.zw actually contain v2
- * eData2.xy actually contain v1
- * eData2.zw actually contain v0
+ * eData2[0] actually contain v2
+ * eData2[1] actually contain v1
+ * eData2[2] actually contain v0
*
* - Hard case : two 2d edge corner are described by each
* vec4 as origin and direction. This is constant over
* the triangle and use to detect the correct case. */
-noperspective in vec4 eData1;
-flat in vec4 eData2;
+noperspective in vec2 eData1;
+flat in vec2 eData2[3];
out vec4 FragColor;
@@ -72,7 +76,7 @@ const ivec3 clipPointIdx[6] = ivec3[6](
ivec3(2, 1, 0)
);
-const mat4 stipple_matrix = mat4(
+const vec4 stipple_matrix[4] = vec4[4](
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
@@ -107,34 +111,34 @@ void main()
/* Step 1 : Computing Distances */
if (clipCase == 0) {
- e.xy = eData1.xy;
+ e.xy = eData1;
/* computing missing distance */
- vec2 dir = normalize(eData2.zw - eData2.xy);
- e.z = distToEdge(eData2.zw, dir);
+ vec2 dir = normalize(eData2[2] - eData2[1]);
+ e.z = distToEdge(eData2[2], dir);
- p.x = distance(eData2.zw, gl_FragCoord.xy);
- p.y = distance(eData2.xy, gl_FragCoord.xy);
- p.z = distance(eData1.zw, gl_FragCoord.xy);
+ p.x = distance(eData2[2], gl_FragCoord.xy);
+ p.y = distance(eData2[1], gl_FragCoord.xy);
+ p.z = distance(eData2[0], gl_FragCoord.xy);
}
else {
ivec3 eidxs = clipEdgeIdx[clipCase - 1];
ivec3 pidxs = clipPointIdx[clipCase - 1];
- e[eidxs.x] = distToEdge(eData1.xy, eData1.zw);
- e[eidxs.y] = distToEdge(eData2.xy, eData2.zw);
+ e[eidxs.x] = distToEdge(eData1, eData2[0]);
+ e[eidxs.y] = distToEdge(eData2[1], eData2[2]);
/* Three edges visible cases */
if (clipCase == 1 || clipCase == 2 || clipCase == 4) {
- e[eidxs.z] = distToEdge(eData1.xy, normalize(eData2.xy - eData1.xy));
- p[pidxs.y] = distance(eData2.xy, gl_FragCoord.xy);
+ e[eidxs.z] = distToEdge(eData1, normalize(eData2[1] - eData1));
+ p[pidxs.y] = distance(eData2[1], gl_FragCoord.xy);
}
else {
e[eidxs.z] = 1e10; /* off screen */
p[pidxs.y] = 1e10; /* off screen */
}
- p[pidxs.x] = distance(eData1.xy, gl_FragCoord.xy);
+ p[pidxs.x] = distance(eData1, gl_FragCoord.xy);
p[pidxs.z] = 1e10; /* off screen */
}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
index 7d71e1540d5..77bc8a25695 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_edge.glsl
@@ -22,8 +22,8 @@ in float vFacing[];
* and does not need interpolation */
flat out vec3 edgesCrease;
flat out vec3 edgesBweight;
-flat out ivec3 flag;
flat out vec4 faceColor;
+flat out ivec3 flag;
flat out int clipCase;
#ifdef VERTEX_SELECTION
out vec3 vertexColor;
@@ -33,8 +33,8 @@ out float facing;
#endif
/* See fragment shader */
-noperspective out vec4 eData1;
-flat out vec4 eData2;
+noperspective out vec2 eData1;
+flat out vec2 eData2[3];
#define VERTEX_ACTIVE (1 << 0)
#define VERTEX_SELECTED (1 << 1)
@@ -128,9 +128,10 @@ void main()
}
/* Edge / Vert data */
- eData1 = vec4(1e10);
- eData2.zw = pos[0];
- eData2.xy = pos[1];
+ eData1 = vec2(1e10);
+ eData2[0] = vec2(1e10);
+ eData2[2] = pos[0];
+ eData2[1] = pos[1];
flag[0] = (vData[0].x << 8);
flag[1] = (vData[1].x << 8);
flag[2] = 0;
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
index f83402e3869..d9c902697b6 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_geom_tri.glsl
@@ -7,6 +7,10 @@
layout(triangles) in;
+/* This is not perfect. Only a subset of intel gpus are affected.
+ * This fix have some performance impact.
+ * TODO Refine the range to only affect GPUs. */
+
#ifdef EDGE_FIX
/* To fix the edge artifacts, we render
* an outline strip around the screenspace
@@ -37,8 +41,8 @@ in float vFacing[];
* and does not need interpolation */
flat out vec3 edgesCrease;
flat out vec3 edgesBweight;
-flat out ivec3 flag;
flat out vec4 faceColor;
+flat out ivec3 flag;
flat out int clipCase;
#ifdef VERTEX_SELECTION
out vec3 vertexColor;
@@ -48,9 +52,8 @@ out float facing;
#endif
/* See fragment shader */
-noperspective out vec4 eData1;
-flat out vec4 eData2;
-
+noperspective out vec2 eData1;
+flat out vec2 eData2[3];
#define VERTEX_ACTIVE (1 << 0)
#define VERTEX_SELECTED (1 << 1)
@@ -103,7 +106,7 @@ vec4 getClipData(vec2 pos[3], ivec2 vidx)
return vec4(A, Adir);
}
-void doVertex(int v, vec4 pos)
+void doVertex(int v)
{
#ifdef VERTEX_SELECTION
vertexColor = getVertexColor(v);
@@ -113,7 +116,16 @@ void doVertex(int v, vec4 pos)
facing = vFacing[v];
#endif
- gl_Position = pos;
+ gl_Position = pPos[v];
+
+ EmitVertex();
+}
+
+void doLoopStrip(int v, vec3 offset)
+{
+ doVertex(v);
+
+ gl_Position.xyz += offset;
EmitVertex();
}
@@ -164,18 +176,19 @@ void main()
if (clipCase == 0) {
/* Packing screen positions and 2 distances */
- eData1 = vec4(0.0, 0.0, pos[2]);
- eData2 = vec4(pos[1], pos[0]);
+ eData2[0] = pos[2];
+ eData2[1] = pos[1];
+ eData2[2] = pos[0];
/* Only pass the first 2 distances */
for (int v = 0; v < 2; ++v) {
eData1[v] = dist(pos, pos[v], v);
- doVertex(v, pPos[v]);
+ doVertex(v);
eData1[v] = 0.0;
}
/* and the last vertex */
- doVertex(2, pPos[2]);
+ doVertex(2);
#ifdef EDGE_FIX
vec2 fixvec[6];
@@ -233,7 +246,8 @@ void main()
faceColor.a = 0.0;
/* we don't want other edges : make them far */
- eData1 = vec4(1e10);
+ eData1 = vec2(1e10);
+ eData2[0] = vec2(1e10);
/* Start with the same last vertex to create a
* degenerate triangle in order to "create"
@@ -244,49 +258,49 @@ void main()
int v = i % 3;
/* Position of the "hidden" third vertex */
- eData1.zw = pos[vbe];
-
- doVertex(v, pPos[v]);
- doVertex(v, pPos[v] + vec4(fixvec[v], Z_OFFSET, 0.0));
+ eData2[0] = pos[vbe];
+ doLoopStrip(v, vec3(fixvec[v], Z_OFFSET));
/* Now one triangle only shade one edge
* so we use the edge distance calculated
* in the fragment shader, the third edge;
* we do this because we need flat interp to
* draw a continuous triangle strip */
- eData2.xy = pos[vaf];
- eData2.zw = pos[v];
+ eData2[1] = pos[vaf];
+ eData2[2] = pos[v];
flag[0] = (vData[v].x << 8);
flag[1] = (vData[vaf].x << 8);
flag[2] = eflag[vbe];
edgesCrease[2] = ecrease[vbe];
edgesBweight[2] = ebweight[vbe];
- doVertex(vaf, pPos[vaf]);
- doVertex(vaf, pPos[vaf] + vec4(fixvecaf[v], Z_OFFSET, 0.0));
+ doLoopStrip(vaf, vec3(fixvecaf[v], Z_OFFSET));
/* corner vertices should not draw edges but draw point only */
flag[2] = (vData[vbe].x << 8);
#ifdef VERTEX_SELECTION
- doVertex(vaf, pPos[vaf]);
- doVertex(vaf, pPos[vaf] + vec4(cornervec[vaf], Z_OFFSET, 0.0));
+ doLoopStrip(vaf, vec3(cornervec[vaf], Z_OFFSET));
#endif
}
/* finish the loop strip */
- doVertex(2, pPos[2]);
- doVertex(2, pPos[2] + vec4(fixvec[2], Z_OFFSET, 0.0));
+ doLoopStrip(2, vec3(fixvec[2], Z_OFFSET));
#endif
}
/* Harder case : compute visible edges vectors */
else {
ivec4 vindices = clipPointsIdx[clipCase - 1];
- eData1 = getClipData(pos, vindices.xz);
- eData2 = getClipData(pos, vindices.yw);
+ vec4 tmp;
+ tmp = getClipData(pos, vindices.xz);
+ eData1 = tmp.xy;
+ eData2[0] = tmp.zw;
+ tmp = getClipData(pos, vindices.yw);
+ eData2[1] = tmp.xy;
+ eData2[2] = tmp.zw;
for (int v = 0; v < 3; ++v)
- doVertex(v, pPos[v]);
+ doVertex(v);
}
EndPrimitive();
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl
index 0a396a5325f..53e5b09cb70 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_loosevert_vert.glsl
@@ -15,16 +15,16 @@ in ivec4 data;
* and does not need interpolation */
flat out vec3 edgesCrease;
flat out vec3 edgesBweight;
-flat out ivec3 flag;
flat out vec4 faceColor;
+flat out ivec3 flag;
flat out int clipCase;
#ifdef VERTEX_SELECTION
out vec3 vertexColor;
#endif
/* See fragment shader */
-noperspective out vec4 eData1;
-flat out vec4 eData2;
+noperspective out vec2 eData1;
+flat out vec2 eData2[3];
/* project to screen space */
vec2 proj(vec4 pos)
@@ -48,11 +48,13 @@ void main()
#endif
/* only vertex position 0 is used */
- eData1 = eData2 = vec4(1e10);
- eData2.zw = proj(pPos);
+ eData1 = vec2(1e10);
+ eData2[0] = vec2(1e10);
+ eData2[1] = vec2(1e10);
+ eData2[2] = proj(pPos);
- flag = ivec3(0);
flag[0] = (data.x << 8);
+ flag[1] = flag[2] = 0;
gl_PointSize = sizeEdgeFix;
gl_Position = pPos;
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl b/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
deleted file mode 100644
index aa455a85cf0..00000000000
--- a/source/blender/draw/modes/shaders/object_particle_prim_frag.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-flat in vec4 finalColor;
-
-out vec4 fragColor;
-
-void main()
-{
- fragColor = finalColor;
-}