Copy Link
Add to Bookmark
Report

3d starfield

The New Outlaw Triad Demo Series, Part 2

DrWatson's profile picture
Published in 
atari
 · 26 Nov 2023

THE OUTLAW TRIAD DEMO-SERIES

PART II

Written by : Vulture/OT
Code in : Pascal/Asm
Topic : 3d starfield

Introduction

Welcome to the Outlaw Triad demo-series! In these series we will be talking about programming demo-effects in either pascal or assembler. Theory behind the effects shall be discussed while a full source code is also provided. In this second release of the Outlaw Triad demo-series we will discuss how to create a 3d starfield in 100% assembler. This is a well known effect in the demo-scene and is used in many demos. It's a great background routine for various effects so let's see how one creates such a starfield. Enjoy!

Theory

A 3d point consists of X,Y,Z values. However, your screen is a 2d plane. This means you must do a 3d to 2d conversion. You can do that with these formulas:

ScreenX := ((X * 256) / Z) + 160 
ScreenY := ((Y * 256) / Z) + 100

I assume ScreenX and ScreenY don't need any further explanation.

Now, setup X to be a random value between -160..160. Your Y value should be setup between -100..100. I choose Z to be 256 at start. When decreasing the Z value, the stars will come towards you. Obviously, when you increase Z, stars will fly away from you. You add 160 and 100 to center the point on the screen. Ok, if the star Z value is 0 (or below), then abort the star and create a new one. Also do this when the star is not in VGA range.

In my code I did these steps:

  • Check Z (and do appropriate action)
  • Delete old star
  • Calculate Screen X
  • Range check X
  • Calculate Screen Y
  • Range check Y
  • Calculate final vga-position (y*320+x)
  • Plot star
  • Save vgaposition (for deletion)
  • Decrease (or increase) Z

Do this for all stars and that's it! You've got a cool 3d starfield!

The little trick in this source is the Random routine. When I first started coding assembler, I examined an example of 3d stars by Draeden of VLA. His example used a chart with the random values pre-calculated in it. This is a nice solution but the disadvantage is that you will always see the same stars because you work with the same random values constantly. That's not too good. So, when I finally got my own random routine, I decided to write my own little 3d starfield. The starting seed value is obtained from the system clock, just like using the Randomize command in Pascal.

Of course you can do various little tricks with 3d starfields. For example, you could rotate all stars so they fly in another direction. What I'm trying to say is that a simple basic 3d starfield ain't nothing special. So go and make something cool using 3d starfields. Try implementing this in other resolutions (like 320*400). Be creative!

Ok, this is all for now. Happy coding!

- Vulture / Outlaw Triad -

Distro Sites

Call our distros to get all our releases.

  BlueNose     World HQ     +31 (0)345-619401 
FireHouse Distrosite +31 (0)528-274176 More distros wanted!
The Force Distrosite +31 (0)36-5346967
MagicWare Italian HQ +39 6-52355532

Contact

Want to contact Outlaw Triad for some reason? You can reach us at our distro sites in Holland. Or if you have e-mail access, mail us:

Vulture (coder/pr) comma400@tem.nhl.nl

Our internet homepage: http://www.tem.nhl.nl/~comma400/vulture.html

These internet adresses should be valid at least till June 1996.

3d starfield
Pin it

STARS3D.ASM

; A 3d starfield in (t)asm 
; By Vulture / Outlaw Triad

DOSSEG ; Init program
.MODEL SMALL
.STACK 200h
.386
.DATA
.CODE
JUMPS

Label Credits Byte
db 13,10,"- -- ------------------------------------------------------------------ -- -"
db 13,10," - An Outlaw Triad Production (c) 1996 -",13,10
db 13,10," CodeùùùùùùùùùùVulture" ,13,10,13,10
db 13,10," -=ð Outlaw Triad Is ð=-",13,10
db 13,10," Vulture(code) þ Dazl(artist) þ Troop(sysop) þ Xplorer(artist)",13,10
db 13,10,"--------------------------------------------------------------------------------",13,10,"$"

Label Palette Byte
db 0,0,0 ; Base color black => R,G,B = 0,0,0
i=63
REPT 16 ; 16 grey shades (from bright to black)
db i,i,i
i=i-4
ENDM

Star_3d STRUC ; Format of star
X DW 0 ; X-position of star
Y DW 0 ; Y-position of star
Z DW 0 ; Z-position of star
Old DW 0 ; Where to erase old star
Star_3d ENDS

StarSize = 8 ; 4 wordz are 8 bytes

MaxStar equ 250 ; What would thiz be, eh? ;-)

Stars Star_3d MaxStar DUP (?) ; Array to hold all star data

Speed equ 1 ; Guess what?

Xoff equ 160
Yoff equ 100 ; To center the star on the vga
Zoff equ 256 ; Z-value at start (distance, try and change this)

Seed dw ? ; Random number seed (obtained from system clock)

