5.9 KiB
5.9 KiB
Text Rendering Implementation in VulkanWidget
Overview
This document describes the text rendering implementation added to the VulkanWidget using FreeType library.
Features Implemented
1. FreeType Integration
- Library: Uses system libfreetype.a (found at
/usr/local/lib/libfreetype.a) - Font Loading: Automatically searches common font paths:
/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf/usr/share/fonts/TTF/DejaVuSans.ttf/System/Library/Fonts/Helvetica.ttc(macOS)/usr/local/share/fonts/DejaVuSans.ttf
2. Font Atlas Generation
- Size: 512x512 texture atlas
- Character Range: ASCII 32-126 (95 printable characters)
- Format: Single-channel R8_UNORM texture
- Packing: Automatic row-based packing with 1-pixel padding
- Storage: CharInfo map stores texture coordinates, size, bearing, and advance for each character
3. Text Rendering Pipeline
- Shaders:
text.vert- Converts pixel coordinates to NDCtext.frag- Samples font atlas with alpha blending
- Blending: Alpha blending enabled for smooth text rendering
- Descriptors:
- Binding 0: Uniform Buffer (time, resolution, rotation, wavePhase)
- Binding 1: Font texture sampler
4. Text Content (Matching CustomWidget)
The text rendering displays the same information as CustomWidget:
Active State:
- Title: "Screen Lock Detector - Painting Active" (top center, white, scale 0.8)
- Statistics Box (top left, green, scale 0.6):
- Frame Count
- FPS: ~60
- Rotation angle
- Running Time
- Lock Info Box (below stats, magenta, scale 0.65/0.5):
- Last Lock Info title
- Lock time
- Duration
- Frame count at lock
- Total locks
- Hint: "Lock your screen..." (bottom center, yellow, scale 0.65)
Locked State:
- Title: "PAINTING DISABLED" (center, white, scale 1.2)
- Subtitle: "(Screen Locked)" (center, gray, scale 0.9)
- Stats: Total frames painted (bottom left, gray, scale 0.7)
Implementation Details
Code Structure
-
VulkanRenderer::initializeTextRendering()
- Initializes FreeType library
- Loads font face
- Generates character glyphs
- Creates font texture atlas
- Sets up Vulkan image, image view, and sampler
-
VulkanRenderer::createTextPipeline()
- Loads text vertex and fragment shaders
- Sets up vertex input (position, color, texCoord)
- Configures alpha blending
- Creates descriptor set layout with texture sampler
- Builds graphics pipeline
-
VulkanRenderer::generateTextQuads()
- Converts text string to quad vertices
- Handles newlines
- Uses pixel coordinates (shader converts to NDC)
- Sets texture coordinates from CharInfo map
- Applies scale and color
-
VulkanRenderer::drawText()
- Binds text pipeline
- Binds descriptor sets (UBO + font texture)
- Generates text quads based on painting state
- Creates temporary vertex/index buffers
- Issues draw calls
Coordinate System
- Input: Pixel coordinates (0,0 = top-left, width,height = bottom-right)
- Shader: Converts to NDC (-1,-1 = bottom-left, 1,1 = top-right)
- Y-axis: Flipped in shader (Vulkan Y-down → traditional Y-up)
Resource Management
- Font texture and sampler are persistent (created once)
- Text vertex/index buffers are recreated each frame (using static variables)
- Old buffers are destroyed before creating new ones
- Descriptor sets are updated after text rendering initialization
CMake Configuration
# FreeType support (for text rendering in Vulkan)
find_package(Freetype)
if(FREETYPE_FOUND)
target_include_directories(${PROJECT_NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${FREETYPE_LIBRARIES})
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_FREETYPE)
endif()
Debugging
Debug output is enabled every ~5 seconds (300 frames):
Initializing text rendering with FreeType...
Text rendering initialized successfully with 95 characters
Font texture: OK
Font texture view: OK
Font sampler: OK
Creating text pipeline...
Text pipeline created successfully
Updating descriptor sets with font texture...
Descriptor sets updated with font texture
drawText called: charMap=95 pipeline=OK fontTexView=OK
Drawing text with 572 vertices, 858 indices
Window size: 756x425
First vertex pos: (30.4, 1.2)
First vertex color: (1, 1, 1, 1)
Known Issues and Future Improvements
Current Limitations:
- Text buffers are recreated every frame (performance impact)
- No text caching or batching
- Limited to ASCII characters only
- Fixed font size (48pt base)
Potential Improvements:
- Implement text buffer caching for static text
- Add support for Unicode/UTF-8
- Multiple font sizes/styles
- Text layout system (word wrapping, alignment)
- Better memory management for text resources
- Dynamic font atlas resizing
- SDF (Signed Distance Field) rendering for scalable text
Testing
To verify text rendering:
- Build project:
./build.sh - Run application:
./run.sh - Check console for text rendering initialization messages
- Verify text appears on screen matching CustomWidget layout
- Lock screen to test state changes
Dependencies
- FreeType 2.x
- Vulkan 1.x
- Volk (for Vulkan function loading)
- Qt 5.15.x (for window management)
Files Modified
CMakeLists.txt- Added FreeType supportsrc/vulkanrenderer.h- Added text rendering declarationssrc/vulkanrenderer.cpp- Implemented text rendering functionsshaders/text.vert- Text vertex shadershaders/text.frag- Text fragment shader
References
- FreeType Documentation: https://freetype.org/freetype2/docs/
- Vulkan Text Rendering: https://learnopengl.com/In-Practice/Text-Rendering
- Font Atlas Generation: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02