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": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
|
||||
({"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": "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
|
||||
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
class Empties {
|
||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
class EmptyPassesBase : public OverlayPasses {
|
||||
|
||||
private:
|
||||
const SelectionType selection_type_;
|
||||
|
||||
PassSimple empty_ps_ = {"Empties"};
|
||||
PassSimple empty_in_front_ps_ = {"Empties_In_front"};
|
||||
|
||||
struct CallBuffers {
|
||||
const SelectionType selection_type_;
|
||||
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_}};
|
||||
ExtraInstanceBuf plain_axes = extra_buf("plain_axes", shapes.plain_axes);
|
||||
ExtraInstanceBuf single_arrow = extra_buf("single_arrow", shapes.single_arrow);
|
||||
ExtraInstanceBuf arrows = extra_buf("arrows", shapes.arrows);
|
||||
ExtraInstanceBuf image = extra_buf("image", shapes.quad_wire);
|
||||
ExtraInstanceBuf circle = extra_buf("circle", shapes.circle);
|
||||
ExtraInstanceBuf cube = extra_buf("cube", shapes.empty_cube);
|
||||
ExtraInstanceBuf sphere = extra_buf("sphere", shapes.empty_sphere);
|
||||
ExtraInstanceBuf cone = extra_buf("cone", shapes.empty_cone);
|
||||
|
||||
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++) {
|
||||
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) {
|
||||
switch (empty_drawtype) {
|
||||
case OB_PLAINAXES:
|
||||
call_bufs.plain_axes_buf.append(data, select_id);
|
||||
break;
|
||||
return plain_axes;
|
||||
case OB_SINGLE_ARROW:
|
||||
call_bufs.single_arrow_buf.append(data, select_id);
|
||||
break;
|
||||
return single_arrow;
|
||||
case OB_CUBE:
|
||||
call_bufs.cube_buf.append(data, select_id);
|
||||
break;
|
||||
return cube;
|
||||
case OB_CIRCLE:
|
||||
call_bufs.circle_buf.append(data, select_id);
|
||||
break;
|
||||
return circle;
|
||||
case OB_EMPTY_SPHERE:
|
||||
call_bufs.sphere_buf.append(data, select_id);
|
||||
break;
|
||||
return sphere;
|
||||
case OB_EMPTY_CONE:
|
||||
call_bufs.cone_buf.append(data, select_id);
|
||||
break;
|
||||
return cone;
|
||||
case OB_ARROWS:
|
||||
call_bufs.arrows_buf.append(data, select_id);
|
||||
break;
|
||||
return arrows;
|
||||
case OB_EMPTY_IMAGE:
|
||||
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
|
||||
call_bufs.image_buf.append(data, select_id);
|
||||
break;
|
||||
return image;
|
||||
default:
|
||||
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
|
||||
|
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_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 {
|
||||
|
||||
void Instance::init()
|
||||
@ -22,6 +30,7 @@ void Instance::init()
|
||||
BKE_view_layer_synced_ensure(ctx->scene, ctx->view_layer);
|
||||
|
||||
state.depsgraph = ctx->depsgraph;
|
||||
state.manager = DRW_manager_get();
|
||||
state.view_layer = ctx->view_layer;
|
||||
state.scene = ctx->scene;
|
||||
state.v3d = ctx->v3d;
|
||||
@ -30,6 +39,7 @@ void Instance::init()
|
||||
state.object_mode = ctx->object_mode;
|
||||
|
||||
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.space_type = state.v3d != nullptr ? SPACE_VIEW3D : eSpace_Type(ctx->space_data->spacetype);
|
||||
if (state.v3d != nullptr) {
|
||||
@ -75,9 +85,18 @@ void Instance::begin_sync()
|
||||
|
||||
background.begin_sync(resources, state);
|
||||
prepass.begin_sync(resources, state);
|
||||
empties.begin_sync();
|
||||
metaballs.begin_sync();
|
||||
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)
|
||||
@ -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 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) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_MESH:
|
||||
@ -92,7 +117,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
case OB_CURVES:
|
||||
case OB_FONT:
|
||||
case OB_CURVES_LEGACY:
|
||||
prepass.object_sync(manager, ob_ref, resources);
|
||||
prepass.object_sync(manager, ob_ref, select_id, resources);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -121,19 +146,36 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
|
||||
if (!state.hide_overlays) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_EMPTY:
|
||||
empties.object_sync(ob_ref, resources, state);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
break;
|
||||
case OB_MBALL:
|
||||
if (!in_edit_mode) {
|
||||
metaballs.object_sync(ob_ref, resources, state);
|
||||
}
|
||||
case OB_CAMERA:
|
||||
cameras.object_sync(ob_ref, select_id, resources, state);
|
||||
break;
|
||||
case OB_EMPTY:
|
||||
empties.object_sync(ob_ref, select_id, resources, state);
|
||||
break;
|
||||
case OB_GPENCIL_LEGACY:
|
||||
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();
|
||||
|
||||
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)
|
||||
@ -157,7 +208,7 @@ void Instance::draw(Manager &manager)
|
||||
const DRWView *view_legacy = DRW_view_default_get();
|
||||
View view("OverlayView", view_legacy);
|
||||
|
||||
/* TODO: Better semantics using a switch? */
|
||||
/* TODO: Better semantical switch? */
|
||||
if (!resources.color_overlay_tx.is_valid()) {
|
||||
/* Likely to be the selection case. Allocate dummy texture and bind only depth buffer. */
|
||||
resources.line_tx.acquire(int2(1, 1), GPU_RGBA8);
|
||||
@ -207,13 +258,31 @@ void Instance::draw(Manager &manager)
|
||||
|
||||
background.draw(resources, manager);
|
||||
|
||||
empties.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);
|
||||
|
||||
empties.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);
|
||||
|
||||
|
@ -11,11 +11,23 @@
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
#include "overlay_next_background.hh"
|
||||
#include "overlay_next_empty.hh"
|
||||
#include "overlay_next_grid.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_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 {
|
||||
|
||||
/**
|
||||
@ -40,8 +52,17 @@ class Instance {
|
||||
Background background;
|
||||
Prepass prepass;
|
||||
Metaballs metaballs = {selection_type_};
|
||||
Empties empties = {selection_type_};
|
||||
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){};
|
||||
|
||||
|
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>;
|
||||
|
||||
private:
|
||||
const SelectionType selection_type_;
|
||||
|
||||
PassSimple metaball_ps_ = {"MetaBalls"};
|
||||
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
|
||||
|
||||
SphereOutlineInstanceBuf circle_buf_ = {selection_type_, "metaball_data_buf"};
|
||||
SphereOutlineInstanceBuf circle_in_front_buf_ = {selection_type_, "metaball_data_buf"};
|
||||
SphereOutlineInstanceBuf circle_buf_;
|
||||
SphereOutlineInstanceBuf circle_in_front_buf_;
|
||||
|
||||
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()
|
||||
{
|
||||
@ -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 ?
|
||||
circle_in_front_buf_ :
|
||||
@ -72,7 +75,6 @@ class Metaballs {
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
|
||||
const float4 &color = res.object_wire_color(ob_ref, state);
|
||||
const select::ID select_id = res.select_id(ob_ref);
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
|
||||
/* 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_);
|
||||
}
|
||||
|
||||
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_ :
|
||||
prepass_ps_;
|
||||
@ -43,7 +46,7 @@ class Prepass {
|
||||
GPUBatch *geom = DRW_cache_object_surface_get(ob_ref.object);
|
||||
if (geom) {
|
||||
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 {
|
||||
Depsgraph *depsgraph;
|
||||
Manager *manager;
|
||||
const ViewLayer *view_layer;
|
||||
const Scene *scene;
|
||||
const View3D *v3d;
|
||||
@ -40,6 +41,7 @@ struct State {
|
||||
const Base *active_base;
|
||||
View3DOverlay overlay;
|
||||
float pixelsize;
|
||||
SelectionType selection_type;
|
||||
enum eSpace_Type space_type;
|
||||
enum eContextObjectMode ctx_mode;
|
||||
enum eObjectMode object_mode;
|
||||
@ -56,46 +58,88 @@ struct 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.
|
||||
*/
|
||||
class ShapeCache {
|
||||
private:
|
||||
struct BatchDeleter {
|
||||
void operator()(GPUBatch *shader)
|
||||
{
|
||||
GPU_BATCH_DISCARD_SAFE(shader);
|
||||
}
|
||||
};
|
||||
using BatchPtr = std::unique_ptr<GPUBatch, BatchDeleter>;
|
||||
|
||||
public:
|
||||
BatchPtr quad_wire;
|
||||
// GPUBatch *drw_normal_arrow; /* Single Arrow? */
|
||||
BatchPtr plain_axes;
|
||||
BatchPtr single_arrow;
|
||||
BatchPtr cube;
|
||||
BatchPtr arrows;
|
||||
BatchPtr quad_wire;
|
||||
BatchPtr circle;
|
||||
BatchPtr empty_cube;
|
||||
BatchPtr empty_sphere;
|
||||
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 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();
|
||||
};
|
||||
|
||||
struct ShaderDeleter {
|
||||
void operator()(GPUShader *shader)
|
||||
{
|
||||
DRW_SHADER_FREE_SAFE(shader);
|
||||
}
|
||||
};
|
||||
|
||||
using ShaderPtr = std::unique_ptr<GPUShader, ShaderDeleter>;
|
||||
|
||||
/**
|
||||
* Shader module. Shared between instances.
|
||||
*/
|
||||
class ShaderModule {
|
||||
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. */
|
||||
static ShaderModule *g_shader_modules[2 /*Selection Instance*/][2 /*Clipping Enabled*/];
|
||||
|
||||
@ -115,6 +159,16 @@ class ShaderModule {
|
||||
ShaderPtr depth_mesh;
|
||||
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);
|
||||
|
||||
/** Module */
|
||||
@ -230,12 +284,25 @@ struct Resources : public select::SelectMap {
|
||||
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
||||
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.
|
||||
*/
|
||||
template<typename InstanceDataT> struct ShapeInstanceBuf : private select::SelectBuf {
|
||||
template<typename InstanceDataT> struct ShapeInstanceBuf : protected select::SelectBuf {
|
||||
|
||||
StorageVectorBuffer<InstanceDataT> data_buf;
|
||||
|
||||
@ -254,7 +321,7 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
||||
data_buf.append(data);
|
||||
}
|
||||
|
||||
void end_sync(PassSimple &pass, GPUBatch *shape)
|
||||
void end_sync(PassSimple::Sub &pass, GPUBatch *shape)
|
||||
{
|
||||
if (data_buf.size() == 0) {
|
||||
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
|
||||
|
@ -12,19 +12,20 @@ namespace blender::draw::overlay {
|
||||
|
||||
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. */
|
||||
// std::string create_info_name = base_create_info;
|
||||
// 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());
|
||||
UNUSED_VARS(clipping_enabled_);
|
||||
|
||||
/* 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_create_info_get(create_info_name));
|
||||
|
||||
info.define("OVERLAY_NEXT");
|
||||
|
||||
if (selection_type_ != SelectionType::DISABLED) {
|
||||
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)));
|
||||
}
|
||||
|
||||
ShaderModule::ShaderPtr ShaderModule::selectable_shader(
|
||||
ShaderPtr ShaderModule::selectable_shader(
|
||||
const char *create_info_name, std::function<void(gpu::shader::ShaderCreateInfo &info)> patch)
|
||||
{
|
||||
gpu::shader::ShaderCreateInfo info = *reinterpret_cast<const gpu::shader::ShaderCreateInfo *>(
|
||||
@ -41,6 +42,8 @@ ShaderModule::ShaderPtr ShaderModule::selectable_shader(
|
||||
|
||||
patch(info);
|
||||
|
||||
info.define("OVERLAY_NEXT");
|
||||
|
||||
if (selection_type_ != SelectionType::DISABLED) {
|
||||
info.define("SELECT_ENABLE");
|
||||
/* 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) {
|
||||
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("inst_obmat", "data_buf[gl_InstanceID].object_to_world_");
|
||||
info.define("color", "data_buf[gl_InstanceID]._color");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID].matrix");
|
||||
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)
|
||||
|
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 ThemeColorData ThemeColorData;
|
||||
typedef struct ExtraInstanceData ExtraInstanceData;
|
||||
typedef struct LineInstanceData LineInstanceData;
|
||||
#endif
|
||||
|
||||
/* TODO(fclem): Should eventually become OVERLAY_BackgroundType.
|
||||
@ -195,20 +196,65 @@ struct ThemeColorData {
|
||||
BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16)
|
||||
|
||||
struct ExtraInstanceData {
|
||||
float4 color_;
|
||||
float4x4 object_to_world_;
|
||||
#ifdef GPU_SHADER
|
||||
/** NOTE: The `color` token is reserved for its macro alias. */
|
||||
float4 _color;
|
||||
#else
|
||||
float4 color;
|
||||
#endif
|
||||
float4x4 matrix;
|
||||
|
||||
#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->object_to_world_ = object_to_world;
|
||||
this->object_to_world_[3][3] = draw_size;
|
||||
this->color = color;
|
||||
this->matrix = object_to_world;
|
||||
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
|
||||
};
|
||||
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
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
@ -24,12 +24,18 @@ vec4 color_from_id(float color_id)
|
||||
|
||||
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[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;
|
||||
/* Keep in sync with update_irradiance_probe */
|
||||
|
@ -4,7 +4,11 @@
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef OVERLAY_NEXT
|
||||
vec3 world_pos = pos;
|
||||
#else
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
#endif
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
|
||||
gl_PointSize = sizeObjectCenter;
|
||||
|
@ -9,7 +9,11 @@ vec2 screen_position(vec4 p)
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef OVERLAY_NEXT
|
||||
vec3 world_pos = pos;
|
||||
#else
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
#endif
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
|
||||
#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) {
|
||||
select_buf.push_update();
|
||||
|
@ -615,13 +615,14 @@ void DrawMultiBuf::bind(RecordingState &state,
|
||||
group.start = resource_id_count_;
|
||||
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. */
|
||||
GPU_batch_draw_parameter_get(group.gpu_batch,
|
||||
&group.vertex_len,
|
||||
&group.vertex_first,
|
||||
&group.base_index,
|
||||
&batch_inst_len);
|
||||
GPU_batch_draw_parameter_get(
|
||||
group.gpu_batch, &batch_vert_len, &batch_vert_first, &batch_base_index, &batch_inst_len);
|
||||
|
||||
group.vertex_len = group.vertex_len == -1 ? batch_vert_len : group.vertex_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
|
||||
* instance to set the correct resource_id. Workaround is a storage_buf + gl_InstanceID. */
|
||||
|
Loading…
Reference in New Issue
Block a user
Unwanted change