{"id":17125403,"url":"https://github.com/ruby0x1/hxsw","last_synced_at":"2026-01-06T04:05:43.561Z","repository":{"id":23387380,"uuid":"26749057","full_name":"ruby0x1/hxsw","owner":"ruby0x1","description":"Haxe Shader Wrangler (hxsw) - a port of glsw","archived":false,"fork":false,"pushed_at":"2020-06-12T16:48:36.000Z","size":45,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-01T22:42:27.055Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Haxe","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruby0x1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-17T09:13:22.000Z","updated_at":"2023-07-25T13:53:54.000Z","dependencies_parsed_at":"2022-08-22T00:10:28.899Z","dependency_job_id":null,"html_url":"https://github.com/ruby0x1/hxsw","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ruby0x1/hxsw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0x1%2Fhxsw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0x1%2Fhxsw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0x1%2Fhxsw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0x1%2Fhxsw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruby0x1","download_url":"https://codeload.github.com/ruby0x1/hxsw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruby0x1%2Fhxsw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28221548,"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":"2026-01-06T02:00:07.049Z","response_time":56,"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":[],"created_at":"2024-10-14T18:44:50.537Z","updated_at":"2026-01-06T04:05:43.530Z","avatar_url":"https://github.com/ruby0x1.png","language":"Haxe","funding_links":[],"categories":[],"sub_categories":[],"readme":"Haxe Shader Wrangler\n====\n\nThis is a haxe port of \"[OpenGL Shader Wrangler](http://prideout.net/blog/?p=11)\" by Philip Rideout. \nThis library is part of the [snõwkit](http://snowkit.org) collective.\n\n![hxsw](hxsw.png)\n\n## Facts\n\n- This is a string manipulator\n- No dependency on OpenGL\n- Not even dependent on use for Shaders\n- Easy to implement, with load callback\n- Very simple api (2 feature functions)\n- Detailed logging (see below)\n- Cross target/platform code\n- The code is well documented\n- Test code includes example usage in full\n\n\n## To run the test\n\n- Install [Haxe](http://haxe.org)\n- `cd tests/`\n- `haxe build.hxml`\n\nThis will generate a `run.n` file, and run `neko run.n` which will run the binary. There is a prebuilt version included. \n\n## To use the code\n\n- copy `hxsw/` to your project\n\nOR\n\n- or use `haxelib install hxsw`\n- use `haxelib git hxsw https://github.com/underscorediscovery/hxsw.git`\n- then add -lib to your hxml, or as a dependency in your IDE/project\n\n## License\n\nMIT (see LICENSE.md)    \nIt's preferable the HXSW.hx file maintains it's licensing info at the top as well.\n\n## Versions\n\n- 1.0.0 - Initial implementation\n\n## About\n\n#### The following below is taken from the original [blog post](http://prideout.net/blog/?p=11):\n\nTo recap, you’d like to avoid creating a separate file for every friggin’ shader in your OpenGL program, especially with the advent of purely shader-based OpenGL and the new programmable stages in OpenGL 4.0. You’d also like to avoid big frameworks that attempt to accommodate other API’s like DirectX.\n\nSo, you need a lightweight solution that can organize your shader strings, load them up in a convenient manner, and automatically prepend #line directives. ... To that end, I wrote an “OpenGL Shader Wrangler” (GLSW), a tiny library that does the following:\n\n- Chops up simple “effect” files into lists of strings\n- Automatically prepends shaders with #line to enable proper error reporting\n- Optionally prepends shader directives like #version and #extension\n- Associates each shader with a quasi-hierarchical path called a shader key\n\n##### Vocabulary \n\nHere’s an example effect key with four tokens:\n\n![effectKey](tests/EffectKey.png)\n\n**effect**   \nSimple text file that contains a bundle of shaders in any combination. For example, an effect might have 3 vertex shaders and 1 fragment shader. It might have 0 vertex shaders, or it might contain only tessellation shaders. Effects should not be confused with OpenGL program objects. A program object is a set of shaders that are linked together; an effect is just a grouping of various shader strings.\n\n**shader key**   \nIdentifier for a shader consisting of alphanumeric characters and periods. In a way, the periods serve as path separators, and the shader key is a path into a simple hierarchy of your own design. However, HXSW does not maintain a hierarchy; it stores shaders in a flat list.\n\n**effect key**   \nSame as a shader key, but prefaced with a token for the effect. Your C/C++ code uses an effect key when requesting a certain shader string.\n\n**token**   \nContiguous sequence of alphanumeric characters in a shader key (or effect key) delimited by periods.\n\n**section divider**   \nAny line in an effect file that starts with two dash characters (--). If the dashes are followed by a shader key, then all the text until the next section divider officially belongs to the corresponding shader.\n\n**directive**   \nAny line of GLSL code that starts with a pound (#) symbol.\n\n\n--\n\nIn the above example, I placed the shader stage in the second token and the API version in the third token. You aren’t required to arrange your shader keys in this way. The only requirement is that the first token corresponds to the effect file. You don’t need to use the GL3 notation for your version tokens either; in fact, you don’t have to include a version token at all. The onus is on you to create a consistent hierarchy and naming convention.\n\n## Simple example\n\n```glsl\n\n-- Vertex\n\nin vec4 Position;\nvoid main() {\n    gl_Position = Position;\n}\n\n-- Fragment\n\nuniform sampler2D Sampler;\nout vec4 FragColor;\nvoid main() {\n    ivec2 coord = ivec2(gl_FragCoord.xy);\n    FragColor = texelFetch(Sampler, coord, 0);\n}\n\n```\n\nHere’s how you’d use HXSW to pluck out strings from the preceding file and automatically prepend them with #line:\n\n```\nvar sw = new HXSW({ load_effect: load_file_handler });\n\nvar vs = sw.get('Blit.Vertex');\nvar fs = sw.get('Blit.Fragment');\n```\n\nHXSW handles everything except file reading; you do that with load_effect. HXSW then takes the first token from the effect key that you pass to `get`, then checks if it has the effect cached; if not, it finds a file by decorating the effect name with a path prefix (in this case, the default, `./`) and a path suffix (in this case, the default, `.glsl`).\n\n## Ignored Text\n\nIf a section divider in your effect file does not contain any alphanumeric characters, then all text is ignored until the next section divider (or the end of the file). Also, any text that precedes the first section divider is ignored (this could be useful for a copyright notice).\n\nIf a section divider does declare a legal shader key (i.e., the first contiguous sequence of alphanumeric characters and periods), then any characters appearing before and after the shader key are ignored.\n\nFor example, the following is a silly but valid effect file:\n\n```\n______  _  _  _   \n| ___ \\| |(_)| |  \n| |_/ /| | _ | |_ \n| ___ \\| || || __|\n| |_/ /| || || |_ \n\\____/ |_||_| \\__|\n                  \n-------- Vertex --------\n\nin vec4 Position;\nvoid main() {\n    gl_Position = Position;\n}\n\n--- /\\/\\/\\/\\/\\/\\/\\/\\ ---\n\nContrariwise, if it was so, it might be; and if it were so,\nit would be; but as it isn't, it ain't. That's logic. \n\n--[[[[[ Fragment \u003c== Brigadier Lethbridge-Stewart\n\nuniform sampler2D Sampler;\nout vec4 FragColor;\nvoid main() {\n    ivec2 coord = ivec2(gl_FragCoord.xy);\n    FragColor = texelFetch(Sampler, coord, 0);\n}\n\n```\n\n## Error Handling and Shader Key Matching\nHXSW never aborts or throws exceptions. It returns 0 on failure and lets you fetch the most recent error string using `sw.error`, where sw is an instance. This can happen if it can’t find the file for your specified effect key, etc. The following are error states:\n\nErrors are encountered under the following conditions, each will also give additional information where possible:\n\n- Malformed effect key\n    - set when the effect key given to `get` is invalid.\n    - a valid effectkey has Effect.Shader, requiring a . delimeter\n- Unable to open effect file\n    - set when the file load function returns a blank string\n    - implementation details of the reasons are outside of this code\n- Could not find shader with key\n    - `get` requested a shader that was not found in the effect/s\n- Cannot add blank directive, only blank tokens.\n    - storing a blank directive makes no sense, only a blank token is valid\n\nWhen HXSW tries to find a shader key that matches with the effect key requested from your user code, it doesn’t necessarily need to find an exact match. Instead, it finds the longest shader key that matches with the beginning of your requested effect key. For example, consider an effect file called TimeMachine.glsl that looks like this:\n\n```\n-- Vertex\nFOO\n-- Geometry\nBAR\n-- Fragment.Erosion\nBAZ\n-- Fragment.Grassfire\nQUX\n-- TessControl\nQUUX\n-- TessEvaluation\nQUUUX\n```\n\nIf your user code does this:\n\n```haxe\n\nvar sw : HXSW;\n\nfunction load() {\n\n\tsw = new HXSW({...});\n\n\ttest(\"TimeMachine.Vertex.Grassfire\");\n\ttest(\"TimeMachine.Fragment.Grassfire\");\n\ttest(\"TimeMachine.Fragment.Cilantro\");\n\ttest(\"Madrid\");\n\t\n}\n\nfunction test(key:String) {\n\n    var shader = sw.get(key);\n    if(shader == '') {\n        trace(sw.error);\n    } else {\n        trace(shader);\n    }\n\n} //test\n```\n\nThen your output would be this:\n\n```\nFOO\nQUX\nCould not find shader with key 'TimeMachine.Fragment.Cilantro'.\nUnable to open effect file 'Madrid.glsl'.\n```\n\nNote that the first requested effect key did not report an error even though that exact shader key does not exist in the effect file. Here’s an example where this is useful: you’d like to use the same vertex shader with two different fragment shaders, but your rendering engine forms the string for effect keys in a generic way. \n\nHXSW will simply return the longest key that matches with the beginning of the requestion key. This avoids complicating the file format with support for cross-referencing.\n\n## Directive Mapping\nThis is the only function we haven’t explained yet:\n\n`add_directive(token:String, directive:String);`  \nThis tells HXSW to add a token-to-directive mapping. Whenever it sees a shader key that contains the specified token, it prepends the specified directive to the top of the shader. If the specified token is an empty string, then the specified directive is prepended to all shaders. For example, given this user code:\n\n```haxe\n\nsw.add_directive(\"\", \"#define FOO 1\");\nsw.add_directive(\"GL32\", \"#version 140\");\nsw.add_directive(\"iOS\", \"#extension GL_OES_standard_derivatives : enable\");\n\nvar effectKey = '';\n\neffectKey = \"Blit.ES2.iPhone.Fragment\";\ntrace(sw.get(effectKey) + '\\n');\n\neffectKey = \"Blit.GL32.Fragment\";\ntrace(sw.get(effectKey) + '\\n');\n\n```\n\nYou’d get output like this:\n\n\n```glsl\n\tBlit.ES2.iPhone.Fragment:\n\t#define FOO 1\n\t#extension GL_OES_standard_derivatives : enable\n\t#line 7\n\tvoid main() {}\n\t\n\tBlit.GL32.Fragment:\n\t#define FOO 1\n\t#version 140\n\t#line 51\n\tvoid main() {}\n\n```\n\nYou can also use an effect name for the token parameter in `add_directive`, which tells HXSW to prepend the specified directive to all shaders in that effect.\n\n\n## Example output\n\nThis only makes sense if you have [seen the code](tests/Main.hx)   \n\n#### [With Logging](tests/output_with_logging.txt)\n#### [Without Logging](tests/output_without_logging.txt)\n\n\u0026nbsp;\n\n---\n\n[Feedback? Bugs? Issues? Chat?](https://github.com/underscorediscovery/hxsw/issues)\n\n--\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby0x1%2Fhxsw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruby0x1%2Fhxsw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruby0x1%2Fhxsw/lists"}