j-2k / SoftwareRendererTGA

Writing a Offline Software Renderer (Rasterizer) that outputs a single TGA image with a rendered model with some shaders, using nothing but C++ and Ssloy's TinyRender Resource.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

About this Project

This project contains 2 things, a ppm image generator which is the minor project, & the major project which is the software rasterizer. Go down below to learn more about each project. These projects were done for learning purposes, credits & learning resources might be in here or in my graphics roadmap repository.

Software Rasterizer was learned through SSloy's TinyRenderer Wiki on github direct link > https://github.com/ssloy/tinyrenderer/wiki

Note: Even though I'm going through Sloy's Tiny renderer I sometimes dont understand stuff & when thats the case, I always look on youtube about the topic im struggling to understand, one series that keeps coming is Brendan Galeas Vulkan Game Engine Series. I have already suggested this in learning resources of my graphics programming roadmap repo, but I just really want to say it's insanely informative & probably the best series when it comes to quality and being to-date.
This is also really helpful > Triangle Rasterization Algorithims

An example, do you struggle understanding barycentric coordinates & prespective projection (specificially the math)? His videos cover these topics really well (especially his prespective projection video).

Software Rasterizer Project

Showcase Images

Note: All important project information is after the images section!

Stage 0.5 Render TGA Image & Stage 1.0 Bresenham's line Algorithm

Stage 2 Wireframe Rendering

Stage 3 Triangle Rasterization

First 3 Using Line Sweep, Last using Barycentric Coordinates & Bounding Box Check

Stage 4 Model Triangle Rasterization & Lighting

Stage 5 Depth Buffer Fix

Stage 6 Depth Buffer & Prespective Projection

Stage 7 Shader Pipeline / Frag & Vert Manipulation

Stage 8 Phong Lighting / Normal & Specular Map Integration.

Albedo > Normal > Specular

Stage 9 Shadow Mapping

Shadow Mapping (double pass) & Z Fighting > Fixed Shadow
Didn't fix the z-fighting below

Stage 10 Ambient Occulusion

If no images are present assume I stopped here & most likely will just jump into a gfx specialization because AO is mainly a pfx.

Rasterizer Project Personal Notes

All topics covered are below with bold stages being extremely important to understand

(this is mainly done for myself to remember the important stages for rendering):

  1. Hello World Image - Generate a TGA Image
  2. UV Image - Color the TGA Image
  3. Bresenham's Line Algorithim - Line Generation Stage
  4. Wireframe Rendering - Connect the lines with the verticies on a obj file
  5. Old Line Sweep Algorithim - Triangle Rasterization Stage (Slow)
  6. Barycentric Coordinates - Triangle Rasterization Stage
  7. Z Buffer Algorithim/Scan Line Rendering, Painters Algorithim - Depth Buffer Stage
  8. Orthographic to Prespective Projection - Static Prespective Camera Stage
  9. Homogenous Coordinates & MVP (MODEL, VIEW, PROJECTION) - Moving Prespective Camera Stage
  10. OpenGL Shader Pipeline

CPP2PPM Project

Testing how to get a ppm image from cpp, work flow is awful on windows with cmake but whatever.
I used VS22, and chose a cmake as a base project. Will try to do proper build instructions later, I will try building to both mac & windows.

I'm not sure what workflow I should use but cmake makes me want to use VSC and not VS, but ill just write some stuff for how to make this garbage work, since this took me an hour to figure out.
to get a image from cpp code in ppm format,

this build instructions writing from me is garbage, im going to later copy what other good people write for build instructions, im just writing this for myself

Prerequisites

  • CMake (version 3.12 or higher)
  • A C++ compiler that supports C++20

Building

1. clone the project

git clone https://github.com/j-2k/ImagePPM.git

2. go to the "out" directory

#ex > assuming ur in imagePPM master folder, 
cd cpp2ppm_CMake/out/

3. make an empty build folder in out

#build is already taken & not empty, so build ur
#own proj files with in a different build folder/name
mkdir build2
cd build2

4. generate the build files

#cmake .. goes into the parent directory to find CMAKELISTS.text file
#to generate build files
cmake ..

5. build the project

#do make or cmake --build .
make
#or
cmake --build .

6. Run the project & output stream to ppm

#find the path to the exe (file path/to/directory/with/exe)/jumagfx_cmake.exe > image.ppm
#incase you didnt put the exe in some other place this should just work
./jumagfx_cmake.exe > image.ppm
# the "." will search the current dir & run the exe file remove .exe if on terminal
./jumagfx_cmake > image.ppm

Debug Mode Guide

