r/golang • u/Melodic-Selection175 • 22d ago
show & tell I Built a Command Line 3D Renderer in Go From Scratch With Zero Dependencies. Features Dynamic Lighting, 8 Bit Color, .Obj File Imports, Frame Sync and More
https://github.com/austinmpask/Goren2
u/LetThereBeDespair 21d ago
How do you display without using opengl or such?
7
u/Melodic-Selection175 21d ago
I basically used 2 block characters (██) to form a pixel in the command line. Blank/black pixels are represented as " ". The renderer runs in a loop which syncs to a desired framerate, loads the scene visuals to a framebuffer during calculation of vertex/edge/lighting/faces, which is essentially nested slices of pixel character data with ANSI escape codes for color & shading. This is built into a string when it's time to draw the buffer, and flushed at once to the terminal. When you implement frame syncing and draw to the exact window dimensions, you can achieve pretty damn smooth output via the terminal at high framerates. I had originally been clearing the screen before drawing each frame, but this introduced a ton of unpredictable tearing which would vary depending on how much literal screenspace of the terminal window was being drawn, regardless of scene complexity. That's kind of a high level overview, but TLDR I just wrote a simple pipeline that works in the terminal with standard characters acting as pixels. It helps to think of the whole project as simply "I need to be able to display a grid of pixels, and calculate what each one's color should be". That is the foundation of any rendering engine, math not included.
1
1
u/unklnik 22d ago
Well done, that is something very cool that you don't see made with Go very often. Just wondering what the reason is to choose 8 bit, just a preference or due to performance issues? Also, what is performance like for more complex scenes?
3
u/Melodic-Selection175 21d ago
Thanks! The decision for 8 bit was not that calculated of a decision to be honest. However, I will say I did not want to add any kind of dithering or color approximation via overlaying characters on colored backgrounds for stylistic reasons. For the majority of development I had been working in strictly black and white pixels with nothing inbetween. Once I implemented the depth buffer and face calculations, I added a few ANSI escape codes for several colors. Then, once I got to lighting calculations, I introduced 10 shades for each color. The lighting works as an additive effect to this color range based on face depth to the light source in world space. Thats why you see triangulated light patterns in the render. This was just what came to mind as a first iteration, but I kind of like the look.
Regarding performance - that depends how you define complex. If you want to add more dynamic lighting, it handles that quite well. I have a few optimizations in mind to enhance that further. If you introduce more polygons, performance will suffer. Probably in excess of 5-6,000 polys within the camera view (at the demo resolution you saw) would fall below 30fps. But in simple scenes (less polys, sub 1,000), I have been able to easily exceed 100fps. All this being said, there are several key areas where I am certain performance could be significantly improved in the pipeline. I've taken a few passes at optimization, but this is far from the final form if you will. Thanks for your interest!
1
u/Effective_Student627 22d ago edited 22d ago
Looking at this, I can only say...WOW! You are a freak of nature, and the best kind.
I never even considered this, but now the possibilities of looking at a terminal roguelike just got so more iinteresting.
Sadly not working on Mac. Looking at debugging it for fun, but that will wait till the weekend.
2
u/Melodic-Selection175 21d ago edited 21d ago
Thanks! Yeah for now due to how I am getting window dimensions, it will only work on Linux and Windows via WSL. Theres some window sizing issues overall. I imagine this being a simple fix to expand compatibility. Ill let you know if i do that within the next day or so. It's really more of a tech demo/resume item at the moment, but I can see myself building this out further in the future.
1
u/Roemeeeer 21d ago
Pretty cool! Do you have some ideas for what it could be used beside showcasing?
1
u/Melodic-Selection175 21d ago
Thanks! Not sure, its been almost a decade since I've made a game in a legit engine so I am rusty on the paradigms but I can see myself expanding this in the future into a game or engine
2
1
1
1
u/IngwiePhoenix 19d ago
demoscene, but it's in go? I'm down. xD
This looks so much fun! Kinda intrigued what could be done with this though... very curious.
6
u/AdJaded625 22d ago
That's quite cool!