Overlay-Next: Light

Overlay-Next version of light.

Rel #102179

#109059 was used as a reference.

Pull Request: https://projects.blender.org/blender/blender/pulls/123848
This commit is contained in:
Laurynas Duburas
2024-07-30 17:37:42 +02:00
committed by Clément Foucault
parent 811c1d50f3
commit 94ea25ba09
10 changed files with 446 additions and 8 deletions

View File

@@ -294,6 +294,7 @@ set(SRC
engines/overlay/overlay_next_grid.hh
engines/overlay/overlay_next_instance.hh
engines/overlay/overlay_next_lattice.hh
engines/overlay/overlay_next_light.hh
engines/overlay/overlay_next_metaball.hh
engines/overlay/overlay_next_prepass.hh
engines/overlay/overlay_next_private.hh

View File

@@ -80,6 +80,11 @@ void Instance::begin_sync()
prepass.begin_sync(resources, state);
empties.begin_sync();
lattices.begin_sync(resources, state);
auto begin_sync_layer = [&](OverlayLayer &layer) { layer.lights.begin_sync(); };
begin_sync_layer(regular);
begin_sync_layer(infront);
metaballs.begin_sync();
speakers.begin_sync();
grid.begin_sync(resources, state, view);
@@ -90,6 +95,8 @@ 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 */
OverlayLayer &layer = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) ? infront : regular;
if (needs_prepass) {
switch (ob_ref.object->type) {
case OB_MESH:
@@ -137,6 +144,9 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
lattices.object_sync(manager, ob_ref, resources, state);
}
break;
case OB_LAMP:
layer.lights.object_sync(ob_ref, resources, state);
break;
case OB_MBALL:
if (!in_edit_mode) {
metaballs.object_sync(ob_ref, resources, state);
@@ -155,6 +165,12 @@ void Instance::end_sync()
{
resources.end_sync();
auto end_sync_layer = [&](OverlayLayer &layer) {
layer.lights.end_sync(resources, shapes, state);
};
end_sync_layer(regular);
end_sync_layer(infront);
metaballs.end_sync(resources, shapes, state);
empties.end_sync(resources, shapes, state);
speakers.end_sync(resources, shapes, state);
@@ -222,6 +238,7 @@ void Instance::draw(Manager &manager)
background.draw(resources, manager);
regular.lights.draw(resources.overlay_line_fb, manager, view);
empties.draw(resources, manager, view);
lattices.draw(resources, manager, view);
metaballs.draw(resources, manager, view);
@@ -230,7 +247,8 @@ void Instance::draw(Manager &manager)
grid.draw(resources, manager, view);
empties.draw_in_front(resources, manager, view);
lattices.draw_in_front(resources, manager, view);
/* TODO(: Breaks selection on M1 Max. */
// lattices.draw_in_front(resources, manager, view);
metaballs.draw_in_front(resources, manager, view);
speakers.draw_in_front(resources, manager, view);

View File

@@ -14,6 +14,7 @@
#include "overlay_next_empty.hh"
#include "overlay_next_grid.hh"
#include "overlay_next_lattice.hh"
#include "overlay_next_light.hh"
#include "overlay_next_metaball.hh"
#include "overlay_next_prepass.hh"
#include "overlay_next_speaker.hh"
@@ -41,6 +42,13 @@ class Instance {
/** Overlay types. */
Background background;
Prepass prepass;
struct OverlayLayer {
const SelectionType selection_type_;
Lights lights = {selection_type_};
} regular{selection_type_}, infront{selection_type_};
Metaballs metaballs = {selection_type_};
Empties empties = {selection_type_};
Lattices lattices;

View File

@@ -0,0 +1,197 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#pragma once
#include "overlay_next_private.hh"
namespace blender::draw::overlay {
class Lights {
using LightInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
using GroundLineInstanceBuf = ShapeInstanceBuf<float4>;
private:
const SelectionType selection_type_;
PassSimple ps_ = {"Lights"};
struct CallBuffers {
const SelectionType selection_type_;
GroundLineInstanceBuf ground_line_buf = {selection_type_, "ground_line_buf"};
LightInstanceBuf icon_inner_buf = {selection_type_, "icon_inner_buf"};
LightInstanceBuf icon_outer_buf = {selection_type_, "icon_outer_buf"};
LightInstanceBuf icon_sun_rays_buf = {selection_type_, "icon_sun_rays_buf"};
LightInstanceBuf point_buf = {selection_type_, "point_buf"};
LightInstanceBuf sun_buf = {selection_type_, "sun_buf"};
LightInstanceBuf spot_buf = {selection_type_, "spot_buf"};
LightInstanceBuf spot_cone_back_buf = {selection_type_, "spot_cone_back_buf"};
LightInstanceBuf spot_cone_front_buf = {selection_type_, "spot_cone_front_buf"};
LightInstanceBuf area_disk_buf = {selection_type_, "area_disk_buf"};
LightInstanceBuf area_square_buf = {selection_type_, "area_square_buf"};
} call_buffers_{selection_type_};
public:
Lights(const SelectionType selection_type) : selection_type_(selection_type){};
void begin_sync()
{
call_buffers_.ground_line_buf.clear();
call_buffers_.icon_inner_buf.clear();
call_buffers_.icon_outer_buf.clear();
call_buffers_.icon_sun_rays_buf.clear();
call_buffers_.point_buf.clear();
call_buffers_.sun_buf.clear();
call_buffers_.spot_buf.clear();
call_buffers_.spot_cone_back_buf.clear();
call_buffers_.spot_cone_front_buf.clear();
call_buffers_.area_disk_buf.clear();
call_buffers_.area_square_buf.clear();
}
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
{
ExtraInstanceData data(ob_ref.object->object_to_world(),
float4{res.object_wire_color(ob_ref, state).xyz(), 1.0f},
1.0f);
float4 &theme_color = data.color_;
/* Pack render data into object matrix. */
float4x4 &matrix = data.object_to_world_;
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;
const Light &la = *static_cast<Light *>(ob_ref.object->data);
const select::ID select_id = res.select_id(ob_ref);
/* 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;
call_buffers_.ground_line_buf.append(float4(matrix.location()), select_id);
const float4 light_color = {la.r, la.g, la.b, 1.0f};
const bool show_light_colors = state.overlay.flag & V3D_OVERLAY_SHOW_LIGHT_COLORS;
/* Draw the outer ring of the light icon and the sun rays in `light_color`, if required. */
call_buffers_.icon_outer_buf.append(data, select_id);
call_buffers_.icon_inner_buf.append(show_light_colors ? data.with_color(light_color) : data,
select_id);
switch (la.type) {
case LA_LOCAL:
area_size_x = area_size_y = la.radius;
call_buffers_.point_buf.append(data, select_id);
break;
case LA_SUN:
call_buffers_.sun_buf.append(data, select_id);
call_buffers_.icon_sun_rays_buf.append(
show_light_colors ? data.with_color(light_color) : data, select_id);
break;
case 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) */
rescale_m4(matrix.ptr(), float3{10.0f, 10.0f, 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. */
const float a = cosf(la.spotsize * 0.5f);
const float b = la.spotblend;
const float c = a * b - a - b;
const float a2 = a * a;
const 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. */
theme_color[3] = -max_ff(la.radius, FLT_MIN);
call_buffers_.spot_buf.append(data, select_id);
if ((la.mode & LA_SHOW_CONE) && !DRW_state_is_select()) {
const float4 color_inside{0.0f, 0.0f, 0.0f, 0.5f};
const float4 color_outside{1.0f, 1.0f, 1.0f, 0.3f};
call_buffers_.spot_cone_front_buf.append(data.with_color(color_inside), select_id);
call_buffers_.spot_cone_back_buf.append(data.with_color(color_outside), select_id);
}
break;
}
case LA_AREA:
const bool uniform_scale = !ELEM(la.area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE);
LightInstanceBuf &area_buf = ELEM(la.area_shape, LA_AREA_SQUARE, LA_AREA_RECT) ?
call_buffers_.area_square_buf :
call_buffers_.area_disk_buf;
area_size_x = la.area_size;
area_size_y = uniform_scale ? la.area_size : la.area_sizey;
area_buf.append(data, select_id);
break;
}
}
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
{
const DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
DRW_STATE_DEPTH_LESS_EQUAL | state.clipping_state;
ps_.init();
res.select_bind(ps_);
{
PassSimple::Sub &sub_pass = ps_.sub("spot_cone_front");
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_FRONT |
state.clipping_state);
sub_pass.shader_set(res.shaders.extra_shape.get());
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
call_buffers_.spot_cone_front_buf.end_sync(sub_pass, shapes.light_spot_volume.get());
}
{
PassSimple::Sub &sub_pass = ps_.sub("spot_cone_back");
sub_pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK | state.clipping_state);
sub_pass.shader_set(res.shaders.extra_shape.get());
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
call_buffers_.spot_cone_back_buf.end_sync(sub_pass, shapes.light_spot_volume.get());
}
{
PassSimple::Sub &sub_pass = ps_.sub("light_shapes");
sub_pass.state_set(pass_state);
sub_pass.shader_set(res.shaders.extra_shape.get());
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
call_buffers_.icon_inner_buf.end_sync(sub_pass, shapes.light_icon_outer_lines.get());
call_buffers_.icon_outer_buf.end_sync(sub_pass, shapes.light_icon_inner_lines.get());
call_buffers_.icon_sun_rays_buf.end_sync(sub_pass, shapes.light_icon_sun_rays.get());
call_buffers_.point_buf.end_sync(sub_pass, shapes.light_point_lines.get());
call_buffers_.sun_buf.end_sync(sub_pass, shapes.light_sun_lines.get());
call_buffers_.spot_buf.end_sync(sub_pass, shapes.light_spot_lines.get());
call_buffers_.area_disk_buf.end_sync(sub_pass, shapes.light_area_disk_lines.get());
call_buffers_.area_square_buf.end_sync(sub_pass, shapes.light_area_square_lines.get());
}
{
PassSimple::Sub &sub_pass = ps_.sub("ground_line");
sub_pass.state_set(pass_state | DRW_STATE_BLEND_ALPHA);
sub_pass.shader_set(res.shaders.extra_ground_line.get());
sub_pass.bind_ubo("globalsBlock", &res.globals_buf);
call_buffers_.ground_line_buf.end_sync(sub_pass, shapes.ground_line.get());
}
}
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
{
GPU_framebuffer_bind(framebuffer);
manager.submit(ps_, view);
}
};
} // namespace blender::draw::overlay

View File

@@ -84,6 +84,18 @@ class ShapeCache {
BatchPtr speaker;
BatchPtr ground_line;
BatchPtr light_icon_outer_lines;
BatchPtr light_icon_inner_lines;
BatchPtr light_icon_sun_rays;
BatchPtr light_point_lines;
BatchPtr light_sun_lines;
BatchPtr light_spot_lines;
BatchPtr light_area_disk_lines;
BatchPtr light_area_square_lines;
BatchPtr light_spot_volume;
ShapeCache();
};
@@ -119,6 +131,7 @@ class ShaderModule {
ShaderPtr depth_mesh;
ShaderPtr extra_shape;
ShaderPtr extra_wire_object;
ShaderPtr extra_ground_line;
ShaderPtr lattice_points;
ShaderPtr lattice_wire;
@@ -262,7 +275,7 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
data_buf.append(data);
}
void end_sync(PassSimple &pass, gpu::Batch *shape)
void end_sync(PassSimple::Sub &pass, gpu::Batch *shape)
{
if (data_buf.is_empty()) {
return;

View File

@@ -89,18 +89,27 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
info.additional_info(
"draw_view", "draw_modelmat_new", "draw_resource_handle_new", "draw_globals");
});
lattice_points = selectable_shader(
"overlay_edit_lattice_point", [](gpu::shader::ShaderCreateInfo &info) {
info.additional_infos_.clear();
info.additional_info(
"draw_view", "draw_modelmat_new", "draw_resource_handle_new", "draw_globals");
});
lattice_wire = selectable_shader(
"overlay_edit_lattice_wire", [](gpu::shader::ShaderCreateInfo &info) {
info.additional_infos_.clear();
info.additional_info(
"draw_view", "draw_modelmat_new", "draw_resource_handle_new", "draw_globals");
});
extra_ground_line = selectable_shader(
"overlay_extra_groundline", [](gpu::shader::ShaderCreateInfo &info) {
info.storage_buf(0, Qualifier::READ, "vec4", "data_buf[]");
info.define("inst_pos", "data_buf[gl_InstanceID].xyz");
info.vertex_inputs_.pop_last();
});
}
ShaderModule &ShaderModule::module_get(SelectionType selection_type, bool clipping_enabled)

View File

@@ -52,6 +52,11 @@ enum VertexClass {
VCLASS_EMPTY_SIZE = 1 << 14,
};
static constexpr int diamond_nsegments = 4;
static constexpr int inner_nsegments = 8;
static constexpr int outer_nsegments = 10;
static constexpr int circle_nsegments = 32;
static constexpr float bone_box_verts[8][3] = {
{1.0f, 0.0f, 1.0f},
{1.0f, 0.0f, -1.0f},
@@ -67,12 +72,43 @@ static constexpr std::array<uint, 24> bone_box_wire = {
0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7,
};
static void append_line_loop(
Vector<Vertex> &dest, Span<float2> verts, float z, int flag, bool dashed = false)
{
const int step = dashed ? 2 : 1;
for (int i : IndexRange(verts.size() / step)) {
for (int j : IndexRange(2)) {
float2 cv = verts[(i * step + j) % (verts.size())];
dest.append({{cv[0], cv[1], z}, flag});
}
}
}
static float light_distance_z_get(char axis, const bool start)
{
switch (axis) {
case 'x': /* - X */
return start ? 0.4f : 0.3f;
case 'X': /* + X */
return start ? 0.6f : 0.7f;
case 'y': /* - Y */
return start ? 1.4f : 1.3f;
case 'Y': /* + Y */
return start ? 1.6f : 1.7f;
case 'z': /* - Z */
return start ? 2.4f : 2.3f;
case 'Z': /* + Z */
return start ? 2.6f : 2.7f;
}
return 0.0;
}
/* A single ring of vertices. */
static Vector<float2> ring_vertices(const float radius, const int segments)
{
Vector<float2> verts;
for (int i : IndexRange(segments)) {
float angle = (2 * M_PI * i) / segments;
float angle = (2 * math::numbers::pi * i) / segments;
verts.append(radius * float2(math::cos(angle), math::sin(angle)));
}
return verts;
@@ -105,6 +141,17 @@ static Vector<Vertex> sphere_axes_circles(const float radius,
return verts;
}
static void light_append_direction_line(Vector<Vertex> &verts)
{
const Vector<float2> diamond = ring_vertices(1.2f, diamond_nsegments);
const float zsta = light_distance_z_get('z', true);
const float zend = light_distance_z_get('z', false);
verts.append({{0.0, 0.0, zsta}, VCLASS_LIGHT_DIST});
verts.append({{0.0, 0.0, zend}, VCLASS_LIGHT_DIST});
append_line_loop(verts, diamond, zsta, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
append_line_loop(verts, diamond, zend, VCLASS_LIGHT_DIST | VCLASS_SCREENSPACE);
}
ShapeCache::ShapeCache()
{
/* quad_wire */
@@ -318,7 +365,7 @@ ShapeCache::ShapeCache()
};
/* speaker */
{
const int segments = 16;
constexpr int segments = 16;
Vector<Vertex> verts;
for (int j = 0; j < 3; j++) {
@@ -328,8 +375,8 @@ ShapeCache::ShapeCache()
verts.append({{r, 0.0f, z}});
for (int i = 1; i < segments; i++) {
float x = cosf(2.0f * float(M_PI) * i / segments) * r;
float y = sinf(2.0f * float(M_PI) * i / segments) * r;
float x = cosf(2.0f * math::numbers::pi * i / segments) * r;
float y = sinf(2.0f * math::numbers::pi * i / segments) * r;
Vertex v{{x, y, z}};
verts.append(v);
verts.append(v);
@@ -358,6 +405,141 @@ ShapeCache::ShapeCache()
speaker = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* ground line */
{
const Vector<float2> ring = ring_vertices(1.35f, diamond_nsegments);
Vector<Vertex> verts;
/* Ground Point */
append_line_loop(verts, ring, 0.0f, 0);
/* Ground Line */
verts.append({{0.0, 0.0, 1.0}, 0});
verts.append({{0.0, 0.0, 0.0}, 0});
ground_line = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light spot volume */
{
Vector<Vertex> verts;
/* Cone apex */
verts.append({{0.0f, 0.0f, 0.0f}, 0});
/* Cone silhouette */
for (const int angle_i : IndexRange(circle_nsegments + 1)) {
const float angle = (2.0f * math::numbers::pi * angle_i) / circle_nsegments;
const float s = sinf(-angle);
const float c = cosf(-angle);
verts.append({{s, c, -1.0f}, VCLASS_LIGHT_SPOT_SHAPE});
}
light_spot_volume = BatchPtr(GPU_batch_create_ex(
GPU_PRIM_TRI_FAN, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light icon outer lines */
{
constexpr float r = 9.0f;
const Vector<float2> ring = ring_vertices(r * 1.33f, outer_nsegments * 2);
Vector<Vertex> verts;
append_line_loop(verts, ring, 0.0f, VCLASS_SCREENSPACE, true);
light_icon_outer_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light icon inner lines */
{
constexpr float r = 9.0f;
const Vector<float2> diamond = ring_vertices(r * 0.3f, diamond_nsegments);
const Vector<float2> ring = ring_vertices(r, inner_nsegments * 2);
Vector<Vertex> verts;
append_line_loop(verts, diamond, 0.0f, VCLASS_SCREENSPACE);
append_line_loop(verts, ring, 0.0f, VCLASS_SCREENSPACE, true);
light_icon_inner_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light icon sun rays */
{
constexpr int num_rays = 8;
constexpr float r = 9.0f;
const Vector<float2> ring = ring_vertices(r, num_rays);
const std::array<float, 4> scales{1.6f, 1.9f, 2.2f, 2.5f};
Vector<Vertex> verts;
for (const float2 &point : ring) {
for (float scale : scales) {
float2 scaled = point * scale;
verts.append({{scaled.x, scaled.y, 0.0f}, VCLASS_SCREENSPACE});
}
}
light_icon_sun_rays = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light point lines */
{
const Vector<float2> ring = ring_vertices(1.0f, circle_nsegments);
Vector<Vertex> verts;
append_line_loop(verts, ring, 0.0f, VCLASS_SCREENALIGNED | VCLASS_LIGHT_AREA_SHAPE);
light_point_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light sun lines */
{
Vector<Vertex> verts;
/* Direction Line */
verts.append({{0.0, 0.0, 0.0}, 0});
verts.append({{0.0, 0.0, -20.0}, 0}); /* Good default. */
light_sun_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light spot lines */
{
const Vector<float2> ring = ring_vertices(1.0f, circle_nsegments);
Vector<Vertex> verts;
/* Light area */
append_line_loop(verts, ring, 0.0f, VCLASS_SCREENALIGNED | VCLASS_LIGHT_AREA_SHAPE);
/* Cone cap */
append_line_loop(verts, ring, 0.0f, VCLASS_LIGHT_SPOT_SHAPE);
append_line_loop(verts, ring, 0.0f, VCLASS_LIGHT_SPOT_SHAPE | VCLASS_LIGHT_SPOT_BLEND);
/* Cone silhouette */
for (const float2 &point : ring) {
verts.append({{0.0f, 0.0f, 0.0f}, 0});
verts.append({{point.x, point.y, -1.0f}, VCLASS_LIGHT_SPOT_SHAPE | VCLASS_LIGHT_SPOT_CONE});
}
light_append_direction_line(verts);
light_spot_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light area disk lines */
{
const Vector<float2> ring = ring_vertices(0.5f, circle_nsegments);
Vector<Vertex> verts;
/* Light area */
append_line_loop(verts, ring, 0.0f, VCLASS_LIGHT_AREA_SHAPE);
light_append_direction_line(verts);
light_area_disk_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
/* light area square lines */
{
const Array<float2> rect{{-0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f}, {0.5f, -0.5f}};
Vector<Vertex> verts;
/* Light area */
append_line_loop(verts, rect, 0.0f, VCLASS_LIGHT_AREA_SHAPE);
light_append_direction_line(verts);
light_area_square_lines = BatchPtr(
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
}
}
} // namespace blender::draw::overlay

View File

@@ -213,12 +213,20 @@ struct ExtraInstanceData {
float4x4 object_to_world_;
#if !defined(GPU_SHADER) && defined(__cplusplus)
ExtraInstanceData(const float4x4 &object_to_world, float4 &color, float draw_size)
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;
};
ExtraInstanceData with_color(const float4 &color) const
{
ExtraInstanceData copy = *this;
copy.color_ = color;
return copy;
}
#endif
};
BLI_STATIC_ASSERT_ALIGN(ExtraInstanceData, 16)

View File

@@ -4,9 +4,11 @@
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(select_lib.glsl)
void main()
{
select_id_set(in_select_buf[gl_InstanceID]);
finalColor = colorLight;
/* Relative to DPI scaling. Have constant screen size. */

View File

@@ -70,7 +70,7 @@ struct SelectBuf {
}
}
void select_bind(PassSimple &pass)
void select_bind(PassSimple::Sub &pass)
{
if (selection_type != SelectionType::DISABLED) {
select_buf.push_update();