diff options
24 files changed, 401 insertions, 252 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index acf7a0dfa8d..e8ac2f9e13f 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -143,7 +143,6 @@ set(SRC engines/overlay/overlay_outline.c engines/overlay/overlay_paint.c engines/overlay/overlay_particle.c - engines/overlay/overlay_pointcloud.c engines/overlay/overlay_sculpt.c engines/overlay/overlay_shader.c engines/overlay/overlay_wireframe.c @@ -270,6 +269,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_material_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_merge_infront_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_hair_vert.glsl SRC) +data_to_c_simple(engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_shader_interface_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_shadow_caps_geom.glsl SRC) @@ -284,6 +284,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC) data_to_c_simple(intern/shaders/common_colormanagement_lib.glsl SRC) data_to_c_simple(intern/shaders/common_globals_lib.glsl SRC) +data_to_c_simple(intern/shaders/common_pointcloud_lib.glsl SRC) data_to_c_simple(intern/shaders/common_hair_lib.glsl SRC) data_to_c_simple(intern/shaders/common_hair_refine_vert.glsl SRC) data_to_c_simple(intern/shaders/common_view_lib.glsl SRC) @@ -385,8 +386,6 @@ data_to_c_simple(engines/overlay/shaders/paint_weight_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/paint_wire_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/particle_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/particle_frag.glsl SRC) -data_to_c_simple(engines/overlay/shaders/pointcloud_vert.glsl SRC) -data_to_c_simple(engines/overlay/shaders/pointcloud_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/sculpt_mask_frag.glsl SRC) data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC) diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index e76b3c82c1d..bc96a03da31 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -182,7 +182,6 @@ static void OVERLAY_cache_init(void *vedata) OVERLAY_motion_path_cache_init(vedata); OVERLAY_outline_cache_init(vedata); OVERLAY_particle_cache_init(vedata); - OVERLAY_pointcloud_cache_init(vedata); OVERLAY_wireframe_cache_init(vedata); } @@ -403,12 +402,6 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob) OVERLAY_particle_cache_populate(vedata, ob); } - /* TODO: these should not be overlays, just here for testing since it's - * easier to implement than integrating it into eevee/workbench. */ - if (ob->type == OB_POINTCLOUD) { - OVERLAY_pointcloud_cache_populate(vedata, ob); - } - /* Relationship, object center, bounbox ... */ if (!pd->hide_overlays) { OVERLAY_extra_cache_populate(vedata, ob); @@ -482,7 +475,6 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_armature_draw(vedata); OVERLAY_particle_draw(vedata); OVERLAY_metaball_draw(vedata); - OVERLAY_pointcloud_draw(vedata); OVERLAY_gpencil_draw(vedata); OVERLAY_extra_draw(vedata); diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index e00ebe12cd6..214322c4adc 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -138,6 +138,11 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata) pd->outlines_grp = grp = DRW_shgroup_create(sh_geom, psl->outlines_prepass_ps); DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); + GPUShader *sh_geom_ptcloud = OVERLAY_shader_outline_prepass_pointcloud(); + + pd->outlines_ptcloud_grp = grp = DRW_shgroup_create(sh_geom_ptcloud, psl->outlines_prepass_ps); + DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); + GPUShader *sh_gpencil = OVERLAY_shader_outline_prepass_gpencil(); pd->outlines_gpencil_grp = grp = DRW_shgroup_create(sh_gpencil, psl->outlines_prepass_ps); @@ -288,6 +293,12 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, return; } + if (ob->type == OB_POINTCLOUD && pd->wireframe_mode) { + /* Looks bad in this case. Could be relaxed if we draw a + * wireframe of some sort in the future. */ + return; + } + if (dupli && !init_dupli) { geom = dupli->outline_geom; shgroup = dupli->outline_shgrp; @@ -307,12 +318,18 @@ void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, } if (geom) { - shgroup = pd->outlines_grp; + shgroup = (ob->type == OB_POINTCLOUD) ? pd->outlines_ptcloud_grp : pd->outlines_grp; } } if (shgroup && geom) { - DRW_shgroup_call(shgroup, geom, ob); + if (ob->type == OB_POINTCLOUD) { + /* Draw range to avoid drawcall batching messing up the instance attrib. */ + DRW_shgroup_call_instance_range(shgroup, ob, geom, 0, 0); + } + else { + DRW_shgroup_call(shgroup, geom, ob); + } } if (init_dupli) { diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c deleted file mode 100644 index b2a2d44bf73..00000000000 --- a/source/blender/draw/engines/overlay/overlay_pointcloud.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Copyright 2020, Blender Foundation. - */ - -/** \file - * \ingroup draw_engine - */ - -#include "DRW_render.h" - -#include "DEG_depsgraph_query.h" - -#include "DNA_pointcloud_types.h" - -#include "BKE_pointcache.h" - -#include "overlay_private.h" - -/* -------------------------------------------------------------------- */ -/** \name PointCloud - * \{ */ - -void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata) -{ - OVERLAY_PassList *psl = vedata->psl; - OVERLAY_PrivateData *pd = vedata->stl->pd; - GPUShader *sh; - DRWShadingGroup *grp; - - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRW_PASS_CREATE(psl->pointcloud_ps, state | pd->clipping_state); - - sh = OVERLAY_shader_pointcloud_dot(); - pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps); - DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); -} - -void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob) -{ - OVERLAY_PrivateData *pd = vedata->stl->pd; - - struct GPUBatch *geom = DRW_cache_pointcloud_get_dots(ob); - - const float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - - DRWShadingGroup *grp = DRW_shgroup_create_sub(pd->pointcloud_dots_grp); - DRW_shgroup_uniform_vec4_copy(grp, "color", color); - DRW_shgroup_call(grp, geom, ob); -} - -void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata) -{ - OVERLAY_PassList *psl = vedata->psl; - - DRW_draw_pass(psl->pointcloud_ps); -} - -/** \} */ diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 59fa58c0c03..027478c3e3c 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -243,6 +243,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *motion_path_lines_grp; DRWShadingGroup *motion_path_points_grp; DRWShadingGroup *outlines_grp; + DRWShadingGroup *outlines_ptcloud_grp; DRWShadingGroup *outlines_gpencil_grp; DRWShadingGroup *paint_depth_grp; DRWShadingGroup *paint_surf_grp; @@ -550,10 +551,6 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata); void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_particle_draw(OVERLAY_Data *vedata); -void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata); -void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob); -void OVERLAY_pointcloud_draw(OVERLAY_Data *vedata); - void OVERLAY_sculpt_cache_init(OVERLAY_Data *vedata); void OVERLAY_sculpt_cache_populate(OVERLAY_Data *vedata, Object *ob); void OVERLAY_sculpt_draw(OVERLAY_Data *vedata); @@ -610,6 +607,7 @@ GPUShader *OVERLAY_shader_motion_path_vert(void); GPUShader *OVERLAY_shader_uniform_color(void); GPUShader *OVERLAY_shader_outline_prepass(bool use_wire); GPUShader *OVERLAY_shader_outline_prepass_gpencil(void); +GPUShader *OVERLAY_shader_outline_prepass_pointcloud(void); GPUShader *OVERLAY_shader_extra_grid(void); GPUShader *OVERLAY_shader_outline_detect(void); GPUShader *OVERLAY_shader_paint_face(void); @@ -620,7 +618,6 @@ GPUShader *OVERLAY_shader_paint_weight(void); GPUShader *OVERLAY_shader_paint_wire(void); GPUShader *OVERLAY_shader_particle_dot(void); GPUShader *OVERLAY_shader_particle_shape(void); -GPUShader *OVERLAY_shader_pointcloud_dot(void); GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); GPUShader *OVERLAY_shader_wireframe(bool custom_bias); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index edf91c99531..87f4642809b 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -103,8 +103,6 @@ extern char datatoc_paint_weight_vert_glsl[]; extern char datatoc_paint_wire_vert_glsl[]; extern char datatoc_particle_vert_glsl[]; extern char datatoc_particle_frag_glsl[]; -extern char datatoc_pointcloud_vert_glsl[]; -extern char datatoc_pointcloud_frag_glsl[]; extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_sculpt_mask_frag_glsl[]; extern char datatoc_volume_velocity_vert_glsl[]; @@ -127,6 +125,7 @@ extern char datatoc_common_fullscreen_vert_glsl[]; extern char datatoc_common_fxaa_lib_glsl[]; extern char datatoc_common_smaa_lib_glsl[]; extern char datatoc_common_globals_lib_glsl[]; +extern char datatoc_common_pointcloud_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; typedef struct OVERLAY_Shaders { @@ -181,6 +180,7 @@ typedef struct OVERLAY_Shaders { GPUShader *motion_path_vert; GPUShader *outline_prepass; GPUShader *outline_prepass_gpencil; + GPUShader *outline_prepass_pointcloud; GPUShader *outline_prepass_wire; GPUShader *outline_detect; GPUShader *paint_face; @@ -1135,6 +1135,33 @@ GPUShader *OVERLAY_shader_outline_prepass_gpencil(void) return sh_data->outline_prepass_gpencil; } +GPUShader *OVERLAY_shader_outline_prepass_pointcloud(void) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; + if (!sh_data->outline_prepass_pointcloud) { + sh_data->outline_prepass_pointcloud = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg->lib, + datatoc_common_view_lib_glsl, + datatoc_common_pointcloud_lib_glsl, + datatoc_gpu_shader_common_obinfos_lib_glsl, + datatoc_outline_prepass_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_gpencil_common_lib_glsl, + datatoc_outline_prepass_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg->def, + "#define POINTCLOUD\n", + "#define INSTANCED_ATTR\n", + "#define UNIFORM_RESOURCE_ID\n", + NULL}, + }); + } + return sh_data->outline_prepass_pointcloud; +} + GPUShader *OVERLAY_shader_outline_detect(void) { OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; @@ -1306,25 +1333,6 @@ GPUShader *OVERLAY_shader_particle_shape(void) return sh_data->particle_shape; } -GPUShader *OVERLAY_shader_pointcloud_dot(void) -{ - const DRWContextState *draw_ctx = DRW_context_state_get(); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; - OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (!sh_data->pointcloud_dot) { - sh_data->pointcloud_dot = GPU_shader_create_from_arrays({ - .vert = (const char *[]){sh_cfg->lib, - datatoc_common_globals_lib_glsl, - datatoc_common_view_lib_glsl, - datatoc_pointcloud_vert_glsl, - NULL}, - .frag = (const char *[]){datatoc_pointcloud_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, "#define USE_DOTS\n", NULL}, - }); - } - return sh_data->pointcloud_dot; -} - GPUShader *OVERLAY_shader_sculpt_mask(void) { const DRWContextState *draw_ctx = DRW_context_state_get(); diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index ea45ad5190c..2135e13ffe0 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -235,10 +235,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, } } - if (use_wire && ob->type == OB_VOLUME) { - /* Volume object as points exception. */ - Volume *volume = ob->data; - if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) { + if (use_wire && ELEM(ob->type, OB_VOLUME, OB_POINTCLOUD)) { + bool draw_as_points = true; + if (ob->type == OB_VOLUME) { + /* Volume object as points exception. */ + Volume *volume = ob->data; + draw_as_points = volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS; + } + + if (draw_as_points) { float *color; OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob); DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color); diff --git a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl index a2021759196..582a7c6cae2 100644 --- a/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl @@ -1,7 +1,7 @@ uniform bool isTransform; -#ifndef USE_GPENCIL +#if !defined(USE_GPENCIL) && !defined(POINTCLOUD) in vec3 pos; #endif @@ -56,7 +56,11 @@ void main() # endif #else +# ifdef POINTCLOUD + vec3 world_pos = pointcloud_get_pos(); +# else vec3 world_pos = point_object_to_world(pos); +# endif gl_Position = point_world_to_ndc(world_pos); # ifdef USE_GEOM vPos = point_world_to_view(world_pos); diff --git a/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl b/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl deleted file mode 100644 index 36928d0c776..00000000000 --- a/source/blender/draw/engines/overlay/shaders/pointcloud_frag.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -in vec4 finalColor; - -out vec4 fragColor; - -void main() -{ - float dist = length(gl_PointCoord - vec2(0.5)); - - if (dist > 0.5) { - discard; - } - /* Nice sphere falloff. */ - float intensity = sqrt(1.0 - dist * 2.0) * 0.5 + 0.5; - fragColor = finalColor * vec4(intensity, intensity, intensity, 1.0); -} diff --git a/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl b/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl deleted file mode 100644 index d71ccee5159..00000000000 --- a/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl +++ /dev/null @@ -1,27 +0,0 @@ - -uniform vec4 color; - -/* ---- Per instance Attrs ---- */ -in vec3 pointcloud_pos; -in vec3 pointcloud_radius; - -out vec4 finalColor; - -void main() -{ - vec3 world_pos = point_object_to_world(pointcloud_pos); - - vec3 world_size = abs(mat3(ModelMatrix) * vec3(pointcloud_radius)); - float world_radius = (world_size.x + world_size.y + world_size.z) / 3.0; - - gl_Position = point_world_to_ndc(world_pos); - /* World sized points. */ - gl_PointSize = sizePixel * world_radius * ProjectionMatrix[1][1] * sizeViewport.y / - gl_Position.w; - - finalColor = color; - -#ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); -#endif -} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl new file mode 100644 index 00000000000..8e5c8a1b21f --- /dev/null +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl @@ -0,0 +1,38 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_pointcloud_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_shader_interface_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_common_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_material_lib.glsl) +#pragma BLENDER_REQUIRE(workbench_image_lib.glsl) + +void main() +{ + vec3 world_pos; + pointcloud_get_pos_and_nor(world_pos, normal_interp); + + normal_interp = normalize(normal_world_to_view(normal_interp)); + + gl_Position = point_world_to_ndc(world_pos); + +#ifdef USE_WORLD_CLIP_PLANES + world_clip_planes_calc_clip_distance(world_pos); +#endif + + uv_interp = vec2(0.0); + +#ifdef OPAQUE_MATERIAL + float metallic, roughness; +#endif + workbench_material_data_get(resource_handle, color_interp, alpha_interp, roughness, metallic); + + if (materialIndex == 0) { + color_interp = vec3(1.0); + } + +#ifdef OPAQUE_MATERIAL + packed_rough_metal = workbench_float_pair_encode(roughness, metallic); +#endif + + object_id = int((uint(resource_id) + 1u) & 0xFFu); +} diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index 5b06cb03c59..5fff55e2f26 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -130,6 +130,17 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd, } } +BLI_INLINE void workbench_object_drawcall(DRWShadingGroup *grp, struct GPUBatch *geom, Object *ob) +{ + if (ob->type == OB_POINTCLOUD) { + /* Draw range to avoid drawcall batching messing up the instance attrib. */ + DRW_shgroup_call_instance_range(grp, ob, geom, 0, 0); + } + else { + DRW_shgroup_call(grp, geom, ob); + } +} + static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object *ob) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -145,7 +156,7 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object SET_FLAG_FROM_TEST(state, imapaint->interp == IMAGEPAINT_INTERP_LINEAR, GPU_SAMPLER_FILTER); DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, state); - DRW_shgroup_call(grp, geom, ob); + workbench_object_drawcall(grp, geom, ob); } } else { @@ -157,7 +168,7 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object continue; } DRWShadingGroup *grp = workbench_image_setup(wpd, ob, i + 1, NULL, NULL, 0); - DRW_shgroup_call(grp, geoms[i], ob); + workbench_object_drawcall(grp, geoms[i], ob); } } } @@ -194,7 +205,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, if (geom) { DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, r_transp); - DRW_shgroup_call(grp, geom, ob); + workbench_object_drawcall(grp, geom, ob); } } else { @@ -207,7 +218,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, continue; } DRWShadingGroup *grp = workbench_material_setup(wpd, ob, i + 1, color_type, r_transp); - DRW_shgroup_call(grp, geoms[i], ob); + workbench_object_drawcall(grp, geoms[i], ob); } } } @@ -450,7 +461,7 @@ void workbench_cache_finish(void *ved) /* TODO don't free reuse next redraw. */ for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { + for (int k = 0; k < WORKBENCH_DATATYPE_MAX; k++) { if (wpd->prepass[i][j][k].material_hash) { BLI_ghash_free(wpd->prepass[i][j][k].material_hash, NULL, NULL); wpd->prepass[i][j][k].material_hash = NULL; diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index d6d3ff8610b..e04063c4487 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -162,7 +162,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, eV3DShadingColorType color_type, - bool hair, + eWORKBENCH_DataType datatype, bool *r_transp) { Image *ima = NULL; @@ -180,7 +180,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, switch (color_type) { case V3D_SHADING_TEXTURE_COLOR: { - return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, hair); + return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, sampler, datatype); } case V3D_SHADING_MATERIAL_COLOR: { /* For now, we use the same ubo for material and object coloring but with different indices. @@ -191,7 +191,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Material *ma = workbench_object_material_get(ob, mat_nr); const bool transp = wpd->shading.xray_alpha < 1.0f || ma->a < 1.0f; - WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][hair]; + WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype]; if (r_transp && transp) { *r_transp = true; @@ -216,7 +216,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, } case V3D_SHADING_VERTEX_COLOR: { const bool transp = wpd->shading.xray_alpha < 1.0f; - DRWShadingGroup *grp = wpd->prepass[transp][infront][hair].vcol_shgrp; + DRWShadingGroup *grp = wpd->prepass[transp][infront][datatype].vcol_shgrp; return grp; } default: { @@ -231,7 +231,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, workbench_material_ubo_data(wpd, ob, NULL, &wpd->material_ubo_data_curr[mat_id], color_type); const bool transp = wpd->shading.xray_alpha < 1.0f || ob->color[3] < 1.0f; - DRWShadingGroup *grp = wpd->prepass[transp][infront][hair].common_shgrp; + DRWShadingGroup *grp = wpd->prepass[transp][infront][datatype].common_shgrp; if (resource_changed) { grp = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); @@ -251,7 +251,7 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Image *ima, ImageUser *iuser, eGPUSamplerState sampler, - bool hair) + eWORKBENCH_DataType datatype) { GPUTexture *tex = NULL, *tex_tile_data = NULL; @@ -275,7 +275,7 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, const bool infront = (ob->dtx & OB_DRAWXRAY) != 0; const bool transp = wpd->shading.xray_alpha < 1.0f; - WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][hair]; + WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][datatype]; DRWShadingGroup **grp_tex = NULL; /* A hashmap stores image shgroups to pack all similar drawcalls together. */ diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c index 27d5b71f35c..738f4a67471 100644 --- a/source/blender/draw/engines/workbench/workbench_opaque.c +++ b/source/blender/draw/engines/workbench/workbench_opaque.c @@ -59,10 +59,10 @@ void workbench_opaque_engine_init(WORKBENCH_Data *data) }); } -void workbench_opaque_cache_init(WORKBENCH_Data *data) +void workbench_opaque_cache_init(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = data->psl; - WORKBENCH_PrivateData *wpd = data->stl->wpd; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = vedata->stl->wpd; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); struct GPUShader *sh; DRWShadingGroup *grp; @@ -84,31 +84,31 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data) pass = psl->opaque_ps; } - for (int hair = 0; hair < 2; hair++) { - wpd->prepass[opaque][infront][hair].material_hash = BLI_ghash_ptr_new(__func__); + for (eWORKBENCH_DataType data = 0; data < WORKBENCH_DATATYPE_MAX; data++) { + wpd->prepass[opaque][infront][data].material_hash = BLI_ghash_ptr_new(__func__); - sh = workbench_shader_opaque_get(wpd, hair); + sh = workbench_shader_opaque_get(wpd, data); - wpd->prepass[opaque][infront][hair].common_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].common_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", -1); DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - sh = workbench_shader_opaque_image_get(wpd, hair, false); + sh = workbench_shader_opaque_image_get(wpd, data, false); - wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].image_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); - sh = workbench_shader_opaque_image_get(wpd, hair, true); + sh = workbench_shader_opaque_image_get(wpd, data, true); - wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[opaque][infront][data].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 18ed43f7f15..244ac695e78 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -71,6 +71,14 @@ struct RenderEngine; struct RenderLayer; struct rcti; +typedef enum eWORKBENCH_DataType { + WORKBENCH_DATATYPE_MESH = 0, + WORKBENCH_DATATYPE_HAIR, + WORKBENCH_DATATYPE_POINTCLOUD, + + WORKBENCH_DATATYPE_MAX, +} eWORKBENCH_DataType; + typedef struct WORKBENCH_FramebufferList { struct GPUFrameBuffer *opaque_fb; struct GPUFrameBuffer *opaque_infront_fb; @@ -292,8 +300,8 @@ typedef struct WORKBENCH_PrivateData { /** Object IDs buffer for curvature & outline. */ struct GPUTexture *object_id_tx; - /** Pre-pass information for each draw types [transparent][infront][hair]. */ - WORKBENCH_Prepass prepass[2][2][2]; + /** Pre-pass information for each draw types [transparent][infront][datatype]. */ + WORKBENCH_Prepass prepass[2][2][WORKBENCH_DATATYPE_MAX]; /* Materials */ /** Copy of vldata->material_ubo for faster access. */ @@ -392,14 +400,16 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data); void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const bool has_transp_mat); /* workbench_shader.c */ -GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair); -GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled); +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data); +GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType data, + bool tiled); GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd); GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData *wpd); -GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, bool hair); +GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data); GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd, - bool hair, + eWORKBENCH_DataType data, bool tiled); GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd); @@ -454,7 +464,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, eV3DShadingColorType color_type, - bool hair, + eWORKBENCH_DataType datatype, bool *r_transp); DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Object *ob, @@ -462,17 +472,20 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, Image *ima, ImageUser *iuser, eGPUSamplerState sampler, - bool hair); + eWORKBENCH_DataType datatype); + +#define WORKBENCH_OBJECT_DATATYPE(ob) \ + ((ob->type == OB_POINTCLOUD) ? WORKBENCH_DATATYPE_POINTCLOUD : WORKBENCH_DATATYPE_MESH) #define workbench_material_setup(wpd, ob, mat_nr, color_type, r_transp) \ - workbench_material_setup_ex(wpd, ob, mat_nr, color_type, false, r_transp) + workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_OBJECT_DATATYPE(ob), r_transp) #define workbench_image_setup(wpd, ob, mat_nr, ima, iuser, interp) \ - workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, false) + workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_OBJECT_DATATYPE(ob)) #define workbench_material_hair_setup(wpd, ob, mat_nr, color_type) \ - workbench_material_setup_ex(wpd, ob, mat_nr, color_type, true, 0) + workbench_material_setup_ex(wpd, ob, mat_nr, color_type, WORKBENCH_DATATYPE_HAIR, 0) #define workbench_image_hair_setup(wpd, ob, mat_nr, ima, iuser, interp) \ - workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, true) + workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, WORKBENCH_DATATYPE_HAIR) /* workbench_data.c */ void workbench_private_data_init(WORKBENCH_PrivateData *wpd); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 99366779b22..835f10598d4 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -29,11 +29,13 @@ #include "workbench_private.h" extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_common_pointcloud_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; extern char datatoc_common_smaa_lib_glsl[]; extern char datatoc_workbench_prepass_vert_glsl[]; extern char datatoc_workbench_prepass_hair_vert_glsl[]; +extern char datatoc_workbench_prepass_pointcloud_vert_glsl[]; extern char datatoc_workbench_prepass_frag_glsl[]; extern char datatoc_workbench_effect_cavity_frag_glsl[]; @@ -74,7 +76,6 @@ extern char datatoc_gpu_shader_common_obinfos_lib_glsl[]; /* Maximum number of variations. */ #define MAX_LIGHTING 3 #define MAX_COLOR 3 -#define MAX_GEOM 2 enum { VOLUME_SH_SLICE = 0, @@ -85,8 +86,9 @@ enum { #define VOLUME_SH_MAX (1 << (VOLUME_SH_CUBIC + 1)) static struct { - struct GPUShader *opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_GEOM][MAX_COLOR]; - struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][MAX_GEOM][MAX_LIGHTING][MAX_COLOR]; + struct GPUShader *opaque_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX][MAX_COLOR]; + struct GPUShader *transp_prepass_sh_cache[GPU_SHADER_CFG_LEN][WORKBENCH_DATATYPE_MAX] + [MAX_LIGHTING][MAX_COLOR]; struct GPUShader *opaque_composite_sh[MAX_LIGHTING]; struct GPUShader *oit_resolve_sh; @@ -119,6 +121,7 @@ void workbench_shader_library_ensure(void) /* NOTE: Theses needs to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); + DRW_SHADER_LIB_ADD(e_data.lib, common_pointcloud_lib); DRW_SHADER_LIB_ADD(e_data.lib, gpu_shader_common_obinfos_lib); DRW_SHADER_LIB_ADD(e_data.lib, workbench_shader_interface_lib); DRW_SHADER_LIB_ADD(e_data.lib, workbench_common_lib); @@ -177,15 +180,18 @@ static int workbench_color_index(WORKBENCH_PrivateData *UNUSED(wpd), bool textur return (textured) ? (tiled ? 2 : 1) : 0; } -static GPUShader *workbench_shader_get_ex( - WORKBENCH_PrivateData *wpd, bool transp, bool hair, bool textured, bool tiled) +static GPUShader *workbench_shader_get_ex(WORKBENCH_PrivateData *wpd, + bool transp, + eWORKBENCH_DataType datatype, + bool textured, + bool tiled) { int color = workbench_color_index(wpd, textured, tiled); int light = wpd->shading.light; BLI_assert(light < MAX_LIGHTING); struct GPUShader **shader = - (transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][hair][light][color] : - &e_data.opaque_prepass_sh_cache[wpd->sh_cfg][hair][color]; + (transp) ? &e_data.transp_prepass_sh_cache[wpd->sh_cfg][datatype][light][color] : + &e_data.opaque_prepass_sh_cache[wpd->sh_cfg][datatype][color]; if (*shader == NULL) { char *defines = workbench_build_defines(wpd, textured, tiled, false, false); @@ -194,8 +200,11 @@ static GPUShader *workbench_shader_get_ex( datatoc_workbench_prepass_frag_glsl; char *frag_src = DRW_shader_library_create_shader_string(e_data.lib, frag_file); - char *vert_file = hair ? datatoc_workbench_prepass_hair_vert_glsl : - datatoc_workbench_prepass_vert_glsl; + char *vert_file = (datatype == WORKBENCH_DATATYPE_HAIR) ? + datatoc_workbench_prepass_hair_vert_glsl : + ((datatype == WORKBENCH_DATATYPE_POINTCLOUD) ? + datatoc_workbench_prepass_pointcloud_vert_glsl : + datatoc_workbench_prepass_vert_glsl); char *vert_src = DRW_shader_library_create_shader_string(e_data.lib, vert_file); const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[wpd->sh_cfg]; @@ -207,6 +216,10 @@ static GPUShader *workbench_shader_get_ex( defines, transp ? "#define TRANSPARENT_MATERIAL\n" : "#define OPAQUE_MATERIAL\n", + (datatype == WORKBENCH_DATATYPE_POINTCLOUD) ? + "#define UNIFORM_RESOURCE_ID\n" + "#define INSTANCED_ATTR\n" : + NULL, NULL}, }); @@ -217,26 +230,29 @@ static GPUShader *workbench_shader_get_ex( return *shader; } -GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair) +GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType datatype) { - return workbench_shader_get_ex(wpd, false, hair, false, false); + return workbench_shader_get_ex(wpd, false, datatype, false, false); } -GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled) +GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType datatype, + bool tiled) { - return workbench_shader_get_ex(wpd, false, hair, true, tiled); + return workbench_shader_get_ex(wpd, false, datatype, true, tiled); } -GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, bool hair) +GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, + eWORKBENCH_DataType datatype) { - return workbench_shader_get_ex(wpd, true, hair, false, false); + return workbench_shader_get_ex(wpd, true, datatype, false, false); } GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd, - bool hair, + eWORKBENCH_DataType datatype, bool tiled) { - return workbench_shader_get_ex(wpd, true, hair, true, tiled); + return workbench_shader_get_ex(wpd, true, datatype, true, tiled); } GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd) diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c index 1c40a350300..5eff056846c 100644 --- a/source/blender/draw/engines/workbench/workbench_transparent.c +++ b/source/blender/draw/engines/workbench/workbench_transparent.c @@ -83,10 +83,10 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd, } } -void workbench_transparent_cache_init(WORKBENCH_Data *data) +void workbench_transparent_cache_init(WORKBENCH_Data *vedata) { - WORKBENCH_PassList *psl = data->psl; - WORKBENCH_PrivateData *wpd = data->stl->wpd; + WORKBENCH_PassList *psl = vedata->psl; + WORKBENCH_PrivateData *wpd = vedata->stl->wpd; struct GPUShader *sh; DRWShadingGroup *grp; @@ -105,30 +105,30 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data) pass = psl->transp_accum_ps; } - for (int hair = 0; hair < 2; hair++) { - wpd->prepass[transp][infront][hair].material_hash = BLI_ghash_ptr_new(__func__); + for (eWORKBENCH_DataType data = 0; data < WORKBENCH_DATATYPE_MAX; data++) { + wpd->prepass[transp][infront][data].material_hash = BLI_ghash_ptr_new(__func__); - sh = workbench_shader_transparent_get(wpd, hair); + sh = workbench_shader_transparent_get(wpd, data); - wpd->prepass[transp][infront][hair].common_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].common_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", -1); workbench_transparent_lighting_uniforms(wpd, grp); - wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ - sh = workbench_shader_transparent_image_get(wpd, hair, false); + sh = workbench_shader_transparent_image_get(wpd, data, false); - wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].image_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); - sh = workbench_shader_transparent_image_get(wpd, hair, true); + sh = workbench_shader_transparent_image_get(wpd, data, true); - wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); + wpd->prepass[transp][infront][data].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 9f30cd85957..20e346375a7 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -829,7 +829,7 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob) case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_pointcloud_batch_cache_get_dots(ob); case OB_VOLUME: return DRW_cache_volume_face_wireframe_get(ob); case OB_GPENCIL: { @@ -880,7 +880,7 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob) case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_cache_pointcloud_surface_get(ob); case OB_VOLUME: return NULL; default: @@ -958,7 +958,7 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob, case OB_HAIR: return NULL; case OB_POINTCLOUD: - return NULL; + return DRW_cache_pointcloud_surface_shaded_get(ob, gpumat_array, gpumat_array_len); case OB_VOLUME: return NULL; default: @@ -3289,9 +3289,16 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob) GPUBatch *DRW_cache_pointcloud_get_dots(Object *object) { + BLI_assert(object->type == OB_POINTCLOUD); return DRW_pointcloud_batch_cache_get_dots(object); } +GPUBatch *DRW_cache_pointcloud_surface_get(Object *object) +{ + BLI_assert(object->type == OB_POINTCLOUD); + return DRW_pointcloud_batch_cache_get_surface(object); +} + /* -------------------------------------------------------------------- */ /** \name Volume * \{ */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 2f289bf4110..1ea53c91cb3 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -215,6 +215,7 @@ struct GPUBatch *DRW_cache_hair_edge_detection_get(struct Object *ob, bool *r_is /* PointCloud */ struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj); +struct GPUBatch *DRW_cache_pointcloud_surface_get(struct Object *obj); /* Volume */ typedef struct DRWVolumeGrid { diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 5cf1c24af0b..96d351794e6 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -144,6 +144,10 @@ int DRW_hair_material_count_get(struct Hair *hair); int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud); struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob); +struct GPUBatch *DRW_pointcloud_batch_cache_get_surface(struct Object *ob); +struct GPUBatch **DRW_cache_pointcloud_surface_shaded_get(struct Object *ob, + struct GPUMaterial **gpumat_array, + uint gpumat_array_len); /* Volume */ int DRW_volume_material_count_get(struct Volume *volume); diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.c b/source/blender/draw/intern/draw_cache_impl_pointcloud.c index 53939b35285..91baf9fa15e 100644 --- a/source/blender/draw/intern/draw_cache_impl_pointcloud.c +++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.c @@ -28,6 +28,7 @@ #include "MEM_guardedalloc.h" #include "BLI_math_base.h" +#include "BLI_math_vector.h" #include "BLI_utildefines.h" #include "DNA_object_types.h" @@ -45,11 +46,18 @@ static void pointcloud_batch_cache_clear(PointCloud *pointcloud); /* PointCloud GPUBatch Cache */ typedef struct PointCloudBatchCache { - GPUVertBuf *pos; - GPUBatch *batch; + GPUVertBuf *pos; /* Position and radius. */ + GPUVertBuf *geom; /* Instanced geometry for each point in the cloud (small sphere). */ + GPUIndexBuf *geom_indices; + + GPUBatch *dots; + GPUBatch *surface; + GPUBatch **surface_per_mat; /* settings to determine if cache is invalid */ bool is_dirty; + + int mat_len; } PointCloudBatchCache; /* GPUBatch cache management. */ @@ -57,7 +65,14 @@ typedef struct PointCloudBatchCache { static bool pointcloud_batch_cache_valid(PointCloud *pointcloud) { PointCloudBatchCache *cache = pointcloud->batch_cache; - return (cache && cache->is_dirty == false); + + if (cache == NULL) { + return false; + } + if (cache->mat_len != DRW_pointcloud_material_count_get(pointcloud)) { + return false; + } + return cache->is_dirty == false; } static void pointcloud_batch_cache_init(PointCloud *pointcloud) @@ -71,6 +86,10 @@ static void pointcloud_batch_cache_init(PointCloud *pointcloud) memset(cache, 0, sizeof(*cache)); } + cache->mat_len = DRW_pointcloud_material_count_get(pointcloud); + cache->surface_per_mat = MEM_callocN(sizeof(GPUBatch *) * cache->mat_len, + "pointcloud suface_per_mat"); + cache->is_dirty = false; } @@ -109,8 +128,18 @@ static void pointcloud_batch_cache_clear(PointCloud *pointcloud) return; } - GPU_BATCH_DISCARD_SAFE(cache->batch); + GPU_BATCH_DISCARD_SAFE(cache->dots); + GPU_BATCH_DISCARD_SAFE(cache->surface); GPU_VERTBUF_DISCARD_SAFE(cache->pos); + GPU_VERTBUF_DISCARD_SAFE(cache->geom); + GPU_INDEXBUF_DISCARD_SAFE(cache->geom_indices); + + if (cache->surface_per_mat) { + for (int i = 0; i < cache->mat_len; i++) { + GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]); + } + } + MEM_SAFE_FREE(cache->surface_per_mat); } void DRW_pointcloud_batch_cache_free(PointCloud *pointcloud) @@ -126,35 +155,83 @@ static void pointcloud_batch_cache_ensure_pos(Object *ob, PointCloudBatchCache * } PointCloud *pointcloud = ob->data; + const bool has_radius = pointcloud->radius != NULL; static GPUVertFormat format = {0}; - static uint pos_id; - static uint radius_id; + static uint pos; if (format.attr_len == 0) { /* initialize vertex format */ - pos_id = GPU_vertformat_attr_add(&format, "pointcloud_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - radius_id = GPU_vertformat_attr_add( - &format, "pointcloud_radius", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + /* From the opengl wiki: + * Note that size does not have to exactly match the size used by the vertex shader. If the + * vertex shader has fewer components than the attribute provides, then the extras are ignored. + * If the vertex shader has more components than the array provides, the extras are given + * values from the vector (0, 0, 0, 1) for the missing XYZW components. + */ + int comp_len = has_radius ? 4 : 3; + pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, comp_len, GPU_FETCH_FLOAT); } - GPU_VERTBUF_DISCARD_SAFE(cache->pos); cache->pos = GPU_vertbuf_create_with_format(&format); GPU_vertbuf_data_alloc(cache->pos, pointcloud->totpoint); - GPU_vertbuf_attr_fill(cache->pos, pos_id, pointcloud->co); - if (pointcloud->radius) { - GPU_vertbuf_attr_fill(cache->pos, radius_id, pointcloud->radius); - } - else if (pointcloud->totpoint) { - /* TODO: optimize for constant radius by not including in vertex buffer at all? */ - float *radius = MEM_malloc_arrayN(pointcloud->totpoint, sizeof(float), __func__); + if (has_radius) { + float(*vbo_data)[4] = (float(*)[4])cache->pos->data; for (int i = 0; i < pointcloud->totpoint; i++) { - /* TODO: add default radius to PointCloud data structure. */ - radius[i] = 0.01f; + copy_v3_v3(vbo_data[i], pointcloud->co[i]); + /* TODO(fclem) remove multiplication here. Here only for keeping the size correct for now. */ + vbo_data[i][3] = pointcloud->radius[i] * 100.0f; } - GPU_vertbuf_attr_fill(cache->pos, radius_id, radius); - MEM_freeN(radius); } + else { + GPU_vertbuf_attr_fill(cache->pos, pos, pointcloud->co); + } +} + +static const float half_octahedron_normals[5][3] = { + {0.0f, 0.0f, 1.0f}, + {1.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, +}; + +static const uint half_octahedron_tris[4][3] = { + {0, 1, 2}, + {0, 2, 3}, + {0, 3, 4}, + {0, 4, 1}, +}; + +static void pointcloud_batch_cache_ensure_geom(Object *UNUSED(ob), PointCloudBatchCache *cache) +{ + if (cache->geom != NULL) { + return; + } + + static GPUVertFormat format = {0}; + static uint pos; + if (format.attr_len == 0) { + /* initialize vertex format */ + pos = GPU_vertformat_attr_add(&format, "pos_inst", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_alias_add(&format, "nor"); + } + + cache->geom = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(cache->geom, ARRAY_SIZE(half_octahedron_normals)); + + GPU_vertbuf_attr_fill(cache->geom, pos, half_octahedron_normals); + + GPUIndexBufBuilder builder; + GPU_indexbuf_init(&builder, + GPU_PRIM_TRIS, + ARRAY_SIZE(half_octahedron_tris), + ARRAY_SIZE(half_octahedron_normals)); + + for (int i = 0; i < ARRAY_SIZE(half_octahedron_tris); i++) { + GPU_indexbuf_add_tri_verts(&builder, UNPACK3(half_octahedron_tris[i])); + } + + cache->geom_indices = GPU_indexbuf_build(&builder); } GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) @@ -162,12 +239,47 @@ GPUBatch *DRW_pointcloud_batch_cache_get_dots(Object *ob) PointCloud *pointcloud = ob->data; PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); - if (cache->batch == NULL) { + if (cache->dots == NULL) { pointcloud_batch_cache_ensure_pos(ob, cache); - cache->batch = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, NULL); + cache->dots = GPU_batch_create(GPU_PRIM_POINTS, cache->pos, NULL); + } + + return cache->dots; +} + +GPUBatch *DRW_pointcloud_batch_cache_get_surface(Object *ob) +{ + PointCloud *pointcloud = ob->data; + PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + + if (cache->surface == NULL) { + pointcloud_batch_cache_ensure_pos(ob, cache); + pointcloud_batch_cache_ensure_geom(ob, cache); + + cache->surface = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); + GPU_batch_instbuf_add_ex(cache->surface, cache->pos, false); + } + + return cache->surface; +} + +GPUBatch **DRW_cache_pointcloud_surface_shaded_get(Object *ob, + struct GPUMaterial **UNUSED(gpumat_array), + uint gpumat_array_len) +{ + PointCloud *pointcloud = ob->data; + PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud); + BLI_assert(cache->mat_len == gpumat_array_len); + + if (cache->surface_per_mat[0] == NULL) { + pointcloud_batch_cache_ensure_pos(ob, cache); + pointcloud_batch_cache_ensure_geom(ob, cache); + + cache->surface_per_mat[0] = GPU_batch_create(GPU_PRIM_TRIS, cache->geom, cache->geom_indices); + GPU_batch_instbuf_add_ex(cache->surface_per_mat[0], cache->pos, false); } - return cache->batch; + return cache->surface_per_mat; } int DRW_pointcloud_material_count_get(PointCloud *pointcloud) diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 5dc40bcdc76..9d8050504ab 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -793,10 +793,10 @@ void DRW_shgroup_call_range( drw_command_draw_range(shgroup, geom, handle, v_sta, v_ct); } +/* A count of 0 instance will use the default number of instance in the batch. */ void DRW_shgroup_call_instance_range( DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct) { - BLI_assert(i_ct > 0); BLI_assert(geom != NULL); if (G.f & G_FLAG_PICKSEL) { drw_command_set_select_id(shgroup, NULL, DST.select_id); diff --git a/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl new file mode 100644 index 00000000000..36b67f2bd60 --- /dev/null +++ b/source/blender/draw/intern/shaders/common_pointcloud_lib.glsl @@ -0,0 +1,39 @@ + +/* NOTE: To be used with UNIFORM_RESOURCE_ID and INSTANCED_ATTR as define. */ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) + +in vec4 pos; /* Position and radius. */ + +/* ---- Instanced attribs ---- */ + +in vec3 pos_inst; +in vec3 nor; + +mat3 pointcloud_get_facing_matrix(vec3 p) +{ + mat3 facing_mat; + facing_mat[2] = normalize(ViewMatrixInverse[3].xyz - p); + facing_mat[1] = normalize(cross(ViewMatrixInverse[0].xyz, facing_mat[2])); + facing_mat[0] = cross(facing_mat[1], facing_mat[2]); + return facing_mat; +} + +/* Return world position and normal. */ +void pointcloud_get_pos_and_nor(out vec3 outpos, out vec3 outnor) +{ + vec3 p = point_object_to_world(pos.xyz); + mat3 facing_mat = pointcloud_get_facing_matrix(p); + + float radius = dot(abs(mat3(ModelMatrix) * pos.www), vec3(1.0 / 3.0)); + /* TODO(fclem) remove multiplication here. Here only for keeping the size correct for now. */ + radius *= 0.01; + outpos = p + (facing_mat * pos_inst) * radius; + outnor = facing_mat * nor; +} + +vec3 pointcloud_get_pos(void) +{ + vec3 outpos, outnor; + pointcloud_get_pos_and_nor(outpos, outnor); + return outpos; +}
\ No newline at end of file diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 2188c38ee63..095bc64a19e 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -175,6 +175,7 @@ uniform mat4 ModelMatrixInverse; #define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n) #define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n) #define normal_world_to_view(n) (mat3(ViewMatrix) * n) +#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) #define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)) #define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) |