I now have a pretty decent implementation of subpixel-correct polygon rendering on Amiga: http://www.youtube.com/watch?v=f4a7rxGL7b0
I ended up with a hybrid approach, using blitter for lines where abs(dx) < abs(dy), and CPU for the other cases, seems to work quite well.
I've given up on the other cases, the fact that the blitter renders them horizontally rather than vertically seems to be quite problematic. It might be possible to fix those quirks as well, but this will have to do for now.
Posted on 2012-01-05 18:59:37 by Scali
And a more detailed explanation in part 5.1 on my blog:
Also threw in some other goodies for good measure, like dithered polygons on Hercules, and the ever-funky PCjr/Tandy graphics mode.
Posted on 2012-01-06 08:18:46 by Scali
CRT displays historically rendered horizontally, with the vertical position describing one horizontal row. Later, interlacing was introduced as a way of disguising horizontal artefacts visible due to electronic latency when recording a previously recorded image. This became a standard in all CRT devices, which at the end of the day still had a single pixel beam deflected by two sets of energized plates.
I was particularly fond of the raster effects achieved on the c64.
Posted on 2012-01-17 01:08:11 by Homer
If you like raster effects, you'll like the Angels' Copper Master demo:
The Amiga was built for raster effects.
Posted on 2012-01-17 07:44:59 by Scali
I'm trying to add sound to my Amiga code now.
I've been collecting the sources of various replayer routines:
This includes SoundTracker, NoiseTracker, ProTracker and StarTrekker replayers (especially StarTrekker is quite cool, allows AM/FM synthesis and 8-channel replay).

I've patched up the code of one of the ProTracker routines to work with my SAS compiler/assembler package. Hopefully I can get it to play a tune soon :)
Posted on 2012-03-09 15:04:29 by Scali
Yay, tune is playing!
Lovely... so now I have 3D graphics AND music on Amiga.

I'd need a nice oldskool MOD player for PC as well. But I guess the only way to get one is to write it myself. Stuff like minifmod is horribly slow.
Posted on 2012-03-09 17:32:14 by Scali
While I was doing the oldskool PC stuff, the demo Crystal Dream by Triton was one of my inspirations: http://pouet.net/prod.php?which=463
It's one of the first demos ever to have smooth polygons on PC, and great mod-based music.
It uses the same EGA trickery that I developed.

However, when I tried to run it on my 486DX2-80, I couldn't get the Sound Blaster to work. I have an original Sound Blaster Pro 2.0, and neither SB nor SB Pro worked properly. Only internal speaker worked, which sounds horrible.
That's odd, because I recall the music well. But I had a 386SX-16 at the time (with the same SB Pro card). So I turned off the turbo on my 486, and found that the SB gets detected properly in that case. You just can't fully enjoy the demo, because the system is too slow that way.

So I figured there must be some kind of timing bug or such in the SB code. So I put it on my todo-list to find and fix the bug.
I made a start with it a while ago, but it turned out to be more difficult than just putting a bigger value in a loop counter somewhere. And I did not know anything about programming the SB anyway. I didn't have the time, so I left it for now, but kept it on the todo-list for later.

Yesterday and today, I had some more time to look into it, and I finally managed to pinpoint the issue, and patch up the actual code.
It now works flawlessly on my 486DX2-80 in both SB and SB Pro mode:
It still does not work properly in Dosbox though, but I think that is related to the way it uses DMA. It also won't run properly under Windows 95, only from pure DOS. It might be because it does not reset the PIC timer rate to the default value... But I don't know if and when I'll ever look into that.
Posted on 2012-03-14 13:01:04 by Scali
I've made a video capture of my 486 running Crystal Dream with the fixed Sound Blaster Pro routines:
Posted on 2012-03-21 08:17:13 by Scali
I've been having a bit more of the oldskool fun.
The 486 donut was a proper bit of 486-optimized code, which meant that it did not use the FPU for any time-critical code. Instead, it uses fixedpoint integer mathematics (the 486 may come with an FPU, but its performance is very poor). For the Amiga and CGA/EGA/VGA code, I have not bothered to optimize the entire pipeline yet. They still relied on some (emulated) float code for the transforming of the polygons.

Since the donut code was 32-bit, I could easily use 32-bit integer operations throughout, and use the 64-bit results of 32-bit multiplies.
That gave me plenty of precision, without having to worry much about fitting everything in. The CGA/EGA/VGA fillers as well as the Amiga are aimed at lower spec platforms. The PC side is all 16-bit code, and although the Amiga's 68000 has 32-bit registers, it is not a true 32-bit CPU. It is faster at most 16-bit operations.
So, I've been trying to cut down the mathematics so that they would mostly fit inside 16-bit operations. Not that easy in general, but the fact that I want to squeeze a few bits for subpixel correction in there makes it even harder.
However, I have a reasonable proof-of-concept now. I have traded in virtually no visible precision, the textured donut still looks the same as it did, and it still has the same range of motion between near and far z-plane. The clipping also still works. Yet I need only 16-bit precision in most cases, and some 32-bits results of 16-bit multiplies.

Now I need to transfer the code over to the other platforms, connect it up to the polygon renderers, and optimize in 8086 and 68000 assembly. And then things are going to get interesting. On the one hand, polygon throughput should improve considerably. On the other hand, I will have more control over the objects on screen, so more advanced scenes, animation and even interaction will be possible.
Posted on 2012-06-13 05:22:47 by Scali
The donut generation routine has been ported to 16-bit now.
I've also done quite a bit of cleanup and refactoring, so that 16/32-bit code now is slightly closer together. I also need to do some refactoring so the different video standards (CGA/EGA/VGA/Tandy/Hercules) share as much code as possible.

Next step is to optimize the math in the pipeline. Then I'll need to add a polygon sorter to the pipeline, since donuts cannot be rendered correctly with backface culling alone (which is why cubes and lowpoly spheres were such popular objects in early demos).
Posted on 2012-06-24 18:13:33 by Scali
Here is an early video: http://www.youtube.com/watch?v=X8f8sNTjgmM
The donut is now sorted and rendered correctly from every angle.
Math is now entirely integer-based, using 16-bit wherever possible.
The trigonometry is done via a lookup table, as is the perspective division.
Still managed to squeeze in 4 bit subpixel correction.
I'm quite happy with the resulting accuracy.
Posted on 2012-06-28 18:08:39 by Scali
Some small updates on the oldskool-front...
Firstly I also made a version of the donut without subpixel correction, to demonstrate the improvements in rendering stability: http://www.youtube.com/watch?v=dTxt7qfC7o4
Secondly, I have added a 16-colour VGA palette, so that I could do some simple flatshading with reasonable results: http://www.youtube.com/watch?v=bpa-wZQBppI (the videomode is still EGA's mode 0x0D, 320x200 with 4 bitplanes)

Lastly, while I was going through my collection of old boxes, to test my Direct3D code, I also found my old Pentium Pro 200, which had a VideoLogic Apocalypse 3Dx card in it. That is a very early 3d accelerator (around 1997), with a very early PowerVR PCX2 tile-based deferred rendering chip on it (PowerVR is still around, powering iPhones, iPads, and various other smartphones, tablets and other mobile equipment).

I figured I could do a donut on that one as well. So I grabbed some old code of mine, and made a simple Direct3D renderer out of that (DirectX 2.0, the first version to include Direct3D): http://www.youtube.com/watch?v=1BWbuUg8yvA

I also managed to obtain an SDK for PowerSGL, the native rendering API for this chip. I might port the donut from Direct3D to PowerSGL at some point.
Posted on 2012-08-01 12:01:18 by Scali
Just though I would mention that I use PowerVR lib to develop for GLES 1 and 2 using Windows 7 as the development platform, and mobile devices as the target.. Quite handy!
Posted on 2012-08-02 01:46:38 by Homer
Yes, PowerVR has become quite the force in OpenGL ES, powering all those Apple devices.
Speaking of development libs... Microsoft stopped supporting anything lower than Direct3D 9 long ago in their SDK.
Since my PowerVR PCX2 only has DDI 5 drivers, the highest version of Direct3D that will work on it is Direct3D 7. I had to rummage through my old downloads on various old machines in order to find all the right headers and libraries.
I took the headers and libs from the DX 8.1 SDK, which has support for all versions of Direct3D. Then I found the docs for pretty much all versions of DirectX (1, 2, 3, 5, 6.1, 7 and 8 ), so I had the proper API reference. Newer SDKs generally only documented the latest interfaces.
But with this homemade 'legacy SDK' I was able to build DirectDraw and Direct3D code for all different versions of the interfaces. I could also 'cheat' a little, and use the D3DX libraries for versions of Direct3D that did not have it yet.

