# Rishov Sarkar’s Software 3D Renderer

View this project on the web!  
https://rrs-software-3d-renderer.netlify.app/

This is the first project for the Professor Aaron Lanterman’s Summer 2020
offering of Georgia Tech’s ECE 4795: GPU Programming for Video Games.

My implementation of this project is written in [TypeScript][1] using the [React
framework][2] and [Redux][3] for state management.

[1]: https://www.typescriptlang.org/
[2]: https://reactjs.org/
[3]: https://redux.js.org/

## Usage

It’s simple!

1. To load a model, drag a model file onto the webpage, or just click the link
   on the webpage to select a model file. You can also choose a preset below.
2. Drag the model around or play with the controls on the left.
3. ???
4. Profit!

### Presets

These presets load the specified model with hand-tuned parameters that make them
easy to view. An image of the rendered output is shown below each as a preview.

- [Shark  
   ![3-D rendered shark][image 1]][4]
- [Mew  
   ![3-D rendered Mew][image 2]][5]
- [Mewtwo  
   ![3-D rendered Mewtwo][image 3]][6]
- [Chief  
   ![3-D rendered Chief][image 4]][7]
- [Eiffel  
   ![3-D rendered Eiffel Tower][image 5]][8]

[4]: https://rrs-software-3d-renderer.netlify.app/?url=%2Fmodels%2Fshark_ag.raw&cpx=2&cpy=0&cpz=12&ctx=2&cty=0&ctz=0&oox=0&ooy=270&ooz=0&oc=c0c0c0&lpx=2&lpy=0&lpz=12
[5]: https://rrs-software-3d-renderer.netlify.app/?url=%2Fmodels%2FMew_lp.raw&cpx=0&cpy=7.5&cpz=5&ctx=0&cty=7.5&ctz=0&oox=90&ooy=0&ooz=0&oc=f5c7d4&lpx=0&lpy=7.5&lpz=5
[6]: https://rrs-software-3d-renderer.netlify.app/?url=%2Fmodels%2FMewtwo_lp.raw&cpx=0&cpy=9&cpz=18&ctx=0&cty=9&ctz=0&oox=90&ooy=0&ooz=0&oc=ded8e2&lpx=0&lpy=9&lpz=18
[7]: https://rrs-software-3d-renderer.netlify.app/?url=%2Fmodels%2Fchief_ag.raw&cpx=0&cpy=38&cpz=70&ctx=0&cty=38&ctz=0&far=150&oox=270&ooy=0&ooz=0&oc=68763b&lpx=0&lpy=38&lpz=70
[8]: https://rrs-software-3d-renderer.netlify.app/?url=%2Fmodels%2Feiffel_ag.raw&cpx=0&cpy=50&cpz=105&ctx=0&cty=50&ctz=0&far=200&oc=cbb697&lpx=0&lpy=50&lpz=105

[image 1]: https://rrs-software-3d-renderer.netlify.app/renders/shark.png
[image 2]: https://rrs-software-3d-renderer.netlify.app/renders/mew.png
[image 3]: https://rrs-software-3d-renderer.netlify.app/renders/mewtwo.png
[image 4]: https://rrs-software-3d-renderer.netlify.app/renders/chief.png
[image 5]: https://rrs-software-3d-renderer.netlify.app/renders/eiffel.png

## Technical Details

### Code Highlights

For this project, I decided to write a custom `Matrix` class inspired by
Python’s [NumPy][9] library. In particular, my matrix class supports
[broadcasting][10] and [strided arrays][11], which I use throughout the code.
The code for this matrix class can be found in `src/util/matrix.ts`. (Sidenote:
when reading matrix code, please note that I use `multiply()` to refer to matrix
multiplication and `scale()` to refer to elementwise multiplication.)

My `Transform3D` class is a utility class with static methods to create 3-D
transformation matrices, such as translations, rotations, and look-at matrices.
These transforms all assume a **left-handed coordinate system**, where the
positive z-axis points into the screen. You can find the code in
`src/util/transform3d.ts`.

`src/features/loader/fileSlice.ts` takes care of loading model files and parsing
them into 2-D arrays, which become matrices in later parts of the code.

`src/features/canvas/rendererSlice.ts` contains the code that defines the state
of all parts of the 3-D renderer besides the model itself. This is where you’ll
find, for example, the code that updates the camera position when you drag the
mouse.

Last but not least, the `Canvas` React component, defined in
`src/features/canvas/Canvas.tsx`, is where the magic happens. This file takes
the vertices directly from the file that was loaded in and applies all the
necessary transforms before painting them to a 2-D [&lt;canvas&gt;][12]. This
includes the code to compute the world transform, view transform, projection
transform, and viewport transform, as well as the code to calculate lighting
information for each triangle and the code to clip out-of-bounds triangles.

[9]: https://numpy.org/
[10]: https://numpy.org/doc/1.18/user/theory.broadcasting.html
[11]: https://numpy.org/doc/1.18/reference/internals.html#internal-organization-of-numpy-arrays
[12]: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API

### Running Locally

To build and run this project locally, you’ll need to have Node.js installed.
You can download it [here][13].

Node.js comes with the package manager [npm][14], and this is sufficient for
building and running the project. However, I personally use and recommend the
[yarn][15] package manager. In my experience, yarn is faster in running
commands, faster in installing packages, and has nicer UX.

Now, once you’re set up:

1. From the project directory, run `yarn install` or `npm install` to install
   dependencies.
2. Run `yarn start` or `npm start` to start a development server on
   http://localhost:3000/.
3. You can now make changes to the code, if you’d like. Changes will show up in
   real time on the development server.
4. If you’d like to export to a static site for publishing on a platform like
   [GitHub Pages][16] or [Netlify][17], run `yarn build` or `npm run build` to
   generate the static site in the project’s `build/` directory.

[13]: https://nodejs.org/en/download/
[14]: https://www.npmjs.com/get-npm
[15]: https://classic.yarnpkg.com/en/
[16]: https://pages.github.com/
[17]: https://www.netlify.com/
