diff options
| author | yum <yum.food.vr@gmail.com> | 2023-08-09 18:54:17 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2023-08-09 18:54:17 -0700 |
| commit | 3bf013dc3b5479f4fbb458d44801403afe0bb1d2 (patch) | |
| tree | d91ef918797b2036e1005afa1e9b221d293b696f /Shaders/STT_text.cginc | |
| parent | 1285caf31578d758c2b52b915eedb17cc12a1826 (diff) | |
Add ray-marched custom chatbox
* Refactor shader code to make development easier. Templates are now
as small as possible.
* Update scaling code. Use Unity scaling instead of a blendshape.
* Check in a fuckton of shader FOSS. Mostly unused.
* Update TaSTT.fbx. Now has 6 faces instead of 2.
Diffstat (limited to 'Shaders/STT_text.cginc')
| -rw-r--r-- | Shaders/STT_text.cginc | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/Shaders/STT_text.cginc b/Shaders/STT_text.cginc new file mode 100644 index 0000000..1e7a96e --- /dev/null +++ b/Shaders/STT_text.cginc @@ -0,0 +1,187 @@ +#ifndef __STT_TEXT_INC__ +#define __STT_TEXT_INC__ + +#include "stt_generated.cginc" + +float Enable_Dithering; + +SamplerState linear_clamp_sampler; + +Texture2D _Font_0x0000_0x1FFF; +float4 _Font_0x0000_0x1FFF_TexelSize; +Texture2D _Font_0x2000_0x3FFF; +float4 _Font_0x2000_0x3FFF_TexelSize; +Texture2D _Font_0x4000_0x5FFF; +float4 _Font_0x4000_0x5FFF_TexelSize; +Texture2D _Font_0x6000_0x7FFF; +float4 _Font_0x6000_0x7FFF_TexelSize; +Texture2D _Font_0x8000_0x9FFF; +float4 _Font_0x8000_0x9FFF_TexelSize; +Texture2D _Font_0xA000_0xBFFF; +float4 _Font_0xA000_0xBFFF_TexelSize; +Texture2D _Font_0xC000_0xDFFF; +float4 _Font_0xC000_0xDFFF_TexelSize; +Texture2D _Img_0xE000_0xE03F; +float4 _Img_0xE000_0xE03F_TexelSize; + +float2 AddMarginToUV(float2 uv, float2 margin) +{ + float2 lo = float2(-margin.x / 2, -margin.y / 2); + float2 hi = float2(1.0 + margin.x / 2, 1.0 + margin.y / 2); + + return clamp(lerp(lo, hi, uv), 0.0, 1.0); +} + +// Generate a random number on [0, 1]. +float prng(float2 p) +{ + return frac(sin(dot(p, float2(561.0, 885.0))) * 776.2) / 2.0; +} + +bool f3ltf3(fixed3 a, fixed3 b) +{ + return a[0] < b[0] && + a[1] < b[1] && + a[2] < b[2]; +} + +// Write the nth letter in the current cell and return the value of the +// pixel. +// `texture_rows` and `texture_cols` indicate how many rows and columns are +// in the texture being sampled. +float2 GetLetterUV(float2 uv, int nth_letter, + float texture_cols, float texture_rows, + float board_cols, float board_rows, + float margin) +{ + // UV spans from [0,1] to [0,1]. + // 'U' is horizontal; cols. + // 'V' is vertical; rows. + // + // I want to divide the mesh into an m x n grid. + // I want to know what grid cell I'm in. This is simply u * m, v * n. + + // OK, I know what cell I'm in. Now I need to know how far across it I + // am. Produce a float in the range [0, 1). + float CHAR_FRAC_COL = uv.x * board_cols - floor(uv.x * board_cols); + float CHAR_FRAC_ROW = uv.y * board_rows - floor(uv.y * board_rows); + + // Avoid rendering pixels right on the edge of the slot. If we were to + // do this, then that value would get stretched due to clamping + // (AddMarginToUV), resulting in long lines on the edge of the display. + float lo = margin / 2; + float hi = 1.0 - margin / 2; + if (margin != 0 && + (CHAR_FRAC_ROW < lo || + CHAR_FRAC_COL < lo || + CHAR_FRAC_ROW > hi || + CHAR_FRAC_COL > hi)) { + return float2(-1, -1); + } + + float LETTER_COL = fmod(nth_letter, floor(texture_cols)); + float LETTER_ROW = floor(texture_rows) - floor(nth_letter / floor(texture_cols)); + + float LETTER_UV_ROW = (LETTER_ROW + CHAR_FRAC_ROW - 1.00) / texture_rows; + float LETTER_UV_COL = (LETTER_COL + CHAR_FRAC_COL) / texture_cols; + + float2 result; + result.x = LETTER_UV_COL; + result.y = LETTER_UV_ROW; + + return result; +} + +float4 GetLetter(float2 uv) { + fixed4 text = fixed4(0, 0, 0, 0); + bool discard_text = false; + + uint letter = GetLetterParameter(uv); + + float texture_cols; + float texture_rows; + float2 letter_uv; + bool is_emote = false; + if (letter < 0xE000) { + letter_uv = GetLetterUV(uv, letter % 0x2000, TEXTURE_NCOLS, TEXTURE_NROWS, BOARD_NCOLS, BOARD_NROWS, /*margin=*/0.02); + } else { + is_emote = true; + texture_cols = 16.0; + texture_rows = 8.0; + // This will need to be updated if we create multiple emote textures. + letter_uv = GetLetterUV(uv, letter % 0x2000, texture_cols, texture_rows, BOARD_NCOLS, BOARD_NROWS, /*margin=*/0); + } + + if (letter_uv.x == -1 && letter_uv.y == -1) { + discard_text = true; + } + + // We use ddx/ddy to get the correct mipmaps of the font textures. This + // confers 2 main benefits: + // 1. We don't use as much VRAM for distant players. + // 2. Glyphs anti-alias much more nicely. + const float iddx = ddx(letter_uv.x); + const float iddy = ddy(letter_uv.y); + + if (Enable_Dithering && !is_emote) { + // Add noise to UV. + // Here, iddx and iddy tell us how big the current UV cell is with respect to + // screen space (i.e. how many pixels wide it is). + float noise = frac(prng(letter_uv) + _Time[0]); + letter_uv.x += (noise - 0.5) * iddx / 4.0; + letter_uv.y += (noise - 0.5) * iddy / 4.0; + } + + int which_texture = (int) floor(letter / (uint) (64 * 128)); + [forcecase] switch (which_texture) + { + case 0: + // Divide iddx, iddy by 2.0 to remain on a higher-detail mip level for + // longer. + text += _Font_0x0000_0x1FFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 1: + text += _Font_0x2000_0x3FFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 2: + text += _Font_0x4000_0x5FFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 3: + text += _Font_0x6000_0x7FFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 4: + text += _Font_0x8000_0x9FFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 5: + text += _Font_0xA000_0xBFFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 6: + text += _Font_0xC000_0xDFFF.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + case 7: + text += _Img_0xE000_0xE03F.SampleGrad(linear_clamp_sampler, + letter_uv, iddx / 2.0, iddy / 2.0); + break; + default: + // Return some distinctive pattern that will look like a bug. + return fixed4(1, 0, _SinTime[0], 1); + } + + // The edges of each letter cell can be slightly grey due to mip maps. + // Detect this and shade it as the background. + fixed3 grey = 0.5; + if (f3ltf3(text.rgb, grey) || discard_text || is_emote) { + return 0; + } + return fixed4(text.rgb, 1); +} + +#endif // __STT_TEXT_INC__ + |
