Tech

Real-Time 3D Shader for the Game Boy Color Becomes a Reality

Published

on


Danny Spencer took his trusty old Game Boy Color and turned it into a canvas for real-time 3D shading, transforming the simple handheld into a shockingly convincing three dimensional environment. As the teapot spins, its curves capture the light from a source you control with the D-pad, causing shadows to alter seamlessly in response to each nudge.



Pixels light up one by one with a Lambertian shader, which tells you exactly how directly light hits a surface, and Spencer solved the problem of multiplying non-integer numbers by baking surface information into normal maps and storing them in tiny three-byte chunks in the ROM. Each pixel selects a normal vector from these maps, doses it with light direction, and outputs a shade ranging from dead black to full-on white. The teapot’s spout glints in the light or falls into shade, with each frame a whole new creation from raw calculations.

The hardware will not be pleased because the Game Boy Color only runs at 8 MHz, which equates to approximately 140,000 cycles each 60 FPS frame. There is no multiply command, so Spencer had to get inventive. He had no trouble swapping multiplications for logarithms and lookup tables. Log tables convert products into sums, whereas power tables do the reverse. All values are compressed into 8-bit fractions from 1 to 1, with signs hidden away in the highest bits. Negative numbers in logarithmic space? No need to worry, he flags them independently and makes modifications on the fly.


To reduce the workload, Spencer shifted to spherical coordinates, in which vectors become angles: tilt (theta) and spin (phi), where light theta remains constant and you only adjust phi to move the light. The dot product is a simple formula: sin(Nθ)sin(Lθ)cos(Nφ – Lφ) + cos(Nθ)cos(Lθ). One subtraction later, he’s incorporating a custom cos_log table, a combination of cosine and logarithm, to speed things up. Five lookups every pixel, subtract, add, lookup, add, for a total of 960 pixels and 89% of the frame budget.


Spencer can patch the shader method in real time, swapping memory loads for hard-coded immediates. That’s an additional 8 cycles saved every subtraction, for a total of 11,520 over the frame. He skips over rows that contain no pixels at a rate of three cycles per pop. As a result, all of the frames remain consistent, even with some slight LCD ghosting to contend with.


You can examine the code for yourself in the GitHub repository, which was compiled with the RGBDS toolkit and includes Python scripts to transform Blender normal maps into ROM data. Two ROMs appear: teapot and gbspin. The releases page contains pre-compiled versions that will get you up and running. You can launch the BGB emulator or flash it onto a cart. Or, better yet, simply press some keys on Spencer’s internet emulator.
[Source]

Source link

Advertisement

Leave a Reply

Your email address will not be published. Required fields are marked *

Trending

Exit mobile version