Skip to content

JSOBJ: A lesson in how software 3D renderers are made

Evan
Published date:

Learning shader programming as a game developer can be hard. There are a lot of new terms and concepts, many of which any normal game designer need not delve into, let alone most programmers, but, despite its complexity, where shader programming remains one of the few practices in which math and visual art coalesce, its fundamentals aren’t that hard to understand. It is this property of art resulting from math that we have modern 3D renderers and game engines a-like, but to those who want to learn how to create 3D renderers themselves, or create shaders as a professional career, the process of learning shader programming can seem daunting. So where is the best “entry point” to get started with what seems to be such an abstract practice?

Most people will face the high learning curve of shader programming head on, learning shaders within the specific context they intend to use them, like Unity or Unreal Engine. But to get a real foundational understanding, the best way to understand the render pipeline, and shader programming as a result, is to build it yourself.

Table of contents

Open Table of contents

Getting Started

Because this is more of a learning exercise, and not a tutorial on how to create a full 3D engine, and because I want to contextualize this against OpenGl—a great point to actually dive deeper into writing your own engine—we’ll start by creating our own ‘renderer’ using Javascript and its canvas functions. The ideas in this post, however, will still be applicable to any other language, given you have some means to write shapes to a canvas, like with Python’s Pygame or Tkinter.

The goal of this project is to create a very basic 3D renderer that can teach the principles of 3D rendering, and to make it somewhat useful, we’ll give the software the ability to take in a OBJ file to read and display the wire frame, vertices, and faces. Which, as it turns out, isn’t that difficult to do.

To start, lets use a canvas in Javascript and CTX to create a 2D square using points, make it a cube, and then render those points to the screen. You can download these basic Index.html and script.js files to get started. Just download them into a folder and open that folder in Visual Studio code, preferably with the Live Preview extension installed, so that you can see the preview for your code in-editor.

From 2D to 3D

If you think about what 3D actually is, its really just 2D with an extra dimension, so not only will the space in our renderer use both the X and Y axis, but it will also use the Z axis. Now, this much is obvious, but when we render our view to our screen, we don’t have any way to display that third axis, depth, but we’ll worry about that later.

Viewing the test website with the JS script embedded we should see 4 points being rendered, like this:

Description of image in case it doesn't load
This is what the output of the start files looks like. 4 points, creating a square.

Now, this is entirely 2D, using only the x and y axis, but if we add a z axis to our points struct, we can allow our ‘renderer’ to take in the depth of an object. To do this we will first add the necessary data to our points list. Lets turn our “square” into a proper cube. You can copy the data below, or put the points exactly where you want them to be. Just know that right now, the edges of the screen are at +/- 1 on the y and x axis, so any point farther than that will get cut off.

const points = [ 
    {x: 0.25, y: 0.25, z: 0},
    {x: -.25, y: 0.25, z: 0},
    {x: -.25, y: -.25, z: 0},
    {x: 0.25, y: -.25, z: 0} 
]tutorial.js
Previous
Creating a water shader in blender