// struct TerminalCell { // cell index into GlyphTexture, should be two 16-bit (x,y) values packed: "x | (y << 16)" uint GlyphIndex; // 0xAABBGGRR encoded colors, nonzero alpha for Foreground indicates to render colored-glyph // which means use RGB values from GlyphTexture directly as output, not as ClearType blending weights uint Foreground; uint Background; }; cbuffer ConstBuffer : register(b0) { uint2 CellSize; uint2 TermSize; }; // TermSize.x * TermSize.y amount of cells to render as output StructuredBuffer Cells : register(t0); // RGB blending weights for ClearType // or alpha-premultipled RGB values for colored glyphs Texture2D GlyphTexture : register(t1); RWTexture2D Output : register(u0); float3 GetColor(uint i) { int r = i & 0xff; int g = (i >> 8) & 0xff; int b = (i >> 16) & 0xff; return float3(r, g, b) / 255.0; } uint2 GetGlyphPos(uint GlyphIndex) { return uint2(GlyphIndex & 0xffff, GlyphIndex >> 16) * CellSize; } // dispatch with (TermSize*CellSize+7)/8 groups for x,y and 1 for z [numthreads(8, 8, 1)] void shader(uint3 Id: SV_DispatchThreadID) { uint2 ScreenPos = Id.xy; // index of cell on screen uint2 CellIndex = ScreenPos / CellSize; // pixel position in cell uint2 CellPos = ScreenPos % CellSize; TerminalCell Cell = Cells[CellIndex.y * TermSize.x + CellIndex.x]; // position where glyph starts in texture uint2 GlyphPos = GetGlyphPos(Cell.GlyphIndex); // absolute pixel location in texture to use for output uint2 PixelPos = GlyphPos + CellPos; float4 Tex = GlyphTexture[PixelPos]; float3 Background = GetColor(Cell.Background); float3 Foreground = GetColor(Cell.Foreground); bool ColoredGlyph = (Cell.Foreground >> 24) != 0; float3 Color; if (ColoredGlyph) { // colored glyphs are alpha premultiplied Color = Background * (1.0 - Tex.a) + Tex.rgb; } else { // TODO: proper ClearType blending Color = lerp(Background, Foreground, Tex.rgb); } Output[ScreenPos] = float4(Color, 1); }