What is the *most efficient* way to draw a single pixel to the screen?

That’s an interesting question. Back when I was working on the 3D games I would really have liked native triangle and quad drawing functions, so I think that was one of the big gaps which is now covered.

A big obstacle for running on hardware devices was that fixed point math is clunky - the Fx8 class helps but is rather verbose to use, and it’s easy to accidentally exceed range limits in calculations. For example, doing a dot product requires multiplying components. Fx8 uses 8 bits after the decimal point (“binary point”?) out of 30 usable integer bits, so numbers need to stay below 127.0 (using 15 bits for a 7.8 bit fixed point number) to be able to multiply them without overflowing. (This is from memory, I may have gotten some details wrong.)

Apparently some of the target devices would natively support 32bit single precision float arithmetic, but from what I remember there’s not really any reasonable way to make use of that from TypeScript which is based on 64bit double precision floats. I don’t really know of any straightforward way to get around this. I suspect many users would be fine with focusing on the emulator which has good performance for double-precision float arithmetic and ignoring performance on hardware devices.

blitRow can be a useful helper a handcoded triangle renderer, but it’s a bit limited. It can be used to mix colors, but that needs some slightly clunky setup to make a source image that has vertical strips containing all the needed color mixes, and that would also be a bit wasteful as far as memory is concerned. I think it currently doesn’t really work for texture mapping since it doesn’t have support for rescaling or general transforms.

Would it be feasible to add a generalized blit function that can apply affine transforms + perspective when looking up the source texture? This could be used for effects similar to NES “mode 7” graphics. This would have been really helpful for the MakeCode Kart project (see MakeCode Kart - #166 by kwx), and could also be used to do some simple texture mapped 3D. That’s a bit of a slippery slope though - the next feature request would be applying lighting and shading to the textures, and that would be hard to do with the limited available color palette.

I have mixed feelings about adding vectors or matrix math. If code is intended to work on hardware devices, it pretty much needs to be based on fixed point arithmetic for the performance critical parts, and that is hard to generalize. It works if the high-level game logic does floating point math and then feeds coordinates of a handful of individual objects to a 3D renderer which then internally uses fixed point (that’s how I did it in my games), but it still needs to be used carefully to avoid exceeding the numerical range limits for fixed point values.

Adding a full native 3D renderer to MakeCode Arcade doesn’t sound like a good fit, especially since the APIs to do so in a generalized way would get very complicated.

Sorry, this turned out a bit more rambling than intended :slight_smile:

6 Likes