{"id":15032785,"url":"https://github.com/rswinkle/portablegl","last_synced_at":"2026-03-05T09:10:01.158Z","repository":{"id":45142362,"uuid":"294358513","full_name":"rswinkle/PortableGL","owner":"rswinkle","description":"An implementation of OpenGL 3.x-ish in clean C","archived":false,"fork":false,"pushed_at":"2025-03-21T07:34:55.000Z","size":29125,"stargazers_count":1100,"open_issues_count":2,"forks_count":52,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-05-14T19:07:43.357Z","etag":null,"topics":["3d","3d-graphics","computer-graphics","graphics","opengl","rasterization","rasterizer","renderer","rendering","rendering-pipeline","shader","shaders","single-header-library","software-renderer","software-rendering","tutorial"],"latest_commit_sha":null,"homepage":"","language":"C","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/rswinkle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"rswinkle","liberapay":"rswinkle","custom":"http://www.robertwinkler.com/donations.html"}},"created_at":"2020-09-10T09:04:34.000Z","updated_at":"2025-05-07T13:59:47.000Z","dependencies_parsed_at":"2023-09-24T02:04:18.434Z","dependency_job_id":"8fbafd48-d6a9-486f-be3e-3fd590de3afe","html_url":"https://github.com/rswinkle/PortableGL","commit_stats":{"total_commits":286,"total_committers":2,"mean_commits":143.0,"dds":"0.0034965034965035446","last_synced_commit":"7c678e6ccff573cccb8d9c337e64d006a2b562f4"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2FPortableGL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2FPortableGL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2FPortableGL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2FPortableGL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rswinkle","download_url":"https://codeload.github.com/rswinkle/PortableGL/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"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":["3d","3d-graphics","computer-graphics","graphics","opengl","rasterization","rasterizer","renderer","rendering","rendering-pipeline","shader","shaders","single-header-library","software-renderer","software-rendering","tutorial"],"created_at":"2024-09-24T20:19:27.182Z","updated_at":"2026-03-05T09:10:01.114Z","avatar_url":"https://github.com/rswinkle.png","language":"C","readme":"PortableGL\n==========\n\nCrowdfunding Announcement\n=========================\n![PGL Shadertoy](media/screenshots/pgl_shadertoy_deform_tunnel.png)\n\nI'm launching a crowdfunding campaign for a PortableGL-based shadertoy application.\nIf you'd like to support PortableGL development or are interested in shader art\n(or ideally both) check it out\n[here](https://www.indiegogo.com/en/projects/robertwinkler/portablegl-shadertoy).\n\n---\n\n***\"Because of the nature of Moore's law, anything that an extremely clever graphics programmer can do at one point can be replicated by a merely competent programmer some number of years later.\"*** -John Carmack\n\n\nIn a nutshell, PortableGL is an implementation of OpenGL 3.x core (mostly; see [GL Version](#gl-version))\nin clean C99 as a single header library (in the style of the [stb libraries](https://github.com/nothings/stb)).  This means it compiles cleanly as C++\nand can be easily added to almost any codebase.\n\nIt can theoretically be used with anything that takes a 32 or 16 bit framebuffer/texture as input in any format.\n(including just writing images to disk manually or using something like stb_image_write). That should mean it supports almost everything, barring\nperformance issues.\n\nAlmost all the demos use SDL2 except the programs in the `backends` directory which show how to use it with other backends.\n\nIt supports arbitrary 32- and 16-bit color buffer formats (selected at compile time) with several common ones ready to use out the box.\nSee the [documentation](src/header_docs.txt#L57) for more details.\n\nIts goals are, roughly in order of priority,\n\n1. Portability\n2. Matching the API within reason, at the least matching features/abilities\n3. Ease of Use\n4. Straightforward code\n5. Speed\n\nObviously there are trade-offs between several of those.  An example where 4 trumps 2 (and arguably 3) is with shaders.  Rather than\nwrite or include a GLSL parser and have a built in compiler or interpreter, shaders are special C/C++ functions that match a specific prototype.\nUniforms are another example where 3 and 4 beat 2 because it made no sense to match the API because we can do things so much simpler by\npassing a pointer to a user defined struct (see the examples).\n\nDownload\n========\nGet the source from [Github](https://github.com/rswinkle/PortableGL).\n\nYou can also install it via [Homebrew](https://formulae.brew.sh/formula/portablegl).\n\nGallery\n=======\n![gears](examples/classic/gears.png)\n![sphereworld](media/screenshots/sphereworld.png)\n[![backpack](media/screenshots/backpack_model.png)](https://github.com/rswinkle/LearnPortableGL/blob/main/src/3.model_loading/model_loading.cpp)\n![craft](media/screenshots/craft.png)\n\nThe last is a [PortableGL port](https://github.com/rswinkle/Craft/tree/portablegl) of Michael Fogleman's [Craft](https://www.michaelfogleman.com/projects/craft/).\n\nDirectory Structure\n===================\n- `demos`: Unpolished open ended programs demonstrating a wide variety of features\n- `examples`: More polished examples in C and C++, some graduating from demos\n    - `original`: Original custom examples, C++ programs use rsw_math rather than glm\n    - `classic`: Ports of classic OpenGL programs/demos, currently just gears\n    - `webgl_lessons`: Ports of lessons from learningwebgl.com based off my ports to OpenGL 3.3 [here](https://github.com/rswinkle/opengl_reference)\n- `backends`: \"hello triangle\" using backends other than SDL2 (win32 and xlib currently)\n- `glcommon`: Collection of helper libraries I use for graphics programming\n- `media`: Parent directory for external resources\n    - `models`: Models in my own simplified text format (created with `demos/assimp_convert`)\n    - `screenshots`: screenshots of demos and external programs\n    - `textures`: All textures used in any program in the repo\n- `src`: Contains the actual source files of `portablegl.h` which are amalgamated with `generate_gl_h.py`\n- `testing`: Contains a more formal regression and performance test suite\n    - `expected_output`: The expected output frames for the regression tests (`run_tests`)\n    - `test_output`: The output of the regression tests (see Building section)\n- `portablegl.h` : Current dev version of PortableGL\n\nWhile I try not to introduce bugs, they do occasionally slip in, as well as (rarely) breaking\nchanges.  At some point I'll move to more frequent point releases for fixes\nand non-breaking changes and be more consistent with semantic versioning.\n\nDocumentation\n=============\nThere is the documentation including a minimal program in the comments at the top of the\n[file](src/header_docs.txt)\nbut there is currently no formal documentation.\n\nThe best way to learn is to look at the [examples](https://github.com/rswinkle/PortableGL/tree/master/examples/README.md) (and [demos](https://github.com/rswinkle/PortableGL/tree/master/demos/README.md)) and comparing them to equivalent OpenGL 3.3+ programs.\n\nMy ports of the [learnopengl.com](https://learnopengl.com/) tutorial code [here](https://github.com/rswinkle/LearnPortableGL)\nare the best resource, combining his tutorials explaining the OpenGL aspects and my comments in the ported code\nexplaining PortableGL's differences and limitations (at least in the first time they appear).\n\nFor the original examples and demos you can compare with my equivalent programs in\n[opengl_reference](https://github.com/rswinkle/opengl_reference)).\n\nHonestly, the official OpenGL docs\nand [reference pages](https://www.khronos.org/registry/OpenGL-Refpages/gl4/) are good for 90-95% of it as far as basic usage:\n\n[4.6 Core reference](https://www.khronos.org/opengl/wiki/Category:Core_API_Reference)\n[4.5 comprehensive reference](https://www.khronos.org/registry/OpenGL-Refpages/gl4/)\n[tutorials and guides](https://www.khronos.org/opengl/wiki/Getting_Started#Tutorials_and_How_To_Guides)\n\nBuilding\n========\nThere are no dependencies for PortableGL itself, other than a compliant C99/C++ compiler.\n\nIf you just want to do a quick test that it compiles and runs:\n\n\tcd testing\n\tmake run_tests\n\t...\n\t./run_tests\n\t...\n\tAll tests passed\n\nSee the [testing README](https://github.com/rswinkle/PortableGL/blob/master/testing/README.md) for more on the formal testing.\n\nSee the [examples README](https://github.com/rswinkle/PortableGL/blob/master/examples/README.md) which describes how to get SDL2\nif you don't already have it and how to use make to build them.\n\nTo sum up, the only thing that is guaranteed to build and run anywhere out of the box with no extra effort on your part\nare the regression tests since they don't depend on anything except a compliant C++ compiler.\n\nModifying\n=========\n`portablegl.h` is generated in the src subdirectory with the python script\n`generate_gl_h.py`. You can see how it's put together and either modify the script to\nleave out or add files, or actually edit any of the code. Make sure if you add any actual\ngl functions that you add them to `gl_function_list.c` as it's used in the script for\noptionally wrapping all of them in a macro to allow user defined prefix/namespacing.\n\nAdditionally, there is a growing set of more formal tests in `testing`, one set of\nregression/feature tests, and one for performance. If you make any changes to core\nalgorithms or data structures, you should definitely run those and make\nsure nothing broke or got drastically slower.  The examples and demos can also function as\nperformance tests, so if one of those would be especially affected by a change, it\nmight be worth comparing its before/after performance too.\n\nOn the other hand, if you're adding a function or feature that doesn't really affect\nanything else, it might be worth adding your own test if applicable. You can see how\nthey work from looking at the code, but I'll add more details and documentation about\nthe testing system later when it's more mature.\n\nBindings/Ports\n==============\n\n[pgl](https://github.com/TotallyGamerJet/pgl) is a Go port using [CXGO](https://github.com/gotranspile/cxgo), and hand\ntranslating the individual examples/demos.\n\nSponsors\n========\nYou can help support PortableGL development by becoming a Github Sponsor or via one of the other methods shown/linked to\nin the Sponsor popup.\n\nPast\n[Aeronix](https://www.aeronix.com/) Sep-Oct 2023\n\nLICENSE\n=======\nPortableGL is licensed under the MIT License (MIT)\n\nThe code used for clipping is copyright (c) Fabrice Bellard from TinyGL also under\nthe MIT License, see LICENSE.\n\nHistory\n=======\nPortableGL started as a very simple wireframe software renderer based on a tutorial in summer 2011.  I kept playing with it, adding minor features\nover the next year, until in early 2013 I decided I should turn it into a software implementation of OpenGL.  This would save me a huge amount of time\nand energy on API design since I'd just be implementing an existing good API (though some disagree) and also make the project more useful both to me\nand potentially others.  Also, at the time Mesa3D was still years away from full 3.x support, not that I'm really competing, and the fact that there\nwas no finished implementation was a little motivating.  I made a lot of progress that year and had a few bursts here and there since, but once I got it\nmostly working, I was less motivated and when I did work on it I spent my time on creating new demos/examples and tweaking or fixing minor things.  I\ncould have released an MVP back in 2014 at the earliest but late 2016 would have been the best compromise.  Anyway, after several thousand\nhours spread out over more than 10 years, it is as you see it today. Software is never finished, and I'll be the first to admit PortableGL could use\nmore polish.\n\nWhy\n===\nAside from the fact that I just wrote it for fun and because I thought it was cool (maybe others will too), I can think of a few semi-practical purposes.\n\n### Educational\nI took a 400 level 3D Graphics course in college in fall 2010 months after OpenGL 3.3/4.0 was released.  It was taught based on the original\nRed Book using OpenGL 1.1.  Fortunately, the professor let me use OpenGL 3.3 as long as I met the assignment requirements.  Sadly, college graphics\nprofessors still teach 1.x and 2.x OpenGL today in 2022 more commonly than 3.x/4.x (or Vulkan).  A few are using WebGL 2.0 which I kind of\nconsider 1 step forward, 2 steps back.\n\nWhile Vulkan is the newest thing (already 5 years old time flies), it really is overkill for learning 3D graphics.  There is rarely anything that students\nmake in your standard intro to 3D graphics that remotely stresses the performance of any laptop built in the last decade plus.  Using modern OpenGL (ie 3.3+ core profile)\nto introduce all the standard concepts, vertices, triangles, textures, shaders, fragments/pixels, the transformation pipeline etc. first is much better\nthan trying to teach them Vulkan and graphics at the same time, and obviously better than teaching OpenGL API's that are decades old.\n\nPortableGL could be a very convenient base for such a class.  It's easy to walk through the code and see the pipeline and how all the steps flow together.\nFor more advanced classes or graduate students in a shared class, modifying PortableGL in some way would be a good project.  It could be some\noptimization or algorithm, maybe a new feature.  Theoretically it could be used as starter code for actual research into new graphics algorithms or techniques because it's such a convenient small foundation to change and share, vs trying to modify a project the size and complexity of Mesa3D or create a software\nrenderer from scratch.\n\n### Special Cases\nIt's hard to imagine any hardware today that has a CPU capable of running software rendered 3D graphics at any respectable speed (especially with full\nIEEE floating point) that doesn't *also* have some kind of dedicated GPU.  The GPU might only support OpenGL 2.0 give or take but for performance it'd\nbe better to stick to whatever the hardware supported than use PortableGL.  However, theoretically, there could be some platform somewhere where the CPU\nis relatively powerful that doesn't have a GPU.  Maybe some of the current and future RISC SoC's for example?  In such a case PortableGL might be a\nuseful alternative to Mesa3D or similar.\n\nAnother special case is hobby OS's.  The hardware they run on might have a GPU but it might be impossible or more trouble than it's worth to get Mesa3D\nto run on some systems.  If they have a C99 compliant compiler and standard library, they could use PortableGL to get at least some OpenGL-ish 3D support.\n\n### Why C\nI recently came across a comment regarding PortableGL that essentially asked, \"why implement a dead technology\nin a dying language?\"\n\nWhile I would argue that OpenGL is far from dead and C [isn't even close to dying](https://www.tiobe.com/tiobe-index/),\nthere are many good reasons to write a *library* in C.\n\nHere are a few libraries written in C, along with some links to their reasoning:\n\n* [SQLite](https://www.sqlite.org/whyc.html) The most [deployed database](https://www.sqlite.org/mostdeployed.html) in the world.\n* [raylib](https://www.raylib.com/) One of the most [starred](https://gitstar-ranking.com/raysan5/raylib) and active repos, and among the most popular [OSS game engines](https://ossinsight.io/collections/game-engine).\n* [Lua](https://www.lua.org/about.html) The very popular language used in tools like [premake](https://premake.github.io/), game engines like [Love](https://love2d.org/), and best selling games like [Balatro](https://www.playbalatro.com/).\n* [Chipmunk Physics](https://chipmunk-physics.net/release/ChipmunkLatest-Docs/#Intro-WhyC)\n* [SDL](https://libsdl.org/) The cross platform library used in 10000's of games and apps, including most of my own demos.\n* [GLFW](https://www.glfw.org/) A popular OpenGL/Vulkan specific cross-platform library.\n* [stb](https://github.com/nothings/stb/tree/master) The OG single header libraries like stb_image. His own answers to why [C](https://github.com/nothings/stb/blob/master/docs/stb_howto.txt#L73) and why [single-headers](https://github.com/nothings/stb/blob/master/README.md#why-single-file-headers)\n* [Sokol](https://github.com/floooh/sokol/blob/master/README.md#why-c). He [has a](https://floooh.github.io/2017/07/29/sokol-gfx-tour.html) [whole](https://floooh.github.io/2018/05/01/cpp-to-c-size-reduction.html) [series](https://floooh.github.io/2018/06/02/one-year-of-c.html)\n[of](https://floooh.github.io/2018/06/17/handles-vs-pointers.html) [blog](https://floooh.github.io/2019/09/27/modern-c-for-cpp-peeps.html) [posts](https://floooh.github.io/2020/08/23/sokol-bindgen.html)\n* [miniaudio](https://miniaud.io/)\n* many many more...\n\nIf you read through any of those you may have noticed a pattern.  Choosing to write a *library* in the C++-clean subset of C\ngives you automatic C/C++ support, the most portability across platforms, the easiest integration into other projects, and the easiest bindings\nto other languages. Keeping the library small with few or no dependencies only enhances all those benefits and makes it even easier to use.\n\nAll that said, if I were ever going to actually write a real/large 3D application or game I would probably use C++ for the benefits\nlike operator overloading, just like I do with the majority of the demos.  Choosing a language for a large user level application\nis an entirely different animal from choosing one for a library.  On the other hand, there are still reasons to use C, including objective\nreasons like compilation time and binary size, but most are more subjective/personal.  On the other other hand, I don't think the\n[\"It Runs Doom\"](https://knowyourmeme.com/memes/it-runs-doom) meme would exist if it were written in C++ and who doesn't want their\napplication to run on toasters and oscilloscopes 3 decades after it was released?\n\nLastly, I just like C.  It was my first language and is still my favorite for a host of reasons.\nHey, if it's good enough for Bellard, it's certainly good enough for me.\n\n## What PortableGL Is Not\n\nIt is *not* a drop in replacement for libGL the way Mesa and some other software rendering libraries are.  Porting a real OpenGL program to PGL will\nrequire some code changes, though depending on the program that could be as little as a couple dozen lines or so.  In many cases the biggest changes\nrequired have nothing to do with PGL vs OpenGL directly, but having to change the windowing system.  If you want to use PGL for full window software rendering\nyou need a system that supports blitting raw pixels to the screen.  Libraries like GLFW which are designed to be used with real OpenGL do not have that capability\nbecause everything is done through the OpenGL context.  There is some talk of adding some kind of\n[support for real software rendering](https://github.com/glfw/glfw/issues/589) but I don't see it going anywhere because it just doesn't make sense\nfor GLFW's goals.  SDL is great but it is a rather large dependency that links dozens of external libraries.  So what else is out there?\nI've seen many lighter windowing/input libraries out there that wrap platform specific toolkits that would work, most recently\n[RGFW](https://github.com/ColleagueRiley/RGFW/tree/main) which recently added a [PGL example](https://github.com/ColleagueRiley/RGFW/blob/main/examples/portableGL/main.c).\nThere are also, of course lower level/platform specific backends like win32 and X11's xlib which I now have examples for in the `backends` directory.\nSee the backends [README](https://github.com/rswinkle/PortableGL/blob/master/backends/README.md) for more details.\n\n\n### GL Version\n\nYou may have noticed that I link to OpenGL 4 references above, even though I describe PortableGL as \"3.x-ish\".\nThere is a good reason for that.\n\nWhen I first started PortableGL I originally wanted to target OpenGL 3.3 Core profile since that's what I knew, and\nfor the history of this project I've described it as 3.x-ish core, but that's not entirely accurate.  While I\ndon't include any of the old fixed function stuff (no glBegin/glEnd or anything that goes with them), right away\nI found that I supported some things from the compatibility profile (like a default VAO) for free.  Later I\nrealized there was no reason not to add the 4.x DSA functions which are also simple to implement as everything\nis in RAM anyway.  Mapping buffers is free for the same reason, and textures too (see\n[pgl_ext.c](src/pgl_ext.c)).\n\nIn late 2023 I was working with OpenGL ES 2.  I'd worked with it before but in the past it seemed\nso similar to what I already knew, I mostly skimmed the book, assuming most differences were just fewer formats\nand smaller limits.  Obviously that's not quite true.  In digging deeper, I learned about \"client arrays\" and they explain\nwhy the last parameter to VertexAttribPointer is `GLVoid* pointer` and not `GLsizei offset`.\nOf course the name should have given it away too.  Turned out even OpenGL 3.3 (compatibility) and ES 3.0 still\nsupport client arrays, as long as the current VAO is 0.  So now I technically match their spec but as a software\nrenderer, there's really no downside to using client arrays if you prefer that.  You can easily change\nthe [if statement](https://github.com/rswinkle/PortableGL/blob/master/src/gl_impl.c#L1271).\n\nAnd as of mid-2024 I just added support for the very useful GL [debug output](https://www.khronos.org/opengl/wiki/Debug_Output)\nfrom OpenGL 4.3. It doesn't support everything because most is overkill/unecessary for PGL so far but by default\nPGL will print all errors to `stdout` and you can set your own message handler with just like normal.\n\nSo what version of OpenGL is PortableGL?  _Shrug_, it's still mostly 3.x but I will add things outside of\n3.x as long as it makes sense to me and is in line with the goals and priorities of the project.\n\nReferences\n==========\n\nWhile I often used the official OpenGL documentation to make sure I was matching the spec as closely as realistically\npossible, what I used most, especially early on were a few textbooks.\n\nThe first was [Fundamentals of Computer Graphics 3rd Edition](https://amzn.to/2UIyAor) which I used\nextensively early on to understand all the math involved, including the matrix transformation pipeline, barycentric coordinates\nand interpolation, texture mapping and more.  There is now a [4th Edition](https://amzn.to/3quOj69) and a soon to be released\n[5th Edition](https://amzn.to/2U6nEkh).\n\nThe second was the 5th edition of the [OpenGL Superbible](https://amzn.to/3hcbLAS).  I got this in 2010, right\nafter OpenGL 3.3/4.0 was released, and used it for my college graphics course mentioned above.  A lot of people didn't like\nthis book because they thought it relied too much on the author`s helper libraries but I had no problems.  It was my first\nexposure to any kind of OpenGL so I didn't have to unlearn the old stuff and all his code was free and available online so\nit was easy to look inside and not only see what actual OpenGL calls are used, but to then develop\nyour own classes to your own preferences.  I still use a\n[class](glcommon/rsw_glframe.h)\nbased on his [GLFrame](https://raw.githubusercontent.com/rswinkle/oglsuperbible5/master/Src/GLTools/include/GLFrame.h)\nclass for example.\n\nIn any case, that's the book I actually learned OpenGL from, and still use as a reference sometimes.  I have a fork of\nthe [book repo](https://github.com/rswinkle/oglsuperbible5) too that I occasionally look at/update.  Of course they've come\nout with a [6th](https://amzn.to/3qF0iOZ) and a [7th edition](https://amzn.to/2UBRbCt) in the last decade.\n\nLastly, while I haven't used it as much since I got it years later, the\n[OpenGL 4.0 Shading Language Cookbook](https://amzn.to/3h7P0hI) has been useful in specific OpenGL topics occasionally.\nOnce again, you can now get the expanded [3rd edition](https://amzn.to/3qtatWr).\n\nSimilar/Related Projects\n========================\nI'll probably add others to this list as I find them.\n\n[TinyGL](https://bellard.org/TinyGL/) is Fabrice Bellard's implementation of a subset of OpenGL 1.x.  If you want something like PortableGL\nbut don't want to write shaders, just want old style glBegin/glEnd/glVertex etc. this is the closest I know of.  Also I shamelessly copied his\nclipping code because I'm not 1/10th the programmer Bellard was even as an undergrad and I knew it would \"just work\".\n\n[TinyGL Updated](https://github.com/C-Chads/tinygl): An updated and cleaned up version of TinyGL that adds several fixes and features, including performance\ntuning and limited multithreading.\n\n[Pixomatic](http://www.radgametools.com/cn/pixofeat.htm) is/was a software implementation of D3D 7 and 9 written in C and assembly by Michael Abrash\nand Mike Sartain.  You can read a [series](https://www.drdobbs.com/architecture-and-design/optimizing-pixomatic-for-x86-processors/184405765)\n[of](https://www.drdobbs.com/optimizing-pixomatic-for-modern-x86-proc/184405807)\n[articles](https://www.drdobbs.com/optimizing-pixomatic-for-modern-x86-proc/184405848) about it written by Abrash for Dr. Dobbs.\n\n[TTSIOD](https://www.thanassis.space/renderer.html) is an advanced software renderer written in C++.\n\nAs an aside, the way I handle interpolation in PortableGL works as a semi-rebuttal of [this article](https://www.thanassis.space/cpp.html).\nThe answer is not the terrible strawman C approach he comes up with just to easily say \"look how bad that is\".  The answer is that interpolation is\nan algorithm, a simple function, and it doesn't care what the data means or how many elements there are.  Pass it data and let the\nalgorithm do its job, same as graphics hardware does.  While the inheritance + template functions method works ok if you only have a few \"types\" of data,\nevery time you think of some new feature you want to interpolate, you need to define a new struct and a new template function specialization.\nHaving a function/pipeline that just takes an arbitrary amount of float data to operate on takes less code *and* even has less runtime overhead\nsince it's a single function that interpolates all the features at once rather than having to call a function for each feature.  See lines ~1200-1250\nof `src/gl_internals`.  Obviously it looks more complicated with all the other openGL stuff going on but you can see a simpler version on line 308 that's\nused for interpolating between line endpoints instead of over a triangle.  This is closer to his example but still longer because it has to support\nSMOOTH, PERSPECTIVE and FLAT.  You can see the shape of a straightforward implementation even there though, and the benefits of decoupling the\nalgorithm from the data it operates on.\n\n[Mesa3D](https://mesa3d.org/) is an open source implementation of OpenGL, Vulkan and other graphics APIs.  It includes several different software renderers including the Gallium rasterizer (softpipe or llvmpipe depending on whether llvm is used) and Intel's OpenSWR.\n\n[libosmesa](https://github.com/starseeker/osmesa) is an extraction and clean-up of the subset of Mesa3D 7.0.4 needed to support the old \"swrast\"\nsoftware rasterizer and OSMesa offscreen renderer (both of which were removed from upstream Mesa3D in 2020.)  libosmesa's intended purpose is to\nallow programs to offer a last-resort fallback renderer when system OpenGL capabilities are unavailable (or inadequate), while being fully self\ncontained and buildable as simple C with no external dependencies (which is why the 7.0.4 version was chosen for ths purpose.)  As that version\nof Mesa targets OpenGL v2.1, libosmesa may be a useful middle ground between PortableGL's OpenGL 3.x target and TinyGL's minimalist subset.\n\n[bbgl](https://github.com/graphitemaster/bbgl) is just a very interesting concept.  When I first saw it soon after it was published I was very frightened that it was exactly what PortableGL is but far more polished and from a better programmer.  Fortunately, it is not.\n\n[pixman](http://pixman.org/) I feel like you could use them together or combine useful parts of pixman with PortableGL.\n\n[fauxgl](https://github.com/fogleman/fauxgl) \"3D software rendering in pure Go.  No OpenGL, no C extensions, no nothin'.\"\n\n[swGL](https://github.com/h0MER247/swGL) A GPL2 multithreaded software implementation of OpenGL 1.3(ish) in C++. x86 and Windows only.\n\n[EmberGL](https://github.com/EmberGL-org/EmberGL) An MIT licensed 2D/3D graphics library featuring a tiled software rasterizer.\n\n[SoftGLRender](https://github.com/keith2018/SoftGLRender) A OpenGL renderer/rasterizer in modern C++.  The very impressive\ndemo lets you toggle and change various features and settings including switching seamlessly between the GPU and the software\nrenderer.  AFAIK, this is the only project that lets you write shaders in C++ like PortableGL, however the process is more complicated\nsince it has to work with the same class/API structure as real OpenGL and can't take the shortcuts that PortableGL does.\nAn advantage of all the extra plumbing and complexity is the actual C++ shader code is more standardized, looks a little cleaner, and more like GLSL.\nBesides supporting many more features (though I didn't see gl_FragDepth?), it is also optimized with threading, and SIMD on x86.\nGiven all the abstraction and extra overhead necessary to do what it does, it's impressive it manages to still be as fast as it is.\nAs best I can tell, disabling features to get vaguely close to an apples to apples comparison, it's about as fast as PortableGL.\nSo if you want OpenGL, don't need to use C, like modern C++/OOP style, and want software rendering while still being able to write your\nown shaders and avoid the old fixed-function mess, this might be the best option on this list (or a generic C++ OpenGL wrapper library\nlinked with modern Mesa+llvmpipe).\n\nTODO/IDEAS\n==========\n- [ ] Render to texture; do I bother with FBOs/Renderbuffers/PixelBuffers etc.? See ch 8 of superbible 5\n- [ ] Render to texture example program\n- [ ] ~~Finish duplicating NeHe style tutorial programs from [learningwebgl](https://github.com/rswinkle/webgl-lessons) to [opengl_reference](https://github.com/rswinkle/opengl_reference) and then porting those to use PortableGL~~ Port [learnopengl](https://learnopengl.com/) instead, repo [here](https://github.com/rswinkle/LearnPortableGL) WIP.\n- [x] Port medium to large open source game project as correctness/performance/API coverage test (Craft done, other ideas)\n- [ ] More texture and render target formats\n- [ ] Logo\n- [ ] Update premake scripts to Premake5 and handle other platforms once 5 is out of beta\n- [x] Formal regression testing (WIP)\n- [x] Formal performance testing (WIP)\n- [ ] Formal/organized documentation\n- [x] Integrated documentation, license etc. a la stb libraries\n\n","funding_links":["https://github.com/sponsors/rswinkle","https://liberapay.com/rswinkle","http://www.robertwinkler.com/donations.html"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frswinkle%2Fportablegl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frswinkle%2Fportablegl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frswinkle%2Fportablegl/lists"}