{"id":13682001,"url":"https://github.com/gfxfundamentals/webgl-fundamentals","last_synced_at":"2026-01-27T03:36:31.892Z","repository":{"id":2295558,"uuid":"3253898","full_name":"gfxfundamentals/webgl-fundamentals","owner":"gfxfundamentals","description":"WebGL lessons that start with the basics","archived":false,"fork":false,"pushed_at":"2025-02-26T01:28:29.000Z","size":281921,"stargazers_count":4960,"open_issues_count":48,"forks_count":689,"subscribers_count":101,"default_branch":"master","last_synced_at":"2026-01-13T18:35:04.936Z","etag":null,"topics":["3d","3d-math","glsl","glsl-shaders","math","shaders","webgl"],"latest_commit_sha":null,"homepage":"http://webglfundamentals.org","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gfxfundamentals.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":"2012-01-24T07:11:20.000Z","updated_at":"2026-01-13T09:39:57.000Z","dependencies_parsed_at":"2024-09-25T00:22:00.013Z","dependency_job_id":"bef852c0-82fd-4d84-86a3-50e2f2ae8102","html_url":"https://github.com/gfxfundamentals/webgl-fundamentals","commit_stats":{"total_commits":1677,"total_committers":93,"mean_commits":"18.032258064516128","dds":0.3303518187239117,"last_synced_commit":"c3a8e1ab7982e8cde80ca256736f7ea7e7abb608"},"previous_names":["greggman/webgl-fundamentals"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gfxfundamentals/webgl-fundamentals","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gfxfundamentals%2Fwebgl-fundamentals","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gfxfundamentals%2Fwebgl-fundamentals/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gfxfundamentals%2Fwebgl-fundamentals/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gfxfundamentals%2Fwebgl-fundamentals/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gfxfundamentals","download_url":"https://codeload.github.com/gfxfundamentals/webgl-fundamentals/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gfxfundamentals%2Fwebgl-fundamentals/sbom","scorecard":{"id":425109,"data":{"date":"2025-08-11","repo":{"name":"github.com/gfxfundamentals/webgl-fundamentals","commit":"fd4401e2741a68ebb7c3beb33ed064a5859d22d7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":6,"reason":"Found 19/28 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/deploy-to-gh-pages.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/deploy-to-gh-pages.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/gfxfundamentals/webgl-fundamentals/deploy-to-gh-pages.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/deploy-to-gh-pages.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/gfxfundamentals/webgl-fundamentals/deploy-to-gh-pages.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/deploy-to-gh-pages.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/gfxfundamentals/webgl-fundamentals/deploy-to-gh-pages.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/deploy-to-gh-pages.yml:23","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T02:04:30.955Z","repository_id":2295558,"created_at":"2025-08-19T02:04:30.956Z","updated_at":"2025-08-19T02:04:30.956Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28799828,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"online","status_checked_at":"2026-01-27T02:00:07.755Z","response_time":168,"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":["3d","3d-math","glsl","glsl-shaders","math","shaders","webgl"],"created_at":"2024-08-02T13:01:39.004Z","updated_at":"2026-01-27T03:36:31.870Z","avatar_url":"https://github.com/gfxfundamentals.png","language":"HTML","funding_links":[],"categories":["HTML"],"sub_categories":[],"readme":"WebGL Fundamentals\n===================\n\nThis is [a series of lessons or tutorials about WebGL](https://webglfundamentals.org/).\n\nUnlike most WebGL lessons these are not based off of OpenGL.\nOpenGL is 20 years old. The lessons of OpenGL don't match well with WebGL.\nThe APIs have changed too much. The ideas of OpenGL and OpenGL tutorials\nare out of date with WebGL, OpenGL ES 2.0 and the land of shaders.\n\nI would argue that WebGL is actually a very simple API. What makes it\nappear complicated is the way in which it's used. The complications\nare added by the programmer. WebGL itself is simple.\n\nThese lessons try to show that simplicity as well as teach the\nfundamentals of 2D math and 3D math so readers can hopefully\nhave an easier time writing their own WebGL programs and\nunderstanding the complexity that other programmers pile on\ntop of simple WebGL.\n\nThis is work in progress. Feel free to contribute.\n\n## Contributing\n\nOf course bug fixes are always welcome.\n\nIf you'd like to write a new article please try to always take\none step at a time. Don't do 2 or more things in a single step.\nExplain any new math in the simplest terms possible. Ideally\nwith diagrams where possible.\n\n### Translating\n\nEach translation goes in a folder under `webgl/lessons/\u003ccountry-code\u003e`.\n\nRequired files are\n\n    langinfo.hanson\n    index.md\n    toc.html\n\n#### `langinfo.hanson`\n\nDefines various language specific options.\n[Hanson](https://github.com/timjansen/hanson) is a JSON like format but allows comments.\n\nCurrent fields are\n\n    {\n      // The language (will show up in the language selection menu)\n      language: 'English',\n\n      // Phrase that appears under examples\n      defaultExampleCaption: \"click here to open in a separate window\",\n\n      // Title that appears on each page\n      title: 'WebGL Fundamentals',\n\n      // Basic description that appears on each page\n      description: 'Learn WebGL from the ground up. No magic',\n\n      // Link to the language root.\n      link: 'https://webglfundamentals.org/webgl/lessons/ja',  // replace `ja` with country code\n\n      // html that appears after the article and before the comments\n      commentSectionHeader: '\u003cdiv\u003eIssue/Bug? \u003ca href=\"https://github.com/gfxfundamentals/webgl-fundamentals/issues\"\u003eCreate an issue on github\u003c/a\u003e.\u003c/div\u003e',\n\n      // markdown that appears for untranslated articles\n      missing: \"Sorry this article has not been translated yet. [Translations Welcome](https://github.com/gfxfundamentals/webgl-fundamentals)! 😄\\n\\n[Here's the original English article for now]({{{origLink}}}).\",\n\n      // the phrase \"Table of Contents\"\n      toc: \"Table of Contents\",\n\n      // translation of categories for table of contents\n      categoryMapping: {\n        'fundamentals': \"Fundamentals\",\n        'image-processing': \"Image Processing\",\n        'matrices': \"2D translation, rotation, scale, matrix math\",\n        '3d': \"3D\",\n        'lighting': \"Lighting\",\n        'organization': \"Structure and Organization\",\n        'geometry': \"Geometry\",\n        'textures': \"Textures\",\n        'rendertargets': \"Rendering To A Texture\",\n        '2d': \"2D\",\n        'text': \"Text\",\n        'misc': \"Misc\",\n        'reference': \"Reference\",\n      },\n\n    }\n\n#### `index.md`\n\nThis is the template for the main page for each language\n\n#### `toc.html`\n\nThis is template for the table of contents for the language.\nIt is included on both the index and on each article. The only\nparts not auto-generated are the links ending links which\nyou can translate if you want to.\nThe build system will create a placeholder for every English article for which there is no corresponding article in that language. It will be filled with the `missing` message from above.\n\n#### `lang.css`\n\nThis is included if and only if it exists. I'd strongly prefer not to have to\nuse it. In particular I don't want people to get into arguments about fonts\nbut basically it's a way to choose the fonts per language. You should only set\nthe variables that are absolutely needed. Example\n\n```css\n/* lessons/ko/lang.css */\n\n/* Only comment in overrides as absolutely necessary! */\n:root {\n  --article-font-family: \"best font for korean article text\";\n  --headline-font-family: \"best font for korean headlines\";\n  /* a block of code */\n  /* --code-block-font-family: \"Lucida Console\", Monaco, monospace; */\n  /* a word in a sentence */\n  /* --code-font-family: monospace; */\n}\n```\n\nNotice 2 settings are not changed. It seems unlikely to me that code would\nneed a different font per language.\n\nPS: While we're here, I love code fonts with ligatures but they seem like a bad\nidea for a tutorial site because the ligatures hide the actual characters needed\nso please don't ask for or use a ligature code font here.\n\n#### Translation notes\n\nThe build process will make a placeholder html file for each article that has an English .md file in\n`webgl/lessons` but no corresponding .md file for the language. This is to make it easy to include\nlinks in an article that links to another article but that other article has not yet been translated.\nThis way you don't have to go back and fix already translated articles. Just translate one article\nat a time and leave the links as is. They'll link to placeholders until someone translates the missing\narticles.\n\nArticles have front matter at the top\n\n```\nTitle: Localized Title of article\nDescription: Localized description of article (used in RSS and social media tags)\nTOC: Localized text for Table of Contents\n```\n\n**DO NOT CHANGE LINKS** : For example a link to a local resources might look like\n\n    [text](link)\n\nor\n\n    \u003cimg src=\"somelink\"\u003e\n\nWhile you can add query parameters (see below) do not add \"../\" to try to make the link relative to the\n.md file. Links should stay as though the article exists at the same location as the original English.\n\n### UI localization\n\nSome of the diagrams allow passing translations for the UI and other text.\n\nFor example if there is a slider named \"rotation\"\nyou can add \"?ui-rotation=girar\" at the end of the URL for the diagram. For 2 or more translations\nseparate them with a `\u0026`. Certain characters are disallowed in URLs like `=`, `#`, `\u0026` etc. For those\nuse their uri encoding.\n\nFor diagram labels you'll have to look inside the code. For example for the\ndirectional lighting diagram near the start of the code it looks like this\n\n```\nconst lang = {\n  lightDir: opt.lightDir || \"light direction\",\n  dot: opt.dot || \"dot(reverseLightDirection,surfaceDirection) = \",\n  surface1: opt.surface1 || \"surface\",\n  surface2: opt.surface2 || \"direction\",\n};\n```\n\nWhich means you can localize the labels like this\n\n```\n{{{diagram url=\"resources/directional-lighting.html?lightDir=光線方向\u0026surface1=オブジェクト\u0026surface2=表面方向\u0026dot=dot(光線反対方向,表面方向)%20%3D%20\u0026ui-rotation=角度\" caption=\"方向を回転してみて\" width=\"500\" height=\"400\"}}}\n```\n\nFor testing, reference the sample directly in your browser. For example\n\n[`http://localhost:8080/webgl/lessons/resources/directional-lighting.html?lightDir=光線方向\u0026surface1=オブジェクト\u0026surface2=表面方向\u0026dot=dot(光線反対方向,表面方向)%20%3D%20\u0026ui-rotation=角度`](https://webglfundamentals.org/webgl/lessons/resources/directional-lighting.html?lightDir=光線方向\u0026surface1=オブジェクト\u0026surface2=表面方向\u0026dot=dot(光線反対方向,表面方向)%20%3D%20\u0026ui-rotation=角度)\n\n### To build\n\nThe site is built into the `out` folder\n\nSteps\n\n    git clone https://github.com/gfxfundamentals/webgl-fundamentals.git\n    cd webgl-fundamentals\n    npm install\n    npm run build\n    npm start\n\nnow open your browser to `http://localhost:8080`\n\n### Continuous build\n\nYou can run `npm run watch` after you've built to get continuous building.\nOnly the article .md files and files that are normally copied are watched.\nThe index files (the top page with the table of contents) is not regenerated\nnor does changing a template rebuild all the articles.\n\n#### Build options\n\nThis is mostly for debugging `build.js`. Since it takes a while to process all the files\nyou can set `ARTICLE_FILTER` to a substring of the filenames to process. For example\n\n    ARTICLE_FILTER=rotation npm run build\n\nWill build the site as though only articles with `rotation` in their filename exist.\n\n## TO DO\n\n### A list of articles I'd like to write or see written\n\n*   lighting\n    *   normal maps\n*   geometry\n    *   plane, cube, sphere, cone, disc, torus\n        *   lines vs triangles\n        *   vertex colors\n    *   other\n    *   pre-process (don't load .obj, .dae, .fbx etc at runtime)\n    *   pre-optimize (texture atlas, sizes, combine meshes, etc...)\n*   animation\n    *   blendshapes\n    *   hierarchical animation\n*   debugging\n    *   debugging JS WebGL\n        *   example (https://goo.gl/8U5whT)\n        *   CHECK THE GAWD DAMN CONSOLE!\n            *   actually read the error message\n            *   understand it.\n                *   INVALID_ENUM means one of your gl.XXX values is not valid period\n                *   INVALID_VALUE means one of the int or float values is probably off\n                *   INVALID_OPERATION means something you tried to do won't work for the given state\n                *   texture not renderable\n                *   attribute out of range\n                *   check your framebuffers\n                *   check your extensions\n        *   make shorter samples (MCVE)\n            *   remove any code you don't need\n            *   get rid of CSS\n            *   get rid of HTML\n            *   consider using a POINT (no attributes needed)\n            *   don't use images if they are not relevant. Use a canvas or a single and double pixel texture\n            *   While creating this MCVE you'll often find the bug\n    *   debugging a shader\n        *   set fragment shader to solid color.\n        *   render normals\n        *   render texcoords\n        *   render cube/sphere/plane\n*   text\n    *   glyph cache\n*   post processing\n    *   DOF\n    *   glow\n    *   light rays\n    *   RGB glitch, CRT distortion, scanlines\n    *   color mapping/tone mapping\n*   Creative coding\n    *   color palettes\n    *   tilemaps\n    *   generated geometry\n    *   histogram\n    *   particles\n    *   toon/ramp shading\n    *   procedural textures\n*   code organization\n    *   scene graph\n        *   putting lights and camera in scene graph\n*   Engine Creation\n    *   culling\n        *   frustum culling\n        *   grid culling\n        *   quad tree / oct tree\n        *   portals (is this still a thing?)\n        *   PVS\n    *   materials\n    *   lighting DB\n*   Physically based rendering\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgfxfundamentals%2Fwebgl-fundamentals","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgfxfundamentals%2Fwebgl-fundamentals","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgfxfundamentals%2Fwebgl-fundamentals/lists"}