From 7e4d06169c366206261e3ce2f5b3067fb601b044 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sun, 18 Aug 2024 17:59:26 +0200 Subject: [PATCH] qr shader: correct data bit layout for all but leftmost column of aligners --- Assets/test/QRCode.shader | 110 ++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 23 deletions(-) diff --git a/Assets/test/QRCode.shader b/Assets/test/QRCode.shader index f6912f0..da4b72a 100644 --- a/Assets/test/QRCode.shader +++ b/Assets/test/QRCode.shader @@ -6,8 +6,11 @@ Properties { _Mask("Mask type", Range(0, 7)) = 1 [Toggle] _DisableMask("Hide mask", Integer) = 0 - // _TimeSlider("Time", Range(150, 300)) = 0 - _TimeSlider("Time", Range(0, 300)) = 0 + [Toggle] + _Animate("Animate debug worm", Integer) = 0 + _AnimationSpeed("Speed", Range(1, 100)) = 0 + _TimeSlider("Time", Range(0, 200)) = 0 + _TimeSliderCoarse("Time Coarse", Range(0, 250)) = 0 } SubShader { Tags { "RenderType"="Opaque" } @@ -18,7 +21,10 @@ CGPROGRAM uint _Version; uint _Mask; bool _DisableMask; + bool _Animate; float _TimeSlider; + float _TimeSliderCoarse; + float _AnimationSpeed; #define VERSION _Version #define WIDTH (17 + VERSION * 4) @@ -29,8 +35,8 @@ CGPROGRAM #define ALIGNER_SPACING (ALIGNER_SPACING_IDEAL + ALIGNER_SPACING_IDEAL % 2) #define MISALIGNMENT ((WIDTH - 13) - ALIGNER_SPACING * ALIGNERS) #define BIT_COUNT (WIDTH * WIDTH - 225 - (WIDTH - 17)*2 - 25 * (ALIGNERS * ALIGNERS - 3) * (VERSION > 1)) - #define TIME (_Time.y*24) - #define TIME (uint)(_TimeSlider) + #define TIME_MANUAL (_TimeSlider + _TimeSliderCoarse*100) + #define TIME (uint)(_Animate ? _Time.y * _AnimationSpeed + TIME_MANUAL : TIME_MANUAL) #define EC_LEVEL_L 1 #define EC_LEVEL_M 0 @@ -67,9 +73,9 @@ CGPROGRAM const uint data_len = 3*4; const uint total_len = 7*4; uv.y = 1 - uv.y; - uv = uv * 1.5 - 0.25; + uv = uv * 1.2 - 0.1; // Quiet zone/frame - if (uv.x < 0 || uv.x > 1 || uv.y < 0 || uv.y > 1) return 1.2; + if (uv.x < 0 || uv.x > 1 || uv.y < 0 || uv.y > 1) return 1; uint px = uv.x * PIXEL_WIDTH; uint py = uv.y * PIXEL_WIDTH; @@ -129,11 +135,14 @@ CGPROGRAM bit_index += tiny_columns * (WIDTH - 17) * 2; bit_index += (px + (px < 6)) % 2; uint column_progress; - if (direction_up) + uint y_relative; + if (direction_up) { + y_relative = WIDTH - py - 1; column_progress = WIDTH - py - 1 - (py < 7); - else + } else { + y_relative = py; column_progress = py - ((full_columns == 0) ? 9 : (py > 6)); - + } bit_index += column_progress * 2; if (px < 9) bit_index -= 16; // rightmost tiny column @@ -143,24 +152,75 @@ CGPROGRAM // aligners always cover a half column to the left and two full columns to the right // outer aligners are always 4 from all edges - // rightmost column of aligners - uint passed_up = (column_progress - 9 + ALIGNER_SPACING) / ALIGNER_SPACING; - if (column == 2) { + uint aligner_col = (column - 2) / (ALIGNER_SPACING/2); + uint aligner_col_mod = (column - 2) % (ALIGNER_SPACING/2); + if (aligner_col > 0) { // full columns passed + bit_index -= (ALIGNERS - 1) * aligner_col*25; + if (aligner_col > 1) { + // top row only obstructs 20 since it overlaps the timing stripe + bit_index -= (aligner_col - 1)*20; + } + } + + uint passed_up = (y_relative - 9 + ALIGNER_SPACING - (!direction_up * (MISALIGNMENT+ALIGNER_SPACING))) / ALIGNER_SPACING; + passed_up = min(passed_up, ALIGNERS-1); + + if (aligner_col_mod == 0) { bit_index -= passed_up * 10; - } else if (column == 3) { - uint passed_down = (column_progress) / ALIGNER_SPACING; + if (direction_up && py < 5){ + bit_index -= 8; + } + if (!direction_up && py > 5){ + bit_index += 2; + if (py > WIDTH-5){ + bit_index -= 10; + } + } + } else if (aligner_col_mod == 1) { + uint passed_down = (y_relative - 8 + ALIGNER_SPACING - !direction_up*MISALIGNMENT) / ALIGNER_SPACING; bit_index -= (passed_down + ALIGNERS - 1) * 10; - } else if (column == 4) { + if (!direction_up) + bit_index += 10; + if (aligner_col > 0) { + bit_index -= 8; + } else { + bit_index += 8; + } + if (direction_up ? py < 5 : py > 5){ + bit_index += 2; + } + } else if (aligner_col_mod == 2) { bit_index -= (ALIGNERS - 1) * 20; - uint offset = (column_progress + ALIGNER_SPACING - 3) % ALIGNER_SPACING; - if (offset < 6) { + if (aligner_col > 0) { + bit_index -= 16; // most of the current column top aligner, excluding the left 4 pixels + if (py < 9) {// top aligner + if (direction_up){ + bit_index -= min(9-py, 5) - (py < 6); + } else if (py > 3) { + bit_index -= py - 3 - (py > 6); + } + } else { + bit_index += !direction_up; + } + if (!direction_up && py > WIDTH-5){ + bit_index-=5; + } + } + uint offset = (column_progress + ALIGNER_SPACING - 3 - !direction_up*0 + (!direction_up * (-MISALIGNMENT+1))) % ALIGNER_SPACING; + + // left side of regular aligners + if (offset < 6 && py > 9 && px > 9) { bit_index -= offset; } bit_index -= passed_up * 5; - } else { - bit_index -= (ALIGNERS-1)*25; - } + } else { // include the full row + bit_index -= (ALIGNERS - 1)*25; + if (aligner_col > 0){ + // return PINK; + bit_index -= 20; + } + } } // data @@ -209,9 +269,13 @@ CGPROGRAM // return !bit; // bit index debugging worm - uint worm = abs(TIME % BIT_COUNT - bit_index); - const uint length = 4; - if (worm < length) return BLUE * (worm/(float)length); + uint worm = TIME % BIT_COUNT - bit_index; + worm %= 200; + const uint length = 6; + if (worm == 0) return float3(3,0,0); + if (worm < length) return lerp(PINK, BLUE, (worm/(float)length)); + if (bit_index > BIT_COUNT) return float3(1,0,0); + // #define BIT_COUNT 24 return (float)(bit_index%BIT_COUNT)/(float)BIT_COUNT; }