diff --git a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc index fa63f044f5a..52434ef9d75 100644 --- a/source/blender/editors/space_sequencer/sequencer_preview_draw.cc +++ b/source/blender/editors/space_sequencer/sequencer_preview_draw.cc @@ -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(®ion->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(®ion->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(); diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.cc b/source/blender/editors/space_sequencer/sequencer_scopes.cc index 94ece696108..188fcb42452 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.cc +++ b/source/blender/editors/space_sequencer/sequencer_scopes.cc @@ -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); }