VSE: Scopes improvements #116798
|
@ -10,6 +10,7 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math_rotation.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
@ -571,20 +572,98 @@ static void draw_histogram(const blender::ed::seq::ScopeHistogram &hist,
|
|||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
}
|
||||
|
||||
static blender::float2 rgb_to_uv(const blender::float3 &rgb)
|
||||
{
|
||||
float y, u, v;
|
||||
rgb_to_yuv(rgb.x, rgb.y, rgb.z, &y, &u, &v, BLI_YUV_ITU_BT709);
|
||||
return blender::float2(u, v);
|
||||
}
|
||||
|
||||
static void draw_vectorscope_graticule(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 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 - radius * 0.1f, centery, centerx + radius * 0.1f, centery, col_grid);
|
||||
quads.add_line(centerx, centery - radius * 0.1f, centerx, centery + radius * 0.1f, col_grid);
|
||||
|
||||
/* fully saturated vs "safe" (0.75) colored areas */
|
||||
quads.draw();
|
||||
GPU_blend(GPU_BLEND_ADDITIVE);
|
||||
const float3 primaries[6] = {
|
||||
{1, 0, 0},
|
||||
{1, 1, 0},
|
||||
{0, 1, 0},
|
||||
{0, 1, 1},
|
||||
{0, 0, 1},
|
||||
{1, 0, 1},
|
||||
};
|
||||
float2 center{centerx, centery};
|
||||
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) * (radius * 2);
|
||||
float2 uv1 = center + rgb_to_uv(prim1) * (radius * 2);
|
||||
float2 uv2 = center + rgb_to_uv(safe0) * (radius * 2);
|
||||
aras_p marked this conversation as resolved
|
||||
float2 uv3 = center + rgb_to_uv(safe1) * (radius * 2);
|
||||
uchar col0[4] = {uchar(prim0.x * 255), uchar(prim0.y * 255), uchar(prim0.z * 255), 128};
|
||||
uchar col1[4] = {uchar(prim1.x * 255), uchar(prim1.y * 255), uchar(prim1.z * 255), 128};
|
||||
uchar col2[4] = {uchar(safe0.x * 255), uchar(safe0.y * 255), uchar(safe0.z * 255), 128};
|
||||
uchar col3[4] = {uchar(safe1.x * 255), uchar(safe1.y * 255), uchar(safe1.z * 255), 128};
|
||||
quads.add_quad(uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y, uv3.x, uv3.y, col0, col1, col2, col3);
|
||||
}
|
||||
quads.draw();
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
/* skin tone line */
|
||||
uchar col_tone[4] = {255, 102, 0, 128};
|
||||
const float tone_line_len = radius * 0.895f; /* makes it end at outer edge of saturation ring */
|
||||
quads.add_line(centerx,
|
||||
centery,
|
||||
centerx + cosf(skin_rad) * tone_line_len,
|
||||
centery + sinf(skin_rad) * tone_line_len,
|
||||
col_tone);
|
||||
}
|
||||
|
||||
static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq, bool draw_overlay)
|
||||
{
|
||||
using namespace blender::ed::seq;
|
||||
|
||||
/* Figure out draw coordinates. */
|
||||
rctf preview;
|
||||
rctf canvas;
|
||||
sequencer_preview_get_rect(&preview, scene, region, sseq, draw_overlay, false);
|
||||
|
||||
rctf uv;
|
||||
if (draw_overlay && (sseq->overlay_frame_type == SEQ_OVERLAY_FRAME_TYPE_RECT)) {
|
||||
canvas = scene->ed->overlay_frame_rect;
|
||||
uv = scene->ed->overlay_frame_rect;
|
||||
}
|
||||
else {
|
||||
BLI_rctf_init(&canvas, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
BLI_rctf_init(&uv, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
}
|
||||
const bool keep_aspect = sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE;
|
||||
float vecscope_aspect = 1.0f;
|
||||
if (keep_aspect) {
|
||||
float width = std::max(BLI_rctf_size_x(&preview), 0.1f);
|
||||
float height = std::max(BLI_rctf_size_y(&preview), 0.1f);
|
||||
vecscope_aspect = width / height;
|
||||
if (vecscope_aspect >= 1.0f) {
|
||||
BLI_rctf_resize_x(&uv, BLI_rctf_size_x(&uv) * vecscope_aspect);
|
||||
}
|
||||
else {
|
||||
BLI_rctf_resize_y(&uv, BLI_rctf_size_y(&uv) / vecscope_aspect);
|
||||
}
|
||||
}
|
||||
|
||||
SeqQuadsBatch quads;
|
||||
|
@ -623,6 +702,7 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq,
|
|||
"seq_display_buf", scope_image->x, scope_image->y, 1, format, usage, nullptr);
|
||||
GPU_texture_update(texture, data, scope_image->byte_buffer.data);
|
||||
GPU_texture_filter_mode(texture, false);
|
||||
GPU_texture_extend_mode(texture, GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER);
|
||||
|
||||
GPU_texture_bind(texture, 0);
|
||||
|
||||
|
@ -635,16 +715,16 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq,
|
|||
|
||||
immBegin(GPU_PRIM_TRI_FAN, 4);
|
||||
|
||||
immAttr2f(texCoord, canvas.xmin, canvas.ymin);
|
||||
immAttr2f(texCoord, uv.xmin, uv.ymin);
|
||||
immVertex2f(pos, preview.xmin, preview.ymin);
|
||||
|
||||
immAttr2f(texCoord, canvas.xmin, canvas.ymax);
|
||||
immAttr2f(texCoord, uv.xmin, uv.ymax);
|
||||
immVertex2f(pos, preview.xmin, preview.ymax);
|
||||
|
||||
immAttr2f(texCoord, canvas.xmax, canvas.ymax);
|
||||
immAttr2f(texCoord, uv.xmax, uv.ymax);
|
||||
immVertex2f(pos, preview.xmax, preview.ymax);
|
||||
|
||||
immAttr2f(texCoord, canvas.xmax, canvas.ymin);
|
||||
immAttr2f(texCoord, uv.xmax, uv.ymin);
|
||||
immVertex2f(pos, preview.xmax, preview.ymin);
|
||||
|
||||
immEnd();
|
||||
|
@ -673,6 +753,10 @@ static void sequencer_draw_scopes(Scene *scene, ARegion *region, SpaceSeq *sseq,
|
|||
uchar col_border[4] = {64, 64, 64, 128};
|
||||
quads.add_wire_quad(x0, preview.ymin, x1, preview.ymax, col_border);
|
||||
}
|
||||
if (sseq->mainb == SEQ_DRAW_IMG_VECTORSCOPE) {
|
||||
use_blend = true;
|
||||
draw_vectorscope_graticule(quads, preview);
|
||||
}
|
||||
|
||||
quads.draw();
|
||||
|
||||
|
|
|
@ -53,10 +53,10 @@ SeqQuadsBatch::SeqQuadsBatch()
|
|||
|
||||
batch_quads = GPU_batch_create_ex(
|
||||
GPU_PRIM_TRIS, vbo_quads, ibo_quads, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
|
||||
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_FLAT_COLOR);
|
||||
GPU_batch_program_set_builtin(batch_quads, GPU_SHADER_3D_SMOOTH_COLOR);
|
||||
|
||||
batch_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo_lines, nullptr, GPU_BATCH_OWNS_VBO);
|
||||
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_FLAT_COLOR);
|
||||
GPU_batch_program_set_builtin(batch_lines, GPU_SHADER_3D_SMOOTH_COLOR);
|
||||
}
|
||||
|
||||
SeqQuadsBatch::~SeqQuadsBatch()
|
||||
|
@ -93,7 +93,10 @@ void SeqQuadsBatch::add_quad(float x1,
|
|||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
const uchar color[4])
|
||||
const uchar color1[4],
|
||||
const uchar color2[4],
|
||||
const uchar color3[4],
|
||||
const uchar color4[4])
|
||||
{
|
||||
if (quads_num >= MAX_QUADS) {
|
||||
draw();
|
||||
|
@ -103,10 +106,10 @@ void SeqQuadsBatch::add_quad(float x1,
|
|||
BLI_assert(verts_quads != nullptr);
|
||||
}
|
||||
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color};
|
||||
ColorVertex v1 = {blender::float2(x2, y2), color};
|
||||
ColorVertex v2 = {blender::float2(x3, y3), color};
|
||||
ColorVertex v3 = {blender::float2(x4, y4), color};
|
||||
ColorVertex v0 = {blender::float2(x1, y1), color1};
|
||||
ColorVertex v1 = {blender::float2(x2, y2), color2};
|
||||
ColorVertex v2 = {blender::float2(x3, y3), color3};
|
||||
ColorVertex v3 = {blender::float2(x4, y4), color4};
|
||||
|
||||
*verts_quads++ = v0;
|
||||
*verts_quads++ = v1;
|
||||
|
|
|
@ -33,9 +33,9 @@ class SeqQuadsBatch {
|
|||
/** Add an axis-aligned quad. */
|
||||
void add_quad(float x1, float y1, float x2, float y2, const uchar color[4])
|
||||
{
|
||||
add_quad(x1, y1, x1, y2, x2, y1, x2, y2, color);
|
||||
add_quad(x1, y1, x1, y2, x2, y1, x2, y2, color, color, color, color);
|
||||
}
|
||||
/** Add a quad. */
|
||||
/** Add a quad with four arbitrary coordinates and one color. */
|
||||
void add_quad(float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
|
@ -44,7 +44,23 @@ class SeqQuadsBatch {
|
|||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
const uchar color[4]);
|
||||
const uchar color[4])
|
||||
{
|
||||
add_quad(x1, y1, x2, y2, x3, y3, x4, y4, color, color, color, color);
|
||||
}
|
||||
/** Add a quad with four arbitrary coordinates and a color for each. */
|
||||
void add_quad(float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
float x3,
|
||||
float y3,
|
||||
float x4,
|
||||
float y4,
|
||||
const uchar color1[4],
|
||||
const uchar color2[4],
|
||||
const uchar color3[4],
|
||||
const uchar color4[4]);
|
||||
/** Add four lines of an axis-aligned quad edges. */
|
||||
void add_wire_quad(float x1, float y1, float x2, float y2, const uchar color[4]);
|
||||
/** Add a line. */
|
||||
|
|
|
@ -54,20 +54,14 @@ void SeqScopes::cleanup()
|
|||
histogram.data.reinitialize(0);
|
||||
}
|
||||
|
||||
/* XXX(@ideasman42): why is this function better than BLI_math version?
|
||||
* only difference is it does some normalize after, need to double check on this. */
|
||||
static void rgb_to_yuv_normalized(const float rgb[3], float yuv[3])
|
||||
static blender::float2 rgb_to_uv_normalized(const float rgb[3])
|
||||
{
|
||||
yuv[0] = 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
|
||||
yuv[1] = 0.492f * (rgb[2] - yuv[0]);
|
||||
yuv[2] = 0.877f * (rgb[0] - yuv[0]);
|
||||
float3 yuv;
|
||||
rgb_to_yuv(rgb[0], rgb[1], rgb[2], &yuv.x, &yuv.y, &yuv.z, BLI_YUV_ITU_BT709);
|
||||
|
||||
/* Normalize. */
|
||||
yuv[1] *= 255.0f / (122 * 2.0f);
|
||||
yuv[1] += 0.5f;
|
||||
|
||||
yuv[2] *= 255.0f / (157 * 2.0f);
|
||||
yuv[2] += 0.5f;
|
||||
/* Normalize: UV range is +/- 0.615 */
|
||||
float2 uv = yuv.yz() * (0.5f / 0.615f) + 0.5f;
|
||||
return math::clamp(uv, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static void scope_put_pixel(const uchar *table, uchar *pos)
|
||||
|
@ -420,60 +414,22 @@ void ScopeHistogram::calc_from_ibuf(const ImBuf *ibuf)
|
|||
}
|
||||
}
|
||||
|
||||
static void vectorscope_put_cross(uchar r, uchar g, uchar b, uchar *tgt, int w, int h, int size)
|
||||
{
|
||||
float rgb[3], yuv[3];
|
||||
uchar *p;
|
||||
|
||||
rgb[0] = float(r) / 255.0f;
|
||||
rgb[1] = float(g) / 255.0f;
|
||||
rgb[2] = float(b) / 255.0f;
|
||||
rgb_to_yuv_normalized(rgb, yuv);
|
||||
|
||||
p = tgt + 4 * (w * int(yuv[2] * (h - 3) + 1) + int(yuv[1] * (w - 3) + 1));
|
||||
|
||||
if (r == 0 && g == 0 && b == 0) {
|
||||
r = 255;
|
||||
}
|
||||
|
||||
for (int y = -size; y <= size; y++) {
|
||||
for (int x = -size; x <= size; x++) {
|
||||
uchar *q = p + 4 * (y * w + x);
|
||||
q[0] = r;
|
||||
q[1] = g;
|
||||
q[2] = b;
|
||||
q[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
|
||||
{
|
||||
#ifdef DEBUG_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
#endif
|
||||
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
|
||||
int w = 512;
|
||||
int h = 512;
|
||||
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
|
||||
|
||||
int x, y;
|
||||
const uchar *src = ibuf->byte_buffer.data;
|
||||
uchar *tgt = rval->byte_buffer.data;
|
||||
float rgb[3], yuv[3];
|
||||
int w = 515;
|
||||
int h = 515;
|
||||
float scope_gamma = 0.2;
|
||||
float rgb[3];
|
||||
|
||||
uchar wtable[256];
|
||||
|
||||
for (x = 0; x < 256; x++) {
|
||||
wtable[x] = uchar(pow((float(x) + 1.0f) / 256.0f, scope_gamma) * 255.0f);
|
||||
}
|
||||
|
||||
for (x = 0; x < 256; x++) {
|
||||
vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
|
||||
vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
|
||||
vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
|
||||
vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
|
||||
vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
|
||||
vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
|
||||
}
|
||||
init_wave_table(math::midpoint(ibuf->x, ibuf->y), wtable);
|
||||
|
||||
for (y = 0; y < ibuf->y; y++) {
|
||||
for (x = 0; x < ibuf->x; x++) {
|
||||
|
@ -483,15 +439,13 @@ static ImBuf *make_vectorscope_view_from_ibuf_byte(ImBuf *ibuf)
|
|||
rgb[0] = float(src1[0]) / 255.0f;
|
||||
rgb[1] = float(src1[1]) / 255.0f;
|
||||
rgb[2] = float(src1[2]) / 255.0f;
|
||||
rgb_to_yuv_normalized(rgb, yuv);
|
||||
float2 uv = rgb_to_uv_normalized(rgb);
|
||||
|
||||
p = tgt + 4 * (w * int(yuv[2] * (h - 3) + 1) + int(yuv[1] * (w - 3) + 1));
|
||||
p = tgt + 4 * (w * int(uv.y * (h - 1)) + int(uv.x * (w - 1)));
|
||||
scope_put_pixel(wtable, (uchar *)p);
|
||||
}
|
||||
}
|
||||
|
||||
vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -500,13 +454,13 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
|
|||
#ifdef DEBUG_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
#endif
|
||||
ImBuf *rval = IMB_allocImBuf(515, 515, 32, IB_rect);
|
||||
int w = 512;
|
||||
int h = 512;
|
||||
ImBuf *rval = IMB_allocImBuf(w, h, 32, IB_rect);
|
||||
int x, y;
|
||||
const float *src = ibuf->float_buffer.data;
|
||||
uchar *tgt = rval->byte_buffer.data;
|
||||
float rgb[3], yuv[3];
|
||||
int w = 515;
|
||||
int h = 515;
|
||||
float rgb[3];
|
||||
float scope_gamma = 0.2;
|
||||
uchar wtable[256];
|
||||
|
||||
|
@ -514,15 +468,6 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
|
|||
wtable[x] = uchar(pow((float(x) + 1.0f) / 256.0f, scope_gamma) * 255.0f);
|
||||
}
|
||||
|
||||
for (x = 0; x <= 255; x++) {
|
||||
vectorscope_put_cross(255, 0, 255 - x, tgt, w, h, 1);
|
||||
vectorscope_put_cross(255, x, 0, tgt, w, h, 1);
|
||||
vectorscope_put_cross(255 - x, 255, 0, tgt, w, h, 1);
|
||||
vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
|
||||
vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
|
||||
vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
|
||||
}
|
||||
|
||||
for (y = 0; y < ibuf->y; y++) {
|
||||
for (x = 0; x < ibuf->x; x++) {
|
||||
const float *src1 = src + 4 * (ibuf->x * y + x);
|
||||
|
@ -532,15 +477,13 @@ static ImBuf *make_vectorscope_view_from_ibuf_float(ImBuf *ibuf)
|
|||
|
||||
clamp_v3(rgb, 0.0f, 1.0f);
|
||||
|
||||
rgb_to_yuv_normalized(rgb, yuv);
|
||||
float2 uv = rgb_to_uv_normalized(rgb);
|
||||
|
||||
p = tgt + 4 * (w * int(yuv[2] * (h - 3) + 1) + int(yuv[1] * (w - 3) + 1));
|
||||
p = tgt + 4 * (w * int(uv.y * (h - 1)) + int(uv.x * (w - 1)));
|
||||
scope_put_pixel(wtable, (uchar *)p);
|
||||
}
|
||||
}
|
||||
|
||||
vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Use
BLI_snprintf()