2023-08-24 10:54:59 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2019-2023 Blender Authors
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2025-09-25 10:57:02 +02:00
|
|
|
#include "infos/overlay_extra_infos.hh"
|
2025-02-24 16:17:18 +01:00
|
|
|
|
|
|
|
|
VERTEX_SHADER_CREATE_INFO(overlay_extra_spot_cone)
|
|
|
|
|
|
2025-02-19 17:46:04 +01:00
|
|
|
#include "draw_view_clipping_lib.glsl"
|
2025-01-23 18:06:22 +01:00
|
|
|
#include "draw_view_lib.glsl"
|
2025-06-09 15:33:13 +02:00
|
|
|
#include "gpu_shader_utildefines_lib.glsl"
|
2025-01-23 18:06:22 +01:00
|
|
|
#include "overlay_common_lib.glsl"
|
2024-10-04 15:48:22 +02:00
|
|
|
#include "select_lib.glsl"
|
2019-12-02 01:40:58 +01:00
|
|
|
|
|
|
|
|
void main()
|
|
|
|
|
{
|
2023-05-23 15:00:38 +02:00
|
|
|
select_id_set(in_select_buf[gl_InstanceID]);
|
|
|
|
|
|
2024-11-26 22:21:30 +01:00
|
|
|
/* Loading the matrix first before doing the manipulation fixes an issue
|
|
|
|
|
* with the Metal compiler on older Intel macs (see #130867). */
|
2025-04-14 13:46:41 +02:00
|
|
|
float4x4 inst_obmat = data_buf[gl_InstanceID].object_to_world;
|
|
|
|
|
float4x4 input_mat = inst_obmat;
|
2024-11-26 22:21:30 +01:00
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
/* Extract data packed inside the unused float4x4 members. */
|
|
|
|
|
float4 inst_data = float4(input_mat[0][3], input_mat[1][3], input_mat[2][3], input_mat[3][3]);
|
2024-12-12 23:05:00 +01:00
|
|
|
float4 color = data_buf[gl_InstanceID].color_;
|
2019-12-02 01:40:58 +01:00
|
|
|
float inst_color_data = color.a;
|
2025-04-14 13:46:41 +02:00
|
|
|
float4x4 obmat = input_mat;
|
2025-04-11 18:28:45 +02:00
|
|
|
obmat[0][3] = obmat[1][3] = obmat[2][3] = 0.0f;
|
|
|
|
|
obmat[3][3] = 1.0f;
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = color;
|
2025-04-11 18:28:45 +02:00
|
|
|
if (color.a < 0.0f) {
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color.a = 1.0f;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-17 18:25:14 +02:00
|
|
|
float2 lamp_area_size = inst_data.xy;
|
|
|
|
|
float lamp_clip_sta = inst_data.z;
|
|
|
|
|
float lamp_clip_end = inst_data.w;
|
|
|
|
|
|
|
|
|
|
float lamp_spot_cosine = inst_data.x;
|
|
|
|
|
float lamp_spot_blend = inst_data.y;
|
|
|
|
|
|
|
|
|
|
float2 camera_corner = inst_data.xy;
|
|
|
|
|
float2 camera_center = inst_data.zw;
|
|
|
|
|
float camera_dist = color.a;
|
|
|
|
|
float camera_dist_sta = inst_data.z;
|
|
|
|
|
float camera_dist_end = inst_data.w;
|
|
|
|
|
float camera_distance_color = inst_data.x;
|
|
|
|
|
|
|
|
|
|
float3 empty_size = inst_data.xyz;
|
|
|
|
|
float empty_scale = inst_data.w;
|
|
|
|
|
|
2019-12-02 01:40:58 +01:00
|
|
|
float lamp_spot_sine;
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 vpos = pos;
|
|
|
|
|
float3 vofs = float3(0.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Lights */
|
2025-06-09 15:33:13 +02:00
|
|
|
if (flag_test(vclass, VCLASS_LIGHT_AREA_SHAPE)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* HACK: use alpha color for spots to pass the area_size. */
|
2025-04-11 18:28:45 +02:00
|
|
|
if (inst_color_data < 0.0f) {
|
2025-04-14 13:46:41 +02:00
|
|
|
lamp_area_size = float2(-inst_color_data);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2025-02-24 16:17:18 +01:00
|
|
|
vpos.xy *= lamp_area_size;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_LIGHT_SPOT_SHAPE)) {
|
2025-04-11 18:28:45 +02:00
|
|
|
lamp_spot_sine = sqrt(1.0f - lamp_spot_cosine * lamp_spot_cosine);
|
2025-06-09 15:33:13 +02:00
|
|
|
lamp_spot_sine *= (flag_test(vclass, VCLASS_LIGHT_SPOT_BLEND)) ? lamp_spot_blend : 1.0f;
|
2025-04-14 13:46:41 +02:00
|
|
|
vpos = float3(pos.xy * lamp_spot_sine, -lamp_spot_cosine);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_LIGHT_DIST)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Meh nasty mess. Select one of the 6 axes to display on. (see light_distance_z_get()) */
|
|
|
|
|
int dist_axis = int(pos.z);
|
2025-04-11 18:28:45 +02:00
|
|
|
float dist = pos.z - floor(pos.z) - 0.5f;
|
2019-12-02 01:40:58 +01:00
|
|
|
float inv = sign(dist);
|
2025-04-11 18:28:45 +02:00
|
|
|
dist = (abs(dist) > 0.15f) ? lamp_clip_end : lamp_clip_sta;
|
2019-12-02 01:40:58 +01:00
|
|
|
vofs[dist_axis] = inv * dist / length(obmat[dist_axis].xyz);
|
2025-04-11 18:28:45 +02:00
|
|
|
vpos.z = 0.0f;
|
|
|
|
|
if (lamp_clip_end < 0.0f) {
|
2025-04-14 13:46:41 +02:00
|
|
|
vpos = vofs = float3(0.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Camera */
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_CAMERA_FRAME)) {
|
|
|
|
|
if (flag_test(vclass, VCLASS_CAMERA_VOLUME)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
vpos.z = mix(color.b, color.a, pos.z);
|
|
|
|
|
}
|
2025-04-11 18:28:45 +02:00
|
|
|
else if (camera_dist > 0.0f) {
|
2019-12-02 01:40:58 +01:00
|
|
|
vpos.z = -abs(camera_dist);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
vpos.z *= -abs(camera_dist);
|
|
|
|
|
}
|
|
|
|
|
vpos.xy = (camera_center + camera_corner * vpos.xy) * abs(vpos.z);
|
|
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_CAMERA_DIST)) {
|
2025-04-14 13:46:41 +02:00
|
|
|
vofs.xy = float2(0.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
vofs.z = -mix(camera_dist_sta, camera_dist_end, pos.z);
|
2025-04-11 18:28:45 +02:00
|
|
|
vpos.z = 0.0f;
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Distance line endpoints color */
|
2025-04-14 13:46:41 +02:00
|
|
|
if (any(notEqual(pos.xy, float2(0.0f)))) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Override color. */
|
|
|
|
|
switch (int(camera_distance_color)) {
|
|
|
|
|
case 0: /* Mist */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(0.5f, 0.5f, 0.5f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
|
|
|
|
case 1: /* Mist Active */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(1.0f, 1.0f, 1.0f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
|
|
|
|
case 2: /* Clip */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(0.5f, 0.5f, 0.25f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
|
|
|
|
case 3: /* Clip Active */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(1.0f, 1.0f, 0.5f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Focus cross */
|
2025-04-11 18:28:45 +02:00
|
|
|
if (pos.z == 2.0f) {
|
|
|
|
|
vofs.z = 0.0f;
|
|
|
|
|
if (camera_dist < 0.0f) {
|
2019-12-02 01:40:58 +01:00
|
|
|
vpos.z = -abs(camera_dist);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Disabled */
|
2025-04-14 13:46:41 +02:00
|
|
|
vpos = float3(0.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Empties */
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_EMPTY_SCALED)) {
|
2025-04-14 13:46:41 +02:00
|
|
|
/* This is a bit silly but we avoid scaling the object matrix on CPU (saving a float4x4 mul) */
|
2019-12-02 01:40:58 +01:00
|
|
|
vpos *= empty_scale;
|
|
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_EMPTY_SIZE)) {
|
2025-04-14 13:46:41 +02:00
|
|
|
/* This is a bit silly but we avoid scaling the object matrix on CPU (saving a float4x4 mul) */
|
2019-12-02 01:40:58 +01:00
|
|
|
vpos *= empty_size;
|
|
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_EMPTY_AXES)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
float axis = vpos.z;
|
2025-04-11 18:28:45 +02:00
|
|
|
vofs[int(axis)] = (1.0f + fract(axis)) * empty_scale;
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Scale uniformly by axis length */
|
|
|
|
|
vpos *= length(obmat[int(axis)].xyz) * empty_scale;
|
|
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 axis_color = float3(0.0f);
|
2025-04-11 18:28:45 +02:00
|
|
|
axis_color[int(axis)] = 1.0f;
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color.rgb = mix(axis_color + fract(axis), color.rgb, color.a);
|
|
|
|
|
final_color.a = 1.0f;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Not exclusive with previous flags. */
|
2025-06-09 15:33:13 +02:00
|
|
|
if (flag_test(vclass, VCLASS_CAMERA_VOLUME)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Unpack final color. */
|
|
|
|
|
int color_class = int(floor(color.r));
|
|
|
|
|
float color_intensity = fract(color.r);
|
|
|
|
|
switch (color_class) {
|
2021-06-24 15:56:58 +10:00
|
|
|
case 0: /* No eye (convergence plane). */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(1.0f, 1.0f, 1.0f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
2021-06-24 15:56:58 +10:00
|
|
|
case 1: /* Left eye. */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(0.0f, 1.0f, 1.0f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
2021-06-24 15:56:58 +10:00
|
|
|
case 2: /* Right eye. */
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color = float4(1.0f, 0.0f, 0.0f, 1.0f);
|
2019-12-02 01:40:58 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2025-04-24 12:50:45 +02:00
|
|
|
final_color *= float4(float3(color_intensity), color.g);
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 world_pos;
|
2025-06-09 15:33:13 +02:00
|
|
|
if (flag_test(vclass, VCLASS_SCREENSPACE)) {
|
2020-03-03 22:06:52 +11:00
|
|
|
/* Relative to DPI scaling. Have constant screen size. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 screen_pos = drw_view().viewinv[0].xyz * vpos.x + drw_view().viewinv[1].xyz * vpos.y;
|
|
|
|
|
float3 p = (obmat * float4(vofs, 1.0f)).xyz;
|
2025-04-26 11:28:24 +02:00
|
|
|
float screen_size = mul_project_m4_v3_zfac(uniform_buf.pixel_fac, p) * theme.sizes.pixel;
|
2019-12-02 01:40:58 +01:00
|
|
|
world_pos = p + screen_pos * screen_size;
|
|
|
|
|
}
|
2025-06-09 15:33:13 +02:00
|
|
|
else if (flag_test(vclass, VCLASS_SCREENALIGNED)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* World sized, camera facing geometry. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 screen_pos = drw_view().viewinv[0].xyz * vpos.x + drw_view().viewinv[1].xyz * vpos.y;
|
|
|
|
|
world_pos = (obmat * float4(vofs, 1.0f)).xyz + screen_pos;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
else {
|
2025-04-14 13:46:41 +02:00
|
|
|
world_pos = (obmat * float4(vofs + vpos, 1.0f)).xyz;
|
2019-12-02 01:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
2025-06-09 15:33:13 +02:00
|
|
|
if (flag_test(vclass, VCLASS_LIGHT_SPOT_CONE)) {
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Compute point on the cone before and after this one. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float2 perp = float2(pos.y, -pos.x);
|
2025-04-15 11:36:53 +02:00
|
|
|
constexpr float incr_angle = 2.0f * 3.1415f / 32.0f;
|
2025-04-14 13:46:41 +02:00
|
|
|
const float2 slope = float2(cos(incr_angle), sin(incr_angle));
|
|
|
|
|
float3 p0 = float3((pos.xy * slope.x + perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
|
|
|
|
|
float3 p1 = float3((pos.xy * slope.x - perp * slope.y) * lamp_spot_sine, -lamp_spot_cosine);
|
|
|
|
|
p0 = (obmat * float4(p0, 1.0f)).xyz;
|
|
|
|
|
p1 = (obmat * float4(p1, 1.0f)).xyz;
|
2019-12-02 01:40:58 +01:00
|
|
|
/* Compute normals of each side. */
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 edge = obmat[3].xyz - world_pos;
|
|
|
|
|
float3 n0 = normalize(cross(edge, p0 - world_pos));
|
|
|
|
|
float3 n1 = normalize(cross(edge, world_pos - p1));
|
2025-04-11 18:28:45 +02:00
|
|
|
bool persp = (drw_view().winmat[3][3] == 0.0f);
|
2025-04-14 13:46:41 +02:00
|
|
|
float3 V = (persp) ? normalize(drw_view().viewinv[3].xyz - world_pos) :
|
|
|
|
|
drw_view().viewinv[2].xyz;
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Discard non-silhouette edges. */
|
2025-04-11 18:28:45 +02:00
|
|
|
bool facing0 = dot(n0, V) > 0.0f;
|
|
|
|
|
bool facing1 = dot(n1, V) > 0.0f;
|
2019-12-02 01:40:58 +01:00
|
|
|
if (facing0 == facing1) {
|
|
|
|
|
/* Hide line by making it cover 0 pixels. */
|
|
|
|
|
world_pos = obmat[3].xyz;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 18:06:22 +01:00
|
|
|
gl_Position = drw_point_world_to_homogenous(world_pos);
|
2019-12-02 01:40:58 +01:00
|
|
|
|
|
|
|
|
/* Convert to screen position [0..sizeVp]. */
|
2025-04-26 11:28:24 +02:00
|
|
|
edge_pos = edge_start = ((gl_Position.xy / gl_Position.w) * 0.5f + 0.5f) *
|
|
|
|
|
uniform_buf.size_viewport;
|
2019-12-02 01:40:58 +01:00
|
|
|
|
2024-12-12 23:05:00 +01:00
|
|
|
#if defined(SELECT_ENABLE)
|
2021-02-05 19:07:03 -08:00
|
|
|
/* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the
|
2020-05-25 19:35:07 +02:00
|
|
|
* wire to at least create one fragment that will pass the occlusion query. */
|
2020-09-19 14:32:41 +10:00
|
|
|
/* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */
|
2025-04-26 11:28:24 +02:00
|
|
|
gl_Position.xy += uniform_buf.size_viewport_inv * gl_Position.w *
|
|
|
|
|
((gl_VertexID % 2 == 0) ? -1.0f : 1.0f);
|
2020-05-29 11:14:10 +02:00
|
|
|
#endif
|
2020-05-25 19:35:07 +02:00
|
|
|
|
2022-04-29 20:38:33 +02:00
|
|
|
view_clipping_distances(world_pos);
|
2019-12-16 13:49:11 +11:00
|
|
|
}
|