VSE: tweak look of Vectorscope to match upcoming Image vectorscope #117738

Merged
Aras Pranckevicius merged 1 commits from aras_p/blender:vse-scopes into main 2024-02-02 20:59:12 +01:00
2 changed files with 137 additions and 41 deletions

View File

@ -631,28 +631,116 @@ static void draw_waveform_graticule(ARegion *region, SeqQuadsBatch &quads, const
UI_view2d_text_cache_draw(region);
}
static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
static void draw_vectorscope_graticule(ARegion *region, SeqQuadsBatch &quads, const rctf &area)
{
using namespace blender;
GPU_blend(GPU_BLEND_ALPHA);
const float skin_rad = DEG2RADF(123.0f); /* angle in radians of the skin tone line */
const float w = BLI_rctf_size_x(&area);
const float h = BLI_rctf_size_y(&area);
const float centerx = BLI_rctf_cent_x(&area);
const float centery = BLI_rctf_cent_y(&area);
const float rad_base = ((w < h) ? w : h) * 0.5f;
/* vectorscope image is scaled over YUV range, +/- (0.436, 0.615) */
const float rad_x = rad_base * (0.5f / 0.436f);
const float rad_y = rad_base * (0.5f / 0.615f);
const float2 center{BLI_rctf_cent_x(&area), BLI_rctf_cent_y(&area)};
/* Vectorscope image is scaled over UV range (+/-0.615). */
const float radius = ((w < h) ? w : h) * 0.5f * (0.5f / 0.615f);
/* center cross */
uchar col_grid[4] = {128, 128, 128, 96};
quads.add_line(centerx - rad_base * 0.1f, centery, centerx + rad_base * 0.1f, centery, col_grid);
quads.add_line(centerx, centery - rad_base * 0.1f, centerx, centery + rad_base * 0.1f, col_grid);
/* Precalculate circle points/colors. */
constexpr int circle_delta = 6;
constexpr int num_circle_points = 360 / circle_delta;
float2 circle_pos[num_circle_points];
float3 circle_col[num_circle_points];
for (int i = 0; i < num_circle_points; i++) {
float a = DEG2RADF(i * circle_delta);
float u = cosf(a);
float v = sinf(a);
circle_pos[i] = float2(u, v);
/* fully saturated vs "safe" (0.75) colored areas */
float3 col;
yuv_to_rgb(0.5f, u, v, &col.x, &col.y, &col.z, BLI_YUV_ITU_BT709);
circle_col[i] = col;
}
/* Draw colored background and outer ring, additively blended
* since vectorscope image is already drawn. */
GPU_blend(GPU_BLEND_ADDITIVE);
constexpr float alpha_f = 0.8f;
constexpr uchar alpha_b = uchar(alpha_f * 255.0f);
const uchar4 col_center(50, 50, 50, alpha_b);
uchar4 col1(0, 0, 0, alpha_b);
uchar4 col2(0, 0, 0, alpha_b);
uchar4 col3(0, 0, 0, alpha_b);
/* Background: since the quads batch utility draws quads, draw two
* segments of the circle (two triangles) in one iteration. */
constexpr float mul_background = 0.2f;
for (int i = 0; i < num_circle_points; i += 2) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
int idx3 = (i + 2) % num_circle_points;
float2 pt1 = center + circle_pos[idx1] * radius;
float2 pt2 = center + circle_pos[idx2] * radius;
float2 pt3 = center + circle_pos[idx3] * radius;
float3 rgb1 = circle_col[idx1] * mul_background;
float3 rgb2 = circle_col[idx2] * mul_background;
float3 rgb3 = circle_col[idx3] * mul_background;
rgb_float_to_uchar(col1, rgb1);
rgb_float_to_uchar(col2, rgb2);
rgb_float_to_uchar(col3, rgb3);
quads.add_quad(pt1.x,
pt1.y,
pt2.x,
pt2.y,
center.x,
center.y,
pt3.x,
pt3.y,
col1,
col2,
col_center,
col3);
}
/* Outer ring. */
const float outer_radius = radius * 1.02f;
for (int i = 0; i < num_circle_points; i++) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
float2 pt1a = center + circle_pos[idx1] * radius;
float2 pt2a = center + circle_pos[idx2] * radius;
float2 pt1b = center + circle_pos[idx1] * outer_radius;
float2 pt2b = center + circle_pos[idx2] * outer_radius;
float3 rgb1 = circle_col[idx1];
float3 rgb2 = circle_col[idx2];
rgb_float_to_uchar(col1, rgb1);
rgb_float_to_uchar(col2, rgb2);
quads.add_quad(
pt1a.x, pt1a.y, pt1b.x, pt1b.y, pt2a.x, pt2a.y, pt2b.x, pt2b.y, col1, col1, col2, col2);
}
quads.draw();
/* Draw grid and other labels using regular alpha blending. */
GPU_blend(GPU_BLEND_ALPHA);
const uchar4 col_grid(128, 128, 128, 128);
/* Cross. */
quads.add_line(center.x - radius, center.y, center.x + radius, center.y, col_grid);
quads.add_line(center.x, center.y - radius, center.x, center.y + radius, col_grid);
/* Inner circles. */
for (int j = 1; j < 5; j++) {
float r = radius * j * 0.2f;
for (int i = 0; i < num_circle_points; i++) {
int idx1 = i;
int idx2 = (i + 1) % num_circle_points;
float2 pt1 = center + circle_pos[idx1] * r;
float2 pt2 = center + circle_pos[idx2] * r;
quads.add_line(pt1.x, pt1.y, pt2.x, pt2.y, col_grid);
}
}
/* "Safe" (0.75 saturation) primary color locations and labels. */
const float3 primaries[6] = {
{1, 0, 0},
{1, 1, 0},
@ -661,35 +749,43 @@ static void draw_vectorscope_graticule(SeqQuadsBatch &quads, const rctf &area)
{0, 0, 1},
{1, 0, 1},
};
float2 center{centerx, centery};
float2 rad_scale{rad_x * 2, rad_y * 2};
const char *names = "RYGCBM";
/* Calculate size of single text letter. */
char buf[2] = {'M', 0};
float text_scale_x, text_scale_y;
UI_view2d_scale_get_inverse(&region->v2d, &text_scale_x, &text_scale_y);
float text_width, text_height;
BLF_width_and_height(BLF_default(), buf, 1, &text_width, &text_height);
text_width *= text_scale_x;
text_height *= text_scale_y;
const uchar4 col_target(128, 128, 128, 192);
const float delta = radius * 0.01f;
for (int i = 0; i < 6; i++) {
float3 prim0 = primaries[i];
float3 prim1 = primaries[(i + 1) % 6];
float3 safe0 = prim0 * 0.75f;
float3 safe1 = prim1 * 0.75f;
float2 uv0 = center + rgb_to_uv(prim0) * rad_scale;
float2 uv1 = center + rgb_to_uv(prim1) * rad_scale;
float2 uv2 = center + rgb_to_uv(safe0) * rad_scale;
float2 uv3 = center + rgb_to_uv(safe1) * rad_scale;
uchar col0[4] = {uchar(prim0.x * 255), uchar(prim0.y * 255), uchar(prim0.z * 255), 64};
uchar col1[4] = {uchar(prim1.x * 255), uchar(prim1.y * 255), uchar(prim1.z * 255), 64};
uchar col2[4] = {uchar(safe0.x * 255), uchar(safe0.y * 255), uchar(safe0.z * 255), 64};
uchar col3[4] = {uchar(safe1.x * 255), uchar(safe1.y * 255), uchar(safe1.z * 255), 64};
quads.add_quad(uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, uv3.x, uv3.y, col0, col1, col2, col3);
col0[3] = col1[3] = col2[3] = col3[3] = 192;
quads.add_line(uv0.x, uv0.y, uv1.x, uv1.y, col0, col1);
quads.add_line(uv2.x, uv2.y, uv3.x, uv3.y, col2, col3);
float3 safe = primaries[i] * 0.75f;
float2 pos = center + rgb_to_uv(safe) * (radius * 2);
quads.add_wire_quad(pos.x - delta, pos.y - delta, pos.x + delta, pos.y + delta, col_target);
buf[0] = names[i];
UI_view2d_text_cache_add(&region->v2d,
pos.x + delta * 1.2f + text_width / 4,
pos.y - text_height / 2,
buf,
1,
col_target);
}
/* skin tone line */
uchar col_tone[4] = {255, 102, 0, 128};
const float tone_line_len = 0.895f; /* makes it end at outer edge of saturation ring. */
quads.add_line(centerx,
centery,
centerx + cosf(skin_rad) * rad_x * tone_line_len,
centery + sinf(skin_rad) * rad_y * tone_line_len,
/* Skin tone line. */
const uchar4 col_tone(255, 102, 0, 128);
quads.add_line(center.x,
center.y,
center.x + cosf(skin_rad) * radius,
center.y + sinf(skin_rad) * radius,
col_tone);
quads.draw();
UI_view2d_text_cache_draw(region);
}
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
@ -794,7 +890,7 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq)
}
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
use_blend = true;
draw_vectorscope_graticule(quads, preview);
draw_vectorscope_graticule(region, quads, preview);
}
quads.draw();

View File

@ -64,8 +64,8 @@ static blender::float2 rgb_to_uv_normalized(const float rgb[3])
float u = -0.09991f * r - 0.33609f * g + 0.436f * b;
float v = 0.615f * r - 0.55861f * g - 0.05639f * b;
/* Normalize: (U, V) range is +/- (0.436, 0.615) */
u = clamp_f(u * (0.5f / 0.436f) + 0.5f, 0.0f, 1.0f);
/* Normalize: possible range is +/- 0.615. */
u = clamp_f(u * (0.5f / 0.615f) + 0.5f, 0.0f, 1.0f);
v = clamp_f(v * (0.5f / 0.615f) + 0.5f, 0.0f, 1.0f);
return float2(u, v);
}