Hacker News new | past | comments | ask | show | jobs | submit login
3D graphics rendering pipeline. Implemented in JavaScript. Run in a terminal (github.com/sinclairzx81)
229 points by bwidlar on Oct 28, 2019 | hide | past | favorite | 51 comments



This is awesome! As an enthusiast of 3D graphics, I appreciate how clean and easy to read the source is. We have very few examples of how the graphics pipeline works in code, tinyrenderer [1] by ssloy being one of the most famous and easy to follow. This should enter the awesome-graphics list as a must read code!

[1] - https://github.com/ssloy/tinyrenderer


The amazing Michael Fogleman also has https://github.com/fogleman/fauxgl - a software renderer written in Go.


This is code is very clean... someone should add this to a list of very nice codebases to read.


Graphics pipelines are typically well understood. Software renderers capable of N64 like graphics are not complex to write:

https://github.com/glouw/gel/blob/master/main.c

But you are right. It does take some ingenuity to make it clean.


I agree. Does anyone know how they achieve the alignment of all the ‘=‘ signs? Perhaps a VSCode extension?


SublimeText has the AlignTabs extension which can do this.


Great, thanks for the tip. I managed to find an equivelent in vscode called Auto-Align


The title says "JavaScript", but the file extension says ".ts". It doesn't look very Javascript to me.

Can anyone clarify?


It's TypeScript! It is "a strict syntactical superset of JavaScript, and adds optional static typing to the language." [1], and compiles to standard JavaScript.

[1] https://en.wikipedia.org/wiki/TypeScript


A more correct word for converting code from one programming language into another is "transpile".


It's always "from one language to another", sometimes the destination is machine language. The output is generally not meant to be meant to be human-readable in any case. "Transpile" is an ugly and unnecessary word, please don't push it as "more correct".


> It's always "from one language to another“

Hmmm, sometimes it’s “from one version of a language to another version of the same language”. As is the case with Babel[0] and JavaScript.

[0] https://babeljs.io/


I mean, arguably ES6 and TS are as close or closer to being "the same language" than ES6 and Babel targets.


It's just a more specific word. You can say all words are unnecessary because you can express the same thing using more words.


"Transpilation" and "compilation" describe the exact same concept. From user's perspective, readable code is translated into runnable code. From theoretical perspective, code in a more complex language is translated into a less complex language while preserving semantics. From a compiler writer's perspective, it's a totem pole of compilers, with at least one middle-level language usually. Plenty of people use the term "compiles to JavaScript" to describe languages like TS or Elm. It's just some overly pedantic people insist on the term "transpile" when the target is also, in a completely unrelated way, used to write code directly by a significant number of contemporary programmers.


> "Transpilation" and "compilation" describe the exact same concept.

No I think transpile implies compiling from one level of abstraction to another similar level of abstraction, which is quite different in theory and practice to compiling to a much lower level of abstraction. It's a useful word to have in your communication toolbox.


I agree with your overall definition. In fact, the dictionary definition of compile does also suggest that you are transforming to a 'lower level' so, in strictness, there is a need for a word to fill the void that you suggest transpile provides.

But I do wonder about the actual usefulness of the distinction. If someone says that they compile Typescript to Javascript, I'm not sure that anyone is going to be confused about what is meant, even if violates the letter of the dictionary definition.

Ultimately, english is fluid and is always correct as long as those in communication are able to understand each other. For transpile to be a useful word in the toolbox, there must be a circumstance where compile cannot be used to convey the same idea. When might that be?


'This is a transpiler' gives me a massive amount of additional context compared to 'this is a compiler' - likely structure, implementation techniques, output. Not all transpilers will fit this usual structure, but if they do you can tell me by changing this one little word. Powerful communication tool, I think.


But neither 'this is a transpiler' or 'this is a compiler' provide any meaningful information without specifying the compatible inputs and outputs. Once the inputs and outputs are specified then it is already reasonably known if the operation is transpilation or compilation, making the distinction between transpiler and compiler redundant.


Fine, but by that logic, gcc with -O0 is a transpiler, and becomes a compiler again with -O2. Similarly, TS transpiles to JS, but, say, ClojureScript compiles to JS. And if a compiler is built with something like Nanopass, it's a sequence of transpilers that somehow become a compiler along the way.


No I don’t agree. A compiler pass is not a compiler. An non-optimising C to assembly compiler is not compiling to the same level of abstraction.


>A compiler pass is not a compiler.

What is the difference, if there's one well-defined language before the pass and another after it?

>A non-optimising C to assembly compiler is not compiling to the same level of abstraction.

Neither are "transpilers", otherwise they'd be quite useless. Abstraction isn't a linear hirerarchy, in any case.


