Initial Grease Pencil 3.0 stage #106848

Merged
Falk David merged 224 commits from filedescriptor/blender:grease-pencil-v3 into main 2023-05-30 11:14:22 +02:00
4 changed files with 112 additions and 118 deletions
Showing only changes of commit 00726d67d9 - Show all commits

View File

@ -401,8 +401,7 @@ blender::Span<GreasePencilDrawingOrReference *> GreasePencil::drawings() const
}
void GreasePencil::foreach_visible_drawing(
int frame,
blender::FunctionRef<void(GreasePencilDrawing &, blender::bke::gpencil::Layer &)> function)
int frame, blender::FunctionRef<void(GreasePencilDrawing &)> function)
{
using namespace blender::bke::gpencil;
@ -419,7 +418,7 @@ void GreasePencil::foreach_visible_drawing(
GreasePencilDrawingOrReference *drawing_or_reference = drawings[index];
if (drawing_or_reference->type == GREASE_PENCIL_DRAWING) {
GreasePencilDrawing *drawing = reinterpret_cast<GreasePencilDrawing *>(drawing_or_reference);
function(*drawing, layer);
function(*drawing);

Forget if we talked about this already, but without std::move in the function, there doesn't seem to be much of a point to this second override. Usually there is one for a const reference and one for an rvalue, I haven't seen a non-const reference override like this before.

Forget if we talked about this already, but without `std::move` in the function, there doesn't seem to be much of a point to this second override. Usually there is one for a const reference and one for an rvalue, I haven't seen a non-const reference override like this before.

Maybe @JacquesLucke can clarify here, but I believe sine add_overwrite has an implementation with an r-value reference that does the std::move I think this is fine?

Maybe @JacquesLucke can clarify here, but I believe sine `add_overwrite` has an implementation with an r-value reference that does the `std::move` I think this is fine?

I recommend just using a debugger to see if this calls the function you intend to call (the one with an rvalue reference). Haven't tried right now, but it will probably call the const reference version without std::move.

I recommend just using a debugger to see if this calls the function you intend to call (the one with an rvalue reference). Haven't tried right now, but it will probably call the const reference version without `std::move`.
}
else if (drawing_or_reference->type == GREASE_PENCIL_DRAWING_REFERENCE) {
/* TODO */

View File

@ -25,7 +25,6 @@ using namespace draw;
class ObjectModule {
private:
LayerModule &layers_;
MaterialModule &materials_;
ShaderModule &shaders_;
@ -152,39 +151,39 @@ class ObjectModule {
GPUVertBuf *color_tx = DRW_cache_grease_pencil_color_buffer_get(object, current_frame_);
GPUBatch *geom = DRW_cache_grease_pencil_get(object, current_frame_);
grease_pencil.foreach_visible_drawing(
current_frame_, [&](GreasePencilDrawing &drawing, bke::gpencil::Layer &layer) {
/* TODO(fclem): Pass per frame object matrix here. */
ResourceHandle handle = manager.resource_handle(object_ref);
gpObject &ob = objects_buf_.get_or_resize(handle.resource_index());
ob.is_shadeless = false;
ob.stroke_order3d = false;
ob.tint = float4(1.0); // frame_tint_get(gpd, frame.gpf, current_frame_);
ob.layer_offset = layer_offset;
ob.material_offset = material_offset;
// grease_pencil.foreach_visible_drawing(current_frame_, [&](GreasePencilDrawing & /*drawing*/)
// {
/* TODO(fclem): Pass per frame object matrix here. */
ResourceHandle handle = manager.resource_handle(object_ref);
gpObject &ob = objects_buf_.get_or_resize(handle.resource_index());
ob.is_shadeless = false;
ob.stroke_order3d = false;
ob.tint = float4(1.0); // frame_tint_get(gpd, frame.gpf, current_frame_);
ob.layer_offset = layer_offset;
ob.material_offset = material_offset;
if (do_layer_blending) {
// for (const LayerData &layer : frame.layers) {
// UNUSED_VARS(layer);
// if (has_blending(layer)) {
// object_subpass.framebuffer_set(*vfx_fb.current());
// }
if (do_layer_blending) {
// for (const LayerData &layer : frame.layers) {
// UNUSED_VARS(layer);

Typically dead code is discouraged.
Not sure what is it part of, so can't really give strong suggestions.

Typically dead code is discouraged. Not sure what is it part of, so can't really give strong suggestions.
// if (has_blending(layer)) {
// object_subpass.framebuffer_set(*vfx_fb.current());
// }
/* TODO(fclem): Only draw subrange of geometry for this layer. */
object_subpass.draw(geom, handle);
/* TODO(fclem): Only draw subrange of geometry for this layer. */
object_subpass.draw(geom, handle);
// if (has_blending(layer)) {
// layer_blend_sync(object_ref, object_subpass);
// }
// }
}
else {
/* Fast path. */
object_subpass.bind_texture("gp_pos_tx", position_tx);
object_subpass.bind_texture("gp_col_tx", color_tx);
object_subpass.draw(geom, handle);
}
});
// if (has_blending(layer)) {
// layer_blend_sync(object_ref, object_subpass);
// }
// }
}
else {
/* Fast path. */
object_subpass.bind_texture("gp_pos_tx", position_tx);
object_subpass.bind_texture("gp_col_tx", color_tx);
object_subpass.draw(geom, handle);
}
// });
#if 0
if (object_has_vfx) {
Review

Add a comment what is this about, or remove.

Add a comment what is this about, or remove.

View File

@ -226,16 +226,15 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra)
/* First count how many vertices and triangles are needed for the whole object. */
int total_points_num = 0;
int total_triangles_num = 0;
grease_pencil.foreach_visible_drawing(
cfra, [&](GreasePencilDrawing &drawing, blender::bke::gpencil::Layer &layer) {
bke::CurvesGeometry &curves = drawing.geometry.wrap();
int num_cyclic = count_cyclic_curves(curves);
/* One vertex is stored before and after as padding. Cyclic strokes have one extra
* vertex.*/
total_points_num += curves.points_num() + num_cyclic + curves.curves_num() * 2;
total_triangles_num += (curves.points_num() + num_cyclic) * 2;
total_triangles_num += drawing.runtime->triangles_cache.size();
});
grease_pencil.foreach_visible_drawing(cfra, [&](GreasePencilDrawing &drawing) {
bke::CurvesGeometry &curves = drawing.geometry.wrap();
int num_cyclic = count_cyclic_curves(curves);
/* One vertex is stored before and after as padding. Cyclic strokes have one extra
* vertex.*/
total_points_num += curves.points_num() + num_cyclic + curves.curves_num() * 2;
total_triangles_num += (curves.points_num() + num_cyclic) * 2;
total_triangles_num += drawing.runtime->triangles_cache.size();
});
GPUUsageType vbo_flag = GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY;
/* Create VBOs. */
@ -259,86 +258,84 @@ static void grease_pencil_batches_ensure(GreasePencil &grease_pencil, int cfra)
/* Fill buffers with data. */
int v = 0;
grease_pencil.foreach_visible_drawing(
cfra, [&](GreasePencilDrawing &drawing, blender::bke::gpencil::Layer &layer) {
bke::CurvesGeometry &curves = drawing.geometry.wrap();
bke::AttributeAccessor attributes = curves.attributes();
offset_indices::OffsetIndices<int> points_by_curve = curves.points_by_curve();
const Span<float3> positions = curves.positions();
const VArray<bool> cyclic = curves.cyclic();
VArray<float> radii = attributes.lookup_or_default<float>(
"radius", ATTR_DOMAIN_POINT, 1.0f);
VArray<float> opacities = attributes.lookup_or_default<float>(
"opacity", ATTR_DOMAIN_POINT, 1.0f);
VArray<int> materials = attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_CURVE, -1);
grease_pencil.foreach_visible_drawing(cfra, [&](GreasePencilDrawing &drawing) {
bke::CurvesGeometry &curves = drawing.geometry.wrap();
bke::AttributeAccessor attributes = curves.attributes();
offset_indices::OffsetIndices<int> points_by_curve = curves.points_by_curve();
const Span<float3> positions = curves.positions();
const VArray<bool> cyclic = curves.cyclic();
VArray<float> radii = attributes.lookup_or_default<float>("radius", ATTR_DOMAIN_POINT, 1.0f);
VArray<float> opacities = attributes.lookup_or_default<float>(
"opacity", ATTR_DOMAIN_POINT, 1.0f);
VArray<int> materials = attributes.lookup_or_default<int>(
"material_index", ATTR_DOMAIN_CURVE, -1);
auto populate_point = [&](int curve_i, int point_i, int v_start, int v) {
copy_v3_v3(verts[v].pos, positions[point_i]);
verts[v].radius = radii[point_i];
verts[v].opacity = opacities[point_i];
verts[v].point_id = v;
verts[v].stroke_id = v_start;
verts[v].mat = materials[curve_i] % GPENCIL_MATERIAL_BUFFER_LEN;
auto populate_point = [&](int curve_i, int point_i, int v_start, int v) {
copy_v3_v3(verts[v].pos, positions[point_i]);

Use the * overload rather than adding .varray at the end

Use the `*` overload rather than adding `.varray` at the end
verts[v].radius = radii[point_i];
verts[v].opacity = opacities[point_i];
verts[v].point_id = v;
verts[v].stroke_id = v_start;
verts[v].mat = materials[curve_i] % GPENCIL_MATERIAL_BUFFER_LEN;
/* TODO */
verts[v].packed_asp_hard_rot = pack_rotation_aspect_hardness(0.0f, 1.0f, 1.0f);
/* TODO */
verts[v].u_stroke = 0;
/* TODO */
verts[v].uv_fill[0] = verts[v].uv_fill[1] = 0;
/* TODO */
verts[v].packed_asp_hard_rot = pack_rotation_aspect_hardness(0.0f, 1.0f, 1.0f);
/* TODO */
verts[v].u_stroke = 0;
/* TODO */
verts[v].uv_fill[0] = verts[v].uv_fill[1] = 0;

These .as_span() calls shouldn't be necessary

These `.as_span()` calls shouldn't be necessary
/* TODO */
copy_v4_v4(cols[v].vcol, float4(0.0f, 0.0f, 0.0f, 0.0f));
copy_v4_v4(cols[v].fcol, float4(0.0f, 0.0f, 0.0f, 0.0f));
/* TODO */
copy_v4_v4(cols[v].vcol, float4(0.0f, 0.0f, 0.0f, 0.0f));
copy_v4_v4(cols[v].fcol, float4(0.0f, 0.0f, 0.0f, 0.0f));
/* TODO */
cols[v].fcol[3] = (int(cols[v].fcol[3] * 10000.0f) * 10.0f) + 1.0f;
/* TODO */
cols[v].fcol[3] = (int(cols[v].fcol[3] * 10000.0f) * 10.0f) + 1.0f;
int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT;
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 0, v_mat + 1, v_mat + 2);
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3);
};
int v_mat = (v << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT;
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 0, v_mat + 1, v_mat + 2);
GPU_indexbuf_add_tri_verts(&ibo, v_mat + 2, v_mat + 1, v_mat + 3);
};
int t = 0;
for (const int curve_i : curves.curves_range()) {
IndexRange points = points_by_curve[curve_i];
const bool is_cyclic = cyclic[curve_i];
const int v_start = v;
int num_triangles = 0;
int t = 0;
for (const int curve_i : curves.curves_range()) {
IndexRange points = points_by_curve[curve_i];
const bool is_cyclic = cyclic[curve_i];
const int v_start = v;
int num_triangles = 0;

Add details about TODO. Something that helps others to pick up a task, or to understand that specific case is not expected to be yet working.

Add details about TODO. Something that helps others to pick up a task, or to understand that specific case is not expected to be yet working.
/* First point is not drawn. */
verts[v].mat = -1;
v++;
/* First point is not drawn. */
verts[v].mat = -1;
v++;
if (points.size() >= 3) {
num_triangles = points.size() - 2;
for (const int tri_i : IndexRange(num_triangles)) {
uint3 tri = drawing.runtime->triangles_cache[t + tri_i];
GPU_indexbuf_add_tri_verts(&ibo,
(v + tri.x) << GP_VERTEX_ID_SHIFT,
(v + tri.y) << GP_VERTEX_ID_SHIFT,
(v + tri.z) << GP_VERTEX_ID_SHIFT);
}
}
for (const int point_i : points) {
populate_point(curve_i, point_i, v_start, v);
v++;
}
if (is_cyclic) {
populate_point(curve_i, points.first(), v_start, v);
v++;
}
/* Last point is not drawn. */
verts[v].mat = -1;
v++;
t += num_triangles;
if (points.size() >= 3) {
num_triangles = points.size() - 2;
for (const int tri_i : IndexRange(num_triangles)) {
uint3 tri = drawing.runtime->triangles_cache[t + tri_i];
GPU_indexbuf_add_tri_verts(&ibo,
(v + tri.x) << GP_VERTEX_ID_SHIFT,
(v + tri.y) << GP_VERTEX_ID_SHIFT,
(v + tri.z) << GP_VERTEX_ID_SHIFT);
}
});
}
for (const int point_i : points) {
populate_point(curve_i, point_i, v_start, v);
v++;
}
if (is_cyclic) {
populate_point(curve_i, points.first(), v_start, v);
v++;
}
/* Last point is not drawn. */
verts[v].mat = -1;
v++;
t += num_triangles;
}
});
/* Mark last 2 verts as invalid. */
verts[total_points_num + 0].mat = -1;

View File

@ -167,9 +167,8 @@ typedef struct GreasePencil {
#ifdef __cplusplus
blender::Span<GreasePencilDrawingOrReference *> drawings() const;
void foreach_visible_drawing(
int frame,
blender::FunctionRef<void(GreasePencilDrawing &, blender::bke::gpencil::Layer &)> function);
void foreach_visible_drawing(int frame,
blender::FunctionRef<void(GreasePencilDrawing &)> function);
void read_drawing_array(BlendDataReader *reader);
void write_drawing_array(BlendWriter *writer);
void free_drawing_array();