;TEX_X = 512 ;TEX_Y = 512 ;ROUND equ 8 ;SIZE_X = 512 ;SIZE_Y = 512 ;TEX_SHIFT = 9 CATMULL_SHIFT equ 8 ;------------------------------------------------------------------------ ;- Procedure drawing textured triangle using Catmull Z-buffer algorithm - ;------------------------------------------------------------------------ tex_triangle_z: ;----------in - eax - x1 shl 16 + y1 ;-------------- ebx - x2 shl 16 + y2 ;---------------ecx - x3 shl 16 + y3 ;---------------edx - pointer to Z-buffer ;---------------esi - pointer to texture buffer ;---------------edi - pointer to screen buffer ;-------------stack - texture coordinates ;------------------ - z coordinates .tex_x1 equ ebp+4 .tex_y1 equ ebp+6 .tex_x2 equ ebp+8 .tex_y2 equ ebp+10 .tex_x3 equ ebp+12 .tex_y3 equ ebp+14 .z1 equ word[ebp+16] .z2 equ word[ebp+18] .z3 equ word[ebp+20] .tex_ptr equ dword[ebp-4] ; pointer to texture .z_ptr equ dword[ebp-8] ; pointer to z-buffer .x1 equ word[ebp-10] .y1 equ word[ebp-12] .x2 equ word[ebp-14] .y2 equ word[ebp-16] .x3 equ word[ebp-18] .y3 equ word[ebp-20] .dx12 equ dword[ebp-24] .tex_dx12 equ dword[ebp-28] .tex_dy12 equ dword[ebp-32] .dz12 equ dword[ebp-36] .dx13 equ dword[ebp-40] .tex_dx13 equ dword[ebp-44] .tex_dy13 equ dword[ebp-48] .dz13 equ dword[ebp-52] .dx23 equ dword[ebp-56] .tex_dx23 equ dword[ebp-60] .tex_dy23 equ dword[ebp-64] .dz23 equ dword[ebp-68] .scan_x1 equ dword[ebp-72] .scan_x2 equ dword[ebp-76] .scan_y1 equ dword[ebp-80] .scan_y2 equ dword[ebp-84] .cz1 equ dword[ebp-88] .cz2 equ dword[ebp-92] mov ebp,esp push esi ; store memory pointers push edx .tt_sort3: cmp ax,bx ;sort all parameters jle .tt_sort1 xchg eax,ebx mov edx,dword [.tex_x1] xchg edx,dword [.tex_x2] mov dword[.tex_x1],edx mov dx,.z1 xchg dx,.z2 mov .z1,dx .tt_sort1: cmp bx,cx jle .tt_sort2 xchg ebx,ecx mov edx,dword [.tex_x2] xchg edx,dword [.tex_x3] mov dword [.tex_x2],edx mov dx,.z2 xchg dx,.z3 mov .z2,dx jmp .tt_sort3 .tt_sort2: push eax ; and store to user friendly variables push ebx push ecx mov edx,80008000h ; eax,ebx,ecx are ANDd together into edx which means that and edx,ebx ; if *all* of them are negative a sign flag is raised and edx,ecx and edx,eax test edx,80008000h ; Check both X&Y at once jne .tt_loop2_end cmp ax,SIZE_Y jl @f cmp bx,SIZE_Y jl @f cmp cx,SIZE_Y jl @f ror eax,16 ror ebx,16 ror ecx,16 cmp ax,SIZE_X jl @f cmp bx,SIZE_X jl @f cmp cx,SIZE_X jl @f jmp .tt_loop2_end @@: mov eax,dword[.tex_x1] ; texture coords must be in [0..TEX_X(Y)] mov ebx,dword[.tex_x2] mov ecx,dword[.tex_x3] mov edx,eax or edx,ebx or edx,ecx test edx,80008000h jne .tt_loop2_end cmp ax,TEX_X jge .tt_loop2_end cmp bx,TEX_X jge .tt_loop2_end cmp cx,TEX_X jge .tt_loop2_end ror eax,16 ror ebx,16 ror ecx,16 cmp ax,TEX_Y jge .tt_loop2_end cmp bx,TEX_Y jge .tt_loop2_end cmp cx,TEX_Y jge .tt_loop2_end movsx ebx,.y2 ; calc delta sub bx,.y1 jnz .tt_dx12_make xor edx,edx mov ecx,4 @@: push edx loop @b jmp .tt_dx12_done .tt_dx12_make: mov ax,.x2 sub ax,.x1 cwde shl eax,ROUND cdq idiv ebx ; mov .dx12,eax ; dx12 = (x2-x1)/(y2-y1) push eax mov ax,word[.tex_x2] sub ax,word[.tex_x1] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dx12],eax ; tex_dx12 = (tex_x2-tex_x1)/(y2-y1) push eax mov ax,word[.tex_y2] sub ax,word[.tex_y1] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dy12],eax ; tex_dy12 = (tex_y2-tex_y1)/(y2-y1) push eax mov ax,.z2 sub ax,.z1 cwde shl eax,CATMULL_SHIFT cdq idiv ebx push eax .tt_dx12_done: movsx ebx,.y3 ; calc delta sub bx,.y1 jnz .tt_dx13_make xor edx,edx mov ecx,4 @@: push edx loop @b jmp .tt_dx13_done .tt_dx13_make: mov ax,.x3 sub ax,.x1 cwde shl eax,ROUND cdq idiv ebx ; mov .dx12,eax ; dx13 = (x3-x1)/(y3-y1) push eax mov ax,word[.tex_x3] sub ax,word[.tex_x1] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dx12],eax ; tex_dx13 = (tex_x3-tex_x1)/(y3-y1) push eax mov ax,word[.tex_y3] sub ax,word[.tex_y1] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dy12],eax ; tex_dy13 = (tex_y3-tex_y1)/(y3-y1) push eax mov ax,.z3 sub ax,.z1 cwde shl eax,CATMULL_SHIFT cdq idiv ebx push eax .tt_dx13_done: mov bx,.y3 ; calc delta sub bx,.y2 jnz .tt_dx23_make xor edx,edx mov ecx,4 @@: push edx loop @b jmp .tt_dx23_done .tt_dx23_make: mov ax,.x3 sub ax,.x2 cwde shl eax,ROUND cdq movzx ebx,bx idiv ebx ; mov .dx23,eax ; dx23 = (x3-x2)/(y3-y2) push eax mov ax,word[.tex_x3] sub ax,word[.tex_x2] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dx23],eax ; tex_dx23 = (tex_x3-tex_x2)/(y3-y2) push eax mov ax,word[.tex_y3] sub ax,word[.tex_y2] cwde shl eax,ROUND cdq idiv ebx ; mov [.tex_dy23],eax ; tex_dy23 = (tex_y3-tex_y2)/(y3-y2) push eax mov ax,.z3 sub ax,.z2 cwde shl eax,CATMULL_SHIFT cdq idiv ebx push eax .tt_dx23_done: movsx eax,.x1 ;eax - cur x1 shl eax,ROUND ;ebx - cur x2 mov ebx,eax movsx edx, word[.tex_x1] shl edx,ROUND ; mov [.scan_x1],edx ; mov [.scan_x2],edx push edx push edx movsx edx, word[.tex_y1] shl edx,ROUND ; mov [.scan_y1],edx ; mov [.scan_y2],edx push edx push edx movsx edx,.z1 shl edx,CATMULL_SHIFT push edx push edx mov cx,.y1 cmp cx,.y2 jge .tt_loop1_end .tt_loop1: pushad push .z_ptr push .cz1 ; z coords shifted shl catmull_shift push .cz2 mov edx, .scan_y2 sar edx, ROUND push dx mov edx, .scan_x2 sar edx, ROUND push dx mov edx, .scan_y1 sar edx, ROUND push dx mov edx, .scan_x1 sar edx, ROUND push dx push esi ;[.tex_ptr] push cx sar ebx,ROUND push bx sar eax,ROUND push ax call textured_line_z popad mov edx,.dz13 add .cz1,edx mov edx,.dz12 add .cz2,edx mov edx, .tex_dx13 add .scan_x1, edx mov edx, .tex_dx12 add .scan_x2, edx mov edx, .tex_dy13 add .scan_y1, edx mov edx, .tex_dy12 add .scan_y2, edx add eax, .dx13 add ebx, .dx12 inc cx cmp cx,.y2 jl .tt_loop1 .tt_loop1_end: mov cx,.y2 cmp cx,.y3 jge .tt_loop2_end movsx ebx,.x2 shl ebx,ROUND movsx edx,.z2 shl edx,CATMULL_SHIFT mov .cz2,edx movzx edx, word [.tex_x2] shl edx,ROUND mov .scan_x2,edx movzx edx, word[.tex_y2] shl edx,ROUND mov .scan_y2,edx .tt_loop2: pushad push .z_ptr push .cz1 ; z coords shifted shl catmull_shift push .cz2 mov edx, .scan_y2 sar edx, ROUND push dx mov edx, .scan_x2 sar edx, ROUND push dx mov edx, .scan_y1 sar edx, ROUND push dx mov edx, .scan_x1 sar edx, ROUND push dx push esi ;[.tex_ptr] push cx sar ebx,ROUND push bx sar eax,ROUND push ax call textured_line_z popad mov edx,.dz13 add .cz1,edx mov edx,.dz23 add .cz2,edx mov edx, .tex_dx13 add .scan_x1, edx mov edx, .tex_dx23 add .scan_x2, edx mov edx, .tex_dy13 add .scan_y1, edx mov edx, .tex_dy23 add .scan_y2, edx add eax, .dx13 add ebx, .dx23 inc cx cmp cx,.y3 jl .tt_loop2 .tt_loop2_end: .tt_end: mov esp,ebp ret 18 textured_line_z: ;-----in -edi screen buffer pointer ;------------ stack: .x1 equ word [ebp+4] .x2 equ word [ebp+6] .y equ word [ebp+8] .tex_ptr equ dword [ebp+10] .tex_x1 equ ebp+14 .tex_y1 equ ebp+16 .tex_x2 equ ebp+18 .tex_y2 equ ebp+20 .z2 equ dword [ebp+22] ;z1, z2 coords shifted shl CATMULL_SHIFT .z1 equ dword [ebp+26] .z_ptr equ dword [ebp+30] .tex_dx equ dword [ebp-4] .tex_dy equ dword [ebp-8] .dz equ dword [ebp-12] .cz equ dword [ebp-16] .c_tex_x equ dword [ebp-20] ; current tex x mov ebp,esp mov ax,.y or ax,ax jl .tl_quit cmp ax,SIZE_Y jge .tl_quit mov ax,.x1 cmp ax,.x2 je .tl_quit jl .tl_ok xchg ax,.x2 ; sort params mov .x1,ax mov eax,dword[.tex_x1] xchg eax,dword[.tex_x2] mov dword[.tex_x1],eax mov eax,.z1 xchg eax,.z2 mov .z1,eax .tl_ok: cmp .x1,SIZE_X jge .tl_quit cmp .x2,0 jle .tl_quit mov bx,.x2 sub bx,.x1 movsx ebx,bx mov ax,word[.tex_x2] ; calc .dtx sub ax,word[.tex_x1] cwde shl eax,ROUND cdq idiv ebx push eax mov ax,word[.tex_y2] ; calc .dty sub ax,word[.tex_y1] cwde shl eax,ROUND cdq idiv ebx push eax mov eax,.z2 ; calc .dz sub eax,.z1 cdq idiv ebx push eax cmp .x1,0 ; clipping jge @f movsx ebx,.x1 neg ebx imul ebx ; eax = .dz * abs(.x1) add .z1,eax mov .x1,0 mov eax,.tex_dy sar eax,ROUND imul ebx add word[.tex_y1],ax mov eax,.tex_dx sar eax,ROUND imul ebx add word[.tex_x1],ax @@: cmp .x2,SIZE_X jl @f mov .x2,SIZE_X @@: movsx ebx,.y ; calc mem begin in buffers mov eax,SIZE_X mul ebx movsx ebx,.x1 add eax,ebx mov ebx,eax lea eax,[eax*3] add edi,eax ; edi - scr buff shl ebx,2 add .z_ptr,ebx ; z buffer pointer mov cx,.x2 sub cx,.x1 movzx ecx,cx movzx eax,word[.tex_x1] shl eax,ROUND movzx ebx,word[.tex_y1] shl ebx,ROUND push .z1 ; .cz push eax ;.c_tex_x .tl_loop: mov edx,.z_ptr ; eax - temp mov eax,.cz ; ebx - cur tex y shl ROUND cmp eax,[edx] ; ecx - l.lenght jge .skip ; ebx - cur tex_y ; edx - temp mov esi,ebx ; edi - scr buff sar esi,ROUND ; esi - tex_ptr temp shl esi,TEX_SHIFT ; .z_ptr - cur pointer to z buff mov eax,.c_tex_x ; .cz - cur z coord shl CATMULL_SHIFT sar eax,ROUND add esi,eax and esi,TEXTURE_SIZE lea esi,[esi*3] add esi,.tex_ptr movsd dec edi mov eax,.cz mov esi,.z_ptr mov dword[esi],eax ; renew z buffer jmp .no_skip .skip: add edi,3 .no_skip: add .z_ptr,4 mov eax,.dz add .cz,eax mov eax,.tex_dx add .c_tex_x,eax add ebx,.tex_dy loop .tl_loop .tl_quit: mov esp,ebp ret 30