Terms are fuzzy. That doesn't mean they're useless. When I talk about 'transpilers' instead of 'compilers' it instantly gives people context.

The term's been in use since the 60s, when most compilers were not optimising.


Transpile is a superset or compile just like typescript is a superset of JavaScript. Transpile implies translating but not into a less complex language but rather onto a similar runtime. So typescript is dynamic just like JavaScript, and they share much of their semantics. So transpile means compile but onto a similar runtime with similar runtime semantic behavior.


In that case surely you'd agree that there are hardly any compilers in wide use these days - more often than not the first step of a modern compiler is translation into a similar but less expressive intermediate language.

Or does it only count as "transpilation" if the intermediate representation is an already existing language, thus making the distincion purely based on the history of a language, not the implementation?


It’s TypeScript. You can strip the annotations and type definitions and it’s pure JS. TS is typically ran on JS runtimes, hence why people consider TS programs to also just be JS program.

*not exactly, there’s a couple of features that map differently. But there's a 1:1 TS to JS conversion.


I think it's worded in a way that's odd to developers that usually write code for multiple target languages.

What you type is usually considered what it's implemented in, not what it's compiled/transpiled to. The later is the target language, which there may be many.

This differentiation is required if you want to modify/read the code. You would almost certainly modify/read it in the language it was implemented in, and make it clear which language this is when sharing.

Maybe "...implemented in TS, targeting JS" or at least something more obvious like "...implemented in JS using TS".


.ts comes from TypeScript, which is just JavaScript but with compile-time-checked types (and some other goodies) added on top. TS is really popular now, I don't think any sane dev would start a new project today in plain JS instead of TS.


That's huge hyperbole there. Plenty of projects are started in JS today. It's still wise to provide typings to your user base if you're publishing a library, whether or not you're using TS under the hood.


I agree with parent that while people will still start JS projects today they'd probably be better off with TS.


It's typescript.


The source code is TypeScript, which once compiled produces JavaScript.


Author's name "sinclairzx81" and the logo implies an affiliation with the 1980s computer & company. Is there any?


In most cases like this, the affiliation is that of former user with fond memories.


Maybe a user of the ZX81?


This is awesome, very well done.

As someone with very little knowledge of computer graphics, are there any resources anyone would recommend in order to learn how to build something like this?


A smaller subproblem to get you started is to build a matrix multiplication library (with matrices, vectors, and the ability to multiply them).

Note that when you're building test cases, matrix multiplication is not commutative.

My high school teacher literally just pointed me at the Wikipedia article and said go:

https://en.wikipedia.org/wiki/Matrix_multiplication

The next step up from that is to then render meshes using some form of projection (isometric or perspective). You'll need to figure out how to actually map the drawing to the screen at that point. (In high school we just used the built-in 2D methods in Java. Some of my classmates then went on to shading and textures, but I didn't quite get that far.)


I'm not sure linear algebra is the best way to get into 3D graphics. I'd suggest, starting with old fashioned 3D renderers such as ray casters.

https://en.wikipedia.org/wiki/Ray_casting

Of course it has more to do with raytracing than with 3D projections (which is most often used for real time 3D rendering). If you want to learn about 3D projections, first you should understand what linear algebra has to do with projecting a 3D model on a 2D screen. This is probably a good start.

https://en.wikipedia.org/wiki/3D_projection

And then, learning about matrix multiplications makes sense.


You should DEFINITELY write your own matrix library to learn the underlying principles, but once you want your renderer to actually do something with reasonable speed you'll pretty quickly be replacing your homegrown matrix code with something like Eigen that handles SIMD for you.


For rendering at interactive rates, maybe check out "Real-time Rendering", currently on its 4th edition. https://www.realtimerendering.com/

For rendering at rates measured in seconds per frame, consider the "Physically Based Rendering Textbook", currently on its 3rd edition. https://www.pbrt.org/


Implemented in ~JavaScript~ TypeScript FTFY ...

Also nice to see a Douglas Crockford book (who is not a fan of TS BTW) ...

Anyways I star'd this repo ... very impressive +1


Sometimes I think TS was made for Java/C# crowd coming to JS. TS is clean, have to agree. But not much of a fan.

This project is awesome though.


It's amazing it resizes to the terminal perfectly, if you zoom out the terminal the resolution gets much clearer!


what's the point of rendering into a terminal? why not use a raster framebuffer?


As far as I can see the terminal rendering is one of the main points that's showcased with this project. Sure you could do this with a raster framebuffer, but that's been done loads of times. The fact that it looks this good in a terminal is marvelous imho.


This is a bad language choice for the problem.


I cannot deny how much I like asciiart renderings.


Someone please post something cool made with this


Already done.

(See: Recursion)


Recursion?


I'd be curious to see some benchmarks




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: