3D software rendering in Rust

This is a project I started working on literally yesterday. This aims to be a fully fledged 3D renderer powered entirely by the CPU. This basically means you can run this on a hardware that doesn't have GPU, or on a PC that lacks drivers. Currently it can only draw 2D triangles, but eventually this would take shape as a 3D renderer, complete with a shader system.
No description
No description
147 Replies
Enceladus
Enceladus2mo ago
what's the second image for?
polyzium
polyzium2mo ago
That was a polygon gap test that got borked My triangles weren't rendering there because the scanlines' begin and end X coords were swapped around that is fixed now
Enceladus
Enceladus2mo ago
polygon?? why not beginning with a cube? I mean maybe you already have the cube...
polyzium
polyzium2mo ago
Polygons are made out of triangles that's how GPUs render them So for now I am focusing on 2D triangle rasterization first, then I'll do 3D projection, texture mapping and everything
Enceladus
Enceladus2mo ago
yes everything 3d is triangles alright
polyzium
polyzium2mo ago
Finally, affine mapping
polyzium
polyzium2mo ago
I'm gonna do 3D stuff later
Dumb Bird
Dumb Bird2mo ago
like I have no idea how these graphics APIs even work
I've done quite a lot of work with OpenGL and Vulkan. But now for anything graphic and game based I use Raylib Graphic APIs are a doozy though, what are you currently using for rendering? I can't imagine this is very cross platform Looks very nice for something done within a day I'm impressed!
Nick_Z
Nick_Z2mo ago
Very Nice
Enceladus
Enceladus2mo ago
Is it an image or a lot of triangles?
polyzium
polyzium2mo ago
SDL2 The triangles are software rendered entirely Well I was following a tutorial though so it's not really that impressive The only thing I personally did is a bit of refactoring 2 triangles making up a textured rectangle, you can see the effects of affine mapping here
Enceladus
Enceladus5w ago
ok that's cool! @polyzium does your engine have a name already?
polyzium
polyzium5w ago
Yeah Necromancy Engine
Enceladus
Enceladus5w ago
lol I didn't think about that, this is kind of fancy Do you have an explication?
polyzium
polyzium5w ago
Explanation you mean?
Enceladus
Enceladus5w ago
I mean is there a reason? Why this name
polyzium
polyzium5w ago
Like I said this all started from a Minecraft mod
Enceladus
Enceladus5w ago
sorry that wasn't very clear ^^' yep
polyzium
polyzium5w ago
and his mod's name has "Necro" in it and necromancy means communicating with the dead Though the project kinda carries this name because this field of programming (software rendering and overall engine from scratch) is dead Like it's some sort of black magic thing rasterizing triangles manually
Enceladus
Enceladus5w ago
yeah I see, that's a nice name then ^^
polyzium
polyzium5w ago
I am doing perspective projection now, should be finished soon
Enceladus
Enceladus5w ago
For mine (in a near future), I think i'll call it "Dust Engine", firstly inspired from my pseudo and my name, and secondly as you say, all of that is quite dusty and idk I find that a bit fun oh really? You don't seem to struggle that much, do you?
polyzium
polyzium5w ago
I am following a C++ tutorial on software 3D rendering
Enceladus
Enceladus5w ago
making a 3d engin from "scratch" is not something said easy
polyzium
polyzium5w ago
but I am translating the code into Rust and doing some code readability refactoring while I am at it 3D graphics is honestly one big pile of maths
Enceladus
Enceladus5w ago
what is it? It could help me too
polyzium
polyzium5w ago
It consists of 4 videos do you want me to send them all?
Enceladus
Enceladus5w ago
Idk, if it's yt videos you can send the link I mean as you want
polyzium
polyzium5w ago
Bisqwit
YouTube
Texture Mapping & Polygon Rasterizing Tutorial (1/2) [C++20]
Textured polygons are the foundation of nearly all 3D games in existence. Used before even 3D-capable GPUs were a thing, they were rendered using nothing but software. How was that achieved? Let’s explore an easy and intuitive method. We create an extensible 3D polygon rasterizer using nothing but standard C++20 (and libSDL for 2D graphics). Be...
Enceladus
Enceladus5w ago
alright, i'll find the rest thank you!
polyzium
polyzium5w ago
they should pop up in suggested on the right
Enceladus
Enceladus5w ago
also, for your MC project, what do you want to do? Like, making entire minecraft in today's version is without a doubt a huge and tough work
polyzium
polyzium5w ago
I am aware, but this is not up to me This is up to a friend of mine who wants to make such a game But most likely it is NOT going to be minecraft from scratch As for the MC mod itself, his mod is a part of a WIP server network that I am a part of They could use some help, so if you are interested, DM me and I'll explain everything
Enceladus
Enceladus5w ago
ok! so do you have a project for your Engine?
polyzium
polyzium5w ago
Define "project"? Like a file structure or theoretical project?
Enceladus
Enceladus5w ago
Something you want to do using your engine, so basically a game or an application using it
polyzium
polyzium5w ago
My plan is to make an entire scene like a game level thing For now I am gonna test my perspective projection with a simple cuboid
polyzium
polyzium5w ago
Bisqwit
YouTube
Texture Mapping & Polygon Rasterizing Tutorial (2/2) [C++20]
Textured polygons are the foundation of nearly all 3D games in existence. Used before even 3D-capable GPUs were a thing, they were rendered using nothing but software. How was that achieved? Let’s explore an easy and intuitive method. We create an extensible 3D polygon rasterizer using nothing but standard C++20 (and libSDL for 2D graphics). Be...
Enceladus
Enceladus5w ago
nice Btw you have to see something so cool:
Enceladus
Enceladus5w ago
jdh
YouTube
Why I use Wave Function Collapse to create levels for my game
this was so much work i'm about to (wave function) collapse sorry I used the terms "element", "cell", and "pixel" interchangeably :c they all mean the same thing! SEE THE CODE (utilities, etc. coming soon!) https://gist.github.com/jdah/ad997b858513a278426f8d91317115b9 Oskar Stålberg's visualization tool: https://oskarstalberg.com/game/wave/wa...
Enceladus
Enceladus5w ago
that's really cool imo and I'll add that to my engine
polyzium
polyzium5w ago
Yikes... I've heard that WFC is slow as a snail
Enceladus
Enceladus5w ago
I mean that's the plan, tehcnically I can't say if I will succeed... idk, I guess it depends, a game often cited is Bad North; I have it and It runs very well on my portable potato! (very nice game btw)
polyzium
polyzium5w ago
Hm not sure if RTS is my thing Oh look, Steam Deck Verified could pick it up
Enceladus
Enceladus5w ago
you have a steam deck?
polyzium
polyzium5w ago
Yeah, OLED 1TB with that anti glare glass
Enceladus
Enceladus5w ago
-5000 $ XD no apparently it's 570 € I thought it would be much more
polyzium
polyzium5w ago
It's less than 1k USD/EUR Well you know what costs more? ROG Ally, Legion Go, etc These things have better hardware, but worse software and a Windows license lmfao Steam Deck is the ideal balance between hardware and software
Enceladus
Enceladus5w ago
yeah but why not playing on pc?
polyzium
polyzium5w ago
I do mostly coding on PC now and only thing I play on PC is Minecraft
Enceladus
Enceladus5w ago
or console
polyzium
polyzium5w ago
the Steam Deck allows me to kill some time and play on the go/vacation, especially after working hours I can just fall on my bed and play til midnight It completely changed the way I play games
Enceladus
Enceladus5w ago
oh ok that's fair
polyzium
polyzium5w ago
Because yk I am not feeling like playing on PC after working hours, especially considering that I sit at a PC at my work all day (I am employed as a webdev) Anyway back to perspective projection
Enceladus
Enceladus5w ago
xd yeah
Dumb Bird
Dumb Bird5w ago
Not at all! Huge communities of people still do this.
polyzium
polyzium5w ago
Let's be honest nobody ships a software renderer and an inhouse engine these days anymore
Dumb Bird
Dumb Bird5w ago
Sure maybe not in the modern games you see on steam but there is still huge communities of people that still do this kind of stuff. Me included
polyzium
polyzium5w ago
Then I wonder what for
Dumb Bird
Dumb Bird5w ago
Fun
polyzium
polyzium5w ago
...I meant in practice Holy fuck quaternions are hard to deal with
Enceladus
Enceladus5w ago
what are you even doing with that 💀 I didn't know there is something after complex numbers honestly
polyzium
polyzium5w ago
The tutorial for some reason uses quaternions for rotations and then it uses these quaternions to calculate the projection matrix This shit is hard to understand ngl
Enceladus
Enceladus5w ago
no wayyyyyy I don't even know what it does, i'll search that
polyzium
polyzium5w ago
I think it's mostly related to projection matrix anyway
Enceladus
Enceladus5w ago
don't tell me they used quaternions in the 90'
polyzium
polyzium5w ago
Quaternions is just a much harder way to represent rotation\ and it's 4 dimensional for some reason You got Euler angles and quaternions
Enceladus
Enceladus5w ago
that's a f*cking joke 😂 I don't even know how it's possible sounds fun to do lmfao
polyzium
polyzium5w ago
I am 100% sure quaternions relate to the projection matrix
polyzium
polyzium5w ago
Um... well...
polyzium
polyzium5w ago
Black screen at the end = crash
polyzium
polyzium5w ago
Better now, but still crashy
polyzium
polyzium5w ago
Trying to implement Z buffer stuff
polyzium
polyzium5w ago
Hm I think I got that fixed
polyzium
polyzium5w ago
I figured I'd go back to square one I am having so much trouble doing perspective correction
polyzium
polyzium5w ago
Finally, perspective correct textures
polyzium
polyzium5w ago
Dithering
No description
No description
polyzium
polyzium5w ago
OK now the only thing left is clipping But clipping is for some reason hard asf It isn't as trivial as it seems which is very very sad
Enceladus
Enceladus5w ago
@polyziumThe rasterization makes everything pixelized right? is it possible to avoid that? Like if we add some antialiasing, will it make it look smoother? also I recommend this website which explain all the steps to make software rendering. I find it very well explained: https://medium.com/@aminere/software-rendering-from-scratch-f60127a7cd58 yeah btw could you tell me what's you're file structure? I'm a bit lost on how I should do that, i'm not used to it and it looks different than a standard project
polyzium
polyzium5w ago
Yeah if you're doing nearest neighbour texturing Here I am doing dithering though to hide the large pixels I could do bilinear filtering, but A it does not fit the retro aesthetic I am going for and B all software renderers I've seen they all use either nearest neighbour (Doom, Quake) or dithering (Unreal, Deus Ex) Tbh not even I know how to structure this kind of project properly In the coming days I'll be refactoring this proper But for now I put all the stuff in their respective files
Enceladus
Enceladus5w ago
Alright thanks!
Enceladus
Enceladus5w ago
GitHub
Tutorial: Basic Game Engine
Simple and Fast Multimedia Library. Contribute to SFML/SFML development by creating an account on GitHub.
polyzium
polyzium5w ago
@earth's goose This is what I have now if you are curious
No description
Enceladus
Enceladus5w ago
what do you have on your main? also I think it could be good to make subdirectories like:
engine
graphics
sound
...
engine
graphics
sound
...
polyzium
polyzium5w ago
On main I have the actual graphics plotting and SDL2 initialization + camera control stuff But it is wise to put everything under one Rasterizer class or something like that which is what I am going to do later after I finish dealing with clipping this is annoying ngl
Enceladus
Enceladus5w ago
Yeah so here it’s more like a standard project, like a game or something you’d do rather than an actual engine
polyzium
polyzium5w ago
I know This project is currently at a proof of concept stage I need to do refactoring so badly But I am stuck with clipping
Enceladus
Enceladus4w ago
Alright good luck then There is a vscode extension called Draw.io, which allows you to make sketchs and mind maps. I started to make a map representing the engine, so if you want we can make it together to help each other, or at least me...
polyzium
polyzium4w ago
Lmao you're just in time
Enceladus
Enceladus4w ago
here's what I already did
polyzium
polyzium4w ago
I just came back from work
Enceladus
Enceladus4w ago
lol xd perfect timing
polyzium
polyzium4w ago
and on my free work time I finally implemented clipping
Enceladus
Enceladus4w ago
oh nice!
polyzium
polyzium4w ago
I probably need to optimize it further Also I need to figure out wtf do I need to do to make it "stick" to the camera because my rotation is just quaternions, this is not good
Enceladus
Enceladus4w ago
I made the basic directories I think there should be, and for the graphics I put some ideas and system I have to implement. For now I don't know what I should put in same file or just just if I should make everything very modulable and separated
polyzium
polyzium4w ago
Here's the clipping video
Enceladus
Enceladus4w ago
why does it disapear? there's a wall simulated?
polyzium
polyzium4w ago
Because I cba to figure out how to stick it to the camera I need a look vector and I have no idea how to make one from a quaternion
Enceladus
Enceladus4w ago
oh that' why, ok
polyzium
polyzium4w ago
But basically once it sticks to the camera
polyzium
polyzium4w ago
this won't happen:
Enceladus
Enceladus4w ago
I can't help you with that, I just learn it existed because of you xd* oh wow looks like you entered the matrix
polyzium
polyzium4w ago
The transformation matrix yeah lmao
Enceladus
Enceladus4w ago
Because I want to have a clear idea of the global structure and start making the graphics once I have a functional engine
polyzium
polyzium4w ago
Clipping, the final frontier
Enceladus
Enceladus4w ago
Oh Nice! It’s seems totally working now
polyzium
polyzium4w ago
As a bonus, here is the renderer in 720p
Enceladus
Enceladus4w ago
Really nice! Isn’t it a bit laggy tho?
polyzium
polyzium4w ago
Though in 720p it is quite slow
Enceladus
Enceladus4w ago
Yeah
polyzium
polyzium4w ago
with even 4 triangles this thing reaches like 15fps... maybe less I must investigate that ngl
Enceladus
Enceladus4w ago
Is that a normal behaviour?
polyzium
polyzium4w ago
Well for a POC yes this engine just seems to be unoptimized Lemme try affine mapping and see if I get perf boost from that
Enceladus
Enceladus4w ago
Yeah probably
polyzium
polyzium4w ago
Just tried, it's not any better need a profiler Or actually maybe parallelize the entire thing?
polyzium
polyzium4w ago
I just realized Rust compiles with no optimizations in dev mode. Here's the release build with -O3
Enceladus
Enceladus4w ago
Much better!
polyzium
polyzium4w ago
If you don't put any timing stuff in, it runs plenty fast I didn't implement any type of ΔT stuff in this so if I remove the 60fps limit the camera moves super fast
Enceladus
Enceladus4w ago
that's what I expected from 2 panels, that shouldn't be that greedy yeah I don't think it's useful for these things
polyzium
polyzium4w ago
Also I was curious how would it perform at 1080p TLDR it doesn't, crashes due to stack overflow It's using 136 megabytes of memory though lmao No sorry 98 megs actually 136 megs is VIRT memory according to my htop output Release build takes about 40%-45% CPU I wonder how fast could this be if I parallelize this
Enceladus
Enceladus4w ago
wdym about parallelization?
polyzium
polyzium4w ago
Make this run on all of your CPU's threads
Enceladus
Enceladus4w ago
ow ok
polyzium
polyzium4w ago
Currently this thing is singlethreaded
Enceladus
Enceladus4w ago
this could be very efficient then Do you have texturing yet?
polyzium
polyzium4w ago
As you can see, no Dammit of course I do, since the affine mapping days Why are you even asking? You can clearly see dithering of the texture in my later videos
Enceladus
Enceladus4w ago
No, well tell me if I'm wrong but you only have colored triangles there. So I meant: can you apply a picture on whatever surface you have?
polyzium
polyzium4w ago
You can But here I am generating a texture What you are seeing is a custom version of the Munching Squares texture
polyzium
polyzium4w ago
The original looks like this
No description
Enceladus
Enceladus4w ago
Yes ok, I see so are you planning on adding this?
polyzium
polyzium4w ago
Planning adding on what? Texturing? It is already done
Enceladus
Enceladus4w ago
oh, ok that being said, once you have I guess you can just upload a picture and set it to the right position and the rest is done?
polyzium
polyzium4w ago
Well yea but I have to implement the code for that Currently my texture is 256x256 I have no code that loads from a PNG or something, the texture is generated straight into the bitmap
Enceladus
Enceladus4w ago
alright!
polyzium
polyzium4w ago
Here's a very crude conversion to Shadertoy compatible GLSL
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 iResolution = vec2(800.0, 450.0); // Set this to your desired resolution
vec2 uv = fragCoord / iResolution;
int x = int(fragCoord.x);
int y = int(fragCoord.y);

