Shader "CrispyPin/QRCode" { Properties { [HideInInspector] _("",2D)=""{} _Version("Version", Range(1, 40)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 CGPROGRAM #pragma surface s Standard struct Input{float2 uv_;}; uint _Version; #define VERSION _Version #define WIDTH (17 + VERSION * 4) #define PIXEL_WIDTH WIDTH // #define PIXEL_WIDTH 177 #define ALIGNERS ((VERSION / 7) + 2) #define ALIGNER_SPACING_IDEAL ((WIDTH - 13) / (ALIGNERS-1)) #define ALIGNER_SPACING (ALIGNER_SPACING_IDEAL + ALIGNER_SPACING_IDEAL % 2) #define MISALIGNMENT ((WIDTH - 13) - ALIGNER_SPACING * ALIGNERS) #define EC_LEVEL_L 1 #define EC_LEVEL_M 0 #define EC_LEVEL_Q 3 #define EC_LEVEL_H 2 #define EC_LEVEL EC_LEVEL_L #define MASK_TYPE 1 static const uint FORMAT_BIT_SETS[32] = {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b, 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed}; #define FORMAT_BITS_RAW ((EC_LEVEL << 3) | MASK_TYPE) #define FORMAT_BITS FORMAT_BIT_SETS[FORMAT_BITS_RAW] /* v = 15 width = 77 aligners = 4 spacing = (77-13)/3 */ #define WHITE 1 #define BLACK 0 #define PINK float3(1, .3, .5) #define BLUE float3(0, .4, .7) float3 finder_pattern(uint x, uint y) { if (x < 6 && x > 0 && y < 6 && y > 0) return !(x < 5 && x > 1 && y < 5 && y > 1); return (x > 6 || y > 6); } float3 main (float2 uv){ const uint data[] = {0x68656c6c,0x6f20776f,0x726c6421}; uv.y = 1 - uv.y; uv = uv * 1.5 - 0.25; // Quiet zone 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; // Finder patterns if (px < 8 && py < 8) return finder_pattern(px, py); if (px < 8 && py > WIDTH - 9) return finder_pattern(px, py - WIDTH + 7); if (px > WIDTH - 9 && py < 8) return finder_pattern(px - WIDTH + 7, py); // filler pixel if (px == 8 && py == WIDTH - 8) return 0; // Timing patterns if (px == 6) return py & 1; if (py == 6) return px & 1; // Aligners if (VERSION > 1 && (px > 12 || py > 12) // top left && (px < WIDTH - 13 || py > 12) // top right && (py < WIDTH - 13 || px > 12) // bottom left ) { uint x = px + ALIGNER_SPACING - 4; uint y = py + ALIGNER_SPACING - 4; if (px > 12) x -= MISALIGNMENT; if (py > 12) y -= MISALIGNMENT; x %= ALIGNER_SPACING; y %= ALIGNER_SPACING; if (x < 5 && y < 5) { return (x < 4 && x > 0 && y < 4 && y > 0 && !(x == 2 && y == 2)); } } // Format bits // left if (px < 6 && py == 8) return (FORMAT_BITS & (1 << (14 - px))) == 0; if (px == 7 && py == 8) return (FORMAT_BITS & (1 << 8)) == 0; // right if (px > WIDTH - 9 && py == 8) return (FORMAT_BITS & (1 << (WIDTH - 1 - px))) == 0; // top if (px == 8 && py < 6) return (FORMAT_BITS & (1 << py)) == 0; if (px == 8 && py < 9) return (FORMAT_BITS & (1 << (py-1))) == 0; // bottom if (px == 8 && py > WIDTH - 8) return (FORMAT_BITS & (1 << py + 15 - WIDTH)) == 0; uint column = (WIDTH - px - (px > 6))/2; uint direction_up = column & 1; // return lerp(BLUE, PINK, column / (WIDTH/2.)); return lerp(BLUE, PINK, (px+py)&1); // return float3((px%5)/5., (px/10+py/10)&1, (py%5)/5.); // return float3((px/8 + py/8) & 1, (px/2 + py/2) & 1, (px/4 + py/4) & 1, 1); // return direction_up; return 0.5; } void s (Input IN, inout SurfaceOutputStandard o) { o.Albedo = main(IN.uv_); } ENDCG }}