If anyone wants this stuff, I could upload it somewhere. Realistically you should never have to go lower than Direct3D 7, because Microsoft still had full backward compatibility with older drivers up to then. So even on the most basic 3D card and drivers, Direct3D 7 should still work.
Direct3D 8 will work on DDI 6 drivers and higher, and Direct3D 9 needs DDI 7 or higher.
But if you want to write non-shader code, the difference between the different versions of D3D is not very large. So using D3D7 instead of D3D9 for fixed-function stuff should be simple. The only version of D3D that's very different is the first version (included with DX2 and DX3). It uses execute buffers instead of SetState() and DrawPrimitive() APIs.
Which is the main reason why I chose that particular API instead of just going with D3D7. I had never used that version of D3D before, and wondered how difficult it would be. Seeing as it had quite the reputation for being difficult to use. Carmack made some comments on that early on.
Turns out that it wasn't all that difficult really. I was also surprised at how much functionality that first version of D3D already supports.
Posted on 2012-08-02 06:03:13 by Scali
Oh, and here is a video recording of an actual 386SX-16 machine running my donut code: http://www.youtube.com/watch?v=I3JvgSrRG7Q

As you can see, the lowpoly one is quite smooth.
The highpoly one still isn't super-slow, but the framerate may just be below the 'smooth/realtime' threshold for most people. Then again, it's quite a high polycount for such a machine. I was aiming for a 20-25 MHz 286 with that one, which may just have enough grunt to pull it off.
Posted on 2012-08-13 12:45:53 by Scali
Sometimes you remind me of Bryant and his TI calculator obsession, however since I am now dabbling in the low end of the market, I see beauty in small things. You're doing interesting stuff, I'm just dancing to the tune.
Posted on 2012-08-14 05:09:39 by Homer

Sometimes you remind me of Bryant and his TI calculator obsession, however since I am now dabbling in the low end of the market, I see beauty in small things. You're doing interesting stuff, I'm just dancing to the tune.

To be honest, I've not touched the Z80/TI-83+ in a few months now. I've actually been spending a lot of my time doing Verilog/HDL and arsing with some 4-bit systems. I still randomly make time to play around on the AVR paradox sent me, but the calculator has had to take it's place in my drawer for now.
Posted on 2012-08-14 15:23:46 by Synfire

Sometimes you remind me of Bryant and his TI calculator obsession, however since I am now dabbling in the low end of the market, I see beauty in small things. You're doing interesting stuff, I'm just dancing to the tune.

Thanks... and yea, there's low end, and then there's low end :P
A modern smartphone may be considerably slower than a PC, but still you have a GPU with programmable shaders and whatnot on there.
The above PowerVR PCX2 card is one of the first ever 3d accelerators, and doesn't have any programmability whatsoever. It can only use a single texture, and per-vertex lighting and alphablending with a texture.
And it's massively slower to boot. That donut only runs at about 45 fps (although that is partly because of the slow CPU, as a lower poly version can get up to 90 fps).

But, you still have *some* level of acceleration. And the CPU still has a built-in FPU.
The 386SX-16 is oodles slower still (barely faster than a decent calculator :)), does not have an FPU, and the videocard is little more than a dumb framebuffer, so the CPU has to do all the rendering as well.
And my code is actually written for 8086, so I don't even make use of the 32-bit capabilities either, it is purely 16-bit.

But, there are people who go even lower than that. Like this Commodore 64 stuff:
Only 64KB memory, 1 MHz, 8-bit, and it doesn't even have div or mul instructions.
Still they get smooth 3d out of it :)
(It's actually a conversion of a legendary Amiga demo, a much more powerful platform).
Posted on 2012-08-14 15:32:40 by Scali
I learned 3D programming basics on the apple 2c, with my glorious monochrome screen and one sound channel, although I was actively involved with the c64 demoscene, I did no 3D stuff on there, and it never really occurred to me at the time.
Posted on 2012-08-23 01:19:06 by Homer
Yea, 3d graphics on C64 is a bit of an anachronism. Just like various other 'newskool' effects using plasmas, textures etc.
These effects were mostly pioneered on Amiga, and were later backported by C64 coders, but at a time when the C64 itself was already mostly 'obsolete' (somewhere in the early to mid 90s I believe, I think this was one of the earlier C64 demos with 3D: http://www.pouet.net/prod.php?which=1586), as in, it was already out of production, and most users had moved on to other platforms already (mostly Amiga or PC).
Then again, in the demoscene it still remains an incredibly popular platform, I believe it is still by far the platform with the most releases, and people continue to release for it at a steady pace.

I think the C64 coders might just be the most hardcore coders in the scene. The stuff they manage to cram out of that modest hardware is incredible. It is truly an art, refined over many years.
Posted on 2012-08-23 04:54:57 by Scali