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:
committed by
Clément Foucault
parent
811c1d50f3
commit
94ea25ba09
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
197
source/blender/draw/engines/overlay/overlay_next_light.hh
Normal file
197
source/blender/draw/engines/overlay/overlay_next_light.hh
Normal 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
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user