{"id":14225391,"url":"https://github.com/polyfloyd/shady","last_synced_at":"2025-04-05T21:07:35.389Z","repository":{"id":28177878,"uuid":"116586868","full_name":"polyfloyd/shady","owner":"polyfloyd","description":"CLI tool to render GLSL shaders","archived":false,"fork":false,"pushed_at":"2025-03-09T19:57:17.000Z","size":31793,"stargazers_count":122,"open_issues_count":6,"forks_count":8,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-29T20:05:13.318Z","etag":null,"topics":["glsl","glslviewer","raytracing","shadertoy"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/polyfloyd.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}},"created_at":"2018-01-07T17:53:53.000Z","updated_at":"2025-03-09T19:56:57.000Z","dependencies_parsed_at":"2024-06-20T13:14:35.105Z","dependency_job_id":null,"html_url":"https://github.com/polyfloyd/shady","commit_stats":{"total_commits":177,"total_committers":2,"mean_commits":88.5,"dds":0.005649717514124242,"last_synced_commit":"49f6562d4e67d23f32e0a0b39ff00bba4a154177"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polyfloyd%2Fshady","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polyfloyd%2Fshady/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polyfloyd%2Fshady/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/polyfloyd%2Fshady/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/polyfloyd","download_url":"https://codeload.github.com/polyfloyd/shady/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399877,"owners_count":20932876,"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","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":["glsl","glslviewer","raytracing","shadertoy"],"created_at":"2024-08-20T01:00:50.380Z","updated_at":"2025-04-05T21:07:35.370Z","avatar_url":"https://github.com/polyfloyd.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"Shady\n=====\n[![Build Status](https://github.com/polyfloyd/shady/workflows/CI/badge.svg)](https://github.com/polyfloyd/shady/actions)\n\nShady is a nifty CLI tool for rendering GLSL fragment shaders for easy\ndevelopment and hacking.\n\n\n## Usage\n### Installation\n```sh\ngo install github.com/polyfloyd/shady/cmd/shady@latest\n```\n\n### Shadertoy\n* https://shadertoy.com/\n\nThe basic setup is a single fragment shader, like a regular fragments shader,\ncalculates the color for each pixel. But instead of receiving vertex and normal\nand transformation information from the vertex shader, it defines it's own\nalgorithm for shapes.\n\nThe best supported format/environment for shaders is that of Shadertoy.com.\nExample:\n```\nvoid mainImage(out vec4 fragColor, in vec2 fragCoord) {\n  vec2 uv = fragCoord.xy / iResolution.xy;\n  fragColor = vec4(uv.x, uv.y, 0, 1);\n}\n```\n\nCurrently, the `iTime`, `iTimeDelta`, `iFrame`, `iDate`, `iMouse`, and\n`iResolution`, `iChannelResolution` uniforms are supported. Other uniforms are\ndefined but not initialized.\n\nSee also https://www.shadertoy.com/howto for info on how to write shaders for\nShadertoy.\n\n### Including other source files\nTo include another GLSL file, you may use the directive below:\n```glsl\n#pragma use \"path/to/file.glsl\"\n```\nThis allows you to use functions and such from other GLSL files so it becomes\npossible to create libraries. There is no namespacing or generation of forward\nfunction declarations, it just takes a source file and dumps it in the place of\nthis directive much like C does. However, it does prevent including the same\nfile more than once in recursive inclusion.\n\nFile paths are resolved relative to the source file that declared the include\ndirective.\n\n### Mappings\nIt is possible use resources like images, videos and audio from shaders in\nthis environment by using the `iChannelX` samplers. On the website, one can\nselect this resource input mapping using dialogs. This implementation requires\nthese mappings to be specified in the shader source. The respective uniform is\ndeclared automatically.\n\nMappings can refer to other files such as images, videos and audio. Relative\npaths are resolved relative to the GLSL file that declared them.\n\nMappings are declared in a special directive that is parsed by shady. These are\ntypically inserted at the top of the file. Its format is:\n```glsl\n#pragma map \u003cuniform name\u003e=\u003cloader\u003e:\u003cvalue\u003e\n```\n\nMappings can also be set on the command line when invoking shady by using the\n`-map` flag. The format is the same as described earlier. Mappings set on the\ncommand line take precedence over mappings declared in source files. There are\nno hard requirements for the `namespace` being the same as in the shader, so it\nis possible to e.g. override an image with a video. Example:\n```\nshady -i thing.glsl -ofmt x11 -g 1366x768 -f 60 -map myTexture=video:myVideo.mkv\n```\n\n`uniform name` is the name of the sampler uniform that is inserted into the\nsource of the fragment shader. Unlike shadertoy.com, which names all samples as\n`iChannelX`, the name can be of any value as long as it is a valid GLSL\nvariable name.\n`loader` specifies how `value` should be interpreted.\nThere are a couple of loaders that you can choose from:\n\n#### The \"builtin\" loader\nThe `builtin` loader gives access to some of the presets that can be found on\nShadertoy. Accepted values for `builtin` are:\n* `Back Buffer`: creates a `sampler2D` containing the previously rendered\n  image.\n* `RGBA Noise Small`: creates a `sampler2D` texture with pseudo-random noise.\n  The randomness is deterministic.\n* `RGBA Noise Medium`: the same as above, but bigger.\n\nExample: Enable the sampler named `iChannel0` as a noise texture:\n```glsl\n#pragma map iChannel0=builtin:RGBA Noise Medium\n```\n\n#### The \"image\" loader\nSetting the loader to `image` interprets the value as a path to an image file\nand creates a `sampler2D` containing a static texture containing the RGBA data\nof the image file.\nSupported formats are JPEG, PNG and GIF, the latter using the first frame of\nthe animation for the texture.\n\nFor each mapped image, an additional `vec3` uniform is created with the\noriginal size of the image named `${uniform name}Size`. The Z component of this\nvector is reserved.\n\nExample:\n```glsl\n#pragma map myTexture=image:yoloswag.png\n```\n\n#### The \"audio\" loader\nAudio files can be loaded as a texture with a size of 512x2. Row 0 contains the\nFFT of the current window and row 1 contains the actual sound wave. For regular\naudio files, The playback rate is determined by the duration and framerate\nflags. For realtime audio, the window is the most recently produced audio,\nskipping information if rendering can not keep up.\n\nIf the value is just a file, this file is used as audio. FFmpeg is invoked to\ndecode the file, so any format supported by FFmpeg can be played.\n\nFor realtime audio, only raw PCM pipes are supported. The filename must be\nfollowed by the PCM format settings as `;\u003crate\u003e:\u003cchannels\u003e:\u003cencoding\u003e`.\n`encoding` is the sign as `s` or `u` followed by the number of bits per sample\nand then the endianness as `le` or `be`, e.g. `s16le`.\n\nExample: Map `audio` to the audio of an MP3 file:\n```glsl\n#pragma map music=audio:whatever.mp3\n```\n\n#### The \"video\" loader\nUsing videos as textures is very similar to images, there is a `sampler2D`\nuniform containing the current video frame and a `${uniform name}Size` vector\nfor the resolution. There is an additional `{uniform name}CurTime` float which\nis the current time in seconds in the video. This value is the same as `iTime`,\nbut wraps when the video is restarted from the beginning.\n\nThe sound of the video is not available, although this may be implemented in\nthe future.\n\nExample:\n```glsl\n#pragma map video=video:party.mkv\n```\n\n#### The \"buffer\" loader\nIt is possible to map another shader as a texture by using the `buffer` loader.\nThis is equivalent of just calling the `mainImage` function of this other\nshader and using the calculated color as texel. However, buffers have a\nseparate resolution and `Back Buffer`. Because the render output of a buffer in\nraster format, the size of the texture should be specified in the mapping by\nappending `;WxH` to the shader filename.\n\nLike videos, the buffer is declared as a `sampler2D` along with a\n`${uniform name}Size` vector.\n\nExample:\n```glsl\n#pragma map thing=buffer:other-shader.glsl;512x512\n```\n\n**NOTE**: Buffer support is not very well tested, your mileage may vary.\n\n#### The \"kinect\" loader\nIf Shady was compiled using the `kinect` build tag, it is possible to use a\nKinect's RGB and depth image in shaders. Just pass `-tags kinect` to `go build`\nwhen building and use `#pragma map kinect=kinect:on` to create a `sampler2D` of\nthe Kinect's video stream. The alpha channel holds the depth image.\n\nInternally, libfreenect is used which only supports the earlier Kinect versions\nfor the XBox 360.\n\n\n## Combining with other tools\n### Ledcat\n[Ledcat](https://github.com/polyfloyd/ledcat) is a program that can be used to\ncontrol lots of LEDs over lots of protocols. Shady can be combined with Ledcat\nto bring the fireworks to your LED-displays!\n\nIt can be installed like this when you have the [Rust\nLanguage](https://www.rust-lang.org/):\n```sh\ncargo install ledcat\n```\n\nTo aid development, Ledcat can be used to simulate a display in a terminal like\nthis:\n```sh\n# LEDCAT_GEOMETRY is a special env var that Ledcat and Shady use to set the\n# display size. It is also possible to use the -g flag on both programs.\nexport LEDCAT_GEOMETRY=128x128\n\nshady -i example.glsl -ofmt rgb24 -f 20 | ledcat -f 20 show\n```\n\n### FFmpeg\nFFmpeg may be used to render to video files:\n```\n# Render at 1024x768 at 20 fps and show it, the same as using `-ofmt x11`:\nshady -i example.glsl -ofmt rgb24 -g 1024x768 -f 20 \\\n  | ffplay -f rawvideo -pixel_format rgb24 -video_size 1024x768 -f 20 -\n\n# The same, but render 12 seconds to an MP4 file\nshady -i example.glsl -ofmt rgb24 -g 1024x768 -f 10 \\\n  | ffmpeg -f rawvideo -pixel_format rgb24 -video_size 1024x768 \\\n    -framerate 10 -t 12 -i - example.mp4\n```\n\n### MPD\nVisualising the output of MPD is possible by adding the following to your MPD\nconfig:\n```\naudio_output {\n  type   \"fifo\"\n  name   \"FIFO\"\n  path   \"~/.mpd/mpd.fifo\"\n  format \"22000:16:1\"\n}\n```\nAnd then creating a PCM audio mapping like this:\n```glsl\n#pragma map music=audio:~/.mpd/mpd.fifo;22000:1:s16le\n```\n\n## Troubleshooting\n### My performance is really bad\nSome shaders can really ask a lot from a system, in these cases it may not be\npossible to animate real time. If it is acceptable to have the animation be of\nfinite length and restart after a while, write a series of frame to a file, and\nload them in a loop.\n\n```sh\n# Render a 20 second loop to a file:\nshady -i example.glsl -g 64x64 -f 60 -n $((20*60)) -ofmt rgb24 -o ./my-animation.bin\n\n# Play the animation repeatedly:\nwhile true; do\n    cat ./my-animation.bin | ledcat -g 64x64 -f 60 show\ndone\n```\nOptionally, you could use something like gzip to reduce the file size.\n\n### EGL is not initialized, or could not be initialized\nHeadless rendering is possible. If `$DISPLAY` is unset because X11 is not\nrunning, try running shady with the `EGL_PLATFORM` env var set to `surfaceless`\nor `drm`.\n\nIf you still are not able to get shady to run headless, animate to a file and\nplay from that file in real time. [See\nabove](#user-content-my-performance-is-really-bad).\n\n### unexpected NEW_IDENTIFIER\n```\nError compiling fragment shader:\n0:2(1): error: syntax error, unexpected NEW_IDENTIFIER\n```\nThe above error could be caused by a `precision mediump float;` being present.\nBecause this is an OpenGL ES directive, it is not supported. Try removing it or\nwrapping with a preprocessor macro:\n```glsl\n#ifdef GL_ES\nprecision mediump float;\n#endif\n```\n\n\n## Media\n![Galaxy](media/galaxy.gif)\n![Space](media/space.gif)\n![Thingy](media/thingy.gif)\n![Tunnel](media/tunnel.gif)\n![Wolfenstein](media/wolfenstein.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolyfloyd%2Fshady","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpolyfloyd%2Fshady","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpolyfloyd%2Fshady/lists"}