2024-08-16 10:06:39 +02:00
|
|
|
Shader "CrispyPin/QRCode" {
|
|
|
|
Properties {
|
|
|
|
[HideInInspector]
|
|
|
|
_("",2D)=""
|
|
|
|
_Version("Version", Integer) = 1
|
|
|
|
}
|
|
|
|
SubShader {
|
|
|
|
Tags { "RenderType"="Opaque" }
|
|
|
|
LOD 100
|
|
|
|
CGPROGRAM
|
|
|
|
#pragma surface s Standard
|
|
|
|
struct Input{float2 uv_;};
|
|
|
|
uint _Version;
|
|
|
|
|
|
|
|
#define VERSION _Version
|
2024-08-16 11:02:26 +02:00
|
|
|
#define WIDTH (17 + VERSION * 4)
|
2024-08-16 10:06:39 +02:00
|
|
|
#define ALIGNERS ((VERSION / 7) + 2)
|
2024-08-16 11:02:26 +02:00
|
|
|
#define ALIGNER_SPACING ((WIDTH - 13) / (ALIGNERS-1))
|
2024-08-16 10:06:39 +02:00
|
|
|
#define MISALIGNMENT ((WIDTH - 13) % (ALIGNERS-1))
|
|
|
|
|
2024-08-16 11:02:26 +02:00
|
|
|
#define EC_LEVEL (3)
|
|
|
|
#define MASK_TYPE (4)
|
|
|
|
#define FORMAT_BITS ((EC_LEVEL << 3) | MASK_TYPE)
|
|
|
|
|
2024-08-16 10:06:39 +02:00
|
|
|
/*
|
|
|
|
v = 15
|
|
|
|
width = 77
|
|
|
|
aligners = 4
|
|
|
|
spacing = (77-13)/3
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define WHITE 1
|
|
|
|
#define BLACK 0
|
|
|
|
#define PINK float4(1, .3, .5, 1)
|
2024-08-16 11:02:26 +02:00
|
|
|
#define BLUE float4(0, .4, .7, 1)
|
2024-08-16 10:06:39 +02:00
|
|
|
|
|
|
|
float4 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
float4 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 * WIDTH;
|
|
|
|
uint py = uv.y * 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);
|
|
|
|
|
2024-08-16 11:02:26 +02:00
|
|
|
// filler pixel
|
|
|
|
if (px == 8 && py == WIDTH - 8) return 0;
|
|
|
|
|
2024-08-16 10:06:39 +02:00
|
|
|
// Timing patterns
|
|
|
|
if (px == 6) return py & 1;
|
|
|
|
if (py == 6) return px & 1;
|
|
|
|
|
|
|
|
// Aligners
|
|
|
|
if (VERSION > 1
|
|
|
|
&& (px > 8 || py > 8) // top left
|
|
|
|
&& (px < WIDTH - 9 || py > 8) // top right
|
|
|
|
&& (py < WIDTH - 9 || px > 8) // bottom left
|
|
|
|
) {
|
|
|
|
// if (MISALIGNMENT != 0) return PINK;
|
|
|
|
|
|
|
|
uint x = px + ALIGNER_SPACING - 4;// - MISALIGNMENT;
|
|
|
|
uint y = py + ALIGNER_SPACING - 4;// - MISALIGNMENT;
|
|
|
|
// if (px > WIDTH-15) x -= MISALIGNMENT;
|
|
|
|
// if (py > WIDTH-15) y -= MISALIGNMENT;
|
|
|
|
// if (px < 10) {
|
|
|
|
// x += MISALIGNMENT;
|
|
|
|
// }
|
|
|
|
// if (py < 10) {
|
|
|
|
// y += MISALIGNMENT;
|
|
|
|
// }
|
|
|
|
uint ax = x % ALIGNER_SPACING;
|
|
|
|
uint ay = y % ALIGNER_SPACING;
|
2024-08-16 11:02:26 +02:00
|
|
|
if (ax < 5 && ay < 5) {
|
2024-08-16 10:06:39 +02:00
|
|
|
return (ax < 4 && ax > 0 && ay < 4 && ay > 0 && !(ax == 2 && ay == 2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format bits
|
2024-08-16 11:02:26 +02:00
|
|
|
if (px < 5 && py == 8) return (FORMAT_BITS & (1 << (4 - px))) == 0;
|
|
|
|
if (px == 8 && py > WIDTH - 6) return (FORMAT_BITS & (1 << py + 5 - WIDTH)) == 0;
|
|
|
|
|
|
|
|
if (px == 8 && (py < 9 || py > WIDTH - 9)) return PINK;
|
|
|
|
if (py == 8 && (px < 9 || px > WIDTH - 9)) return PINK;
|
2024-08-16 10:06:39 +02:00
|
|
|
|
|
|
|
uint column = (WIDTH - px - (px > 6))/2;
|
|
|
|
uint direction_up = column & 1;
|
2024-08-16 11:02:26 +02:00
|
|
|
return lerp(BLUE, PINK, column / (WIDTH/2.));
|
2024-08-16 10:06:39 +02:00
|
|
|
// return direction_up;
|
|
|
|
return 0.5;
|
|
|
|
}
|
|
|
|
|
2024-08-16 11:02:26 +02:00
|
|
|
void s (Input IN, inout SurfaceOutputStandard o) { o.Albedo = main(IN.uv_); }
|
2024-08-16 10:06:39 +02:00
|
|
|
ENDCG
|
|
|
|
}}
|