2022-02-11 09:07:11 +11:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
* Copyright 2019 Blender Foundation. */
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
|
* \ingroup draw
|
|
|
|
|
*/
|
|
|
|
|
|
2019-09-13 21:12:26 +10:00
|
|
|
#pragma once
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h"
|
2020-06-02 15:07:17 +02:00
|
|
|
|
2021-10-26 18:16:33 -03:00
|
|
|
#include "DNA_customdata_types.h"
|
2022-06-05 12:04:42 +02:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
|
#include "DNA_view3d_enums.h"
|
2021-10-26 18:16:33 -03:00
|
|
|
|
|
|
|
|
#include "BKE_attribute.h"
|
2022-01-11 15:42:07 +01:00
|
|
|
#include "BKE_object.h"
|
2021-10-26 18:16:33 -03:00
|
|
|
|
2021-06-01 09:23:37 +02:00
|
|
|
#include "GPU_batch.h"
|
|
|
|
|
#include "GPU_index_buffer.h"
|
|
|
|
|
#include "GPU_vertex_buffer.h"
|
|
|
|
|
|
EEVEE: support Curves attributes rendering
This adds support to render Curves attributes in EEVEE.
Each attribute is stored in a texture derived from a VBO. As the
shading group needs the textures to be valid upon creation, the
attributes are created and setup during its very creation, instead
of doing it lazily via create_requested which we cannot rely on
anyway as contrary to the mesh batch, we do cannot really tell if
attributes need to be updated or else via some `DRW_batch_requested`.
Since point attributes need refinement, and since attributes are all
cast to vec4/float4 to account for differences in type conversions
between Blender and OpenGL, the refinement shader for points is
used as is. The point attributes are stored for each subdivision level
in CurvesEvalFinalCache. Each subdivision level also keeps track of the
attributes already in use so they are properly updated when needed.
Some basic garbage collection was added similar to what is done
for meshes: if the attributes used over time have been different
from the currently used attributes for too long, then the buffers
are freed, ensuring that stale attributesare removed.
This adds `CurvesInfos` to the shader creation info, which stores
the scope in which the attributes are defined. Scopes are stored
as booleans, in an array indexed by attribute loading order which
is also the order in which the attributes were added to the material.
A mapping is necessary between the indices used for the scoping, and
the ones used in the Curves cache, as this may contain stale
attributes which have not been garbage collected yet.
Common utilities with the mesh code for handling requested
attributes were moved to a separate file.
Differential Revision: https://developer.blender.org/D14916
2022-05-24 05:02:57 +02:00
|
|
|
#include "draw_attributes.h"
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct DRWSubdivCache;
|
|
|
|
|
struct MeshRenderData;
|
|
|
|
|
struct TaskGraph;
|
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Vertex Group Selection and display options */
|
2022-06-05 12:04:42 +02:00
|
|
|
struct DRW_MeshWeightState {
|
2019-07-14 16:49:44 +02:00
|
|
|
int defgroup_active;
|
|
|
|
|
int defgroup_len;
|
|
|
|
|
|
|
|
|
|
short flags;
|
|
|
|
|
char alert_mode;
|
|
|
|
|
|
2021-07-08 13:26:55 +10:00
|
|
|
/* Set of all selected bones for Multi-paint. */
|
2022-06-05 12:15:22 +02:00
|
|
|
bool *defgroup_sel; /* #defgroup_len */
|
2019-07-14 16:49:44 +02:00
|
|
|
int defgroup_sel_count;
|
2018-10-07 18:25:51 +03:00
|
|
|
|
|
|
|
|
/* Set of all locked and unlocked deform bones for Lock Relative mode. */
|
2022-06-05 12:15:22 +02:00
|
|
|
bool *defgroup_locked; /* #defgroup_len */
|
|
|
|
|
bool *defgroup_unlocked; /* #defgroup_len */
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
|
/* DRW_MeshWeightState.flags */
|
|
|
|
|
enum {
|
|
|
|
|
DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0),
|
|
|
|
|
DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1),
|
2018-10-07 18:25:51 +03:00
|
|
|
DRW_MESH_WEIGHT_STATE_LOCK_RELATIVE = (1 << 2),
|
2019-07-14 16:49:44 +02:00
|
|
|
};
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct DRW_MeshCDMask {
|
2019-07-14 16:49:44 +02:00
|
|
|
uint32_t uv : 8;
|
|
|
|
|
uint32_t tan : 8;
|
|
|
|
|
uint32_t vcol : 8;
|
|
|
|
|
uint32_t orco : 1;
|
|
|
|
|
uint32_t tan_orco : 1;
|
2020-09-18 19:30:02 +02:00
|
|
|
uint32_t sculpt_overlays : 1;
|
2022-06-05 12:15:22 +02:00
|
|
|
/**
|
|
|
|
|
* Edit uv layer is from the base edit mesh as modifiers could remove it. (see T68857)
|
|
|
|
|
*/
|
2019-10-08 18:35:57 +02:00
|
|
|
uint32_t edit_uv : 1;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Keep `DRW_MeshCDMask` struct within a `uint32_t`.
|
2020-07-06 08:41:28 +02:00
|
|
|
* bit-wise and atomic operations are used to compare and update the struct.
|
|
|
|
|
* See `mesh_cd_layers_type_*` functions. */
|
2021-10-26 18:16:33 -03:00
|
|
|
BLI_STATIC_ASSERT(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask exceeds 32 bits")
|
2022-06-05 12:15:22 +02:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
enum eMRIterType {
|
2019-07-14 16:49:44 +02:00
|
|
|
MR_ITER_LOOPTRI = 1 << 0,
|
2020-07-01 00:13:39 +10:00
|
|
|
MR_ITER_POLY = 1 << 1,
|
2019-07-14 16:49:44 +02:00
|
|
|
MR_ITER_LEDGE = 1 << 2,
|
|
|
|
|
MR_ITER_LVERT = 1 << 3,
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2021-06-01 12:12:13 +02:00
|
|
|
ENUM_OPERATORS(eMRIterType, MR_ITER_LVERT)
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
enum eMRDataType {
|
2021-06-07 13:27:38 +02:00
|
|
|
MR_DATA_NONE = 0,
|
2019-07-14 16:49:44 +02:00
|
|
|
MR_DATA_POLY_NOR = 1 << 1,
|
|
|
|
|
MR_DATA_LOOP_NOR = 1 << 2,
|
|
|
|
|
MR_DATA_LOOPTRI = 1 << 3,
|
2021-07-21 14:46:41 -03:00
|
|
|
MR_DATA_LOOSE_GEOM = 1 << 4,
|
2021-06-24 15:56:58 +10:00
|
|
|
/** Force loop normals calculation. */
|
2021-07-21 14:46:41 -03:00
|
|
|
MR_DATA_TAN_LOOP_NOR = 1 << 5,
|
2021-07-20 11:43:38 -03:00
|
|
|
MR_DATA_POLYS_SORTED = 1 << 6,
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2021-07-20 11:43:38 -03:00
|
|
|
ENUM_OPERATORS(eMRDataType, MR_DATA_POLYS_SORTED)
|
2021-06-01 12:12:13 +02:00
|
|
|
|
2022-01-11 15:42:07 +01:00
|
|
|
BLI_INLINE int mesh_render_mat_len_get(const Object *object, const Mesh *me)
|
2019-07-14 16:49:44 +02:00
|
|
|
{
|
2022-01-11 15:42:07 +01:00
|
|
|
if (me->edit_mesh != NULL) {
|
|
|
|
|
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object);
|
|
|
|
|
if (editmesh_eval_final != NULL) {
|
2022-06-05 12:04:42 +02:00
|
|
|
return std::max<int>(1, editmesh_eval_final->totcol);
|
2022-01-11 15:42:07 +01:00
|
|
|
}
|
2021-05-19 10:23:09 +02:00
|
|
|
}
|
2022-06-05 12:04:42 +02:00
|
|
|
return std::max<int>(1, me->totcol);
|
2019-07-14 16:49:44 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct MeshBufferList {
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Every VBO below contains at least enough data for every loop in the mesh
|
|
|
|
|
* (except fdots and skin roots). For some VBOs, it extends to (in this exact order) :
|
|
|
|
|
* loops + loose_edges * 2 + loose_verts */
|
2019-07-14 16:49:44 +02:00
|
|
|
struct {
|
|
|
|
|
GPUVertBuf *pos_nor; /* extend */
|
|
|
|
|
GPUVertBuf *lnor; /* extend */
|
|
|
|
|
GPUVertBuf *edge_fac; /* extend */
|
|
|
|
|
GPUVertBuf *weights; /* extend */
|
2019-08-14 22:43:44 +02:00
|
|
|
GPUVertBuf *uv;
|
|
|
|
|
GPUVertBuf *tan;
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUVertBuf *vcol;
|
2020-09-18 19:30:02 +02:00
|
|
|
GPUVertBuf *sculpt_data;
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUVertBuf *orco;
|
|
|
|
|
/* Only for edit mode. */
|
|
|
|
|
GPUVertBuf *edit_data; /* extend */
|
|
|
|
|
GPUVertBuf *edituv_data;
|
2021-02-17 15:36:18 +11:00
|
|
|
GPUVertBuf *edituv_stretch_area;
|
|
|
|
|
GPUVertBuf *edituv_stretch_angle;
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUVertBuf *mesh_analysis;
|
|
|
|
|
GPUVertBuf *fdots_pos;
|
|
|
|
|
GPUVertBuf *fdots_nor;
|
|
|
|
|
GPUVertBuf *fdots_uv;
|
|
|
|
|
// GPUVertBuf *fdots_edit_data; /* inside fdots_nor for now. */
|
|
|
|
|
GPUVertBuf *fdots_edituv_data;
|
2019-10-15 01:49:53 +02:00
|
|
|
GPUVertBuf *skin_roots;
|
2019-07-14 16:49:44 +02:00
|
|
|
/* Selection */
|
|
|
|
|
GPUVertBuf *vert_idx; /* extend */
|
|
|
|
|
GPUVertBuf *edge_idx; /* extend */
|
|
|
|
|
GPUVertBuf *poly_idx;
|
|
|
|
|
GPUVertBuf *fdot_idx;
|
2021-10-26 18:16:33 -03:00
|
|
|
GPUVertBuf *attr[GPU_MAX_ATTR];
|
2019-07-14 16:49:44 +02:00
|
|
|
} vbo;
|
|
|
|
|
/* Index Buffers:
|
|
|
|
|
* Only need to be updated when topology changes. */
|
|
|
|
|
struct {
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Indices to vloops. Ordered per material. */
|
|
|
|
|
GPUIndexBuf *tris;
|
|
|
|
|
/* Loose edges last. */
|
|
|
|
|
GPUIndexBuf *lines;
|
|
|
|
|
/* Sub buffer of `lines` only containing the loose edges. */
|
|
|
|
|
GPUIndexBuf *lines_loose;
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUIndexBuf *points;
|
|
|
|
|
GPUIndexBuf *fdots;
|
|
|
|
|
/* 3D overlays. */
|
2022-06-05 12:15:22 +02:00
|
|
|
/* no loose edges. */
|
|
|
|
|
GPUIndexBuf *lines_paint_mask;
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUIndexBuf *lines_adjacency;
|
|
|
|
|
/* Uv overlays. (visibility can differ from 3D view) */
|
|
|
|
|
GPUIndexBuf *edituv_tris;
|
|
|
|
|
GPUIndexBuf *edituv_lines;
|
|
|
|
|
GPUIndexBuf *edituv_points;
|
|
|
|
|
GPUIndexBuf *edituv_fdots;
|
|
|
|
|
} ibo;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct MeshBatchList {
|
2021-08-23 12:46:14 -03:00
|
|
|
/* Surfaces / Render */
|
|
|
|
|
GPUBatch *surface;
|
|
|
|
|
GPUBatch *surface_weights;
|
|
|
|
|
/* Edit mode */
|
|
|
|
|
GPUBatch *edit_triangles;
|
|
|
|
|
GPUBatch *edit_vertices;
|
|
|
|
|
GPUBatch *edit_edges;
|
|
|
|
|
GPUBatch *edit_vnor;
|
|
|
|
|
GPUBatch *edit_lnor;
|
|
|
|
|
GPUBatch *edit_fdots;
|
|
|
|
|
GPUBatch *edit_mesh_analysis;
|
|
|
|
|
GPUBatch *edit_skin_roots;
|
|
|
|
|
/* Edit UVs */
|
|
|
|
|
GPUBatch *edituv_faces_stretch_area;
|
|
|
|
|
GPUBatch *edituv_faces_stretch_angle;
|
|
|
|
|
GPUBatch *edituv_faces;
|
|
|
|
|
GPUBatch *edituv_edges;
|
|
|
|
|
GPUBatch *edituv_verts;
|
|
|
|
|
GPUBatch *edituv_fdots;
|
|
|
|
|
/* Edit selection */
|
|
|
|
|
GPUBatch *edit_selection_verts;
|
|
|
|
|
GPUBatch *edit_selection_edges;
|
|
|
|
|
GPUBatch *edit_selection_faces;
|
|
|
|
|
GPUBatch *edit_selection_fdots;
|
|
|
|
|
/* Common display / Other */
|
|
|
|
|
GPUBatch *all_verts;
|
|
|
|
|
GPUBatch *all_edges;
|
|
|
|
|
GPUBatch *loose_edges;
|
|
|
|
|
GPUBatch *edge_detection;
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Individual edges with face normals. */
|
|
|
|
|
GPUBatch *wire_edges;
|
|
|
|
|
/* Loops around faces. no edges between selected faces */
|
|
|
|
|
GPUBatch *wire_loops;
|
|
|
|
|
/* Same as wire_loops but only has uvs. */
|
|
|
|
|
GPUBatch *wire_loops_uvs;
|
2021-08-23 12:46:14 -03:00
|
|
|
GPUBatch *sculpt_overlays;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2021-08-23 12:46:14 -03:00
|
|
|
|
|
|
|
|
#define MBC_BATCH_LEN (sizeof(MeshBatchList) / sizeof(void *))
|
2022-06-07 10:31:28 +02:00
|
|
|
#define MBC_VBO_LEN (sizeof(MeshBufferList::vbo) / sizeof(void *))
|
|
|
|
|
#define MBC_IBO_LEN (sizeof(MeshBufferList::ibo) / sizeof(void *))
|
2021-08-23 12:46:14 -03:00
|
|
|
|
|
|
|
|
#define MBC_BATCH_INDEX(batch) (offsetof(MeshBatchList, batch) / sizeof(void *))
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
enum DRWBatchFlag {
|
2021-08-23 12:46:14 -03:00
|
|
|
MBC_SURFACE = (1u << MBC_BATCH_INDEX(surface)),
|
|
|
|
|
MBC_SURFACE_WEIGHTS = (1u << MBC_BATCH_INDEX(surface_weights)),
|
|
|
|
|
MBC_EDIT_TRIANGLES = (1u << MBC_BATCH_INDEX(edit_triangles)),
|
|
|
|
|
MBC_EDIT_VERTICES = (1u << MBC_BATCH_INDEX(edit_vertices)),
|
|
|
|
|
MBC_EDIT_EDGES = (1u << MBC_BATCH_INDEX(edit_edges)),
|
|
|
|
|
MBC_EDIT_VNOR = (1u << MBC_BATCH_INDEX(edit_vnor)),
|
|
|
|
|
MBC_EDIT_LNOR = (1u << MBC_BATCH_INDEX(edit_lnor)),
|
|
|
|
|
MBC_EDIT_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_fdots)),
|
|
|
|
|
MBC_EDIT_MESH_ANALYSIS = (1u << MBC_BATCH_INDEX(edit_mesh_analysis)),
|
|
|
|
|
MBC_SKIN_ROOTS = (1u << MBC_BATCH_INDEX(edit_skin_roots)),
|
|
|
|
|
MBC_EDITUV_FACES_STRETCH_AREA = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_area)),
|
|
|
|
|
MBC_EDITUV_FACES_STRETCH_ANGLE = (1u << MBC_BATCH_INDEX(edituv_faces_stretch_angle)),
|
|
|
|
|
MBC_EDITUV_FACES = (1u << MBC_BATCH_INDEX(edituv_faces)),
|
|
|
|
|
MBC_EDITUV_EDGES = (1u << MBC_BATCH_INDEX(edituv_edges)),
|
|
|
|
|
MBC_EDITUV_VERTS = (1u << MBC_BATCH_INDEX(edituv_verts)),
|
|
|
|
|
MBC_EDITUV_FACEDOTS = (1u << MBC_BATCH_INDEX(edituv_fdots)),
|
|
|
|
|
MBC_EDIT_SELECTION_VERTS = (1u << MBC_BATCH_INDEX(edit_selection_verts)),
|
|
|
|
|
MBC_EDIT_SELECTION_EDGES = (1u << MBC_BATCH_INDEX(edit_selection_edges)),
|
|
|
|
|
MBC_EDIT_SELECTION_FACES = (1u << MBC_BATCH_INDEX(edit_selection_faces)),
|
|
|
|
|
MBC_EDIT_SELECTION_FACEDOTS = (1u << MBC_BATCH_INDEX(edit_selection_fdots)),
|
|
|
|
|
MBC_ALL_VERTS = (1u << MBC_BATCH_INDEX(all_verts)),
|
|
|
|
|
MBC_ALL_EDGES = (1u << MBC_BATCH_INDEX(all_edges)),
|
|
|
|
|
MBC_LOOSE_EDGES = (1u << MBC_BATCH_INDEX(loose_edges)),
|
|
|
|
|
MBC_EDGE_DETECTION = (1u << MBC_BATCH_INDEX(edge_detection)),
|
|
|
|
|
MBC_WIRE_EDGES = (1u << MBC_BATCH_INDEX(wire_edges)),
|
|
|
|
|
MBC_WIRE_LOOPS = (1u << MBC_BATCH_INDEX(wire_loops)),
|
|
|
|
|
MBC_WIRE_LOOPS_UVS = (1u << MBC_BATCH_INDEX(wire_loops_uvs)),
|
|
|
|
|
MBC_SCULPT_OVERLAYS = (1u << MBC_BATCH_INDEX(sculpt_overlays)),
|
2022-06-05 12:04:42 +02:00
|
|
|
MBC_SURFACE_PER_MAT = (1u << MBC_BATCH_LEN),
|
|
|
|
|
};
|
|
|
|
|
ENUM_OPERATORS(DRWBatchFlag, MBC_SURFACE_PER_MAT);
|
2021-08-23 12:46:14 -03:00
|
|
|
|
|
|
|
|
BLI_STATIC_ASSERT(MBC_BATCH_LEN < 32, "Number of batches exceeded the limit of bit fields");
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct MeshExtractLooseGeom {
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
int edge_len;
|
|
|
|
|
int vert_len;
|
|
|
|
|
int *verts;
|
|
|
|
|
int *edges;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
|
2021-05-31 09:32:37 +02:00
|
|
|
/**
|
|
|
|
|
* Data that are kept around between extractions to reduce rebuilding time.
|
|
|
|
|
*
|
|
|
|
|
* - Loose geometry.
|
|
|
|
|
*/
|
2022-06-05 12:04:42 +02:00
|
|
|
struct MeshBufferCache {
|
2021-08-23 13:28:55 -03:00
|
|
|
MeshBufferList buff;
|
|
|
|
|
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
MeshExtractLooseGeom loose_geom;
|
2021-06-15 15:31:17 +02:00
|
|
|
|
|
|
|
|
struct {
|
2021-07-20 11:43:38 -03:00
|
|
|
int *tri_first_index;
|
|
|
|
|
int *mat_tri_len;
|
2021-06-15 15:31:17 +02:00
|
|
|
int visible_tri_len;
|
2021-07-20 11:43:38 -03:00
|
|
|
} poly_sorted;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2021-05-31 09:32:37 +02:00
|
|
|
|
2021-08-23 13:28:55 -03:00
|
|
|
#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \
|
|
|
|
|
for (MeshBufferCache *mbc = &batch_cache->final; \
|
|
|
|
|
mbc == &batch_cache->final || mbc == &batch_cache->cage || mbc == &batch_cache->uv_cage; \
|
|
|
|
|
mbc = (mbc == &batch_cache->final) ? \
|
|
|
|
|
&batch_cache->cage : \
|
|
|
|
|
((mbc == &batch_cache->cage) ? &batch_cache->uv_cage : NULL))
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
struct MeshBatchCache {
|
2021-08-23 13:28:55 -03:00
|
|
|
MeshBufferCache final, cage, uv_cage;
|
2021-05-31 09:32:37 +02:00
|
|
|
|
2021-08-23 12:46:14 -03:00
|
|
|
MeshBatchList batch;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-08-23 09:52:13 -03:00
|
|
|
/* Index buffer per material. These are subranges of `ibo.tris` */
|
|
|
|
|
GPUIndexBuf **tris_per_mat;
|
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
GPUBatch **surface_per_mat;
|
|
|
|
|
|
2022-06-05 12:15:22 +02:00
|
|
|
DRWSubdivCache *subdiv_cache;
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
|
2022-06-05 12:15:22 +02:00
|
|
|
DRWBatchFlag batch_requested;
|
|
|
|
|
DRWBatchFlag batch_ready;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Settings to determine if cache is invalid. */
|
2019-07-14 16:49:44 +02:00
|
|
|
int edge_len;
|
|
|
|
|
int tri_len;
|
|
|
|
|
int poly_len;
|
|
|
|
|
int vert_len;
|
|
|
|
|
int mat_len;
|
2022-06-05 12:15:22 +02:00
|
|
|
/* Instantly invalidates cache, skipping mesh check */
|
|
|
|
|
bool is_dirty;
|
2019-07-14 16:49:44 +02:00
|
|
|
bool is_editmode;
|
|
|
|
|
bool is_uvsyncsel;
|
|
|
|
|
|
2022-06-05 12:15:22 +02:00
|
|
|
DRW_MeshWeightState weight_state;
|
2019-07-14 16:49:44 +02:00
|
|
|
|
|
|
|
|
DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time;
|
|
|
|
|
|
EEVEE: support Curves attributes rendering
This adds support to render Curves attributes in EEVEE.
Each attribute is stored in a texture derived from a VBO. As the
shading group needs the textures to be valid upon creation, the
attributes are created and setup during its very creation, instead
of doing it lazily via create_requested which we cannot rely on
anyway as contrary to the mesh batch, we do cannot really tell if
attributes need to be updated or else via some `DRW_batch_requested`.
Since point attributes need refinement, and since attributes are all
cast to vec4/float4 to account for differences in type conversions
between Blender and OpenGL, the refinement shader for points is
used as is. The point attributes are stored for each subdivision level
in CurvesEvalFinalCache. Each subdivision level also keeps track of the
attributes already in use so they are properly updated when needed.
Some basic garbage collection was added similar to what is done
for meshes: if the attributes used over time have been different
from the currently used attributes for too long, then the buffers
are freed, ensuring that stale attributesare removed.
This adds `CurvesInfos` to the shader creation info, which stores
the scope in which the attributes are defined. Scopes are stored
as booleans, in an array indexed by attribute loading order which
is also the order in which the attributes were added to the material.
A mapping is necessary between the indices used for the scoping, and
the ones used in the Curves cache, as this may contain stale
attributes which have not been garbage collected yet.
Common utilities with the mesh code for handling requested
attributes were moved to a separate file.
Differential Revision: https://developer.blender.org/D14916
2022-05-24 05:02:57 +02:00
|
|
|
DRW_Attributes attr_used, attr_needed, attr_used_over_time;
|
2021-10-26 18:16:33 -03:00
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
int lastmatch;
|
|
|
|
|
|
|
|
|
|
/* Valid only if edge_detection is up to date. */
|
|
|
|
|
bool is_manifold;
|
|
|
|
|
|
2019-09-03 13:42:11 +02:00
|
|
|
/* Total areas for drawing UV Stretching. Contains the summed area in mesh
|
|
|
|
|
* space (`tot_area`) and the summed area in uv space (`tot_uvarea`).
|
|
|
|
|
*
|
|
|
|
|
* Only valid after `DRW_mesh_batch_cache_create_requested` has been called. */
|
|
|
|
|
float tot_area, tot_uv_area;
|
|
|
|
|
|
2019-07-14 16:49:44 +02:00
|
|
|
bool no_loose_wire;
|
2022-04-05 11:42:55 -07:00
|
|
|
|
|
|
|
|
eV3DShadingColorType color_type;
|
|
|
|
|
bool pbvh_is_drawing;
|
2022-06-05 12:04:42 +02:00
|
|
|
};
|
2019-07-14 16:49:44 +02:00
|
|
|
|
2021-06-14 08:00:42 -03:00
|
|
|
#define MBC_EDITUV \
|
|
|
|
|
(MBC_EDITUV_FACES_STRETCH_AREA | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | \
|
|
|
|
|
MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS)
|
|
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
namespace blender::draw {
|
|
|
|
|
|
2022-06-05 12:15:22 +02:00
|
|
|
void mesh_buffer_cache_create_requested(TaskGraph *task_graph,
|
2021-08-26 12:36:13 +10:00
|
|
|
MeshBatchCache *cache,
|
|
|
|
|
MeshBufferCache *mbc,
|
2022-01-11 15:42:07 +01:00
|
|
|
Object *object,
|
2019-07-14 16:49:44 +02:00
|
|
|
Mesh *me,
|
2022-01-07 11:38:08 +11:00
|
|
|
bool is_editmode,
|
|
|
|
|
bool is_paint_mode,
|
|
|
|
|
bool is_mode_active,
|
2020-01-07 14:06:33 +11:00
|
|
|
const float obmat[4][4],
|
2022-01-07 11:38:08 +11:00
|
|
|
bool do_final,
|
|
|
|
|
bool do_uvedit,
|
2020-02-19 01:44:52 +01:00
|
|
|
const Scene *scene,
|
2022-06-05 12:15:22 +02:00
|
|
|
const ToolSettings *ts,
|
2022-01-07 11:38:08 +11:00
|
|
|
bool use_hide);
|
2021-06-01 12:12:13 +02:00
|
|
|
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|
|
|
|
MeshBufferCache *mbc,
|
2022-06-05 12:15:22 +02:00
|
|
|
DRWSubdivCache *subdiv_cache,
|
|
|
|
|
MeshRenderData *mr);
|
OpenSubDiv: add support for an OpenGL evaluator
This evaluator is used in order to evaluate subdivision at render time, allowing for
faster renders of meshes with a subdivision surface modifier placed at the last
position in the modifier list.
When evaluating the subsurf modifier, we detect whether we can delegate evaluation
to the draw code. If so, the subdivision is first evaluated on the GPU using our own
custom evaluator (only the coarse data needs to be initially sent to the GPU), then,
buffers for the final `MeshBufferCache` are filled on the GPU using a set of
compute shaders. However, some buffers are still filled on the CPU side, if doing so
on the GPU is impractical (e.g. the line adjacency buffer used for x-ray, whose
logic is hardly GPU compatible).
This is done at the mesh buffer extraction level so that the result can be readily used
in the various OpenGL engines, without having to write custom geometry or tesselation
shaders.
We use our own subdivision evaluation shaders, instead of OpenSubDiv's vanilla one, in
order to control the data layout, and interpolation. For example, we store vertex colors
as compressed 16-bit integers, while OpenSubDiv's default evaluator only work for float
types.
In order to still access the modified geometry on the CPU side, for use in modifiers
or transform operators, a dedicated wrapper type is added `MESH_WRAPPER_TYPE_SUBD`.
Subdivision will be lazily evaluated via `BKE_object_get_evaluated_mesh` which will
create such a wrapper if possible. If the final subdivision surface is not needed on
the CPU side, `BKE_object_get_evaluated_mesh_no_subsurf` should be used.
Enabling or disabling GPU subdivision can be done through the user preferences (under
Viewport -> Subdivision).
See patch description for benchmarks.
Reviewed By: campbellbarton, jbakker, fclem, brecht, #eevee_viewport
Differential Revision: https://developer.blender.org/D12406
2021-12-27 16:34:47 +01:00
|
|
|
|
2022-06-05 12:04:42 +02:00
|
|
|
} // namespace blender::draw
|