summaryrefslogtreecommitdiffstats
path: root/letter_grid.cginc
blob: 9e88fab7f8123edfe2bbb2b429cc5e680fdc9db7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#ifndef __LETTER_GRID_INC
#define __LETTER_GRID_INC

#include "disinfo.cginc"
#include "features.cginc"
#include "globals.cginc"
#include "interpolators.cginc"
#include "math.cginc"
#include "texture_utils.cginc"

#if defined(_LETTER_GRID)

struct LetterGridOutput {
  float4 albedo;
  float metallic;
  float roughness;
  float3 emission;
};

LetterGridOutput LetterGrid(v2f i) {
    LetterGridOutput output;

    int2 font_res = int2(round(_Letter_Grid_Tex_Res_X), round(_Letter_Grid_Tex_Res_Y));
    int2 grid_res = int2(round(_Letter_Grid_Res_X), round(_Letter_Grid_Res_Y));

    float4 scoff = _Letter_Grid_UV_Scale_Offset;
    float2 base_uv = get_uv_by_channel(i, _Letter_Grid_UV_Channel);
    float2 uv = ((base_uv - 0.5) - scoff.zw) * scoff.xy + 0.5;

    int2 cell_pos;
    float2 cell_uv;  // uv within each letter cell
    bool in_box = getBoxLoc(uv, 0, 1, grid_res, _Letter_Grid_Padding, cell_pos, cell_uv);

    // Extract char from _Letter_Grid_Data_Row_0 et al using cell_pos.
    cell_pos.y = (grid_res.y - cell_pos.y) - 1;
    float c = lerp(
        lerp(
        _Letter_Grid_Data_Row_0[cell_pos.x],
        _Letter_Grid_Data_Row_1[cell_pos.x],
        cell_pos.y),
        lerp(
        _Letter_Grid_Data_Row_2[cell_pos.x],
        _Letter_Grid_Data_Row_3[cell_pos.x],
        cell_pos.y - 2),
        cell_pos.y/2);
    c += _Letter_Grid_Global_Offset;
#if defined(_LETTER_GRID_ANIMATE)
    // Sweep cells left-to-right, then top-to-bottom. One full sweep takes
    // _Letter_Grid_Animate_Speed seconds, so each slot updates once per sweep.
    int slot_count = max(grid_res.x * grid_res.y, 1);
    int slot_index = cell_pos.y * grid_res.x + cell_pos.x;
    int sweep_step = (int)floor((_Time.y * _Letter_Grid_Animate_Speed) * slot_count);
    int slot_change_count = (sweep_step + slot_count - slot_index) / slot_count;

    int glyph_count = max(font_res.x * font_res.y, 1);
    int base_char = (int)round(c);
    uint rand_u = hash31_u32(uint3(
        (uint)slot_index,
        (uint)slot_change_count,
        asuint(base_char)));
    c = (float)(rand_u % glyph_count);
#endif

    float3 msd = renderInBox(c, uv, cell_uv, _Letter_Grid_Texture, font_res).rgb;
    float sd = median(msd);

    float screen_px_range;
    {
        float2 tex_size = float2(_Letter_Grid_Texture_TexelSize.zw);
        float2 glyph_tex_size = tex_size / float2(font_res);
        float2 unit_range = _Letter_Grid_Screen_Px_Range / glyph_tex_size;
        float2 screen_tex_size = 1.0 / max(fwidth(cell_uv), float2(1e-4, 1e-4));
        screen_px_range = max(0.5 * dot(unit_range, screen_tex_size), _Letter_Grid_Min_Screen_Px_Range);
    }

    float screen_px_distance = screen_px_range * (sd - _Letter_Grid_Alpha_Threshold);
    float edge_softness = max(exp2((_Letter_Grid_Blurriness - 0.5) * 2.0), 1e-4);
    float op = saturate(screen_px_distance / edge_softness + 0.5);

    // Apply blending to output
    output.albedo = float4(_Letter_Grid_Color.rgb, op * in_box);
    output.metallic = _Letter_Grid_Metallic;
    output.roughness = _Letter_Grid_Roughness;
    output.emission = _Letter_Grid_Color.rgb * _Letter_Grid_Emission;

    return output;
}

#endif  // _LETTER_GRID

#endif  // __LETTER_GRID_INC