home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
SKY.ZIP
/
README.TXT
< prev
next >
Wrap
Text File
|
1996-02-14
|
5KB
|
125 lines
This archive contains some example code to draw a sky plane, as
seen in Tim Clarke's MARS demo.
The code is for Turbo Pascal and MASM, but should be easily portable
to C/TASM since all the important routines are in assembly language.
(I don't have a real mode C compiler, so I couldn't write a C wrapper).
This is essentially a constant-z texture-mapping problem, but since
the sky plane is only in one orientation a number of optimisations
can be made, making the final routine quite fast (under 5 cycles/pixel
on a 486). This routine also uses 2x2 dithering on the sky map, which
makes it look _much_ better :). A similar technique can be used to
dither the ground in Tim Clarke's algorithm, which again reduces banding
noticeably.
The idea for the dithering algorithm was obtained from Chris Green, in
a post on rec.games.programmer:
Path: newsroom.utas.edu.au!munnari.oz.au!network.ucsd.edu!usc!cs.utexas.edu!uunet!olivea!gossip.pyramid.com!pyramid!cbmvax!chrisg
From: chrisg@cbmvax.cbm.commodore.com (Chris Green)
Newsgroups: rec.games.programmer
Subject: Re: Help w/Gouraud Shading
Message-ID: <C8tGzC.8Dz@cbmvax.cbm.commodore.com>
Date: 18 Jun 93 12:21:11 GMT
References: <1vlao2$nsg@msuinfo.cl.msu.edu> <1993Jun16.160757.8197@pony.Ingres.COM>
Reply-To: chrisg@cbmvax.cbm.commodore.com (Chris Green)
Organization: Commodore, West Chester, PA
Lines: 86
In article <1993Jun16.160757.8197@pony.Ingres.COM> edg@Ingres.COM (Ed Goldman) writes:
>klein@egr.msu.edu (Jeffrey Klein) writes:
>: In article <1993Jun15.170045.8377@pony.Ingres.COM> edg@Ingres.COM (Ed Goldman) writes:
>:
>: Calculate the color with higher precision than you can display, then
>: use the remainder to dither between the two closest.
>:
>
>Thanks to everyone who responded! As it turns out, the above was the correct
>answer to what I wanted to do. I realized that I already had the color
>in a higher precision in a temp fixedpoint color variable, and it was
>just a matter of adding a few lines of code to dither. Looks great now!
If you have to add ANY lines of code to the loop to dither, then
you're wasting time:
mov al,bh ; output color(even)
add bx,bp ; color(even)+=delta
mov ah,dh ; output color(odd)
add dx,bp ; color(odd)+=delta
stosw ; and store two pixels
First compute startcolor, and deltacolor as normal for
gouraud shading. Then, conditionally take a one-pixel step
in order to get the destination pointer word-aligned.
Now you want to change the iteration variables to
handle even and odd separately. set color(odd)=startcolor+delta+0.5.
set deltacolor=deltacolor*2 and go (and of course handle the case
when there is an odd number of pixels to render). What you
end up with is a +.5 bias on odd pixels. So, if you were rendering
a long run of pixels of color value $0180 (1.5), you
will end up with outputs of 1,2,1,2,1,2.. for a perfect 2x2 dither.
To do the vertical dither, reverse the sense of odd and
even pixels based upon the low bit of (startx xor ycoord).
The same effect can be achieved by using two deltas and
one iterator as well. The net result is the same: 2x2 dither
"for free".
Cool gouraud trick #2:
instead of using (for instance) linear ranges in the palette
(colors 0-15 for gray, for instance), use scattered ranges.
If you want 16-color ranges, use color 00, 10, 20, 30,... f0 for 16 grays.
Then, you can generate _4_ pixels with the following 386 code:
add eax,ebp ; colors += deltas
mov ebx,eax ; copy colors
and ebx,edx ; mask out lower values
or ebx,esi ; and OR in range selector
mov [edi],ebx ; 4 pixels!
In our example, we would set edx (mask) = f0f0f0f0.
esi would be zero. The deltas are packed in 4.4 format into
ebp.
To handle negative deltas, you run the loop in the opposite
direction. Only four bits of fraction is kinda small, but it works
in many cases. Extra precision can be gained back for small deltas
by using one aditional integrator which adds 0x01010101 to
the color variable when it overflows:
dec cl ; count down whole numbers
jnz no_inc_color
add eax,0x01010101
mov cl,clsave
no_inc_color:
add eax,ebp ; colors += deltas
mov ebx,eax ; copy colors
and ebx,edx ; mask out lower values
or ebx,esi ; and OR in range selector
mov [edi],ebx ; 4 pixels!
this routine is only used when the magnitude of deltacolor/dx is
small.
--
*-------------------------------------------*---------------------------*
|Chris Green - Graphics Software Engineer - chrisg@commodore.COM f
| Commodore-Amiga - rutgers!cbmvax!chrisg n
|My opinions are my own, and do not - icantforgettheimpression o
|necessarily represent those of my employer.- youmadeyouleftaholeinthe r
|"A screaming comes across the sky..." - backofmyhead d
*-------------------------------------------*---------------------------*
Well, what can you say? Thanks, Chris.
I hope you find this code useful. If you see any glaring errors or
optimisations I missed (TANSTATFC), please let me know...
Mark Mackey.
mdm1004@cus.cam.ac.uk (I'll be here until December 1996 at least).