base:spritevectors
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
base:spritevectors [2016-12-09 12:31] – bitbreaker | base:spritevectors [2020-07-28 08:42] (current) – bitbreaker | ||
---|---|---|---|
Line 1: | Line 1: | ||
===== Sprite vectors ===== | ===== Sprite vectors ===== | ||
- | Basically | + | In 2010 Glance presented a vector in there Demo Snapshot, that updated at 50 frames per secons. The technique used therefore was originally named SMGF (Sprite Masking Gap Filling), yet only black blackground was used and no x/ |
+ | |||
+ | So as you see, basically | ||
As a first step, we can expand all sprites in X and Y to achieve more effect area, but this is still not satisfactory. As we inspect the shape of a cube, we notice, that it maximum has 3 edges on the left side and a final edge at the right to separate it from the background. So if we manage to display those 4 edges with 4 sprites, we are already on a good way and only need to change 4 x-positions per rasterline, do we? | As a first step, we can expand all sprites in X and Y to achieve more effect area, but this is still not satisfactory. As we inspect the shape of a cube, we notice, that it maximum has 3 edges on the left side and a final edge at the right to separate it from the background. So if we manage to display those 4 edges with 4 sprites, we are already on a good way and only need to change 4 x-positions per rasterline, do we? | ||
As for the height, we can make use of the sprite stretching trick to make the sprites up to 200 pixels high or even beyond. Happily, this trick also gives us other advantages, as we can switch sprites on/off by omitting a stretch for a single sprite at any given line. Means, our timing over the whole screen will stay the same for each rasterline and thus we can easily use unrolled display code. | As for the height, we can make use of the sprite stretching trick to make the sprites up to 200 pixels high or even beyond. Happily, this trick also gives us other advantages, as we can switch sprites on/off by omitting a stretch for a single sprite at any given line. Means, our timing over the whole screen will stay the same for each rasterline and thus we can easily use unrolled display code. | ||
- | {{: | + | {{: |
+ | |||
+ | This is what sprites look like unexpanded. If only first line is stretched, nothing is displayed, if first line is skipped, display of solid lines start until also this line is skipped in the stretcher. | ||
+ | |||
+ | {{: | ||
First edge being rendered | First edge being rendered | ||
- | {{: | + | {{: |
Second edge being rendered | Second edge being rendered | ||
- | {{: | + | {{: |
Right edge/ | Right edge/ | ||
- | {{: | + | {{: |
First gap sprite with static x position being underlayed | First gap sprite with static x position being underlayed | ||
- | {{: | + | {{: |
And colored like first face | And colored like first face | ||
- | {{: | + | {{: |
Second gap sprite with static x position being underlayed | Second gap sprite with static x position being underlayed | ||
- | {{: | + | {{: |
And colored like first face | And colored like first face | ||
- | {{: | + | {{: |
Still a small gap left, need to underlay another sprite | Still a small gap left, need to underlay another sprite | ||
+ | |||
+ | As the bright green rightmost edge has priority bit set to char underlay, it will vanish under any graphics that uses ink and will just peek through where paper is used. Now as there is a graphic behind that consists of bright green traces and a green background, the rightmost slope sprites only appear bright green on the traces, that are bright green anyway. Cookie cutter ftw \o/ | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Full display with altered colours for better visibility of the different elements the vector is made of. Spot the now red sprite under the traces and the gap sprites being colored differently (and with an ugly palette :-D) | ||
The display code looks like this: | The display code looks like this: | ||
< | < | ||
- | | + | ldy #$ff |
- | ldx #$ff | + | ldx #$ff |
- | lda #$00 ; | + | lda #$00 ; |
- | sta $d017 | + | ;advance one line in sprite -> on/off |
- | eor #$ff | + | sta $d017 |
- | sta $d017 | + | eor #$ff |
- | sty $d006 | + | sta $d017 |
- | lda #$3b ;value is advanced each line to supress badlines and repeat last screen line | + | sty $d006 |
- | stx $d004 | + | lda #$3b ;value is advanced each line to supress badlines and repeat last screen line |
- | ldy #$ff | + | stx $d004 |
- | ldx #$ff | + | ldy #$ff |
- | sta $d011 | + | ldx #$ff |
- | sty $d002 | + | sta $d011 |
- | stx $d000 | + | sty $d002 |
- | nop | + | stx $d000 |
+ | nop | ||
</ | </ | ||
- | to be continued soon... | + | So what does the display code? It stretches all 8 sprites each rasterline, except if $d017 is written with set bits in the first round, then the sprites corresponding |
+ | The x-positions of the sprite are distributed that way that they are valid when being displayed and that writes do not clash and cause display glitches. This works pretty well for the visible range up to 255 (remember, we do not use the MSB, that would just be too much) | ||
+ | ====== Y-movement ====== | ||
+ | The display code is entered at the right offset at the right rasterline and is left after the full height of the object being displayed. The entry can only happen on full charlines, as sprite display and badline supression can only work from there on. So some offsetting wizardry has to be added (rough y position charline-wise, | ||
+ | |||
+ | ====== Precalced flat slopes ====== | ||
+ | |||
+ | Flat slopes are stores in slope tables. To save space, each slope is references with a pointer. Thus, we have the possibility to also reference parts of other slopes in case of matches and save memory. | ||
+ | The slope code plots directly into the ldx/y statements of the display-code one value per codeblock/ | ||
+ | |||
+ | < | ||
+ | sbc (slope), | ||
+ | iny | ||
+ | sta sprite1_pos + .x * dcode_size, | ||
+ | </ | ||
+ | |||
+ | Thus we save on code and only need unrolled code for increasing and decreasing slopes. Way less than for the steep case! | ||
+ | ====== Steep slopes - Bresenham vs. fixed point math ====== | ||
+ | |||
+ | Bresenham can be done pretty fast, but when doing fixed point we are even faster and the accuracy bears still enough potential to not cause glitches. The unrolled code however is pretty much expensive size-wise. It works the same like the flat slope plotting, but 8 replicas are needed, 4 (max. 4 sprites/ | ||
+ | |||
+ | < | ||
+ | sbc frac | ||
+ | bcs + | ||
+ | inx | ||
+ | + | ||
+ | stx sprite1_pos + .x * dcode_size | ||
+ | </ | ||
+ | |||
+ | ====== The data exporter ====== | ||
+ | |||
+ | The nifty part is to write a data exporter that runs through all edges from left to right and finds out about the right order to build up the object with sprites with the right order/ | ||
+ | |||
+ | ====== Future work / outlook ====== | ||
+ | |||
+ | If the badline-supression is done per frame and not per line (but black background then) the ratio of edge building sprites and gap sprites can be shifted towards more edges, as more x-position writes can happen. Also this technique peaks on frames where a lot of nearly 45° slopes happen, else quite some rastertime is left, but on peaks (SID included) only 3 rasterlines are left at maximum size of 160x160. Also if going one pixel beyond in size, 3 gap sprites are needed for a single face and we run out of sprites anyway :-) | ||
+ | |||
+ | ====== Adding the Wurstglanz ====== | ||
+ | |||
+ | to be continued soon... |
base/spritevectors.txt · Last modified: 2020-07-28 08:42 by bitbreaker