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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-17 18:27:08 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2020-03-18 13:23:05 +0300
commitfd53b72871e045dfebfb9ddbe2b3c491491aa913 (patch)
tree892721f97e6bff16c9d87bc3ffee295d2f4a77bc /source/blender
parentb0a1cf2c9ae696b07f7a236bc855a5ab4a493dcb (diff)
Objects: Eevee and workbench rendering of new Volume, Hair, PointCloud
Only the volume drawing part is really finished and exposed to the user. Hair plugs into the existing hair rendering code and is fairly straightforward. The pointcloud drawing is a hack using overlays rather than Eevee and workbench. The most tricky part for volume rendering is the case where each volume grid has a different transform, which requires an additional matrix in the shader and non-trivial logic in Eevee volume drawing. In the common case were all the transforms match we don't use the additional per-grid matrix in the shader. Ref T73201, T68981 Differential Revision: https://developer.blender.org/D6955
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_volume_render.h72
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/volume_render.cc358
-rw-r--r--source/blender/draw/CMakeLists.txt6
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c20
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h4
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c218
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl3
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c25
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c16
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h7
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c22
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c15
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl16
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl7
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c46
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h6
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c11
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c135
-rw-r--r--source/blender/draw/intern/draw_cache.c75
-rw-r--r--source/blender/draw/intern/draw_cache.h35
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h33
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c16
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c2
-rw-r--r--source/blender/draw/intern/draw_common.c10
-rw-r--r--source/blender/draw/intern/draw_hair.c65
-rw-r--r--source/blender/draw/intern/draw_hair_private.h7
-rw-r--r--source/blender/draw/intern/draw_manager.c12
-rw-r--r--source/blender/gpu/GPU_material.h3
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c4
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c17
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h3
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl22
35 files changed, 1170 insertions, 138 deletions
diff --git a/source/blender/blenkernel/BKE_volume_render.h b/source/blender/blenkernel/BKE_volume_render.h
new file mode 100644
index 00000000000..72360f316a0
--- /dev/null
+++ b/source/blender/blenkernel/BKE_volume_render.h
@@ -0,0 +1,72 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Brecht Van Lommel.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_VOLUME_RENDER_H__
+#define __BKE_VOLUME_RENDER_H__
+
+/** \file BKE_volume_render.h
+ * \ingroup bke
+ * \brief Volume datablock rendering and viewport drawing utilities.
+ */
+
+#include "BLI_sys_types.h"
+
+#include "DNA_volume_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Volume;
+struct VolumeGrid;
+
+/* Dense Voxels */
+
+bool BKE_volume_grid_dense_bounds(const struct Volume *volume,
+ struct VolumeGrid *volume_grid,
+ int64_t min[3],
+ int64_t max[3]);
+void BKE_volume_grid_dense_transform_matrix(const struct VolumeGrid *volume_grid,
+ const int64_t min[3],
+ const int64_t max[3],
+ float matrix[4][4]);
+void BKE_volume_grid_dense_voxels(const struct Volume *volume,
+ struct VolumeGrid *volume_grid,
+ const int64_t min[3],
+ const int64_t max[3],
+ float *voxels);
+
+/* Wireframe */
+
+typedef void (*BKE_volume_wireframe_cb)(
+ void *userdata, float (*verts)[3], int (*edges)[2], int totvert, int totedge);
+
+void BKE_volume_grid_wireframe(const struct Volume *volume,
+ struct VolumeGrid *volume_grid,
+ BKE_volume_wireframe_cb cb,
+ void *cb_userdata);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index d3dfa422ebd..7fd5470cecc 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -242,6 +242,7 @@ set(SRC
intern/undo_system.c
intern/unit.c
intern/volume.cc
+ intern/volume_render.cc
intern/workspace.c
intern/world.c
intern/writeavi.c
@@ -375,6 +376,7 @@ set(SRC
BKE_undo_system.h
BKE_unit.h
BKE_volume.h
+ BKE_volume_render.h
BKE_workspace.h
BKE_world.h
BKE_writeavi.h
diff --git a/source/blender/blenkernel/intern/volume_render.cc b/source/blender/blenkernel/intern/volume_render.cc
new file mode 100644
index 00000000000..d8fbbce3bae
--- /dev/null
+++ b/source/blender/blenkernel/intern/volume_render.cc
@@ -0,0 +1,358 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/volume_render.cc
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math_matrix.h"
+#include "BLI_math_vector.h"
+
+#include "DNA_volume_types.h"
+
+#include "BKE_volume.h"
+#include "BKE_volume_render.h"
+
+#ifdef WITH_OPENVDB
+# include <openvdb/openvdb.h>
+# include <openvdb/tools/Dense.h>
+#endif
+
+/* Dense Voxels */
+
+bool BKE_volume_grid_dense_bounds(const Volume *volume,
+ VolumeGrid *volume_grid,
+ int64_t min[3],
+ int64_t max[3])
+{
+#ifdef WITH_OPENVDB
+ openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+
+ openvdb::CoordBBox bbox = grid->evalActiveVoxelBoundingBox();
+ if (!bbox.empty()) {
+ /* OpenVDB bbox is inclusive, so add 1 to convert. */
+ min[0] = bbox.min().x();
+ min[1] = bbox.min().y();
+ min[2] = bbox.min().z();
+ max[0] = bbox.max().x() + 1;
+ max[1] = bbox.max().y() + 1;
+ max[2] = bbox.max().z() + 1;
+ return true;
+ }
+#else
+ UNUSED_VARS(volume, volume_grid);
+#endif
+
+ min[0] = 0;
+ min[1] = 0;
+ min[2] = 0;
+ max[0] = 0;
+ max[1] = 0;
+ max[2] = 0;
+ return false;
+}
+
+/* Transform matrix from unit cube to object space, for 3D texture sampling. */
+void BKE_volume_grid_dense_transform_matrix(const VolumeGrid *volume_grid,
+ const int64_t min[3],
+ const int64_t max[3],
+ float mat[4][4])
+{
+#ifdef WITH_OPENVDB
+ float index_to_world[4][4];
+ BKE_volume_grid_transform_matrix(volume_grid, index_to_world);
+
+ float texture_to_index[4][4];
+ float loc[3] = {(float)min[0], (float)min[1], (float)min[2]};
+ float size[3] = {(float)(max[0] - min[0]), (float)(max[1] - min[1]), (float)(max[2] - min[2])};
+ size_to_mat4(texture_to_index, size);
+ copy_v3_v3(texture_to_index[3], loc);
+
+ mul_m4_m4m4(mat, index_to_world, texture_to_index);
+#else
+ UNUSED_VARS(volume_grid, min, max);
+ unit_m4(mat);
+#endif
+}
+
+void BKE_volume_grid_dense_voxels(const Volume *volume,
+ VolumeGrid *volume_grid,
+ const int64_t min[3],
+ const int64_t max[3],
+ float *voxels)
+{
+#ifdef WITH_OPENVDB
+ openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+
+ /* Convert to OpenVDB inclusive bbox with -1. */
+ openvdb::CoordBBox bbox(min[0], min[1], min[2], max[0] - 1, max[1] - 1, max[2] - 1);
+
+ switch (BKE_volume_grid_type(volume_grid)) {
+ case VOLUME_GRID_BOOLEAN: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_FLOAT: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_DOUBLE: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_INT: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_INT64: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_MASK: {
+ openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_FLOAT: {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_DOUBLE: {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_INT: {
+ openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
+ bbox, (openvdb::Vec3f *)voxels);
+ openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
+ break;
+ }
+ case VOLUME_GRID_STRING:
+ case VOLUME_GRID_POINTS:
+ case VOLUME_GRID_UNKNOWN: {
+ /* Zero channels to copy. */
+ break;
+ }
+ }
+#else
+ UNUSED_VARS(volume, volume_grid, min, max, voxels);
+#endif
+}
+
+/* Wireframe */
+
+#ifdef WITH_OPENVDB
+struct VolumeWireframe {
+ std::vector<openvdb::Vec3f> verts;
+ std::vector<openvdb::Vec2I> edges;
+
+ template<typename GridType>
+ void add_grid(openvdb::GridBase::ConstPtr gridbase, const bool points, const bool coarse)
+ {
+ using TreeType = typename GridType::TreeType;
+ using Depth2Type = typename TreeType::RootNodeType::ChildNodeType::ChildNodeType;
+ using NodeCIter = typename TreeType::NodeCIter;
+ using GridConstPtr = typename GridType::ConstPtr;
+
+ GridConstPtr grid = openvdb::gridConstPtrCast<GridType>(gridbase);
+ const openvdb::math::Transform &transform = grid->transform();
+ const int depth = (coarse) ? 2 : 3;
+
+ NodeCIter iter = grid->tree().cbeginNode();
+ iter.setMaxDepth(depth);
+
+ for (; iter; ++iter) {
+ if (iter.getDepth() == depth) {
+ openvdb::CoordBBox coordbbox;
+
+ if (depth == 2) {
+ /* Internal node at depth 2. */
+ const Depth2Type *node = nullptr;
+ iter.getNode(node);
+ if (node) {
+ node->evalActiveBoundingBox(coordbbox, false);
+ }
+ else {
+ continue;
+ }
+ }
+ else {
+ /* Leaf node. */
+ if (!iter.getBoundingBox(coordbbox)) {
+ continue;
+ }
+ }
+
+ /* +1 to convert from exclusive to include bounds. */
+ coordbbox.max() = coordbbox.max().offsetBy(1);
+ openvdb::BBoxd bbox = transform.indexToWorld(coordbbox);
+
+ if (points) {
+ add_point(bbox);
+ }
+ else {
+ add_box(bbox);
+ }
+ }
+ }
+ }
+
+ void add_point(const openvdb::BBoxd &bbox)
+ {
+ verts.push_back(bbox.getCenter());
+ }
+
+ void add_box(const openvdb::BBoxd &bbox)
+ {
+ /* TODO: deduplicate edges, hide flat edges? */
+ openvdb::Vec3f min = bbox.min();
+ openvdb::Vec3f max = bbox.max();
+
+ const int vert_offset = verts.size();
+ const int edge_offset = edges.size();
+
+ /* Create vertices. */
+ verts.resize(vert_offset + 8);
+ verts[vert_offset + 0] = openvdb::Vec3f(min[0], min[1], min[2]);
+ verts[vert_offset + 1] = openvdb::Vec3f(max[0], min[1], min[2]);
+ verts[vert_offset + 2] = openvdb::Vec3f(max[0], max[1], min[2]);
+ verts[vert_offset + 3] = openvdb::Vec3f(min[0], max[1], min[2]);
+ verts[vert_offset + 4] = openvdb::Vec3f(min[0], min[1], max[2]);
+ verts[vert_offset + 5] = openvdb::Vec3f(max[0], min[1], max[2]);
+ verts[vert_offset + 6] = openvdb::Vec3f(max[0], max[1], max[2]);
+ verts[vert_offset + 7] = openvdb::Vec3f(min[0], max[1], max[2]);
+
+ /* Create edges. */
+ const int box_edges[12][2] = {{0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 0},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 4},
+ {0, 4},
+ {1, 5},
+ {2, 6},
+ {3, 7}};
+
+ edges.resize(edge_offset + 12);
+ for (int i = 0; i < 12; i++) {
+ edges[edge_offset + i] = openvdb::Vec2I(vert_offset + box_edges[i][0],
+ vert_offset + box_edges[i][1]);
+ }
+ }
+};
+#endif
+
+void BKE_volume_grid_wireframe(const Volume *volume,
+ VolumeGrid *volume_grid,
+ BKE_volume_wireframe_cb cb,
+ void *cb_userdata)
+{
+#ifdef WITH_OPENVDB
+ VolumeWireframe wireframe;
+
+ if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) {
+ /* Nothing. */
+ }
+ else if (volume->display.wireframe_type == VOLUME_WIREFRAME_BOUNDS) {
+ /* Bounding box. */
+ float min[3], max[3];
+ BKE_volume_grid_bounds(volume_grid, min, max);
+
+ openvdb::BBoxd bbox(min, max);
+ wireframe.add_box(bbox);
+ }
+ else {
+ /* Tree nodes. */
+ openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
+ const bool points = (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS);
+ const bool coarse = (volume->display.wireframe_detail == VOLUME_WIREFRAME_COARSE);
+
+ switch (BKE_volume_grid_type(volume_grid)) {
+ case VOLUME_GRID_BOOLEAN: {
+ wireframe.add_grid<openvdb::BoolGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_FLOAT: {
+ wireframe.add_grid<openvdb::FloatGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_DOUBLE: {
+ wireframe.add_grid<openvdb::DoubleGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_INT: {
+ wireframe.add_grid<openvdb::Int32Grid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_INT64: {
+ wireframe.add_grid<openvdb::Int64Grid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_MASK: {
+ wireframe.add_grid<openvdb::MaskGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_FLOAT: {
+ wireframe.add_grid<openvdb::Vec3fGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_DOUBLE: {
+ wireframe.add_grid<openvdb::Vec3dGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_VECTOR_INT: {
+ wireframe.add_grid<openvdb::Vec3IGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_STRING: {
+ wireframe.add_grid<openvdb::StringGrid>(grid, points, coarse);
+ break;
+ }
+ case VOLUME_GRID_POINTS:
+ case VOLUME_GRID_UNKNOWN: {
+ break;
+ }
+ }
+ }
+
+ cb(cb_userdata,
+ (float(*)[3])wireframe.verts.data(),
+ (int(*)[2])wireframe.edges.data(),
+ wireframe.verts.size(),
+ wireframe.edges.size());
+#else
+ UNUSED_VARS(volume, volume_grid);
+ cb(cb_userdata, NULL, NULL, 0, 0);
+#endif
+}
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 81f2214b402..46263f694cb 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -53,10 +53,13 @@ set(SRC
intern/draw_cache_impl_curve.c
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_gpencil.c
+ intern/draw_cache_impl_hair.c
intern/draw_cache_impl_lattice.c
intern/draw_cache_impl_mesh.c
intern/draw_cache_impl_metaball.c
intern/draw_cache_impl_particles.c
+ intern/draw_cache_impl_pointcloud.c
+ intern/draw_cache_impl_volume.c
intern/draw_color_management.c
intern/draw_common.c
intern/draw_debug.c
@@ -139,6 +142,7 @@ 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
@@ -377,6 +381,8 @@ 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/volume_velocity_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a886fa26589..70933e21719 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -127,6 +127,12 @@ void EEVEE_cache_populate(void *vedata, Object *ob)
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow);
}
+ else if (ob->type == OB_HAIR) {
+ EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
+ }
+ else if (ob->type == OB_VOLUME) {
+ EEVEE_volumes_cache_object_add(sldata, vedata, draw_ctx->scene, ob);
+ }
else if (!USE_SCENE_LIGHT(draw_ctx->v3d)) {
/* do not add any scene light sources to the cache */
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 230a0725493..bb64fe32bc3 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -32,9 +32,10 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "DNA_world_types.h"
+#include "DNA_hair_types.h"
#include "DNA_modifier_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
#include "GPU_material.h"
@@ -1021,7 +1022,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
EEVEE_PassList *psl = vedata->psl;
- BLI_assert(!is_hair || (ob && psys && md));
+ BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
@@ -1715,7 +1716,12 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot)
{
Material *ma = BKE_object_material_get(ob, slot + 1);
if (ma == NULL) {
- ma = BKE_material_default_empty();
+ if (ob->type == OB_VOLUME) {
+ ma = BKE_material_default_volume();
+ }
+ else {
+ ma = BKE_material_default_empty();
+ }
}
return ma;
}
@@ -2064,6 +2070,14 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
}
}
+void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Object *ob,
+ bool *cast_shadow)
+{
+ eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, HAIR_MATERIAL_NR, cast_shadow);
+}
+
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 52fb8b3cced..e2470b4fa76 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -902,6 +902,10 @@ void EEVEE_particle_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow);
+void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Object *ob,
+ bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index eedc64f32e6..c8357b56b18 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -177,7 +177,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
void EEVEE_render_cache(void *vedata,
struct Object *ob,
struct RenderEngine *engine,
- struct Depsgraph *UNUSED(depsgraph))
+ struct Depsgraph *depsgraph)
{
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_LightProbesInfo *pinfo = sldata->probes;
@@ -211,6 +211,13 @@ void EEVEE_render_cache(void *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow);
}
+ else if (ob->type == OB_HAIR) {
+ EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
+ }
+ else if (ob->type == OB_VOLUME) {
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
+ }
else if (ob->type == OB_LIGHTPROBE) {
EEVEE_lightprobes_cache_add(sldata, vedata, ob);
}
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 41f8dddf0fb..0e82ac237c0 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -29,11 +29,15 @@
#include "DNA_object_force_types.h"
#include "DNA_fluid_types.h"
+#include "DNA_volume_types.h"
#include "DNA_world_types.h"
-#include "BKE_modifier.h"
-#include "BKE_mesh.h"
#include "BKE_fluid.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_volume.h"
+#include "BKE_volume_render.h"
#include "ED_screen.h"
@@ -59,6 +63,7 @@ static struct {
GPUTexture *depth_src;
GPUTexture *dummy_density;
+ GPUTexture *dummy_color;
GPUTexture *dummy_flame;
GPUTexture *dummy_scatter;
@@ -368,8 +373,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid;
- gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
@@ -390,64 +394,92 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-typedef struct EEVEE_InstanceVolumeMatrix {
- DrawData dd;
- float volume_mat[4][4];
-} EEVEE_InstanceVolumeMatrix;
-
-void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Scene *scene,
- Object *ob)
+static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWShadingGroup *grp)
{
- static const float white[3] = {1.0f, 1.0f, 1.0f};
-
- float *texcoloc = NULL;
- float *texcosize = NULL;
- struct ModifierData *md = NULL;
- Material *ma = BKE_object_material_get(ob, 1);
-
- if (ma == NULL) {
- return;
+ Volume *volume = ob->data;
+ BKE_volume_load(volume, G.main);
+
+ /* Test if we need to use multiple transforms. */
+ DRWVolumeGrid *first_drw_grid = NULL;
+ bool multiple_transforms = true;
+
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
+ VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name);
+ DRWVolumeGrid *drw_grid = (volume_grid) ?
+ DRW_volume_batch_cache_get_grid(volume, volume_grid) :
+ NULL;
+
+ if (drw_grid) {
+ if (first_drw_grid == NULL) {
+ first_drw_grid = drw_grid;
+ }
+ else if (drw_grid &&
+ !equals_m4m4(drw_grid->object_to_texture, first_drw_grid->object_to_texture)) {
+ multiple_transforms = true;
+ break;
+ }
+ }
}
- float size[3];
- mat4_to_size(size, ob->obmat);
- /* Check if any of the axes have 0 length. (see T69070) */
- const float epsilon = 1e-8f;
- if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) {
- return;
+ /* Bail out of no grids to render. */
+ if (first_drw_grid == NULL) {
+ return false;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
- eGPUMaterialStatus status = GPU_material_status(mat);
-
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
+ /* Set transform matrix for the volume as a whole. This one is also used for
+ * clipping so must map the entire bounding box to 0..1. */
+ float bounds_to_object[4][4];
+
+ if (multiple_transforms) {
+ /* For multiple grids with different transform, we first transform from object space
+ * to bounds, then for each individual grid from bounds to texture. */
+ BoundBox *bb = BKE_volume_boundbox_get(ob);
+ float bb_size[3];
+ sub_v3_v3v3(bb_size, bb->vec[6], bb->vec[0]);
+ size_to_mat4(bounds_to_object, bb_size);
+ copy_v3_v3(bounds_to_object[3], bb->vec[0]);
+
+ invert_m4_m4(first_drw_grid->object_to_bounds, bounds_to_object);
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_bounds);
}
- /* If shader failed to compile or is currently compiling. */
- if (status != GPU_MAT_SUCCESS) {
- return;
+ else {
+ /* All grid transforms are equal, we can transform to texture space immediately. */
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", first_drw_grid->object_to_texture);
}
- DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
-
- BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, &texcosize);
+ /* Don't use orco transform here, only matrix. */
+ DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoLoc", (float[3]){0.5f, 0.5f, 0.5f});
+ DRW_shgroup_uniform_vec3_copy(grp, "volumeOrcoSize", (float[3]){0.5f, 0.5f, 0.5f});
+
+ /* Bind volume grid textures. */
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
+ VolumeGrid *volume_grid = BKE_volume_grid_find(volume, gpu_grid->name);
+ DRWVolumeGrid *drw_grid = (volume_grid) ?
+ DRW_volume_batch_cache_get_grid(volume, volume_grid) :
+ NULL;
+
+ DRW_shgroup_uniform_texture(
+ grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_density);
+
+ if (drw_grid && multiple_transforms) {
+ /* Specify per-volume tranform matrix that is applied after the
+ * transform from object to bounds. */
+ mul_m4_m4m4(drw_grid->bounds_to_texture, drw_grid->object_to_texture, bounds_to_object);
+ DRW_shgroup_uniform_mat4(grp, gpu_grid->transform_name, drw_grid->bounds_to_texture);
+ }
+ }
- /* TODO(fclem) remove those "unnecessary" UBOs */
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ return true;
+}
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
- DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
+static bool eevee_volume_object_mesh_init(Scene *scene,
+ Object *ob,
+ ListBase *gpu_grids,
+ DRWShadingGroup *grp)
+{
+ static const float white[3] = {1.0f, 1.0f, 1.0f};
+ ModifierData *md = NULL;
- ListBase gpu_grids = GPU_material_volume_grids(mat);
/* Smoke Simulation */
if (((ob->base_flag & BASE_FROM_DUPLI) == 0) &&
(md = modifiers_findByType(ob, eModifierType_Fluid)) &&
@@ -458,7 +490,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
/* Don't try to show liquid domains here. */
if (!mds->fluid || !(mds->type == FLUID_DOMAIN_TYPE_GAS)) {
- return;
+ return false;
}
/* Don't show smoke before simulation starts, this could be made an option in the future. */
@@ -479,7 +511,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(mmd));
}
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
if (STREQ(gpu_grid->name, "density")) {
DRW_shgroup_uniform_texture_ref(grp,
gpu_grid->sampler_name,
@@ -510,10 +542,85 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_vec2(grp, "volumeTemperature", &mds->flame_ignition, 1);
}
else {
- for (GPUMaterialVolumeGrid *gpu_grid = gpu_grids.first; gpu_grid; gpu_grid = gpu_grid->next) {
+ LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
}
- DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
+ }
+
+ /* Transform for mesh volumes. */
+ static const float unit_mat[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f, 0.0f},
+ {0.0f, 0.0f, 1.0f, 0.0f},
+ {0.0f, 0.0f, 0.0f, 1.0f}};
+ float *texco_loc, *texco_size;
+ BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texco_loc, &texco_size);
+
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", unit_mat);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texco_loc, 1);
+ DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texco_size, 1);
+
+ return true;
+}
+
+void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ Scene *scene,
+ Object *ob)
+{
+ Material *ma = BKE_object_material_get(ob, 1);
+
+ if (ma == NULL) {
+ if (ob->type == OB_VOLUME) {
+ ma = BKE_material_default_volume();
+ }
+ else {
+ return;
+ }
+ }
+
+ float size[3];
+ mat4_to_size(size, ob->obmat);
+ /* Check if any of the axes have 0 length. (see T69070) */
+ const float epsilon = 1e-8f;
+ if ((size[0] < epsilon) || (size[1] < epsilon) || (size[2] < epsilon)) {
+ return;
+ }
+
+ struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ eGPUMaterialStatus status = GPU_material_status(mat);
+
+ if (status == GPU_MAT_QUEUED) {
+ vedata->stl->g_data->queued_shaders_count++;
+ }
+ /* If shader failed to compile or is currently compiling. */
+ if (status != GPU_MAT_SUCCESS) {
+ return;
+ }
+
+ DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
+
+ /* TODO(fclem) remove those "unnecessary" UBOs */
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(
+ grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ ListBase gpu_grids = GPU_material_volume_grids(mat);
+
+ if (ob->type == OB_VOLUME) {
+ if (!eevee_volume_object_grids_init(ob, &gpu_grids, grp)) {
+ return;
+ }
+ }
+ else {
+ if (!eevee_volume_object_mesh_init(scene, ob, &gpu_grids, grp)) {
+ return;
+ }
}
/* TODO Reduce to number of slices intersecting. */
@@ -757,6 +864,7 @@ void EEVEE_volumes_free(void)
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 2b1ae60654e..f5e92cd7495 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -7,6 +7,7 @@
#ifdef MESH_SHADER
uniform vec3 volumeOrcoLoc;
uniform vec3 volumeOrcoSize;
+uniform mat4 volumeObjectToTexture;
#endif
flat in int slice;
@@ -35,8 +36,10 @@ void main()
worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
volumeObjectLocalCoord = point_world_to_object(worldPosition);
+ /* TODO: redundant transform */
volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) /
(volumeOrcoSize * 2.0);
+ volumeObjectLocalCoord = (volumeObjectToTexture * vec4(volumeObjectLocalCoord, 1.0)).xyz;
if (any(lessThan(volumeObjectLocalCoord, vec3(0.0))) ||
any(greaterThan(volumeObjectLocalCoord, vec3(1.0))))
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index 740ca42800e..9b900a53d8d 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -161,6 +161,7 @@ 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);
}
@@ -205,6 +206,11 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj
return pd->ctx_mode == CTX_MODE_EDIT_METABALL;
case OB_FONT:
return pd->ctx_mode == CTX_MODE_EDIT_TEXT;
+ case OB_HAIR:
+ case OB_POINTCLOUD:
+ case OB_VOLUME:
+ /* No edit mode yet. */
+ return false;
}
}
return false;
@@ -223,8 +229,16 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool in_paint_mode = (ob == draw_ctx->obact) &&
(draw_ctx->object_mode & OB_MODE_ALL_PAINT);
const bool in_sculpt_mode = (ob == draw_ctx->obact) && (ob->sculpt != NULL);
- const bool has_surface = ELEM(
- ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_MBALL, OB_FONT, OB_GPENCIL);
+ const bool has_surface = ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_SURF,
+ OB_MBALL,
+ OB_FONT,
+ OB_GPENCIL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME);
const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE));
const bool draw_facing = draw_surface && (pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION);
const bool draw_bones = (pd->overlay.flag & V3D_OVERLAY_HIDE_BONES) == 0;
@@ -361,6 +375,12 @@ 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);
@@ -434,6 +454,7 @@ 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_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 53550fb115e..4c525acd5be 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -475,13 +475,25 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons
texcosize = mb->size;
break;
}
+ case ID_HA:
+ case ID_PT:
+ case ID_VO: {
+ /* No user defined texture space support. */
+ break;
+ }
default:
BLI_assert(0);
}
float mat[4][4];
- size_to_mat4(mat, texcosize);
- copy_v3_v3(mat[3], texcoloc);
+
+ if (texcoloc != NULL && texcosize != NULL) {
+ size_to_mat4(mat, texcosize);
+ copy_v3_v3(mat[3], texcoloc);
+ }
+ else {
+ unit_m4(mat);
+ }
mul_m4_m4m4(mat, ob->obmat, mat);
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 167a8e940df..de35d4f760e 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -95,6 +95,7 @@ typedef struct OVERLAY_PassList {
DRWPass *paint_color_ps;
DRWPass *paint_overlay_ps;
DRWPass *particle_ps;
+ DRWPass *pointcloud_ps;
DRWPass *sculpt_mask_ps;
DRWPass *wireframe_ps;
DRWPass *wireframe_xray_ps;
@@ -251,6 +252,7 @@ typedef struct OVERLAY_PrivateData {
DRWShadingGroup *paint_face_grp;
DRWShadingGroup *particle_dots_grp;
DRWShadingGroup *particle_shapes_grp;
+ DRWShadingGroup *pointcloud_dots_grp;
DRWShadingGroup *sculpt_mask_grp;
DRWShadingGroup *wires_grp[2][2]; /* With and without coloring. */
DRWShadingGroup *wires_all_grp[2][2]; /* With and without coloring. */
@@ -532,6 +534,10 @@ 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);
@@ -597,6 +603,7 @@ 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(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index d5509c7f56b..0b2f98294ec 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -102,6 +102,8 @@ 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_volume_velocity_vert_glsl[];
extern char datatoc_wireframe_vert_glsl[];
@@ -184,6 +186,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *paint_wire;
GPUShader *particle_dot;
GPUShader *particle_shape;
+ GPUShader *pointcloud_dot;
GPUShader *sculpt_mask;
GPUShader *uniform_color;
GPUShader *volume_velocity_needle_sh;
@@ -1272,6 +1275,25 @@ 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 6b0e5e0b72e..cdf8005b827 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -22,6 +22,7 @@
#include "DNA_mesh_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_volume_types.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
@@ -163,6 +164,20 @@ 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) {
+ float *color;
+ OVERLAY_ExtraCallBuffers *cb = OVERLAY_extra_call_buffer_get(vedata, ob);
+ DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
+
+ struct GPUBatch *geom = DRW_cache_object_face_wireframe_get(ob);
+ OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
+ return;
+ }
+ }
+
const bool is_edit_mode = DRW_object_is_in_edit_mode(ob);
bool has_edit_mesh_cage = false;
if (is_mesh && is_edit_mode) {
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index e957f8bbe9c..0c2b7850f94 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -11,6 +11,7 @@ uniform sampler3D shadowTexture;
uniform sampler3D flameTexture;
uniform sampler1D flameColorTexture;
uniform sampler1D transferTexture;
+uniform mat4 volumeObjectToTexture;
uniform int samplesLen = 256;
uniform float noiseOfs = 0.0;
@@ -110,20 +111,24 @@ void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction)
scattering = tval.rgb * 1500.0;
extinction = max(1e-4, tval.a * 50.0);
#else
+# ifdef VOLUME_SMOKE
float flame = sample_volume_texture(flameTexture, co).r;
vec4 emission = texture(flameColorTexture, flame);
+# endif
+ vec3 density = sample_volume_texture(densityTexture, co).rgb;
float shadows = sample_volume_texture(shadowTexture, co).r;
- vec4 density = sample_volume_texture(densityTexture, co); /* rgb: color, a: density */
- scattering = density.rgb * densityScale;
+ scattering = density * densityScale;
extinction = max(1e-4, dot(scattering, vec3(0.33333)));
scattering *= activeColor;
/* Scale shadows in log space and clamp them to avoid completely black shadows. */
scattering *= exp(clamp(log(shadows) * densityScale * 0.1, -2.5, 0.0)) * M_PI;
+# ifdef VOLUME_SMOKE
/* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */
scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0;
+# endif
#endif
}
@@ -201,9 +206,16 @@ void main()
vec3 ls_ray_ori = point_view_to_object(vs_ray_ori);
vec3 ls_ray_end = point_view_to_object(vs_ray_end);
+# ifdef VOLUME_SMOKE
ls_ray_dir = (OrcoTexCoFactors[0].xyz + ls_ray_dir * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
ls_ray_ori = (OrcoTexCoFactors[0].xyz + ls_ray_ori * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
ls_ray_end = (OrcoTexCoFactors[0].xyz + ls_ray_end * OrcoTexCoFactors[1].xyz) * 2.0 - 1.0;
+# else
+ ls_ray_dir = (volumeObjectToTexture * vec4(ls_ray_dir, 1.0)).xyz * 2.0f - 1.0;
+ ls_ray_ori = (volumeObjectToTexture * vec4(ls_ray_ori, 1.0)).xyz * 2.0f - 1.0;
+ ls_ray_end = (volumeObjectToTexture * vec4(ls_ray_end, 1.0)).xyz * 2.0f - 1.0;
+# endif
+
ls_ray_dir -= ls_ray_ori;
/* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
index 1a32a202290..7327a92e04f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
@@ -5,6 +5,8 @@
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
+uniform mat4 volumeTextureToObject;
+
in vec3 pos;
RESOURCE_ID_VARYING
@@ -31,7 +33,12 @@ void main()
#else
vec3 final_pos = pos;
#endif
+
+#ifdef VOLUME_SMOKE
final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0].xyz) / OrcoTexCoFactors[1].xyz;
+#else
+ final_pos = (volumeTextureToObject * vec4(final_pos * 0.5 + 0.5, 1.0)).xyz;
+#endif
gl_Position = point_object_to_ndc(final_pos);
PASS_RESOURCE_ID
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 742489c7311..e9525af5682 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -33,8 +33,9 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
-#include "DNA_image_types.h"
#include "DNA_fluid_types.h"
+#include "DNA_hair_types.h"
+#include "DNA_image_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
@@ -192,12 +193,12 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd,
static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
Object *ob,
+ ParticleSystem *psys,
ModifierData *md,
eV3DShadingColorType color_type,
- bool use_texpaint_mode)
+ bool use_texpaint_mode,
+ const int matnr)
{
- ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
- ParticleSettings *part = psys->part;
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene = draw_ctx->scene;
@@ -206,8 +207,8 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
int interp = (imapaint && imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
SHD_INTERP_CLOSEST;
DRWShadingGroup *grp = (use_texpaint_mode) ?
- workbench_image_hair_setup(wpd, ob, part->omat, ima, NULL, interp) :
- workbench_material_hair_setup(wpd, ob, part->omat, color_type);
+ workbench_image_hair_setup(wpd, ob, matnr, ima, NULL, interp) :
+ workbench_material_hair_setup(wpd, ob, matnr, color_type);
DRW_shgroup_hair_create_sub(ob, psys, md, grp);
}
@@ -244,14 +245,20 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
color_type = V3D_SHADING_OBJECT_COLOR;
}
- *r_sculpt_pbvh = is_sculpt_pbvh;
- *r_texpaint_mode = false;
+ if (r_sculpt_pbvh) {
+ *r_sculpt_pbvh = is_sculpt_pbvh;
+ }
+ if (r_texpaint_mode) {
+ *r_texpaint_mode = false;
+ }
if (!is_sculpt_pbvh && !is_render) {
/* Force texture or vertex mode if object is in paint mode. */
if (is_texpaint_mode && me && me->mloopuv) {
color_type = V3D_SHADING_TEXTURE_COLOR;
- *r_texpaint_mode = true;
+ if (r_texpaint_mode) {
+ *r_texpaint_mode = true;
+ }
}
else if (is_vertpaint_mode && me && me->mloopcol) {
color_type = V3D_SHADING_VERTEX_COLOR;
@@ -286,8 +293,8 @@ void workbench_cache_populate(void *ved, Object *ob)
}
if (ob->type == OB_MESH && ob->modifiers.first != NULL) {
- bool use_sculpt_pbvh, use_texpaint_mode;
- int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, NULL);
+ bool use_texpaint_mode;
+ int color_type = workbench_color_type_get(wpd, ob, NULL, &use_texpaint_mode, NULL);
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type != eModifierType_ParticleSystem) {
@@ -301,7 +308,8 @@ void workbench_cache_populate(void *ved, Object *ob)
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
- workbench_cache_hair_populate(wpd, ob, md, color_type, use_texpaint_mode);
+ workbench_cache_hair_populate(
+ wpd, ob, psys, md, color_type, use_texpaint_mode, part->omat);
}
}
}
@@ -311,7 +319,7 @@ void workbench_cache_populate(void *ved, Object *ob)
if (md && modifier_isEnabled(wpd->scene, md, eModifierMode_Realtime)) {
FluidModifierData *fmd = (FluidModifierData *)md;
if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) {
- workbench_volume_cache_populate(vedata, wpd->scene, ob, md);
+ workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR);
return; /* Do not draw solid in this case. */
}
}
@@ -325,7 +333,7 @@ void workbench_cache_populate(void *ved, Object *ob)
return;
}
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
+ if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_POINTCLOUD)) {
bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false;
eV3DShadingColorType color_type = workbench_color_type_get(
wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow);
@@ -344,6 +352,16 @@ void workbench_cache_populate(void *ved, Object *ob)
workbench_shadow_cache_populate(vedata, ob, has_transp_mat);
}
}
+ else if (ob->type == OB_HAIR) {
+ int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
+ workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, HAIR_MATERIAL_NR);
+ }
+ else if (ob->type == OB_VOLUME) {
+ if (wpd->shading.type != OB_WIRE) {
+ int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
+ workbench_volume_cache_populate(vedata, wpd->scene, ob, NULL, color_type);
+ }
+ }
}
void workbench_cache_finish(void *ved)
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index a68b66e0f85..49becf93f48 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -101,6 +101,7 @@ typedef struct WORKBENCH_TextureList {
struct GPUTexture *smaa_area_tx;
struct GPUTexture *dummy_image_tx;
struct GPUTexture *dummy_volume_tx;
+ struct GPUTexture *dummy_shadow_tx;
struct GPUTexture *dummy_coba_tx;
} WORKBENCH_TextureList;
@@ -405,7 +406,7 @@ GPUShader *workbench_shader_outline_get(void);
GPUShader *workbench_shader_antialiasing_accumulation_get(void);
GPUShader *workbench_shader_antialiasing_get(int stage);
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic);
+GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke);
void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **downsample_sh,
@@ -479,7 +480,8 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata);
void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
struct Scene *UNUSED(scene),
struct Object *ob,
- struct ModifierData *md);
+ struct ModifierData *md,
+ eV3DShadingColorType color_type);
void workbench_volume_draw_pass(WORKBENCH_Data *vedata);
void workbench_volume_draw_finish(WORKBENCH_Data *vedata);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 14a980fe628..2e796056029 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -106,7 +106,7 @@ static struct {
struct GPUShader *aa_accum_sh;
struct GPUShader *smaa_sh[3];
- struct GPUShader *volume_sh[2][2][2];
+ struct GPUShader *volume_sh[2][2][2][2];
struct DRWShaderLibrary *lib;
} e_data = {{{{NULL}}}};
@@ -448,9 +448,9 @@ GPUShader *workbench_shader_antialiasing_get(int stage)
return e_data.smaa_sh[stage];
}
-GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic)
+GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic, bool smoke)
{
- GPUShader **shader = &e_data.volume_sh[slice][coba][cubic];
+ GPUShader **shader = &e_data.volume_sh[slice][coba][cubic][smoke];
if (*shader == NULL) {
DynStr *ds = BLI_dynstr_new();
@@ -464,6 +464,9 @@ GPUShader *workbench_shader_volume_get(bool slice, bool coba, bool cubic)
if (cubic) {
BLI_dynstr_append(ds, "#define USE_TRICUBIC\n");
}
+ if (smoke) {
+ BLI_dynstr_append(ds, "#define VOLUME_SMOKE\n");
+ }
char *defines = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -513,7 +516,7 @@ void workbench_shader_free(void)
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
for (int j = 0; j < sizeof(e_data.volume_sh) / sizeof(void *); j++) {
- struct GPUShader **sh_array = &e_data.volume_sh[0][0][0];
+ struct GPUShader **sh_array = &e_data.volume_sh[0][0][0][0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index a3072b834bd..1eccc99d9e9 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -22,16 +22,20 @@
#include "workbench_private.h"
-#include "BKE_object.h"
-#include "BKE_fluid.h"
+#include "DNA_fluid_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_force_types.h"
+#include "DNA_volume_types.h"
#include "BLI_rand.h"
#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_force_types.h"
-#include "DNA_fluid_types.h"
+#include "BKE_fluid.h"
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_volume.h"
+#include "BKE_volume_render.h"
#include "GPU_draw.h"
@@ -40,9 +44,11 @@ void workbench_volume_engine_init(WORKBENCH_Data *vedata)
WORKBENCH_TextureList *txl = vedata->txl;
if (txl->dummy_volume_tx == NULL) {
- float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, pixel, NULL);
- txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, pixel, NULL);
+ float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ txl->dummy_volume_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, zero, NULL);
+ txl->dummy_shadow_tx = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, one, NULL);
+ txl->dummy_coba_tx = GPU_texture_create_1d(1, GPU_RGBA8, zero, NULL);
}
}
@@ -54,10 +60,9 @@ void workbench_volume_cache_init(WORKBENCH_Data *vedata)
vedata->stl->wpd->volumes_do = false;
}
-void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
- Scene *UNUSED(scene),
- Object *ob,
- ModifierData *md)
+static void workbench_volume_modifier_cache_populate(WORKBENCH_Data *vedata,
+ Object *ob,
+ ModifierData *md)
{
FluidModifierData *mmd = (FluidModifierData *)md;
FluidDomainSettings *mds = mmd->domain;
@@ -90,8 +95,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
const bool use_slice = (mds->slice_method == FLUID_DOMAIN_SLICE_AXIS_ALIGNED &&
mds->axis_slice_method == AXIS_SLICE_SINGLE);
const bool cubic_interp = (mds->interp_method == VOLUME_INTERP_CUBIC);
-
- GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp);
+ GPUShader *sh = workbench_shader_volume_get(use_slice, mds->use_coba, cubic_interp, true);
if (use_slice) {
float invviewmat[4][4];
@@ -162,6 +166,107 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(mmd));
}
+static void workbench_volume_material_color(WORKBENCH_PrivateData *wpd,
+ Object *ob,
+ eV3DShadingColorType color_type,
+ float color[3])
+{
+ Material *ma = BKE_object_material_get(ob, VOLUME_MATERIAL_NR);
+ WORKBENCH_UBO_Material ubo_data;
+ workbench_material_ubo_data(wpd, ob, ma, &ubo_data, color_type);
+ copy_v3_v3(color, ubo_data.base_color);
+}
+
+static void workbench_volume_object_cache_populate(WORKBENCH_Data *vedata,
+ Object *ob,
+ eV3DShadingColorType color_type)
+{
+ /* Create 3D textures. */
+ Volume *volume = ob->data;
+ BKE_volume_load(volume, G.main);
+ VolumeGrid *volume_grid = BKE_volume_grid_active_get(volume);
+ if (volume_grid == NULL) {
+ return;
+ }
+ DRWVolumeGrid *grid = DRW_volume_batch_cache_get_grid(volume, volume_grid);
+ if (grid == NULL) {
+ return;
+ }
+
+ WORKBENCH_PrivateData *wpd = vedata->stl->wpd;
+ WORKBENCH_TextureList *txl = vedata->txl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ wpd->volumes_do = true;
+
+ /* Create shader. */
+ GPUShader *sh = workbench_shader_volume_get(false, false, false, false);
+
+ /* Compute color. */
+ float color[3];
+ workbench_volume_material_color(wpd, ob, color_type, color);
+
+ /* Combined texture to object, and object to world transform. */
+ float texture_to_world[4][4];
+ mul_m4_m4m4(texture_to_world, ob->obmat, grid->texture_to_object);
+
+ /* Compute world space dimensions for step size. */
+ float world_size[3];
+ mat4_to_size(world_size, texture_to_world);
+ abs_v3(world_size);
+
+ /* Compute step parameters. */
+ double noise_ofs;
+ BLI_halton_1d(3, 0.0, wpd->taa_sample, &noise_ofs);
+ float step_length, max_slice;
+ int resolution[3];
+ GPU_texture_get_mipmap_size(grid->texture, 0, resolution);
+ float slice_ct[3] = {resolution[0], resolution[1], resolution[2]};
+ mul_v3_fl(slice_ct, max_ff(0.001f, 5.0f));
+ max_slice = max_fff(slice_ct[0], slice_ct[1], slice_ct[2]);
+ invert_v3(slice_ct);
+ mul_v3_v3(slice_ct, world_size);
+ step_length = len_v3(slice_ct);
+
+ /* Compute density scale. */
+ const float density_scale = volume->display.density;
+
+ /* Set uniforms. */
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, vedata->psl->volume_ps);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slice);
+ DRW_shgroup_uniform_float_copy(grp, "stepLength", step_length);
+ DRW_shgroup_uniform_float_copy(grp, "noiseOfs", noise_ofs);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
+
+ DRW_shgroup_uniform_texture(grp, "densityTexture", grid->texture);
+ /* TODO: implement shadow texture, see manta_smoke_calc_transparency. */
+ DRW_shgroup_uniform_texture(grp, "shadowTexture", txl->dummy_shadow_tx);
+ DRW_shgroup_uniform_vec3_copy(grp, "activeColor", color);
+
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_float_copy(grp, "densityScale", density_scale);
+
+ DRW_shgroup_uniform_mat4(grp, "volumeObjectToTexture", grid->object_to_texture);
+ DRW_shgroup_uniform_mat4(grp, "volumeTextureToObject", grid->texture_to_object);
+
+ DRW_shgroup_call(grp, DRW_cache_cube_get(), ob);
+}
+
+void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
+ Scene *UNUSED(scene),
+ Object *ob,
+ ModifierData *md,
+ eV3DShadingColorType color_type)
+{
+ if (md == NULL) {
+ workbench_volume_object_cache_populate(vedata, ob, color_type);
+ }
+ else {
+ workbench_volume_modifier_cache_populate(vedata, ob, md);
+ }
+}
+
void workbench_volume_draw_pass(WORKBENCH_Data *vedata)
{
WORKBENCH_PassList *psl = vedata->psl;
@@ -189,4 +294,4 @@ void workbench_volume_draw_finish(WORKBENCH_Data *vedata)
GPU_free_smoke(mmd);
}
BLI_freelistN(&wpd->smoke_domains);
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index d0cea5b8c5c..1f76b5ac431 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -19,13 +19,16 @@
*/
#include "DNA_scene_types.h"
+#include "DNA_hair_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_curve_types.h"
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
#include "DNA_modifier_types.h"
#include "DNA_lattice_types.h"
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_pointcloud_types.h"
+#include "DNA_volume_types.h"
#include "UI_resources.h"
@@ -799,6 +802,12 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
return DRW_cache_text_edge_detection_get(ob, r_is_manifold);
case OB_MBALL:
return DRW_cache_mball_edge_detection_get(ob, r_is_manifold);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -817,6 +826,12 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
return DRW_cache_text_face_wireframe_get(ob);
case OB_MBALL:
return DRW_cache_mball_face_wireframe_get(ob);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return DRW_cache_volume_face_wireframe_get(ob);
case OB_GPENCIL: {
return DRW_cache_gpencil_face_wireframe_get(ob);
}
@@ -837,7 +852,13 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
case OB_FONT:
return DRW_cache_text_loose_edges_get(ob);
case OB_MBALL:
- /* Cannot have any loose edge */
+ return NULL;
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -856,6 +877,12 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
return DRW_cache_text_surface_get(ob);
case OB_MBALL:
return DRW_cache_mball_surface_get(ob);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -875,6 +902,12 @@ int DRW_cache_object_material_count_get(struct Object *ob)
return DRW_curve_material_count_get(ob->data);
case OB_MBALL:
return DRW_metaball_material_count_get(ob->data);
+ case OB_HAIR:
+ return DRW_hair_material_count_get(ob->data);
+ case OB_POINTCLOUD:
+ return DRW_pointcloud_material_count_get(ob->data);
+ case OB_VOLUME:
+ return DRW_volume_material_count_get(ob->data);
default:
BLI_assert(0);
return 0;
@@ -896,6 +929,12 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_MBALL:
return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
+ case OB_HAIR:
+ return NULL;
+ case OB_POINTCLOUD:
+ return NULL;
+ case OB_VOLUME:
+ return NULL;
default:
return NULL;
}
@@ -3214,6 +3253,27 @@ GPUBatch *DRW_cache_lattice_vert_overlay_get(Object *ob)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name PointCloud
+ * \{ */
+
+GPUBatch *DRW_cache_pointcloud_get_dots(Object *object)
+{
+ return DRW_pointcloud_batch_cache_get_dots(object);
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Volume
+ * \{ */
+
+GPUBatch *DRW_cache_volume_face_wireframe_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_VOLUME);
+ return DRW_volume_batch_cache_get_wireframes_face(ob->data);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Particles
* \{ */
@@ -3444,6 +3504,15 @@ void drw_batch_cache_validate(Object *ob)
case OB_LATTICE:
DRW_lattice_batch_cache_validate((Lattice *)ob->data);
break;
+ case OB_HAIR:
+ DRW_hair_batch_cache_validate((Hair *)ob->data);
+ break;
+ case OB_POINTCLOUD:
+ DRW_pointcloud_batch_cache_validate((PointCloud *)ob->data);
+ break;
+ case OB_VOLUME:
+ DRW_volume_batch_cache_validate((Volume *)ob->data);
+ break;
default:
break;
}
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 8ac0d7ada21..77c7b6b9307 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -29,6 +29,8 @@ struct ModifierData;
struct Object;
struct PTCacheEdit;
struct ParticleSystem;
+struct Volume;
+struct VolumeGrid;
struct bGPDstroke;
void DRW_shape_cache_free(void);
@@ -200,6 +202,39 @@ struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob,
struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+/* Hair */
+struct GPUBatch *DRW_cache_hair_surface_get(struct Object *ob);
+struct GPUBatch **DRW_cache_hair_surface_shaded_get(struct Object *ob,
+ struct GPUMaterial **gpumat_array,
+ uint gpumat_array_len);
+struct GPUBatch *DRW_cache_hair_face_wireframe_get(struct Object *ob);
+struct GPUBatch *DRW_cache_hair_edge_detection_get(struct Object *ob, bool *r_is_manifold);
+
+/* PointCloud */
+struct GPUBatch *DRW_cache_pointcloud_get_dots(struct Object *obj);
+
+/* Volume */
+typedef struct DRWVolumeGrid {
+ struct DRWVolumeGrid *next, *prev;
+
+ /* Grid name. */
+ char *name;
+
+ /* 3D texture. */
+ struct GPUTexture *texture;
+
+ /* Transform between 0..1 texture space and object space. */
+ float texture_to_object[4][4];
+ float object_to_texture[4][4];
+
+ /* Transfrom from bounds to texture space. */
+ float object_to_bounds[4][4];
+ float bounds_to_texture[4][4];
+} DRWVolumeGrid;
+
+DRWVolumeGrid *DRW_volume_batch_cache_get_grid(struct Volume *volume, struct VolumeGrid *grid);
+struct GPUBatch *DRW_cache_volume_face_wireframe_get(struct Object *ob);
+
/* GPencil */
struct GPUBatch *DRW_cache_gpencil_strokes_get(struct Object *ob, int cfra);
struct GPUBatch *DRW_cache_gpencil_fills_get(struct Object *ob, int cfra);
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 755f794d201..b3450bf4715 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -32,11 +32,14 @@ struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
+struct bGPdata;
struct Curve;
+struct Hair;
struct Lattice;
struct Mesh;
struct MetaBall;
-struct bGPdata;
+struct PointCloud;
+struct Volume;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode);
@@ -61,11 +64,26 @@ void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
void DRW_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
void DRW_gpencil_batch_cache_free(struct bGPdata *gpd);
+void DRW_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
+void DRW_hair_batch_cache_validate(struct Hair *hair);
+void DRW_hair_batch_cache_free(struct Hair *hair);
+
+void DRW_pointcloud_batch_cache_dirty_tag(struct PointCloud *pointcloud, int mode);
+void DRW_pointcloud_batch_cache_validate(struct PointCloud *pointcloud);
+void DRW_pointcloud_batch_cache_free(struct PointCloud *pointcloud);
+
+void DRW_volume_batch_cache_dirty_tag(struct Volume *volume, int mode);
+void DRW_volume_batch_cache_validate(struct Volume *volume);
+void DRW_volume_batch_cache_free(struct Volume *volume);
+
/* Garbage collection */
void DRW_batch_cache_free_old(struct Object *ob, int ctime);
void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime);
+/* Generic */
+void DRW_vertbuf_create_wiredata(struct GPUVertBuf *vbo, const int vert_len);
+
/* Curve */
void DRW_curve_batch_cache_create_requested(struct Object *ob);
@@ -118,6 +136,19 @@ struct GPUBatch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt,
struct GPUBatch *DRW_lattice_batch_cache_get_all_verts(struct Lattice *lt);
struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt);
+/* Hair */
+int DRW_hair_material_count_get(struct Hair *hair);
+
+/* PointCloud */
+int DRW_pointcloud_material_count_get(struct PointCloud *pointcloud);
+
+struct GPUBatch *DRW_pointcloud_batch_cache_get_dots(struct Object *ob);
+
+/* Volume */
+int DRW_volume_material_count_get(struct Volume *volume);
+
+struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume);
+
/* Mesh */
void DRW_mesh_batch_cache_create_requested(struct Object *ob,
struct Mesh *me,
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 50979d72189..bc4eb37c3b4 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -214,7 +214,7 @@ void DRW_displist_vertbuf_create_pos_and_nor(ListBase *lb, GPUVertBuf *vbo)
}
}
-void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
+void DRW_vertbuf_create_wiredata(GPUVertBuf *vbo, const int vert_len)
{
static GPUVertFormat format = {0};
static struct {
@@ -232,23 +232,27 @@ void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
}
}
- int vbo_len_used = curve_render_surface_vert_len_get(lb);
-
GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, vbo_len_used);
+ GPU_vertbuf_data_alloc(vbo, vert_len);
if (vbo->format.stride == 1) {
- memset(vbo->data, 0xFF, (size_t)vbo_len_used);
+ memset(vbo->data, 0xFF, (size_t)vert_len);
}
else {
GPUVertBufRaw wd_step;
GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step);
- for (int i = 0; i < vbo_len_used; i++) {
+ for (int i = 0; i < vert_len; i++) {
*((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f;
}
}
}
+void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo)
+{
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+ DRW_vertbuf_create_wiredata(vbo, vert_len);
+}
+
void DRW_displist_indexbuf_create_triangles_in_order(ListBase *lb, GPUIndexBuf *ibo)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index 795e7be63b1..c4433cea0df 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -179,7 +179,7 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
}
-static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
+void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
{
/* TODO more granular update tagging. */
GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index b1ad1455d8c..87cd1cd8546 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -437,7 +437,15 @@ bool DRW_object_is_flat(Object *ob, int *r_axis)
{
float dim[3];
- if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
+ if (!ELEM(ob->type,
+ OB_MESH,
+ OB_CURVE,
+ OB_SURF,
+ OB_FONT,
+ OB_MBALL,
+ OB_HAIR,
+ OB_POINTCLOUD,
+ OB_VOLUME)) {
/* Non-meshes object cannot be considered as flat. */
return false;
}
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index c88071dc6d6..c89f5f5bba6 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -142,9 +142,16 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
ParticleHairCache *hair_cache;
- ParticleSettings *part = psys->part;
- bool need_ft_update = particles_ensure_procedural_data(
- object, psys, md, &hair_cache, subdiv, thickness_res);
+ bool need_ft_update;
+ if (psys) {
+ /* Old particle hair. */
+ need_ft_update = particles_ensure_procedural_data(
+ object, psys, md, &hair_cache, subdiv, thickness_res);
+ }
+ else {
+ /* New hair object. */
+ need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
+ }
DRWShadingGroup *shgrp;
if (shgrp_parent) {
@@ -185,34 +192,58 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
}
- if ((dupli_parent != NULL) && (dupli_object != NULL)) {
- if (dupli_object->type & OB_DUPLICOLLECTION) {
- copy_m4_m4(dupli_mat, dupli_parent->obmat);
+ if (psys) {
+ if ((dupli_parent != NULL) && (dupli_object != NULL)) {
+ if (dupli_object->type & OB_DUPLICOLLECTION) {
+ copy_m4_m4(dupli_mat, dupli_parent->obmat);
+ }
+ else {
+ copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
+ invert_m4(dupli_mat);
+ mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ }
}
else {
- copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
- invert_m4(dupli_mat);
- mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
+ unit_m4(dupli_mat);
}
}
else {
- unit_m4(dupli_mat);
+ /* New hair object. */
+ copy_m4_m4(dupli_mat, object->obmat);
+ }
+
+ /* Get hair shape parameters. */
+ float hair_rad_shape, hair_rad_root, hair_rad_tip;
+ bool hair_close_tip;
+ if (psys) {
+ /* Old particle hair. */
+ ParticleSettings *part = psys->part;
+ hair_rad_shape = part->shape;
+ hair_rad_root = part->rad_root * part->rad_scale * 0.5f;
+ hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f;
+ hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
+ }
+ else {
+ /* TODO: implement for new hair object. */
+ hair_rad_shape = 1.0f;
+ hair_rad_root = 0.005f;
+ hair_rad_tip = 0.0f;
+ hair_close_tip = true;
}
DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
- DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1);
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[0]", dupli_mat[0]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[1]", dupli_mat[1]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[2]", dupli_mat[2]);
DRW_shgroup_uniform_vec4_copy(shgrp, "hairDupliMatrix[3]", dupli_mat[3]);
- DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f);
- DRW_shgroup_uniform_bool_copy(
- shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0);
- /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling
- * test. */
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
+ DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
+ DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
+ /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass
+ * culling test. */
GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
DRW_shgroup_call_no_cull(shgrp, geom, object);
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index c03b4822b1b..4d9eaf88a7d 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -79,6 +79,8 @@ typedef struct ParticleHairCache {
int point_len;
} ParticleHairCache;
+void particle_batch_cache_clear_hair(struct ParticleHairCache *hair_cache);
+
bool particles_ensure_procedural_data(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
@@ -86,4 +88,9 @@ bool particles_ensure_procedural_data(struct Object *object,
int subdiv,
int thickness_res);
+bool hair_ensure_procedural_data(struct Object *object,
+ struct ParticleHairCache **r_hair_cache,
+ int subdiv,
+ int thickness_res);
+
#endif /* __DRAW_HAIR_PRIVATE_H__ */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 618922d8544..df3a1e3da79 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -38,6 +38,7 @@
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
+#include "BKE_hair.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mball.h"
@@ -48,6 +49,8 @@
#include "BKE_paint.h"
#include "BKE_pbvh.h"
#include "BKE_pointcache.h"
+#include "BKE_pointcloud.h"
+#include "BKE_volume.h"
#include "draw_manager.h"
#include "DNA_camera_types.h"
@@ -2653,6 +2656,15 @@ void DRW_engines_register(void)
BKE_gpencil_batch_cache_dirty_tag_cb = DRW_gpencil_batch_cache_dirty_tag;
BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
+
+ BKE_hair_batch_cache_dirty_tag_cb = DRW_hair_batch_cache_dirty_tag;
+ BKE_hair_batch_cache_free_cb = DRW_hair_batch_cache_free;
+
+ BKE_pointcloud_batch_cache_dirty_tag_cb = DRW_pointcloud_batch_cache_dirty_tag;
+ BKE_pointcloud_batch_cache_free_cb = DRW_pointcloud_batch_cache_free;
+
+ BKE_volume_batch_cache_dirty_tag_cb = DRW_volume_batch_cache_dirty_tag;
+ BKE_volume_batch_cache_free_cb = DRW_volume_batch_cache_free;
}
}
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index da00306bf9f..337c0b03308 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -233,7 +233,8 @@ typedef struct GPUMaterialTexture {
typedef struct GPUMaterialVolumeGrid {
struct GPUMaterialVolumeGrid *next, *prev;
char *name;
- char sampler_name[32]; /* Name of sampler in GLSL. */
+ char sampler_name[32]; /* Name of sampler in GLSL. */
+ char transform_name[32]; /* Name of 4x4 matrix in GLSL. */
int users;
} GPUMaterialVolumeGrid;
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index bcaa95c2f59..066b8d633d2 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -335,6 +335,7 @@ static int codegen_process_uniforms_functions(GPUMaterial *material,
/* Volume Grids */
for (GPUMaterialVolumeGrid *grid = graph->volume_grids.first; grid; grid = grid->next) {
BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", grid->sampler_name);
+ BLI_dynstr_appendf(ds, "uniform mat4 %s = mat4(0.0);\n", grid->transform_name);
}
/* Print other uniforms */
@@ -432,6 +433,9 @@ static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *f
else if (input->source == GPU_SOURCE_VOLUME_GRID) {
BLI_dynstr_append(ds, input->volume_grid->sampler_name);
}
+ else if (input->source == GPU_SOURCE_VOLUME_GRID_TRANSFORM) {
+ BLI_dynstr_append(ds, input->volume_grid->transform_name);
+ }
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
ds, input->link->output->type, input->type, "tmp", input->link->output->id);
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 0d5cc46c0b9..0eb62bf5b2f 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -123,6 +123,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_VOLUME_GRID;
input->volume_grid = link->volume_grid;
break;
+ case GPU_NODE_LINK_VOLUME_GRID_TRANSFORM:
+ input->source = GPU_SOURCE_VOLUME_GRID_TRANSFORM;
+ input->volume_grid = link->volume_grid;
+ break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
input->attr = link->attr;
@@ -342,6 +346,7 @@ static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph
grid = MEM_callocN(sizeof(*grid), __func__);
grid->name = BLI_strdup(name);
BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
+ BLI_snprintf(grid->transform_name, sizeof(grid->transform_name), "vtfm%d", num_grids);
BLI_addtail(&graph->volume_grids, grid);
}
@@ -432,16 +437,20 @@ GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
link->link_type = GPU_NODE_LINK_VOLUME_GRID;
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
+ GPUNodeLink *transform_link = gpu_node_link_create();
+ transform_link->link_type = GPU_NODE_LINK_VOLUME_GRID_TRANSFORM;
+ transform_link->volume_grid = link->volume_grid;
+
/* Two special cases, where we adjust the output values of smoke grids to
* bring the into standard range without having to modify the grid values. */
if (strcmp(name, "color") == 0) {
- GPU_link(mat, "node_attribute_volume_color", link, &link);
+ GPU_link(mat, "node_attribute_volume_color", link, transform_link, &link);
}
else if (strcmp(name, "temperature") == 0) {
- GPU_link(mat, "node_attribute_volume_temperature", link, &link);
+ GPU_link(mat, "node_attribute_volume_temperature", link, transform_link, &link);
}
else {
- GPU_link(mat, "node_attribute_volume", link, &link);
+ GPU_link(mat, "node_attribute_volume", link, transform_link, &link);
}
return link;
@@ -590,7 +599,7 @@ static void gpu_inputs_free(ListBase *inputs)
else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
input->texture->users--;
}
- else if (ELEM(input->source, GPU_SOURCE_VOLUME_GRID)) {
+ else if (ELEM(input->source, GPU_SOURCE_VOLUME_GRID, GPU_SOURCE_VOLUME_GRID_TRANSFORM)) {
input->volume_grid->users--;
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index ceaeea2bfa8..8506c6a87e2 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -62,6 +62,7 @@ typedef enum {
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
GPU_NODE_LINK_VOLUME_GRID,
+ GPU_NODE_LINK_VOLUME_GRID_TRANSFORM,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@@ -131,7 +132,7 @@ typedef struct GPUInput {
struct GPUMaterialTexture *texture;
/* GPU_SOURCE_ATTR */
struct GPUMaterialAttribute *attr;
- /* GPU_SOURCE_VOLUME_GRID */
+ /* GPU_SOURCE_VOLUME_GRID | GPU_SOURCE_VOLUME_GRID_TRANSFORM */
struct GPUMaterialVolumeGrid *volume_grid;
};
} GPUInput;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
index a80cd3cb329..e6d7b9d3721 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
@@ -4,18 +4,24 @@ uniform vec3 volumeColor = vec3(1.0);
uniform vec2 volumeTemperature = vec2(0.0);
/* Generic volume attribute. */
-void node_attribute_volume(sampler3D tex, out vec3 outvec)
+void node_attribute_volume(sampler3D tex, mat4 transform, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
#else
vec3 cos = vec3(0.0);
#endif
+
+ /* Optional per-grid transform. */
+ if (transform[3][3] != 0.0) {
+ cos = (transform * vec4(cos, 1.0)).xyz;
+ }
+
outvec = texture(tex, cos).rgb;
}
/* Special color attribute for smoke. */
-void node_attribute_volume_color(sampler3D tex, out vec3 outvec)
+void node_attribute_volume_color(sampler3D tex, mat4 transform, out vec3 outvec)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
@@ -23,6 +29,11 @@ void node_attribute_volume_color(sampler3D tex, out vec3 outvec)
vec3 cos = vec3(0.0);
#endif
+ /* Optional per-grid transform. */
+ if (transform[3][3] != 0.0) {
+ cos = (transform * vec4(cos, 1.0)).xyz;
+ }
+
/* Density is premultiplied for interpolation, divide it out here. */
vec4 value = texture(tex, cos).rgba;
if (value.a > 1e-8) {
@@ -33,7 +44,7 @@ void node_attribute_volume_color(sampler3D tex, out vec3 outvec)
}
/* Special temperature attribute for smoke. */
-void node_attribute_volume_temperature(sampler3D tex, out float outf)
+void node_attribute_volume_temperature(sampler3D tex, mat4 transform, out float outf)
{
#if defined(MESH_SHADER) && defined(VOLUMETRICS)
vec3 cos = volumeObjectLocalCoord;
@@ -41,6 +52,11 @@ void node_attribute_volume_temperature(sampler3D tex, out float outf)
vec3 cos = vec3(0.0);
#endif
+ /* Optional per-grid transform. */
+ if (transform[3][3] != 0.0) {
+ cos = (transform * vec4(cos, 1.0)).xyz;
+ }
+
float value = texture(tex, cos).r;
if (volumeTemperature.x < volumeTemperature.y) {
outf = (value > 0.01) ?