int TEXTURE_W = int(iResolution.x);
int TEXTURE_H = int(iResolution.y);

int l = 0x1FF >> min(min(min(min(x, y), TEXTURE_W - 1 - x), TEXTURE_H - 1 - y), 31);

float fx = float(x);
float fy = float(y);
float fw = float(TEXTURE_W);
float fh = float(TEXTURE_H);

float hypot = pow(length(vec2(fx / (fw / 2.0) - 1.0, fy / (fh / 2.0) - 1.0) * 4.0), 2.0);
int d = int(min(50.0, max(0.0, 255.0 - 50.0 * hypot)));

int r = (~x & ~y) & 255;
int g = (x & ~y) & 255;
int b = (~x & y) & 255;

float red = float(min(max(r - d, l), 255)) / 255.0;
float green = float(min(max(g - d, l), 255)) / 255.0;
float blue = float(min(max(b - d, l), 255)) / 255.0;

fragColor = vec4(red, green, blue, 1.0);
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 iResolution = vec2(800.0, 450.0); // Set this to your desired resolution
vec2 uv = fragCoord / iResolution;
int x = int(fragCoord.x);
int y = int(fragCoord.y);

int TEXTURE_W = int(iResolution.x);
int TEXTURE_H = int(iResolution.y);

int l = 0x1FF >> min(min(min(min(x, y), TEXTURE_W - 1 - x), TEXTURE_H - 1 - y), 31);

