2024-08-16 10:06:39 +02:00
|
|
|
Shader "CrispyPin/QRCode" {
|
|
|
|
Properties {
|
|
|
|
[HideInInspector]
|
2024-08-17 12:24:04 +02:00
|
|
|
_("",2D)=""{}
|
|
|
|
_Version("Version", Range(1, 40)) = 1
|
2024-08-17 15:42:09 +02:00
|
|
|
_Mask("Mask type", Range(0, 7)) = 1
|
|
|
|
[Toggle]
|
|
|
|
_DisableMask("Hide mask", Integer) = 0
|
2024-08-18 17:59:26 +02:00
|
|
|
[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
|
2024-08-16 10:06:39 +02:00
|
|
|
}
|
|
|
|
SubShader {
|
|
|
|
Tags { "RenderType"="Opaque" }
|
|
|
|
LOD 100
|
|
|
|
CGPROGRAM
|
|
|
|
#pragma surface s Standard
|
|
|
|
struct Input{float2 uv_;};
|
|
|
|
uint _Version;
|
2024-08-17 15:42:09 +02:00
|
|
|
uint _Mask;
|
|
|
|
bool _DisableMask;
|
2024-08-18 17:59:26 +02:00
|
|
|
bool _Animate;
|
2024-08-17 14:24:02 +02:00
|
|
|
float _TimeSlider;
|
2024-08-18 17:59:26 +02:00
|
|
|
float _TimeSliderCoarse;
|
|
|
|
float _AnimationSpeed;
|
2024-08-16 10:06:39 +02:00
|
|
|
|
|
|
|
#define VERSION _Version
|
2024-08-16 11:02:26 +02:00
|
|
|
#define WIDTH (17 + VERSION * 4)
|
2024-08-17 12:24:04 +02:00
|
|
|
#define PIXEL_WIDTH WIDTH
|
|
|
|
// #define PIXEL_WIDTH 177
|
2024-08-16 10:06:39 +02:00
|
|
|
#define ALIGNERS ((VERSION / 7) + 2)
|
2024-08-16 15:21:34 +02:00
|
|
|
#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)
|
2024-08-21 14:36:55 +02:00
|
|
|
#define ALIGNER_COUNT ((ALIGNERS * ALIGNERS - 3) * (VERSION > 1))
|
|
|
|
#define BIT_COUNT (WIDTH * WIDTH - 225 - (WIDTH - 17)*2 - 25 * ALIGNER_COUNT + 10*(ALIGNERS-2)*(ALIGNERS>2) - 36 * (VERSION > 6))
|
2024-08-18 17:59:26 +02:00
|
|
|
#define TIME_MANUAL (_TimeSlider + _TimeSliderCoarse*100)
|
|
|
|
#define TIME (uint)(_Animate ? _Time.y * _AnimationSpeed + TIME_MANUAL : TIME_MANUAL)
|
2024-08-16 10:06:39 +02:00
|
|
|
|
2024-08-16 14:46:24 +02:00
|
|
|
#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
|
2024-08-17 15:42:09 +02:00
|
|
|
#define MASK_TYPE _Mask
|
|
|
|
// ECI_MODE 0100 = byte
|
|
|
|
#define ECI_MODE 4
|
2024-08-16 14:46:24 +02:00
|
|
|
|
|
|
|
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]
|
2024-08-16 11:02:26 +02:00
|
|
|
|
2024-08-18 18:30:25 +02:00
|
|
|
static const uint VERSION_BIT_SETS[34] = {0x07C94,0x085BC,0x09A99,0x0A4D3,0x0BBF6,0x0C762,0x0D847,0x0E60D,0x0F928,0x10B78,0x1145D,0x12A17,0x13532,0x149A6,0x15683,0x168C9,0x177EC,0x18EC4,0x191E1,0x1AFAB,0x1B08E,0x1CC1A,0x1D33F,0x1ED75,0x1F250,0x209D5,0x216F0,0x228BA,0x2379F,0x24B0B,0x2542E,0x26A64,0x27541,0x28C69};
|
|
|
|
#define VERSION_BITS (VERSION > 6 ? VERSION_BIT_SETS[VERSION - 7] : 0)
|
|
|
|
|
2024-08-16 10:06:39 +02:00
|
|
|
#define WHITE 1
|
|
|
|
#define BLACK 0
|
2024-08-17 12:24:04 +02:00
|
|
|
#define PINK float3(1, .3, .5)
|
|
|
|
#define BLUE float3(0, .4, .7)
|
2024-08-16 10:06:39 +02:00
|
|
|
|
2024-08-17 12:24:04 +02:00
|
|
|
float3 finder_pattern(uint x, uint y) {
|
2024-08-16 10:06:39 +02:00
|
|
|
if (x < 6 && x > 0 && y < 6 && y > 0) return !(x < 5 && x > 1 && y < 5 && y > 1);
|
|
|
|
return (x > 6 || y > 6);
|
|
|
|
}
|
|
|
|
|
2024-08-17 12:24:04 +02:00
|
|
|
float3 main (float2 uv){
|
2024-08-17 23:44:40 +02:00
|
|
|
// "hell", "o wo", "rld!"
|
|
|
|
const uint data[] = {0x68656c6c,0x6f20776f,0x726c6421,
|
|
|
|
// 4 bits 0 padding to align to byte (4 bit ECI_MODE is inserted before data and length)
|
|
|
|
// then ec11ec11... until some version-specific length reached?
|
|
|
|
// then EC data
|
|
|
|
0x0ec11ec1, 0x1ec2d631, 0x95423722, 0xe0000000
|
|
|
|
};
|
|
|
|
const uint data_len = 3*4;
|
|
|
|
const uint total_len = 7*4;
|
2024-08-16 10:06:39 +02:00
|
|
|
uv.y = 1 - uv.y;
|
2024-08-18 17:59:26 +02:00
|
|
|
uv = uv * 1.2 - 0.1;
|
2024-08-17 23:44:40 +02:00
|
|
|
// Quiet zone/frame
|
2024-08-18 17:59:26 +02:00
|
|
|
if (uv.x < 0 || uv.x > 1 || uv.y < 0 || uv.y > 1) return 1;
|
2024-08-16 10:06:39 +02:00
|
|
|
|
2024-08-17 12:24:04 +02:00
|
|
|
uint px = uv.x * PIXEL_WIDTH;
|
|
|
|
uint py = uv.y * PIXEL_WIDTH;
|
2024-08-16 10:06:39 +02:00
|
|
|
|
|
|
|
// 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
|
2024-08-16 15:21:34 +02:00
|
|
|
&& (px > 12 || py > 12) // top left
|
|
|
|
&& (px < WIDTH - 13 || py > 12) // top right
|
|
|
|
&& (py < WIDTH - 13 || px > 12) // bottom left
|
2024-08-16 10:06:39 +02:00
|
|
|
) {
|
2024-08-17 12:24:04 +02:00
|
|
|
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));
|
2024-08-16 10:06:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format bits
|
2024-08-16 14:46:24 +02:00
|
|
|
// 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;
|
2024-08-16 10:06:39 +02:00
|
|
|
|
2024-08-18 18:30:25 +02:00
|
|
|
// version information
|
|
|
|
if (VERSION > 6) {
|
|
|
|
if (px < 6 && py > WIDTH - 12) {
|
|
|
|
uint b = px * 3 + py - (WIDTH - 11) ;
|
|
|
|
return ((VERSION_BITS >> b) & 1) == 0;
|
|
|
|
}
|
|
|
|
if (px > WIDTH - 12 && py < 6) {
|
|
|
|
uint b = px - (WIDTH - 11) + py * 3;
|
|
|
|
return ((VERSION_BITS >> b) & 1) == 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-17 14:24:02 +02:00
|
|
|
// data bit layout
|
|
|
|
uint column = (WIDTH - px - (px < 6)-1)/2;
|
|
|
|
uint direction_up = column % 2 == 0;
|
|
|
|
uint full_columns = column > 4 ? column - 4 : 0;
|
|
|
|
full_columns = min(full_columns, VERSION*2);
|
|
|
|
// the 4 columns under the right finder
|
|
|
|
uint short_columns = min(column, 4);
|
|
|
|
// between the left two finder patterns
|
|
|
|
uint tiny_columns = column > (VERSION*2 + 4) ? column - (VERSION*2 + 4) : 0;
|
|
|
|
uint bit_index = full_columns * (WIDTH - 1) * 2;
|
|
|
|
bit_index += short_columns * (WIDTH - 9) * 2;
|
|
|
|
bit_index += tiny_columns * (WIDTH - 17) * 2;
|
|
|
|
bit_index += (px + (px < 6)) % 2;
|
2024-08-17 23:44:40 +02:00
|
|
|
uint column_progress;
|
2024-08-18 17:59:26 +02:00
|
|
|
uint y_relative;
|
|
|
|
if (direction_up) {
|
|
|
|
y_relative = WIDTH - py - 1;
|
2024-08-17 23:44:40 +02:00
|
|
|
column_progress = WIDTH - py - 1 - (py < 7);
|
2024-08-18 17:59:26 +02:00
|
|
|
} else {
|
|
|
|
y_relative = py;
|
2024-08-17 23:44:40 +02:00
|
|
|
column_progress = py - ((full_columns == 0) ? 9 : (py > 6));
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
2024-08-17 23:44:40 +02:00
|
|
|
bit_index += column_progress * 2;
|
2024-08-17 14:24:02 +02:00
|
|
|
|
|
|
|
if (px < 9) bit_index -= 16; // rightmost tiny column
|
|
|
|
|
2024-08-17 23:44:40 +02:00
|
|
|
// data bit layout - aligners
|
|
|
|
if (VERSION > 1 && column > 1) {
|
|
|
|
// aligners always cover a half column to the left and two full columns to the right
|
|
|
|
// outer aligners are always 4 from all edges
|
|
|
|
|
2024-08-21 14:36:55 +02:00
|
|
|
if (VERSION > 6) {
|
|
|
|
// top version info section
|
|
|
|
if (column == 5){
|
|
|
|
bit_index -= 12;
|
|
|
|
bit_index -= min(py + 1, 6);
|
|
|
|
} else if (column > 5) {
|
|
|
|
bit_index -= 18;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-18 17:59:26 +02:00
|
|
|
uint aligner_col = (column - 2) / (ALIGNER_SPACING/2);
|
|
|
|
uint aligner_col_mod = (column - 2) % (ALIGNER_SPACING/2);
|
2024-08-21 14:36:55 +02:00
|
|
|
if (aligner_col > (ALIGNERS - 2)){
|
|
|
|
aligner_col_mod = (column-2) - (aligner_col-1) * (ALIGNER_SPACING/2);
|
|
|
|
aligner_col -= 1;
|
|
|
|
}
|
2024-08-18 17:59:26 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-21 14:36:55 +02:00
|
|
|
uint passed_up = min((y_relative - 9 + ALIGNER_SPACING)/ALIGNER_SPACING, ALIGNERS-1);
|
2024-08-18 17:59:26 +02:00
|
|
|
|
2024-08-21 14:36:55 +02:00
|
|
|
#define ALIGNER_GRID_Y_START (WIDTH - 9 - ALIGNER_SPACING * (ALIGNERS - 1))
|
|
|
|
|
|
|
|
uint passed_down = py > ALIGNER_GRID_Y_START ? (py - ALIGNER_GRID_Y_START) / ALIGNER_SPACING : 0;
|
|
|
|
|
|
|
|
if (px < 9) {
|
|
|
|
if (passed_up>0) passed_up -= 1;
|
|
|
|
if (passed_down>(ALIGNERS-2)) passed_down-=1;
|
|
|
|
// if (passed_down>0) return 5;
|
|
|
|
// if (passed_up>0) return 5;
|
|
|
|
if (tiny_columns == 0) {
|
|
|
|
bit_index -= passed_up*10;
|
|
|
|
} else if (tiny_columns == 1) {
|
|
|
|
// bit_index += 16;
|
|
|
|
bit_index -= passed_down*10;
|
|
|
|
bit_index -= (ALIGNERS-2)*10;
|
|
|
|
} else if (tiny_columns == 2) {
|
|
|
|
if (VERSION > 6) {
|
|
|
|
bit_index -= 12;
|
|
|
|
}
|
|
|
|
bit_index -= (ALIGNERS-2) * 20;
|
|
|
|
} else if (tiny_columns == 3) {
|
|
|
|
if (VERSION > 6) {
|
|
|
|
bit_index -= 12;
|
|
|
|
bit_index -= (ALIGNERS-2)*20;
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
|
|
|
}
|
2024-08-21 14:36:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aligner_col_mod == 0) {
|
|
|
|
if (direction_up) {
|
|
|
|
bit_index -= passed_up * 10;
|
|
|
|
if (py < 8)
|
|
|
|
bit_index -= 8;
|
|
|
|
} else {
|
|
|
|
bit_index -= passed_down * 10;
|
|
|
|
if (py > 8)
|
|
|
|
bit_index -= 8;
|
|
|
|
}
|
2024-08-18 17:59:26 +02:00
|
|
|
} else if (aligner_col_mod == 1) {
|
2024-08-21 14:36:55 +02:00
|
|
|
if (column > 3){
|
|
|
|
bit_index -= ALIGNERS*10 - 2;
|
2024-08-18 17:59:26 +02:00
|
|
|
} else {
|
2024-08-21 14:36:55 +02:00
|
|
|
bit_index -= ALIGNERS*10;
|
|
|
|
bit_index += 26; // right finder
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
2024-08-21 14:36:55 +02:00
|
|
|
if (direction_up){
|
|
|
|
bit_index -= passed_up*10;
|
|
|
|
if (py < 5)
|
|
|
|
bit_index -= 8;
|
|
|
|
} else {
|
|
|
|
bit_index -= passed_down*10;
|
|
|
|
if (py > 8)
|
|
|
|
bit_index -= 8;
|
|
|
|
if (column == 3)
|
|
|
|
bit_index -= 8;
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
2024-08-21 14:36:55 +02:00
|
|
|
} else if (aligner_col_mod == 2 && px > 5) {
|
2024-08-17 23:44:40 +02:00
|
|
|
bit_index -= (ALIGNERS - 1) * 20;
|
2024-08-21 14:36:55 +02:00
|
|
|
if (aligner_col > 0)
|
2024-08-18 17:59:26 +02:00
|
|
|
bit_index -= 16; // most of the current column top aligner, excluding the left 4 pixels
|
2024-08-21 14:36:55 +02:00
|
|
|
if (direction_up) {
|
|
|
|
bit_index -= passed_up*5;
|
|
|
|
uint progress = (y_relative - 4) % ALIGNER_SPACING;
|
|
|
|
if (y_relative - 4 >= ALIGNER_SPACING*(ALIGNERS-1)) {
|
|
|
|
progress = 999;
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
2024-08-21 14:36:55 +02:00
|
|
|
if (progress < 5) {
|
|
|
|
bit_index -= progress+1;
|
|
|
|
}
|
|
|
|
if (py < 9) {
|
|
|
|
if (py < 4)
|
|
|
|
bit_index -= 4;
|
|
|
|
else
|
|
|
|
bit_index -= (9-py) - (py<6);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bit_index -= passed_down*5;
|
|
|
|
if (py < 6 && py > 3) {
|
|
|
|
bit_index -= py-3;
|
|
|
|
}
|
|
|
|
else if (py < 9 && py > 6) {
|
|
|
|
bit_index -= py-4;
|
|
|
|
} else if (py > 8){
|
|
|
|
bit_index -= 4;
|
2024-08-18 17:59:26 +02:00
|
|
|
}
|
|
|
|
|
2024-08-21 14:36:55 +02:00
|
|
|
uint progress = (py - ALIGNER_GRID_Y_START) % ALIGNER_SPACING;
|
|
|
|
if (py < WIDTH-((ALIGNERS-1)*ALIGNER_SPACING+4)) {
|
|
|
|
progress = 999;
|
|
|
|
}
|
|
|
|
if (progress < 5) {
|
|
|
|
bit_index -= progress;
|
|
|
|
bit_index += 4;
|
|
|
|
}
|
2024-08-17 23:44:40 +02:00
|
|
|
}
|
|
|
|
|
2024-08-21 14:36:55 +02:00
|
|
|
} else if (aligner_col_mod > 2) { // include the full column of aligners
|
2024-08-18 17:59:26 +02:00
|
|
|
bit_index -= (ALIGNERS - 1)*25;
|
|
|
|
if (aligner_col > 0){
|
|
|
|
bit_index -= 20;
|
|
|
|
}
|
|
|
|
}
|
2024-08-17 23:44:40 +02:00
|
|
|
}
|
|
|
|
|
2024-08-17 15:42:09 +02:00
|
|
|
// data
|
|
|
|
uint bit = 0;
|
|
|
|
if (bit_index < 4){
|
|
|
|
bit = (ECI_MODE >> (3-bit_index))&1;
|
|
|
|
} else if (bit_index < 12) {
|
|
|
|
bit = (data_len >> (7 - (bit_index - 4))) & 1;
|
2024-08-17 23:44:40 +02:00
|
|
|
} else if (bit_index < total_len*8 + 12){
|
2024-08-17 15:42:09 +02:00
|
|
|
uint data_bit_index = bit_index - 12;
|
|
|
|
bit = ((data[data_bit_index/32] >> (31-(data_bit_index % 32))) & 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// mask
|
|
|
|
uint mask;
|
|
|
|
switch (_Mask){
|
|
|
|
case 0:
|
|
|
|
mask = (px+py) % 2 == 0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
mask = py % 2 == 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
mask = px % 3 == 0;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
mask = (px+py) % 3 == 0;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
mask = (py/2 + px/3) % 2 == 0;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
mask = (py*px)%2 + (px*py)%3 == 0;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
mask = ((py*px)%2 + (px*py)%3) % 2 == 0;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
mask = ((py+px)%2 + (px*py)%3) % 2 == 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!_DisableMask) {
|
|
|
|
bit ^= mask;
|
|
|
|
}
|
|
|
|
|
2024-08-17 23:44:40 +02:00
|
|
|
// return !bit;
|
2024-08-17 15:42:09 +02:00
|
|
|
|
2024-08-17 23:44:40 +02:00
|
|
|
// bit index debugging worm
|
2024-08-18 17:59:26 +02:00
|
|
|
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));
|
2024-08-21 14:36:55 +02:00
|
|
|
if (bit_index >= BIT_COUNT) return float3(1,0,0);
|
2024-08-18 17:59:26 +02:00
|
|
|
// #define BIT_COUNT 24
|
2024-08-17 23:44:40 +02:00
|
|
|
return (float)(bit_index%BIT_COUNT)/(float)BIT_COUNT;
|
2024-08-16 10:06:39 +02:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}}
|