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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c21
-rw-r--r--source/blender/draw/engines/overlay/overlay_pointcloud.c72
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h6
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c29
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c13
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_prepass_vert.glsl6
-rw-r--r--source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl7
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl38
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c21
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c14
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c24
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h37
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c50
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c24
-rw-r--r--source/blender/draw/intern/draw_cache.c13
-rw-r--r--source/blender/draw/intern/draw_cache.h1
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_pointcloud.c160
-rw-r--r--source/blender/draw/intern/draw_manager_data.c2
-rw-r--r--source/blender/draw/intern/shaders/common_pointcloud_lib.glsl39
-rw-r--r--source/blender/draw/intern/shaders/common_view_lib.glsl1
23 files changed, 404 insertions, 189 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 1ddae11999b..1abb7ecf17e 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
@@ -271,6 +270,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_material_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_merge_infront_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_prepass_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_prepass_hair_vert.glsl SRC)
+data_to_c_simple(engines/workbench/shaders/workbench_prepass_pointcloud_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_prepass_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shader_interface_lib.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_shadow_caps_geom.glsl SRC)
@@ -285,6 +285,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)
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..16604caf1d8 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);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index edf91c99531..49f182d942f 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -127,6 +127,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 +182,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 +1137,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];
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_vert.glsl b/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl
index d71ccee5159..b7886c3f681 100644
--- a/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl
+++ b/source/blender/draw/engines/overlay/shaders/pointcloud_vert.glsl
@@ -2,16 +2,15 @@
uniform vec4 color;
/* ---- Per instance Attrs ---- */
-in vec3 pointcloud_pos;
-in vec3 pointcloud_radius;
+in vec4 ptcloud; /* Position and radius. */
out vec4 finalColor;
void main()
{
- vec3 world_pos = point_object_to_world(pointcloud_pos);
+ vec3 world_pos = point_object_to_world(ptcloud.xyz);
- vec3 world_size = abs(mat3(ModelMatrix) * vec3(pointcloud_radius));
+ vec3 world_size = abs(mat3(ModelMatrix) * vec3(ptcloud.w));
float world_radius = (world_size.x + world_size.y + world_size.z) / 3.0;
gl_Position = point_world_to_ndc(world_pos);
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 ee9960ea0ef..69efc2fc392 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;
@@ -293,8 +301,8 @@ typedef struct WORKBENCH_PrivateData {
/** Object IDs buffer for curvature & outline. */
struct GPUTexture *object_id_tx;
- /** Pre-pass information for each draw types [transparent][infront][hair]. */
- WORKBENCH_Prepass prepass[2][2][2];
+ /** Pre-pass information for each draw types [transparent][infront][datatype]. */
+ WORKBENCH_Prepass prepass[2][2][WORKBENCH_DATATYPE_MAX];
/* Materials */
/** Copy of vldata->material_ubo for faster access. */
@@ -393,14 +401,16 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data);
void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const bool has_transp_mat);
/* workbench_shader.c */
-GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair);
-GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled);
+GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data);
+GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd,
+ eWORKBENCH_DataType data,
+ bool tiled);
GPUShader *workbench_shader_composite_get(WORKBENCH_PrivateData *wpd);
GPUShader *workbench_shader_merge_infront_get(WORKBENCH_PrivateData *wpd);
-GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, bool hair);
+GPUShader *workbench_shader_transparent_get(WORKBENCH_PrivateData *wpd, eWORKBENCH_DataType data);
GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd,
- bool hair,
+ eWORKBENCH_DataType data,
bool tiled);
GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd);
@@ -455,7 +465,7 @@ DRWShadingGroup *workbench_material_setup_ex(WORKBENCH_PrivateData *wpd,
Object *ob,
int mat_nr,
eV3DShadingColorType color_type,
- bool hair,
+ eWORKBENCH_DataType datatype,
bool *r_transp);
DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
Object *ob,
@@ -463,17 +473,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..7203af87c0e 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, 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 52238d2ffa4..43fec503301 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 1054f4d11c9..6dd6b0400ca 100644
--- a/source/blender/draw/intern/shaders/common_view_lib.glsl
+++ b/source/blender/draw/intern/shaders/common_view_lib.glsl
@@ -171,6 +171,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)