Techdemo for full color alpha compositing with 3D. Support for anti-aliasing on lines can be easily added using Wu's Algorithm. The cover doesn't properly capture the palette and OVR changes.
Source: https://bitbucket.org/AMcBain/tic-80-public/src/main/compositing.bugfix.lua.tic
pke1029
|
This is incredible! Care to share how this is rasterized and how many colours can be displayed at once?
|
Starchaser
|
You can download the cart from the source link in the description or via the "download cartridge" link above the cover. It's covered by the Fair License.
tl;dd*: It's 15 colors per line + 15 per frame, not counting background or knockout colors. I think even if you can do the full 16 in OVR I only use 15, iirc. The rendering is the reverse of what you might expect. OVR is used to draw almost everything, and the standard frame buffer is used to draw any remaining colors that overflow the per-line max. Also this comment skips some stuff. Like, there's code to avoid drawing the same pixel twice in two cases to avoid getting spurious colors due to the overlaps resulting from drawing that don't exist in the original "pure" shapes. This effect is a lot faster if you turn that detection off! I also suspect this is not the most optimized as I went for ease of my own understanding. Colors are already arrays of 4 numbers, but triangles are tables with x, y, and z properties. Every frame does the following: 0. Run OVR() effects 1. Clear screen and pixel table 2. Copy shapes and apply transforms. 3. Combine outer and nested shapes into one shape (simplifies rendering to just sorting triangles) 4. Draw shape(s) to pixel table one triangle at a time 5. Post process pixel table to calculate per-line palettes and overflow pixels 6. Draw overflow pixels to screen -- Part 0 in detail -- Interesting to note here is that OVR() runs **before** TIC() which I was surprised to find. The docs are correct now since I filed a ticket about that last year. ;) 0a. Iterate every line with changed pixels in the pixel table 0b. For that line, set the palette to that line's pre-calculated palette (step 5) 0c. For every pixel in that line reduce all values by baking in the alpha then draw the resulting color -- Part 3 in detail -- 3a. Protect triangle from 3D to 2D 3b. Draw triangle to the screen (any non-bg/knockout color will do) 3c. Iterate all pixels within the 2D projected bounds of triangle 3d. Add any detected pixels' true color (from the triangle, not the screen buffer) to the pixel table 3e. Update max drawn vertical extents of the pixel table 3f. Clear the drawn area (I use rect(); cls() might be slightly faster) -- * too long; didn't download |
Starchaser
|
Oops, that should be "Part 4 in detail" not 3.
|
Starchaser
|
Because the magic happens after what is written to the pixel table, you can do wireframes instead of fills (per triangle even) with antialiasing.
1. Implement Wu's Algorithm 1a. Write results directly to the pixel table (not screen) 1b. 1 - Wu's brightness value = alpha value (in my code) 2. Update drawTriangle() to detect wireframe flag on a triangle 3. Draw wireframe triangles as three lines with Wu's Algorithm Here's a live example of that: https://woof.tech/@asmcbain/111702199396243562 I do recommend using division and rounding to fix the number of transparency steps with Wu's to something more manageable, as there's not enough colors to handle more than like 3 stops a shape as complicated as an icosahedron. |