[HN Gopher] Olive.c: a simple graphics library that does not hav...
___________________________________________________________________
Olive.c: a simple graphics library that does not have any
dependencies
Author : masterofsome
Score : 466 points
Date : 2022-09-21 22:50 UTC (1 days ago)
(HTM) web link (tsoding.org)
(TXT) w3m dump (tsoding.org)
| treuks wrote:
| Please do note that it is in an extremely early stage of
| development, so if it may seem raw and unpolished, it is because
| it is.
| dezmou wrote:
| Nice to see tsoding on the top of HN, this guy does amazing
| streams and youtube video
| mikedelago wrote:
| I agree, he's pretty great. Really intelligent guy.
|
| It's a damn shame that he's unable to get paid from Twitch and
| Youtube due to the war.
| NeutralForest wrote:
| Dude is insanely talented and patient enough to learn new
| stuff, it's always a pleasure to watch the videos even though
| they're usually really long.
| _qua wrote:
| I only follow about 20% of what he does because of my limited
| skill but he's certainly entertaining.
| abainbridge wrote:
| How can I find them?
| sph wrote:
| He's got a channel on the tube, Tsoding Daily. These days
| he's really into WASM and Jai, but he's always trying
| something new.
|
| https://youtube.com/c/TsodingDaily
| SiempreViernes wrote:
| Using the search field on youtube is probably easiest.
| abainbridge wrote:
| Gee thanks. I tried typing olive.c there. That didn't help.
| The string "tsoding" is the magic I needed.
| WoodenChair wrote:
| I started something superficially similar but for SVG in an intro
| C class: https://github.com/davecom/SuperSimpleGraphics
| two_almonds wrote:
| _The name is pronounced as "olivets" which is a Ukrainian word
| for "pencil" ("olivets'")._
|
| From the readme.
| SotCodeLaureate wrote:
| Neat.. of course it seems obvious now, but that's funny - I'm
| Ukrainian and I think that without explicit explanation it
| would have never occurred to me to read, let alone pronounce it
| this way - the dot before the extension somehow puts an
| insurmountable boundary after "olive".
| lioeters wrote:
| As a long-time beginner student of several Slavic languages,
| I like that word play too, with ".c" being "ts". It makes me
| wonder what missed opportunities there are for C library
| names with a funny pun.
| sylware wrote:
| arriu wrote:
| Any plans for text rendering?
| tyingq wrote:
| There's a fairly simple olivec_text() function there that uses
| a built-in bitmap font.
| an1sotropy wrote:
| The TODO section at the end of olive.c shows that there's lots
| more to do, and decisions to make about how much to do (e.g. what
| about bezier curves?), but that's quibbling: it is refreshing
| (and educational) to see everything here done in such a perfectly
| self-contained way. Godspeed!
| shultays wrote:
| Hell, half the letters in alphabet is not implemented in that
| glyph list. That is a weird place to leave a work halfway done.
| I wonder if he only added the letters for his hello world
| bearon wrote:
| Nice! An awesome retrospective.
| tleb_ wrote:
| Idea for improvement: avoiding color blending in sRGB. A first
| step would be to work in linear space.
|
| https://github.com/tsoding/olive.c/blob/43a67dd76760f915516a...
| simonw wrote:
| This is so nice. It feels a bit like Logo using C syntax - I love
| that it's totally safe to run software written in this in a
| browser thanks to WebAssembly.
| erwincoumans wrote:
| Cool use of Webassemly! See also the 500 line
| https://github.com/ssloy/tinyrenderer or the 100 line
| Python/numpy version https://github.com/rougier/tiny-renderer
|
| Both cpu renderers with texture mapping and Wavefront obj import
| without further dependencies.
| billsix wrote:
| Nice! PortableGL is also great, OpenGL api that is defined in
| entirely in C and writes the "framebuffer" into an SDL window
|
| https://github.com/rswinkle/PortableGL
| rswinkle wrote:
| Minor correction/clarification, the library doesn't depend on
| SDL, it just writes into a 32 bit color frame buffer, but all
| the demos/examples use SDL for getting it to the screen since
| that's the best option. The test suite just writes frames to
| disk as png images to compare against expected for example.
| jstimpfle wrote:
| It's an implementation, not an API.
| sylware wrote:
| ... and it is opengl-ish, namely seriously castrated
| (shaders). Borrowing maths from Mr. Bellard's tinygl.
| rswinkle wrote:
| Depends on how you define castrated. It's not like using C
| or C++ is really limiting and using a C++ math library
| (like my own rsw_math or more complete glm) lets you
| basically write it in GLSL. It's not like there's anything
| you can't do.
|
| And the only math from Bellard's TinyGL that I use is his
| clipping code, maybe 80 lines of code give or take. Not to
| diminish Bellard at all, if anything I'm saying any
| problems with PortableGL are mine not his.
| sylware wrote:
| My bad, I used "castrated", it is not what I really
| wanted to say. I should have said a subset of opengl
| features. Namely, it is not a software GL implementation
| you can run an opengl4 3D game on (only those horrible
| c++ diarehas which are llvm with things like llvmpipe or
| the other one from intel are supposed to be able to do
| so).
| osener wrote:
| I also found this Cairo-like vector graphics library that runs in
| a shader interesting: https://www.shadertoy.com/view/lslXW8
| stoeckley wrote:
| That is truly one of the coolest things I've seen in a while.
| TazeTSchnitzel wrote:
| It's cool that you can get away with software rendering these
| days, but it's a shame to not make use of the power of the GPU.
| jesse__ wrote:
| That's the point. Also, not all devices have dedicated graphics
| hardware
| nottorp wrote:
| And even if they do, if they're portable please think of my
| battery :)
| TazeTSchnitzel wrote:
| Only embedded systems and servers lack it these days. Server-
| side rendering is an interesting use-case, I guess.
| urjjhjx wrote:
| dlivingston wrote:
| Cool project! What's the motivation? Since it eschews any
| graphics API, is it safe to assume this only does CPU-based
| rendering?
| feiss wrote:
| yes, this is only cpu based
| skulk wrote:
| From demos/triangle.c (https://github.com/tsoding/olive.c/blob/
| master/demos/triangl...) // This idea is that
| you can take this code and compile it to different platforms
| with different rendering machanisms: // native with
| SDL, WebAssembly with HTML5 canvas, etc.
|
| The goal seems to be to maximize portability.
| p1necone wrote:
| Unfortunately only portable to systems with fast CPUs though.
| Although I guess rendering simple 3d shapes probably runs
| just fine on low end hardware.
| keeglin wrote:
| Uh, right? The demo page renders fine on this decade old
| core i5-3337u, with all the vulnerabilities patched.
| unsafecast wrote:
| It depends how fast "fast" is. PCs in the 90s could run
| games like quake in lower quality mode with lower
| framerates, but they ran. CPUs that we have now are many
| orders of magnitude more powerful, so imagine what you can
| do with that.
|
| Though most games don't bother so we don't really have
| actual evidence.
| mysterydip wrote:
| I was thinking about this just yesterday, it would be
| neat to have a game jam to make something run in dosbox
| at modern cpu speeds.
| Someone wrote:
| Quake used hand-coded assembly for blitting pixels. That
| could be a bit less efficient when using this engine.
|
| I would expect multi+GHz CPUs hardware to be able to
| overcome that, though, especially if you're happy with
| the tiny (for today) screen resolution of Quake.
|
| Quake also did a few hacks to stay performant (https://en
| .wikipedia.org/wiki/Quake_engine#Engine_design_and...).
|
| If necessary you would have to do the same for something
| that uses this library.
| unsafecast wrote:
| I'm not giving this library as an example of very fast
| code. I mean, it's really cool, but at the moment it
| doesn't even use SIMD (which _dramatically_ improves
| performance).
|
| Also, I think handmade hero started with a software
| renderer. Not sure how far they went with that, but I
| remember Casey mentioning once that software rendering is
| viable if you do it right. Certain art styles are easier
| to do as well -- I'm not expecting PBR to be fast, but
| you could pull off a cel shaded look with simple
| lighting, and make it look good.
|
| It's also worth mentioning that even with portable APIs
| like OpenGL, drivers are terrible and porting to other
| operating systems (and even other GPUs!) can be a chore.
| Software rendering can be an asset in those cases.
| nspattak wrote:
| i understand that it is more portable but if it is cpu based,
| i guess its power performance is terrible since it is not
| using gpu acceleration which is a priori more efficient
| quickthrower2 wrote:
| The combination of mapping pixels to memory and rendering
| individually and then that appearing on webgl and looking great
| on a not too expensive phone, where I am pinch zooming while it
| flawlessly animates, sort of blows my mind in how much technology
| has come in 25 years. Connects the old with the new in a way I
| haven't seen for a while (and yeah seen loads of C64 emulators
| and such)
| sriram_malhar wrote:
| At first I thought the demos were gifs! After seeing your
| comment, I went back and remained slack-jawed!
| darkwinx wrote:
| those are canvas with 2d context, not webgl
| tambourine_man wrote:
| Amazing that software rendering can be this smooth on a phone.
| altilunium wrote:
| Years ago, i made something similar as a coursework (Computer
| Graphics)
|
| https://github.com/rtnF14/ComputerGraphics
| jandrese wrote:
| It pains me to see #include <olive.c> at the top of the file. It
| makes the project feel like a toy.
| kazinator wrote:
| It looks like olive.c is a "single header" library. They chose
| a .c suffix rather than .h.
|
| If OLIVE_IMPLEMENTATION is defined before including "olive.c",
| then the full implementation is produced. Otherwise, just
| declarations, so that it behaves like a header file.
|
| It's a valid technique. If you have a library all in one source
| file, the requirement to have a separate .h doubles your file
| count.
|
| One small reason to have a .c suffix is might be that your
| editor can then choose a more specific syntax scheme. A .h file
| could be C++. Another one is that it can be used as a source
| file. You can pop it into a Makefile project, and just make
| sure you have -DOLIVE_IMPLEMENTATION on the compiler command
| line for that file. Other files using it just include "olive.c"
| to get the declarations. Because it has a .c suffix, make will
| handle it via its .c.o rule.
| jandrese wrote:
| This feels far messier to me than just having a .h file.
| worthless-trash wrote:
| Its part of the spec, and not even obscure. this is not
| even scratching the surface of nightmare level C.
| Brian_K_White wrote:
| In this case, 2 files is a failure and blows the whole
| point. 2 files means a tgz and might as well be 50 files.
| kazinator wrote:
| Sure, but let's look at the larger picture. If you have one
| file, then that's your deliverable. You can host that file
| somewhere, send it as an e-mail body, drop it into a paste-
| bin or whatever. It is one self-contained unit.
|
| If you have two files: .h and .c, the use scenario may be
| simpler. Not a lot though. And now youu have two files
| which have to stay together somehow, yet remain distinct.
| If you combine them in one body of text, you have to
| indicate: oh, please snip out this part as a .h file and
| then the rest as a .c file. In e-mail you can have it as
| two separate MIME attachments. You can use an archive file
| --- have you looked into the formats? Not so simple.
|
| It's not hard to understand the attraction to the one file
| deployment, even if you don't do it yourself.
| mrweasel wrote:
| Can you do something like what SQLite does an squash the
| .h and .c into one file, but also have multiple files for
| those who are doing development or just like separate
| files?
| kazinator wrote:
| Yes, I can, and so can you, without a doubt.
|
| If I wanted to distribute a single file library, but have
| the two file option for users, I'd make it so that a
| specific Awk one-liner produces the two. For instance,
| the file might look like this: #ifndef
| FOOBAR_LIB_H_D3B94F3C #define
| FOOBAR_LIB_H_D3B94F3C // header stuff here
| #endif // FOOBAR_LIB_H_D3B94F3 #if
| FOOBAR_LIB_IMPL // impl here
| #endif
|
| Then to people who want two, I would say, just run this
| command in your shell and paste the content into it:
| awk 'BEGIN { print "#include \"foobar.h\"" > "foobar.c"
| print "#define FOOBAR_LIB_IMPL" > "foobar.c" }
| /#ifndef FOOBAR_LIB/,/#endif.*FOOBAR_LIB/ { print >
| "foobar.h"; next } { print > "foobar.c" }'
|
| that way I wouldn't need a build step on my end to
| generate parallel files.
|
| I would have the extra build step if it were a large
| project of multiple .c files that I wanted to deploy as a
| single file for the users who want that. (Not only would
| I build the single file out of multiple files, but also
| have some test cases which actually use it. Things have
| ways of breaking when you combine files, like giving the
| same name two two static variables or functions in
| different files.)
| KMnO4 wrote:
| Just wait till you find out that you can do:
|
| const char *s =
|
| #include "test.txt"
|
| ;
| unwind wrote:
| Sure, but only if the text file looks like a C string
| literal, i.e. starts and ends with double quotes (which would
| make it into a weird text file).
|
| Doing const char *s = " #inclued
| "test.txt" ";
|
| won't work, since the preprocessor won't interpret directives
| inside string literals of course.
|
| In many assemblers, there is a directive called "incbin"
| which pastes in unstructured binary data at the point of
| usage. I just found a very clever C and C++ wrapper [1] for
| that, which gives you an INCBIN() macro. Nice!
|
| [1]: https://github.com/graphitemaster/incbin
| a_e_k wrote:
| An incbin-like facility is coming to the standard:
| https://thephd.dev/finally-embed-in-c23
| unwind wrote:
| Yeah, I actually had heard about that but it didn't show
| up in my first search. Thanks!
| iforgotpassword wrote:
| Yeah, ignoring incbin hackery, a better example than
| strings might be float vertices[] = {
| #include "stuff.txt" };
| cygx wrote:
| Note that C23 will include a variant of _incbin_ spelled
| _#embed_ : Semantically, the preprocessor will insert a
| list of integers which you can use to initialize an array.
| jsmith45 wrote:
| Also, for clarity, it is fully expected that the compiler
| will use the as-if rule to optimize it. Most likely by
| having a dedicated token/ast node that only decomposes to
| comma separated values if if actually needs to, with
| common usage in initalizers being handled by simply
| copying the data directly into a static data segment
| without ever creating an integer list at all.
| LastTrain wrote:
| Then you made an incorrect assumption without enough
| investigation.
| mcmuffin6o wrote:
| Sorry, why does it make the project feel like a toy? I'm not
| trying to argue, I just don't understand. Is it because you're
| including a source file instead of a header file?
| teraflop wrote:
| The function _declarations_ and _definitions_ are all
| commingled in a single file. So if you want to use this
| library in a project that contains multiple source files, you
| have to include a duplicate copy of the implementation
| (including e.g. the static font data) in every single
| compilation unit.
|
| It's possible that your linker would be smart enough to
| identify and remove the duplicates, but it's still inelegant,
| unidiomatic and needlessly inefficient.
| jandrese wrote:
| gcc or clang would crash on the linking step complaining
| about duplicate symbols. This library is only good for a
| project that is built in a single .c file.
| esrauch wrote:
| That's not true in this case: if you look at the .c file
| you can see it actually has no definitions by default and
| is a relatively normal .h file when it's included.
|
| You can #include it in any number of files as long as
| exactly one has #define OLIVEC_IMPLEMENTATION.
| anthk wrote:
| False.
| dundarious wrote:
| There are many single-file C "libraries" that work
| perfectly fine as both "header" and "implementation", and
| that do not require unity builds (building everything as
| a single translation unit, e.g., a single .c file). Here
| is but one famous collection of them:
| https://github.com/nothings/stb
| bangonkeyboard wrote:
| Incorrect. The implementation is #define'd out of every
| compilation unit save one.
| teraflop wrote:
| Ah, I missed that, but I don't think your comment is
| precisely correct either.
|
| All of the function definitions are declared with
| OLIVECDEF, which by default is #defined as `static
| inline`. So if you want to only get a single copy of the
| implementation, you would have to choose one compilation
| unit that defines OLIVEC_IMPLEMENTATION, _and_ you would
| have to define OLIVECDEF as something else (like the
| empty string) that causes the functions to be non-static.
|
| Still kind of hacky, but not as bad as I thought.
|
| EDIT: I just noticed that only _some_ of the functions
| are marked with OLIVECDEF, so you _have_ to do this trick
| if you want to reference the library in multiple
| compilation units, or else you would get duplicate
| symbols. The default behavior doesn 't seem like it would
| ever be useful.
| hactually wrote:
| All good - I struggled when I first started with C.
|
| The macro preprocessor is like a Schrodinger's Cat of
| helpful and painful!
| collegeburner wrote:
| single-file libraries almost always feel like toys because
| most serious projects i'd want them integrated into a real
| build system. vcpkg is a good one these days for c/cpp.
| nothing wrong with a toy library ofc.
| TillE wrote:
| Unless it contains C++ templates, it's fairly trivial to
| compile a "header-only" library and use it as normal, even
| in unusual cases where the author has made no effort to
| support that.
| ctrlmeta wrote:
| Just saying that these "feel like toys" is a very low-
| effort comment. Header-only libraries exist even if
| uncommon and they work fine when written properly.
|
| If you actually use a header-only library and it fails to
| link properly or be used in a project with multiple
| compilation units, then that would be a bug in the header-
| only library worth discussing and fixing. That would be a
| good-effort and interesting comment.
| butterisgood wrote:
| sqlite has amalgamated source too. It's used EVERYWHERE.
| This opinion doesn't seem like it's based on anything valid
| or real.
|
| Note you get some opportunities for better compiler
| optimizations when the entire compilation unit is the
| entire project. In fact, sqlite claims the code runs 5-10%
| faster when built as an amalgamation
| (https://www.sqlite.org/amalgamation.html)
| m00dy wrote:
| I have been wondering what he is going to do under the recently
| declared partial mobilisation. I hope he could find a way to get
| out the country. He needs to know he is always welcomed in
| Turkiye.
| synergy20 wrote:
| this is very impressive, how is this done? the executable is only
| a few hundred KB and it runs for me, wasm is doing the magic here
| but I don't know too much about how the process works.
|
| I added -I/usr/include/SDL2 to build.sh, made sure wasm-ld is in
| place, and it builds and runs smoothly.
| Jasper_ wrote:
| It's a simple software rasterizer. If you're interested in
| writing your own, I've written a tutorial explaining the
| basics. https://magcius.github.io/xplain/article/rast1.html
| dazhbog wrote:
| Nice website. Looking forward to the next rasterization
| article!
| sowbug wrote:
| Also look at the source for original Quake
| (https://github.com/id-Software/Quake), one of the last pure
| software-rasterizing AAA 3D PC games. Michael Abrash's
| Graphics Programming Black Book
| (https://github.com/jagregory/abrash-black-book) explains
| many of the critical parts of the rendering pipeline.
|
| By the way, quake.exe for DOS was 404,480 bytes.
| andai wrote:
| Does this use WebGL2? It doesn't run on my phone (which does
| support WebGL 1).
|
| Edit: According to the JS source file it appears to be a plain 2D
| canvas. Now I am even more confused, those should definitely
| load!
|
| https://github.com/tsoding/olive.c/blob/master/js/vc.js
| jeroenhd wrote:
| Depending on your privacy settings, your anti fingerprinting
| configuration may block canvas operations. I know some
| stringent Firefox fingerprinting protection used to do this,
| not sure if that has been refined since.
| MobiusHorizons wrote:
| If you read the linked article, it is a c cpu rendering library
| compiled to web assembly.
| unsafecast wrote:
| Does your browser version support webassembly?
| ofrzeta wrote:
| From the build.sh I figured out that all it takes is to compile
| with the wasm target, I think:
|
| clang $COMMON_CFLAGS -Os -fno-builtin --target=wasm32 ...
___________________________________________________________________
(page generated 2022-09-22 23:02 UTC)