Skip to content

Commit

Permalink
First Public Commit/Release
Browse files Browse the repository at this point in the history
  • Loading branch information
rswinkle committed Sep 10, 2020
0 parents commit 475359f
Show file tree
Hide file tree
Showing 209 changed files with 345,471 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
@@ -0,0 +1,12 @@
# These are supported funding model platforms

#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
#patreon: # Replace with a single Patreon username
#open_collective: # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: rswinkle
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
custom: http://www.robertwinkler.com/donations.html
71 changes: 71 additions & 0 deletions .gitignore
@@ -0,0 +1,71 @@
# Object files
*.o

# Libraries
*.lib
*.a

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.pyc
*.app

#ignore ~ files
*~
*.gif
*.kate-swp
*.swp
CMakeFiles/*
CMakeCache.txt
cmake_install.cmake
stats/*

*/obj/*

build/*
!build/Makefile
!build/*.make

*.zip
*.tbz2
*.tgz
*.tar

media/music/*
media/video/*

examples/c_ex1
examples/c_ex2
examples/c_ex3
examples/ex1
examples/ex2
examples/ex3

demos/cubemap
demos/grass
demos/shadertoy
demos/sphereworld
demos/swrenderer
demos/texturing
demos/gears
demos/modelviewer
demos/pointsprites
demos/assimp_convert

testing/blend_test
testing/clipping
testing/edge_test
testing/line_perf
testing/line_test
testing/point_perf
testing/test_primitives
testing/zbuf_learn


42 changes: 42 additions & 0 deletions LICENSE
@@ -0,0 +1,42 @@
The MIT License (MIT)

Copyright (c) 2011-2020 Robert Winkler

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.


Clipping code copyright (c) Fabrice Bellard from TinyGL

Copyright notice:

(C) 1997-1998 Fabrice Bellard

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product and its documentation
*is* required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

If you redistribute modified sources, I would appreciate that you
include in the files history information documenting your changes.
140 changes: 140 additions & 0 deletions README.md
@@ -0,0 +1,140 @@
PortableGL
==========

"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


In a nutshell, PortableGL is an implementation of OpenGL 3.x core in clean C99. It can theoretically be used with anything that lets you render to a framebuffer/texture but all the demos use SDL2 and it currently only supports 8-bits per channel RGBA as a target (and also for textures).

Its goals are,

1. Portability
2. Matching the API within reason, at the least matching features/abilities
3. Ease of Use
4. Straightforward code
5. Speed

Obviously there are tradeoffs between several of those and some things. An example where 4 trumps 2 (and arguably 3) is with shaders. Rather than
write or include a glsl parser and have a built in compiler or interpreter, shaders are just special C functions that match a specific prototype.
Uniforms 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 just
passing a pointer to a user defined struct (see the examples).

Gallery
=======
![gears](https://raw.githubusercontent.com/rswinkle/opengl_reference/master/media/screenshots/gears.png)
![pointsprites](https://raw.githubusercontent.com/rswinkle/opengl_reference/master/media/screenshots/pointsprites.png)
![modelviewer](https://raw.githubusercontent.com/rswinkle/opengl_reference/master/media/screenshots/modelviewer.png)

History
=======
PortableGL started as a very simple wireframe software renderer based on a tutorial in summer 2011. I kept playing with it and adding minor features
over the next year and then in early 2013 I decided I should turn it into a software implementation of OpenGL. This would save me a huge amount of time
and 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
and potentially others. Also, at the time Mesa3D was still years away from full 3.x support, not that I'm really competing but just the fact that there
was 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
mostly 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
could have released an MVP back in 2014 at the earliest but late 2016 would have been the best compromise. Anyway after somewhere between 300 and 1000+
hours (depending on what/how you count) spread out over 9 years, I've finally finished the the last 90% or at least enough to justify sharing it.
Software is never finished, and I'll be the first to admit PortableGL could use more polish.

Why
===
Aside 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.

#### Educational
I 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
Red 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
professors still teach 1.x and 2.x OpenGL today in 2020 far more commonly than 3.x/4.x (or Vulkan). A few are using WebGL 2.0 ...

While Vulkan is the newest thing (already 4 years old time flies), it really is overkill for learning 3D graphics. There is nothing that students
make in your standard intro to 3D graphics that remotely stresses the performance of any laptop built in the last decade plus. Using modern OpenGL
to introduce all the standard concepts, vertices, triangles, textures, shaders, fragments/pixels, the transformation pipeline etc. first is much better
than trying to teach them Vulkan and graphics at the same time and obviously better than teaching OpenGL API's that are decades old.

PortableGL could be a very convenient base for such a class. It's easy to walk through the code and see the pipeline and all the steps flow together.
For more advanced classes or graduate students in a shared class, modifying PortableGL in someway would be a good project. It could be some
optimization or algorithm, maybe a new feature. Theoretically it could be used as a base for actual research into new graphics algorithms or techniques
just because it's such a convenient small base to change and share, vs trying to modify a project the size and complexity of Mesa3D or create a software
renderer from scratch.

#### Special Cases
It'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
IEEE 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
be better to stick to whatever the hardware supported than use PortableGL. However, theoretically, there could be some platform somewhere where the CPU
is relatively powerful that doesn't have GPU. Maybe some of the current and future RISC SoC's for example? In such a case PortableGL might be a
useful alternative to Mesa3D or similar.

Another 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
to 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.

Documentation
=============
TODO

For now, there's no formal documentation but looking at the examples and demos (and comparing them to [opengl_reference](https://github.com/rswinkle/opengl_reference) should be helpful. Honestly, the official OpenGL docs and man pages are good for 90-95% of it as far as basic usage.

Building
========
If you have SDL2 installed you should be able to cd into examples, demos, or testing and just run `make` or `make config=release` for an optimized build.
I use premake generated makefiles that I include in the repo, but you should be able to compile it on Windows or Mac too, there's nothing Linux
specific about the code. I'll fill out this section more later.

Similar/Related Projects
========================
[TinyGL](https://bellard.org/TinyGL/) is Fabrice Bellard's implementation of a subset of of OpenGL 1.x. If you want something like PortableGL
but 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
clipping code because I'm not 1/10th the programmer Bellard was even as an undergrad and I knew it would "just work". I've included his copyright
and BSD license in LICENSE just in case.


[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
and Mike Sartain. You can read a [series](https://www.drdobbs.com/architecture-and-design/optimizing-pixomatic-for-x86-processors/184405765)
[of](https://www.drdobbs.com/optimizing-pixomatic-for-modern-x86-proc/184405807)
[articles](https://www.drdobbs.com/optimizing-pixomatic-for-modern-x86-proc/184405848) about it written by Abrash for Dr. Dobbs.


[TTSIOD](https://www.thanassis.space/renderer.html) is an advanced software renderer written in C++.

As an aside, the way I handle interpolation in PortableGL works as a semi-rebuttal of [this article](https://www.thanassis.space/cpp.html).
The 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
an 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
algorithm do its job, same as graphics hardware does. While the inheritance + template functions works ok if you only have a few "types" of data,
every time you think of some new feature you want to interpolate, you need to define a new struct and a new template function specialization.
Having a function/pipeline that just takes an arbitrary amount of float data to operate on takes less code *and* even has less runtime overhead
since 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
of gl_internals.c. 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
used for interpolating between line endpoints instead of over a triangle. This is closer to his example but still longer because it has to support
SMOOTH, PERSPECTIVE and FLAT. You can see the shape of a straightforward implementation even there though, and the benefits of decoupling the
algorithm from the data it operates on.

[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.

[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.


[pixman](http://pixman.org/): I feel like you could use them together or combine useful parts of pixman with PortableGL.


LICENSE
=======
PortableGL is licensed under the MIT License (MIT)

The code used for clipping is copyright (c) Fabrice Bellard from TinyGL under the
BSD License, see LICENSE.


TODO/IDEAS
==========
- [ ] Render to texture; do I bother with FBOs/Renderbuffers/PixelBuffers etc.? See ch 8 of superbible 5
- [ ] Multitexture and texture array and render to texture example programs
- [ ] Mapped buffers according to API and...
- [ ] Extension functions that avoid unecessary copying, ie user owns buffer/texture data and gl doesn't free
- [x] Unsafe mode (ie no gl error checking for speedup)
- [ ] 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 medium to large open source game project as correctness/performance/API coverage test?
- [ ] Fix cubemapping skybox texture bug
- [ ] More texture and render target formats
- [ ] Formal/organized documentation

88 changes: 88 additions & 0 deletions demos/Makefile
@@ -0,0 +1,88 @@
# GNU Make solution makefile autogenerated by Premake
# Type "make help" for usage help

ifndef config
config=debug
endif
export config

PROJECTS := swrenderer sphereworld shadertoy texturing cubemap grass gears modelviewer pointsprites assimp_convert

.PHONY: all clean help $(PROJECTS)

all: $(PROJECTS)

swrenderer:
@echo "==== Building swrenderer ($(config)) ===="
@${MAKE} --no-print-directory -C . -f swrenderer.make

sphereworld:
@echo "==== Building sphereworld ($(config)) ===="
@${MAKE} --no-print-directory -C . -f sphereworld.make

shadertoy:
@echo "==== Building shadertoy ($(config)) ===="
@${MAKE} --no-print-directory -C . -f shadertoy.make

texturing:
@echo "==== Building texturing ($(config)) ===="
@${MAKE} --no-print-directory -C . -f texturing.make

cubemap:
@echo "==== Building cubemap ($(config)) ===="
@${MAKE} --no-print-directory -C . -f cubemap.make

grass:
@echo "==== Building grass ($(config)) ===="
@${MAKE} --no-print-directory -C . -f grass.make

gears:
@echo "==== Building gears ($(config)) ===="
@${MAKE} --no-print-directory -C . -f gears.make

modelviewer:
@echo "==== Building modelviewer ($(config)) ===="
@${MAKE} --no-print-directory -C . -f modelviewer.make

pointsprites:
@echo "==== Building pointsprites ($(config)) ===="
@${MAKE} --no-print-directory -C . -f pointsprites.make

assimp_convert:
@echo "==== Building assimp_convert ($(config)) ===="
@${MAKE} --no-print-directory -C . -f assimp_convert.make

clean:
@${MAKE} --no-print-directory -C . -f swrenderer.make clean
@${MAKE} --no-print-directory -C . -f sphereworld.make clean
@${MAKE} --no-print-directory -C . -f shadertoy.make clean
@${MAKE} --no-print-directory -C . -f texturing.make clean
@${MAKE} --no-print-directory -C . -f cubemap.make clean
@${MAKE} --no-print-directory -C . -f grass.make clean
@${MAKE} --no-print-directory -C . -f gears.make clean
@${MAKE} --no-print-directory -C . -f modelviewer.make clean
@${MAKE} --no-print-directory -C . -f pointsprites.make clean
@${MAKE} --no-print-directory -C . -f assimp_convert.make clean

help:
@echo "Usage: make [config=name] [target]"
@echo ""
@echo "CONFIGURATIONS:"
@echo " debug"
@echo " release"
@echo ""
@echo "TARGETS:"
@echo " all (default)"
@echo " clean"
@echo " swrenderer"
@echo " sphereworld"
@echo " shadertoy"
@echo " texturing"
@echo " cubemap"
@echo " grass"
@echo " gears"
@echo " modelviewer"
@echo " pointsprites"
@echo " assimp_convert"
@echo ""
@echo "For more information, see http://industriousone.com/premake/quick-start"

0 comments on commit 475359f

Please sign in to comment.