|
realtime truecolor fading using the blitter
in contrast to working in indexed colormodes fading truecolor screens is a mere challange for a standard falcon
with its 16bit wide data bus. this clearly corresponds to the fact that you can't control the colors' brightness
by changing a small color lookup table (sic) per vbl interrupt but you rather must process
the complete screen per pixel, which is why this task isn't basically something to be performed in realtime
or even ontop of another effect.
however, two realtime methods exist, one of which i've been told that it does not work on vga screens and also only
working due to a bug in ataris videl chip, so it doesn't suit my needs (you can read about it nontheless
here ).
the second uses a large table which has shaded scales for each of the possible 65536 colors, but since you can't
fade to abitrary colors using a single table and because each table eats 128kbytes i don't like this method, either -
even worse, it can't be keyframed so it just depends on your falcon's speed how fast it will fade all the way.
desperately trying to finish our beams demo i came up with the idea of
abusing the blitter once again. this time for the fading task since it
outperforms the cpu when it comes to bit and shifting operations and i
have finally come up with a solution. here it goes, it is quite
straightforward imo:
people tend to forget that the blitter actually does have an indexed addressing mode which is a bit limited though,
since only the small range of 16 halfetone registers can be addressed.
this can be achieved by setting the _LineNum register's smudge flag
(bit 5, $ffff8a3c.w). operating in 'smuge mode' a source words' four
LSBs will be interpreted to access a corresponding halftone word only in case you forgot.
it's plain to see that
f(n) = shade/(n*a)
can directly be expressed as series of:
f(n) = f(n-1)-a , f(0) = shade
i assume you're already slowly guessing how this taps into my method.
a screen can be faded by iteratively substracting/adding a (constant) number to each pixel (of course you mustn't forget
to catch overflows seperately for each channel).
using the blitter you can perform a single iteration in 3 passes (one
per red, green and blue), shifting the source data by accordingly
setting up the skew-register. and don't forget to adapt the endmasks
either - and there comes one drawback, you can't have more than 4 bits
accuracy per channel due to the halftone ram's limitations.
you might wonder how this should be keyframed also as the core isn't any diffrent from the table method mentioned above
(i.e. an iterative process)...well this is simple. see, the halftone ram is quite small (just as the CLUT in an indexed
color mode), so you can change the halftone registers in between based on a synced keyframing counter, so now this is
decoupled from machine speed.
notice that you can have very flexible and non linear fadings and you can select single color channels because those are
seperated and so forth.
using large screen resolutions generally isn't recommended though, because the blitter speed is limited as well (16bit
bus, source and destination must be located in st-ram...) but you can skip pixels and or rows per iteration and with the
blitter you get this for free as opposed to the cpu.
'nuff said, here comes my source:
BlitterFade move.l #$20000,d0 ; Initialize blitter
move.l d0,$ffff8a20.w ;
Source X|Y-Increment
move.l d0,$ffff8a2e.w ;
Dest X|Y-Increment
move.w #$103,$ffff8a3a.w
; HOP (halftone only), LOP (source only)
move.w .scale(pc),d0
move.w .keyframe(pc),d1 ;
Keyframing delta (increment during timer interrupt)
clr.w .keyframe
sub.w d1,d0 ;
Fade out
bmi.s .break ;
Reached minimum brightness?
move.w d0,.scale
lsr.w #2,d0 ;
Scale down the timer
movem.l .halftone(pc,d0.w*2),d0-d7 ; Load halftone ram
movem.l d0-d7,$ffff8a00.w
lea.l .rgb(pc),a0
moveq.l
#3-1,d3 ;
3 passes
.passes move.l source(pc),$ffff8a24.w ; *Source
move.l dest(pc),$ffff8a32.w ;
*Dest
movem.w
(a0)+,d0-d2 ; Endmasks
movem.w d0-d2,$ffff8a28.w
move.l #(x_res+1)<<16|y_res,$ffff8a36.w
; XCount|YCount
move.w (a0)+,$ffff8a3c.w ; Start blitter
dbra d3,.passes ;
Fade r, g, b seperately
.break rts
.halftone dcb.w
16,$0000 ;
Linear Fading table
scale set 0
rept 16
dc.w scale
scale set scale+%0001000010000010
endr
dcb.w
16,$ffff ;
Overflow range (all white)
.rgb dc.w $f800,$f800,$f800 ; Endmasks (r,g,b)
dc.w
%1110000000001100 ; Smudge=true, FXSR=false,
NFSR=false, skew
dc.w $07e0,$07e0,$07e0
dc.w %1110000000000111
dc.w $001f,$001f,$001f
dc.w %1110000000000001
.scale dc.w 16<<2 ; Current brightness
- 2005 ray//.tscc. -
|
|