yum/DisInfo

Simple HLSL text rendering utilities.

git clone https://git.yummers.dev/yum/DisInfo

yumInitial commita5e0aaf

master
2.8 KiB101 linesraw
1#ifndef __DISINFO_INC
2#define __DISINFO_INC
3
4/*
5 * A small font rendering library.
6 *
7 * Sample usage:
8 *
9 * fixed4 frag(v2f i) : SV_Target
10 * {
11 *   float2 uv = i.uv;
12 *   int2 cell_pos;
13 *   float2 cell_uv;
14 *   float2 res = int2(4, 4);
15 *   if (!getBoxLoc(uv, 0.1, 0.9, res, cell_pos, cell_uv)) {
16 *     return float4(0, 0, 0, 1);
17 *   }
18 *   float2 duv = float2(ddx(i.uv.x), ddy(i.uv.y)) / 4;
19 *   float4 font_color = renderInBox(67, cell_uv, duv);
20 * 
21 *   return font_color;
22 * }
23 */
24
25// `_Font` should be an 8x16 (8 rows, 16 columns) grid of monospace ASCII
26// glyphs.
27Texture2D _Font;
28float4 _Font_TexelSize;
29SamplerState linear_clamp_sampler;
30
31// Returns false if `uv` does not fall within `bounds`.
32bool remapUVSmaller(float2 uv, float2 bottom_left, float2 top_right,
33    out float2 uvr) {
34  if (!(uv.x > bottom_left.x && uv.x < top_right.x &&
35      uv.y > bottom_left.y && uv.y < top_right.y)) {
36    return false;
37  }
38
39  uvr = uv - bottom_left;
40  uvr = uvr / (top_right - bottom_left);
41
42  return true;
43}
44
45// bounds: the left/right/top/bottom bounds of the inner UV region,
46//     respectively.
47// Always returns true.
48bool remapUVBigger(float2 uv, float2 bottom_left, float2 top_right,
49    out float2 uvr) {
50  uvr = uv * (top_right - bottom_left) + bottom_left;
51
52  return true;
53}
54
55bool getBoxLoc(float2 uv, float2 bottom_left, float2 top_right,
56    int2 res, out int2 cell_pos, out float2 cell_uv)
57{
58  float2 box_uv;
59  if (!remapUVSmaller(uv, bottom_left, top_right, box_uv)) {
60    return false;
61  }
62
63  // The integer index of the cell pointed to by `uv`, on the interval
64  // [0, res.x - 1] * [0, res.y - 1]
65  cell_pos = fmod(floor(box_uv * res), res);
66
67  float2 box_sz = 1.0 / float2(res);
68  float2 cell_bot_left = cell_pos * box_sz;
69  float2 cell_top_right = (cell_pos + 1) * box_sz;
70  if (!remapUVSmaller(box_uv, cell_bot_left, cell_top_right, cell_uv)) {
71    // This should never happen Clueless
72    return false;
73  }
74
75  return true;
76}
77
78// `c` is a character encoded as ASCII.
79// `duv` is float2(ddx(i.uv.x), ddy(i.uv.y)), where `i.uv` is the UV of the
80//    object we're rendering on.
81float4 renderInBox(int c, float2 cell_uv, float2 duv)
82{
83  int2 bitmap_res = int2(16, 8);
84  int letter_idx = c;
85  int2 letter_pos = int2(
86      bitmap_res.x - (letter_idx % bitmap_res.x),
87      letter_idx / bitmap_res.x);
88  letter_pos.x = bitmap_res.x - letter_pos.x;
89  letter_pos.y = (bitmap_res.y - 1) - letter_pos.y;
90  float2 letter_box_sz = 1.0 / float2(bitmap_res);
91  float2 letter_bot_left = letter_pos * letter_box_sz;
92  float2 letter_top_right = (letter_pos + 1) * letter_box_sz;
93  float2 letter_uv;
94  remapUVBigger(cell_uv, letter_bot_left, letter_top_right, letter_uv);
95
96  float4 font_color = _Font.SampleGrad(linear_clamp_sampler, letter_uv, duv.x, duv.y);
97  return font_color;
98}
99
100#endif  // __DISINFO_INC
101