Overlay-Next: Armature #126474
@ -640,10 +640,12 @@ set(GLSL_SRC
|
||||
engines/overlay/shaders/overlay_armature_envelope_solid_frag.glsl
|
||||
engines/overlay/shaders/overlay_armature_envelope_solid_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_solid_frag.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_solid_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_frag.glsl
|
||||
|
661
source/blender/draw/engines/overlay/overlay_next_armature.hh
Normal file
@ -0,0 +1,661 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "overlay_next_private.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
using namespace blender;
|
||||
|
||||
enum eArmatureDrawMode {
|
||||
ARM_DRAW_MODE_OBJECT,
|
||||
ARM_DRAW_MODE_POSE,
|
||||
ARM_DRAW_MODE_EDIT,
|
||||
};
|
||||
|
||||
class Armatures {
|
||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
using BoneEnvelopeBuf = ShapeInstanceBuf<BoneEnvelopeData>;
|
||||
using BoneStickBuf = ShapeInstanceBuf<BoneStickData>;
|
||||
using DegreesOfFreedomBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
|
||||
private:
|
||||
const SelectionType selection_type_;
|
||||
|
||||
PassSimple armature_ps_ = {"Armature"};
|
||||
|
||||
/* Force transparent drawing in Xray mode. */
|
||||
bool draw_transparent = false;
|
||||
/* Force disable drawing relation is relations are off in viewport. */
|
||||
bool show_relations = false;
|
||||
/* Show selection state. */
|
||||
bool show_outline = false;
|
||||
|
||||
struct BoneBuffers {
|
||||
const SelectionType selection_type_;
|
||||
|
||||
/* Bone end points (joints). */
|
||||
PassSimple::Sub *sphere_fill = nullptr;
|
||||
PassSimple::Sub *sphere_outline = nullptr;
|
||||
/* Bone shapes. */
|
||||
PassSimple::Sub *shape_fill = nullptr;
|
||||
PassSimple::Sub *shape_outline = nullptr;
|
||||
/* Custom bone wire-frame. */
|
||||
PassSimple::Sub *shape_wire = nullptr;
|
||||
/* Envelopes. */
|
||||
PassSimple::Sub *envelope_fill = nullptr;
|
||||
PassSimple::Sub *envelope_outline = nullptr;
|
||||
PassSimple::Sub *envelope_distance = nullptr;
|
||||
/* Stick bones. */
|
||||
PassSimple::Sub *stick = nullptr;
|
||||
/* Wire bones. */
|
||||
PassSimple::Sub *wire = nullptr;
|
||||
|
||||
/* Bone axes. */
|
||||
PassSimple::Sub *arrows = nullptr;
|
||||
/* Degrees of freedom. */
|
||||
PassSimple::Sub *degrees_of_freedom_fill = nullptr;
|
||||
PassSimple::Sub *degrees_of_freedom_wire = nullptr;
|
||||
/* Relations. */
|
||||
PassSimple::Sub *relations = nullptr;
|
||||
|
||||
BoneInstanceBuf bbones_fill_buf = {selection_type_, "bbones_fill_buf"};
|
||||
BoneInstanceBuf bbones_outline_buf = {selection_type_, "bbones_outline_buf"};
|
||||
|
||||
BoneInstanceBuf octahedral_fill_buf = {selection_type_, "octahedral_fill_buf"};
|
||||
BoneInstanceBuf octahedral_outline_buf = {selection_type_, "octahedral_outline_buf"};
|
||||
|
||||
BoneInstanceBuf sphere_fill_buf = {selection_type_, "sphere_fill_buf"};
|
||||
BoneInstanceBuf sphere_outline_buf = {selection_type_, "sphere_outline_buf"};
|
||||
|
||||
BoneEnvelopeBuf envelope_fill_buf = {selection_type_, "envelope_fill_buf"};
|
||||
BoneEnvelopeBuf envelope_outline_buf = {selection_type_, "envelope_outline_buf"};
|
||||
BoneEnvelopeBuf envelope_distance_buf = {selection_type_, "envelope_distance_buf"};
|
||||
|
||||
BoneStickBuf stick_buf = {selection_type_, "stick_buf"};
|
||||
|
||||
LinePrimitiveBuf wire_buf = {selection_type_, "wire_buf"};
|
||||
|
||||
EmptyInstanceBuf arrows_buf = {selection_type_, "arrows_buf"};
|
||||
|
||||
DegreesOfFreedomBuf degrees_of_freedom_fill_buf = {SelectionType::DISABLED,
|
||||
"degrees_of_freedom_buf"};
|
||||
DegreesOfFreedomBuf degrees_of_freedom_wire_buf = {SelectionType::DISABLED,
|
||||
"degrees_of_freedom_buf"};
|
||||
|
||||
LinePrimitiveBuf relations_buf = {SelectionType::DISABLED, "relations_buf"};
|
||||
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_fill;
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_outline;
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_wire;
|
||||
|
||||
BoneInstanceBuf &custom_shape_fill_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_fill.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneSolid");
|
||||
});
|
||||
}
|
||||
|
||||
BoneInstanceBuf &custom_shape_outline_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_outline.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneOutline");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
BoneInstanceBuf &custom_shape_wire_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_wire.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneWire");
|
||||
});
|
||||
}
|
||||
|
||||
BoneBuffers(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||
};
|
||||
|
||||
BoneBuffers opaque_ = {selection_type_};
|
||||
BoneBuffers transparent_ = {selection_type_};
|
||||
|
||||
bool enabled_ = false;
|
||||
|
||||
public:
|
||||
Armatures(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||
|
||||
void begin_sync(Resources &res, const State &state)
|
||||
{
|
||||
enabled_ = !(state.overlay.flag & V3D_OVERLAY_HIDE_BONES);
|
||||
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool is_select_mode = (selection_type_ != SelectionType::DISABLED);
|
||||
|
||||
draw_transparent = (state.v3d->shading.type == OB_WIRE) || XRAY_FLAG_ENABLED(state.v3d);
|
||||
show_relations = !((state.v3d->flag & V3D_HIDE_HELPLINES) || is_select_mode);
|
||||
show_outline = (state.v3d->flag & V3D_SELECT_OUTLINE);
|
||||
|
||||
const bool do_smooth_wire = U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE;
|
||||
fclem marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Use Use `this->` prefix to make it clear that this is not just some local variable, but modifying `this`.
Clément Foucault
commented
I prefer using I prefer using `_` suffix as they are private variables.
|
||||
const float wire_alpha = state.overlay.bone_wire_alpha;
|
||||
/* Draw bone outlines and custom shape wire with a specific alpha. */
|
||||
const bool use_wire_alpha = (wire_alpha < 1.0f);
|
||||
|
||||
GPUTexture **depth_tex = (state.xray_enabled) ? &res.depth_tx : &res.dummy_depth_tx;
|
||||
|
||||
armature_ps_.init();
|
||||
res.select_bind(armature_ps_);
|
||||
|
||||
/* Envelope distances and degrees of freedom need to be drawn first as they use additive
|
||||
* transparent blending. */
|
||||
{
|
||||
DRWState transparent_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
DRW_STATE_BLEND_ADD;
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_distance");
|
||||
sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.push_constant("isDistance", true);
|
||||
opaque_.envelope_distance = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_distance");
|
||||
sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.push_constant("isDistance", true);
|
||||
transparent_.envelope_distance = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.envelope_distance = opaque_.envelope_distance;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_fill");
|
||||
sub.state_set(transparent_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
fclem marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
For every anonymous block, add a little comment that makes it clear what the block is for. At least for the outer ones; the inner ones start with a line that's already quite indicative of what they're for. For every anonymous block, add a little comment that makes it clear what the block is for. At least for the outer ones; the inner ones start with a line that's already quite indicative of what they're for.
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.degrees_of_freedom_fill = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_fill");
|
||||
sub.state_set(transparent_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
transparent_.degrees_of_freedom_fill = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.degrees_of_freedom_fill = opaque_.degrees_of_freedom_fill;
|
||||
}
|
||||
}
|
||||
|
||||
DRWState default_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
DRW_STATE_WRITE_DEPTH;
|
||||
|
||||
/* Bone Shapes (Octahedral, Box, Custom Shapes, Spheres). */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.sphere_fill");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.sphere_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.sphere_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.4f);
|
||||
transparent_.sphere_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_fill");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.shape_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
transparent_.shape_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.sphere_outline");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.sphere_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.sphere_outline");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.sphere_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.sphere_outline = opaque_.sphere_outline;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_outline");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.shape_outline");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("depthTex", depth_tex);
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
sub.push_constant("do_smooth_wire", do_smooth_wire);
|
||||
transparent_.shape_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.shape_outline = opaque_.shape_outline;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_wire");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.shape_wire");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("depthTex", depth_tex);
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
sub.push_constant("do_smooth_wire", do_smooth_wire);
|
||||
transparent_.shape_wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.shape_wire = opaque_.shape_wire;
|
||||
}
|
||||
}
|
||||
/* Degrees of freedom. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_wire");
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.degrees_of_freedom_wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_wire");
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
transparent_.degrees_of_freedom_wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.degrees_of_freedom_wire = opaque_.degrees_of_freedom_wire;
|
||||
}
|
||||
}
|
||||
/* Stick bones. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.stick");
|
||||
sub.shader_set(res.shaders.armature_stick.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.stick = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.stick");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_stick.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.stick = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.stick = opaque_.stick;
|
||||
}
|
||||
}
|
||||
/* Envelopes. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_fill");
|
||||
sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("isDistance", false);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.envelope_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
|
||||
(DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK),
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
transparent_.envelope_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_outline");
|
||||
sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.envelope_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_outline");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
|
||||
(DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK),
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.envelope_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.envelope_outline = opaque_.envelope_outline;
|
||||
}
|
||||
}
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.wire");
|
||||
sub.shader_set(res.shaders.armature_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
dr.sybren marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
Since this code only accesses properties of Since this code only accesses properties of `bb`, wouldn't it make sense to have it as a method on `BoneBuffers`?
Clément Foucault
commented
It's here as it is a design pattern that is used throughout the overlay next codebase. It increases locality of the code. And this is never supposed to be called anywhere else. It's here as it is a design pattern that is used throughout the overlay next codebase. It increases locality of the code. And this is never supposed to be called anywhere else.
|
||||
auto &sub = armature_ps_.sub("transparent.wire");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.wire = opaque_.wire;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.arrow");
|
||||
sub.shader_set(res.shaders.extra_shape.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.arrows = ⊂
|
||||
transparent_.arrows = opaque_.arrows;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.relations");
|
||||
sub.shader_set(res.shaders.extra_wire.get());
|
||||
fclem marked this conversation as resolved
Outdated
Sybren A. Stüvel
commented
After all the code above that seems to put stuff into After all the code above that seems to put stuff into`transparent` and `opaque`, why are they cleared now? This could use a comment.
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.relations = ⊂
|
||||
transparent_.relations = opaque_.relations;
|
||||
}
|
||||
|
||||
auto shape_instance_bufs_begin_sync = [](BoneBuffers &bb) {
|
||||
bb.envelope_fill_buf.clear();
|
||||
bb.envelope_outline_buf.clear();
|
||||
bb.envelope_distance_buf.clear();
|
||||
bb.bbones_fill_buf.clear();
|
||||
bb.bbones_outline_buf.clear();
|
||||
bb.octahedral_fill_buf.clear();
|
||||
bb.octahedral_outline_buf.clear();
|
||||
bb.sphere_fill_buf.clear();
|
||||
bb.sphere_outline_buf.clear();
|
||||
bb.stick_buf.clear();
|
||||
bb.wire_buf.clear();
|
||||
Sybren A. Stüvel
commented
IMO it could make sense to prefix those fields with IMO it could make sense to prefix those fields with `legacy_`; that way their legacy status is clear at every use site.
Clément Foucault
commented
That makes the patch modify a lot more of legacy overlay code. Which I wanted to avoid. But I can batch rename them if that's wanted. That makes the patch modify a lot more of legacy overlay code. Which I wanted to avoid. But I can batch rename them if that's wanted.
Sybren A. Stüvel
commented
hmmmmm in that case better to keep it as-is for now. Or as a followup 'cleanup' commit/PR? hmmmmm in that case better to keep it as-is for now. Or as a followup 'cleanup' commit/PR?
Clément Foucault
commented
Added as follow up to #102179 Added as follow up to #102179
|
||||
bb.arrows_buf.clear();
|
||||
bb.degrees_of_freedom_fill_buf.clear();
|
||||
bb.degrees_of_freedom_wire_buf.clear();
|
||||
bb.relations_buf.clear();
|
||||
/* TODO(fclem): Potentially expensive operation recreating a lot of gpu buffers.
|
||||
* Prefer a pruning strategy. */
|
||||
bb.custom_shape_fill.clear();
|
||||
bb.custom_shape_outline.clear();
|
||||
bb.custom_shape_wire.clear();
|
||||
};
|
||||
|
||||
shape_instance_bufs_begin_sync(transparent_);
|
||||
shape_instance_bufs_begin_sync(opaque_);
|
||||
}
|
||||
|
||||
struct DrawContext {
|
||||
/* Current armature object */
|
||||
Object *ob = nullptr;
|
||||
const ObjectRef *ob_ref = nullptr;
|
||||
|
||||
/* Note: can be mutated inside `draw_armature_pose()`. */
|
||||
eArmatureDrawMode draw_mode = ARM_DRAW_MODE_OBJECT;
|
||||
eArmature_Drawtype drawtype = ARM_OCTA;
|
||||
|
||||
Armatures::BoneBuffers *bone_buf = nullptr;
|
||||
Resources *res = nullptr;
|
||||
const ShapeCache *shapes = nullptr;
|
||||
|
||||
/* TODO: Legacy structures to be removed after overlay next is shipped. */
|
||||
DRWCallBuffer *outline = nullptr;
|
||||
DRWCallBuffer *solid = nullptr;
|
||||
DRWCallBuffer *wire = nullptr;
|
||||
DRWCallBuffer *envelope_outline = nullptr;
|
||||
DRWCallBuffer *envelope_solid = nullptr;
|
||||
DRWCallBuffer *envelope_distance = nullptr;
|
||||
DRWCallBuffer *stick = nullptr;
|
||||
DRWCallBuffer *dof_lines = nullptr;
|
||||
DRWCallBuffer *dof_sphere = nullptr;
|
||||
DRWCallBuffer *point_solid = nullptr;
|
||||
DRWCallBuffer *point_outline = nullptr;
|
||||
DRWShadingGroup *custom_solid = nullptr;
|
||||
DRWShadingGroup *custom_outline = nullptr;
|
||||
DRWShadingGroup *custom_wire = nullptr;
|
||||
GHash *custom_shapes_ghash = nullptr;
|
||||
OVERLAY_ExtraCallBuffers *extras = nullptr;
|
||||
|
||||
/* Not a theme, this is an override. */
|
||||
const float *const_color = nullptr;
|
||||
/* Wire thickness. */
|
||||
float const_wire = 0.0f;
|
||||
|
||||
bool do_relations = false;
|
||||
bool transparent = false;
|
||||
bool show_relations = false;
|
||||
bool draw_envelope_distance = false;
|
||||
bool draw_relation_from_head = false;
|
||||
/* Draw the inner part of the bones, otherwise render just outlines. */
|
||||
bool is_filled = false;
|
||||
|
||||
const ThemeWireColor *bcolor = nullptr; /* pchan color */
|
||||
|
||||
DrawContext() = default;
|
||||
|
||||
/* Runtime switch between legacy and new overlay codebase.
|
||||
* Should be removed once the legacy code is removed. */
|
||||
bool is_overlay_next() const
|
||||
{
|
||||
return this->bone_buf != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
DrawContext create_draw_context(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
const ShapeCache &shapes,
|
||||
const State &state,
|
||||
eArmatureDrawMode draw_mode)
|
||||
{
|
||||
bArmature *arm = static_cast<bArmature *>(ob_ref.object->data);
|
||||
|
||||
DrawContext ctx;
|
||||
ctx.ob = ob_ref.object;
|
||||
ctx.ob_ref = &ob_ref;
|
||||
ctx.res = &res;
|
||||
ctx.shapes = &shapes;
|
||||
ctx.draw_mode = draw_mode;
|
||||
ctx.drawtype = eArmature_Drawtype(arm->drawtype);
|
||||
|
||||
const bool is_edit_or_pose_mode = draw_mode != ARM_DRAW_MODE_OBJECT;
|
||||
const bool draw_as_wire = (ctx.ob->dt < OB_SOLID);
|
||||
const bool is_transparent = draw_transparent || (draw_as_wire && is_edit_or_pose_mode);
|
||||
|
||||
ctx.bone_buf = is_transparent ? &transparent_ : &opaque_;
|
||||
|
||||
ctx.is_filled = (!draw_transparent && !draw_as_wire) || is_edit_or_pose_mode;
|
||||
ctx.show_relations = show_relations;
|
||||
ctx.do_relations = show_relations && is_edit_or_pose_mode;
|
||||
ctx.draw_envelope_distance = is_edit_or_pose_mode;
|
||||
ctx.draw_relation_from_head = (arm->flag & ARM_DRAW_RELATION_FROM_HEAD);
|
||||
ctx.const_color = is_edit_or_pose_mode ? nullptr : &res.object_wire_color(ob_ref, state)[0];
|
||||
ctx.const_wire = (!ctx.is_filled || is_transparent) ? 1.0f : 0.0f;
|
||||
if ((ctx.ob->base_flag & BASE_SELECTED) && show_outline) {
|
||||
ctx.const_wire = 1.5f;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
Sybren A. Stüvel
commented
Same as in Same as in `begin_sync`, this seems to be "feature envy".
Clément Foucault
commented
Same answer then :) I suppose this is resolve now? Same answer then :) I suppose this is resolve now?
|
||||
void edit_object_sync(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
ShapeCache &shapes,
|
||||
const State &state)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawContext ctx = create_draw_context(ob_ref, res, shapes, state, ARM_DRAW_MODE_EDIT);
|
||||
draw_armature_edit(&ctx);
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
const ShapeCache &shapes,
|
||||
const State &state)
|
||||
{
|
||||
if (!enabled_ || ob_ref.object->dt == OB_BOUNDBOX) {
|
||||
return;
|
||||
}
|
||||
|
||||
eArmatureDrawMode draw_mode = is_pose_mode(ob_ref.object, state) ? ARM_DRAW_MODE_POSE :
|
||||
ARM_DRAW_MODE_OBJECT;
|
||||
|
||||
DrawContext ctx = create_draw_context(ob_ref, res, shapes, state, draw_mode);
|
||||
draw_armature_pose(&ctx);
|
||||
}
|
||||
|
||||
void end_sync(Resources & /*res*/, const ShapeCache &shapes, const State & /*state*/)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto end_sync = [&](BoneBuffers &bb) {
|
||||
bb.sphere_fill_buf.end_sync(*bb.sphere_fill, shapes.bone_sphere.get());
|
||||
bb.sphere_outline_buf.end_sync(*bb.sphere_outline, shapes.bone_sphere_wire.get());
|
||||
|
||||
bb.octahedral_fill_buf.end_sync(*bb.shape_fill, shapes.bone_octahedron.get());
|
||||
bb.octahedral_outline_buf.end_sync(
|
||||
*bb.shape_outline, shapes.bone_octahedron_wire.get(), GPU_PRIM_LINES, 1);
|
||||
|
||||
bb.bbones_fill_buf.end_sync(*bb.shape_fill, shapes.bone_box.get());
|
||||
bb.bbones_outline_buf.end_sync(
|
||||
*bb.shape_outline, shapes.bone_box_wire.get(), GPU_PRIM_LINES, 1);
|
||||
|
||||
bb.envelope_fill_buf.end_sync(*bb.envelope_fill, shapes.bone_envelope.get());
|
||||
bb.envelope_outline_buf.end_sync(*bb.envelope_outline, shapes.bone_envelope_wire.get());
|
||||
bb.envelope_distance_buf.end_sync(*bb.envelope_distance, shapes.bone_envelope.get());
|
||||
|
||||
bb.stick_buf.end_sync(*bb.stick, shapes.bone_stick.get());
|
||||
|
||||
bb.wire_buf.end_sync(*bb.wire);
|
||||
|
||||
bb.arrows_buf.end_sync(*bb.arrows, shapes.arrows.get());
|
||||
|
||||
bb.degrees_of_freedom_fill_buf.end_sync(*bb.degrees_of_freedom_fill,
|
||||
shapes.bone_degrees_of_freedom.get());
|
||||
bb.degrees_of_freedom_wire_buf.end_sync(*bb.degrees_of_freedom_wire,
|
||||
shapes.bone_degrees_of_freedom_wire.get());
|
||||
|
||||
bb.relations_buf.end_sync(*bb.relations);
|
||||
|
||||
using CustomShapeBuf = MutableMapItem<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>>;
|
||||
|
||||
for (CustomShapeBuf item : bb.custom_shape_fill.items()) {
|
||||
item.value->end_sync(*bb.shape_fill, item.key);
|
||||
}
|
||||
for (CustomShapeBuf item : bb.custom_shape_outline.items()) {
|
||||
item.value->end_sync(*bb.shape_outline, item.key, GPU_PRIM_LINES, 1);
|
||||
}
|
||||
for (CustomShapeBuf item : bb.custom_shape_wire.items()) {
|
||||
item.value->end_sync(*bb.shape_wire, item.key, GPU_PRIM_TRIS, 2);
|
||||
}
|
||||
};
|
||||
|
||||
end_sync(transparent_);
|
||||
end_sync(opaque_);
|
||||
}
|
||||
|
||||
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(armature_ps_, view);
|
||||
}
|
||||
|
||||
/* Public for the time of the Overlay Next port to avoid duplicated logic. */
|
||||
public:
|
||||
static void draw_armature_pose(Armatures::DrawContext *ctx);
|
||||
static void draw_armature_edit(Armatures::DrawContext *ctx);
|
||||
|
||||
static bool is_pose_mode(const Object *armature_ob, const State &state)
|
||||
{
|
||||
Object *active_ob = state.active_base->object;
|
||||
|
||||
/* Armature is in pose mode. */
|
||||
if (((armature_ob == active_ob) || (armature_ob->mode & OB_MODE_POSE)) &&
|
||||
((state.object_mode & OB_MODE_POSE) != 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Active object is in weight paint and the associated armature is in pose mode. */
|
||||
if ((active_ob != nullptr) && (state.object_mode & OB_MODE_ALL_WEIGHT_PAINT)) {
|
||||
if (armature_ob == BKE_object_pose_armature_get(active_ob)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
@ -65,6 +65,10 @@ void Instance::init()
|
||||
state.overlay.wireframe_threshold = state.v3d->overlay.wireframe_threshold;
|
||||
state.overlay.wireframe_opacity = state.v3d->overlay.wireframe_opacity;
|
||||
}
|
||||
|
||||
state.do_pose_xray = (state.overlay.flag & V3D_OVERLAY_BONE_SELECT);
|
||||
state.do_pose_fade_geom = state.do_pose_xray && !(state.object_mode & OB_MODE_WEIGHT_PAINT) &&
|
||||
ctx->object_pose != nullptr;
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove DRW global usage. */
|
||||
@ -73,10 +77,9 @@ void Instance::init()
|
||||
resources.weight_ramp_tx.wrap(G_draw.weight_ramp);
|
||||
{
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ;
|
||||
if (resources.dummy_depth_tx.ensure_2d(GPU_DEPTH24_STENCIL8, int2(1, 1), usage)) {
|
||||
uint32_t data = 0;
|
||||
GPU_texture_update_sub(
|
||||
resources.dummy_depth_tx, GPU_DATA_UINT_24_8, &data, 0, 0, 0, 1, 1, 1);
|
||||
if (resources.dummy_depth_tx.ensure_2d(GPU_DEPTH_COMPONENT32F, int2(1, 1), usage)) {
|
||||
float data = 1.0f;
|
||||
GPU_texture_update_sub(resources.dummy_depth_tx, GPU_DATA_FLOAT, &data, 0, 0, 0, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,6 +98,7 @@ void Instance::begin_sync()
|
||||
outline.begin_sync(resources, state);
|
||||
|
||||
auto begin_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.armatures.begin_sync(resources, state);
|
||||
layer.bounds.begin_sync();
|
||||
layer.cameras.begin_sync(resources, state, view);
|
||||
layer.curves.begin_sync(resources, state, view);
|
||||
@ -131,8 +135,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
|
||||
const bool needs_prepass = !state.xray_enabled; /* TODO */
|
||||
|
||||
OverlayLayer &layer = (state.use_in_front && ob_ref.object->dtx & OB_DRAW_IN_FRONT) ? infront :
|
||||
regular;
|
||||
OverlayLayer &layer = object_is_in_front(ob_ref.object, state) ? infront : regular;
|
||||
|
||||
if (needs_prepass) {
|
||||
layer.prepass.object_sync(manager, ob_ref, resources);
|
||||
@ -144,6 +147,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
layer.meshes.edit_object_sync(manager, ob_ref, resources);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
layer.armatures.edit_object_sync(ob_ref, resources, shapes, state);
|
||||
break;
|
||||
case OB_CURVES_LEGACY:
|
||||
layer.curves.edit_object_sync_legacy(manager, ob_ref, resources);
|
||||
@ -177,6 +181,9 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
layer.cameras.object_sync(ob_ref, shapes, manager, resources, state);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if (!in_edit_mode) {
|
||||
layer.armatures.object_sync(ob_ref, resources, shapes, state);
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if (!in_edit_mode) {
|
||||
@ -218,6 +225,7 @@ void Instance::end_sync()
|
||||
resources.end_sync();
|
||||
|
||||
auto end_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.armatures.end_sync(resources, shapes, state);
|
||||
layer.bounds.end_sync(resources, shapes, state);
|
||||
layer.cameras.end_sync(resources, shapes, state);
|
||||
layer.empties.end_sync(resources, shapes, state);
|
||||
@ -362,6 +370,7 @@ void Instance::draw(Manager &manager)
|
||||
layer.relations.draw(framebuffer, manager, view);
|
||||
layer.fluids.draw(framebuffer, manager, view);
|
||||
layer.particles.draw(framebuffer, manager, view);
|
||||
layer.armatures.draw(framebuffer, manager, view);
|
||||
layer.meshes.draw(framebuffer, manager, view);
|
||||
};
|
||||
|
||||
@ -481,21 +490,24 @@ bool Instance::object_is_edit_mode(const Object *object)
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
#include "overlay_private.hh"
|
||||
|
||||
/* TODO(fclem): Move elsewhere. */
|
||||
BoneInstanceData::BoneInstanceData(Object *ob,
|
||||
const float *pos,
|
||||
const float radius,
|
||||
const float color[4])
|
||||
bool Instance::object_is_in_front(const Object *object, const State &state)
|
||||
{
|
||||
/* TODO(fclem): Use C++ math API. */
|
||||
mul_v3_v3fl(this->mat[0], ob->object_to_world().ptr()[0], radius);
|
||||
mul_v3_v3fl(this->mat[1], ob->object_to_world().ptr()[1], radius);
|
||||
mul_v3_v3fl(this->mat[2], ob->object_to_world().ptr()[2], radius);
|
||||
mul_v3_m4v3(this->mat[3], ob->object_to_world().ptr(), pos);
|
||||
/* WATCH: Reminder, alpha is wire-size. */
|
||||
OVERLAY_bone_instance_data_set_color(this, color);
|
||||
switch (object->type) {
|
||||
case OB_ARMATURE:
|
||||
return (object->dtx & OB_DRAW_IN_FRONT) ||
|
||||
(state.do_pose_xray && Armatures::is_pose_mode(object, state));
|
||||
case OB_MESH:
|
||||
case OB_CURVES_LEGACY:
|
||||
case OB_SURF:
|
||||
case OB_LATTICE:
|
||||
case OB_MBALL:
|
||||
case OB_FONT:
|
||||
case OB_CURVES:
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME:
|
||||
return state.use_in_front && (object->dtx & OB_DRAW_IN_FRONT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
#include "overlay_next_antialiasing.hh"
|
||||
#include "overlay_next_armature.hh"
|
||||
#include "overlay_next_background.hh"
|
||||
#include "overlay_next_bounds.hh"
|
||||
#include "overlay_next_camera.hh"
|
||||
@ -62,6 +63,7 @@ class Instance {
|
||||
struct OverlayLayer {
|
||||
const SelectionType selection_type_;
|
||||
|
||||
Armatures armatures = {selection_type_};
|
||||
Bounds bounds = {selection_type_};
|
||||
Cameras cameras = {selection_type_};
|
||||
Curves curves;
|
||||
@ -119,6 +121,7 @@ class Instance {
|
||||
bool in_edit_mode,
|
||||
bool in_paint_mode,
|
||||
bool in_sculpt_mode);
|
||||
bool object_is_in_front(const Object *object, const State &state);
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
@ -35,7 +35,8 @@ class Metaballs {
|
||||
|
||||
void edit_object_sync(const ObjectRef &ob_ref, Resources &res)
|
||||
{
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
const Object *ob = ob_ref.object;
|
||||
const MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
Sybren A. Stüvel
commented
Not sure how these changes are relevant to the Armature overlay? Not sure how these changes are relevant to the Armature overlay?
Clément Foucault
commented
I modified the constructor used for I modified the constructor used for `circle_buf_.append`. But if you are talking about these two lines, then it is just small cleanup that I spotted doing the change.
|
||||
|
||||
const float *color;
|
||||
const float *col_radius = res.theme_settings.color_mball_radius;
|
||||
@ -48,28 +49,31 @@ class Metaballs {
|
||||
const bool is_selected = (ml->flag & SELECT) != 0;
|
||||
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
|
||||
const float stiffness_radius = ml->rad * atanf(ml->s) * 2.0f / math::numbers::pi;
|
||||
const float3 position = float3(&ml->x);
|
||||
|
||||
const select::ID radius_id = res.select_id(ob_ref, MBALLSEL_RADIUS | elem_num);
|
||||
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
|
||||
circle_buf_.append({ob_ref.object, &ml->x, ml->rad, color}, radius_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, ml->rad, color}, radius_id);
|
||||
|
||||
const select::ID stiff_id = res.select_id(ob_ref, MBALLSEL_STIFF | elem_num);
|
||||
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
|
||||
circle_buf_.append({ob_ref.object, &ml->x, stiffness_radius, color}, stiff_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, stiffness_radius, color}, stiff_id);
|
||||
elem_num += 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
||||
{
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
const Object *ob = ob_ref.object;
|
||||
const MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
|
||||
const float4 &color = res.object_wire_color(ob_ref, state);
|
||||
const select::ID select_id = res.select_id(ob_ref);
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
|
||||
const float3 position = float3(&ml->x);
|
||||
/* Draw radius only. */
|
||||
circle_buf_.append({ob_ref.object, &ml->x, ml->rad, color}, select_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, ml->rad, color}, select_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,10 @@ struct State {
|
||||
bool hide_overlays;
|
||||
bool xray_enabled;
|
||||
bool xray_enabled_and_not_wire;
|
||||
/* Brings the active pose armature in front of all objects. */
|
||||
bool do_pose_xray;
|
||||
/* Add a veil on top of all surfaces to make the active pose armature pop out. */
|
||||
bool do_pose_fade_geom;
|
||||
float xray_opacity;
|
||||
short v3d_flag; /* TODO: move to #View3DOverlay. */
|
||||
short v3d_gridflag; /* TODO: move to #View3DOverlay. */
|
||||
@ -95,6 +99,19 @@ class ShapeCache {
|
||||
using BatchPtr = std::unique_ptr<gpu::Batch, BatchDeleter>;
|
||||
|
||||
public:
|
||||
BatchPtr bone_box;
|
||||
BatchPtr bone_box_wire;
|
||||
BatchPtr bone_envelope;
|
||||
BatchPtr bone_envelope_wire;
|
||||
BatchPtr bone_octahedron;
|
||||
BatchPtr bone_octahedron_wire;
|
||||
BatchPtr bone_sphere;
|
||||
BatchPtr bone_sphere_wire;
|
||||
BatchPtr bone_stick;
|
||||
|
||||
BatchPtr bone_degrees_of_freedom;
|
||||
BatchPtr bone_degrees_of_freedom_wire;
|
||||
|
||||
BatchPtr quad_wire;
|
||||
BatchPtr quad_solid;
|
||||
BatchPtr plain_axes;
|
||||
@ -172,6 +189,7 @@ class ShaderModule {
|
||||
public:
|
||||
/** Shaders */
|
||||
ShaderPtr anti_aliasing = shader("overlay_antialiasing");
|
||||
ShaderPtr armature_degrees_of_freedom;
|
||||
ShaderPtr background_fill = shader("overlay_background");
|
||||
ShaderPtr background_clip_bound = shader("overlay_clipbound");
|
||||
ShaderPtr curve_edit_points;
|
||||
@ -201,7 +219,15 @@ class ShaderModule {
|
||||
ShaderPtr xray_fade = shader("overlay_xray_fade");
|
||||
|
||||
/** Selectable Shaders */
|
||||
ShaderPtr armature_envelope_fill;
|
||||
ShaderPtr armature_envelope_outline;
|
||||
ShaderPtr armature_shape_outline;
|
||||
ShaderPtr armature_shape_fill;
|
||||
ShaderPtr armature_shape_wire;
|
||||
ShaderPtr armature_sphere_outline;
|
||||
ShaderPtr armature_sphere_fill;
|
||||
ShaderPtr armature_stick;
|
||||
ShaderPtr armature_wire;
|
||||
ShaderPtr depth_mesh;
|
||||
ShaderPtr extra_grid;
|
||||
ShaderPtr extra_shape;
|
||||
@ -446,6 +472,21 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
||||
pass.bind_ssbo("data_buf", &data_buf);
|
||||
pass.draw(shape, data_buf.size());
|
||||
}
|
||||
|
||||
void end_sync(PassSimple::Sub &pass,
|
||||
gpu::Batch *shape,
|
||||
GPUPrimType primitive_type,
|
||||
uint primitive_len)
|
||||
{
|
||||
if (data_buf.is_empty()) {
|
||||
return;
|
||||
}
|
||||
this->select_bind(pass);
|
||||
data_buf.push_update();
|
||||
pass.bind_ssbo("data_buf", &data_buf);
|
||||
pass.draw_expand(
|
||||
shape, primitive_type, primitive_len, data_buf.size(), ResourceHandle(0), uint(0));
|
||||
}
|
||||
};
|
||||
|
||||
struct VertexPrimitiveBuf {
|
||||
|
@ -116,6 +116,15 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
{
|
||||
/** Shaders */
|
||||
|
||||
armature_degrees_of_freedom = shader(
|
||||
"overlay_armature_dof", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "ExtraInstanceData", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID].object_to_world_");
|
||||
info.define("color", "data_buf[gl_InstanceID].color_");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
curve_edit_points = shader(
|
||||
"overlay_edit_particle_point",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
@ -221,12 +230,100 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
|
||||
/** Selectable Shaders */
|
||||
|
||||
armature_envelope_fill = selectable_shader(
|
||||
"overlay_armature_envelope_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "BoneEnvelopeData", "data_buf[]");
|
||||
info.define("headSphere", "data_buf[gl_InstanceID].head_sphere");
|
||||
info.define("tailSphere", "data_buf[gl_InstanceID].tail_sphere");
|
||||
info.define("xAxis", "data_buf[gl_InstanceID].x_axis.xyz");
|
||||
info.define("stateColor", "data_buf[gl_InstanceID].state_color.xyz");
|
||||
info.define("boneColor", "data_buf[gl_InstanceID].bone_color_and_wire_width.xyz");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_envelope_outline = selectable_shader(
|
||||
"overlay_armature_envelope_outline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "BoneEnvelopeData", "data_buf[]");
|
||||
info.define("headSphere", "data_buf[gl_InstanceID].head_sphere");
|
||||
info.define("tailSphere", "data_buf[gl_InstanceID].tail_sphere");
|
||||
info.define("outlineColorSize", "data_buf[gl_InstanceID].bone_color_and_wire_width");
|
||||
info.define("xAxis", "data_buf[gl_InstanceID].x_axis.xyz");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_shape_outline = selectable_shader("overlay_armature_shape_outline_next",
|
||||
[](gpu::shader::ShaderCreateInfo & /*info*/) {});
|
||||
|
||||
armature_shape_fill = selectable_shader(
|
||||
"overlay_armature_shape_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_shape_wire = selectable_shader("overlay_armature_shape_wire_next",
|
||||
[](gpu::shader::ShaderCreateInfo & /*info*/) {});
|
||||
|
||||
armature_sphere_outline = selectable_shader(
|
||||
"overlay_armature_sphere_outline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
armature_sphere_fill = selectable_shader(
|
||||
"overlay_armature_sphere_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_stick = selectable_shader(
|
||||
"overlay_armature_stick", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info("overlay_frag_output",
|
||||
"overlay_armature_common",
|
||||
"draw_resource_handle_new",
|
||||
"draw_modelmat_new",
|
||||
"draw_globals");
|
||||
info.storage_buf(0, Qualifier::READ, "BoneStickData", "data_buf[]");
|
||||
info.define("boneStart", "data_buf[gl_InstanceID].bone_start.xyz");
|
||||
info.define("boneEnd", "data_buf[gl_InstanceID].bone_end.xyz");
|
||||
info.define("wireColor", "data_buf[gl_InstanceID].wire_color");
|
||||
info.define("boneColor", "data_buf[gl_InstanceID].bone_color");
|
||||
info.define("headColor", "data_buf[gl_InstanceID].head_color");
|
||||
info.define("tailColor", "data_buf[gl_InstanceID].tail_color");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_in(1, gpu::shader::Type::INT, "vclass");
|
||||
info.define("flag", "vclass");
|
||||
});
|
||||
|
||||
armature_wire = selectable_shader(
|
||||
"overlay_armature_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info("draw_view",
|
||||
"overlay_frag_output",
|
||||
"draw_resource_handle_new",
|
||||
"draw_modelmat_new",
|
||||
"draw_globals");
|
||||
info.storage_buf(0, Qualifier::READ, "VertexData", "data_buf[]");
|
||||
info.define("pos", "data_buf[gl_VertexID].pos_.xyz");
|
||||
info.define("color", "data_buf[gl_VertexID].color_");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
depth_mesh = selectable_shader("overlay_depth_only", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
|
@ -22,6 +22,13 @@ struct VertShaded {
|
||||
float3 nor;
|
||||
};
|
||||
|
||||
/* TODO(fclem): Might be good to remove for simplicity. */
|
||||
struct VertexTriple {
|
||||
float2 pos0;
|
||||
float2 pos1;
|
||||
float2 pos2;
|
||||
};
|
||||
|
||||
/* Caller gets ownership of the #gpu::VertBuf. */
|
||||
static gpu::VertBuf *vbo_from_vector(const Vector<Vertex> &vector)
|
||||
{
|
||||
@ -52,6 +59,21 @@ static gpu::VertBuf *vbo_from_vector(Vector<VertShaded> &vector)
|
||||
return vbo;
|
||||
}
|
||||
|
||||
static gpu::VertBuf *vbo_from_vector(Vector<VertexTriple> &vector)
|
||||
{
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "pos2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
||||
GPU_vertbuf_data_alloc(*vbo, vector.size());
|
||||
vbo->data<VertexTriple>().copy_from(vector);
|
||||
return vbo;
|
||||
}
|
||||
|
||||
enum VertexClass {
|
||||
VCLASS_NONE = 0,
|
||||
|
||||
@ -91,7 +113,7 @@ static constexpr float bone_box_verts[8][3] = {
|
||||
{-1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
static constexpr std::array<uint, 24> bone_box_wire = {
|
||||
static constexpr std::array<uint, 24> bone_box_wire_lines = {
|
||||
0, 1, 1, 2, 2, 3, 3, 0 |
This function exists on many overlay structs. Wouldn't it be better to have some abstract superclass that defines this interface? That can then also hold the documentation for such functions. It'll also allow the use of the
override
keyword here, so that it's clear that this function is part of some API. Even when no code directly uses that superclass, the code-as-documentation benefits would be quite nice.If that's not an option, document this function. I have no idea whats purpose is, so I also can't really review it.
Well this is not an overlay thing but every piece of engine code inside of DRW module have the same structure.
That proposal about code as documentation is really interesting, but I think it is way out of scope of this PR. I added it as a follow up task to #102179.