From 2f6219c48df4e39addca3b462d5a753c71a1374e Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 23 Apr 2021 10:02:53 +0200 Subject: Fix T78845: Eevee wrong material selection. In cases where the same node tree is used in different materials with small changes, the wrong material could be selected. Cause: Hair shaders GPU resources weren't updated and used the previous bound data. Reviewed By: fclem Differential Revision: https://developer.blender.org/D11036 --- source/blender/draw/engines/eevee/eevee_materials.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index f05aa562e6b..131f9a954cf 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -765,12 +765,15 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata, if (matcache.depth_grp) { *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp); + DRW_shgroup_add_material_resources(*matcache.depth_grp_p, matcache.shading_gpumat); } if (matcache.shading_grp) { *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp); + DRW_shgroup_add_material_resources(*matcache.shading_grp_p, matcache.shading_gpumat); } if (matcache.shadow_grp) { *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp); + DRW_shgroup_add_material_resources(*matcache.shadow_grp_p, matcache.shading_gpumat); *cast_shadow = true; } -- cgit v1.2.3 From c4bebc03e0e7af0b6fe31c9751b81635645bd547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 28 Apr 2021 15:36:33 +0200 Subject: Fix T87464 EEVEE: Crash with deformation Motion Blur This was caused by the new depsgraph persistence. The GPUbatches we got from the cache being the same for each frame means that we need to be more careful about cleanning the additional VBOs references. Moving the `EEVEE_motion_blur_swap_data` function call at the end of the loop makes sure the references are cleaned. --- source/blender/draw/engines/eevee/eevee_engine.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index ae726d7af9a..509c002e25a 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -494,12 +494,7 @@ static void eevee_render_to_image(void *vedata, /* Previous motion step. */ if (do_motion_blur_fx) { - if (i > 0) { - /* The previous step of this iteration N is exactly the next step of iteration N - 1. - * So we just swap the resources to avoid too much re-evaluation. */ - EEVEE_motion_blur_swap_data(vedata); - } - else { + if (i == 0) { EEVEE_motion_blur_step_set(ved, MB_PREV); DRW_render_set_time(engine, depsgraph, floorf(time_prev), fractf(time_prev)); EEVEE_render_modules_init(vedata, engine, depsgraph); @@ -570,6 +565,14 @@ static void eevee_render_to_image(void *vedata, DRW_cache_restart(); } } + + if (do_motion_blur_fx) { + /* The previous step of next iteration N is exactly the next step of this iteration N - 1. + * So we just swap the resources to avoid too much re-evaluation. + * Note that this also clears the VBO references from the GPUBatches of deformed + * geometries. */ + EEVEE_motion_blur_swap_data(vedata); + } } EEVEE_volumes_free_smoke_textures(); -- cgit v1.2.3 From 97923d9b9892b422cfd4c5a795258a34e44c09e8 Mon Sep 17 00:00:00 2001 From: Falk David Date: Thu, 29 Apr 2021 16:49:57 +0200 Subject: GPencil: glow fx, add threshold value color mode This patch adds a threshold value to the glow effect in color mode. Currently, the threshold is hardcoded to 5%. You can select a color and specify a higher threshold to include similar colors in the effect. Note: depends on D10670 Reviewed By: #grease_pencil, pepeland Differential Revision: https://developer.blender.org/D10672 --- source/blender/draw/engines/gpencil/gpencil_shader_fx.c | 10 +++++++--- .../blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 0b66141e51a..ab90831f4ac 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -424,22 +424,26 @@ static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfx GPUShader *sh = GPENCIL_shader_fx_glow_get(); - float ref_col[3]; + float ref_col[4]; if (fx->mode == eShaderFxGlowMode_Luminance) { + /* Only pass in the first value for luminace. */ ref_col[0] = fx->threshold; ref_col[1] = -1.0f; ref_col[2] = -1.0f; + ref_col[3] = -1.0f; } else { + /* First three values are the RGB for the selected color, last value the threshold. */ copy_v3_v3(ref_col, fx->select_color); + ref_col[3] = fx->threshold; } DRWState state = DRW_STATE_WRITE_COLOR; grp = gpencil_vfx_pass_create("Fx Glow H", state, iter, sh); DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){fx->blur[0] * c, fx->blur[0] * s}); DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0]))); - DRW_shgroup_uniform_vec3_copy(grp, "threshold", ref_col); + DRW_shgroup_uniform_vec4_copy(grp, "threshold", ref_col); DRW_shgroup_uniform_vec4_copy(grp, "glowColor", fx->glow_color); DRW_shgroup_uniform_bool_copy(grp, "glowUnder", use_glow_under); DRW_shgroup_uniform_bool_copy(grp, "firstPass", true); @@ -473,7 +477,7 @@ static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfx grp = gpencil_vfx_pass_create("Fx Glow V", state, iter, sh); DRW_shgroup_uniform_vec2_copy(grp, "offset", (float[2]){-fx->blur[1] * s, fx->blur[1] * c}); DRW_shgroup_uniform_int_copy(grp, "sampCount", max_ii(1, min_ii(fx->samples, fx->blur[0]))); - DRW_shgroup_uniform_vec3_copy(grp, "threshold", (float[3]){-1.0f, -1.0f, -1.0f}); + DRW_shgroup_uniform_vec4_copy(grp, "threshold", (float[4]){-1.0f, -1.0f, -1.0f, -1.0}); DRW_shgroup_uniform_vec4_copy(grp, "glowColor", (float[4]){1.0f, 1.0f, 1.0f, fx->glow_color[3]}); DRW_shgroup_uniform_bool_copy(grp, "firstPass", false); DRW_shgroup_uniform_int_copy(grp, "blendMode", fx->blend_mode); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl index bb905f8694b..269ed49c4d0 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl @@ -145,7 +145,7 @@ void main() uniform vec4 glowColor; uniform vec2 offset; uniform int sampCount; -uniform vec3 threshold; +uniform vec4 threshold; uniform bool firstPass; uniform bool glowUnder; uniform int blendMode; @@ -168,7 +168,7 @@ void main() vec3 rev = texture(revealBuf, uv).rgb; if (threshold.x > -1.0) { if (threshold.y > -1.0) { - if (any(greaterThan(abs(col - threshold), vec3(0.05)))) { + if (any(greaterThan(abs(col - vec3(threshold)), vec3(threshold.w)))) { weight = 0.0; } } -- cgit v1.2.3 From d6b26b3fa0c46c6a9d9c9e5d3816a713dfa261a7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 30 Apr 2021 14:27:44 +1000 Subject: Fix potential buffer overrun in drw_shader_dependencies_get Logical error let this function to write one past the buffer bounds. --- source/blender/draw/intern/draw_manager_shader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index c93cbf16a30..2aad1f10154 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -606,10 +606,10 @@ static uint32_t drw_shader_dependencies_get(const DRWShaderLibrary *lib, const c haystack += 16; int dep = drw_shader_library_search(lib, haystack); if (dep == -1) { - char dbg_name[32]; + char dbg_name[33]; int i = 0; - while ((haystack[0] != ')') && (i < 31)) { - dbg_name[i] = haystack[0]; + while ((*haystack != ')') && (i < (sizeof(dbg_name) - 2))) { + dbg_name[i] = *haystack; haystack++; i++; } -- cgit v1.2.3 From 888a697e247f60a7eac33385c91c490c5b05bee0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 4 May 2021 00:42:34 +1000 Subject: Cleanup: spelling --- source/blender/draw/engines/gpencil/gpencil_shader_fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index ab90831f4ac..21d55357a2a 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -427,7 +427,7 @@ static void gpencil_vfx_glow(GlowShaderFxData *fx, Object *UNUSED(ob), gpIterVfx float ref_col[4]; if (fx->mode == eShaderFxGlowMode_Luminance) { - /* Only pass in the first value for luminace. */ + /* Only pass in the first value for luminance. */ ref_col[0] = fx->threshold; ref_col[1] = -1.0f; ref_col[2] = -1.0f; -- cgit v1.2.3 From 96abe5ebbc55323fc28ee4f6a852c912298c72d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Tue, 4 May 2021 22:30:10 +0200 Subject: DRW: Fix issue with batch reusing freed VBO indices. Some discard of vertbuf were not correctly followed by discards of the GPUBatches that were using them. This lead to a use-after-free situation where GPUBatches would reuse old VBO information. This did not crash immediatly because the VBO indices were cached by our VAO caching system. It kept working on some implementation because VBO reference in the VAO (probably) preventing the VBO from being freed by reference counting. This fixes T85977 NVidia: Random crashes in 'DrvPresentBuffers' --- source/blender/draw/intern/draw_cache_impl_mesh.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index f11fd0f3906..af54b57b162 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -557,12 +557,18 @@ static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache) static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) { FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { - GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.tan); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco); } + /* Discard batches using vbo.uv. */ + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_area); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_faces_stretch_angle); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges); + GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts); + mesh_batch_cache_discard_surface_batches(cache); mesh_cd_layers_type_clear(&cache->cd_used); } @@ -659,8 +665,17 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode) GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor); } GPU_BATCH_DISCARD_SAFE(cache->batch.surface); + /* Discard batches using vbo.pos_nor. */ GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops); GPU_BATCH_DISCARD_SAFE(cache->batch.wire_edges); + GPU_BATCH_DISCARD_SAFE(cache->batch.all_verts); + GPU_BATCH_DISCARD_SAFE(cache->batch.all_edges); + GPU_BATCH_DISCARD_SAFE(cache->batch.loose_edges); + GPU_BATCH_DISCARD_SAFE(cache->batch.edge_detection); + GPU_BATCH_DISCARD_SAFE(cache->batch.surface_weights); + GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis); + /* Discard batches using vbo.lnor. */ + GPU_BATCH_DISCARD_SAFE(cache->batch.edit_lnor); mesh_batch_cache_discard_surface_batches(cache); cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS); break; -- cgit v1.2.3 From a7b7f67fc4ad0a5bf4ffc2a64467b55479f4fd95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 5 May 2021 16:10:43 +0200 Subject: Fix T86037 EEVEE: SSR option changes render passes result This was caused by the SSR option resetting the accumulation. But the render passes were only cleared in the init phase. This means that when SSR was resetting the taa_render_sample the actual renderpasses would still contains 1 sample. This means the renderpasses were always divided by the wrong number of samples. The fix is to clear just before accumulation if the sample is 1. The fact that it works for motion blur is kind of a blessing. This is because we check stl->effects->ssr_was_valid_double_buffer before resetting the sampling. So this only happens on the first motion step and does not affect the rest of the rendering. Reviewed by: jbakker Differential Revision: https://developer.blender.org/D11033 --- .../blender/draw/engines/eevee/eevee_materials.c | 64 +++++++++++----------- source/blender/draw/engines/eevee/eevee_mist.c | 17 +++--- .../blender/draw/engines/eevee/eevee_occlusion.c | 15 ++--- .../draw/engines/eevee/eevee_screen_raytrace.c | 18 +++--- source/blender/draw/engines/eevee/eevee_shadows.c | 18 +++--- source/blender/draw/engines/eevee/eevee_volumes.c | 23 ++++---- 6 files changed, 76 insertions(+), 79 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 131f9a954cf..45c6900fc0f 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -961,22 +961,9 @@ void EEVEE_material_renderpasses_init(EEVEE_Data *vedata) } } -static void material_renderpass_init(EEVEE_FramebufferList *fbl, - GPUTexture **output_tx, - const eGPUTextureFormat format, - const bool do_clear) +static void material_renderpass_init(GPUTexture **output_tx, const eGPUTextureFormat format) { DRW_texture_ensure_fullscreen_2d(output_tx, format, 0); - /* Clear texture. */ - if (do_clear) { - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* TODO(fclem): replace by GPU_texture_clear once it is fast. */ - GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0); - GPU_framebuffer_bind(fbl->material_accum_fb); - GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); - GPU_framebuffer_bind(fbl->main_fb); - GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx); - } } void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) @@ -991,33 +978,32 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, /* Should be enough precision for many samples. */ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; - const bool do_clear = (effects->taa_current_sample == 1); /* Create FrameBuffer. */ GPU_framebuffer_ensure_config(&fbl->material_accum_fb, {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE}); if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { - material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear); + material_renderpass_init(&txl->env_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { - material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear); + material_renderpass_init(&txl->emit_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { - material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear); + material_renderpass_init(&txl->diff_color_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear); + material_renderpass_init(&txl->diff_light_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { - material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear); + material_renderpass_init(&txl->spec_color_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { - material_renderpass_init(fbl, &txl->aov_surface_accum[aov_index], texture_format, do_clear); + material_renderpass_init(&txl->aov_surface_accum[aov_index], texture_format); } } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear); + material_renderpass_init(&txl->spec_light_accum, texture_format); if (effects->enabled_effects & EFFECT_SSR) { EEVEE_reflection_output_init(sldata, vedata, tot_samples); @@ -1025,7 +1011,8 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, } } -static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, +static void material_renderpass_accumulate(EEVEE_EffectsInfo *effects, + EEVEE_FramebufferList *fbl, DRWPass *renderpass, DRWPass *renderpass2, EEVEE_PrivateData *pd, @@ -1035,6 +1022,11 @@ static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0); GPU_framebuffer_bind(fbl->material_accum_fb); + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); + } + pd->renderpass_ubo = renderpass_option_ubo; DRW_draw_pass(renderpass); if (renderpass2) { @@ -1056,15 +1048,21 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRWPass *material_accum_ps = psl->material_accum_ps; DRWPass *background_accum_ps = psl->background_accum_ps; if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { - material_renderpass_accumulate( - fbl, background_accum_ps, NULL, pd, txl->env_accum, sldata->renderpass_ubo.environment); + material_renderpass_accumulate(effects, + fbl, + background_accum_ps, + NULL, + pd, + txl->env_accum, + sldata->renderpass_ubo.environment); } if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { material_renderpass_accumulate( - fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit); + effects, fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1072,7 +1070,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v sldata->renderpass_ubo.diff_color); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1090,7 +1089,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v sldata->common_data.ssr_toggle = false; GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data); } - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1102,7 +1102,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v } } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1115,7 +1116,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v } if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, background_accum_ps, pd, diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 2b448695528..d4490d6fd4c 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -40,12 +40,9 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PassList *psl = vedata->psl; - EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; Scene *scene = draw_ctx->scene; - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ /* Should be enough precision for many samples. */ DRW_texture_ensure_fullscreen_2d(&txl->mist_accum, GPU_R32F, 0); @@ -53,12 +50,6 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->mist_accum_fb); - GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); - } - /* Mist settings. */ if (scene && scene->world) { g_data->mist_start = scene->world->miststa; @@ -103,9 +94,17 @@ void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->mist_accum_fb != NULL) { GPU_framebuffer_bind(fbl->mist_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + } + DRW_draw_pass(psl->mist_accum_ps); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 19f34fa6108..4c2024a6f65 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -120,7 +120,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Should be enough precision for many samples. */ DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0); @@ -128,12 +127,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->ao_accum_fb); - GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); - } - /* Accumulation pass */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD; DRW_PASS_CREATE(psl->ao_accum_ps, state); @@ -246,6 +239,7 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data * { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->ao_accum_fb != NULL) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -255,6 +249,13 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data * EEVEE_occlusion_compute(sldata, vedata); GPU_framebuffer_bind(fbl->ao_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + } + DRW_draw_pass(psl->ao_accum_ps); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 54f23073bd0..7af0f60748b 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -234,10 +234,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_EffectsInfo *effects = stl->effects; - - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Create FrameBuffer. */ const eGPUTextureFormat texture_format = (tot_samples > 256) ? GPU_RGBA32F : GPU_RGBA16F; @@ -245,12 +241,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), GPU_framebuffer_ensure_config(&fbl->ssr_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)}); - - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->ssr_accum_fb); - GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); - } } void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -258,9 +248,17 @@ void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (stl->g_data->valid_double_buffer) { GPU_framebuffer_bind(fbl->ssr_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); + } + DRW_draw_pass(psl->ssr_resolve); } } diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 51fd1cad41e..6a98c3316f3 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -361,12 +361,8 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_EffectsInfo *effects = stl->effects; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ const eGPUTextureFormat texture_format = GPU_R32F; DRW_texture_ensure_fullscreen_2d(&txl->shadow_accum, texture_format, 0); @@ -374,12 +370,6 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, GPU_framebuffer_ensure_config(&fbl->shadow_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->shadow_accum_fb); - GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); - } - /* Create Pass and shgroup. */ DRW_PASS_CREATE(psl->shadow_accum_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ADD_FULL); @@ -404,9 +394,17 @@ void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_D { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->shadow_accum_fb != NULL) { GPU_framebuffer_bind(fbl->shadow_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); + } + DRW_draw_pass(psl->shadow_accum_pass); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index d228d26cd52..3d24cd6fab5 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -394,10 +394,9 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS * - Grid exists and texture was loaded -> use texture. * - Grid exists but has zero size or failed to load -> use zero. * - Grid does not exist -> use default value. */ - GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : - (volume_grid) ? - e_data.dummy_zero : - eevee_volume_default_texture(gpu_grid->default_value); + GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : + (volume_grid) ? e_data.dummy_zero : + eevee_volume_default_texture(gpu_grid->default_value); DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex); @@ -800,8 +799,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl = vedata->psl; EEVEE_EffectsInfo *effects = stl->effects; - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ /* Should be enough precision for many samples. */ @@ -814,12 +811,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_accum), GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->volumetric_accum_fb); - GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); - } - /* Create Pass and shgroup. */ DRW_PASS_CREATE(psl->volumetric_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); DRWShadingGroup *grp = NULL; @@ -843,10 +834,18 @@ void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->volumetric_accum_fb != NULL) { /* Accum pass */ GPU_framebuffer_bind(fbl->volumetric_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); + } + DRW_draw_pass(psl->volumetric_accum_ps); /* Restore */ -- cgit v1.2.3 From 95889fe071e179a9a7d7e6a27aaf7a4a42fc49b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 5 May 2021 16:30:34 +0200 Subject: Fix T86823 Eevee: refraction depth shared between different materials This was caused by the material grouping system which was missing a per material uniform update in the opaque case. --- source/blender/draw/engines/eevee/eevee_materials.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 45c6900fc0f..a4325675ea9 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -623,6 +623,11 @@ static EeveeMaterialCache material_opaque(EEVEE_Data *vedata, /* This GPUShader has already been used by another material. * Add new shading group just after to avoid shader switching cost. */ grp = DRW_shgroup_create_sub(*grp_p); + + /* Per material uniforms. */ + if (use_ssrefract) { + DRW_shgroup_uniform_float_copy(grp, "refractionDepth", ma->refract_depth); + } } else { *grp_p = grp = DRW_shgroup_create(sh, shading_pass); -- cgit v1.2.3 From a1a9f8e6c3f341061777bc2d985b35e9d7a20ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 5 May 2021 18:13:24 +0200 Subject: Fix T87068 EEVEE: Moire effect with particle hair and subsurface This artifact was already present in previous version but was hidden by the faulty SSS scale. The issue comes from the translucence using the geometric normal (computed using fragment shader derivative) leading to poor precision at depth discontinuity. Replacing using the same geometric normal reconstruction as the ambient occlusion pass removes most of the issue. --- .../eevee/shaders/effect_translucency_frag.glsl | 60 ++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl index 737ef7dc509..356ed102928 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_translucency_frag.glsl @@ -183,16 +183,70 @@ vec3 light_translucent(LightData ld, vec3 P, vec3 N, vec4 l_vector, vec2 rand, f #undef scube #undef scsmd +/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. + * This samples the depth buffer 4 time for each direction to get the most correct + * implicit normal reconstruction out of the depth buffer. */ +vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float depth_center) +{ + vec2 uv1 = uvs - ofs * 2.0; + vec2 uv2 = uvs - ofs; + vec2 uv3 = uvs + ofs; + vec2 uv4 = uvs + ofs * 2.0; + vec4 H; + H.x = textureLod(depthBuffer, uv1, 0.0).r; + H.y = textureLod(depthBuffer, uv2, 0.0).r; + H.z = textureLod(depthBuffer, uv3, 0.0).r; + H.w = textureLod(depthBuffer, uv4, 0.0).r; + /* Fix issue with depth precision. Take even larger diff. */ + vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); + if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { + return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); + } + /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ + vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); + if (deltas.x < deltas.y) { + return vP - get_view_space_from_depth(uv2, H.y); + } + else { + return get_view_space_from_depth(uv3, H.z) - vP; + } +} + +/* TODO(fclem) port to a common place for other effects to use. */ +bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg) +{ + vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y))); + float depth_center = textureLod(depthBuffer, uvs, 0.0).r; + + vP = get_view_space_from_depth(uvs, depth_center); + + vec3 dPdx = view_position_derivative_from_depth(uvs, texel_size * vec2(1, 0), vP, depth_center); + vec3 dPdy = view_position_derivative_from_depth(uvs, texel_size * vec2(0, 1), vP, depth_center); + + vNg = safe_normalize(cross(dPdx, dPdy)); + + /* Background case. */ + if (depth_center == 1.0) { + return false; + } + + return true; +} + void main(void) { vec2 uvs = uvcoordsvar.xy; float sss_scale = texture(sssRadius, uvs).r; - vec3 P = get_world_space_from_depth(uvs, texture(depthBuffer, uvs).r); - vec3 N = normalize(cross(dFdx(P), dFdy(P))); vec3 rand = texelfetch_noise_tex(gl_FragCoord.xy).zwy; rand.xy *= fast_sqrt(rand.z); + vec3 vP, vNg; + reconstruct_view_position_and_normal_from_depth(uvs, vP, vNg); + + vec3 P = point_view_to_world(vP); + vec3 Ng = normal_view_to_world(vNg); + vec3 accum = vec3(0.0); for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) { LightData ld = lights_data[i]; @@ -211,7 +265,7 @@ void main(void) continue; } - accum += att * ld.l_color * light_translucent(ld, P, -N, l_vector, rand.xy, sss_scale); + accum += att * ld.l_color * light_translucent(ld, P, -Ng, l_vector, rand.xy, sss_scale); } FragColor = vec4(accum, 1.0); -- cgit v1.2.3 From c8293d6258e2b74ca29356dd9deca59c127eed3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 21 Apr 2021 00:43:35 +0200 Subject: Fix T86037 EEVEE: SSR option changes render passes result This was caused by the SSR option resetting the accumulation. But the render passes were only cleared in the init phase. This means that when SSR was resetting the `taa_render_sample` the actual renderpasses would still contains 1 sample. This means the renderpasses were always divided by the wrong number of samples. The fix is to clear just before accumulation if the sample is 1. The fact that it works for motion blur is kind of a blessing. This is because we check `stl->effects->ssr_was_valid_double_buffer` before resetting the sampling. So this only happens on the first motion step and does not affect the rest of the rendering. Differential Revision: https://developer.blender.org/D11033 --- .../blender/draw/engines/eevee/eevee_materials.c | 64 +++++++++++----------- source/blender/draw/engines/eevee/eevee_mist.c | 17 +++--- .../blender/draw/engines/eevee/eevee_occlusion.c | 15 ++--- .../draw/engines/eevee/eevee_renderpasses.c | 2 + .../draw/engines/eevee/eevee_screen_raytrace.c | 19 +++---- source/blender/draw/engines/eevee/eevee_shadows.c | 18 +++--- source/blender/draw/engines/eevee/eevee_volumes.c | 23 ++++---- 7 files changed, 79 insertions(+), 79 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 131f9a954cf..45c6900fc0f 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -961,22 +961,9 @@ void EEVEE_material_renderpasses_init(EEVEE_Data *vedata) } } -static void material_renderpass_init(EEVEE_FramebufferList *fbl, - GPUTexture **output_tx, - const eGPUTextureFormat format, - const bool do_clear) +static void material_renderpass_init(GPUTexture **output_tx, const eGPUTextureFormat format) { DRW_texture_ensure_fullscreen_2d(output_tx, format, 0); - /* Clear texture. */ - if (do_clear) { - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* TODO(fclem): replace by GPU_texture_clear once it is fast. */ - GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0); - GPU_framebuffer_bind(fbl->material_accum_fb); - GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); - GPU_framebuffer_bind(fbl->main_fb); - GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx); - } } void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) @@ -991,33 +978,32 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, /* Should be enough precision for many samples. */ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; - const bool do_clear = (effects->taa_current_sample == 1); /* Create FrameBuffer. */ GPU_framebuffer_ensure_config(&fbl->material_accum_fb, {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE}); if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { - material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear); + material_renderpass_init(&txl->env_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { - material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear); + material_renderpass_init(&txl->emit_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { - material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear); + material_renderpass_init(&txl->diff_color_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear); + material_renderpass_init(&txl->diff_light_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { - material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear); + material_renderpass_init(&txl->spec_color_accum, texture_format); } if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { - material_renderpass_init(fbl, &txl->aov_surface_accum[aov_index], texture_format, do_clear); + material_renderpass_init(&txl->aov_surface_accum[aov_index], texture_format); } } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear); + material_renderpass_init(&txl->spec_light_accum, texture_format); if (effects->enabled_effects & EFFECT_SSR) { EEVEE_reflection_output_init(sldata, vedata, tot_samples); @@ -1025,7 +1011,8 @@ void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, } } -static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, +static void material_renderpass_accumulate(EEVEE_EffectsInfo *effects, + EEVEE_FramebufferList *fbl, DRWPass *renderpass, DRWPass *renderpass2, EEVEE_PrivateData *pd, @@ -1035,6 +1022,11 @@ static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0); GPU_framebuffer_bind(fbl->material_accum_fb); + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); + } + pd->renderpass_ubo = renderpass_option_ubo; DRW_draw_pass(renderpass); if (renderpass2) { @@ -1056,15 +1048,21 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRWPass *material_accum_ps = psl->material_accum_ps; DRWPass *background_accum_ps = psl->background_accum_ps; if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { - material_renderpass_accumulate( - fbl, background_accum_ps, NULL, pd, txl->env_accum, sldata->renderpass_ubo.environment); + material_renderpass_accumulate(effects, + fbl, + background_accum_ps, + NULL, + pd, + txl->env_accum, + sldata->renderpass_ubo.environment); } if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { material_renderpass_accumulate( - fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit); + effects, fbl, material_accum_ps, NULL, pd, txl->emit_accum, sldata->renderpass_ubo.emit); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1072,7 +1070,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v sldata->renderpass_ubo.diff_color); } if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1090,7 +1089,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v sldata->common_data.ssr_toggle = false; GPU_uniformbuf_update(sldata->common_ubo, &sldata->common_data); } - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1102,7 +1102,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v } } if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, NULL, pd, @@ -1115,7 +1116,8 @@ void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *v } if (pd->render_passes & EEVEE_RENDER_PASS_AOV) { for (int aov_index = 0; aov_index < pd->num_aovs_used; aov_index++) { - material_renderpass_accumulate(fbl, + material_renderpass_accumulate(effects, + fbl, material_accum_ps, background_accum_ps, pd, diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 2b448695528..d4490d6fd4c 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -40,12 +40,9 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PassList *psl = vedata->psl; - EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; Scene *scene = draw_ctx->scene; - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ /* Should be enough precision for many samples. */ DRW_texture_ensure_fullscreen_2d(&txl->mist_accum, GPU_R32F, 0); @@ -53,12 +50,6 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) GPU_framebuffer_ensure_config(&fbl->mist_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->mist_accum_fb); - GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); - } - /* Mist settings. */ if (scene && scene->world) { g_data->mist_start = scene->world->miststa; @@ -103,9 +94,17 @@ void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->mist_accum_fb != NULL) { GPU_framebuffer_bind(fbl->mist_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + } + DRW_draw_pass(psl->mist_accum_ps); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 19f34fa6108..4c2024a6f65 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -120,7 +120,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Should be enough precision for many samples. */ DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0); @@ -128,12 +127,6 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->ao_accum_fb); - GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); - } - /* Accumulation pass */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD; DRW_PASS_CREATE(psl->ao_accum_ps, state); @@ -246,6 +239,7 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data * { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->ao_accum_fb != NULL) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -255,6 +249,13 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data * EEVEE_occlusion_compute(sldata, vedata); GPU_framebuffer_bind(fbl->ao_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + } + DRW_draw_pass(psl->ao_accum_ps); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 5739024993e..4b12748d2af 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -291,6 +291,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), g_data->renderpass_transmittance_input = volumetric_active ? txl->volume_transmittance_accum : txl->color; + printf("renderpass_current_sample %d\n", g_data->renderpass_current_sample); + if (!volumetric_active && renderpass_type == EEVEE_RENDER_PASS_VOLUME_LIGHT) { /* Early exit: Volumetric effect is off, but the volume light pass was requested. */ static float clear_col[4] = {0.0f}; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 54f23073bd0..8180715e0f6 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -234,10 +234,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_EffectsInfo *effects = stl->effects; - - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Create FrameBuffer. */ const eGPUTextureFormat texture_format = (tot_samples > 256) ? GPU_RGBA32F : GPU_RGBA16F; @@ -245,12 +241,6 @@ void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), GPU_framebuffer_ensure_config(&fbl->ssr_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)}); - - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->ssr_accum_fb); - GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); - } } void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -258,9 +248,18 @@ void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (stl->g_data->valid_double_buffer) { GPU_framebuffer_bind(fbl->ssr_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + printf("Clear\n"); + GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); + } + DRW_draw_pass(psl->ssr_resolve); } } diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 51fd1cad41e..6a98c3316f3 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -361,12 +361,8 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_EffectsInfo *effects = stl->effects; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ const eGPUTextureFormat texture_format = GPU_R32F; DRW_texture_ensure_fullscreen_2d(&txl->shadow_accum, texture_format, 0); @@ -374,12 +370,6 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, GPU_framebuffer_ensure_config(&fbl->shadow_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->shadow_accum_fb); - GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); - } - /* Create Pass and shgroup. */ DRW_PASS_CREATE(psl->shadow_accum_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ADD_FULL); @@ -404,9 +394,17 @@ void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_D { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->shadow_accum_fb != NULL) { GPU_framebuffer_bind(fbl->shadow_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); + } + DRW_draw_pass(psl->shadow_accum_pass); /* Restore */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index d228d26cd52..3d24cd6fab5 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -394,10 +394,9 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS * - Grid exists and texture was loaded -> use texture. * - Grid exists but has zero size or failed to load -> use zero. * - Grid does not exist -> use default value. */ - GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : - (volume_grid) ? - e_data.dummy_zero : - eevee_volume_default_texture(gpu_grid->default_value); + GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : + (volume_grid) ? e_data.dummy_zero : + eevee_volume_default_texture(gpu_grid->default_value); DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex); @@ -800,8 +799,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl = vedata->psl; EEVEE_EffectsInfo *effects = stl->effects; - const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - /* Create FrameBuffer. */ /* Should be enough precision for many samples. */ @@ -814,12 +811,6 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_accum), GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)}); - /* Clear texture. */ - if (effects->taa_current_sample == 1) { - GPU_framebuffer_bind(fbl->volumetric_accum_fb); - GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); - } - /* Create Pass and shgroup. */ DRW_PASS_CREATE(psl->volumetric_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); DRWShadingGroup *grp = NULL; @@ -843,10 +834,18 @@ void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; if (fbl->volumetric_accum_fb != NULL) { /* Accum pass */ GPU_framebuffer_bind(fbl->volumetric_accum_fb); + + /* Clear texture. */ + if (effects->taa_current_sample == 1) { + const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); + } + DRW_draw_pass(psl->volumetric_accum_ps); /* Restore */ -- cgit v1.2.3 From ccb5caef08143cff8922819f0f9ad64217ad90c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 21 Apr 2021 00:49:14 +0200 Subject: Remove printfs --- source/blender/draw/engines/eevee/eevee_renderpasses.c | 2 -- source/blender/draw/engines/eevee/eevee_screen_raytrace.c | 1 - 2 files changed, 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 4b12748d2af..5739024993e 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -291,8 +291,6 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), g_data->renderpass_transmittance_input = volumetric_active ? txl->volume_transmittance_accum : txl->color; - printf("renderpass_current_sample %d\n", g_data->renderpass_current_sample); - if (!volumetric_active && renderpass_type == EEVEE_RENDER_PASS_VOLUME_LIGHT) { /* Early exit: Volumetric effect is off, but the volume light pass was requested. */ static float clear_col[4] = {0.0f}; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 8180715e0f6..7af0f60748b 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -256,7 +256,6 @@ void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV /* Clear texture. */ if (effects->taa_current_sample == 1) { const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - printf("Clear\n"); GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); } -- cgit v1.2.3 From d0c63a2abe60d95b899c7122a754fe82e2077da2 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 7 May 2021 15:41:42 +0200 Subject: Cleanup: make format (clang-format) --- source/blender/draw/engines/eevee/eevee_volumes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 3d24cd6fab5..809d6010f10 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -394,9 +394,10 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS * - Grid exists and texture was loaded -> use texture. * - Grid exists but has zero size or failed to load -> use zero. * - Grid does not exist -> use default value. */ - GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : - (volume_grid) ? e_data.dummy_zero : - eevee_volume_default_texture(gpu_grid->default_value); + GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture : + (volume_grid) ? + e_data.dummy_zero : + eevee_volume_default_texture(gpu_grid->default_value); DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex); -- cgit v1.2.3 From 6cd4bb94350a9395da143fe90d9e600c0196025a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 10 May 2021 12:51:44 +0200 Subject: Fix T87764: Mem-leak during viewport rendering. When a scene uses cryptomatte the viewport rendering would lead to a memory leak. The reason was that all image renders (viewport+final) activated cryptomatte. But is only used for final rendering. This patch only activates cryptomatte when doing final rendering. --- source/blender/draw/engines/eevee/eevee_cryptomatte.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 0cb2d55d1eb..eace4eb18f6 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -121,7 +121,7 @@ void EEVEE_cryptomatte_renderpasses_init(EEVEE_Data *vedata) ViewLayer *view_layer = draw_ctx->view_layer; /* Cryptomatte is only rendered for final image renders */ - if (!DRW_state_is_image_render()) { + if (!DRW_state_is_scene_render()) { return; } const eViewLayerCryptomatteFlags active_layers = eevee_cryptomatte_active_layers(view_layer); @@ -158,9 +158,9 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), const ViewLayer *view_layer = draw_ctx->view_layer; const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); - eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? - GPU_R32F : - (num_cryptomatte_layers == 2) ? GPU_RG32F : GPU_RGBA32F; + eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? GPU_R32F : + (num_cryptomatte_layers == 2) ? GPU_RG32F : + GPU_RGBA32F; const float *viewport_size = DRW_viewport_size_get(); const int buffer_size = viewport_size[0] * viewport_size[1]; -- cgit v1.2.3 From ce62d650945fa87a58c5bd3cc71240858d7d192b Mon Sep 17 00:00:00 2001 From: Pablo Dobarro Date: Mon, 10 May 2021 19:29:52 +0200 Subject: Fix T82155: Fade inactive geometry overlay not working with instanced geometry This enables the overlay for instanced geometry. After this change, objects that are an instance of the current active object (which are also being modified in the current active mode) won't fade, which is different from the previous behavior. Reviewed By: fclem Maniphest Tasks: T82155 Differential Revision: https://developer.blender.org/D9362 --- source/blender/draw/engines/overlay/overlay_engine.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index e9736402ae7..b8f721946f2 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -285,10 +285,6 @@ static bool overlay_should_fade_object(Object *ob, Object *active_object) return false; } - if (ob->base_flag & BASE_FROM_DUPLI) { - return false; - } - return true; } -- cgit v1.2.3 From fc5bf09fd88c331b568c5b485bb0e487179ecb44 Mon Sep 17 00:00:00 2001 From: Yuki Shirakawa Date: Tue, 11 May 2021 11:22:41 +0200 Subject: Rigging: Add transform for custom bone shapes Add translation/rotation/scale parameters for custom bones shapes. The new scale is a 3D vector `custom_shape_scale_xyz`, and replaces the `custom_shape_scale` float. Reviewed By: #animation_rigging, sybren, zeddb Differential Revision: https://developer.blender.org/D10974 --- .../draw/engines/overlay/overlay_armature.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 54224071d23..e4072879adc 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -1031,7 +1031,7 @@ static void pchan_draw_data_init(bPoseChannel *pchan) static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel *pchan) { float ebmat[4][4]; - float length; + float bone_scale[3]; float(*bone_mat)[4]; float(*disp_mat)[4]; float(*disp_tail_mat)[4]; @@ -1040,23 +1040,23 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel * * and not be tight to the draw pass creation. * This would refresh armature without invalidating the draw cache */ if (pchan) { - length = pchan->bone->length; bone_mat = pchan->pose_mat; disp_mat = pchan->disp_mat; disp_tail_mat = pchan->disp_tail_mat; + mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, pchan->bone->length); } else { eBone->length = len_v3v3(eBone->tail, eBone->head); ED_armature_ebone_to_mat4(eBone, ebmat); - length = eBone->length; + copy_v3_fl(bone_scale, eBone->length); bone_mat = ebmat; disp_mat = eBone->disp_mat; disp_tail_mat = eBone->disp_tail_mat; } copy_m4_m4(disp_mat, bone_mat); - rescale_m4(disp_mat, (float[3]){length, length, length}); + rescale_m4(disp_mat, bone_scale); copy_m4_m4(disp_tail_mat, disp_mat); translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); } @@ -1255,19 +1255,27 @@ static void draw_bone_update_disp_matrix_bbone(EditBone *eBone, bPoseChannel *pc static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan) { - float length; + float bone_scale[3]; float(*bone_mat)[4]; float(*disp_mat)[4]; float(*disp_tail_mat)[4]; + float rot_mat[3][3]; /* See TODO above */ - length = PCHAN_CUSTOM_DRAW_SIZE(pchan); + mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, PCHAN_CUSTOM_BONE_LENGTH(pchan)); bone_mat = pchan->custom_tx ? pchan->custom_tx->pose_mat : pchan->pose_mat; disp_mat = pchan->disp_mat; disp_tail_mat = pchan->disp_tail_mat; + eulO_to_mat3(rot_mat, pchan->custom_rotation_euler, ROT_MODE_XYZ); + copy_m4_m4(disp_mat, bone_mat); - rescale_m4(disp_mat, (float[3]){length, length, length}); + translate_m4(disp_mat, + pchan->custom_translation[0], + pchan->custom_translation[1], + pchan->custom_translation[2]); + mul_m4_m4m3(disp_mat, disp_mat, rot_mat); + rescale_m4(disp_mat, bone_scale); copy_m4_m4(disp_tail_mat, disp_mat); translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f); } -- cgit v1.2.3 From 21bed44001a8e81e8278a46ec985a2b8660184ca Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Wed, 12 May 2021 12:55:47 +0200 Subject: Fix custom bone shape scale affecting normal bone display Also some clang-format changes. --- source/blender/draw/engines/overlay/overlay_armature.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index e4072879adc..acda07d7841 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -1043,7 +1043,7 @@ static void draw_bone_update_disp_matrix_default(EditBone *eBone, bPoseChannel * bone_mat = pchan->pose_mat; disp_mat = pchan->disp_mat; disp_tail_mat = pchan->disp_tail_mat; - mul_v3_v3fl(bone_scale, pchan->custom_scale_xyz, pchan->bone->length); + copy_v3_fl(bone_scale, pchan->bone->length); } else { eBone->length = len_v3v3(eBone->tail, eBone->head); @@ -1271,9 +1271,9 @@ static void draw_bone_update_disp_matrix_custom(bPoseChannel *pchan) copy_m4_m4(disp_mat, bone_mat); translate_m4(disp_mat, - pchan->custom_translation[0], - pchan->custom_translation[1], - pchan->custom_translation[2]); + pchan->custom_translation[0], + pchan->custom_translation[1], + pchan->custom_translation[2]); mul_m4_m4m3(disp_mat, disp_mat, rot_mat); rescale_m4(disp_mat, bone_scale); copy_m4_m4(disp_tail_mat, disp_mat); @@ -1286,10 +1286,9 @@ static void draw_axes(ArmatureDrawContext *ctx, const bArmature *arm) { float final_col[4]; - const float *col = (ctx->const_color) ? - ctx->const_color : - (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? G_draw.block.colorTextHi : - G_draw.block.colorText; + const float *col = (ctx->const_color) ? ctx->const_color : + (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? G_draw.block.colorTextHi : + G_draw.block.colorText; copy_v4_v4(final_col, col); /* Mix with axes color. */ final_col[3] = (ctx->const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.1 : 0.65; -- cgit v1.2.3 From d4783e019e3d34e7db49e4a7e2bc611f0956d989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Wed, 12 May 2021 17:20:08 +0200 Subject: Fix T87851 EEVEE: Performance regression with baked lighting & transparency This was caused by the drivers not optimizing the shader enough to remove the samplers and data used by closure eval. Removing the lighting loops from the depth shader fixes the perf regression. --- .../engines/eevee/shaders/closure_eval_lib.glsl | 93 +++++++++++++--------- 1 file changed, 56 insertions(+), 37 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl index b554fd113df..94dd1a439db 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_eval_lib.glsl @@ -51,53 +51,72 @@ closure_##t2##_##subroutine(in_##t2##_2, eval_##t2##_2, cl_common, sub_data, out_##t2##_2); \ closure_##t3##_##subroutine(in_##t3##_3, eval_##t3##_3, cl_common, sub_data, out_##t3##_3); +#ifndef DEPTH_SHADER /* Inputs are inout so that callers can get the final inputs used for evaluation. */ -#define CLOSURE_EVAL_FUNCTION_DECLARE(name, t0, t1, t2, t3) \ - void closure_##name##_eval(ClosureInputCommon in_common, \ - inout ClosureInput##t0 in_##t0##_0, \ - inout ClosureInput##t1 in_##t1##_1, \ - inout ClosureInput##t2 in_##t2##_2, \ - inout ClosureInput##t3 in_##t3##_3, \ - out ClosureOutput##t0 out_##t0##_0, \ - out ClosureOutput##t1 out_##t1##_1, \ - out ClosureOutput##t2 out_##t2##_2, \ - out ClosureOutput##t3 out_##t3##_3) \ - { \ - CLOSURE_EVAL_DECLARE(t0, t1, t2, t3); \ +# define CLOSURE_EVAL_FUNCTION_DECLARE(name, t0, t1, t2, t3) \ + void closure_##name##_eval(ClosureInputCommon in_common, \ + inout ClosureInput##t0 in_##t0##_0, \ + inout ClosureInput##t1 in_##t1##_1, \ + inout ClosureInput##t2 in_##t2##_2, \ + inout ClosureInput##t3 in_##t3##_3, \ + out ClosureOutput##t0 out_##t0##_0, \ + out ClosureOutput##t1 out_##t1##_1, \ + out ClosureOutput##t2 out_##t2##_2, \ + out ClosureOutput##t3 out_##t3##_3) \ + { \ + CLOSURE_EVAL_DECLARE(t0, t1, t2, t3); \ \ - /* Starts at 1 because 0 is world cubemap. */ \ - for (int i = 1; cl_common.specular_accum > 0.0 && i < prbNumRenderCube && i < MAX_PROBE; \ - i++) { \ - ClosureCubemapData cube = closure_cubemap_eval_init(i, cl_common); \ - if (cube.attenuation > 1e-8) { \ - CLOSURE_META_SUBROUTINE_DATA(cubemap_eval, cube, t0, t1, t2, t3); \ + /* Starts at 1 because 0 is world cubemap. */ \ + for (int i = 1; cl_common.specular_accum > 0.0 && i < prbNumRenderCube && i < MAX_PROBE; \ + i++) { \ + ClosureCubemapData cube = closure_cubemap_eval_init(i, cl_common); \ + if (cube.attenuation > 1e-8) { \ + CLOSURE_META_SUBROUTINE_DATA(cubemap_eval, cube, t0, t1, t2, t3); \ + } \ } \ - } \ \ - /* Starts at 1 because 0 is world irradiance. */ \ - for (int i = 1; cl_common.diffuse_accum > 0.0 && i < prbNumRenderGrid && i < MAX_GRID; i++) { \ - ClosureGridData grid = closure_grid_eval_init(i, cl_common); \ - if (grid.attenuation > 1e-8) { \ - CLOSURE_META_SUBROUTINE_DATA(grid_eval, grid, t0, t1, t2, t3); \ + /* Starts at 1 because 0 is world irradiance. */ \ + for (int i = 1; cl_common.diffuse_accum > 0.0 && i < prbNumRenderGrid && i < MAX_GRID; \ + i++) { \ + ClosureGridData grid = closure_grid_eval_init(i, cl_common); \ + if (grid.attenuation > 1e-8) { \ + CLOSURE_META_SUBROUTINE_DATA(grid_eval, grid, t0, t1, t2, t3); \ + } \ } \ - } \ \ - CLOSURE_META_SUBROUTINE(indirect_end, t0, t1, t2, t3); \ + CLOSURE_META_SUBROUTINE(indirect_end, t0, t1, t2, t3); \ \ - ClosurePlanarData planar = closure_planar_eval_init(cl_common); \ - if (planar.attenuation > 1e-8) { \ - CLOSURE_META_SUBROUTINE_DATA(planar_eval, planar, t0, t1, t2, t3); \ - } \ + ClosurePlanarData planar = closure_planar_eval_init(cl_common); \ + if (planar.attenuation > 1e-8) { \ + CLOSURE_META_SUBROUTINE_DATA(planar_eval, planar, t0, t1, t2, t3); \ + } \ \ - for (int i = 0; i < laNumLight && i < MAX_LIGHT; i++) { \ - ClosureLightData light = closure_light_eval_init(cl_common, i); \ - if (light.vis > 1e-8) { \ - CLOSURE_META_SUBROUTINE_DATA(light_eval, light, t0, t1, t2, t3); \ + for (int i = 0; i < laNumLight && i < MAX_LIGHT; i++) { \ + ClosureLightData light = closure_light_eval_init(cl_common, i); \ + if (light.vis > 1e-8) { \ + CLOSURE_META_SUBROUTINE_DATA(light_eval, light, t0, t1, t2, t3); \ + } \ } \ - } \ \ - CLOSURE_META_SUBROUTINE(eval_end, t0, t1, t2, t3); \ - } + CLOSURE_META_SUBROUTINE(eval_end, t0, t1, t2, t3); \ + } + +#else +/* Inputs are inout so that callers can get the final inputs used for evaluation. */ +# define CLOSURE_EVAL_FUNCTION_DECLARE(name, t0, t1, t2, t3) \ + void closure_##name##_eval(ClosureInputCommon in_common, \ + inout ClosureInput##t0 in_##t0##_0, \ + inout ClosureInput##t1 in_##t1##_1, \ + inout ClosureInput##t2 in_##t2##_2, \ + inout ClosureInput##t3 in_##t3##_3, \ + out ClosureOutput##t0 out_##t0##_0, \ + out ClosureOutput##t1 out_##t1##_1, \ + out ClosureOutput##t2 out_##t2##_2, \ + out ClosureOutput##t3 out_##t3##_3) \ + { \ + CLOSURE_EVAL_DECLARE(t0, t1, t2, t3); \ + } +#endif #define CLOSURE_EVAL_FUNCTION(name, t0, t1, t2, t3) \ closure_##name##_eval(in_common, \ -- cgit v1.2.3 From bddc987ba333d7308b35d09d14d97e750ebab11c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 13 May 2021 12:44:11 +1000 Subject: Cleanup: clang format --- source/blender/draw/engines/eevee/eevee_cryptomatte.c | 6 +++--- source/blender/draw/engines/overlay/overlay_armature.c | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index eace4eb18f6..70d48ea6040 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -158,9 +158,9 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), const ViewLayer *view_layer = draw_ctx->view_layer; const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); - eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? GPU_R32F : - (num_cryptomatte_layers == 2) ? GPU_RG32F : - GPU_RGBA32F; + eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? + GPU_R32F : + (num_cryptomatte_layers == 2) ? GPU_RG32F : GPU_RGBA32F; const float *viewport_size = DRW_viewport_size_get(); const int buffer_size = viewport_size[0] * viewport_size[1]; diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index acda07d7841..fbad60ff4ab 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -1286,9 +1286,10 @@ static void draw_axes(ArmatureDrawContext *ctx, const bArmature *arm) { float final_col[4]; - const float *col = (ctx->const_color) ? ctx->const_color : - (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? G_draw.block.colorTextHi : - G_draw.block.colorText; + const float *col = (ctx->const_color) ? + ctx->const_color : + (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? G_draw.block.colorTextHi : + G_draw.block.colorText; copy_v4_v4(final_col, col); /* Mix with axes color. */ final_col[3] = (ctx->const_color) ? 1.0 : (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? 0.1 : 0.65; -- cgit v1.2.3 From 55b9b1ff507c524834ece73908f36ccf14928f63 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 14 May 2021 07:55:01 +0200 Subject: Draw: Put DrawTest in its own compile unit. DrawTest will be used by other tests as well. --- source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/tests/draw_testing.cc | 18 ++++++++++++++++++ source/blender/draw/tests/draw_testing.hh | 12 ++++++++++++ source/blender/draw/tests/shaders_test.cc | 12 +----------- 4 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 source/blender/draw/tests/draw_testing.cc create mode 100644 source/blender/draw/tests/draw_testing.hh (limited to 'source/blender/draw') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 196b46953c4..27167ce839b 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -478,6 +478,7 @@ add_dependencies(bf_draw bf_dna) if(WITH_GTESTS) if(WITH_OPENGL_DRAW_TESTS) set(TEST_SRC + tests/draw_testing.cc tests/shaders_test.cc ) set(TEST_INC diff --git a/source/blender/draw/tests/draw_testing.cc b/source/blender/draw/tests/draw_testing.cc new file mode 100644 index 00000000000..0104437e921 --- /dev/null +++ b/source/blender/draw/tests/draw_testing.cc @@ -0,0 +1,18 @@ +/* Apache License, Version 2.0 */ + +#include "draw_testing.hh" + +#include "GPU_shader.h" + +#include "draw_manager_testing.h" + +namespace blender::draw { + +/* Base class for draw test cases. It will setup and tear down the GPU part around each test. */ +void DrawTest::SetUp() +{ + GPUTest::SetUp(); + DRW_draw_state_init_gtests(GPU_SHADER_CFG_DEFAULT); +} + +} // namespace blender::draw diff --git a/source/blender/draw/tests/draw_testing.hh b/source/blender/draw/tests/draw_testing.hh new file mode 100644 index 00000000000..3b91de007a2 --- /dev/null +++ b/source/blender/draw/tests/draw_testing.hh @@ -0,0 +1,12 @@ +/* Apache License, Version 2.0 */ + +#include "gpu_testing.hh" + +namespace blender::draw { + +/* Base class for draw test cases. It will setup and tear down the GPU part around each test. */ +class DrawTest : public blender::gpu::GPUTest { + void SetUp() override; +}; + +} // namespace blender::draw diff --git a/source/blender/draw/tests/shaders_test.cc b/source/blender/draw/tests/shaders_test.cc index 96d544fd855..c96f22859ca 100644 --- a/source/blender/draw/tests/shaders_test.cc +++ b/source/blender/draw/tests/shaders_test.cc @@ -2,12 +2,12 @@ #include "testing/testing.h" +#include "draw_testing.hh" #include "intern/draw_manager_testing.h" #include "GPU_context.h" #include "GPU_init_exit.h" #include "GPU_shader.h" -#include "gpu_testing.hh" #include "engines/eevee/eevee_private.h" #include "engines/gpencil/gpencil_engine.h" @@ -17,19 +17,9 @@ namespace blender::draw { -/* Base class for draw test cases. It will setup and tear down the GPU part around each test. */ -class DrawTest : public blender::gpu::GPUTest { - void SetUp() override - { - GPUTest::SetUp(); - DRW_draw_state_init_gtests(GPU_SHADER_CFG_DEFAULT); - } -}; - TEST_F(DrawTest, workbench_glsl_shaders) { workbench_shader_library_ensure(); - DRW_draw_state_init_gtests(GPU_SHADER_CFG_DEFAULT); const int MAX_WPD = 6; WORKBENCH_PrivateData wpds[MAX_WPD]; -- cgit v1.2.3 From 20c3db6604e8de49dc780201ce583041d017064d Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 14 May 2021 08:34:13 +0200 Subject: DrawTest: Make setup method public. This allows other tests to override it. --- source/blender/draw/tests/draw_testing.hh | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/tests/draw_testing.hh b/source/blender/draw/tests/draw_testing.hh index 3b91de007a2..ec0b15b611e 100644 --- a/source/blender/draw/tests/draw_testing.hh +++ b/source/blender/draw/tests/draw_testing.hh @@ -6,6 +6,7 @@ namespace blender::draw { /* Base class for draw test cases. It will setup and tear down the GPU part around each test. */ class DrawTest : public blender::gpu::GPUTest { + public: void SetUp() override; }; -- cgit v1.2.3 From 45d3303ae42e0b563bd164148efa516f93261ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 14 May 2021 16:18:12 +0200 Subject: Fix T85845 EEVEE: Depth Of Field: Artifacts with slight out of focus This was caused by the bokeh LUT being sampled outside the valid range. But `texelFetch` is only valid if the sample actually exists. This lead to undefined behavior. The fix is to increase `DOF_MAX_SLIGHT_FOCUS_RADIUS` (which just offsets the LUT along the X=Y axis) to avoid any sample outside the defined range. --- source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl index faac216480b..dac53719149 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_lib.glsl @@ -136,7 +136,7 @@ const float layer_offset_fg = 0.5 + 1.0; /* Extra offset for convolution layers to avoid light leaking from background. */ const float layer_offset = 0.5 + 0.5; -#define DOF_MAX_SLIGHT_FOCUS_RADIUS 5 +#define DOF_MAX_SLIGHT_FOCUS_RADIUS 16 float dof_layer_weight(float coc, const bool is_foreground) { -- cgit v1.2.3 From 5d97e293c30b41bcd84a2d831ae35e67d8e54670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 15 May 2021 17:48:26 +0200 Subject: EEVEE: Depth of Field: Fix tile artifacts in mixed focus regions This was caused by the slight focus gather not being wide enough for small radii. Now the cast to int will properly round the radius to the nearest integer. This is related to T86244 Black Artefacts in EEVEE on Transparent BSDF --- source/blender/draw/engines/eevee/shaders/effect_dof_resolve_frag.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_resolve_frag.glsl index cd69a0e2ab1..32841b7749c 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_resolve_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_resolve_frag.glsl @@ -40,7 +40,7 @@ void dof_slight_focus_gather(float radius, out vec4 out_color, out float out_wei DofGatherData fg_accum = GATHER_DATA_INIT; DofGatherData bg_accum = GATHER_DATA_INIT; - int i_radius = clamp(int(radius), 0, int(layer_threshold)); + int i_radius = clamp(int(radius + 0.5), 0, int(layer_threshold)); const int resolve_ring_density = DOF_SLIGHT_FOCUS_DENSITY; ivec2 texel = ivec2(gl_FragCoord.xy); -- cgit v1.2.3 From 610c0ecc3b91a9d3f08fc83eac26bc75c3dfc92b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 15 May 2021 18:29:14 +0200 Subject: Fix T88204 EEVEE: Animated world light doesnt work during render This was a bug uncovered by rB50782df42586. Previously, the lightcache was always discarded between redraw and forced to be updated again. Now we check for update inside the render loop making it compatible with accumulation motion blur and long exposure. --- source/blender/draw/engines/eevee/eevee_engine.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 509c002e25a..88fd823bc72 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -556,6 +556,11 @@ static void eevee_render_to_image(void *vedata, EEVEE_renderpasses_output_init( sldata, vedata, g_data->render_sample_count_per_timestep * time_steps_tot); + if (scene->world) { + /* Update world in case of animated world material. */ + eevee_id_world_update(vedata, scene->world); + } + EEVEE_temporal_sampling_create_view(vedata); EEVEE_render_draw(vedata, engine, render_layer, rect); -- cgit v1.2.3 From cdc1ddf20bcf6b0a3783039a3828847afd3fd633 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 18 May 2021 12:53:27 +1000 Subject: Cleanup: clang-format --- source/blender/draw/engines/eevee/eevee_cryptomatte.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index eace4eb18f6..70d48ea6040 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -158,9 +158,9 @@ void EEVEE_cryptomatte_output_init(EEVEE_ViewLayerData *UNUSED(sldata), const ViewLayer *view_layer = draw_ctx->view_layer; const int num_cryptomatte_layers = eevee_cryptomatte_layers_count(view_layer); - eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? GPU_R32F : - (num_cryptomatte_layers == 2) ? GPU_RG32F : - GPU_RGBA32F; + eGPUTextureFormat format = (num_cryptomatte_layers == 1) ? + GPU_R32F : + (num_cryptomatte_layers == 2) ? GPU_RG32F : GPU_RGBA32F; const float *viewport_size = DRW_viewport_size_get(); const int buffer_size = viewport_size[0] * viewport_size[1]; -- cgit v1.2.3 From a9da73ab95f07b7965df133edb6f32429ccb7302 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Tue, 18 May 2021 15:42:26 +0200 Subject: Fix T88370: GPencil render crash when use viewlayer and masking When filtering the render using view layer, could be possible the mask is NULL and just need to be ignored. --- source/blender/draw/engines/gpencil/gpencil_engine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 8bb336ebc96..32884eb9e3f 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -819,7 +819,10 @@ static void gpencil_draw_mask(GPENCIL_Data *vedata, GPENCIL_tObject *ob, GPENCIL } GPENCIL_tLayer *mask_layer = gpencil_layer_cache_get(ob, i); - BLI_assert(mask_layer); + /* When filtering by viewlayer, the mask could be null and must be ignored. */ + if (mask_layer == NULL) { + continue; + } DRW_draw_pass(mask_layer->geom_ps); } -- cgit v1.2.3 From 1a81d268a19f2f1402f408ad1dadf92c7a399607 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 19 May 2021 10:23:09 +0200 Subject: Materials: support changing materials during evaluation This commit allows that the evaluated geometry of an object has different materials from the original geometry. This is needed for geometry nodes. The main thing that changes for render engines and exporters is that the number of material slots on an object and its geometry might not match anymore. For original data, the slot counts are still equal, but not for evaluated data. Accessing material slots though rna stays the same. The behavior adapts automatically depending on whether the object is evaluated. When accessing materials of an object through `BKE_object_material_*` one has to use a new api for evaluated objects: `BKE_object_material_get_eval` and `BKE_object_material_count_eval`. In the future, the different behavior might be hidden behind a more general C api, but that would require quite a few more changes. The ground truth for the number of materials is the number of materials on the geometry now. This is important in the current design, because Eevee needs to know the number of materials just based on the mesh in `mesh_render_mat_len_get` and similar places. In a few places I had to add a special case for mesh edit mode to get it to work properly. This is unfortunate, but I don't see a way around that for now. Differential Revision: https://developer.blender.org/D11236 --- source/blender/draw/engines/eevee/eevee_cryptomatte.c | 8 +++----- source/blender/draw/engines/eevee/eevee_materials.c | 2 +- source/blender/draw/engines/eevee/eevee_volumes.c | 2 +- source/blender/draw/engines/gpencil/gpencil_cache_utils.c | 3 ++- source/blender/draw/engines/gpencil/gpencil_draw_data.c | 2 +- source/blender/draw/engines/overlay/overlay_gpencil.c | 2 +- source/blender/draw/engines/overlay/overlay_paint.c | 2 +- source/blender/draw/engines/overlay/overlay_particle.c | 2 +- source/blender/draw/engines/workbench/workbench_materials.c | 2 +- source/blender/draw/engines/workbench/workbench_volume.c | 2 +- source/blender/draw/intern/draw_cache_extract.h | 4 ++++ 11 files changed, 17 insertions(+), 14 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index 70d48ea6040..7fe984b4397 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -265,8 +265,7 @@ void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata, Object *ob) { BLI_assert(ob->type == OB_HAIR); - Hair *hair = ob->data; - Material *material = hair->mat ? hair->mat[HAIR_MATERIAL_NR - 1] : NULL; + Material *material = BKE_object_material_get_eval(ob, HAIR_MATERIAL_NR); eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, NULL, NULL, material); } @@ -291,8 +290,7 @@ void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata, if (draw_as != PART_DRAW_PATH) { continue; } - Mesh *mesh = ob->data; - Material *material = part->omat - 1 < mesh->totcol ? NULL : mesh->mat[part->omat - 1]; + Material *material = BKE_object_material_get_eval(ob, part->omat); eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, psys, md, material); } } @@ -318,7 +316,7 @@ void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *s if (geom == NULL) { continue; } - Material *material = BKE_object_material_get(ob, i + 1); + Material *material = BKE_object_material_get_eval(ob, i + 1); DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create( vedata, sldata, ob, material, false); DRW_shgroup_call(grp, geom, ob); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index a4325675ea9..d2e0c8308c5 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -723,7 +723,7 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou if (holdout) { return BKE_material_default_holdout(); } - Material *ma = BKE_object_material_get(ob, slot + 1); + Material *ma = BKE_object_material_get_eval(ob, slot + 1); if (ma == NULL) { if (ob->type == OB_VOLUME) { ma = BKE_material_default_volume(); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 809d6010f10..eed36221fcb 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -501,7 +501,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, Scene *scene, Object *ob) { - Material *ma = BKE_object_material_get(ob, 1); + Material *ma = BKE_object_material_get_eval(ob, 1); if (ma == NULL) { if (ob->type == OB_VOLUME) { diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index ee51b751187..adb70f97585 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -60,7 +60,8 @@ GPENCIL_tObject *gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob) /* Check if any material with holdout flag enabled. */ tgp_ob->do_mat_holdout = false; - for (int i = 0; i < ob->totcol; i++) { + const int tot_materials = BKE_object_material_count_eval(ob); + for (int i = 0; i < tot_materials; i++) { MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, i + 1); if (((gp_style != NULL) && (gp_style->flag & GP_MATERIAL_IS_STROKE_HOLDOUT)) || ((gp_style->flag & GP_MATERIAL_IS_FILL_HOLDOUT))) { diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 526f553329e..e3e84dd4c8c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -186,7 +186,7 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje { GPENCIL_MaterialPool *matpool = pd->last_material_pool; - int mat_len = max_ii(1, ob->totcol); + int mat_len = max_ii(1, BKE_object_material_count_eval(ob)); bool reuse_matpool = matpool && ((matpool->used_count + mat_len) <= GP_MATERIAL_BUFFER_LEN); diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index 891142fe0a2..aa26aa47faa 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -382,7 +382,7 @@ static void overlay_gpencil_draw_stroke_color_name(bGPDlayer *UNUSED(gpl), void *thunk) { Object *ob = (Object *)thunk; - Material *ma = BKE_object_material_get(ob, gps->mat_nr + 1); + Material *ma = BKE_object_material_get_eval(ob, gps->mat_nr + 1); if (ma == NULL) { return; } diff --git a/source/blender/draw/engines/overlay/overlay_paint.c b/source/blender/draw/engines/overlay/overlay_paint.c index 89e724bcfcc..d52640ed174 100644 --- a/source/blender/draw/engines/overlay/overlay_paint.c +++ b/source/blender/draw/engines/overlay/overlay_paint.c @@ -48,7 +48,7 @@ static bool paint_object_is_rendered_transparent(View3D *v3d, Object *ob) v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR) { Mesh *me = ob->data; for (int i = 0; i < me->totcol; i++) { - Material *mat = me->mat[i]; + Material *mat = BKE_object_material_get_eval(ob, i + 1); if (mat && mat->a < 1.0f) { return true; } diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c index 71064e7ff47..5fa74a8c3a6 100644 --- a/source/blender/draw/engines/overlay/overlay_particle.c +++ b/source/blender/draw/engines/overlay/overlay_particle.c @@ -186,7 +186,7 @@ void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob) /* TODO(fclem): Here would be a good place for preemptive culling. */ /* NOTE(fclem): Is color even useful in our modern context? */ - Material *ma = BKE_object_material_get(ob, part->omat); + Material *ma = BKE_object_material_get_eval(ob, part->omat); float color[4] = {0.6f, 0.6f, 0.6f, part->draw_size}; if (ma != NULL) { copy_v3_v3(color, &ma->r); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 6e9118bfe46..800d1085505 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -93,7 +93,7 @@ void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd, /* Return correct material or empty default material if slot is empty. */ BLI_INLINE Material *workbench_object_material_get(Object *ob, int mat_nr) { - Material *ma = BKE_object_material_get(ob, mat_nr); + Material *ma = BKE_object_material_get_eval(ob, mat_nr); if (ma == NULL) { ma = BKE_material_default_empty(); } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index 525a81b5581..ddda6d7b58e 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -202,7 +202,7 @@ static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd, eV3DShadingColorType color_type, float color[3]) { - Material *ma = BKE_object_material_get(ob, VOLUME_MATERIAL_NR); + Material *ma = BKE_object_material_get_eval(ob, VOLUME_MATERIAL_NR); WORKBENCH_UBO_Material ubo_data; workbench_material_ubo_data(wpd, ob, ma, &ubo_data, color_type); copy_v3_v3(color, ubo_data.base_color); diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index c929fe7dfd3..bbb97fc09a3 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -88,6 +88,10 @@ typedef enum eMRExtractType { BLI_INLINE int mesh_render_mat_len_get(Mesh *me) { + /* In edit mode, the displayed mesh is stored in the edit-mesh. */ + if (me->edit_mesh && me->edit_mesh->mesh_eval_final) { + return MAX2(1, me->edit_mesh->mesh_eval_final->totcol); + } return MAX2(1, me->totcol); } -- cgit v1.2.3 From ef04fd95717d972f294c5ff69a418a7af4504d35 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Thu, 20 May 2021 19:36:53 +0200 Subject: GPencil: Fix missing annotations in VSE strip Since version 2.80, the annotations of the Scene strip were not displayed in VSE. Also, the UI panel was`Grease Pencil` and must be `Annotation` The problem was the offscreen render hasn't evil_CTX and the section of the annotation was never called. Differential Revision: https://developer.blender.org/D11329 --- source/blender/draw/intern/draw_manager.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index c09b4719f3a..37f6bbf52b5 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1473,6 +1473,14 @@ void DRW_draw_callbacks_post_scene(void) GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } + else { + if (v3d && ((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0)) { + GPU_depth_test(GPU_DEPTH_NONE); + /* XXX: as scene->gpd is not copied for COW yet */ + ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, region, true); + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + } + } } struct DRWTextStore *DRW_text_cache_ensure(void) -- cgit v1.2.3 From 2175cbe2ceeffc65517dd21ee94f19bc93094544 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 21 May 2021 17:28:19 -0400 Subject: Cleanup: Move curve draw cache implementation to C++ I'd like to use this file to draw curves from geometry nodes, which would otherwise require implementing a C API. The changes in this commit are minimal, mostly just casts and changing to nullptr. Differential Revision: https://developer.blender.org/D11350 --- source/blender/draw/CMakeLists.txt | 2 +- source/blender/draw/intern/draw_cache_impl.h | 8 + source/blender/draw/intern/draw_cache_impl_curve.c | 1126 ------------------- .../blender/draw/intern/draw_cache_impl_curve.cc | 1131 ++++++++++++++++++++ source/blender/draw/intern/draw_cache_inline.h | 4 +- 5 files changed, 1142 insertions(+), 1129 deletions(-) delete mode 100644 source/blender/draw/intern/draw_cache_impl_curve.c create mode 100644 source/blender/draw/intern/draw_cache_impl_curve.cc (limited to 'source/blender/draw') diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 27167ce839b..045adf4b380 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -51,7 +51,7 @@ set(INC set(SRC intern/draw_cache.c intern/draw_cache_extract_mesh.c - intern/draw_cache_impl_curve.c + intern/draw_cache_impl_curve.cc intern/draw_cache_impl_displist.c intern/draw_cache_impl_gpencil.c intern/draw_cache_impl_hair.c diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 7b97ce43558..2c2ab9eaadd 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -43,6 +43,10 @@ struct bGPdata; #include "BKE_mesh_types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Expose via BKE callbacks */ void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode); void DRW_mball_batch_cache_validate(struct MetaBall *mb); @@ -262,3 +266,7 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object * struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c deleted file mode 100644 index e9558fb320c..00000000000 --- a/source/blender/draw/intern/draw_cache_impl_curve.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2017 by Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup draw - * - * \brief Curve API for render engines - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_listbase.h" -#include "BLI_math_vector.h" -#include "BLI_utildefines.h" - -#include "DNA_curve_types.h" - -#include "BKE_curve.h" -#include "BKE_displist.h" -#include "BKE_font.h" - -#include "GPU_batch.h" -#include "GPU_capabilities.h" -#include "GPU_material.h" -#include "GPU_texture.h" - -#include "UI_resources.h" - -#include "DRW_render.h" - -#include "draw_cache_inline.h" - -#include "draw_cache_impl.h" /* own include */ - -/* See: edit_curve_point_vert.glsl for duplicate includes. */ -#define SELECT 1 -#define ACTIVE_NURB (1 << 2) -#define BEZIER_HANDLE (1 << 3) -#define EVEN_U_BIT (1 << 4) /* Alternate this bit for every U vert. */ -#define COLOR_SHIFT 5 - -/* Used as values of `color_id` in `edit_curve_overlay_handle_geom.glsl` */ -enum { - COLOR_NURB_ULINE_ID = TH_HANDLE_AUTOCLAMP - TH_HANDLE_FREE + 2, - - TOT_HANDLE_COL, -}; - -/** - * TODO - * - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`. - * - Check number of verts/edges to see if cache is valid. - * - Check if 'overlay.edges' can use single attribute per edge, not 2 (for selection drawing). - */ - -static void curve_batch_cache_clear(Curve *cu); - -/* ---------------------------------------------------------------------- */ -/* Curve Interface, direct access to basic data. */ - -static void curve_render_overlay_verts_edges_len_get(ListBase *lb, - int *r_vert_len, - int *r_edge_len) -{ - BLI_assert(r_vert_len || r_edge_len); - int vert_len = 0; - int edge_len = 0; - LISTBASE_FOREACH (Nurb *, nu, lb) { - if (nu->bezt) { - vert_len += nu->pntsu * 3; - /* 2x handles per point*/ - edge_len += 2 * nu->pntsu; - } - else if (nu->bp) { - vert_len += nu->pntsu * nu->pntsv; - /* segments between points */ - edge_len += (nu->pntsu - 1) * nu->pntsv; - edge_len += (nu->pntsv - 1) * nu->pntsu; - } - } - if (r_vert_len) { - *r_vert_len = vert_len; - } - if (r_edge_len) { - *r_edge_len = edge_len; - } -} - -static void curve_render_wire_verts_edges_len_get(const CurveCache *ob_curve_cache, - int *r_curve_len, - int *r_vert_len, - int *r_edge_len) -{ - BLI_assert(r_vert_len || r_edge_len); - int vert_len = 0; - int edge_len = 0; - int curve_len = 0; - LISTBASE_FOREACH (const BevList *, bl, &ob_curve_cache->bev) { - if (bl->nr > 0) { - const bool is_cyclic = bl->poly != -1; - edge_len += (is_cyclic) ? bl->nr : bl->nr - 1; - vert_len += bl->nr; - curve_len += 1; - } - } - LISTBASE_FOREACH (const DispList *, dl, &ob_curve_cache->disp) { - if (ELEM(dl->type, DL_SEGM, DL_POLY)) { - BLI_assert(dl->parts == 1); - const bool is_cyclic = dl->type == DL_POLY; - edge_len += (is_cyclic) ? dl->nr : dl->nr - 1; - vert_len += dl->nr; - curve_len += 1; - } - } - if (r_vert_len) { - *r_vert_len = vert_len; - } - if (r_edge_len) { - *r_edge_len = edge_len; - } - if (r_curve_len) { - *r_curve_len = curve_len; - } -} - -static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache) -{ - int normal_len = 0; - const BevList *bl; - const Nurb *nu; - for (bl = ob_curve_cache->bev.first, nu = lb->first; nu && bl; bl = bl->next, nu = nu->next) { - int nr = bl->nr; - int skip = nu->resolu / 16; -#if 0 - while (nr-- > 0) { /* accounts for empty bevel lists */ - normal_len += 1; - nr -= skip; - } -#else - /* Same as loop above */ - normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0); -#endif - } - return normal_len; -} - -/* ---------------------------------------------------------------------- */ -/* Curve Interface, indirect, partially cached access to complex data. */ - -typedef struct CurveRenderData { - int types; - - struct { - int vert_len; - int edge_len; - } overlay; - - struct { - int curve_len; - int vert_len; - int edge_len; - } wire; - - /* edit mode normal's */ - struct { - /* 'edge_len == len * 2' - * 'vert_len == len * 3' */ - int len; - } normal; - - struct { - EditFont *edit_font; - } text; - - /* borrow from 'Object' */ - CurveCache *ob_curve_cache; - - /* borrow from 'Curve' */ - ListBase *nurbs; - - /* edit, index in nurb list */ - int actnu; - /* edit, index in active nurb (BPoint or BezTriple) */ - int actvert; -} CurveRenderData; - -enum { - /* Wire center-line */ - CU_DATATYPE_WIRE = 1 << 0, - /* Edit-mode verts and optionally handles */ - CU_DATATYPE_OVERLAY = 1 << 1, - /* Edit-mode normals */ - CU_DATATYPE_NORMAL = 1 << 2, - /* Geometry */ - CU_DATATYPE_SURFACE = 1 << 3, - /* Text */ - CU_DATATYPE_TEXT_SELECT = 1 << 4, -}; - -/* - * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE - */ -static CurveRenderData *curve_render_data_create(Curve *cu, - CurveCache *ob_curve_cache, - const int types) -{ - CurveRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); - rdata->types = types; - ListBase *nurbs; - - rdata->actnu = cu->actnu; - rdata->actvert = cu->actvert; - - rdata->ob_curve_cache = ob_curve_cache; - - if (types & CU_DATATYPE_WIRE) { - curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache, - &rdata->wire.curve_len, - &rdata->wire.vert_len, - &rdata->wire.edge_len); - } - - if (cu->editnurb) { - EditNurb *editnurb = cu->editnurb; - nurbs = &editnurb->nurbs; - - if (types & CU_DATATYPE_OVERLAY) { - curve_render_overlay_verts_edges_len_get( - nurbs, &rdata->overlay.vert_len, &rdata->overlay.edge_len); - - rdata->actnu = cu->actnu; - rdata->actvert = cu->actvert; - } - if (types & CU_DATATYPE_NORMAL) { - rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache); - } - } - else { - nurbs = &cu->nurb; - } - - rdata->nurbs = nurbs; - - rdata->text.edit_font = cu->editfont; - - return rdata; -} - -static void curve_render_data_free(CurveRenderData *rdata) -{ -#if 0 - if (rdata->loose_verts) { - MEM_freeN(rdata->loose_verts); - } -#endif - MEM_freeN(rdata); -} - -static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); - return rdata->overlay.vert_len; -} - -static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); - return rdata->overlay.edge_len; -} - -static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_WIRE); - return rdata->wire.vert_len; -} - -static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_WIRE); - return rdata->wire.edge_len; -} - -static int curve_render_data_wire_curve_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_WIRE); - return rdata->wire.curve_len; -} - -static int curve_render_data_normal_len_get(const CurveRenderData *rdata) -{ - BLI_assert(rdata->types & CU_DATATYPE_NORMAL); - return rdata->normal.len; -} - -static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers, - struct GPUMaterial **gpumat_array, - int gpumat_array_len) -{ - for (int i = 0; i < gpumat_array_len; i++) { - struct GPUMaterial *gpumat = gpumat_array[i]; - if (gpumat == NULL) { - continue; - } - - ListBase gpu_attrs = GPU_material_attributes(gpumat); - LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { - const char *name = gpu_attr->name; - int type = gpu_attr->type; - - /* Curves cannot have named layers. - * Note: We could relax this assumption later. */ - if (name[0] != '\0') { - continue; - } - - if (type == CD_AUTO_FROM_NAME) { - type = CD_MTFACE; - } - - switch (type) { - case CD_MTFACE: - *cd_layers |= CD_MASK_MLOOPUV; - break; - case CD_TANGENT: - *cd_layers |= CD_MASK_TANGENT; - break; - case CD_MCOL: - /* Curve object don't have Color data. */ - break; - case CD_ORCO: - *cd_layers |= CD_MASK_ORCO; - break; - } - } - } -} - -/* ---------------------------------------------------------------------- */ -/* Curve GPUBatch Cache */ - -typedef struct CurveBatchCache { - struct { - GPUVertBuf *pos_nor; - GPUVertBuf *edge_fac; - GPUVertBuf *curves_pos; - - GPUVertBuf *loop_pos_nor; - GPUVertBuf *loop_uv; - GPUVertBuf *loop_tan; - } ordered; - - struct { - /* Curve points. Aligned with ordered.pos_nor */ - GPUVertBuf *curves_nor; - GPUVertBuf *curves_weight; /* TODO. */ - /* Edit points (beztriples and bpoints) */ - GPUVertBuf *pos; - GPUVertBuf *data; - } edit; - - struct { - GPUIndexBuf *surfaces_tris; - GPUIndexBuf *surfaces_lines; - GPUIndexBuf *curves_lines; - GPUIndexBuf *edges_adj_lines; - /* Edit mode */ - GPUIndexBuf *edit_verts; - GPUIndexBuf *edit_lines; - } ibo; - - struct { - GPUBatch *surfaces; - GPUBatch *surfaces_edges; - GPUBatch *curves; - /* control handles and vertices */ - GPUBatch *edit_edges; - GPUBatch *edit_verts; - GPUBatch *edit_normals; - GPUBatch *edge_detection; - } batch; - - GPUIndexBuf **surf_per_mat_tris; - GPUBatch **surf_per_mat; - int mat_len; - CustomDataMask cd_used, cd_needed; - - /* settings to determine if cache is invalid */ - bool is_dirty; - bool is_editmode; - - /* Valid only if edge_detection is up to date. */ - bool is_manifold; -} CurveBatchCache; - -/* GPUBatch cache management. */ - -static bool curve_batch_cache_valid(Curve *cu) -{ - CurveBatchCache *cache = cu->batch_cache; - - if (cache == NULL) { - return false; - } - - if (cache->mat_len != DRW_curve_material_count_get(cu)) { - return false; - } - - if (cache->is_dirty) { - return false; - } - - if (cache->is_editmode != ((cu->editnurb != NULL) || (cu->editfont != NULL))) { - return false; - } - - if (cache->is_editmode) { - if (cu->editfont) { - /* TODO */ - } - } - - return true; -} - -static void curve_batch_cache_init(Curve *cu) -{ - CurveBatchCache *cache = cu->batch_cache; - - if (!cache) { - cache = cu->batch_cache = MEM_callocN(sizeof(*cache), __func__); - } - else { - memset(cache, 0, sizeof(*cache)); - } - -#if 0 - ListBase *nurbs; - if (cu->editnurb) { - EditNurb *editnurb = cu->editnurb; - nurbs = &editnurb->nurbs; - } - else { - nurbs = &cu->nurb; - } -#endif - - cache->cd_used = 0; - cache->mat_len = DRW_curve_material_count_get(cu); - cache->surf_per_mat_tris = MEM_callocN(sizeof(*cache->surf_per_mat_tris) * cache->mat_len, - __func__); - cache->surf_per_mat = MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__); - - cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL); - - cache->is_dirty = false; -} - -void DRW_curve_batch_cache_validate(Curve *cu) -{ - if (!curve_batch_cache_valid(cu)) { - curve_batch_cache_clear(cu); - curve_batch_cache_init(cu); - } -} - -static CurveBatchCache *curve_batch_cache_get(Curve *cu) -{ - return cu->batch_cache; -} - -void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode) -{ - CurveBatchCache *cache = cu->batch_cache; - if (cache == NULL) { - return; - } - switch (mode) { - case BKE_CURVE_BATCH_DIRTY_ALL: - cache->is_dirty = true; - break; - case BKE_CURVE_BATCH_DIRTY_SELECT: - GPU_VERTBUF_DISCARD_SAFE(cache->edit.data); - - GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges); - GPU_BATCH_DISCARD_SAFE(cache->batch.edit_verts); - break; - default: - BLI_assert(0); - } -} - -static void curve_batch_cache_clear(Curve *cu) -{ - CurveBatchCache *cache = cu->batch_cache; - if (!cache) { - return; - } - - for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); i++) { - GPUVertBuf **vbo = (GPUVertBuf **)&cache->ordered; - GPU_VERTBUF_DISCARD_SAFE(vbo[i]); - } - for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); i++) { - GPUVertBuf **vbo = (GPUVertBuf **)&cache->edit; - GPU_VERTBUF_DISCARD_SAFE(vbo[i]); - } - for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); i++) { - GPUIndexBuf **ibo = (GPUIndexBuf **)&cache->ibo; - GPU_INDEXBUF_DISCARD_SAFE(ibo[i]); - } - for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { - GPUBatch **batch = (GPUBatch **)&cache->batch; - GPU_BATCH_DISCARD_SAFE(batch[i]); - } - - for (int i = 0; i < cache->mat_len; i++) { - GPU_INDEXBUF_DISCARD_SAFE(cache->surf_per_mat_tris[i]); - GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]); - } - MEM_SAFE_FREE(cache->surf_per_mat_tris); - MEM_SAFE_FREE(cache->surf_per_mat); - cache->mat_len = 0; - cache->cd_used = 0; -} - -void DRW_curve_batch_cache_free(Curve *cu) -{ - curve_batch_cache_clear(cu); - MEM_SAFE_FREE(cu->batch_cache); -} - -/* -------------------------------------------------------------------- */ -/** \name Private Curve Cache API - * \{ */ - -/* GPUBatch cache usage. */ -static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos) -{ - BLI_assert(rdata->ob_curve_cache != NULL); - - static GPUVertFormat format = {0}; - static struct { - uint pos; - } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - - const int vert_len = curve_render_data_wire_verts_len_get(rdata); - GPU_vertbuf_init_with_format(vbo_curves_pos, &format); - GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len); - - int v_idx = 0; - LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) { - if (bl->nr <= 0) { - continue; - } - const int i_end = v_idx + bl->nr; - for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) { - GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec); - } - } - LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) { - if (ELEM(dl->type, DL_SEGM, DL_POLY)) { - for (int i = 0; i < dl->nr; v_idx++, i++) { - GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]); - } - } - } - BLI_assert(v_idx == vert_len); -} - -static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines) -{ - BLI_assert(rdata->ob_curve_cache != NULL); - - const int vert_len = curve_render_data_wire_verts_len_get(rdata); - const int edge_len = curve_render_data_wire_edges_len_get(rdata); - const int curve_len = curve_render_data_wire_curve_len_get(rdata); - /* Count the last vertex or each strip and the primitive restart. */ - const int index_len = edge_len + curve_len * 2; - - GPUIndexBufBuilder elb; - GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len); - - int v_idx = 0; - LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) { - if (bl->nr <= 0) { - continue; - } - const bool is_cyclic = bl->poly != -1; - if (is_cyclic) { - GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1)); - } - for (int i = 0; i < bl->nr; i++) { - GPU_indexbuf_add_generic_vert(&elb, v_idx + i); - } - GPU_indexbuf_add_primitive_restart(&elb); - v_idx += bl->nr; - } - LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) { - if (ELEM(dl->type, DL_SEGM, DL_POLY)) { - const bool is_cyclic = dl->type == DL_POLY; - if (is_cyclic) { - GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1)); - } - for (int i = 0; i < dl->nr; i++) { - GPU_indexbuf_add_generic_vert(&elb, v_idx + i); - } - GPU_indexbuf_add_primitive_restart(&elb); - v_idx += dl->nr; - } - } - GPU_indexbuf_build_in_place(&elb, ibo_curve_lines); -} - -static void curve_create_edit_curves_nor(CurveRenderData *rdata, - GPUVertBuf *vbo_curves_nor, - const Scene *scene) -{ - const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 || - GPU_use_hq_normals_workaround(); - - static GPUVertFormat format = {0}; - static GPUVertFormat format_hq = {0}; - static struct { - uint pos, nor, tan, rad; - uint pos_hq, nor_hq, tan_hq, rad_hq; - } attr_id; - if (format.attr_len == 0) { - /* initialize vertex formats */ - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - attr_id.rad = GPU_vertformat_attr_add(&format, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - attr_id.nor = GPU_vertformat_attr_add( - &format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - attr_id.tan = GPU_vertformat_attr_add( - &format, "tan", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - - attr_id.pos_hq = GPU_vertformat_attr_add(&format_hq, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - attr_id.rad_hq = GPU_vertformat_attr_add(&format_hq, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - attr_id.nor_hq = GPU_vertformat_attr_add( - &format_hq, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - attr_id.tan_hq = GPU_vertformat_attr_add( - &format_hq, "tan", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - - const GPUVertFormat *format_ptr = do_hq_normals ? &format_hq : &format; - - int verts_len_capacity = curve_render_data_normal_len_get(rdata) * 2; - int vbo_len_used = 0; - - GPU_vertbuf_init_with_format(vbo_curves_nor, format_ptr); - GPU_vertbuf_data_alloc(vbo_curves_nor, verts_len_capacity); - - const BevList *bl; - const Nurb *nu; - - const uint pos_id = do_hq_normals ? attr_id.pos_hq : attr_id.pos; - const uint nor_id = do_hq_normals ? attr_id.nor_hq : attr_id.nor; - const uint tan_id = do_hq_normals ? attr_id.tan_hq : attr_id.tan; - const uint rad_id = do_hq_normals ? attr_id.rad_hq : attr_id.rad; - - for (bl = rdata->ob_curve_cache->bev.first, nu = rdata->nurbs->first; nu && bl; - bl = bl->next, nu = nu->next) { - const BevPoint *bevp = bl->bevpoints; - int nr = bl->nr; - int skip = nu->resolu / 16; - - while (nr-- > 0) { /* accounts for empty bevel lists */ - float nor[3] = {1.0f, 0.0f, 0.0f}; - mul_qt_v3(bevp->quat, nor); - - GPUNormal pnor; - GPUNormal ptan; - GPU_normal_convert_v3(&pnor, nor, do_hq_normals); - GPU_normal_convert_v3(&ptan, bevp->dir, do_hq_normals); - /* Only set attributes for one vertex. */ - GPU_vertbuf_attr_set(vbo_curves_nor, pos_id, vbo_len_used, bevp->vec); - GPU_vertbuf_attr_set(vbo_curves_nor, rad_id, vbo_len_used, &bevp->radius); - GPU_vertbuf_attr_set(vbo_curves_nor, nor_id, vbo_len_used, &pnor); - GPU_vertbuf_attr_set(vbo_curves_nor, tan_id, vbo_len_used, &ptan); - vbo_len_used++; - - /* Skip the other vertex (it does not need to be offsetted). */ - GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec); - vbo_len_used++; - - bevp += skip + 1; - nr -= skip; - } - } - BLI_assert(vbo_len_used == verts_len_capacity); -} - -static uint8_t beztriple_vflag_get(CurveRenderData *rdata, - uint8_t flag, - uint8_t col_id, - int v_idx, - int nu_id, - bool handle_point, - const bool handle_selected) -{ - uint8_t vflag = 0; - SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); - SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); - SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); - SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); - SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); - /* Setting flags that overlap with will cause the color id not to work properly. */ - BLI_assert((vflag >> COLOR_SHIFT) == 0); - /* handle color id */ - vflag |= col_id << COLOR_SHIFT; - return vflag; -} - -static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u) -{ - uint8_t vflag = 0; - SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); - SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); - SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); - SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT); - /* Setting flags that overlap with will cause the color id not to work properly. */ - BLI_assert((vflag >> COLOR_SHIFT) == 0); - vflag |= COLOR_NURB_ULINE_ID << COLOR_SHIFT; - return vflag; -} - -static void curve_create_edit_data_and_handles(CurveRenderData *rdata, - GPUVertBuf *vbo_pos, - GPUVertBuf *vbo_data, - GPUIndexBuf *ibo_edit_verts_points, - GPUIndexBuf *ibo_edit_lines) -{ - static GPUVertFormat format_pos = {0}; - static GPUVertFormat format_data = {0}; - static struct { - uint pos, data; - } attr_id; - if (format_pos.attr_len == 0) { - /* initialize vertex formats */ - attr_id.pos = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - attr_id.data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT); - } - - int verts_len_capacity = curve_render_data_overlay_verts_len_get(rdata); - int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2; - int vbo_len_used = 0; - - if (DRW_TEST_ASSIGN_VBO(vbo_pos)) { - GPU_vertbuf_init_with_format(vbo_pos, &format_pos); - GPU_vertbuf_data_alloc(vbo_pos, verts_len_capacity); - } - if (DRW_TEST_ASSIGN_VBO(vbo_data)) { - GPU_vertbuf_init_with_format(vbo_data, &format_data); - GPU_vertbuf_data_alloc(vbo_data, verts_len_capacity); - } - - GPUIndexBufBuilder elb_verts, *elbp_verts = NULL; - GPUIndexBufBuilder elb_lines, *elbp_lines = NULL; - if (DRW_TEST_ASSIGN_IBO(ibo_edit_verts_points)) { - elbp_verts = &elb_verts; - GPU_indexbuf_init(elbp_verts, GPU_PRIM_POINTS, verts_len_capacity, verts_len_capacity); - } - if (DRW_TEST_ASSIGN_IBO(ibo_edit_lines)) { - elbp_lines = &elb_lines; - GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity); - } - - int nu_id = 0; - for (Nurb *nu = rdata->nurbs->first; nu; nu = nu->next, nu_id++) { - const BezTriple *bezt = nu->bezt; - const BPoint *bp = nu->bp; - - if (bezt) { - for (int a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->hide == true) { - continue; - } - const bool handle_selected = BEZT_ISSEL_ANY(bezt); - - if (elbp_verts) { - GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0); - GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 1); - GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 2); - } - if (elbp_lines) { - GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 0); - GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 2); - } - if (vbo_data) { - const uint8_t vflag[3] = { - beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected), - beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected), - beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected), - }; - for (int j = 0; j < 3; j++) { - GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]); - } - } - if (vbo_pos) { - for (int j = 0; j < 3; j++) { - GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used + j, bezt->vec[j]); - } - } - vbo_len_used += 3; - } - } - else if (bp) { - int pt_len = nu->pntsu * nu->pntsv; - for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) { - if (bp->hide == true) { - continue; - } - int u = (a % nu->pntsu); - int v = (a / nu->pntsu); - /* Use indexed rendering for bezier. - * Specify all points and use indices to hide/show. */ - if (elbp_verts) { - GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used); - } - if (elbp_lines) { - const BPoint *bp_next_u = (u < (nu->pntsu - 1)) ? &nu->bp[a + 1] : NULL; - const BPoint *bp_next_v = (v < (nu->pntsv - 1)) ? &nu->bp[a + nu->pntsu] : NULL; - if (bp_next_u && (bp_next_u->hide == false)) { - GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + 1); - } - if (bp_next_v && (bp_next_v->hide == false)) { - GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + nu->pntsu); - } - } - if (vbo_data) { - uint8_t vflag = bpoint_vflag_get(rdata, bp->f1, a, nu_id, u); - GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used, &vflag); - } - if (vbo_pos) { - GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec); - } - } - } - } - - /* Resize & Finish */ - if (elbp_verts != NULL) { - GPU_indexbuf_build_in_place(elbp_verts, ibo_edit_verts_points); - } - if (elbp_lines != NULL) { - GPU_indexbuf_build_in_place(elbp_lines, ibo_edit_lines); - } - if (vbo_len_used != verts_len_capacity) { - if (vbo_pos != NULL) { - GPU_vertbuf_data_resize(vbo_pos, vbo_len_used); - } - if (vbo_data != NULL) { - GPU_vertbuf_data_resize(vbo_data, vbo_len_used); - } - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Public Object/Curve API - * \{ */ - -GPUBatch *DRW_curve_batch_cache_get_wire_edge(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.curves); -} - -GPUBatch *DRW_curve_batch_cache_get_normal_edge(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.edit_normals); -} - -GPUBatch *DRW_curve_batch_cache_get_edit_edges(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.edit_edges); -} - -GPUBatch *DRW_curve_batch_cache_get_edit_verts(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.edit_verts); -} - -GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.surfaces); -} - -GPUBatch **DRW_curve_batch_cache_get_surface_shaded(struct Curve *cu, - struct GPUMaterial **gpumat_array, - uint gpumat_array_len) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - - BLI_assert(gpumat_array_len == cache->mat_len); - - curve_cd_calc_used_gpu_layers(&cache->cd_needed, gpumat_array, gpumat_array_len); - - for (int i = 0; i < cache->mat_len; i++) { - DRW_batch_request(&cache->surf_per_mat[i]); - } - return cache->surf_per_mat; -} - -GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ - DRW_batch_request(&cache->batch.surfaces); - - DRW_vbo_request(NULL, &cache->ordered.loop_pos_nor); - return cache->ordered.loop_pos_nor; -} - -GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - return DRW_batch_request(&cache->batch.surfaces_edges); -} - -GPUBatch *DRW_curve_batch_cache_get_edge_detection(Curve *cu, bool *r_is_manifold) -{ - CurveBatchCache *cache = curve_batch_cache_get(cu); - /* Even if is_manifold is not correct (not updated), - * the default (not manifold) is just the worst case. */ - if (r_is_manifold) { - *r_is_manifold = cache->is_manifold; - } - return DRW_batch_request(&cache->batch.edge_detection); -} - -int DRW_curve_material_count_get(Curve *cu) -{ - return max_ii(1, cu->totcol); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Grouped batch generation - * \{ */ - -void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scene) -{ - BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)); - - Curve *cu = ob->data; - CurveBatchCache *cache = curve_batch_cache_get(cu); - - /* Verify that all surface batches have needed attribute layers. */ - /* TODO(fclem): We could be a bit smarter here and only do it per material. */ - if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) { - for (int i = 0; i < cache->mat_len; i++) { - /* We can't discard batches at this point as they have been - * referenced for drawing. Just clear them in place. */ - GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); - } - - cache->cd_used |= cache->cd_needed; - cache->cd_needed = 0; - } - - /* Init batches and request VBOs & IBOs */ - if (DRW_batch_requested(cache->batch.surfaces, GPU_PRIM_TRIS)) { - DRW_vbo_request(cache->batch.surfaces, &cache->ordered.loop_pos_nor); - } - if (DRW_batch_requested(cache->batch.surfaces_edges, GPU_PRIM_LINES)) { - DRW_ibo_request(cache->batch.surfaces_edges, &cache->ibo.surfaces_lines); - DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.pos_nor); - DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.edge_fac); - } - if (DRW_batch_requested(cache->batch.curves, GPU_PRIM_LINE_STRIP)) { - DRW_ibo_request(cache->batch.curves, &cache->ibo.curves_lines); - DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos); - } - if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) { - DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines); - DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor); - } - - /* Edit mode */ - if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) { - DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_lines); - DRW_vbo_request(cache->batch.edit_edges, &cache->edit.pos); - DRW_vbo_request(cache->batch.edit_edges, &cache->edit.data); - } - if (DRW_batch_requested(cache->batch.edit_verts, GPU_PRIM_POINTS)) { - DRW_ibo_request(cache->batch.edit_verts, &cache->ibo.edit_verts); - DRW_vbo_request(cache->batch.edit_verts, &cache->edit.pos); - DRW_vbo_request(cache->batch.edit_verts, &cache->edit.data); - } - if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) { - DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor); - } - for (int i = 0; i < cache->mat_len; i++) { - if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { - if (cache->mat_len > 1) { - DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); - } - if (cache->cd_used & CD_MASK_MLOOPUV) { - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_uv); - } - if (cache->cd_used & CD_MASK_TANGENT) { - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_tan); - } - DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_pos_nor); - } - } - -#ifdef DRW_DEBUG_MESH_CACHE_REQUEST - printf("-- %s %s --\n", __func__, ob->id.name + 2); -#endif - - /* Generate MeshRenderData flags */ - int mr_flag = 0; - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.edge_fac, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_tan, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_tris, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_lines, CU_DATATYPE_SURFACE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edges_adj_lines, CU_DATATYPE_SURFACE); - - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.pos, CU_DATATYPE_OVERLAY); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.data, CU_DATATYPE_OVERLAY); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_nor, CU_DATATYPE_NORMAL); - DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_weight, CU_DATATYPE_OVERLAY); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts, CU_DATATYPE_OVERLAY); - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVERLAY); - - for (int i = 0; i < cache->mat_len; i++) { - DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], CU_DATATYPE_SURFACE); - } - -#ifdef DRW_DEBUG_MESH_CACHE_REQUEST - printf(" mr_flag %d\n\n", mr_flag); -#endif - - CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag); - - /* DispLists */ - ListBase *lb = &rdata->ob_curve_cache->disp; - - /* Generate VBOs */ - if (DRW_vbo_requested(cache->ordered.pos_nor)) { - DRW_displist_vertbuf_create_pos_and_nor(lb, cache->ordered.pos_nor, scene); - } - if (DRW_vbo_requested(cache->ordered.edge_fac)) { - DRW_displist_vertbuf_create_wiredata(lb, cache->ordered.edge_fac); - } - if (DRW_vbo_requested(cache->ordered.curves_pos)) { - curve_create_curves_pos(rdata, cache->ordered.curves_pos); - } - - if (DRW_vbo_requested(cache->ordered.loop_pos_nor) || - DRW_vbo_requested(cache->ordered.loop_uv) || DRW_vbo_requested(cache->ordered.loop_tan)) { - DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan( - lb, cache->ordered.loop_pos_nor, cache->ordered.loop_uv, cache->ordered.loop_tan, scene); - } - - if (DRW_ibo_requested(cache->surf_per_mat_tris[0])) { - DRW_displist_indexbuf_create_triangles_loop_split_by_material( - lb, cache->surf_per_mat_tris, cache->mat_len); - } - - if (DRW_ibo_requested(cache->ibo.curves_lines)) { - curve_create_curves_lines(rdata, cache->ibo.curves_lines); - } - if (DRW_ibo_requested(cache->ibo.surfaces_tris)) { - DRW_displist_indexbuf_create_triangles_in_order(lb, cache->ibo.surfaces_tris); - } - if (DRW_ibo_requested(cache->ibo.surfaces_lines)) { - DRW_displist_indexbuf_create_lines_in_order(lb, cache->ibo.surfaces_lines); - } - if (DRW_ibo_requested(cache->ibo.edges_adj_lines)) { - DRW_displist_indexbuf_create_edges_adjacency_lines( - lb, cache->ibo.edges_adj_lines, &cache->is_manifold); - } - - if (DRW_vbo_requested(cache->edit.pos) || DRW_vbo_requested(cache->edit.data) || - DRW_ibo_requested(cache->ibo.edit_verts) || DRW_ibo_requested(cache->ibo.edit_lines)) { - curve_create_edit_data_and_handles( - rdata, cache->edit.pos, cache->edit.data, cache->ibo.edit_verts, cache->ibo.edit_lines); - } - if (DRW_vbo_requested(cache->edit.curves_nor)) { - curve_create_edit_curves_nor(rdata, cache->edit.curves_nor, scene); - } - - curve_render_data_free(rdata); - -#ifdef DEBUG - /* Make sure all requested batches have been setup. */ - for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { - BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); - } -#endif -} - -/** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc new file mode 100644 index 00000000000..223b44724b6 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_curve.cc @@ -0,0 +1,1131 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 by Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup draw + * + * \brief Curve API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math_vector.h" +#include "BLI_utildefines.h" + +#include "DNA_curve_types.h" + +#include "BKE_curve.h" +#include "BKE_displist.h" +#include "BKE_font.h" + +#include "GPU_batch.h" +#include "GPU_capabilities.h" +#include "GPU_material.h" +#include "GPU_texture.h" + +#include "UI_resources.h" + +#include "DRW_render.h" + +#include "draw_cache_inline.h" + +#include "draw_cache_impl.h" /* own include */ + +/* See: edit_curve_point_vert.glsl for duplicate includes. */ +#define SELECT 1 +#define ACTIVE_NURB (1 << 2) +#define BEZIER_HANDLE (1 << 3) +#define EVEN_U_BIT (1 << 4) /* Alternate this bit for every U vert. */ +#define COLOR_SHIFT 5 + +/* Used as values of `color_id` in `edit_curve_overlay_handle_geom.glsl` */ +enum { + COLOR_NURB_ULINE_ID = TH_HANDLE_AUTOCLAMP - TH_HANDLE_FREE + 2, + + TOT_HANDLE_COL, +}; + +/** + * TODO + * - Ensure `CurveCache`, `SEQUENCER_DAG_WORKAROUND`. + * - Check number of verts/edges to see if cache is valid. + * - Check if 'overlay.edges' can use single attribute per edge, not 2 (for selection drawing). + */ + +static void curve_batch_cache_clear(Curve *cu); + +/* ---------------------------------------------------------------------- */ +/* Curve Interface, direct access to basic data. */ + +static void curve_render_overlay_verts_edges_len_get(ListBase *lb, + int *r_vert_len, + int *r_edge_len) +{ + BLI_assert(r_vert_len || r_edge_len); + int vert_len = 0; + int edge_len = 0; + LISTBASE_FOREACH (Nurb *, nu, lb) { + if (nu->bezt) { + vert_len += nu->pntsu * 3; + /* 2x handles per point*/ + edge_len += 2 * nu->pntsu; + } + else if (nu->bp) { + vert_len += nu->pntsu * nu->pntsv; + /* segments between points */ + edge_len += (nu->pntsu - 1) * nu->pntsv; + edge_len += (nu->pntsv - 1) * nu->pntsu; + } + } + if (r_vert_len) { + *r_vert_len = vert_len; + } + if (r_edge_len) { + *r_edge_len = edge_len; + } +} + +static void curve_render_wire_verts_edges_len_get(const CurveCache *ob_curve_cache, + int *r_curve_len, + int *r_vert_len, + int *r_edge_len) +{ + BLI_assert(r_vert_len || r_edge_len); + int vert_len = 0; + int edge_len = 0; + int curve_len = 0; + LISTBASE_FOREACH (const BevList *, bl, &ob_curve_cache->bev) { + if (bl->nr > 0) { + const bool is_cyclic = bl->poly != -1; + edge_len += (is_cyclic) ? bl->nr : bl->nr - 1; + vert_len += bl->nr; + curve_len += 1; + } + } + LISTBASE_FOREACH (const DispList *, dl, &ob_curve_cache->disp) { + if (ELEM(dl->type, DL_SEGM, DL_POLY)) { + BLI_assert(dl->parts == 1); + const bool is_cyclic = dl->type == DL_POLY; + edge_len += (is_cyclic) ? dl->nr : dl->nr - 1; + vert_len += dl->nr; + curve_len += 1; + } + } + if (r_vert_len) { + *r_vert_len = vert_len; + } + if (r_edge_len) { + *r_edge_len = edge_len; + } + if (r_curve_len) { + *r_curve_len = curve_len; + } +} + +static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache) +{ + int normal_len = 0; + const BevList *bl; + const Nurb *nu; + for (bl = (const BevList *)ob_curve_cache->bev.first, nu = (const Nurb *)lb->first; nu && bl; + bl = bl->next, nu = nu->next) { + int nr = bl->nr; + int skip = nu->resolu / 16; +#if 0 + while (nr-- > 0) { /* accounts for empty bevel lists */ + normal_len += 1; + nr -= skip; + } +#else + /* Same as loop above */ + normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0); +#endif + } + return normal_len; +} + +/* ---------------------------------------------------------------------- */ +/* Curve Interface, indirect, partially cached access to complex data. */ + +struct CurveRenderData { + int types; + + struct { + int vert_len; + int edge_len; + } overlay; + + struct { + int curve_len; + int vert_len; + int edge_len; + } wire; + + /* edit mode normal's */ + struct { + /* 'edge_len == len * 2' + * 'vert_len == len * 3' */ + int len; + } normal; + + struct { + EditFont *edit_font; + } text; + + /* borrow from 'Object' */ + CurveCache *ob_curve_cache; + + /* borrow from 'Curve' */ + ListBase *nurbs; + + /* edit, index in nurb list */ + int actnu; + /* edit, index in active nurb (BPoint or BezTriple) */ + int actvert; +}; + +enum { + /* Wire center-line */ + CU_DATATYPE_WIRE = 1 << 0, + /* Edit-mode verts and optionally handles */ + CU_DATATYPE_OVERLAY = 1 << 1, + /* Edit-mode normals */ + CU_DATATYPE_NORMAL = 1 << 2, + /* Geometry */ + CU_DATATYPE_SURFACE = 1 << 3, + /* Text */ + CU_DATATYPE_TEXT_SELECT = 1 << 4, +}; + +/* + * ob_curve_cache can be NULL, only needed for CU_DATATYPE_WIRE + */ +static CurveRenderData *curve_render_data_create(Curve *cu, + CurveCache *ob_curve_cache, + const int types) +{ + CurveRenderData *rdata = (CurveRenderData *)MEM_callocN(sizeof(*rdata), __func__); + rdata->types = types; + ListBase *nurbs; + + rdata->actnu = cu->actnu; + rdata->actvert = cu->actvert; + + rdata->ob_curve_cache = ob_curve_cache; + + if (types & CU_DATATYPE_WIRE) { + curve_render_wire_verts_edges_len_get(rdata->ob_curve_cache, + &rdata->wire.curve_len, + &rdata->wire.vert_len, + &rdata->wire.edge_len); + } + + if (cu->editnurb) { + EditNurb *editnurb = cu->editnurb; + nurbs = &editnurb->nurbs; + + if (types & CU_DATATYPE_OVERLAY) { + curve_render_overlay_verts_edges_len_get( + nurbs, &rdata->overlay.vert_len, &rdata->overlay.edge_len); + + rdata->actnu = cu->actnu; + rdata->actvert = cu->actvert; + } + if (types & CU_DATATYPE_NORMAL) { + rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache); + } + } + else { + nurbs = &cu->nurb; + } + + rdata->nurbs = nurbs; + + rdata->text.edit_font = cu->editfont; + + return rdata; +} + +static void curve_render_data_free(CurveRenderData *rdata) +{ +#if 0 + if (rdata->loose_verts) { + MEM_freeN(rdata->loose_verts); + } +#endif + MEM_freeN(rdata); +} + +static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); + return rdata->overlay.vert_len; +} + +static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_OVERLAY); + return rdata->overlay.edge_len; +} + +static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + return rdata->wire.vert_len; +} + +static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + return rdata->wire.edge_len; +} + +static int curve_render_data_wire_curve_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_WIRE); + return rdata->wire.curve_len; +} + +static int curve_render_data_normal_len_get(const CurveRenderData *rdata) +{ + BLI_assert(rdata->types & CU_DATATYPE_NORMAL); + return rdata->normal.len; +} + +static void curve_cd_calc_used_gpu_layers(CustomDataMask *cd_layers, + struct GPUMaterial **gpumat_array, + int gpumat_array_len) +{ + for (int i = 0; i < gpumat_array_len; i++) { + struct GPUMaterial *gpumat = gpumat_array[i]; + if (gpumat == nullptr) { + continue; + } + + ListBase gpu_attrs = GPU_material_attributes(gpumat); + LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { + const char *name = gpu_attr->name; + int type = gpu_attr->type; + + /* Curves cannot have named layers. + * Note: We could relax this assumption later. */ + if (name[0] != '\0') { + continue; + } + + if (type == CD_AUTO_FROM_NAME) { + type = CD_MTFACE; + } + + switch (type) { + case CD_MTFACE: + *cd_layers |= CD_MASK_MLOOPUV; + break; + case CD_TANGENT: + *cd_layers |= CD_MASK_TANGENT; + break; + case CD_MCOL: + /* Curve object don't have Color data. */ + break; + case CD_ORCO: + *cd_layers |= CD_MASK_ORCO; + break; + } + } + } +} + +/* ---------------------------------------------------------------------- */ +/* Curve GPUBatch Cache */ + +struct CurveBatchCache { + struct { + GPUVertBuf *pos_nor; + GPUVertBuf *edge_fac; + GPUVertBuf *curves_pos; + + GPUVertBuf *loop_pos_nor; + GPUVertBuf *loop_uv; + GPUVertBuf *loop_tan; + } ordered; + + struct { + /* Curve points. Aligned with ordered.pos_nor */ + GPUVertBuf *curves_nor; + GPUVertBuf *curves_weight; /* TODO. */ + /* Edit points (beztriples and bpoints) */ + GPUVertBuf *pos; + GPUVertBuf *data; + } edit; + + struct { + GPUIndexBuf *surfaces_tris; + GPUIndexBuf *surfaces_lines; + GPUIndexBuf *curves_lines; + GPUIndexBuf *edges_adj_lines; + /* Edit mode */ + GPUIndexBuf *edit_verts; + GPUIndexBuf *edit_lines; + } ibo; + + struct { + GPUBatch *surfaces; + GPUBatch *surfaces_edges; + GPUBatch *curves; + /* control handles and vertices */ + GPUBatch *edit_edges; + GPUBatch *edit_verts; + GPUBatch *edit_normals; + GPUBatch *edge_detection; + } batch; + + GPUIndexBuf **surf_per_mat_tris; + GPUBatch **surf_per_mat; + int mat_len; + CustomDataMask cd_used, cd_needed; + + /* settings to determine if cache is invalid */ + bool is_dirty; + bool is_editmode; + + /* Valid only if edge_detection is up to date. */ + bool is_manifold; +}; + +/* GPUBatch cache management. */ + +static bool curve_batch_cache_valid(Curve *cu) +{ + CurveBatchCache *cache = (CurveBatchCache *)cu->batch_cache; + + if (cache == nullptr) { + return false; + } + + if (cache->mat_len != DRW_curve_material_count_get(cu)) { + return false; + } + + if (cache->is_dirty) { + return false; + } + + if (cache->is_editmode != ((cu->editnurb != nullptr) || (cu->editfont != nullptr))) { + return false; + } + + if (cache->is_editmode) { + if (cu->editfont) { + /* TODO */ + } + } + + return true; +} + +static void curve_batch_cache_init(Curve *cu) +{ + CurveBatchCache *cache = (CurveBatchCache *)cu->batch_cache; + + if (!cache) { + cache = (CurveBatchCache *)MEM_callocN(sizeof(*cache), __func__); + cu->batch_cache = cache; + } + else { + memset(cache, 0, sizeof(*cache)); + } + +#if 0 + ListBase *nurbs; + if (cu->editnurb) { + EditNurb *editnurb = cu->editnurb; + nurbs = &editnurb->nurbs; + } + else { + nurbs = &cu->nurb; + } +#endif + + cache->cd_used = 0; + cache->mat_len = DRW_curve_material_count_get(cu); + cache->surf_per_mat_tris = (GPUIndexBuf **)MEM_callocN( + sizeof(*cache->surf_per_mat_tris) * cache->mat_len, __func__); + cache->surf_per_mat = (GPUBatch **)MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, + __func__); + + cache->is_editmode = (cu->editnurb != nullptr) || (cu->editfont != nullptr); + + cache->is_dirty = false; +} + +void DRW_curve_batch_cache_validate(Curve *cu) +{ + if (!curve_batch_cache_valid(cu)) { + curve_batch_cache_clear(cu); + curve_batch_cache_init(cu); + } +} + +static CurveBatchCache *curve_batch_cache_get(Curve *cu) +{ + return (CurveBatchCache *)cu->batch_cache; +} + +void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode) +{ + CurveBatchCache *cache = (CurveBatchCache *)cu->batch_cache; + if (cache == nullptr) { + return; + } + switch (mode) { + case BKE_CURVE_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + case BKE_CURVE_BATCH_DIRTY_SELECT: + GPU_VERTBUF_DISCARD_SAFE(cache->edit.data); + + GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges); + GPU_BATCH_DISCARD_SAFE(cache->batch.edit_verts); + break; + default: + BLI_assert(0); + } +} + +static void curve_batch_cache_clear(Curve *cu) +{ + CurveBatchCache *cache = (CurveBatchCache *)cu->batch_cache; + if (!cache) { + return; + } + + for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); i++) { + GPUVertBuf **vbo = (GPUVertBuf **)&cache->ordered; + GPU_VERTBUF_DISCARD_SAFE(vbo[i]); + } + for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); i++) { + GPUVertBuf **vbo = (GPUVertBuf **)&cache->edit; + GPU_VERTBUF_DISCARD_SAFE(vbo[i]); + } + for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); i++) { + GPUIndexBuf **ibo = (GPUIndexBuf **)&cache->ibo; + GPU_INDEXBUF_DISCARD_SAFE(ibo[i]); + } + for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { + GPUBatch **batch = (GPUBatch **)&cache->batch; + GPU_BATCH_DISCARD_SAFE(batch[i]); + } + + for (int i = 0; i < cache->mat_len; i++) { + GPU_INDEXBUF_DISCARD_SAFE(cache->surf_per_mat_tris[i]); + GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]); + } + MEM_SAFE_FREE(cache->surf_per_mat_tris); + MEM_SAFE_FREE(cache->surf_per_mat); + cache->mat_len = 0; + cache->cd_used = 0; +} + +void DRW_curve_batch_cache_free(Curve *cu) +{ + curve_batch_cache_clear(cu); + MEM_SAFE_FREE(cu->batch_cache); +} + +/* -------------------------------------------------------------------- */ +/** \name Private Curve Cache API + * \{ */ + +/* GPUBatch cache usage. */ +static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos) +{ + BLI_assert(rdata->ob_curve_cache != nullptr); + + static GPUVertFormat format = {0}; + static struct { + uint pos; + } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + + const int vert_len = curve_render_data_wire_verts_len_get(rdata); + GPU_vertbuf_init_with_format(vbo_curves_pos, &format); + GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len); + + int v_idx = 0; + LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) { + if (bl->nr <= 0) { + continue; + } + const int i_end = v_idx + bl->nr; + for (const BevPoint *bevp = bl->bevpoints; v_idx < i_end; v_idx++, bevp++) { + GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, bevp->vec); + } + } + LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) { + if (ELEM(dl->type, DL_SEGM, DL_POLY)) { + for (int i = 0; i < dl->nr; v_idx++, i++) { + GPU_vertbuf_attr_set(vbo_curves_pos, attr_id.pos, v_idx, &((float(*)[3])dl->verts)[i]); + } + } + } + BLI_assert(v_idx == vert_len); +} + +static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines) +{ + BLI_assert(rdata->ob_curve_cache != nullptr); + + const int vert_len = curve_render_data_wire_verts_len_get(rdata); + const int edge_len = curve_render_data_wire_edges_len_get(rdata); + const int curve_len = curve_render_data_wire_curve_len_get(rdata); + /* Count the last vertex or each strip and the primitive restart. */ + const int index_len = edge_len + curve_len * 2; + + GPUIndexBufBuilder elb; + GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len); + + int v_idx = 0; + LISTBASE_FOREACH (const BevList *, bl, &rdata->ob_curve_cache->bev) { + if (bl->nr <= 0) { + continue; + } + const bool is_cyclic = bl->poly != -1; + if (is_cyclic) { + GPU_indexbuf_add_generic_vert(&elb, v_idx + (bl->nr - 1)); + } + for (int i = 0; i < bl->nr; i++) { + GPU_indexbuf_add_generic_vert(&elb, v_idx + i); + } + GPU_indexbuf_add_primitive_restart(&elb); + v_idx += bl->nr; + } + LISTBASE_FOREACH (const DispList *, dl, &rdata->ob_curve_cache->disp) { + if (ELEM(dl->type, DL_SEGM, DL_POLY)) { + const bool is_cyclic = dl->type == DL_POLY; + if (is_cyclic) { + GPU_indexbuf_add_generic_vert(&elb, v_idx + (dl->nr - 1)); + } + for (int i = 0; i < dl->nr; i++) { + GPU_indexbuf_add_generic_vert(&elb, v_idx + i); + } + GPU_indexbuf_add_primitive_restart(&elb); + v_idx += dl->nr; + } + } + GPU_indexbuf_build_in_place(&elb, ibo_curve_lines); +} + +static void curve_create_edit_curves_nor(CurveRenderData *rdata, + GPUVertBuf *vbo_curves_nor, + const Scene *scene) +{ + const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 || + GPU_use_hq_normals_workaround(); + + static GPUVertFormat format = {0}; + static GPUVertFormat format_hq = {0}; + static struct { + uint pos, nor, tan, rad; + uint pos_hq, nor_hq, tan_hq, rad_hq; + } attr_id; + if (format.attr_len == 0) { + /* initialize vertex formats */ + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + attr_id.rad = GPU_vertformat_attr_add(&format, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + attr_id.nor = GPU_vertformat_attr_add( + &format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + attr_id.tan = GPU_vertformat_attr_add( + &format, "tan", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + + attr_id.pos_hq = GPU_vertformat_attr_add(&format_hq, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + attr_id.rad_hq = GPU_vertformat_attr_add(&format_hq, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + attr_id.nor_hq = GPU_vertformat_attr_add( + &format_hq, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + attr_id.tan_hq = GPU_vertformat_attr_add( + &format_hq, "tan", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + + const GPUVertFormat *format_ptr = do_hq_normals ? &format_hq : &format; + + int verts_len_capacity = curve_render_data_normal_len_get(rdata) * 2; + int vbo_len_used = 0; + + GPU_vertbuf_init_with_format(vbo_curves_nor, format_ptr); + GPU_vertbuf_data_alloc(vbo_curves_nor, verts_len_capacity); + + const BevList *bl; + const Nurb *nu; + + const uint pos_id = do_hq_normals ? attr_id.pos_hq : attr_id.pos; + const uint nor_id = do_hq_normals ? attr_id.nor_hq : attr_id.nor; + const uint tan_id = do_hq_normals ? attr_id.tan_hq : attr_id.tan; + const uint rad_id = do_hq_normals ? attr_id.rad_hq : attr_id.rad; + + for (bl = (const BevList *)rdata->ob_curve_cache->bev.first, + nu = (const Nurb *)rdata->nurbs->first; + nu && bl; + bl = bl->next, nu = nu->next) { + const BevPoint *bevp = bl->bevpoints; + int nr = bl->nr; + int skip = nu->resolu / 16; + + while (nr-- > 0) { /* accounts for empty bevel lists */ + float nor[3] = {1.0f, 0.0f, 0.0f}; + mul_qt_v3(bevp->quat, nor); + + GPUNormal pnor; + GPUNormal ptan; + GPU_normal_convert_v3(&pnor, nor, do_hq_normals); + GPU_normal_convert_v3(&ptan, bevp->dir, do_hq_normals); + /* Only set attributes for one vertex. */ + GPU_vertbuf_attr_set(vbo_curves_nor, pos_id, vbo_len_used, bevp->vec); + GPU_vertbuf_attr_set(vbo_curves_nor, rad_id, vbo_len_used, &bevp->radius); + GPU_vertbuf_attr_set(vbo_curves_nor, nor_id, vbo_len_used, &pnor); + GPU_vertbuf_attr_set(vbo_curves_nor, tan_id, vbo_len_used, &ptan); + vbo_len_used++; + + /* Skip the other vertex (it does not need to be offsetted). */ + GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec); + vbo_len_used++; + + bevp += skip + 1; + nr -= skip; + } + } + BLI_assert(vbo_len_used == verts_len_capacity); +} + +static uint8_t beztriple_vflag_get(CurveRenderData *rdata, + uint8_t flag, + uint8_t col_id, + int v_idx, + int nu_id, + bool handle_point, + const bool handle_selected) +{ + uint8_t vflag = 0; + SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); + SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); + SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); + SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE); + SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE); + /* Setting flags that overlap with will cause the color id not to work properly. */ + BLI_assert((vflag >> COLOR_SHIFT) == 0); + /* handle color id */ + vflag |= col_id << COLOR_SHIFT; + return vflag; +} + +static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u) +{ + uint8_t vflag = 0; + SET_FLAG_FROM_TEST(vflag, (flag & SELECT), VFLAG_VERT_SELECTED); + SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE); + SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB); + SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT); + /* Setting flags that overlap with will cause the color id not to work properly. */ + BLI_assert((vflag >> COLOR_SHIFT) == 0); + vflag |= COLOR_NURB_ULINE_ID << COLOR_SHIFT; + return vflag; +} + +static void curve_create_edit_data_and_handles(CurveRenderData *rdata, + GPUVertBuf *vbo_pos, + GPUVertBuf *vbo_data, + GPUIndexBuf *ibo_edit_verts_points, + GPUIndexBuf *ibo_edit_lines) +{ + static GPUVertFormat format_pos = {0}; + static GPUVertFormat format_data = {0}; + static struct { + uint pos, data; + } attr_id; + if (format_pos.attr_len == 0) { + /* initialize vertex formats */ + attr_id.pos = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + attr_id.data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT); + } + + int verts_len_capacity = curve_render_data_overlay_verts_len_get(rdata); + int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2; + int vbo_len_used = 0; + + if (DRW_TEST_ASSIGN_VBO(vbo_pos)) { + GPU_vertbuf_init_with_format(vbo_pos, &format_pos); + GPU_vertbuf_data_alloc(vbo_pos, verts_len_capacity); + } + if (DRW_TEST_ASSIGN_VBO(vbo_data)) { + GPU_vertbuf_init_with_format(vbo_data, &format_data); + GPU_vertbuf_data_alloc(vbo_data, verts_len_capacity); + } + + GPUIndexBufBuilder elb_verts, *elbp_verts = nullptr; + GPUIndexBufBuilder elb_lines, *elbp_lines = nullptr; + if (DRW_TEST_ASSIGN_IBO(ibo_edit_verts_points)) { + elbp_verts = &elb_verts; + GPU_indexbuf_init(elbp_verts, GPU_PRIM_POINTS, verts_len_capacity, verts_len_capacity); + } + if (DRW_TEST_ASSIGN_IBO(ibo_edit_lines)) { + elbp_lines = &elb_lines; + GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity); + } + + int nu_id = 0; + for (Nurb *nu = (Nurb *)rdata->nurbs->first; nu; nu = nu->next, nu_id++) { + const BezTriple *bezt = nu->bezt; + const BPoint *bp = nu->bp; + + if (bezt) { + for (int a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->hide == true) { + continue; + } + const bool handle_selected = BEZT_ISSEL_ANY(bezt); + + if (elbp_verts) { + GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0); + GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 1); + GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 2); + } + if (elbp_lines) { + GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 0); + GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 2); + } + if (vbo_data) { + const uint8_t vflag[3] = { + beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected), + beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected), + beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected), + }; + for (int j = 0; j < 3; j++) { + GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]); + } + } + if (vbo_pos) { + for (int j = 0; j < 3; j++) { + GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used + j, bezt->vec[j]); + } + } + vbo_len_used += 3; + } + } + else if (bp) { + int pt_len = nu->pntsu * nu->pntsv; + for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) { + if (bp->hide == true) { + continue; + } + int u = (a % nu->pntsu); + int v = (a / nu->pntsu); + /* Use indexed rendering for bezier. + * Specify all points and use indices to hide/show. */ + if (elbp_verts) { + GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used); + } + if (elbp_lines) { + const BPoint *bp_next_u = (u < (nu->pntsu - 1)) ? &nu->bp[a + 1] : nullptr; + const BPoint *bp_next_v = (v < (nu->pntsv - 1)) ? &nu->bp[a + nu->pntsu] : nullptr; + if (bp_next_u && (bp_next_u->hide == false)) { + GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + 1); + } + if (bp_next_v && (bp_next_v->hide == false)) { + GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + nu->pntsu); + } + } + if (vbo_data) { + uint8_t vflag = bpoint_vflag_get(rdata, bp->f1, a, nu_id, u); + GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used, &vflag); + } + if (vbo_pos) { + GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec); + } + } + } + } + + /* Resize & Finish */ + if (elbp_verts != nullptr) { + GPU_indexbuf_build_in_place(elbp_verts, ibo_edit_verts_points); + } + if (elbp_lines != nullptr) { + GPU_indexbuf_build_in_place(elbp_lines, ibo_edit_lines); + } + if (vbo_len_used != verts_len_capacity) { + if (vbo_pos != nullptr) { + GPU_vertbuf_data_resize(vbo_pos, vbo_len_used); + } + if (vbo_data != nullptr) { + GPU_vertbuf_data_resize(vbo_data, vbo_len_used); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public Object/Curve API + * \{ */ + +GPUBatch *DRW_curve_batch_cache_get_wire_edge(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.curves); +} + +GPUBatch *DRW_curve_batch_cache_get_normal_edge(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.edit_normals); +} + +GPUBatch *DRW_curve_batch_cache_get_edit_edges(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.edit_edges); +} + +GPUBatch *DRW_curve_batch_cache_get_edit_verts(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.edit_verts); +} + +GPUBatch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.surfaces); +} + +GPUBatch **DRW_curve_batch_cache_get_surface_shaded(struct Curve *cu, + struct GPUMaterial **gpumat_array, + uint gpumat_array_len) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + + BLI_assert(gpumat_array_len == cache->mat_len); + + curve_cd_calc_used_gpu_layers(&cache->cd_needed, gpumat_array, gpumat_array_len); + + for (int i = 0; i < cache->mat_len; i++) { + DRW_batch_request(&cache->surf_per_mat[i]); + } + return cache->surf_per_mat; +} + +GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + /* Request surface to trigger the vbo filling. Otherwise it may do nothing. */ + DRW_batch_request(&cache->batch.surfaces); + + DRW_vbo_request(nullptr, &cache->ordered.loop_pos_nor); + return cache->ordered.loop_pos_nor; +} + +GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + return DRW_batch_request(&cache->batch.surfaces_edges); +} + +GPUBatch *DRW_curve_batch_cache_get_edge_detection(Curve *cu, bool *r_is_manifold) +{ + CurveBatchCache *cache = curve_batch_cache_get(cu); + /* Even if is_manifold is not correct (not updated), + * the default (not manifold) is just the worst case. */ + if (r_is_manifold) { + *r_is_manifold = cache->is_manifold; + } + return DRW_batch_request(&cache->batch.edge_detection); +} + +int DRW_curve_material_count_get(Curve *cu) +{ + return max_ii(1, cu->totcol); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Grouped batch generation + * \{ */ + +void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scene) +{ + BLI_assert(ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)); + + Curve *cu = (Curve *)ob->data; + CurveBatchCache *cache = curve_batch_cache_get(cu); + + /* Verify that all surface batches have needed attribute layers. */ + /* TODO(fclem): We could be a bit smarter here and only do it per material. */ + if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) { + for (int i = 0; i < cache->mat_len; i++) { + /* We can't discard batches at this point as they have been + * referenced for drawing. Just clear them in place. */ + GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); + } + + cache->cd_used |= cache->cd_needed; + cache->cd_needed = 0; + } + + /* Init batches and request VBOs & IBOs */ + if (DRW_batch_requested(cache->batch.surfaces, GPU_PRIM_TRIS)) { + DRW_vbo_request(cache->batch.surfaces, &cache->ordered.loop_pos_nor); + } + if (DRW_batch_requested(cache->batch.surfaces_edges, GPU_PRIM_LINES)) { + DRW_ibo_request(cache->batch.surfaces_edges, &cache->ibo.surfaces_lines); + DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.pos_nor); + DRW_vbo_request(cache->batch.surfaces_edges, &cache->ordered.edge_fac); + } + if (DRW_batch_requested(cache->batch.curves, GPU_PRIM_LINE_STRIP)) { + DRW_ibo_request(cache->batch.curves, &cache->ibo.curves_lines); + DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos); + } + if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) { + DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines); + DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor); + } + + /* Edit mode */ + if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) { + DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_lines); + DRW_vbo_request(cache->batch.edit_edges, &cache->edit.pos); + DRW_vbo_request(cache->batch.edit_edges, &cache->edit.data); + } + if (DRW_batch_requested(cache->batch.edit_verts, GPU_PRIM_POINTS)) { + DRW_ibo_request(cache->batch.edit_verts, &cache->ibo.edit_verts); + DRW_vbo_request(cache->batch.edit_verts, &cache->edit.pos); + DRW_vbo_request(cache->batch.edit_verts, &cache->edit.data); + } + if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) { + DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor); + } + for (int i = 0; i < cache->mat_len; i++) { + if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { + if (cache->mat_len > 1) { + DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]); + } + if (cache->cd_used & CD_MASK_MLOOPUV) { + DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_uv); + } + if (cache->cd_used & CD_MASK_TANGENT) { + DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_tan); + } + DRW_vbo_request(cache->surf_per_mat[i], &cache->ordered.loop_pos_nor); + } + } + +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf("-- %s %s --\n", __func__, ob->id.name + 2); +#endif + + /* Generate MeshRenderData flags */ + int mr_flag = 0; + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.edge_fac, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_pos_nor, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_uv, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.loop_tan, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_tris, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_lines, CU_DATATYPE_SURFACE); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edges_adj_lines, CU_DATATYPE_SURFACE); + + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.pos, CU_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.data, CU_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_nor, CU_DATATYPE_NORMAL); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_weight, CU_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts, CU_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVERLAY); + + for (int i = 0; i < cache->mat_len; i++) { + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->surf_per_mat_tris[i], CU_DATATYPE_SURFACE); + } + +#ifdef DRW_DEBUG_MESH_CACHE_REQUEST + printf(" mr_flag %d\n\n", mr_flag); +#endif + + CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag); + + /* DispLists */ + ListBase *lb = &rdata->ob_curve_cache->disp; + + /* Generate VBOs */ + if (DRW_vbo_requested(cache->ordered.pos_nor)) { + DRW_displist_vertbuf_create_pos_and_nor(lb, cache->ordered.pos_nor, scene); + } + if (DRW_vbo_requested(cache->ordered.edge_fac)) { + DRW_displist_vertbuf_create_wiredata(lb, cache->ordered.edge_fac); + } + if (DRW_vbo_requested(cache->ordered.curves_pos)) { + curve_create_curves_pos(rdata, cache->ordered.curves_pos); + } + + if (DRW_vbo_requested(cache->ordered.loop_pos_nor) || + DRW_vbo_requested(cache->ordered.loop_uv) || DRW_vbo_requested(cache->ordered.loop_tan)) { + DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan( + lb, cache->ordered.loop_pos_nor, cache->ordered.loop_uv, cache->ordered.loop_tan, scene); + } + + if (DRW_ibo_requested(cache->surf_per_mat_tris[0])) { + DRW_displist_indexbuf_create_triangles_loop_split_by_material( + lb, cache->surf_per_mat_tris, cache->mat_len); + } + + if (DRW_ibo_requested(cache->ibo.curves_lines)) { + curve_create_curves_lines(rdata, cache->ibo.curves_lines); + } + if (DRW_ibo_requested(cache->ibo.surfaces_tris)) { + DRW_displist_indexbuf_create_triangles_in_order(lb, cache->ibo.surfaces_tris); + } + if (DRW_ibo_requested(cache->ibo.surfaces_lines)) { + DRW_displist_indexbuf_create_lines_in_order(lb, cache->ibo.surfaces_lines); + } + if (DRW_ibo_requested(cache->ibo.edges_adj_lines)) { + DRW_displist_indexbuf_create_edges_adjacency_lines( + lb, cache->ibo.edges_adj_lines, &cache->is_manifold); + } + + if (DRW_vbo_requested(cache->edit.pos) || DRW_vbo_requested(cache->edit.data) || + DRW_ibo_requested(cache->ibo.edit_verts) || DRW_ibo_requested(cache->ibo.edit_lines)) { + curve_create_edit_data_and_handles( + rdata, cache->edit.pos, cache->edit.data, cache->ibo.edit_verts, cache->ibo.edit_lines); + } + if (DRW_vbo_requested(cache->edit.curves_nor)) { + curve_create_edit_curves_nor(rdata, cache->edit.curves_nor, scene); + } + + curve_render_data_free(rdata); + +#ifdef DEBUG + /* Make sure all requested batches have been setup. */ + for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { + BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], (GPUPrimType)0)); + } +#endif +} + +/** \} */ diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h index ebe97b4e7c4..bfc714e5d6a 100644 --- a/source/blender/draw/intern/draw_cache_inline.h +++ b/source/blender/draw/intern/draw_cache_inline.h @@ -53,13 +53,13 @@ BLI_INLINE GPUBatch *DRW_batch_request(GPUBatch **batch) return *batch; } -BLI_INLINE bool DRW_batch_requested(GPUBatch *batch, int prim_type) +BLI_INLINE bool DRW_batch_requested(GPUBatch *batch, GPUPrimType prim_type) { /* Batch has been requested if it has been created but not initialized. */ if (batch != NULL && batch->verts[0] == NULL) { /* HACK. We init without a valid VBO and let the first vbo binding * fill verts[0]. */ - GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0); + GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, (eGPUBatchFlag)0); batch->verts[0] = NULL; return true; } -- cgit v1.2.3 From a20ef4207d46a28c869f8953c5ecf0f5b7af1984 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 25 May 2021 15:10:46 +0200 Subject: Fix T86956: VSE shading mode ignores Grease Pencil Vertex colors. Issue is that due to the strange definition of render in grease pencil (meaning should be rendered similar to rendering). This included normal viewport rendering in OB_RENDER and OpenGL render in OB_RENDER. For other rendering modes the overlay vertex opacity would be used. This patch sets this value to 1 when rendering via a scene strip override. NOTE: that this isn't a good solution as I expect that users want to use the opacity of the Grease pencil object. Perhaps the GPencil team has a better solution for it. --- source/blender/draw/engines/gpencil/gpencil_engine.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 5ceb909bc88..34fe29055d6 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -297,7 +297,9 @@ typedef struct GPENCIL_PrivateData { int v3d_color_type; /* Current frame */ int cfra; - /* If we are rendering for final render (F12). */ + /* If we are rendering for final render (F12). + * NOTE: set to false for viewport and opengl rendering (including VSE scene rendering), but set + * to true when rendering in `OB_RENDER` shading mode (viewport or opengl rendering) */ bool is_render; /* If we are in viewport display (used for VFX). */ bool is_viewport; -- cgit v1.2.3 From fd94e033446c72fb92048a9864c1d539fccde59a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 25 May 2021 17:00:14 +0200 Subject: Blenlib: Explicit Colors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Colors are often thought of as being 4 values that make up that can make any color. But that is of course too limited. In C we didn’t spend time to annotate what we meant when using colors. Recently `BLI_color.hh` was made to facilitate color structures in CPP. CPP has possibilities to enforce annotating structures during compilation and can adds conversions between them using function overloading and explicit constructors. The storage structs can hold 4 channels (r, g, b and a). Usage: Convert a theme byte color to a linearrgb premultiplied. ``` ColorTheme4b theme_color; ColorSceneLinear4f linearrgb_color = BLI_color_convert_to_scene_linear(theme_color).premultiply_alpha(); ``` The API is structured to make most use of inlining. Most notable are space conversions done via `BLI_color_convert_to*` functions. - Conversions between spaces (theme <=> scene linear) should always be done by invoking the `BLI_color_convert_to*` methods. - Encoding colors (compressing to store colors inside a less precision storage) should be done by invoking the `encode` and `decode` methods. - Changing alpha association should be done by invoking `premultiply_alpha` or `unpremultiply_alpha` methods. # Encoding. Color encoding is used to store colors with less precision as in using `uint8_t` in stead of `float`. This encoding is supported for `eSpace::SceneLinear`. To make this clear to the developer the `eSpace::SceneLinearByteEncoded` space is added. # Precision Colors can be stored using `uint8_t` or `float` colors. The conversion between the two precisions are available as methods. (`to_4b` and `to_4f`). # Alpha conversion Alpha conversion is only supported in SceneLinear space. Extending: - This file can be extended with `ColorHex/Hsl/Hsv` for different representations of rgb based colors. `ColorHsl4f` - Add non RGB spaces/storages ColorXyz. Reviewed By: JacquesLucke, brecht Differential Revision: https://developer.blender.org/D10978 --- source/blender/draw/intern/draw_cache_impl.h | 1 - 1 file changed, 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 2c2ab9eaadd..5743f39f7da 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -266,7 +266,6 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object * struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); - #ifdef __cplusplus } #endif -- cgit v1.2.3 From 00955cd31eda95aca619842064d22663af4c812b Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 25 May 2021 17:03:54 +0200 Subject: Revert "Blenlib: Explicit Colors." This reverts commit fd94e033446c72fb92048a9864c1d539fccde59a. does not compile against latest master. --- source/blender/draw/intern/draw_cache_impl.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 5743f39f7da..2c2ab9eaadd 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -266,6 +266,7 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object * struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); + #ifdef __cplusplus } #endif -- cgit v1.2.3 From cb8a6814fdb7755c6f799b64727f078f0076506e Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Tue, 25 May 2021 17:16:35 +0200 Subject: Blenlib: Explicit Colors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Colors are often thought of as being 4 values that make up that can make any color. But that is of course too limited. In C we didn’t spend time to annotate what we meant when using colors. Recently `BLI_color.hh` was made to facilitate color structures in CPP. CPP has possibilities to enforce annotating structures during compilation and can adds conversions between them using function overloading and explicit constructors. The storage structs can hold 4 channels (r, g, b and a). Usage: Convert a theme byte color to a linearrgb premultiplied. ``` ColorTheme4b theme_color; ColorSceneLinear4f linearrgb_color = BLI_color_convert_to_scene_linear(theme_color).premultiply_alpha(); ``` The API is structured to make most use of inlining. Most notable are space conversions done via `BLI_color_convert_to*` functions. - Conversions between spaces (theme <=> scene linear) should always be done by invoking the `BLI_color_convert_to*` methods. - Encoding colors (compressing to store colors inside a less precision storage) should be done by invoking the `encode` and `decode` methods. - Changing alpha association should be done by invoking `premultiply_alpha` or `unpremultiply_alpha` methods. # Encoding. Color encoding is used to store colors with less precision as in using `uint8_t` in stead of `float`. This encoding is supported for `eSpace::SceneLinear`. To make this clear to the developer the `eSpace::SceneLinearByteEncoded` space is added. # Precision Colors can be stored using `uint8_t` or `float` colors. The conversion between the two precisions are available as methods. (`to_4b` and `to_4f`). # Alpha conversion Alpha conversion is only supported in SceneLinear space. Extending: - This file can be extended with `ColorHex/Hsl/Hsv` for different representations of rgb based colors. `ColorHsl4f` - Add non RGB spaces/storages ColorXyz. Reviewed By: JacquesLucke, brecht Differential Revision: https://developer.blender.org/D10978 --- source/blender/draw/intern/draw_cache_impl.h | 1 - 1 file changed, 1 deletion(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 2c2ab9eaadd..5743f39f7da 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -266,7 +266,6 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(struct Object * struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *object, struct ParticleSystem *psys, struct PTCacheEdit *edit); - #ifdef __cplusplus } #endif -- cgit v1.2.3 From c0bb7d9cb78787b006cd71b1d809d6a0e47bb4f2 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 25 May 2021 14:37:58 -0400 Subject: Cleanup: Fix short comparison with bool warning For some reason the hide status is stored in a short and a char (we cannot have bools in DNA). --- source/blender/draw/intern/draw_cache_impl_curve.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_impl_curve.cc b/source/blender/draw/intern/draw_cache_impl_curve.cc index 223b44724b6..ddafc7205bb 100644 --- a/source/blender/draw/intern/draw_cache_impl_curve.cc +++ b/source/blender/draw/intern/draw_cache_impl_curve.cc @@ -796,7 +796,7 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata, if (bezt) { for (int a = 0; a < nu->pntsu; a++, bezt++) { - if (bezt->hide == true) { + if (bezt->hide != 0) { continue; } const bool handle_selected = BEZT_ISSEL_ANY(bezt); @@ -831,7 +831,7 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata, else if (bp) { int pt_len = nu->pntsu * nu->pntsv; for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) { - if (bp->hide == true) { + if (bp->hide != 0) { continue; } int u = (a % nu->pntsu); -- cgit v1.2.3