float fx = float(x);
float fy = float(y);
float fw = float(TEXTURE_W);
float fh = float(TEXTURE_H);

float hypot = pow(length(vec2(fx / (fw / 2.0) - 1.0, fy / (fh / 2.0) - 1.0) * 4.0), 2.0);
int d = int(min(50.0, max(0.0, 255.0 - 50.0 * hypot)));

int r = (~x & ~y) & 255;
int g = (x & ~y) & 255;
int b = (~x & y) & 255;

float red = float(min(max(r - d, l), 255)) / 255.0;
float green = float(min(max(g - d, l), 255)) / 255.0;
float blue = float(min(max(b - d, l), 255)) / 255.0;

fragColor = vec4(red, green, blue, 1.0);
}
this is the code I use to generate the munching squares texture
Enceladus
Enceladus4w ago
ok thank you! I wonder how to deal with hypercomplex numbers in programming, i'll see that after
polyzium
polyzium4w ago
I did some refactoring yesterday I realized that my projection method should take a projection matrix instead of camera position but for some reason it just screws up my rendering entirely Well, I think I am gonna stop right here That was a fun project while it lasted, but unfortunately I am not able to parallelize the renderer I am tempted to rewrite everything to OpenGL now
Enceladus
Enceladus4w ago
would it actually change something or make things work?
polyzium
polyzium4w ago
It would use the GPU and thus make rendering faster Because I cba to parallelize the software renderer properly I only did this as a stepping stone to 3D graphics programming
Enceladus
Enceladus4w ago
Oh, that's sad... At least it's still not a waste every unfinished project is a step up so maybe I should do try to make it with OpenGL from beginning
polyzium
polyzium4w ago
If you don't know how quaternions and matrices work it would be hard for you But of course this is only part of the whole ordeal Anyway do you guys need the source code? in Rust
Enceladus
Enceladus4w ago
I know the basics of matrices, but I think I can make it with some digging I wouldn't say no! Also if you want, you could help me on a game engine system thing i'm wondering #💻┃cpp I think you could understand well chat I mean here since it's the same project
Enceladus
Enceladus4w ago
thx wop nevermind: as SFML uses OpenGL, there is GPU management
polyzium
polyzium4w ago
Btw I left some junk code in there because I released the thing as-is didn't bother getting prepared But it has a very basic OBJ parser
Enceladus
Enceladus4w ago
Alright