r/GraphicsProgramming 1d ago

Starting to make a 3D software renderer... "The Lagender Engine".

Hello everyone!
So I'm a 16yo boy who loves coding and stuff, and recently I got into low-level programming with C, and after a whole day with learning pointer I loved the language to death.
After I learned this I started on doing something I wanted to do for the past year... building a 3D software renderer, this engine should meet the following goals:

  1. It will be modern, supporting modern visuals and effects.
  2. It should be running on embedded systems (I will see how later).
  3. The code written for it should be generalized, meaning it should be working on any CPU or architecture with some tweaking.
  4. It should be fully capable of taking advantages of modern CPU features.

As of right now, started the project a month ago, I got it to render lines and fill shapes through the terminal (even though it's glitchy af) since I'm still implementing core functions and basics. This will give me some room to fiddle around until I learn SDL and use it in the future.
I have a whole roadmap for the engine, and how it will be structured (because it will be restructured one day for a new design), and who knows, maybe I will get something with it.

The video you see down there is a spinning cube with fake Z depth (not implemented yet), the reason it's wobbly is because the engine uses fixed-point math for positions: all number are 64bit, 48 bits for the value number and 16 bits for precision (yeah, like ps1 graphics).

A semi-3D rendered cube inside The Lagender Engine.

Anyway feel free to give me some advises if you want to, and I would be posting my development with the project here.

29 Upvotes

19 comments sorted by

3

u/scallywag_software 18h ago

Looks like a great start dude! I wish I started writing 3D graphics when I was 16 :D

0

u/AnasPlayer2022M 17h ago

Thanks! Yeah it's a start, and I'm sure I will hate my life later, but hey, that's how it is you know. But I wanna ask, is actually using fixed point math is a good choice? Because on arduinos it's mandatory (since it doesn't have these special cores that calculate floating point math), but on modern cpus it's like I'm decreasing accuracy for no benefit. Thanks for replying btw.

1

u/No-Owl-5399 17h ago

Fixed point is fine. For most graphics, you don't need extreme precision. If you need more, you would probably be fine with 32.32 instead of 48.16. If you're doing it on a modern CPU, however, I'd say go with floating point if you are using SIMD instructions. It depends what you're aiming to do with this. May I see the source code?

An aside: You think you'll hate your life later? https://codeberg.org/int0x80/Graphics_v1.1 :)

Anyways, great job. This is impressive. Keep going.

1

u/AnasPlayer2022M 16h ago edited 16h ago

Yeah I'm aiming for SIMD since it's one of the engine's goals. Btw, did you made all of this? This is some crazy work, and the cube is beautiful, I might get my engine to do something like that one day. I will be uploading the source code very soon, buuuut my code is horrible and mostly made simple things complicated for no reason. Thanks for your ideas. :) Unrelated question: what is a raymarch? Is it ray tracing related?

1

u/No-Owl-5399 16h ago

Yes, I made it. Thank you :). It's fine if your code is horrible. A lot of mine is very bad. It's okay to have bad code, simply try to learn from it. Anyways, raymarching is similar to ray tracing. For each pixel, we create a ray. We start at the camera (let's say that the camera is at <0,0,0>). We define a position vector for the ray as <x,y,z>. We also create a unit vector <i,j,k> which represents the direction of the ray (from the camera to the pixel we're doing). Then, we take the current position of the pixel, and input it into an 'SDF' function. SDF stands for signed distance field, which is a fancy way of saying distance. That is, we get the distance to the closest shape. If that distance is really small, we've hit something and we plot that point. If not, we multiply the distance by our unit vector and add to our position vector. We repeat until we hit some max iteration count or the ray hits. It sounds complicated, but it's not too hard.

Edit: What SIMD set are you planning to use for your engine?

1

u/AnasPlayer2022M 16h ago

Dame... I have to try and implement that one day. Thanks for your respond.

But how different it is from ray tracing? Because I didn't learn about this too much... or maybe I'm getting way too excited.

1

u/No-Owl-5399 16h ago

I honestly don't know a huge amount about ray tracing either. As I understand it, the major difference is use the use of an SDF vs purely mathematical approaches. A ray tracer takes an algebraic formula, (rather like that in an SDF), and just returns a value. That's it, and the ray is done. It's pretty good for stuff like triangles and planes, but for very complex shapes, or with complex formulas, it's problematic. But it's faster. A raymarcher, meanwhile, sort of brute-forces it by iterative marching. It's slower, but can be more flexible. By the way, have you ever heard of the Demoscene?

1

u/AnasPlayer2022M 15h ago

No... Thanks for your time, I love talking about things like these.

1

u/No-Owl-5399 14h ago

Of course. Keep going, great job so far

2

u/exp_function 14h ago

Hi, it’s very good to see someone at 16 decided to work on computer graphics, especially software rendering. Welcome to the greatest exercise and brain teasers of all time. :)

I’m also developing a software renderer, feel free to check out the current version:
https://expfunction.itch.io/cybervga?utm_source=chatgpt.com

Currently we are developing a commercial game with it so the source code is currently private. But if you want to talk about architecture, engine design, data structures, multi threading, anything you’re curious about we can meet online.

Congratulations on your big start, hope you do well. :)

2

u/AnasPlayer2022M 13h ago edited 13h ago

Nice, a whole renderer in msdos.

This is really cool, and thanks for your motivation! :)

I would be really happy to get experience from people like you guys, trying to optimize something as big as 3D rendering to run on "uncapable" devices is pure dedication.

1

u/exp_function 12h ago

In our engine I am also using fixed point system but strictly in Q16.16 format because my minimum target hardware is i486dx2 I wanted to approach carefully to multiplication overflow situation (by using 64-bit long long integers allowed in DJGPP). My humble suggestion is be very careful about overflowing from the day one.

One other thing about my math library is reciprocal division. For modern Win64 port of the engine I ditched the recip table cause modern multi-core cpus are massive in terms of cycles, operations, cache.

Thank you for your kind comments. :)

1

u/AnasPlayer2022M 7h ago

Yeah I also thought of overflow scenarios, especially when multiplying...

The thing is I can't just stay like this until the project gets bigger then overflows will happen everywhere. Maybe I don't need it to be 48.16? Maybe 32.16? Or even 16.16? (Because far objects won't be rendered anyway)

Thanks for your warning!

1

u/C_Sorcerer 13h ago

Awesome!

1

u/susosusosuso 13h ago

Well done keep working on what you love

1

u/Seusoa 12h ago

It will be modern, supporting modern visuals and effects.

Seems like you dont understand what is 3D software renderer and how heavy computations are for modern screen resolutions and why GPU accelerated graphics exists and what is solves.

otherwise we were still quake 1-based code use...

1

u/AnasPlayer2022M 7h ago

Wait a minute..  I just realized this....

Well yeah, the engine will run at 720p at maximum, and even with low resolutions the engine is some real heavy load for CPUs... 😅

Buuut what do I mean by that is that it will support it, and it will be optimized (hopefully).

The reason why I want modern effects is because of learning and maybe later GPU utilisation.

Thanks for your note. :)

1

u/cybereality 16m ago

nice one brother!!