Getting debug to work on vsc was a slight pain, so im going to document it real quick so I dont ever have to remember how to do it again on vsc.

I will talk about the Cmake Debugger because idk how to use other ones they personally gave me too many issues.
Firstly, The Cmake Debugger WILL NOT USE THE LAUNCH.json CONFIGURATIONS! It will use settings.json NOT the .vs settings.json but rather the cmakes settings.json file. You can find this file through the cmake extension tools for vscode. See below:

First navigate to the CMake Tools Extension for VScode then > Set the important garbage up such as:

  1. Build Directory & Args commands if you have any
  2. Cmake Path (command to find cmake path = "whereis cmake")
  3. Go to > Cmake Options Advanced then under it turn on the status bar visibility to visibile!
    Screenshot 2024-01-10 at 9 42 19 AM After enabling the status bar to visible you should see the below options, but before continuing, first open the settings.json shown above. Screenshot 2024-01-10 at 9 28 17 AM In the settings.json paste the below to use lldb debug config for mac, other mi modes for other operating systems.
    "cmake.debugConfig": {
        "MIMode": "lldb"
    },

Now set the cmake status bar to the correct options like debug & set the build target and etc then run by pressing the bug option on the status bar & it should work!

Screenshot 2024-01-10 at 9 52 53 AM

Its a little weird in the sense sometimes it just skips my breakpoints?? maybe its because i forgot to build but idk it acts weird sometimes.
But make sure the status bar says debug mode, then build the files set the exe and target then press the bug icon & should run debug mode.
Thats all!

Old personal build notes building is the mostly? the same in all os but im just writing some stuff I learned/did along the way maybe just the compiler setting is different between os (msvc) & the build systems(make ninja nmake visualstudio etc)? but idk much about that.

Windows

Build the project with redirecting the standard output stream to a image file (ppm in this case & using CMake, ps I have no idea how to use CMake, so I'm guna learn that before I continue)

1. cmake --build build

build the new changes

2. your/directory/of/executable.exe > image.ppm

convert output stream to image file ppm, I used cmd, powershell, cmder all cool

3. go to file of executable, image.ppm should be there, open ppm on imagemagic or photoeditor photoshop, gimp etc etc. no native support to open ppm images on windows, however MAC actually lets you open & see PPM images.

MacOS

Building proj on mac

1. enter a empty build folder and run "cmake (PATH TO CMAKELISTS.txt)/." to generate build files

example > in out/build/mac folder is empty, when inside that dir in terminal do "cmake ../../../."

2. do "make" or "cmake --build ." to build the project

exmaple > inside mac should be build folders do make or cmake --build . to build project & gen a exe file

3. locate jumagfx_cmake.exe and run the command "path/to/jumagfx_cmake.exe > image.ppm" to generate a ppm image in the current directory.

example > "cpp2ppm_CMake/out/build/mac/JumaGFX_CMake/JumaGFX_CMake > image.ppm"

C++ notes about file structures with cpp and h files

I didnt touch cpp and needed a refresher on translation units & headers so I wrote this here for myself

basic c++ notes about translation units (.cpp) & header files (.h/.hpp),
use #pragma once to include a header file only ONCE in a translation unit (DONT FORGET TO USE PRAGMA IN H FILES! IMPORTANT!).
an example of duplicate definitions without pragma:
assume car.h, engine.h, & main.cpp if main.cpp contains both h files & calls them, with car having to print "car" and engine printing "engine". then main will give "car" & "engine" printed but if the car h file includes engine h without pragma you will get 2 engine prints and 1 car print if that makes sense. So use pragma once in both h files just for sake of guarding against this issue.
use header files only to hold declarations about certain information, example:
debug.h > should contain function declarations only related to debugging/console,

//inside debug.h
#pragma once
void Debug(const char* msg);

use cpp files to implement the declarations in the header files like so:

//the only line inside debug.cpp
#include "debug.h"
void Debug(const char* msg) {return msg}  

in your main to use this function do #include "debug.h" (quotes for files relative to the current file and angled brackets only for compiler include paths)

//somewhere in main
#include "debug.h"
#include <iostream>
int main()
{
  Debug("Hello")
}

first ppm image

converted image4ppm to png:
uvimage

About

Writing a Offline Software Renderer (Rasterizer) that outputs a single TGA image with a rendered model with some shaders, using nothing but C++ and Ssloy's TinyRender Resource.


Languages

Language:C++ 37.4%Language:Makefile 25.0%Language:CMake 18.0%Language:C 17.7%Language:Tcl 1.8%Language:TypeScript 0.0%