; =====================================
; WaitVrt: Waits for vertical retrace
; =====================================

WaitVrt PROC NEAR ; Waits for vertical retrace
mov dx,3dah ; to avoid "snow"
Vrt:
in al,dx
test al,1000b
jnz Vrt
NoVrt:
in al,dx
test al,1000b
jz NoVrt
ret
WaitVrt ENDP

; =================================
; Random: generates random number
; Input : cx = range
; Output: dx = random number
; =================================

Random PROC NEAR ; Reasonably random (can be improved)
mov ax,Seed
add ax,1234 ; Add a random number
xor al,ah ; Shuffle around
rol ah,1
add ax,4321
ror al,1
xor ah,al
mov Seed,ax
xor dx,dx
div cx
ret
Random ENDP

; =================================
; InitStars: sets variables x,y,z
; for all stars
; =================================

InitStars PROC NEAR
xor si,si
mov bx,MaxStar
InitLoop:
mov cx,320
call Random
sub dx,160
mov [Stars.x+si],dx ; Random X (-160..160)
mov cx,200
call Random
sub dx,100
mov [Stars.y+si],dx ; Random Y (-100..100)
mov [Stars.z+si],Zoff ; Reset Z
add si,StarSize
dec bx
jnz InitLoop
ret
InitStars ENDP

; =========================================
; CreateStar: sets variables for new star
; Input : si = pointer to current star
; Output: variables set
; =========================================

CreateStar PROC NEAR
mov cx,320
call Random
sub dx,160
mov [Stars.x+si],dx ; New random X (-160..160)
mov cx,200
call Random
sub dx,100
mov [Stars.y+si],dx ; New random Y (-100..100)
mov [Stars.z+si],Zoff ; Reset Z
ret
CreateStar ENDP

; =====================================
; CalcStars: updates all stars on vga
; =====================================

UpdateStars PROC NEAR
xor si,si ; First star
mov cx,MaxStar ; Do all
MainStarLoop:
push cx

cmp [Stars+si].z,0 ; Reached z=0?
jbe TermStar ; If so, then terminate star

mov di,[Stars.Old+si]
mov byte ptr es:[di],0 ; Delete old star

; === Calc X pos ===
mov ax,[Stars.x+si]
movsx dx,ah
shl ax,8 ; ax = X * 256
mov cx,[Stars.z+si]
idiv cx ; ax = (X * 256) / Z
add ax,Xoff ; ax = ((X * 256) / Z) + Xoff
cmp ax,320 ; Rangecheck X
jae TermStar
mov di,ax

; === Calc Y pos ===
mov ax,[Stars.y+si]
movsx dx,ah
shl ax,8 ; ax = Y * 256
idiv cx ; ax = (Y * 256) / Z
add ax,Yoff ; ax = ((Y * 256) / Z) + Yoff
cmp ax,200 ; Rangecheck Y
jae TermStar
mov bx,320
imul bx
add di,ax

; === Calc color === ; Z in range 0..255
mov ax,[Stars.z+si]
mov cx,16
idiv cx

; === Place dot & save vars ===
mov byte ptr es:[di],al ; Place star
mov [Stars.Old+si],di ; Save spot for erasure
sub [Stars.z+si],Speed ; Decrease Z (go towards viewer)
jmp short ContinueStar ; Do next

TermStar:
call CreateStar ; If z=0 or star<>range then create new 1

ContinueStar:
add si,StarSize ; Point to next star
pop cx
loop MainStarLoop ; Loop until done

ret
UpdateStars ENDP

; === Main Program ===

START:

; === Set pointers ===
mov ax,cs
mov ds,ax ; Set ds
mov ax,0a000h
mov es,ax ; Set es

; === Set random seed ===
xor ah,ah
int 1ah
mov [Seed],dx ; Get random seed from clock

; === Init vga ===
mov ax,0013h
int 10h ; Vgamode 13h 320*200*256 (1 page)

lea si,Palette ; Set palette
mov dx,03c8h
xor al,al
out dx,al
inc dx
mov cx,17*3 ; 17 colors
rep outsb

; === Do starstuff ===
call InitStars ; Set all variables for stars

MainLoop:
call UpdateStars ; Next frame
call WaitVrt ; Wait for vertical retrace
in al,60h ; Check for escape
cmp al,1
jne MainLoop

; === Quit to DOS ===
mov ax,0003h ; Back to textmode
int 10h
lea dx,Credits
mov ah,9
int 21h ; Write string
mov ax,4c00h ; Return control to DOS
int 21h

END START

OUTLAW.INF

                                            °°°°°°°°°°°°° 
