{"id":21296399,"url":"https://github.com/zlogic/hypno-toadface","last_synced_at":"2025-10-03T19:49:32.164Z","repository":{"id":239023835,"uuid":"795241906","full_name":"zlogic/hypno-toadface","owner":"zlogic","description":"Hypno Toadface","archived":false,"fork":false,"pushed_at":"2025-09-27T14:59:38.000Z","size":133,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-27T16:28:44.792Z","etag":null,"topics":["alsa","direct-rendering-manager","drm","ioctl","vulkan"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zlogic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-05-02T21:38:16.000Z","updated_at":"2025-09-27T14:59:41.000Z","dependencies_parsed_at":"2024-11-12T23:24:54.772Z","dependency_job_id":"aae5dc42-34a5-4eb5-b427-e85b69559d6e","html_url":"https://github.com/zlogic/hypno-toadface","commit_stats":null,"previous_names":["zlogic/hypno-toadface"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/zlogic/hypno-toadface","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlogic%2Fhypno-toadface","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlogic%2Fhypno-toadface/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlogic%2Fhypno-toadface/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlogic%2Fhypno-toadface/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zlogic","download_url":"https://codeload.github.com/zlogic/hypno-toadface/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlogic%2Fhypno-toadface/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278219761,"owners_count":25950349,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-03T02:00:06.070Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alsa","direct-rendering-manager","drm","ioctl","vulkan"],"created_at":"2024-11-21T14:26:18.767Z","updated_at":"2025-10-03T19:49:32.109Z","avatar_url":"https://github.com/zlogic.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hypno Toadface\n\nThis is a weekend project, attempting to display some graphics using Linux ~DRM (Direct Rendering Manager)~ Vulkan's `VK_KHR_surface` and `VK_KHR_display` extensions.\n\nIn addition, it can also play audio using the ALSA API, without an audio server - using kernel ioctls.\n\nhttps://private-user-images.githubusercontent.com/815726/332149344-c367155a-953c-468c-aa67-261616c17d19.mov\n\n## Why?\n\nDo something cool with a headless server that has HDMI output and barebones CoreOS.\nNo X or Wayland is required, because it renders directly to the display surface.\n\nWhen connected to a 4K TV, show something interesting instead of a login console with a tiny font.\n\nThis works well on an off-brand digital signage appliance (NUC) with a Celeron CPU N3350 CPU and 4GB RAM, and maxes out at 30 FPS when rendering 4K images\n(most likely it's limited by the HDMI interface).\n\n## How to run it\n\nBuild and run as a regular Rust project:\n\n```shell\n./hypno-toadface [--speed=\u003cspeed\u003e] [--shader-file=\u003cfilename\u003e] [--sound=\u003cdevicepath\u003e] [--no-print-fps] [--keep-last-frame]\n```\n\n`--speed=\u003cspeed\u003e` is an optional argument to specify how fast the animation should be playing, for example `--speed=0.1`. The default speed is 0.04. Negative values make the animation run in reverse.\n\n`--shader-file=\u003cfilename\u003e` is an optional argument to specify the filename for a custom SPIR-V fragment shader. If not provided, the default shader will be used.\n\n`--sound=\u003cdevicepath\u003e` specifies a path to the ALSA sound device, for example `--sound=/dev/snd/pcmC0D3p`. If not specified, no sound will be played.\n\n`--no-print-fps` turns off printing the FPS counter.\n\n`--keep-last-frame` saves the last frame and binds it as a texture (`layout (binding = 1) uniform sampler2D previousImage;`). It can be accessed as `texture(previousImage, coord)` in a shader. As this has a performance impact, this feature is disabled by default.\n\n⚠️ This project works without a windowing manager, but in Linux only one device can have exclusive access to the GPU. If X or Wayland is running, using the GPU would be impossible. To run this project, stop any windowing managers.\n\nAs accessing displays and audio requires elevated privileges, the safest way to get them is by adding a user to the `video` and `audio` groups:\n\n```shell\n# Required for CoreOS with a sparse /etc/group\ngetent group video \u003e\u003e /etc/group\ngetent group audio \u003e\u003e /etc/group\nusermod -a -G video,audio $USERNAME\n```\n\nIf SELinux is enabled, make sure that `/etc/group` has the right label by running `ls -Z /etc/group`, it should look something like this:\n\n```\nsystem_u:object_r:passwd_file_t:s0 /etc/group\n```\n\n## Run as a systemd service\n\nCreate a systemd unit file:\n\n```shell\ncat \u003c\u003cEOF \u003e ~/.config/systemd/user/hypno-toadface.service\n[Unit]\nDescription=Hypno Toadface\n\n[Service]\nType=exec\nExecStart=/var/home/core/.local/bin/hypno-toadface --no-print-fps --sound=/dev/snd/pcmC0D3p\nKillMode=process\nRestart=on-failure\n\n[Install]\nWantedBy=default.target\nEOF\n```\n\nand start it without logging in:\n\n```shell\nsudo loginctl enable-linger $USER\n```\n\n## Fun fact\n\nIntel HD graphics GPUs have issues with trigonometric functions if the numbers are too large. `sin(x)` starts producing incorrect results if x is larger than 14000, as seen [in this demo](https://www.shadertoy.com/view/4lBcWh). The fix is replacing `sin(x)` with `sin(mod(x, M_PI*2.0))`.\n\n## References:\n\n* [Vulkan Tutorial](https://vulkan-tutorial.com) - an Excellent tutorial on using Vulkan\n* [KMS GLSL](https://github.com/astefanutti/kms-glsl) - a similar project, but using DRM/KMS\n* [Shadertoy](https://www.shadertoy.com) - a collection of really impressive shaders\n* [Raw ALSA player](https://github.com/PHJArea217/raw-alsa-player) - a pure C example how to play audio without an audioserver\n* [Generating pink noise](https://www.firstpr.com.au/dsp/pink-noise/)\n* [Colored noise generator](https://mynoise.net/NoiseMachines/whiteNoiseGenerator.php) - a neat noise generator with a lot of fine tuning\n* [Biquad calculator](https://www.earlevel.com/main/2021/09/02/biquad-calculator-v3/) - showing a frequency response graph for a biquad filter\n\nALL GLORY TO THE HYPNOTOAD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlogic%2Fhypno-toadface","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzlogic%2Fhypno-toadface","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlogic%2Fhypno-toadface/lists"}