I remember buying a 3D engine development book, "Engines of Creation" by Jonathan Blossom, for the Mac decades ago. The included software was able to draw a 3D scene in B/W using dithering with multiple lights. I thought it was so amazing that it could draw a "real time" 3D scene in 15 or so FPS!🤣 And here you are, building your own computer from chewing gum and paper clips, and can squeeze out nearly 30 FPS with a smooth shaded cube! Bravo!
An absolute masterclass. I remember programming a wire-frame cube on bare metal 20+ years ago as a learning exercise, but you have put me to shame. Great video. 👍👍👍
Brings back 35 year old memories of demo scene coding. Had a friend who was very involved in graphics coding on amiga, pc and later professionally for PlayStation.
Jesus! - I'm inline with Peter. I only grasped maybe half of it. Never the less, a beautiful video, that demonstrates, that the really hard part of coding, is optimizing and simplifying as You need to know and understand Your hardware to the very edge. James, You're doing an amazing job. Thanks :-)
@@weirdboyjim Your level is just right. Don't lower the bar. If I need to dig deeper into the subject at hand, all I need to do is go back to one of the relevant videos. I find Your level inpiring 🙂
As one who did some fairly low-level graphics early in my career (for a 2D CAD system running on IBM XTs), I can really appreciate the mathematical tricks you pulled out of your hat to get this working. Great job, as usual, and thanks for sharing it with us all.
Wow James, you've blown my mind. He's me, thinking myself awfully clever because I've written a bit of assembler for microcontrollers. And then you dump this epic on my desk! "I'm not worthy!" ;) And I love the sort-of "cop outs" you've done, like positioning the cube so you don't need to care about clipping. I had a go at very entry-level graphics programming on my 386 back in the days when a 386 was cutting-edge but got disheartened when performance was sloooooow... I wasn't wise to look-up tables and didn't even consider craftily avoiding clipping and such like. Splendid stuff! ... oh yeah... and the trick to change the background colour as the code goes on so that you've got visual feedback to how long stuff is taking to complete is just brilliant.
Probably the best video so far! I know most of the 3D stuff, but it is the optimization techniques and ideas that I get inspired with while I am currently working with 8-bit programming
Very cool demo and excellent discourse around how it was put together, stage by stage. The snippets of theory are helpful starting points where one might want to delve into the topic further - Cheers!
Thank you, James. This was wonderful. I love the way that you walked us through the development process and the many levels of optimisation that you then worked through to achieve the final result.
Closest I got to anything like this back in the day was (hand-assembled) 6502 machine-code line drawing and flood-filling routines, but this is some next-level stuff. Thanks for sharing.
I recently learned of a quick and easy hardware fill. On each scanline, the pixel color XORs the current color instead of setting it. This allows you to do a fill line by setting just the endpoints of the line.
This is great! It takes me WAY back to writing 3D demos in x86 ASM on the PC for the old VGA cards at the time. A lot of the techniques here are identical (I had no floating point co-pro on my PC at the time, so also used fixed point math!) I remember using phong shading at the time, and using the brightness of the pixels as a primitive depth buffer, to allow objects to merge as they passed through each-other! I foresee a new PCB to DMA polygons to the frame buffer in the future! :)
I don't remember if the video card had a register for setting the base address for the VRAM, but adding/using that could be a nice enhancement that would allow switching the frame buffer in hardware and eliminating the need for copying block copy for the double-buffering. Could also update the background clearing so that it only needs to processes the values before/after the min/max X extent of the edges being drawn on a given scanline.
This instantly makes me think of Bresenham's line algorithm, which can be implemented purely with integer arithmetic, and leaves no gaps in the rasterized lines.
That lighting trick relying on only 3 sides being visible (so you can “adjust” the lighting on each flat side in the pallet like you described) I did not see coming. And I admire it so much 😀
Thank you so much James! This is really fantastic and super exciting to see! 🍀✨ Congratulations on taking this next step! Merry Christmas and happy relaxing (if you get the chance).
I really like the result and the explanation of the process you went through to get there. 3D graphics were never my forte (in fact, I try to steer clear of it as much as possible ;-)), but you made it look and sound all so easy!
Glad you enjoyed it! I've been thinking about doing an introduction to 3d graphics. This kind of touches on some of the basics, maybe I'll do more with Jam-2.
I did a computer graphics class at university back in 1992. It was written in C and had all the matrix stuff you mention there. The problem was that I only had a 386sx computer - so it had no floating point hardware and did it all through emulation. It was slow. My friend had a brand new 486, and I was really happy to see how fast it went on that system.
nice demo. you can reduce your clear routine by approximately 50% by only clearing the annulus of those pixels that can possibly _not_ be drawn on (ie. never clear the ones in the center that will always be overdrawn by the cube.)
What's the reason for the fireflies? Also, I'm really missing the screen recordings you did in the vga series. The camera recording and youtube compression really can hide some imperfections in the vga output, but I think they are important in understanding the system and it's limits and I'd appreciate more screen recordings 😊
Stunning piece of work - and to have it on your own machine you designed & built from scratch must feel quite something. Any temptation to build an extension to perform the matrix arithmetic as new operations? 😉
7:30 If dealing with 4x4 matrices, you can concatenate the world->view matrix and the view->projection matrix into one world->projection matrix. Not sure if that concatenation operation will be worth it for only 8 points, but if you start adding in more complex geometry it will definitely help. There's probably a way to construct a world->projection matrix directly, instead of calculating two separate matrices and concatenating them together. Just need to go through and do the maths for it.
Cool demo. Given you have complete control of the hardware, do you think maybe a custom "blit" chip to do some of those graphics manipulations might be useful? It'd be very reminiscent of the Amiga stuff :D
That’s tricky, Demo coding has always been about pushing the hardware, not sure it counts if I start adding hardware for specific things. I’d rather make good general purpose circuitry and then use it as best as I can.
So you only clear the area used by the cube, do you only copy from the back buffer for the same area? Couldn't you combine the the copy and clear routines? Great vid BTW
Oh man, this reminds me of writing 3d graphics from scratch first in turbo pascal, then in C, then switching to GLIDE, then buying the first GeForce 256 when that came out and tossing out all the 3d calculations in favor of OpenGL...
Dude, is that Visual Studio 6? Proper old school! Seriously cool stuff though. I was reading through some of the Elite source code recently as someone did a line-by-line explanation of how it all works. My brain still won't let me believe that it's possible to do 3d on an 8 bit computer though :)
Hah! VS2008, I bought a copy personally years ago, I'll be forced to upgrade one day but I'm always using the latest version for work but for some reason the old version just feels right when working on the retro stuff.
I wonder if you could have work out some hardware acceleration for doing things such as clearing the window (or back buffer), setting it to a certain value - or maybe just zero. Call it a memory fill operation. Could you have some DMA type hardware? It could fill and maybe even copy between two memory blocks. I know that on the C64, where you could have extra memory in a cartridge, they often also included DMA hardware to copy (or swap) blocks between the cartridge RAM and base computer RAM. If setting memory to a constant value, could you get it down to a byte per cycle. You'd need lines to assert the bus and/or pause the main CPU while the block fill happened.
Looking at this, it occurs to me that Elite was designed to run on exactly this kind of computer. It'd probably be way too much work to port it even if the source code is available, but would be cool.
Not having a true bitmap raster buffer is the biggest thing in the way. Of course 8-bit Elite implementations tended to be line's only as well. Would be fun.
The original BBC Elite source code is available (with permission) and there's a project that documents the assembly, but yes it would be a huge project to port.
Yes, that would be hardware double buffering. You would need twice as much video memory as is required for a display frame, something I don't have in this build.
Looks like the spam filter gobbled up my last comment. I also did ZBuffering and have support for vertex shading too. I'm just flat shaded at the moment though, I might look into specular. I can in theory add texturing pretty easily since I did the barycentric coordinate calculation already, but I don't have much RAM for textures, and they might be a but meaningless on a 64x64 pixel object.
For you Bob I checked the moderated comments feed, nothing in there for this video so far. Depth buffering is rarely beneficial for efficiency in a software rasterizer, it's usually better to get the faces drawn in the right order. Texturing can work on a 64x64 though, my "Doomed" runs at a 60 pixel vertical resolution. I could do a textured cube rotating on one access with that code.
Would the computer be fast enough to be able to handle bitmap frame buffers if you built the hardware, or is that against the design philosophy for this computer?
Sure, although the higher the resolution the more effort it takes to fill it. A resolution like 320x200 like early pc games would be workable but it would need banking to fit into the 64k address space.
Join us on Discord: discord.gg/jmf6M3z7XS
Follow me on Twitter: twitter.com/WeirdBoyJim
Support the channel on Patreon: www.patreon.com/JamesSharman
I remember buying a 3D engine development book, "Engines of Creation" by Jonathan Blossom, for the Mac decades ago. The included software was able to draw a 3D scene in B/W using dithering with multiple lights. I thought it was so amazing that it could draw a "real time" 3D scene in 15 or so FPS!🤣 And here you are, building your own computer from chewing gum and paper clips, and can squeeze out nearly 30 FPS with a smooth shaded cube! Bravo!
One of only a few channels I thumbs-up before watching and have never been let down.
Ha ha, same here
An absolute masterclass. I remember programming a wire-frame cube on bare metal 20+ years ago as a learning exercise, but you have put me to shame. Great video. 👍👍👍
Very nice James! The work involved in this is pretty mind bending to me. 3D transformations in assembler. Really cool!
Brings back 35 year old memories of demo scene coding. Had a friend who was very involved in graphics coding on amiga, pc and later professionally for PlayStation.
Very much so, although this is just 8-bit so closer to pre-Amiga hardware.
Beautifully explained as usual!
Glad it was helpful! It did turn into a partial "intro to 3d"
Very impressive work! One day I will actually have to sit down and learn how to do 3D properly.
That palette timing trick is clever!
Basic 3D is quite easy when the fundamentals click into place. The palette trick is indeed cool, probably used that most on PlayStation 2!
Jesus! - I'm inline with Peter. I only grasped maybe half of it. Never the less, a beautiful video, that demonstrates, that the really hard part of coding, is optimizing and simplifying as You need to know and understand Your hardware to the very edge. James, You're doing an amazing job. Thanks :-)
Glad you enjoyed it! I never know if I'm hitting the right level of detail with my explanations of stuff!
@@weirdboyjim Your level is just right. Don't lower the bar. If I need to dig deeper into the subject at hand, all I need to do is go back to one of the relevant videos. I find Your level inpiring 🙂
seeing this result after many months of hard work is truly rewarding and amazing. Keep up with the good work !👍
Bravo. One difference from my teenage mind and years ago now is I realized lerping. And lots of it in parallel.
And the 21st century flip from filling pixels inside shapes to querying if each pixel is in any of the shapes.
Thank you for this comprehensive and excellent tutorial. You have a talent for teaching.
As one who did some fairly low-level graphics early in my career (for a 2D CAD system running on IBM XTs), I can really appreciate the mathematical tricks you pulled out of your hat to get this working. Great job, as usual, and thanks for sharing it with us all.
Wow James, you've blown my mind.
He's me, thinking myself awfully clever because I've written a bit of assembler for microcontrollers. And then you dump this epic on my desk! "I'm not worthy!" ;)
And I love the sort-of "cop outs" you've done, like positioning the cube so you don't need to care about clipping. I had a go at very entry-level graphics programming on my 386 back in the days when a 386 was cutting-edge but got disheartened when performance was sloooooow... I wasn't wise to look-up tables and didn't even consider craftily avoiding clipping and such like.
Splendid stuff!
... oh yeah... and the trick to change the background colour as the code goes on so that you've got visual feedback to how long stuff is taking to complete is just brilliant.
Probably the best video so far! I know most of the 3D stuff, but it is the optimization techniques and ideas that I get inspired with while I am currently working with 8-bit programming
Kind words! Pushing very low end systems is always interesting!
Very cool demo and excellent discourse around how it was put together, stage by stage. The snippets of theory are helpful starting points where one might want to delve into the topic further - Cheers!
Thanks! Glad you enjoyed it!
0:21 You should be! It looks fantastic, congrats!
Thanks!
Amazing work James, worth the wait! 🤩
Thank you, James. This was wonderful. I love the way that you walked us through the development process and the many levels of optimisation that you then worked through to achieve the final result.
Closest I got to anything like this back in the day was (hand-assembled) 6502 machine-code line drawing and flood-filling routines, but this is some next-level stuff. Thanks for sharing.
I recently learned of a quick and easy hardware fill. On each scanline, the pixel color XORs the current color instead of setting it. This allows you to do a fill line by setting just the endpoints of the line.
Instanteneous thums-up before watching :D Very nicely done!
Great to hear from you again! Excellent as always.
I've written both a rastarizer and a pathtracer in modern languages. I can't even fathom the difficulty of writing it in assembly 🤯 Well done!
To be honest, the principles are all the same. It just takes longer
This is great! It takes me WAY back to writing 3D demos in x86 ASM on the PC for the old VGA cards at the time. A lot of the techniques here are identical (I had no floating point co-pro on my PC at the time, so also used fixed point math!) I remember using phong shading at the time, and using the brightness of the pixels as a primitive depth buffer, to allow objects to merge as they passed through each-other! I foresee a new PCB to DMA polygons to the frame buffer in the future! :)
spinnin cubes are always appreciated
Glad to be of service!
I don't remember if the video card had a register for setting the base address for the VRAM, but adding/using that could be a nice enhancement that would allow switching the frame buffer in hardware and eliminating the need for copying block copy for the double-buffering.
Could also update the background clearing so that it only needs to processes the values before/after the min/max X extent of the edges being drawn on a given scanline.
Always love it when you post a new vid and this one is stunning.....cheers !!
This was awesome James. Thank you so much!
This instantly makes me think of Bresenham's line algorithm, which can be implemented purely with integer arithmetic, and leaves no gaps in the rasterized lines.
That’s what I call a Data-Oriented Design 🎉 I applaud you!
Thank you! Cheers!
James, you're a bloody wizard! 😍
@@m1geo my owl must have got lost 🤣
Congrats for another achievement and great video. I like the explanation, even I did only understand half of it :)
Thanks Peter! I was very pleased with how it came out, even if it did take me 3 times longer than planned!
to be honest , that is coolest and cleanest looking computer.
This was great! Well done Sir.
Subscribed!
What a cool demo! Congratulations!
Thank you!
That lighting trick relying on only 3 sides being visible (so you can “adjust” the lighting on each flat side in the pallet like you described) I did not see coming. And I admire it so much 😀
Glad you liked it! It was handy!
Thank you so much James! This is really fantastic and super exciting to see! 🍀✨
Congratulations on taking this next step!
Merry Christmas and happy relaxing (if you get the chance).
I actually spend lots of time over Christmas writing the guts of another game, you'll see that soon!
The next extension has to be a vector co-processor.
Hurray, very impressive! 🎉😃
The lighting is pretty sweet!
Yeah, basic lighting can really lift even basic 3D!
I really like the result and the explanation of the process you went through to get there. 3D graphics were never my forte (in fact, I try to steer clear of it as much as possible ;-)), but you made it look and sound all so easy!
Glad you enjoyed it! I've been thinking about doing an introduction to 3d graphics. This kind of touches on some of the basics, maybe I'll do more with Jam-2.
I did a computer graphics class at university back in 1992. It was written in C and had all the matrix stuff you mention there. The problem was that I only had a 386sx computer - so it had no floating point hardware and did it all through emulation. It was slow. My friend had a brand new 486, and I was really happy to see how fast it went on that system.
I'm very impressed. DIY CPU rendering a 3D object. You can conquer the world :D
When’s the hardware rasteriser + transform & lighting coming?
Merry Christmas, James!
Thanks!
Excellent.
Awesome!
a piece of art ❤
Kind words!
nice demo. you can reduce your clear routine by approximately 50% by only clearing the annulus of those pixels that can possibly _not_ be drawn on (ie. never clear the ones in the center that will always be overdrawn by the cube.)
Congrats, to think this is all in raw and custom hardware.
Writing some cool demos (and games) was always the end goal for this project!
What's the reason for the fireflies? Also, I'm really missing the screen recordings you did in the vga series.
The camera recording and youtube compression really can hide some imperfections in the vga output, but I think they are important in understanding the system and it's limits and I'd appreciate more screen recordings 😊
Stunning piece of work - and to have it on your own machine you designed & built from scratch must feel quite something. Any temptation to build an extension to perform the matrix arithmetic as new operations? 😉
love it
Glad you liked it!
7:30
If dealing with 4x4 matrices, you can concatenate the world->view matrix and the view->projection matrix into one world->projection matrix. Not sure if that concatenation operation will be worth it for only 8 points, but if you start adding in more complex geometry it will definitely help.
There's probably a way to construct a world->projection matrix directly, instead of calculating two separate matrices and concatenating them together. Just need to go through and do the maths for it.
That is how you do it on more modern systems but using the 3x4 and doing the projection directly is far more efficient at this scale.
Fire
Way cool
Cool demo. Given you have complete control of the hardware, do you think maybe a custom "blit" chip to do some of those graphics manipulations might be useful? It'd be very reminiscent of the Amiga stuff :D
That’s tricky, Demo coding has always been about pushing the hardware, not sure it counts if I start adding hardware for specific things. I’d rather make good general purpose circuitry and then use it as best as I can.
insane
Amazing James, now add 3D acceleration :D
So you only clear the area used by the cube, do you only copy from the back buffer for the same area? Couldn't you combine the the copy and clear routines? Great vid BTW
Oh man, this reminds me of writing 3d graphics from scratch first in turbo pascal, then in C, then switching to GLIDE, then buying the first GeForce 256 when that came out and tossing out all the 3d calculations in favor of OpenGL...
Dude, is that Visual Studio 6? Proper old school!
Seriously cool stuff though. I was reading through some of the Elite source code recently as someone did a line-by-line explanation of how it all works. My brain still won't let me believe that it's possible to do 3d on an 8 bit computer though :)
Hah! VS2008, I bought a copy personally years ago, I'll be forced to upgrade one day but I'm always using the latest version for work but for some reason the old version just feels right when working on the retro stuff.
Reminds me of being 14 and using the Amiga to create a rotating square and then cube. But not back face culling or filling just the lines.
I wonder if you could have work out some hardware acceleration for doing things such as clearing the window (or back buffer), setting it to a certain value - or maybe just zero. Call it a memory fill operation. Could you have some DMA type hardware? It could fill and maybe even copy between two memory blocks. I know that on the C64, where you could have extra memory in a cartridge, they often also included DMA hardware to copy (or swap) blocks between the cartridge RAM and base computer RAM. If setting memory to a constant value, could you get it down to a byte per cycle. You'd need lines to assert the bus and/or pause the main CPU while the block fill happened.
Sounds like you need a hardware matrix multiplier, or a bit/blit like coprocessor to set/clear/move bits en-mass. Mini amiga. 😎
Could this be made into a kit that people can make?
Will we see multi-cores or GPU for this?
geat! now can we do the spinning fish meme?
Probably best done as a flick book animation rather than 3d rendering on this kind of low end hardware.
Looking at this, it occurs to me that Elite was designed to run on exactly this kind of computer. It'd probably be way too much work to port it even if the source code is available, but would be cool.
Not having a true bitmap raster buffer is the biggest thing in the way. Of course 8-bit Elite implementations tended to be line's only as well. Would be fun.
The original BBC Elite source code is available (with permission) and there's a project that documents the assembly, but yes it would be a huge project to port.
Is flip copying data? Could you have two screen buffers and just update which one is displayed by the hardware?
Yes, that would be hardware double buffering. You would need twice as much video memory as is required for a display frame, something I don't have in this build.
Now you have a cube, 2nd Reality in what, 3 months? :D
Best call it 4 😅
Better buy some nvidia puts.
Cool project dude!
Vulkan support when?
Looks like the spam filter gobbled up my last comment. I also did ZBuffering and have support for vertex shading too. I'm just flat shaded at the moment though, I might look into specular. I can in theory add texturing pretty easily since I did the barycentric coordinate calculation already, but I don't have much RAM for textures, and they might be a but meaningless on a 64x64 pixel object.
For you Bob I checked the moderated comments feed, nothing in there for this video so far. Depth buffering is rarely beneficial for efficiency in a software rasterizer, it's usually better to get the faces drawn in the right order. Texturing can work on a 64x64 though, my "Doomed" runs at a 60 pixel vertical resolution. I could do a textured cube rotating on one access with that code.
Would the computer be fast enough to be able to handle bitmap frame buffers if you built the hardware, or is that against the design philosophy for this computer?
Sure, although the higher the resolution the more effort it takes to fill it. A resolution like 320x200 like early pc games would be workable but it would need banking to fit into the 64k address space.
Could you minuterize this into only a few chips?
You mean the computer he built? That whole thing could easily be reduced to only one single chip. But that's not why we're here.
Nice. Add one more side, I dare you. :P
Never enough! 😅
So... no textures?
Look like this CPU actually support an Intel_Syntax Assembly..