WIP: Overlay Next: Shapes and Extras #109059
@ -2426,8 +2426,8 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
|||||||
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
|
({"property": "use_experimental_compositors"}, ("blender/blender/issues/88150", "#88150")),
|
||||||
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
|
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
|
||||||
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
|
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
|
||||||
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/40", "Grease Pencil 3.0")),
|
|
||||||
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
|
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
|
||||||
|
({"property": "use_grease_pencil_version3"}, ("blender/blender/projects/40", "Grease Pencil 3.0")),
|
||||||
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
139
source/blender/draw/engines/overlay/overlay_next_bounds.hh
Normal file
139
source/blender/draw/engines/overlay/overlay_next_bounds.hh
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BKE_mball.h"
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class BoundPassesBase : public OverlayPasses {
|
||||||
|
|
||||||
|
ExtraInstanceBuf cube = extra_buf("cube", shapes.empty_cube);
|
||||||
|
ExtraInstanceBuf sphere = extra_buf("sphere", shapes.empty_sphere);
|
||||||
|
ExtraInstanceBuf cone = extra_buf("cone", shapes.empty_cone);
|
||||||
|
ExtraInstanceBuf cylinder = extra_buf("cylinder", shapes.empty_cylinder);
|
||||||
|
ExtraInstanceBuf capsule_body = extra_buf("capsule_body", shapes.empty_capsule_body);
|
||||||
|
ExtraInstanceBuf capsule_cap = extra_buf("capsule_cap", shapes.empty_capsule_cap);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoundPassesBase(const char *name,
|
||||||
|
SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses(name, selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
void bounds_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state,
|
||||||
|
char boundtype,
|
||||||
|
bool around_origin)
|
||||||
|
{
|
||||||
|
ExtraInstanceData data(ob_ref.object, res.object_wire_color(ob_ref, state));
|
||||||
|
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
|
||||||
|
if (ObjectType(ob->type) == OB_MBALL && !BKE_mball_is_basis(ob)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoundBox *bb = BKE_object_boundbox_get(ob);
|
||||||
|
BoundBox bb_local;
|
||||||
|
if (bb == nullptr) {
|
||||||
|
const float3 min = float3(-1.0f);
|
||||||
|
const float3 max = float3(1.0f);
|
||||||
|
BKE_boundbox_init_from_minmax(&bb_local, min, max);
|
||||||
|
bb = &bb_local;
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 center = float3(0);
|
||||||
|
if (!around_origin) {
|
||||||
|
BKE_boundbox_calc_center_aabb(bb, center);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 size;
|
||||||
|
BKE_boundbox_calc_size_aabb(bb, size);
|
||||||
|
|
||||||
|
if (boundtype == OB_BOUND_BOX) {
|
||||||
Clément Foucault
commented
Use Use `switch`
|
|||||||
|
float4x4 mat = math::from_scale<float4x4>(size);
|
||||||
|
mat.location() = center;
|
||||||
|
cube.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
}
|
||||||
|
else if (boundtype == OB_BOUND_SPHERE) {
|
||||||
|
size = float3(std::max({size.x, size.y, size.z}));
|
||||||
|
float4x4 mat = math::from_scale<float4x4>(size);
|
||||||
|
mat.location() = center;
|
||||||
|
sphere.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
}
|
||||||
|
else if (boundtype == OB_BOUND_CYLINDER) {
|
||||||
|
size.x = size.y = std::max(size.x, size.y);
|
||||||
|
float4x4 mat = math::from_scale<float4x4>(size);
|
||||||
|
mat.location() = center;
|
||||||
|
cylinder.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
}
|
||||||
|
else if (boundtype == OB_BOUND_CONE) {
|
||||||
|
size.x = size.y = std::max(size.x, size.y);
|
||||||
|
float4x4 mat = math::from_scale<float4x4>(size);
|
||||||
|
mat.location() = center;
|
||||||
|
/* Cone batch has base at 0 and is pointing towards +Y. */
|
||||||
|
std::swap(mat[1], mat[2]);
|
||||||
|
mat.location().z -= size.z;
|
||||||
|
cone.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
}
|
||||||
|
else if (boundtype == OB_BOUND_CAPSULE) {
|
||||||
|
size.x = size.y = std::max(size.x, size.y);
|
||||||
|
float4x4 mat = math::from_scale<float4x4>(float3(size.x));
|
||||||
|
mat.location() = center;
|
||||||
|
|
||||||
|
mat.location().z = center.z + std::max(0.0f, size.z - size.x);
|
||||||
|
capsule_cap.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
|
||||||
|
mat.location().z = center.z - std::max(0.0f, size.z - size.x);
|
||||||
|
mat.z_axis() *= -1.0f;
|
||||||
|
capsule_cap.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
|
||||||
|
mat.z_axis().z = std::max(0.0f, (size.z - size.x) * 2.0f);
|
||||||
|
capsule_body.append(data.with_matrix(data.matrix * mat), select_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BoundPasses : public BoundPassesBase {
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoundPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: BoundPassesBase("Bounds", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
const bool from_dupli = ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI);
|
||||||
|
const bool has_bounds = !ELEM(
|
||||||
|
ob->type, OB_LAMP, OB_CAMERA, OB_EMPTY, OB_SPEAKER, OB_LIGHTPROBE);
|
||||||
|
const bool draw_bounds = ob->dt == OB_BOUNDBOX || ob->dtx & OB_DRAWBOUNDOX;
|
||||||
|
if (from_dupli || !has_bounds || !draw_bounds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds_sync(ob_ref, select_id, res, state, ob->boundtype, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Bound = OverlayType<BoundPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
501
source/blender/draw/engines/overlay/overlay_next_camera.hh
Normal file
501
source/blender/draw/engines/overlay/overlay_next_camera.hh
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BKE_camera.h"
|
||||||
|
#include "BKE_movieclip.h"
|
||||||
|
#include "BKE_tracking.h"
|
||||||
|
#include "DEG_depsgraph_query.h"
|
||||||
|
#include "DNA_camera_types.h"
|
||||||
|
#include "ED_view3d.h"
|
||||||
|
#include "overlay_next_empty.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
struct CameraInstanceData : public ExtraInstanceData {
|
||||||
|
CameraInstanceData(const ExtraInstanceData &data) : ExtraInstanceData(data){};
|
||||||
|
CameraInstanceData() : ExtraInstanceData(){};
|
||||||
|
|
||||||
|
/* Pack render data inside matrix and color. */
|
||||||
|
float &volume_start()
|
||||||
|
{
|
||||||
|
return color[2];
|
||||||
|
}
|
||||||
|
float &volume_end()
|
||||||
|
{
|
||||||
|
return color[3];
|
||||||
|
}
|
||||||
|
float &depth()
|
||||||
|
{
|
||||||
|
return color[3];
|
||||||
|
}
|
||||||
|
float &focus()
|
||||||
|
{
|
||||||
|
return color[3];
|
||||||
|
}
|
||||||
|
float &dist_color_id()
|
||||||
|
{
|
||||||
|
return matrix[0][3];
|
||||||
|
}
|
||||||
|
float &corner_x()
|
||||||
|
{
|
||||||
|
return matrix[0][3];
|
||||||
|
}
|
||||||
|
float &corner_y()
|
||||||
|
{
|
||||||
|
return matrix[1][3];
|
||||||
|
}
|
||||||
|
float ¢er_x()
|
||||||
|
{
|
||||||
|
return matrix[2][3];
|
||||||
|
}
|
||||||
|
float &clip_start()
|
||||||
|
{
|
||||||
|
return matrix[2][3];
|
||||||
|
}
|
||||||
|
float &mist_start()
|
||||||
|
{
|
||||||
|
return matrix[2][3];
|
||||||
|
}
|
||||||
|
float ¢er_y()
|
||||||
|
{
|
||||||
|
return matrix[3][3];
|
||||||
|
}
|
||||||
|
float &clip_end()
|
||||||
|
{
|
||||||
|
return matrix[3][3];
|
||||||
|
}
|
||||||
|
float &mist_end()
|
||||||
|
{
|
||||||
|
return matrix[3][3];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CameraPasses : public EmptyPassesBase {
|
||||||
|
|
||||||
|
ExtraInstanceBuf volume = extra_buf("camera_volume", shapes.camera_volume, BLEND_CULL_BACK);
|
||||||
|
ExtraInstanceBuf volume_wire = extra_buf(
|
||||||
|
"camera_volume_wire", shapes.camera_volume_wire, BLEND_CULL_BACK);
|
||||||
|
ExtraInstanceBuf frame = extra_buf("camera_frame", shapes.camera_frame);
|
||||||
|
ExtraInstanceBuf distances = extra_buf("camera_distances", shapes.camera_distances);
|
||||||
|
ExtraInstanceBuf tria_wire = extra_buf("camera_tria_wire", shapes.camera_tria_wire);
|
||||||
|
ExtraInstanceBuf tria = extra_buf("camera_tria", shapes.camera_tria);
|
||||||
|
LineInstanceBuf path = line_buf("camera_path", theme_colors.color_camera_path);
|
||||||
|
|
||||||
|
ExtraInstanceBuf sphere_solid = extra_buf("sphere_solid", shapes.sphere_solid);
|
||||||
|
LineInstanceBuf relation_line = line_buf("relation_line", theme_colors.color_wire);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CameraPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: EmptyPassesBase("Cameras", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
void view3d_reconstruction_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state,
|
||||||
|
CameraInstanceData data)
|
||||||
|
{
|
||||||
|
const Scene *scene = state.scene;
|
||||||
|
const View3D *v3d = state.v3d;
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
|
||||||
|
const bool is_select = state.selection_type != SelectionType::DISABLED;
|
||||||
|
|
||||||
|
MovieClip *clip = BKE_object_movieclip_get((Scene *)scene, ob, false);
|
||||||
|
if (clip == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_solid_bundle = (v3d->bundle_drawtype == OB_EMPTY_SPHERE) &&
|
||||||
|
((v3d->shading.type != OB_SOLID) || !XRAY_FLAG_ENABLED(v3d));
|
||||||
|
|
||||||
|
MovieTracking *tracking = &clip->tracking;
|
||||||
|
/* Index must start in 1, to mimic BKE_tracking_track_get_for_selection_index. */
|
||||||
|
int track_index = 1;
|
||||||
|
|
||||||
|
float4x4 camera_mat;
|
||||||
|
BKE_tracking_get_camera_object_matrix(ob, camera_mat.ptr());
|
||||||
|
|
||||||
|
LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
|
||||||
|
float4x4 tracking_object_mat;
|
||||||
|
|
||||||
|
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
||||||
|
tracking_object_mat = camera_mat;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const int framenr = BKE_movieclip_remap_scene_to_clip_frame(
|
||||||
|
clip, DEG_get_ctime(state.depsgraph));
|
||||||
|
|
||||||
|
float4x4 object_mat;
|
||||||
|
BKE_tracking_camera_get_reconstructed_interpolate(
|
||||||
|
tracking, tracking_object, framenr, object_mat.ptr());
|
||||||
|
|
||||||
|
tracking_object_mat = data.matrix * math::invert(object_mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
||||||
|
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool is_selected = TRACK_SELECTED(track);
|
||||||
|
|
||||||
|
CameraInstanceData bundle_data = data.with_size(v3d->bundle_size);
|
||||||
|
bundle_data.matrix = math::translate(bundle_data.matrix, float3(track->bundle_pos));
|
||||||
|
|
||||||
|
if (track->flag & TRACK_CUSTOMCOLOR) {
|
||||||
|
/* Hardcoded srgb transform. */
|
||||||
|
/* TODO: change the actual DNA color to be linear. */
|
||||||
|
srgb_to_linearrgb_v3_v3(bundle_data.color, track->color);
|
||||||
|
}
|
||||||
|
else if (is_solid_bundle) {
|
||||||
|
bundle_data.color = res.theme_settings.color_bundle_solid;
|
||||||
|
}
|
||||||
|
else if (!is_selected) {
|
||||||
|
bundle_data.color = res.theme_settings.color_wire;
|
||||||
|
}
|
||||||
|
|
||||||
|
select::ID track_select_id = select_id;
|
||||||
|
if (is_select) {
|
||||||
|
track_select_id = res.select_id(ob_ref, track_index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_solid_bundle) {
|
||||||
|
if (is_selected) {
|
||||||
|
empty_buf(v3d->bundle_drawtype)
|
||||||
|
.append(bundle_data.with_color(data.color), track_select_id);
|
||||||
|
}
|
||||||
|
sphere_solid.append(bundle_data, track_select_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
empty_buf(v3d->bundle_drawtype).append(bundle_data, track_select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((v3d->flag2 & V3D_SHOW_BUNDLENAME) && !is_select) {
|
||||||
|
#if 0
|
||||||
|
/* TODO(Miguel Pozo): */
|
||||||
|
uchar text_color_selected[4], text_color_unselected[4];
|
||||||
|
/* Color Management: Exception here as texts are drawn in sRGB space directly. */
|
||||||
|
UI_GetThemeColor4ubv(TH_SELECT, text_color_selected);
|
||||||
|
UI_GetThemeColor4ubv(TH_TEXT, text_color_unselected);
|
||||||
|
|
||||||
|
DRWTextStore *dt = DRW_text_cache_ensure();
|
||||||
|
|
||||||
|
DRW_text_cache_add(dt,
|
||||||
|
bundle_mat[3],
|
||||||
|
track->name,
|
||||||
|
strlen(track->name),
|
||||||
|
10,
|
||||||
|
0,
|
||||||
|
DRW_TEXT_CACHE_GLOBALSPACE | DRW_TEXT_CACHE_STRING_PTR,
|
||||||
|
is_selected ? text_color_selected : text_color_unselected);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((v3d->flag2 & V3D_SHOW_CAMERAPATH) && (tracking_object->flag & TRACKING_OBJECT_CAMERA) &&
|
||||||
|
!is_select)
|
||||||
|
{
|
||||||
|
const MovieTrackingReconstruction *reconstruction = &tracking_object->reconstruction;
|
||||||
|
|
||||||
|
if (reconstruction->camnr) {
|
||||||
|
const MovieReconstructedCamera *camera = reconstruction->cameras;
|
||||||
|
float3 v0 = float3(0);
|
||||||
|
float3 v1 = float3(0);
|
||||||
|
for (int i = 0; i < reconstruction->camnr; i++, camera++) {
|
||||||
|
v0 = v1;
|
||||||
|
v1 = math::transform_point(camera_mat, float3(camera->mat[3]));
|
||||||
|
if (i > 0) {
|
||||||
|
path.append({v0, v1}, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float offaxis_shiftx_get(const Scene *scene, Object *ob, CameraInstanceData data, bool right_eye)
|
||||||
|
{
|
||||||
|
::Camera *cam = static_cast<::Camera *>(ob->data);
|
||||||
|
if (cam->stereo.convergence_mode != CAM_S3D_OFFAXIS) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||||
|
const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, viewnames[right_eye]);
|
||||||
|
const float delta_shiftx = shiftx - cam->shiftx;
|
||||||
|
const float width = data.corner_x() * 2.0f;
|
||||||
|
return delta_shiftx * width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the stereo 3d support elements (cameras, plane, volume).
|
||||||
|
* They are only visible when not looking through the camera:
|
||||||
|
*/
|
||||||
|
void stereoscopy_extra_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
const State &state,
|
||||||
|
CameraInstanceData data)
|
||||||
|
{
|
||||||
|
CameraInstanceData stereodata = data;
|
||||||
|
const View3D *v3d = state.v3d;
|
||||||
|
const Scene *scene = state.scene;
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
::Camera *cam = static_cast<::Camera *>(ob->data);
|
||||||
|
const bool is_select = state.selection_type != SelectionType::DISABLED;
|
||||||
|
const char *viewnames[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
|
||||||
|
|
||||||
|
const bool is_stereo3d_cameras = (v3d->stereo3d_flag & V3D_S3D_DISPCAMERAS) != 0;
|
||||||
|
const bool is_stereo3d_plane = (v3d->stereo3d_flag & V3D_S3D_DISPPLANE) != 0;
|
||||||
|
const bool is_stereo3d_volume = (v3d->stereo3d_flag & V3D_S3D_DISPVOLUME) != 0;
|
||||||
|
|
||||||
|
if (!is_stereo3d_cameras) {
|
||||||
|
/* Draw single camera. */
|
||||||
|
frame.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int eye : IndexRange(2)) {
|
||||||
|
ob = BKE_camera_multiview_render(scene, ob, viewnames[eye]);
|
||||||
|
BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[eye], stereodata.matrix.ptr());
|
||||||
|
|
||||||
|
stereodata.corner_x() = data.corner_x();
|
||||||
|
stereodata.corner_y() = data.corner_y();
|
||||||
|
stereodata.center_x() = data.center_x() + offaxis_shiftx_get(scene, ob, data, eye);
|
||||||
|
stereodata.center_y() = data.center_y();
|
||||||
|
stereodata.depth() = data.depth();
|
||||||
|
|
||||||
|
if (is_stereo3d_cameras) {
|
||||||
|
frame.append(stereodata, select_id);
|
||||||
|
/* Connecting line between cameras. */
|
||||||
|
relation_line.append({stereodata.matrix.location(), data.matrix.location()}, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_stereo3d_volume && !is_select) {
|
||||||
|
float r = (eye == 1) ? 2.0f : 1.0f;
|
||||||
|
|
||||||
|
stereodata.volume_start() = -cam->clip_start;
|
||||||
|
stereodata.volume_end() = -cam->clip_end;
|
||||||
|
/* Encode eye + intensity and alpha (see shader) */
|
||||||
|
// stereodata.color.xy() = {r + 0.15f, 1.0f};
|
||||||
|
copy_v2_v2(stereodata.color, float2(r + 0.15f, 1.0f));
|
||||||
|
frame.append(stereodata, select_id);
|
||||||
|
|
||||||
|
if (v3d->stereo3d_volume_alpha > 0.0f) {
|
||||||
|
/* Encode eye + intensity and alpha (see shader) */
|
||||||
|
// stereodata.color.xy() = {r + 0.999f, v3d->stereo3d_volume_alpha};
|
||||||
|
copy_v2_v2(stereodata.color, float2(r + 0.999f, v3d->stereo3d_convergence_alpha));
|
||||||
|
|
||||||
|
volume.append(stereodata, select_id);
|
||||||
|
}
|
||||||
|
/* restore */
|
||||||
|
stereodata.color = data.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_stereo3d_plane && !is_select) {
|
||||||
|
if (cam->stereo.convergence_mode == CAM_S3D_TOE) {
|
||||||
|
/* There is no real convergence plane but we highlight the center
|
||||||
|
* point where the views are pointing at. */
|
||||||
|
// zero_v3(stereodata.matrix[0]); /* We reconstruct from Z and Y */
|
||||||
|
// zero_v3(stereodata.matrix[1]); /* Y doesn't change */
|
||||||
|
stereodata.matrix.z_axis() = float3(0.0f);
|
||||||
|
stereodata.matrix.location() = float3(0.0f);
|
||||||
|
for (int i : IndexRange(2)) {
|
||||||
|
float4x4 mat;
|
||||||
|
/* Need normalized version here. */
|
||||||
|
BKE_camera_multiview_model_matrix(&scene->r, ob, viewnames[i], mat.ptr());
|
||||||
|
stereodata.matrix.z_axis() += mat.z_axis();
|
||||||
|
stereodata.matrix.location() += mat.location() * 0.5f;
|
||||||
|
}
|
||||||
|
stereodata.matrix.z_axis() = math::normalize(stereodata.matrix.z_axis());
|
||||||
|
stereodata.matrix.x_axis() = math::cross(stereodata.matrix.y_axis(),
|
||||||
|
stereodata.matrix.z_axis());
|
||||||
|
}
|
||||||
|
else if (cam->stereo.convergence_mode == CAM_S3D_PARALLEL) {
|
||||||
|
/* Show plane at the given distance between the views even if it makes no sense. */
|
||||||
|
stereodata.matrix.location() = float3(0.0f);
|
||||||
|
for (int i : IndexRange(2)) {
|
||||||
|
float4x4 mat;
|
||||||
|
BKE_camera_multiview_model_matrix_scaled(&scene->r, ob, viewnames[i], mat.ptr());
|
||||||
|
stereodata.matrix.location() += mat.location() * 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cam->stereo.convergence_mode == CAM_S3D_OFFAXIS) {
|
||||||
|
/* Nothing to do. Everything is already setup. */
|
||||||
|
}
|
||||||
|
stereodata.volume_start() = -cam->stereo.convergence_distance;
|
||||||
|
stereodata.volume_end() = -cam->stereo.convergence_distance;
|
||||||
|
/* Encode eye + intensity and alpha (see shader) */
|
||||||
|
// stereodata.color.xy() = {0.1f, 1.0f};
|
||||||
|
copy_v2_v2(stereodata.color, float2(0.1f, 1.0f));
|
||||||
|
frame.append(stereodata, select_id);
|
||||||
|
|
||||||
|
if (v3d->stereo3d_convergence_alpha > 0.0f) {
|
||||||
|
/* Encode eye + intensity and alpha (see shader) */
|
||||||
|
// stereodata.color.xy() = {0.0f, v3d->stereo3d_convergence_alpha};
|
||||||
|
copy_v2_v2(stereodata.color, float2(0.0f, v3d->stereo3d_convergence_alpha));
|
||||||
|
volume.append(stereodata, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
BLI_assert(ob->type == OB_CAMERA);
|
||||||
|
|
||||||
|
CameraInstanceData data(ExtraInstanceData(ob, res.object_wire_color(ob_ref, state)));
|
||||||
|
|
||||||
|
const View3D *v3d = state.v3d;
|
||||||
|
const Scene *scene = state.scene;
|
||||||
|
const RegionView3D *rv3d = state.rv3d;
|
||||||
|
|
||||||
|
::Camera *cam = static_cast<::Camera *>(ob->data);
|
||||||
|
Object *camera_object = DEG_get_evaluated_object(state.depsgraph, v3d->camera);
|
||||||
|
const bool is_select = state.selection_type != SelectionType::DISABLED;
|
||||||
|
const bool is_active = (ob == camera_object);
|
||||||
|
const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
|
||||||
Clément Foucault
commented
is_camera_view is_camera_view
|
|||||||
|
|
||||||
|
const bool is_multiview = (scene->r.scemode & R_MULTIVIEW) != 0;
|
||||||
|
const bool is_stereo3d_view = (scene->r.views_format == SCE_VIEWS_FORMAT_STEREO_3D);
|
||||||
|
const bool is_stereo3d_display_extra = is_active && is_multiview && (!look_through) &&
|
||||||
|
((v3d->stereo3d_flag) != 0);
|
||||||
|
const bool is_selection_camera_stereo = is_select && look_through && is_multiview &&
|
||||||
|
is_stereo3d_view;
|
||||||
|
|
||||||
|
float3 scale = math::to_scale(data.matrix);
|
||||||
|
/* BKE_camera_multiview_model_matrix already accounts for scale, don't do it here. */
|
||||||
|
if (is_selection_camera_stereo) {
|
||||||
|
scale = float3(1.0f);
|
||||||
|
}
|
||||||
|
else if (ELEM(0.0f, scale.x, scale.y, scale.z)) {
|
||||||
|
/* Avoid division by 0. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.matrix.view<3, 3>() = math::normalize(data.matrix.view<3, 3>());
|
||||||
|
|
||||||
|
float3 scale_inv = 1.0f / scale;
|
||||||
|
float4x3 vecs;
|
||||||
|
float2 aspect_ratio;
|
||||||
|
float2 shift;
|
||||||
|
float drawsize;
|
||||||
|
BKE_camera_view_frame_ex(scene,
|
||||||
|
cam,
|
||||||
|
cam->drawsize,
|
||||||
|
look_through,
|
||||||
|
scale_inv,
|
||||||
|
aspect_ratio,
|
||||||
|
shift,
|
||||||
|
&drawsize,
|
||||||
|
vecs.ptr());
|
||||||
|
|
||||||
|
/* Apply scale to simplify the rest of the drawing. */
|
||||||
|
for (int i : IndexRange(4)) {
|
||||||
|
vecs[i] *= scale;
|
||||||
|
/* Project to z=-1 plane. Makes positioning / scaling easier. (see shader) */
|
||||||
|
// vecs[i].xy() *= 1.0f / std::abs(vecs[i].z);
|
||||||
|
mul_v2_fl(vecs[i], 1.0f / std::abs(vecs[i].z));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frame coords */
|
||||||
|
float2 center = (vecs[0].xy() + vecs[2].xy()) / 2.0f;
|
||||||
|
float2 corner = vecs[0].xy() - center;
|
||||||
|
|
||||||
|
data.corner_x() = corner.x;
|
||||||
|
data.corner_y() = corner.y;
|
||||||
|
data.center_x() = center.x;
|
||||||
|
data.center_y() = center.y;
|
||||||
|
data.depth() = vecs[0].z;
|
||||||
|
|
||||||
|
if (look_through) {
|
||||||
|
/* TODO(Miguel Pozo) */
|
||||||
|
if (!DRW_state_is_image_render()) {
|
||||||
|
/* Only draw the frame. */
|
||||||
|
if (is_multiview) {
|
||||||
|
float4x4 mat;
|
||||||
|
const bool is_right = v3d->multiview_eye == STEREO_RIGHT_ID;
|
||||||
|
const char *view_name = is_right ? STEREO_RIGHT_NAME : STEREO_LEFT_NAME;
|
||||||
|
BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat.ptr());
|
||||||
|
data.center_x() += offaxis_shiftx_get(scene, ob, data, is_right);
|
||||||
|
for (int i : IndexRange(4)) {
|
||||||
|
/* Partial copy to avoid overriding packed data. */
|
||||||
|
// data.matrix[i].xyz() = mat[i].xyz();
|
||||||
|
copy_v3_v3(data.matrix[i], mat[i].xyz());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.depth() *= -1.0f; /* Hides the back of the camera wires (see shader). */
|
||||||
|
frame.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Stereo cameras, volumes, plane drawing. */
|
||||||
|
if (is_stereo3d_display_extra) {
|
||||||
|
stereoscopy_extra_sync(ob_ref, select_id, state, data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
frame.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!look_through) {
|
||||||
|
/* Triangle. */
|
||||||
|
float tria_size = 0.7f * drawsize / std::abs(data.depth());
|
||||||
|
float tria_margin = 0.1f * drawsize / std::abs(data.depth());
|
||||||
|
data.center_x() = center.x;
|
||||||
|
data.center_y() = center.y + data.corner_y() + tria_margin + tria_size;
|
||||||
|
data.corner_x() = data.corner_y() = -tria_size;
|
||||||
|
ExtraInstanceBuf &buf = is_active ? tria : tria_wire;
|
||||||
|
buf.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cam->flag & CAM_SHOWLIMITS) {
|
||||||
|
/* Scale focus point. */
|
||||||
|
data.matrix.x_axis() *= cam->drawsize;
|
||||||
|
data.matrix.y_axis() *= cam->drawsize;
|
||||||
|
|
||||||
|
data.dist_color_id() = (is_active) ? 3 : 2;
|
||||||
|
data.focus() = -BKE_camera_object_dof_distance(ob);
|
||||||
|
data.clip_start() = cam->clip_start;
|
||||||
|
data.clip_end() = cam->clip_end;
|
||||||
|
distances.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cam->flag & CAM_SHOWMIST) {
|
||||||
|
World *world = scene->world;
|
||||||
|
if (world) {
|
||||||
|
data.dist_color_id() = (is_active) ? 1 : 0;
|
||||||
|
data.focus() = 1.0f; /* Disable */
|
||||||
|
data.mist_start() = world->miststa;
|
||||||
|
data.mist_end() = world->miststa + world->mistdist;
|
||||||
|
distances.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Motion Tracking. */
|
||||||
|
if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
|
||||||
|
view3d_reconstruction_sync(ob_ref, select_id, res, state, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* TODO(Miguel Pozo): */
|
||||||
|
/* Background images. */
|
||||||
|
if (look_through && (cam->flag & CAM_SHOW_BG_IMAGE) && !BLI_listbase_is_empty(&cam->bg_images))
|
||||||
|
{
|
||||||
|
OVERLAY_image_camera_cache_populate(vedata, ob);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Camera = OverlayType<CameraPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -0,0 +1,62 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_bounds.hh"
|
||||||
|
|
||||||
|
#include "DNA_rigidbody_types.h"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class CollisionPasses : public BoundPassesBase {
|
||||||
Clément Foucault
commented
I would just merge that with the I would just merge that with the `BoundPasses` and avoid the base class. This would avoid splitting the drawing buffers.
|
|||||||
|
|
||||||
|
public:
|
||||||
|
CollisionPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: BoundPassesBase("Collisions", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
const bool from_dupli = ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI);
|
||||||
|
if (from_dupli || ob->rigidbody_object == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bound_type;
|
||||||
|
switch (ob->rigidbody_object->shape) {
|
||||||
|
case RB_SHAPE_BOX:
|
||||||
|
bound_type = OB_BOUND_BOX;
|
||||||
|
break;
|
||||||
|
case RB_SHAPE_SPHERE:
|
||||||
|
bound_type = OB_BOUND_SPHERE;
|
||||||
|
break;
|
||||||
|
case RB_SHAPE_CONE:
|
||||||
|
bound_type = OB_BOUND_CONE;
|
||||||
|
break;
|
||||||
|
case RB_SHAPE_CYLINDER:
|
||||||
|
bound_type = OB_BOUND_CYLINDER;
|
||||||
|
break;
|
||||||
|
case RB_SHAPE_CAPSULE:
|
||||||
|
bound_type = OB_BOUND_CAPSULE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds_sync(ob_ref, select_id, res, state, bound_type, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Collision = OverlayType<CollisionPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -9,121 +9,80 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "overlay_next_private.hh"
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
namespace blender::draw::overlay {
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
class Empties {
|
class EmptyPassesBase : public OverlayPasses {
|
||||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
|
||||||
|
|
||||||
private:
|
ExtraInstanceBuf plain_axes = extra_buf("plain_axes", shapes.plain_axes);
|
||||||
const SelectionType selection_type_;
|
ExtraInstanceBuf single_arrow = extra_buf("single_arrow", shapes.single_arrow);
|
||||||
|
ExtraInstanceBuf arrows = extra_buf("arrows", shapes.arrows);
|
||||||
PassSimple empty_ps_ = {"Empties"};
|
ExtraInstanceBuf image = extra_buf("image", shapes.quad_wire);
|
||||||
PassSimple empty_in_front_ps_ = {"Empties_In_front"};
|
ExtraInstanceBuf circle = extra_buf("circle", shapes.circle);
|
||||||
|
ExtraInstanceBuf cube = extra_buf("cube", shapes.empty_cube);
|
||||||
struct CallBuffers {
|
ExtraInstanceBuf sphere = extra_buf("sphere", shapes.empty_sphere);
|
||||||
const SelectionType selection_type_;
|
ExtraInstanceBuf cone = extra_buf("cone", shapes.empty_cone);
|
||||||
EmptyInstanceBuf plain_axes_buf = {selection_type_, "plain_axes_buf"};
|
|
||||||
EmptyInstanceBuf single_arrow_buf = {selection_type_, "single_arrow_buf"};
|
|
||||||
EmptyInstanceBuf cube_buf = {selection_type_, "cube_buf"};
|
|
||||||
EmptyInstanceBuf circle_buf = {selection_type_, "circle_buf"};
|
|
||||||
EmptyInstanceBuf sphere_buf = {selection_type_, "sphere_buf"};
|
|
||||||
EmptyInstanceBuf cone_buf = {selection_type_, "cone_buf"};
|
|
||||||
EmptyInstanceBuf arrows_buf = {selection_type_, "arrows_buf"};
|
|
||||||
EmptyInstanceBuf image_buf = {selection_type_, "image_buf"};
|
|
||||||
} call_buffers_[2] = {{selection_type_}, {selection_type_}};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Empties(const SelectionType selection_type) : selection_type_(selection_type){};
|
EmptyPassesBase(const char *name,
|
||||||
|
SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses(name, selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
void begin_sync()
|
protected:
|
||||||
|
ExtraInstanceBuf &empty_buf(int empty_drawtype)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 2; i++) {
|
switch (empty_drawtype) {
|
||||||
call_buffers_[i].plain_axes_buf.clear();
|
|
||||||
call_buffers_[i].single_arrow_buf.clear();
|
|
||||||
call_buffers_[i].cube_buf.clear();
|
|
||||||
call_buffers_[i].circle_buf.clear();
|
|
||||||
call_buffers_[i].sphere_buf.clear();
|
|
||||||
call_buffers_[i].cone_buf.clear();
|
|
||||||
call_buffers_[i].arrows_buf.clear();
|
|
||||||
call_buffers_[i].image_buf.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
|
||||||
{
|
|
||||||
CallBuffers &call_bufs = call_buffers_[int((ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0)];
|
|
||||||
|
|
||||||
float4 color = res.object_wire_color(ob_ref, state);
|
|
||||||
ExtraInstanceData data(
|
|
||||||
float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize);
|
|
||||||
|
|
||||||
const select::ID select_id = res.select_id(ob_ref);
|
|
||||||
|
|
||||||
switch (ob_ref.object->empty_drawtype) {
|
|
||||||
case OB_PLAINAXES:
|
case OB_PLAINAXES:
|
||||||
call_bufs.plain_axes_buf.append(data, select_id);
|
return plain_axes;
|
||||||
break;
|
|
||||||
case OB_SINGLE_ARROW:
|
case OB_SINGLE_ARROW:
|
||||||
call_bufs.single_arrow_buf.append(data, select_id);
|
return single_arrow;
|
||||||
break;
|
|
||||||
case OB_CUBE:
|
case OB_CUBE:
|
||||||
call_bufs.cube_buf.append(data, select_id);
|
return cube;
|
||||||
break;
|
|
||||||
case OB_CIRCLE:
|
case OB_CIRCLE:
|
||||||
call_bufs.circle_buf.append(data, select_id);
|
return circle;
|
||||||
break;
|
|
||||||
case OB_EMPTY_SPHERE:
|
case OB_EMPTY_SPHERE:
|
||||||
call_bufs.sphere_buf.append(data, select_id);
|
return sphere;
|
||||||
break;
|
|
||||||
case OB_EMPTY_CONE:
|
case OB_EMPTY_CONE:
|
||||||
call_bufs.cone_buf.append(data, select_id);
|
return cone;
|
||||||
break;
|
|
||||||
case OB_ARROWS:
|
case OB_ARROWS:
|
||||||
call_bufs.arrows_buf.append(data, select_id);
|
return arrows;
|
||||||
break;
|
|
||||||
case OB_EMPTY_IMAGE:
|
case OB_EMPTY_IMAGE:
|
||||||
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
|
return image;
|
||||||
call_bufs.image_buf.append(data, select_id);
|
default:
|
||||||
break;
|
BLI_assert_unreachable();
|
||||||
|
return plain_axes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
|
|
||||||
{
|
|
||||||
auto init_pass = [&](PassSimple &pass, CallBuffers &call_bufs) {
|
|
||||||
pass.init();
|
|
||||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
|
||||||
state.clipping_state);
|
|
||||||
pass.shader_set(res.shaders.extra_shape.get());
|
|
||||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
|
||||||
res.select_bind(pass);
|
|
||||||
|
|
||||||
call_bufs.plain_axes_buf.end_sync(pass, shapes.plain_axes.get());
|
|
||||||
call_bufs.single_arrow_buf.end_sync(pass, shapes.single_arrow.get());
|
|
||||||
call_bufs.cube_buf.end_sync(pass, shapes.cube.get());
|
|
||||||
call_bufs.circle_buf.end_sync(pass, shapes.circle.get());
|
|
||||||
call_bufs.sphere_buf.end_sync(pass, shapes.empty_sphere.get());
|
|
||||||
call_bufs.cone_buf.end_sync(pass, shapes.empty_cone.get());
|
|
||||||
call_bufs.arrows_buf.end_sync(pass, shapes.arrows.get());
|
|
||||||
call_bufs.image_buf.end_sync(pass, shapes.quad_wire.get());
|
|
||||||
};
|
|
||||||
|
|
||||||
init_pass(empty_ps_, call_buffers_[0]);
|
|
||||||
init_pass(empty_in_front_ps_, call_buffers_[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw(Resources &res, Manager &manager, View &view)
|
|
||||||
{
|
|
||||||
GPU_framebuffer_bind(res.overlay_line_fb);
|
|
||||||
manager.submit(empty_ps_, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_in_front(Resources &res, Manager &manager, View &view)
|
|
||||||
{
|
|
||||||
GPU_framebuffer_bind(res.overlay_line_in_front_fb);
|
|
||||||
manager.submit(empty_in_front_ps_, view);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EmptyPasses : public EmptyPassesBase {
|
||||||
|
|
||||||
|
public:
|
||||||
|
EmptyPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: EmptyPassesBase("Empties", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
BLI_assert(ob->type == OB_EMPTY);
|
||||||
|
|
||||||
|
ExtraInstanceData data(ob, res.object_wire_color(ob_ref, state));
|
||||||
|
empty_buf(ob->empty_drawtype).append(data, select_id);
|
||||||
|
if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
|
||||||
|
/** TODO:
|
||||||
|
* See OVERLAY_image_empty_cache_populate() for the image. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Empty = OverlayType<EmptyPasses>;
|
||||||
|
|
||||||
} // namespace blender::draw::overlay
|
} // namespace blender::draw::overlay
|
||||||
|
133
source/blender/draw/engines/overlay/overlay_next_force_field.hh
Normal file
133
source/blender/draw/engines/overlay/overlay_next_force_field.hh
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BKE_anim_path.h"
|
||||||
|
#include "DNA_curve_types.h"
|
||||||
|
#include "DNA_object_force_types.h"
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class ForceFieldPasses : public OverlayPasses {
|
||||||
|
|
||||||
|
ExtraInstanceBuf field_wind = extra_buf("field_wind", shapes.field_wind);
|
||||||
|
ExtraInstanceBuf field_force = extra_buf("field_force", shapes.field_force);
|
||||||
|
ExtraInstanceBuf field_vortex = extra_buf("field_vortex", shapes.field_vortex);
|
||||||
|
ExtraInstanceBuf field_curve = extra_buf("field_curve", shapes.field_curve);
|
||||||
|
ExtraInstanceBuf field_tube_limit = extra_buf("field_tube_limit", shapes.field_tube_limit);
|
||||||
|
ExtraInstanceBuf field_cone_limit = extra_buf("field_cone_limit", shapes.field_cone_limit);
|
||||||
|
ExtraInstanceBuf field_sphere_limit = extra_buf("field_sphere_limit", shapes.field_sphere_limit);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ForceFieldPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Force Fields", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
if (!ob->pd || !ob->pd->forcefield) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraInstanceData data(ob_ref.object, res.object_wire_color(ob_ref, state));
|
||||||
|
|
||||||
|
/* Pack render data into object matrix. */
|
||||||
|
float &size_x = data.matrix[0].w;
|
||||||
|
float &size_y = data.matrix[1].w;
|
||||||
|
float &size_z = data.matrix[2].w;
|
||||||
|
|
||||||
|
PartDeflect *pd = ob->pd;
|
||||||
|
Curve *cu = (ob->type == OB_CURVES_LEGACY) ? static_cast<Curve *>(ob->data) : nullptr;
|
||||||
|
|
||||||
|
data.color = res.object_background_blend_color(ob_ref, state);
|
||||||
|
size_x = size_y = size_z = ob->empty_drawsize;
|
||||||
|
|
||||||
|
switch (pd->forcefield) {
|
||||||
|
case PFIELD_FORCE:
|
||||||
|
field_force.append(data, select_id);
|
||||||
|
break;
|
||||||
|
case PFIELD_WIND:
|
||||||
|
size_z = pd->f_strength;
|
||||||
|
field_wind.append(data, select_id);
|
||||||
|
break;
|
||||||
|
case PFIELD_VORTEX:
|
||||||
|
size_y = (pd->f_strength < 0.0f) ? -size_y : size_y;
|
||||||
|
field_vortex.append(data, select_id);
|
||||||
|
break;
|
||||||
|
case PFIELD_GUIDE:
|
||||||
|
if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->anim_path_accum_length) {
|
||||||
|
float4x4 matrix = data.matrix;
|
||||||
|
float4 position;
|
||||||
|
|
||||||
|
size_x = size_y = size_z = pd->f_strength;
|
||||||
|
|
||||||
|
BKE_where_on_path(ob, 0.0f, position, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
matrix.location() = data.matrix.location() + position.xyz();
|
||||||
|
field_curve.append(data.with_matrix(matrix), select_id);
|
||||||
|
|
||||||
|
BKE_where_on_path(ob, 1.0f, position, nullptr, nullptr, nullptr, nullptr);
|
||||||
|
matrix.location() = data.matrix.location() + position.xyz();
|
||||||
|
field_sphere_limit.append(data.with_matrix(matrix), select_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pd->falloff == PFIELD_FALL_TUBE) {
|
||||||
|
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
|
||||||
|
size_z = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
|
||||||
|
size_x = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
|
||||||
|
size_y = size_x;
|
||||||
|
field_tube_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
|
||||||
|
size_z = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
|
||||||
|
size_x = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
|
||||||
|
size_y = size_x;
|
||||||
|
field_tube_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pd->falloff == PFIELD_FALL_CONE) {
|
||||||
|
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
|
||||||
|
float radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
|
||||||
|
float distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
|
||||||
|
size_x = distance * math::sin(radius);
|
||||||
|
size_z = distance * math::cos(radius);
|
||||||
|
size_y = size_x;
|
||||||
|
field_cone_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
|
||||||
|
float radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
|
||||||
|
float distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
|
||||||
|
size_x = distance * math::sin(radius);
|
||||||
|
size_z = distance * math::cos(radius);
|
||||||
|
size_y = size_x;
|
||||||
|
field_cone_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pd->falloff == PFIELD_FALL_SPHERE) {
|
||||||
|
if (pd->flag & PFIELD_USEMAX) {
|
||||||
|
size_x = size_y = size_z = pd->maxdist;
|
||||||
|
field_sphere_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
if (pd->flag & PFIELD_USEMIN) {
|
||||||
|
size_x = size_y = size_z = pd->mindist;
|
||||||
|
field_sphere_limit.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ForceField = OverlayType<ForceFieldPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -12,6 +12,14 @@
|
|||||||
|
|
||||||
#include "overlay_next_instance.hh"
|
#include "overlay_next_instance.hh"
|
||||||
|
|
||||||
|
#include "overlay_next_bounds.hh"
|
||||||
|
#include "overlay_next_camera.hh"
|
||||||
|
#include "overlay_next_collision.hh"
|
||||||
|
#include "overlay_next_empty.hh"
|
||||||
|
#include "overlay_next_force_field.hh"
|
||||||
|
#include "overlay_next_light.hh"
|
||||||
|
#include "overlay_next_light_probe.hh"
|
||||||
|
|
||||||
namespace blender::draw::overlay {
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
void Instance::init()
|
void Instance::init()
|
||||||
@ -22,6 +30,7 @@ void Instance::init()
|
|||||||
BKE_view_layer_synced_ensure(ctx->scene, ctx->view_layer);
|
BKE_view_layer_synced_ensure(ctx->scene, ctx->view_layer);
|
||||||
|
|
||||||
state.depsgraph = ctx->depsgraph;
|
state.depsgraph = ctx->depsgraph;
|
||||||
|
state.manager = DRW_manager_get();
|
||||||
state.view_layer = ctx->view_layer;
|
state.view_layer = ctx->view_layer;
|
||||||
state.scene = ctx->scene;
|
state.scene = ctx->scene;
|
||||||
state.v3d = ctx->v3d;
|
state.v3d = ctx->v3d;
|
||||||
@ -30,6 +39,7 @@ void Instance::init()
|
|||||||
state.object_mode = ctx->object_mode;
|
state.object_mode = ctx->object_mode;
|
||||||
|
|
||||||
state.pixelsize = U.pixelsize;
|
state.pixelsize = U.pixelsize;
|
||||||
|
state.selection_type = selection_type_;
|
||||||
state.ctx_mode = CTX_data_mode_enum_ex(ctx->object_edit, ctx->obact, ctx->object_mode);
|
state.ctx_mode = CTX_data_mode_enum_ex(ctx->object_edit, ctx->obact, ctx->object_mode);
|
||||||
state.space_type = state.v3d != nullptr ? SPACE_VIEW3D : eSpace_Type(ctx->space_data->spacetype);
|
state.space_type = state.v3d != nullptr ? SPACE_VIEW3D : eSpace_Type(ctx->space_data->spacetype);
|
||||||
if (state.v3d != nullptr) {
|
if (state.v3d != nullptr) {
|
||||||
@ -75,9 +85,18 @@ void Instance::begin_sync()
|
|||||||
|
|
||||||
background.begin_sync(resources, state);
|
background.begin_sync(resources, state);
|
||||||
prepass.begin_sync(resources, state);
|
prepass.begin_sync(resources, state);
|
||||||
empties.begin_sync();
|
|
||||||
metaballs.begin_sync();
|
metaballs.begin_sync();
|
||||||
grid.begin_sync(resources, state, view);
|
grid.begin_sync(resources, state, view);
|
||||||
|
bounds.begin_sync(resources, state);
|
||||||
|
cameras.begin_sync(resources, state);
|
||||||
|
collisions.begin_sync(resources, state);
|
||||||
|
empties.begin_sync(resources, state);
|
||||||
|
force_fields.begin_sync(resources, state);
|
||||||
|
lights.begin_sync(resources, state);
|
||||||
|
light_probes.begin_sync(resources, state);
|
||||||
|
object_centers.begin_sync(resources, state);
|
||||||
|
object_relations.begin_sync(resources, state);
|
||||||
|
speakers.begin_sync(resources, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||||
@ -85,6 +104,12 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
|||||||
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
|
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
|
||||||
const bool needs_prepass = true; /* TODO */
|
const bool needs_prepass = true; /* TODO */
|
||||||
|
|
||||||
|
if (!needs_prepass || state.hide_overlays) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const select::ID select_id = resources.select_id(ob_ref);
|
||||||
Clément Foucault
commented
I would not put the select_id creation there. It would create id for object that might not be drawn. Also it is further for the code that actually uses it. I would not put the select_id creation there. It would create id for object that might not be drawn. Also it is further for the code that actually uses it.
|
|||||||
|
|
||||||
if (needs_prepass) {
|
if (needs_prepass) {
|
||||||
switch (ob_ref.object->type) {
|
switch (ob_ref.object->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
@ -92,7 +117,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
|||||||
case OB_CURVES:
|
case OB_CURVES:
|
||||||
case OB_FONT:
|
case OB_FONT:
|
||||||
case OB_CURVES_LEGACY:
|
case OB_CURVES_LEGACY:
|
||||||
prepass.object_sync(manager, ob_ref, resources);
|
prepass.object_sync(manager, ob_ref, select_id, resources);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,19 +146,36 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
|||||||
|
|
||||||
if (!state.hide_overlays) {
|
if (!state.hide_overlays) {
|
||||||
switch (ob_ref.object->type) {
|
switch (ob_ref.object->type) {
|
||||||
case OB_EMPTY:
|
|
||||||
empties.object_sync(ob_ref, resources, state);
|
|
||||||
break;
|
|
||||||
case OB_ARMATURE:
|
case OB_ARMATURE:
|
||||||
break;
|
break;
|
||||||
case OB_MBALL:
|
case OB_CAMERA:
|
||||||
if (!in_edit_mode) {
|
cameras.object_sync(ob_ref, select_id, resources, state);
|
||||||
metaballs.object_sync(ob_ref, resources, state);
|
break;
|
||||||
}
|
case OB_EMPTY:
|
||||||
|
empties.object_sync(ob_ref, select_id, resources, state);
|
||||||
break;
|
break;
|
||||||
case OB_GPENCIL_LEGACY:
|
case OB_GPENCIL_LEGACY:
|
||||||
break;
|
break;
|
||||||
|
case OB_LAMP:
|
||||||
|
lights.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
break;
|
||||||
|
case OB_LIGHTPROBE:
|
||||||
|
light_probes.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
break;
|
||||||
|
case OB_MBALL:
|
||||||
|
if (!in_edit_mode) {
|
||||||
|
metaballs.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OB_SPEAKER:
|
||||||
|
speakers.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
bounds.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
collisions.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
force_fields.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
object_centers.object_sync(ob_ref, select_id, resources, state);
|
||||||
|
object_relations.object_sync(ob_ref, select_id, resources, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +184,16 @@ void Instance::end_sync()
|
|||||||
resources.end_sync();
|
resources.end_sync();
|
||||||
|
|
||||||
metaballs.end_sync(resources, shapes, state);
|
metaballs.end_sync(resources, shapes, state);
|
||||||
empties.end_sync(resources, shapes, state);
|
bounds.end_sync(resources, state);
|
||||||
|
cameras.end_sync(resources, state);
|
||||||
|
collisions.end_sync(resources, state);
|
||||||
|
empties.end_sync(resources, state);
|
||||||
|
force_fields.end_sync(resources, state);
|
||||||
|
lights.end_sync(resources, state);
|
||||||
|
light_probes.end_sync(resources, state);
|
||||||
|
object_centers.end_sync(resources, state);
|
||||||
|
object_relations.end_sync(resources, state);
|
||||||
|
speakers.end_sync(resources, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::draw(Manager &manager)
|
void Instance::draw(Manager &manager)
|
||||||
@ -157,7 +208,7 @@ void Instance::draw(Manager &manager)
|
|||||||
const DRWView *view_legacy = DRW_view_default_get();
|
const DRWView *view_legacy = DRW_view_default_get();
|
||||||
View view("OverlayView", view_legacy);
|
View view("OverlayView", view_legacy);
|
||||||
|
|
||||||
/* TODO: Better semantics using a switch? */
|
/* TODO: Better semantical switch? */
|
||||||
if (!resources.color_overlay_tx.is_valid()) {
|
if (!resources.color_overlay_tx.is_valid()) {
|
||||||
/* Likely to be the selection case. Allocate dummy texture and bind only depth buffer. */
|
/* Likely to be the selection case. Allocate dummy texture and bind only depth buffer. */
|
||||||
resources.line_tx.acquire(int2(1, 1), GPU_RGBA8);
|
resources.line_tx.acquire(int2(1, 1), GPU_RGBA8);
|
||||||
@ -207,13 +258,31 @@ void Instance::draw(Manager &manager)
|
|||||||
|
|
||||||
background.draw(resources, manager);
|
background.draw(resources, manager);
|
||||||
|
|
||||||
empties.draw(resources, manager, view);
|
|
||||||
metaballs.draw(resources, manager, view);
|
metaballs.draw(resources, manager, view);
|
||||||
|
bounds.draw(resources, manager, view);
|
||||||
|
cameras.draw(resources, manager, view);
|
||||||
|
collisions.draw(resources, manager, view);
|
||||||
|
empties.draw(resources, manager, view);
|
||||||
|
force_fields.draw(resources, manager, view);
|
||||||
|
lights.draw(resources, manager, view);
|
||||||
|
light_probes.draw(resources, manager, view);
|
||||||
|
object_centers.draw(resources, manager, view);
|
||||||
|
object_relations.draw(resources, manager, view);
|
||||||
|
speakers.draw(resources, manager, view);
|
||||||
|
|
||||||
grid.draw(resources, manager, view);
|
grid.draw(resources, manager, view);
|
||||||
|
|
||||||
empties.draw_in_front(resources, manager, view);
|
|
||||||
metaballs.draw_in_front(resources, manager, view);
|
metaballs.draw_in_front(resources, manager, view);
|
||||||
|
bounds.draw_in_front(resources, manager, view);
|
||||||
|
cameras.draw_in_front(resources, manager, view);
|
||||||
|
collisions.draw_in_front(resources, manager, view);
|
||||||
|
empties.draw_in_front(resources, manager, view);
|
||||||
|
force_fields.draw_in_front(resources, manager, view);
|
||||||
|
lights.draw_in_front(resources, manager, view);
|
||||||
|
light_probes.draw_in_front(resources, manager, view);
|
||||||
|
object_centers.draw_in_front(resources, manager, view);
|
||||||
|
object_relations.draw_in_front(resources, manager, view);
|
||||||
|
speakers.draw_in_front(resources, manager, view);
|
||||||
|
|
||||||
// anti_aliasing.draw(resources, manager, view);
|
// anti_aliasing.draw(resources, manager, view);
|
||||||
|
|
||||||
|
@ -11,11 +11,23 @@
|
|||||||
#include "overlay_next_private.hh"
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
#include "overlay_next_background.hh"
|
#include "overlay_next_background.hh"
|
||||||
#include "overlay_next_empty.hh"
|
|
||||||
#include "overlay_next_grid.hh"
|
#include "overlay_next_grid.hh"
|
||||||
#include "overlay_next_metaball.hh"
|
#include "overlay_next_metaball.hh"
|
||||||
|
#include "overlay_next_object_center.hh"
|
||||||
|
#include "overlay_next_object_relation.hh"
|
||||||
#include "overlay_next_prepass.hh"
|
#include "overlay_next_prepass.hh"
|
||||||
|
|
||||||
|
#include "overlay_next_bounds.hh"
|
||||||
|
#include "overlay_next_camera.hh"
|
||||||
|
#include "overlay_next_collision.hh"
|
||||||
|
#include "overlay_next_empty.hh"
|
||||||
|
#include "overlay_next_force_field.hh"
|
||||||
|
#include "overlay_next_light.hh"
|
||||||
|
#include "overlay_next_light_probe.hh"
|
||||||
|
#include "overlay_next_object_center.hh"
|
||||||
|
#include "overlay_next_object_relation.hh"
|
||||||
|
#include "overlay_next_speaker.hh"
|
||||||
|
|
||||||
namespace blender::draw::overlay {
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +52,17 @@ class Instance {
|
|||||||
Background background;
|
Background background;
|
||||||
Prepass prepass;
|
Prepass prepass;
|
||||||
Metaballs metaballs = {selection_type_};
|
Metaballs metaballs = {selection_type_};
|
||||||
Empties empties = {selection_type_};
|
|
||||||
Grid grid;
|
Grid grid;
|
||||||
|
Bound bounds = {selection_type_, shapes, G_draw.block};
|
||||||
|
Camera cameras = {selection_type_, shapes, G_draw.block};
|
||||||
|
Collision collisions = {selection_type_, shapes, G_draw.block};
|
||||||
|
Empty empties = {selection_type_, shapes, G_draw.block};
|
||||||
|
ForceField force_fields = {selection_type_, shapes, G_draw.block};
|
||||||
|
Light lights = {selection_type_, shapes, G_draw.block};
|
||||||
|
LightProbe light_probes = {selection_type_, shapes, G_draw.block};
|
||||||
|
ObjectCenter object_centers = {selection_type_, shapes, G_draw.block};
|
||||||
|
ObjectRelation object_relations = {selection_type_, shapes, G_draw.block};
|
||||||
|
Speaker speakers = {selection_type_, shapes, G_draw.block};
|
||||||
|
|
||||||
Instance(const SelectionType selection_type) : selection_type_(selection_type){};
|
Instance(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||||
|
|
||||||
|
152
source/blender/draw/engines/overlay/overlay_next_light.hh
Normal file
152
source/blender/draw/engines/overlay/overlay_next_light.hh
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
using GroundLineInstanceBuf = BatchInstanceBuf<float4>;
|
||||||
|
|
||||||
|
class LightPasses : public OverlayPasses {
|
||||||
|
|
||||||
|
GroundLineInstanceBuf groundline = {"groundline", shapes.groundline.get(), selection_type};
|
||||||
|
|
||||||
|
ExtraInstanceBuf icon_inner = extra_buf("light_icon_inner", shapes.light_icon_inner);
|
||||||
|
ExtraInstanceBuf icon_outer = extra_buf("light_icon_outer", shapes.light_icon_outer);
|
||||||
|
ExtraInstanceBuf icon_sun_rays = extra_buf("light_icon_sun_rays", shapes.light_icon_sun_rays);
|
||||||
|
|
||||||
|
ExtraInstanceBuf point = extra_buf("light_point", shapes.light_point);
|
||||||
|
ExtraInstanceBuf sun = extra_buf("light_sun", shapes.light_sun);
|
||||||
|
ExtraInstanceBuf spot = extra_buf("light_spot", shapes.light_spot);
|
||||||
|
ExtraInstanceBuf spot_cone_back = extra_buf(
|
||||||
|
"light_spot_cone_back", shapes.light_spot_cone, BLEND_CULL_BACK);
|
||||||
|
ExtraInstanceBuf spot_cone_front = extra_buf(
|
||||||
|
"light_spot_cone_front", shapes.light_spot_cone, BLEND_CULL_FRONT);
|
||||||
|
ExtraInstanceBuf area_disk = extra_buf("light_area_disk", shapes.light_area_disk);
|
||||||
|
ExtraInstanceBuf area_square = extra_buf("light_area_square", shapes.light_area_square);
|
||||||
|
|
||||||
|
public:
|
||||||
|
LightPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Lights", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void begin_sync(Resources &res, const State &state) final override
|
||||||
|
{
|
||||||
|
OverlayPasses::begin_sync(res, state);
|
||||||
|
groundline.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void end_sync(Resources &res, const State &state) final override
|
||||||
|
{
|
||||||
|
OverlayPasses::end_sync(res, state);
|
||||||
|
if (groundline.data_buf.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PassSimple::Sub &ps = ps_.sub("GroundLine");
|
||||||
|
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND_ADD |
|
||||||
|
state.clipping_state);
|
||||||
|
ps.shader_set(res.shaders.extra_groundline.get());
|
||||||
|
/* TODO: Fixed index. */
|
||||||
|
ps.bind_ubo("globalsBlock", &res.globals_buf);
|
||||||
|
groundline.end_sync(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
BLI_assert(ob->type == OB_LAMP);
|
||||||
|
|
||||||
|
ExtraInstanceData data(ob_ref.object, res.object_wire_color(ob_ref, state));
|
||||||
|
|
||||||
|
/* Pack render data into object matrix. */
|
||||||
|
float4x4 &matrix = data.matrix;
|
||||||
|
float &area_size_x = matrix[0].w;
|
||||||
|
float &area_size_y = matrix[1].w;
|
||||||
|
float &spot_cosine = matrix[0].w;
|
||||||
|
float &spot_blend = matrix[1].w;
|
||||||
|
float &clip_start = matrix[2].w;
|
||||||
|
float &clip_end = matrix[3].w;
|
||||||
|
|
||||||
|
Light *la = static_cast<Light *>(ob->data);
|
||||||
|
|
||||||
|
/* FIXME / TODO: clip_end has no meaning nowadays.
|
||||||
|
* In EEVEE, Only clip_start is used shadow-mapping.
|
||||||
|
* Clip end is computed automatically based on light power.
|
||||||
|
* For now, always use the custom distance as clip_end. */
|
||||||
|
clip_end = la->att_dist;
|
||||||
|
clip_start = la->clipsta;
|
||||||
|
|
||||||
|
/* Remove the alpha. */
|
||||||
|
data.color = float4(data.color.xyz(), 1.0f);
|
||||||
|
|
||||||
|
float4 light_color = data.color;
|
||||||
|
if (state.overlay.flag & V3D_OVERLAY_SHOW_LIGHT_COLORS) {
|
||||||
|
light_color = float4(la->r, la->g, la->b, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
groundline.append(float4(data.matrix.location()), select_id);
|
||||||
|
|
||||||
|
icon_inner.append(data.with_color(light_color), select_id);
|
||||||
|
icon_outer.append(data, select_id);
|
||||||
|
|
||||||
|
if (la->type == LA_LOCAL) {
|
||||||
|
area_size_x = area_size_y = la->radius;
|
||||||
|
point.append(data, select_id);
|
||||||
|
}
|
||||||
|
else if (la->type == LA_SUN) {
|
||||||
|
sun.append(data, select_id);
|
||||||
|
icon_sun_rays.append(data.with_color(light_color), select_id);
|
||||||
|
}
|
||||||
|
else if (la->type == LA_SPOT) {
|
||||||
|
/* Previous implementation was using the clip-end distance as cone size.
|
||||||
|
* We cannot do this anymore so we use a fixed size of 10. (see #72871) */
|
||||||
|
matrix = math::scale(matrix, float3(10.0f));
|
||||||
|
/* For cycles and EEVEE the spot attenuation is:
|
||||||
|
* `y = (1/sqrt(1 + x^2) - a)/((1 - a) b)`
|
||||||
|
* x being the tangent of the angle between the light direction and the
|
||||||
|
* generatrix of the cone. We solve the case where spot attenuation y = 1
|
||||||
|
* and y = 0 root for y = 1 is sqrt(1/c^2 - 1) root for y = 0 is
|
||||||
|
* sqrt(1/a^2 - 1) and use that to position the blend circle. */
|
||||||
|
float a = cosf(la->spotsize * 0.5f);
|
||||||
|
float b = la->spotblend;
|
||||||
|
float c = a * b - a - b;
|
||||||
|
float a2 = a * a;
|
||||||
|
float c2 = c * c;
|
||||||
|
/* Optimized version or root1 / root0 */
|
||||||
|
spot_blend = sqrtf((a2 - a2 * c2) / (c2 - a2 * c2));
|
||||||
|
spot_cosine = a;
|
||||||
|
/* HACK: We pack the area size in alpha color. This is decoded by the shader. */
|
||||||
|
data.color.w = -max_ff(la->radius, FLT_MIN);
|
||||||
|
spot.append(data, select_id);
|
||||||
|
if ((la->mode & LA_SHOW_CONE) && !DRW_state_is_select()) {
|
||||||
|
spot_cone_front.append(data.with_color({0.0f, 0.0f, 0.0f, 0.5f}), select_id);
|
||||||
|
spot_cone_back.append(data.with_color({1.0f, 1.0f, 1.0f, 0.3f}), select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (la->type == LA_AREA) {
|
||||||
|
ExtraInstanceBuf &buf = ELEM(la->area_shape, LA_AREA_SQUARE, LA_AREA_RECT) ? area_square :
|
||||||
|
area_disk;
|
||||||
|
bool uniform_scale = !ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE);
|
||||||
|
area_size_x = la->area_size;
|
||||||
|
area_size_y = uniform_scale ? la->area_size : la->area_sizey;
|
||||||
|
buf.append(data, select_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
BLI_assert_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Light = OverlayType<LightPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
198
source/blender/draw/engines/overlay/overlay_next_light_probe.hh
Normal file
198
source/blender/draw/engines/overlay/overlay_next_light_probe.hh
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DNA_lightprobe_types.h"
|
||||||
|
#include "overlay_next_empty.hh"
|
||||||
|
#include "overlay_next_light.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class DotsGridPass {
|
||||||
|
PassMain ps_ = {"Probe Grid"};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void begin_sync(Resources &res, const State &state)
|
||||||
|
{
|
||||||
|
ps_.init();
|
||||||
|
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_PROGRAM_POINT_SIZE | state.clipping_state);
|
||||||
|
ps_.shader_set(res.shaders.extra_grid.get());
|
||||||
|
/* TODO(Miguel Pozo): Selection doesn't work. */
|
||||||
|
res.select_bind(ps_);
|
||||||
|
/* TODO: Fixed index. */
|
||||||
|
ps_.bind_ubo("globalsBlock", &res.globals_buf);
|
||||||
|
ps_.bind_texture("depthBuffer", &res.depth_tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
int3 grid_resolution,
|
||||||
|
int theme_id,
|
||||||
|
Resources & /*res*/,
|
||||||
|
const State &state)
|
||||||
|
{
|
||||||
|
float4x4 matrix = float4x4(ob_ref.object->object_to_world);
|
||||||
|
/* Pack render data into object matrix. */
|
||||||
|
matrix[0][3] = grid_resolution.x;
|
||||||
|
matrix[1][3] = grid_resolution.y;
|
||||||
|
matrix[2][3] = grid_resolution.z;
|
||||||
|
matrix[3][3] = theme_id;
|
||||||
|
|
||||||
|
uint cell_count = grid_resolution.x * grid_resolution.y * grid_resolution.z;
|
||||||
|
|
||||||
|
ResourceHandle res_handle = state.manager->resource_handle(matrix);
|
||||||
|
ps_.draw_procedural(GPU_PRIM_POINTS, 1, cell_count, 0, res_handle, select_id.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Manager &manager, View &view, Framebuffer &fb)
|
||||||
|
{
|
||||||
|
fb.bind();
|
||||||
|
manager.submit(ps_, view);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LightProbePasses : public OverlayPasses {
|
||||||
|
|
||||||
|
DotsGridPass dots_grid;
|
||||||
|
|
||||||
|
GroundLineInstanceBuf groundline = {"groundline", shapes.groundline.get(), selection_type};
|
||||||
|
|
||||||
|
ExtraInstanceBuf probe_cube = extra_buf("probe_cube", shapes.probe_cube);
|
||||||
|
ExtraInstanceBuf probe_grid = extra_buf("probe_grid", shapes.probe_grid);
|
||||||
|
ExtraInstanceBuf probe_planar = extra_buf("probe_planar", shapes.probe_planar);
|
||||||
|
|
||||||
|
ExtraInstanceBuf single_arrow = extra_buf("single_arrow", shapes.single_arrow);
|
||||||
|
ExtraInstanceBuf quad = extra_buf("quad", shapes.quad);
|
||||||
|
ExtraInstanceBuf cube = extra_buf("cube", shapes.empty_cube);
|
||||||
|
ExtraInstanceBuf sphere = extra_buf("sphere", shapes.empty_sphere);
|
||||||
|
|
||||||
|
public:
|
||||||
|
LightProbePasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Lights", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void begin_sync(Resources &res, const State &state) final override
|
||||||
|
{
|
||||||
|
OverlayPasses::begin_sync(res, state);
|
||||||
|
dots_grid.begin_sync(res, state);
|
||||||
|
groundline.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void end_sync(Resources &res, const State &state) final override
|
||||||
|
{
|
||||||
|
OverlayPasses::end_sync(res, state);
|
||||||
|
if (groundline.data_buf.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PassSimple::Sub &ps = ps_.sub("GroundLine");
|
||||||
|
ps.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND_ADD |
|
||||||
|
state.clipping_state);
|
||||||
|
ps.shader_set(res.shaders.extra_groundline.get());
|
||||||
|
/* TODO: Fixed index. */
|
||||||
|
ps.bind_ubo("globalsBlock", &res.globals_buf);
|
||||||
|
groundline.end_sync(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void draw(Manager &manager, View &view, Framebuffer &fb) final override
|
||||||
|
{
|
||||||
|
OverlayPasses::draw(manager, view, fb);
|
||||||
|
dots_grid.draw(manager, view, fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
BLI_assert(ob->type == OB_LIGHTPROBE);
|
||||||
|
|
||||||
|
ExtraInstanceData data(ob, res.object_wire_color(ob_ref, state));
|
||||||
|
|
||||||
|
const ::LightProbe *probe = (::LightProbe *)ob_ref.object->data;
|
||||||
|
const bool show_clipping = (probe->flag & LIGHTPROBE_FLAG_SHOW_CLIP_DIST) != 0;
|
||||||
|
const bool show_parallax = (probe->flag & LIGHTPROBE_FLAG_SHOW_PARALLAX) != 0;
|
||||||
|
const bool show_influence = (probe->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0;
|
||||||
|
const bool show_data = (ob_ref.object->base_flag & BASE_SELECTED) ||
|
||||||
|
res.selection_type != SelectionType::DISABLED;
|
||||||
|
|
||||||
|
if (probe->type == LIGHTPROBE_TYPE_CUBE) {
|
||||||
|
/* Pack render data into object matrix. */
|
||||||
|
data.matrix[2][3] = show_clipping ? probe->clipsta : -1.0;
|
||||||
|
data.matrix[3][3] = show_clipping ? probe->clipend : -1.0;
|
||||||
|
|
||||||
|
probe_cube.append(data, select_id);
|
||||||
|
groundline.append(float4(data.matrix.location()), select_id);
|
||||||
|
|
||||||
|
if (show_influence) {
|
||||||
|
float influence_start = probe->distinf * (1.0f - probe->falloff);
|
||||||
|
float influence_end = probe->distinf;
|
||||||
|
|
||||||
|
ExtraInstanceBuf &buf = (probe->attenuation_type == LIGHTPROBE_SHAPE_BOX) ? cube : sphere;
|
||||||
|
|
||||||
|
buf.append(data.with_size(influence_start), select_id);
|
||||||
|
buf.append(data.with_size(influence_end), select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_parallax) {
|
||||||
|
float radius = (probe->flag & LIGHTPROBE_FLAG_CUSTOM_PARALLAX) ? probe->distpar :
|
||||||
|
probe->distinf;
|
||||||
|
ExtraInstanceBuf &buf = (probe->parallax_type == LIGHTPROBE_SHAPE_BOX) ? cube : sphere;
|
||||||
|
buf.append(data.with_size(radius), select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (probe->type == LIGHTPROBE_TYPE_GRID) {
|
||||||
|
/* Pack render data into object matrix. */
|
||||||
|
data.matrix[2][3] = show_clipping ? probe->clipsta : -1.0;
|
||||||
|
data.matrix[3][3] = show_clipping ? probe->clipend : -1.0;
|
||||||
|
probe_grid.append(data, select_id);
|
||||||
|
|
||||||
|
if (show_influence) {
|
||||||
|
float influence_start = 1.0f + probe->distinf * (1.0f - probe->falloff);
|
||||||
|
float influence_end = 1.0f + probe->distinf;
|
||||||
|
|
||||||
|
cube.append(data.with_size(influence_start), select_id);
|
||||||
|
cube.append(data.with_size(influence_end), select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data dots */
|
||||||
|
if (show_data) {
|
||||||
|
int3 resolution = int3(&probe->grid_resolution_x);
|
||||||
|
int theme_id = res.object_wire_theme_id(ob_ref, state) == TH_ACTIVE ? 1 : 2;
|
||||||
|
dots_grid.object_sync(ob_ref, select_id, resolution, theme_id, res, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
|
||||||
|
probe_planar.append(data, select_id);
|
||||||
|
|
||||||
|
if (res.selection_type != SelectionType::DISABLED &&
|
||||||
|
(probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
|
||||||
|
quad.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_influence) {
|
||||||
|
data.matrix.z_axis() = math::normalize(data.matrix.z_axis()) * probe->distinf;
|
||||||
|
cube.append(data, select_id);
|
||||||
|
data.matrix.z_axis() *= 1.0f - probe->falloff;
|
||||||
|
cube.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.matrix.z_axis() = float3(0);
|
||||||
|
cube.append(data, select_id);
|
||||||
|
|
||||||
|
data.matrix = float4x4(ob_ref.object->object_to_world);
|
||||||
|
data.matrix.view<3, 3>() = math::normalize(data.matrix.view<3, 3>());
|
||||||
|
single_arrow.append(data.with_size(ob_ref.object->empty_drawsize), select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using LightProbe = OverlayType<LightProbePasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -19,16 +19,16 @@ class Metaballs {
|
|||||||
using SphereOutlineInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
using SphereOutlineInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const SelectionType selection_type_;
|
|
||||||
|
|
||||||
PassSimple metaball_ps_ = {"MetaBalls"};
|
PassSimple metaball_ps_ = {"MetaBalls"};
|
||||||
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
|
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
|
||||||
|
|
||||||
SphereOutlineInstanceBuf circle_buf_ = {selection_type_, "metaball_data_buf"};
|
SphereOutlineInstanceBuf circle_buf_;
|
||||||
SphereOutlineInstanceBuf circle_in_front_buf_ = {selection_type_, "metaball_data_buf"};
|
SphereOutlineInstanceBuf circle_in_front_buf_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Metaballs(const SelectionType selection_type) : selection_type_(selection_type){};
|
Metaballs(const SelectionType selection_type)
|
||||||
|
: circle_buf_(selection_type, "metaball_data_buf"),
|
||||||
|
circle_in_front_buf_(selection_type, "metaball_in_front_data_buf"){};
|
||||||
|
|
||||||
void begin_sync()
|
void begin_sync()
|
||||||
{
|
{
|
||||||
@ -64,7 +64,10 @@ class Metaballs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state)
|
||||||
{
|
{
|
||||||
SphereOutlineInstanceBuf &circle_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
|
SphereOutlineInstanceBuf &circle_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
|
||||||
circle_in_front_buf_ :
|
circle_in_front_buf_ :
|
||||||
@ -72,7 +75,6 @@ class Metaballs {
|
|||||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||||
|
|
||||||
const float4 &color = res.object_wire_color(ob_ref, state);
|
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) {
|
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
|
||||||
/* Draw radius only. */
|
/* Draw radius only. */
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class ObjectCenterPasses : public OverlayPasses {
|
||||||
|
|
||||||
|
ExtraInstanceBuf origin_xform = extra_buf("origin_xform", shapes.plain_axes, DEFAULT_ALWAYS);
|
||||||
|
|
||||||
|
ExtraInstanceBuf arrows = extra_buf("arrows", shapes.arrows);
|
||||||
|
|
||||||
|
PointInstanceBuf active = point_buf("active", theme_colors.color_active);
|
||||||
|
PointInstanceBuf selected = point_buf("selected", theme_colors.color_select);
|
||||||
|
PointInstanceBuf deselected = point_buf("deselected", theme_colors.color_deselect);
|
||||||
|
PointInstanceBuf selected_lib = point_buf("selected_lib", theme_colors.color_library_select);
|
||||||
|
PointInstanceBuf deselected_lib = point_buf("deselected_lib", theme_colors.color_library);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ObjectCenterPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Centers", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
ExtraInstanceData data(ob_ref.object, res.object_wire_color(ob_ref, state));
|
||||||
|
|
||||||
|
const bool is_select_mode = state.selection_type != SelectionType::DISABLED;
|
||||||
|
const bool draw_xform = state.object_mode == OB_MODE_OBJECT &&
|
||||||
|
(state.scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) &&
|
||||||
|
(ob->base_flag & BASE_SELECTED) && !is_select_mode;
|
||||||
|
|
||||||
|
if (draw_xform) {
|
||||||
|
/* TODO(Miguel Pozo): What's this? */
|
||||||
|
const float4 color_xform = {0.15f, 0.15f, 0.15f, 0.7f};
|
||||||
|
origin_xform.append(data.with_color(color_xform), select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool from_dupli = ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI);
|
||||||
|
|
||||||
|
if (!from_dupli && ob->dtx & OB_AXIS) {
|
||||||
|
arrows.append(data, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool is_paint_mode = state.object_mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL |
|
||||||
|
OB_MODE_SCULPT_CURVES);
|
||||||
|
const bool hide_obcenters = state.overlay.flag & V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
|
||||||
|
|
||||||
|
if (is_paint_mode || from_dupli || hide_obcenters) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 center = float4(ob->object_to_world[3]);
|
||||||
|
|
||||||
|
const bool is_library = ID_REAL_USERS(&ob->id) > 1 || ID_IS_LINKED(ob);
|
||||||
|
/* TODO(Miguel Pozo): Handle const. */
|
||||||
|
BKE_view_layer_synced_ensure(state.scene, (ViewLayer *)state.view_layer);
|
||||||
|
if (ob == BKE_view_layer_active_object_get(state.view_layer)) {
|
||||||
|
active.append(center, select_id);
|
||||||
|
}
|
||||||
|
else if (ob->base_flag & BASE_SELECTED) {
|
||||||
|
(is_library ? selected_lib : selected).append(center, select_id);
|
||||||
|
}
|
||||||
|
else if (state.v3d_flag & V3D_DRAW_CENTERS) {
|
||||||
|
(is_library ? deselected_lib : deselected).append(center, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ObjectCenter = OverlayType<ObjectCenterPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -0,0 +1,151 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
#include "BKE_constraint.h"
|
||||||
|
#include "DNA_constraint_types.h"
|
||||||
|
#include "DNA_gpencil_modifier_types.h"
|
||||||
|
#include "DNA_modifier_types.h"
|
||||||
|
#include "DNA_rigidbody_types.h"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class ObjectRelationPasses : public OverlayPasses {
|
||||||
|
public:
|
||||||
|
ObjectRelationPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Object Relations", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
PointInstanceBuf relation_point = point_buf("relation_point", theme_colors.color_wire);
|
||||||
|
LineInstanceBuf relation_line = line_buf("relation_line", theme_colors.color_wire);
|
||||||
|
|
||||||
|
LineInstanceBuf constraint_line = line_buf("constraint_line", theme_colors.color_grid_axis_z);
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources & /*res*/,
|
||||||
|
const State &state) override
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
const bool is_select_mode = state.selection_type != SelectionType::DISABLED;
|
||||||
|
const bool from_dupli = ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI);
|
||||||
|
const bool hide_relations = state.v3d_flag & V3D_HIDE_HELPLINES;
|
||||||
|
if (is_select_mode || from_dupli || hide_relations) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float4x4 ob_mat = float4x4(ob->object_to_world);
|
||||||
|
const float3 &ob_pos = ob_mat.location();
|
||||||
|
|
||||||
|
/* Parent lines. */
|
||||||
|
if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) {
|
||||||
|
float3 parent_pos = float3(ob->runtime.parent_display_origin);
|
||||||
|
relation_line.append({parent_pos, ob_pos}, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hook lines. */
|
||||||
|
for (ModifierData *md : ListBaseWrapper<ModifierData>(&ob->modifiers)) {
|
||||||
|
if (md->type == eModifierType_Hook) {
|
||||||
|
HookModifierData *hmd = reinterpret_cast<HookModifierData *>(md);
|
||||||
|
float3 center = math::transform_point(ob_mat, float3(hmd->cent));
|
||||||
|
if (hmd->object) {
|
||||||
|
relation_line.append({hmd->object->object_to_world[3], center}, select_id);
|
||||||
|
}
|
||||||
|
relation_point.append(float4(center), select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (GpencilModifierData *md :
|
||||||
|
ListBaseWrapper<GpencilModifierData>(ob->greasepencil_modifiers)) {
|
||||||
|
if (md->type == eGpencilModifierType_Hook) {
|
||||||
|
HookGpencilModifierData *hmd = reinterpret_cast<HookGpencilModifierData *>(md);
|
||||||
|
float3 center = math::transform_point(ob_mat, float3(hmd->cent));
|
||||||
|
if (hmd->object) {
|
||||||
|
relation_line.append({hmd->object->object_to_world[3], center}, select_id);
|
||||||
|
}
|
||||||
|
relation_point.append(float4(center), select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rigidbody constraint lines. */
|
||||||
|
if (ob->rigidbody_constraint) {
|
||||||
|
Object *rbc_ob1 = ob->rigidbody_constraint->ob1;
|
||||||
|
Object *rbc_ob2 = ob->rigidbody_constraint->ob2;
|
||||||
|
if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) {
|
||||||
|
relation_line.append({rbc_ob1->object_to_world[3], ob_pos}, select_id);
|
||||||
|
}
|
||||||
|
if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) {
|
||||||
|
relation_line.append({rbc_ob2->object_to_world[3], ob_pos}, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constraint lines */
|
||||||
|
if (!BLI_listbase_is_empty(&ob->constraints)) {
|
||||||
|
/** TODO(Miguel Pozo): Remove casting. */
|
||||||
|
Depsgraph *depsgraph = (Depsgraph *)state.depsgraph;
|
||||||
|
Scene *scene = (Scene *)state.scene;
|
||||||
|
|
||||||
|
bConstraintOb *con_ob = BKE_constraints_make_evalob(
|
||||||
|
depsgraph, scene, ob, nullptr, CONSTRAINT_OBTYPE_OBJECT);
|
||||||
|
|
||||||
|
for (bConstraint *con : ListBaseWrapper<bConstraint>(&ob->constraints)) {
|
||||||
|
if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_OBJECTSOLVER)) {
|
||||||
|
/* Special case for object solver and follow track constraints because they don't fill
|
||||||
|
* constraint targets properly (design limitation -- scene is needed for their target
|
||||||
|
* but it can't be accessed from get_targets callback) */
|
||||||
|
Object *cam_ob = nullptr;
|
||||||
|
|
||||||
|
if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
|
||||||
|
bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
|
||||||
|
cam_ob = data->camera ? data->camera : scene->camera;
|
||||||
|
}
|
||||||
|
else if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
|
||||||
|
bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
|
||||||
|
cam_ob = data->camera ? data->camera : scene->camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cam_ob) {
|
||||||
|
constraint_line.append({cam_ob->object_to_world[3], ob_pos}, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const bConstraintTypeInfo *type_info = BKE_constraint_typeinfo_get(con);
|
||||||
|
ListBase targets = {nullptr, nullptr};
|
||||||
|
|
||||||
|
if ((con->ui_expand_flag & (1 << 0)) && BKE_constraint_targets_get(con, &targets)) {
|
||||||
|
BKE_constraint_custom_object_space_init(con_ob, con);
|
||||||
|
|
||||||
|
for (bConstraintTarget *target : ListBaseWrapper<bConstraintTarget>(&targets)) {
|
||||||
|
/* calculate target's position */
|
||||||
|
float3 target_pos = float3(0.0f);
|
||||||
|
if (target->flag & CONSTRAINT_TAR_CUSTOM_SPACE) {
|
||||||
|
target_pos = con_ob->space_obj_world_matrix[3];
|
||||||
|
}
|
||||||
|
else if (type_info->get_target_matrix) {
|
||||||
|
type_info->get_target_matrix(
|
||||||
|
depsgraph, con, con_ob, target, DEG_get_ctime(depsgraph));
|
||||||
|
target_pos = target->matrix[3];
|
||||||
|
}
|
||||||
|
constraint_line.append({target_pos, ob_pos}, select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_constraint_targets_flush(con, &targets, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* NOTE: Don't use #BKE_constraints_clear_evalob here as that will reset `ob->constinv`. */
|
||||||
|
MEM_freeN(con_ob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ObjectRelation = OverlayType<ObjectRelationPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -33,7 +33,10 @@ class Prepass {
|
|||||||
init_pass(prepass_in_front_ps_);
|
init_pass(prepass_in_front_ps_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_sync(Manager &manager, const ObjectRef &ob_ref, Resources &res)
|
void object_sync(Manager &manager,
|
||||||
|
const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res)
|
||||||
{
|
{
|
||||||
PassMain &pass = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? prepass_in_front_ps_ :
|
PassMain &pass = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? prepass_in_front_ps_ :
|
||||||
prepass_ps_;
|
prepass_ps_;
|
||||||
@ -43,7 +46,7 @@ class Prepass {
|
|||||||
GPUBatch *geom = DRW_cache_object_surface_get(ob_ref.object);
|
GPUBatch *geom = DRW_cache_object_surface_get(ob_ref.object);
|
||||||
if (geom) {
|
if (geom) {
|
||||||
ResourceHandle res_handle = manager.resource_handle(ob_ref);
|
ResourceHandle res_handle = manager.resource_handle(ob_ref);
|
||||||
pass.draw(geom, res_handle, res.select_id(ob_ref).get());
|
pass.draw(geom, res_handle, select_id.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ using blender::draw::TextureRef;
|
|||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
Depsgraph *depsgraph;
|
Depsgraph *depsgraph;
|
||||||
|
Manager *manager;
|
||||||
const ViewLayer *view_layer;
|
const ViewLayer *view_layer;
|
||||||
const Scene *scene;
|
const Scene *scene;
|
||||||
const View3D *v3d;
|
const View3D *v3d;
|
||||||
@ -40,6 +41,7 @@ struct State {
|
|||||||
const Base *active_base;
|
const Base *active_base;
|
||||||
View3DOverlay overlay;
|
View3DOverlay overlay;
|
||||||
float pixelsize;
|
float pixelsize;
|
||||||
|
SelectionType selection_type;
|
||||||
enum eSpace_Type space_type;
|
enum eSpace_Type space_type;
|
||||||
enum eContextObjectMode ctx_mode;
|
enum eContextObjectMode ctx_mode;
|
||||||
enum eObjectMode object_mode;
|
enum eObjectMode object_mode;
|
||||||
@ -56,46 +58,88 @@ struct State {
|
|||||||
DRWState clipping_state;
|
DRWState clipping_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BatchDeleter {
|
||||||
|
void operator()(GPUBatch *shader)
|
||||||
|
{
|
||||||
|
GPU_BATCH_DISCARD_SAFE(shader);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using BatchPtr = std::unique_ptr<GPUBatch, BatchDeleter>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all overlay generic geometry batches.
|
* Contains all overlay generic geometry batches.
|
||||||
*/
|
*/
|
||||||
class ShapeCache {
|
class ShapeCache {
|
||||||
private:
|
|
||||||
struct BatchDeleter {
|
|
||||||
void operator()(GPUBatch *shader)
|
|
||||||
{
|
|
||||||
GPU_BATCH_DISCARD_SAFE(shader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using BatchPtr = std::unique_ptr<GPUBatch, BatchDeleter>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BatchPtr quad_wire;
|
// GPUBatch *drw_normal_arrow; /* Single Arrow? */
|
||||||
BatchPtr plain_axes;
|
BatchPtr plain_axes;
|
||||||
BatchPtr single_arrow;
|
BatchPtr single_arrow;
|
||||||
BatchPtr cube;
|
BatchPtr arrows;
|
||||||
|
BatchPtr quad_wire;
|
||||||
BatchPtr circle;
|
BatchPtr circle;
|
||||||
|
BatchPtr empty_cube;
|
||||||
BatchPtr empty_sphere;
|
BatchPtr empty_sphere;
|
||||||
BatchPtr empty_cone;
|
BatchPtr empty_cone;
|
||||||
BatchPtr arrows;
|
BatchPtr empty_cylinder;
|
||||||
|
BatchPtr empty_capsule_body;
|
||||||
|
BatchPtr empty_capsule_cap;
|
||||||
|
|
||||||
|
BatchPtr sphere_solid;
|
||||||
|
|
||||||
|
BatchPtr quad;
|
||||||
|
BatchPtr grid;
|
||||||
|
|
||||||
BatchPtr metaball_wire_circle;
|
BatchPtr metaball_wire_circle;
|
||||||
|
|
||||||
|
BatchPtr speaker;
|
||||||
|
|
||||||
|
BatchPtr groundline;
|
||||||
|
BatchPtr light_icon_inner;
|
||||||
|
BatchPtr light_icon_outer;
|
||||||
|
BatchPtr light_icon_sun_rays;
|
||||||
|
BatchPtr light_point;
|
||||||
|
BatchPtr light_sun;
|
||||||
|
BatchPtr light_spot;
|
||||||
|
BatchPtr light_spot_cone;
|
||||||
|
BatchPtr light_area_disk;
|
||||||
|
BatchPtr light_area_square;
|
||||||
|
|
||||||
|
BatchPtr probe_cube;
|
||||||
|
BatchPtr probe_grid;
|
||||||
|
BatchPtr probe_planar;
|
||||||
|
|
||||||
|
BatchPtr camera_volume;
|
||||||
|
BatchPtr camera_volume_wire;
|
||||||
|
BatchPtr camera_frame;
|
||||||
|
BatchPtr camera_tria_wire;
|
||||||
|
BatchPtr camera_tria;
|
||||||
|
BatchPtr camera_distances;
|
||||||
|
|
||||||
|
BatchPtr field_wind;
|
||||||
|
BatchPtr field_force;
|
||||||
|
BatchPtr field_vortex;
|
||||||
|
BatchPtr field_curve;
|
||||||
|
BatchPtr field_tube_limit;
|
||||||
|
BatchPtr field_cone_limit;
|
||||||
|
BatchPtr field_sphere_limit;
|
||||||
|
|
||||||
ShapeCache();
|
ShapeCache();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ShaderDeleter {
|
||||||
|
void operator()(GPUShader *shader)
|
||||||
|
{
|
||||||
|
DRW_SHADER_FREE_SAFE(shader);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ShaderPtr = std::unique_ptr<GPUShader, ShaderDeleter>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shader module. Shared between instances.
|
* Shader module. Shared between instances.
|
||||||
*/
|
*/
|
||||||
class ShaderModule {
|
class ShaderModule {
|
||||||
private:
|
private:
|
||||||
struct ShaderDeleter {
|
|
||||||
void operator()(GPUShader *shader)
|
|
||||||
{
|
|
||||||
DRW_SHADER_FREE_SAFE(shader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using ShaderPtr = std::unique_ptr<GPUShader, ShaderDeleter>;
|
|
||||||
|
|
||||||
/** Shared shader module across all engine instances. */
|
/** Shared shader module across all engine instances. */
|
||||||
static ShaderModule *g_shader_modules[2 /*Selection Instance*/][2 /*Clipping Enabled*/];
|
static ShaderModule *g_shader_modules[2 /*Selection Instance*/][2 /*Clipping Enabled*/];
|
||||||
|
|
||||||
@ -115,6 +159,16 @@ class ShaderModule {
|
|||||||
ShaderPtr depth_mesh;
|
ShaderPtr depth_mesh;
|
||||||
ShaderPtr extra_shape;
|
ShaderPtr extra_shape;
|
||||||
|
|
||||||
|
ShaderPtr extra_groundline;
|
||||||
|
ShaderPtr extra_point;
|
||||||
|
ShaderPtr extra_line;
|
||||||
|
ShaderPtr extra_grid;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
ShaderPtr extra_wire;
|
||||||
|
ShaderPtr extra_wire_object;
|
||||||
|
ShaderPtr extra_loose_point;
|
||||||
|
|
||||||
ShaderModule(const SelectionType selection_type, const bool clipping_enabled);
|
ShaderModule(const SelectionType selection_type, const bool clipping_enabled);
|
||||||
|
|
||||||
/** Module */
|
/** Module */
|
||||||
@ -230,12 +284,25 @@ struct Resources : public select::SelectMap {
|
|||||||
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
||||||
return object_wire_color(ob_ref, theme_id);
|
return object_wire_color(ob_ref, theme_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float4 background_blend_color(ThemeColorID theme_id) const
|
||||||
|
{
|
||||||
|
float4 color;
|
||||||
|
UI_GetThemeColorBlendShade4fv(theme_id, TH_BACK, 0.5, 0, color);
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 object_background_blend_color(const ObjectRef &ob_ref, const State &state) const
|
||||||
|
{
|
||||||
|
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
||||||
|
return background_blend_color(theme_id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer containing instances of a certain shape.
|
* Buffer containing instances of a certain shape.
|
||||||
*/
|
*/
|
||||||
template<typename InstanceDataT> struct ShapeInstanceBuf : private select::SelectBuf {
|
template<typename InstanceDataT> struct ShapeInstanceBuf : protected select::SelectBuf {
|
||||||
|
|
||||||
StorageVectorBuffer<InstanceDataT> data_buf;
|
StorageVectorBuffer<InstanceDataT> data_buf;
|
||||||
|
|
||||||
@ -254,7 +321,7 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
|||||||
data_buf.append(data);
|
data_buf.append(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_sync(PassSimple &pass, GPUBatch *shape)
|
void end_sync(PassSimple::Sub &pass, GPUBatch *shape)
|
||||||
{
|
{
|
||||||
if (data_buf.size() == 0) {
|
if (data_buf.size() == 0) {
|
||||||
return;
|
return;
|
||||||
@ -266,4 +333,241 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T> struct BatchInstanceBuf : public ShapeInstanceBuf<T> {
|
||||||
|
GPUBatch *batch;
|
||||||
|
|
||||||
|
BatchInstanceBuf(const char *name, GPUBatch *batch, const SelectionType selection_type)
|
||||||
|
: ShapeInstanceBuf<T>(selection_type, name), batch(batch){};
|
||||||
|
|
||||||
|
BatchInstanceBuf(const char *name,
|
||||||
|
GPUBatch *batch,
|
||||||
|
const SelectionType selection_type,
|
||||||
|
Vector<BatchInstanceBuf<T> *> &pass_vector)
|
||||||
|
: BatchInstanceBuf(name, batch, selection_type)
|
||||||
|
{
|
||||||
|
pass_vector.append(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
void end_sync(PassSimple::Sub &pass)
|
||||||
|
{
|
||||||
|
ShapeInstanceBuf<T>::end_sync(pass, batch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ExtraInstanceBuf = BatchInstanceBuf<ExtraInstanceData>;
|
||||||
|
|
||||||
|
struct PointInstanceBuf : public ShapeInstanceBuf<float4> {
|
||||||
|
float4 color;
|
||||||
|
|
||||||
|
PointInstanceBuf(const char *name, float4 color, const SelectionType selection_type)
|
||||||
|
: ShapeInstanceBuf<float4>(selection_type, name), color(color){};
|
||||||
|
|
||||||
|
PointInstanceBuf(const char *name,
|
||||||
|
float4 color,
|
||||||
|
const SelectionType selection_type,
|
||||||
|
Vector<PointInstanceBuf *> &pass_vector)
|
||||||
|
: PointInstanceBuf(name, color, selection_type)
|
||||||
|
{
|
||||||
|
pass_vector.append(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
void end_sync(PassSimple::Sub &pass)
|
||||||
|
{
|
||||||
|
if (data_buf.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->select_bind(pass);
|
||||||
|
data_buf.push_update();
|
||||||
|
pass.bind_ssbo("data_buf", &data_buf);
|
||||||
|
pass.push_constant("ucolor", color);
|
||||||
|
pass.draw_procedural(GPU_PRIM_POINTS, data_buf.size(), 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LineInstanceBuf : public ShapeInstanceBuf<LineInstanceData> {
|
||||||
|
float4 color;
|
||||||
|
|
||||||
|
LineInstanceBuf(const char *name, float4 color, const SelectionType selection_type)
|
||||||
|
: ShapeInstanceBuf<LineInstanceData>(selection_type, name), color(color){};
|
||||||
|
|
||||||
|
LineInstanceBuf(const char *name,
|
||||||
|
float4 color,
|
||||||
|
const SelectionType selection_type,
|
||||||
|
Vector<LineInstanceBuf *> &pass_vector)
|
||||||
|
: LineInstanceBuf(name, color, selection_type)
|
||||||
|
{
|
||||||
|
pass_vector.append(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
void end_sync(PassSimple::Sub &pass)
|
||||||
|
{
|
||||||
|
if (data_buf.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->select_bind(pass);
|
||||||
|
data_buf.push_update();
|
||||||
|
pass.bind_ssbo("data_buf", &data_buf);
|
||||||
|
pass.push_constant("ucolor", color);
|
||||||
|
pass.draw_procedural(GPU_PRIM_LINES, data_buf.size(), 2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class OverlayPasses {
|
||||||
Clément Foucault
commented
This class is too generic of a name. It should be This class is too generic of a name. It should be `GeometryPass` since it is instanciated twice in `OverlayType`.
|
|||||||
|
protected:
|
||||||
|
const SelectionType selection_type;
|
||||||
|
const ShapeCache &shapes;
|
||||||
|
const GlobalsUboStorage &theme_colors;
|
||||||
|
|
||||||
|
PassSimple ps_;
|
||||||
|
|
||||||
|
enum ExtraType { DEFAULT, DEFAULT_ALWAYS, BLEND_CULL_FRONT, BLEND_CULL_BACK, MAX };
|
||||||
Clément Foucault
commented
Document each values. Not sure what's the difference between Document each values. Not sure what's the difference between `DEFAULT` and `DEFAULT_ALWAYS`.
|
|||||||
|
Vector<ExtraInstanceBuf *> extra_buffers_[ExtraType::MAX] = {{}};
|
||||||
|
ExtraInstanceBuf extra_buf(const char *name,
|
||||||
|
const BatchPtr &shape_ptr,
|
||||||
|
ExtraType pass_type = DEFAULT)
|
||||||
|
{
|
||||||
|
Vector<ExtraInstanceBuf *> &vector = extra_buffers_[pass_type];
|
||||||
|
return {name, shape_ptr.get(), selection_type, vector};
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector<PointInstanceBuf *> point_buffers_ = {};
|
||||||
|
PointInstanceBuf point_buf(const char *name, float4 color)
|
||||||
|
{
|
||||||
|
return {name, color, selection_type, point_buffers_};
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<LineInstanceBuf *> line_buffers_ = {};
|
||||||
|
LineInstanceBuf line_buf(const char *name, float4 color)
|
||||||
|
{
|
||||||
|
return {name, color, selection_type, line_buffers_};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
OverlayPasses(const char *name,
|
||||||
|
SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: selection_type(selection_type),
|
||||||
|
shapes(shapes),
|
||||||
|
theme_colors(theme_colors),
|
||||||
|
ps_(in_front ? (name + std::string(" In Front")).c_str() : name){};
|
||||||
|
|
||||||
|
virtual void begin_sync(Resources &res, const State & /*state*/)
|
||||||
|
{
|
||||||
|
ps_.init();
|
||||||
|
res.select_bind(ps_);
|
||||||
|
|
||||||
|
for (Vector<ExtraInstanceBuf *> &vector : extra_buffers_) {
|
||||||
|
for (ExtraInstanceBuf *buf : vector) {
|
||||||
|
buf->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (PointInstanceBuf *buf : point_buffers_) {
|
||||||
|
buf->clear();
|
||||||
|
}
|
||||||
|
for (LineInstanceBuf *buf : line_buffers_) {
|
||||||
|
buf->clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources & /*res*/,
|
||||||
|
const State &state) = 0;
|
||||||
|
|
||||||
|
virtual void end_sync(Resources &res, const State &state)
|
||||||
|
{
|
||||||
|
auto sub_pass =
|
||||||
|
[&](const char *name, ShaderPtr &shader, DRWState drw_state) -> PassSimple::Sub * {
|
||||||
|
PassSimple::Sub &ps = ps_.sub(name);
|
||||||
|
ps.state_set(drw_state);
|
||||||
|
ps.shader_set(shader.get());
|
||||||
|
/* TODO: Fixed index. */
|
||||||
|
ps.bind_ubo("globalsBlock", &res.globals_buf);
|
||||||
|
return &ps;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto sub_pass_iter = [&](const char *name, auto iter, ShaderPtr &shader, DRWState drw_state) {
|
||||||
|
if (iter.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PassSimple::Sub *ps = sub_pass(name, shader, drw_state);
|
||||||
|
for (auto *buf : iter) {
|
||||||
|
buf->end_sync(*ps);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DRWState state_base = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | state.clipping_state;
|
||||||
|
DRWState state_default = state_base | DRW_STATE_DEPTH_LESS_EQUAL;
|
||||||
|
DRWState state_blend = state_default | DRW_STATE_BLEND_ALPHA;
|
||||||
|
DRWState state_point = state_blend | DRW_STATE_PROGRAM_POINT_SIZE;
|
||||||
|
|
||||||
|
sub_pass_iter("Default", extra_buffers_[DEFAULT], res.shaders.extra_shape, state_default);
|
||||||
|
sub_pass_iter("Default Always",
|
||||||
|
extra_buffers_[DEFAULT_ALWAYS],
|
||||||
|
res.shaders.extra_shape,
|
||||||
|
state_base | DRW_STATE_DEPTH_ALWAYS);
|
||||||
|
sub_pass_iter("Blend Cull Back",
|
||||||
|
extra_buffers_[BLEND_CULL_BACK],
|
||||||
|
res.shaders.extra_shape,
|
||||||
|
state_blend | DRW_STATE_CULL_BACK);
|
||||||
|
sub_pass_iter("Blend Cull Front",
|
||||||
|
extra_buffers_[BLEND_CULL_FRONT],
|
||||||
|
res.shaders.extra_shape,
|
||||||
|
state_blend | DRW_STATE_CULL_FRONT);
|
||||||
|
sub_pass_iter("Point", point_buffers_, res.shaders.extra_point, state_point);
|
||||||
|
sub_pass_iter("Line", line_buffers_, res.shaders.extra_line, state_blend);
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void draw(Manager &manager, View &view, Framebuffer &fb)
|
||||||
|
{
|
||||||
|
fb.bind();
|
||||||
|
manager.submit(ps_, view);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> class OverlayType {
|
||||||
|
T passes_;
|
||||||
|
T passes_in_front_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OverlayType(const SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors)
|
||||||
|
: passes_(selection_type, shapes, theme_colors, false),
|
||||||
|
passes_in_front_(selection_type, shapes, theme_colors, true){};
|
||||||
|
|
||||||
|
void begin_sync(Resources &res, const State &state)
|
||||||
|
{
|
||||||
|
passes_.begin_sync(res, state);
|
||||||
|
passes_in_front_.begin_sync(res, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state)
|
||||||
|
{
|
||||||
|
T &passes = ob_ref.object->dtx & OB_DRAW_IN_FRONT ? passes_in_front_ : passes_;
|
||||||
|
passes.object_sync(ob_ref, select_id, res, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void end_sync(Resources &res, const State &state)
|
||||||
|
{
|
||||||
|
passes_.end_sync(res, state);
|
||||||
|
passes_in_front_.end_sync(res, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Resources &res, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
passes_.draw(manager, view, res.overlay_line_fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_in_front(Resources &res, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
passes_in_front_.draw(manager, view, res.overlay_line_in_front_fb);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace blender::draw::overlay
|
} // namespace blender::draw::overlay
|
||||||
|
@ -12,19 +12,20 @@ namespace blender::draw::overlay {
|
|||||||
|
|
||||||
ShaderModule *ShaderModule::g_shader_modules[2][2] = {{nullptr}};
|
ShaderModule *ShaderModule::g_shader_modules[2][2] = {{nullptr}};
|
||||||
|
|
||||||
ShaderModule::ShaderPtr ShaderModule::selectable_shader(const char *create_info_name)
|
ShaderPtr ShaderModule::selectable_shader(const char *create_info_name)
|
||||||
{
|
{
|
||||||
/* TODO: This is what it should be like with all variations defined with create infos. */
|
/* TODO: This is what it should be like with all variations defined with create infos. */
|
||||||
// std::string create_info_name = base_create_info;
|
// std::string create_info_name = base_create_info;
|
||||||
// create_info_name += SelectEngineT::shader_suffix;
|
// create_info_name += SelectEngineT::shader_suffix;
|
||||||
// create_info_name += clipping_enabled_ ? "_clipped" : "";
|
// create_info_name += ClippingEnabled ? "_clipped" : "";
|
||||||
// this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str());
|
// this->shader_ = GPU_shader_create_from_info_name(create_info_name.c_str());
|
||||||
UNUSED_VARS(clipping_enabled_);
|
|
||||||
|
|
||||||
/* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */
|
/* WORKAROUND: ... but for now, we have to patch the create info used by the old engine. */
|
||||||
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
||||||
GPU_shader_create_info_get(create_info_name));
|
GPU_shader_create_info_get(create_info_name));
|
||||||
|
|
||||||
|
info.define("OVERLAY_NEXT");
|
||||||
|
|
||||||
if (selection_type_ != SelectionType::DISABLED) {
|
if (selection_type_ != SelectionType::DISABLED) {
|
||||||
info.define("SELECT_ENABLE");
|
info.define("SELECT_ENABLE");
|
||||||
}
|
}
|
||||||
@ -33,7 +34,7 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(const char *create_info_
|
|||||||
GPU_shader_create_from_info(reinterpret_cast<const GPUShaderCreateInfo *>(&info)));
|
GPU_shader_create_from_info(reinterpret_cast<const GPUShaderCreateInfo *>(&info)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModule::ShaderPtr ShaderModule::selectable_shader(
|
ShaderPtr ShaderModule::selectable_shader(
|
||||||
const char *create_info_name, std::function<void(gpu::shader::ShaderCreateInfo &info)> patch)
|
const char *create_info_name, std::function<void(gpu::shader::ShaderCreateInfo &info)> patch)
|
||||||
{
|
{
|
||||||
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
||||||
@ -41,6 +42,8 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(
|
|||||||
|
|
||||||
patch(info);
|
patch(info);
|
||||||
|
|
||||||
|
info.define("OVERLAY_NEXT");
|
||||||
|
|
||||||
if (selection_type_ != SelectionType::DISABLED) {
|
if (selection_type_ != SelectionType::DISABLED) {
|
||||||
info.define("SELECT_ENABLE");
|
info.define("SELECT_ENABLE");
|
||||||
/* Replace additional info. */
|
/* Replace additional info. */
|
||||||
@ -75,11 +78,44 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
|||||||
|
|
||||||
extra_shape = selectable_shader("overlay_extra", [](gpu::shader::ShaderCreateInfo &info) {
|
extra_shape = selectable_shader("overlay_extra", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
info.storage_buf(0, Qualifier::READ, "ExtraInstanceData", "data_buf[]");
|
info.storage_buf(0, Qualifier::READ, "ExtraInstanceData", "data_buf[]");
|
||||||
Clément Foucault
commented
I would rename I would rename `ExtraInstanceData` to `ShapeInstanceData` so that we can use `ShapeInstanceBuf` instead of the less meaningful `ExtraInstanceBuf`.
|
|||||||
info.define("color", "data_buf[gl_InstanceID].color_");
|
info.define("color", "data_buf[gl_InstanceID]._color");
|
||||||
info.define("inst_obmat", "data_buf[gl_InstanceID].object_to_world_");
|
info.define("inst_obmat", "data_buf[gl_InstanceID].matrix");
|
||||||
info.vertex_inputs_.pop_last();
|
info.vertex_inputs_.pop_last();
|
||||||
info.vertex_inputs_.pop_last();
|
info.vertex_inputs_.pop_last();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
extra_groundline = selectable_shader(
|
||||||
|
"overlay_extra_groundline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
|
info.storage_buf(0, Qualifier::READ, "float4", "data_buf[]");
|
||||||
|
info.define("inst_pos", "data_buf[gl_InstanceID].xyz");
|
||||||
|
info.vertex_inputs_.pop_last();
|
||||||
|
/* Use the same vertex layout for all shapes. */
|
||||||
|
info.vertex_in(1, gpu::shader::Type::INT, "vclass");
|
||||||
|
});
|
||||||
|
|
||||||
|
extra_point = selectable_shader("overlay_extra_point", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
|
info.storage_buf(0, Qualifier::READ, "float4", "data_buf[]");
|
||||||
|
info.define("pos", "data_buf[gl_InstanceID].xyz");
|
||||||
|
info.vertex_inputs_.pop_last();
|
||||||
|
});
|
||||||
|
|
||||||
|
extra_line = selectable_shader("overlay_extra_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
|
info.typedef_source("overlay_shader_shared.h");
|
||||||
|
info.storage_buf(0, Qualifier::READ, "LineInstanceData", "data_buf[]");
|
||||||
|
info.push_constant(gpu::shader::Type::VEC4, "ucolor");
|
||||||
|
info.define("pos",
|
||||||
|
"(gl_VertexID == 0 ? data_buf[gl_InstanceID].start.xyz : "
|
||||||
|
"data_buf[gl_InstanceID].end.xyz)");
|
||||||
|
info.define("color", "ucolor");
|
||||||
|
info.define("colorid", "0");
|
||||||
|
info.vertex_inputs_.pop_last();
|
||||||
|
info.vertex_inputs_.pop_last();
|
||||||
|
info.vertex_inputs_.pop_last();
|
||||||
|
});
|
||||||
|
|
||||||
|
extra_grid = selectable_shader("overlay_extra_grid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
|
info.additional_info("draw_modelmat_new", "draw_resource_handle_new");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderModule &ShaderModule::module_get(SelectionType selection_type, bool clipping_enabled)
|
ShaderModule &ShaderModule::module_get(SelectionType selection_type, bool clipping_enabled)
|
||||||
|
File diff suppressed because it is too large
Load Diff
40
source/blender/draw/engines/overlay/overlay_next_speaker.hh
Normal file
40
source/blender/draw/engines/overlay/overlay_next_speaker.hh
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class SpeakerPasses : public OverlayPasses {
|
||||||
|
|
||||||
|
ExtraInstanceBuf speaker = extra_buf("speaker", shapes.speaker);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SpeakerPasses(SelectionType selection_type,
|
||||||
|
const ShapeCache &shapes,
|
||||||
|
const GlobalsUboStorage &theme_colors,
|
||||||
|
bool in_front)
|
||||||
|
: OverlayPasses("Speakers", selection_type, shapes, theme_colors, in_front){};
|
||||||
|
|
||||||
|
virtual void object_sync(const ObjectRef &ob_ref,
|
||||||
|
const select::ID select_id,
|
||||||
|
Resources &res,
|
||||||
|
const State &state) final override
|
||||||
|
{
|
||||||
|
if (ob_ref.object->type == OB_SPEAKER) {
|
||||||
|
ExtraInstanceData data(ob_ref.object, res.object_wire_color(ob_ref, state));
|
||||||
|
speaker.append(data, select_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Speaker = OverlayType<SpeakerPasses>;
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
@ -18,6 +18,7 @@ typedef enum OVERLAY_GridBits OVERLAY_GridBits;
|
|||||||
typedef struct OVERLAY_GridData OVERLAY_GridData;
|
typedef struct OVERLAY_GridData OVERLAY_GridData;
|
||||||
typedef struct ThemeColorData ThemeColorData;
|
typedef struct ThemeColorData ThemeColorData;
|
||||||
typedef struct ExtraInstanceData ExtraInstanceData;
|
typedef struct ExtraInstanceData ExtraInstanceData;
|
||||||
|
typedef struct LineInstanceData LineInstanceData;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO(fclem): Should eventually become OVERLAY_BackgroundType.
|
/* TODO(fclem): Should eventually become OVERLAY_BackgroundType.
|
||||||
@ -195,20 +196,65 @@ struct ThemeColorData {
|
|||||||
BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16)
|
BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16)
|
||||||
|
|
||||||
struct ExtraInstanceData {
|
struct ExtraInstanceData {
|
||||||
float4 color_;
|
#ifdef GPU_SHADER
|
||||||
float4x4 object_to_world_;
|
/** NOTE: The `color` token is reserved for its macro alias. */
|
||||||
|
float4 _color;
|
||||||
|
#else
|
||||||
|
float4 color;
|
||||||
|
#endif
|
||||||
|
float4x4 matrix;
|
||||||
|
|
||||||
#if !defined(GPU_SHADER) && defined(__cplusplus)
|
#if !defined(GPU_SHADER) && defined(__cplusplus)
|
||||||
ExtraInstanceData(const float4x4 &object_to_world, float4 &color, float draw_size)
|
ExtraInstanceData() = default;
|
||||||
|
|
||||||
|
ExtraInstanceData(const float4x4 &object_to_world, const float4 &color, float draw_size)
|
||||||
{
|
{
|
||||||
this->color_ = color;
|
this->color = color;
|
||||||
this->object_to_world_ = object_to_world;
|
this->matrix = object_to_world;
|
||||||
this->object_to_world_[3][3] = draw_size;
|
this->matrix[3][3] = draw_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ExtraInstanceData(const Object *object, const float4 &color)
|
||||||
|
: ExtraInstanceData(float4x4(object->object_to_world),
|
||||||
|
color,
|
||||||
|
object->type == OB_EMPTY ? object->empty_drawsize : 1.0f){};
|
||||||
|
|
||||||
|
ExtraInstanceData with_matrix(const float4x4 &matrix) const
|
||||||
|
{
|
||||||
|
ExtraInstanceData copy = *this;
|
||||||
|
copy.matrix = matrix;
|
||||||
|
copy.matrix[3][3] = this->matrix[3][3];
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraInstanceData with_color(const float4 &color) const
|
||||||
|
{
|
||||||
|
ExtraInstanceData copy = *this;
|
||||||
|
copy.color = color;
|
||||||
|
copy.matrix[3][3] = this->matrix[3][3];
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtraInstanceData with_size(const float &draw_size) const
|
||||||
|
{
|
||||||
|
ExtraInstanceData copy = *this;
|
||||||
|
copy.matrix[3][3] = draw_size;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
BLI_STATIC_ASSERT_ALIGN(ExtraInstanceData, 16)
|
BLI_STATIC_ASSERT_ALIGN(ExtraInstanceData, 16)
|
||||||
|
|
||||||
|
struct LineInstanceData {
|
||||||
|
float4 start;
|
||||||
|
float4 end;
|
||||||
|
|
||||||
|
#if !defined(GPU_SHADER) && defined(__cplusplus)
|
||||||
|
LineInstanceData(float3 start, float3 end) : start(start), end(end){};
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
BLI_STATIC_ASSERT_ALIGN(LineInstanceData, 16)
|
||||||
|
|
||||||
#ifndef GPU_SHADER
|
#ifndef GPU_SHADER
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,18 @@ vec4 color_from_id(float color_id)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
mat4 model_mat = gridModelMatrix;
|
#ifdef OVERLAY_NEXT
|
||||||
|
mat4 grid_matrix = ModelMatrix;
|
||||||
|
#else
|
||||||
|
mat4 grid_matrix = gridModelMatrix;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mat4 model_mat = grid_matrix;
|
||||||
model_mat[0][3] = model_mat[1][3] = model_mat[2][3] = 0.0;
|
model_mat[0][3] = model_mat[1][3] = model_mat[2][3] = 0.0;
|
||||||
model_mat[3][3] = 1.0;
|
model_mat[3][3] = 1.0;
|
||||||
float color_id = gridModelMatrix[3].w;
|
float color_id = grid_matrix[3].w;
|
||||||
|
|
||||||
ivec3 grid_resolution = ivec3(gridModelMatrix[0].w, gridModelMatrix[1].w, gridModelMatrix[2].w);
|
ivec3 grid_resolution = ivec3(grid_matrix[0].w, grid_matrix[1].w, grid_matrix[2].w);
|
||||||
|
|
||||||
vec3 ls_cell_location;
|
vec3 ls_cell_location;
|
||||||
/* Keep in sync with update_irradiance_probe */
|
/* Keep in sync with update_irradiance_probe */
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#ifdef OVERLAY_NEXT
|
||||||
|
vec3 world_pos = pos;
|
||||||
|
#else
|
||||||
vec3 world_pos = point_object_to_world(pos);
|
vec3 world_pos = point_object_to_world(pos);
|
||||||
|
#endif
|
||||||
gl_Position = point_world_to_ndc(world_pos);
|
gl_Position = point_world_to_ndc(world_pos);
|
||||||
|
|
||||||
gl_PointSize = sizeObjectCenter;
|
gl_PointSize = sizeObjectCenter;
|
||||||
|
@ -9,7 +9,11 @@ vec2 screen_position(vec4 p)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
#ifdef OVERLAY_NEXT
|
||||||
|
vec3 world_pos = pos;
|
||||||
|
#else
|
||||||
vec3 world_pos = point_object_to_world(pos);
|
vec3 world_pos = point_object_to_world(pos);
|
||||||
|
#endif
|
||||||
gl_Position = point_world_to_ndc(world_pos);
|
gl_Position = point_world_to_ndc(world_pos);
|
||||||
|
|
||||||
#ifdef SELECT_EDGES
|
#ifdef SELECT_EDGES
|
||||||
|
@ -69,7 +69,7 @@ struct SelectBuf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void select_bind(PassSimple &pass)
|
void select_bind(PassSimple::Sub &pass)
|
||||||
{
|
{
|
||||||
if (selection_type != SelectionType::DISABLED) {
|
if (selection_type != SelectionType::DISABLED) {
|
||||||
select_buf.push_update();
|
select_buf.push_update();
|
||||||
|
@ -615,13 +615,14 @@ void DrawMultiBuf::bind(RecordingState &state,
|
|||||||
group.start = resource_id_count_;
|
group.start = resource_id_count_;
|
||||||
resource_id_count_ += group.len * view_len;
|
resource_id_count_ += group.len * view_len;
|
||||||
|
|
||||||
int batch_inst_len;
|
int batch_vert_len, batch_vert_first, batch_base_index, batch_inst_len;
|
||||||
/* Now that GPUBatches are guaranteed to be finished, extract their parameters. */
|
/* Now that GPUBatches are guaranteed to be finished, extract their parameters. */
|
||||||
GPU_batch_draw_parameter_get(group.gpu_batch,
|
GPU_batch_draw_parameter_get(
|
||||||
&group.vertex_len,
|
group.gpu_batch, &batch_vert_len, &batch_vert_first, &batch_base_index, &batch_inst_len);
|
||||||
&group.vertex_first,
|
|
||||||
&group.base_index,
|
group.vertex_len = group.vertex_len == -1 ? batch_vert_len : group.vertex_len;
|
||||||
&batch_inst_len);
|
group.vertex_first = group.vertex_first == -1 ? batch_vert_first : group.vertex_first;
|
||||||
|
group.base_index = batch_base_index;
|
||||||
|
|
||||||
/* Instancing attributes are not supported using the new pipeline since we use the base
|
/* Instancing attributes are not supported using the new pipeline since we use the base
|
||||||
* instance to set the correct resource_id. Workaround is a storage_buf + gl_InstanceID. */
|
* instance to set the correct resource_id. Workaround is a storage_buf + gl_InstanceID. */
|
||||||
|
Loading…
Reference in New Issue
Block a user
Unwanted change