°±±±±±±±±±±±±±°
°°°°°°°°°°°°°° °±²²²²²²²²²²²²²±°
°±±±±±±±±±±±±±±° °±²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²±°
°±²²²²²²²²²²²²²²±° °°°±²ÛÉÍÍÍÍÍÍÍÍÍÍͻ۲±°
O °±²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²±°°°° °±±±±²Ûº²²²²²²²²²²²ºÛ²±°° O
U °±²ÛÉÍÍÍÍÍÍÍÍÍÍͻ۲±±±±°°±²²²²²Ûº²²²Ú---¿²²²ºÛ²±±±° U
T °±²Ûº²²²²²²²²²²²ºÛ²²²²²±±²ÛÛÛÛÛÛº±±²À---Ù²²±ºÛ²²²²±° T
L °±²Ûº²²²Ú---¿²²±ºÛÛÛÛÛ²²²ÛÉÍÍͻۺ±±±ÉÍÍÍ»±±°ºÛÛÛÛÛ²±° L
A °±²Ûº±²±|ÉÍÍÏ»²±ºÉÍÍÍ»ÛÛÛÛº²²²ºÛº±±°ºÉÍÍÊ»°°ºÉÍÍͻ۲±° A
W °±²Ûº±±±|º²²²º°±ºº²ÉÍÊÍÍÍ͹²²²ÌÍÊ»±°ºº²²²º°°ºº²²²ºÛ²±° W
ú °±²Ûº±°±À¶²²²º°°ºº±º²²²²²²º²±±º²²ÌÍͼº²²²ÌÍͼº²D±ºÛ²±° ú
T °±²Ûº°°±°º±±²º°°ºº±ÈÍËÍÍ»²º±±±ÌÍͼÛÛÛº²²²ºÉÍ»º²’±ºÛ²±° T
R °±²ÛÈÍÍÍ͹±±±ÌÍͼº±±²ºÛÛº²º±°±ÈÍÍÍÍÍ͹²±±ºº±ºº±Z±ºÛ²±° R
I °±²ÛÛÛÛÛº±°°ÈÍÍͼ±±±ºÛÛº±º°°°°±±±±°°º±±±È¼±È¼±œ±ºÛ²±° I
A °±²²²²²Ûº°°°°°°°±±±±ºÛÛº±ÈÍËÍÍÍÍÍÍÍͺ±°°±±°°°±±±ºÛ²±° A
D °±±±±²ÛÈÍÍÍÍÍÍÍÍÍÍͼÛÛº±°°ºÛÛÛÛÛÛÛÛÈÍÍÍÍÍÍÍÍÍÍͼ۲±° D
°°°±²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²ÛÈÍÍͼ۲²²²²²²ÛÛÛÛÛÛÛÛÛÛÛÛÛ²±°
°±²²²²²²²²²²²²²²±²ÛÛÛÛÛ²±±±±±±²²²²²²²²²²²²²²±°
°±±±±±±±±±±±±±±°±²²²²²±°°°°°°±±±±±±±±±±±±±±°
Ú-------¿ °°°°°°°°°°°°°°-°±±±±±°---¿ °°°°°°°°°°°°°° Ú-------¿
ÚÁ¿ ÖÁ------------°------°°---°°°°°----|--------°°°---------Á· ÚÁ¿
|V| º °² ù ù ° º |D|
|U| ÕÍͼ ±°°² ú ú GeT YaR ÈÍ͸ Ãþ´
|L| ɾ AnD YeT ANoTHeR ±° OnE 3d STarFieLD HaNDs On aLL Ô» |A|
|ç| º QuALiTy ReLeaSE CoMinG uP... ° The oTHa º Ãþ´
|U| ȸ FrOm OUtLaW TRiAD ú ú ú °² ReLeaSeS Õ¼ |Z|
|R| ÔÍ» ù ù ù ±°²² nOw! ÉÍ; Ãþ´
|î| º ° | | | ±² º |L|
ÀÂÙ ÓÂ---------°²--------------------------------------------½ ÀÂÙ
À------Ù °°±² À------Á------Ù À-------Ù
±±

Ú--------------------------------------------------------------------¿
| |
Ú------------------------------------------------------------------------¿
Ú-|-|-ù ú-|-|-¿
| | : ThE SeCoND ReLeaSE Of The OUtLaW TRiAD DeMo TRaiNeR SeRieS : | |
| | ú A TeXTfiLe AnD SouRCeCoDeS To 3d STaRfieLDs iN aSSeMbleR ú | |
| | THiS MiGht JuSt Be oNe oF The SMaLLeST SouRCeS To dO A STarFieLD | |
| | WaNNa tRy To IMproVe It? | |

| | CaLL THeSe OUtLaW TRiAD BoArDZ tO GeT MoRe STuFF: | |
ú ú ú ú
| | BlueNose +31 (0)345-6194011 | |
FireHouse +31 (0)528-2741761
| | The Force +31 (0)36-53469671 | |
| | MagicWare +39 6-523555321 | |
| | | |
| | : OpEn FoR MoRe! : | |
À-|-|-ú ú-|-|-Ù
À------------------------------------------------------------------------Ù
À--------------------------------------------------------------------Ù
Btw, AlSo CHeCK The InTeRnET FoR OUtLaW TRiAD ReLeaSeS!

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT