Эффект RADIAL BLUR Если вы захотите подставить какую-нибудь другую картинку, то проделайте следующую последовательность действий: нарисуйте или считайте другую двух-цветную картинку в PaintBrush сохраните ее как монохромную картинку потом как 256-цветную и вот эту 256 цветную картинку можно подставлять вместо intel.bmp. Размер картинки естественно должен составлять 320x200, и bmp-файл не должен быть упакован, иначе у вас ничего не получиться. Идея radial blur`a проста: блюрить по кругу, то есть как в обычном случае блюрения по одной координате, но с переходом к полярным координатам. Выберем центр нашего блюра, пусть это будет, для простоты, центр экрана. Допустим разрешение экрана 320x200. Тогда центр экрана придется на точку с координатами (160,100). Сместим начало координат в эту точку: x'=x-160; y'=y-100. Теперь рассмотрим точку М с координатами, например, (185,65), эта точка будет нашей текущей точкой, на примере ее я расскажу как выбирать вторую точку, чтобы сблюрить их цвета. Координаты в нашей новой системе координат, у этой точки будут M'(25,-35). Вектор этой точки тоже будет иметь координаты (25,-35). Теперь надо решить, как находить вектор, по которому мы будем находить вторую точку. Есть два варианта: Изменить длину вектора нашей текущей точки так, что-бы она лежала в пределах от 1 до некоторого значения max, которое вы выберите сами, на свой вкус. (Обычно выбирают 8 чтобы использовать сдвиги). Зафиксировать длину вектора. (Опять же выбор длины остается за вами, а но можно опять выбрать 8). Здесь используется второй вариант. Вычислим по ней координаты вектора N, округляя до целого: N.x= 4, N.y= -6. Тогда координаты искомой точки P будут находиться так: P(x'-N.x,y'-N.y). То есть, P(21,-29). Теперь осталось сблюрить точки M и P, и записать получившиеся значение в точку M. Осталось рассказать в каком порядке надо обрабатывать точки, чтобы получить правильное, радиально-сблюренное изображение. Разобьем экран на четыре сектора: Рассмотрим сектор #1: Обрабатывать пиксели по координате X, надо в порядке: 1,2,3..., а по координате Y, по-строчно, в порядке: A,B,C... . По такому же принципу надо поступать и в других секторах: обрабатывать сектор по строкам, начиная с ближней к центру блюра, а в строке тоже двигаться от центра блюра. Естественно, линии с координатами центра блюра надо тоже обработать. Ну вот и все, загляните в прилагаемые исходники, что бы посмотреть, как можно прооптимизировать этот эффект. Взято здесь, текст программы немного переделан, в результате СОМ-файл уменьшился с 1242 байт до 810 байт
Код (ASM): ; masm dos com # .model tiny .code .386 org 100h WIDTH_SCREEN equ 320 HEIGHT_SCREEN equ 200 SCREENSIZE equ WIDTH_SCREEN*HEIGHT_SCREEN MEMBLOCKSIZE equ SCREENSIZE/16 IMPUT_STATUS_0 equ 3DAh ;регистр статуса ввода 0 VGA_SEGMENT equ 0A000h time equ dword ptr [bp-4] n equ dword ptr [bp-8] y equ word ptr [bp-10] vx equ word ptr [bp-12] p1 equ word ptr [bp-14] screen equ word ptr [bp-16] pics equ word ptr [bp-18] bbx equ dword ptr [bp-22] bby equ dword ptr [bp-26] start: mov sp,0DF0h mov ah,4Ah ;ADJUST MEMORY BLOCK SIZE (SETBLOCK) mov bx,0DFh ;ES = segment address of block to change int 21h ;BX = new size in paragraphs enter 26,0 mov time,0 mov bx,MEMBLOCKSIZE ;4000 mov ah,48h ;ALLOCATE MEMORY int 21h ;BX = number of 16-byte paragraphs desired mov screen,ax ;screen[64000] mov bx,MEMBLOCKSIZE ;4000 mov ah,48h ;ALLOCATE MEMORY int 21h ;BX = number of 16-byte paragraphs desired mov pics, ax ;pics[64000] mov bx,MEMBLOCKSIZE*2 mov ah,48h ;ALLOCATE MEMORY int 21h ;BX = number of 16-byte paragraphs desired mov es,ax ;es=sqr sqr[128000] mov fs,ax ;fs=sqr add ax,4000 mov gs,ax ;gs=sqr+64000/16 mov ax,13h int 10h ;initsqr-------------------------------------- mov si,WIDTH_SCREEN-1 a0: mov y,HEIGHT_SCREEN-1 @@: mov ax,y mul ax movzx ecx,ax;ecx=y*y movsx eax,si mul eax add eax,ecx;eax=x*x + y*y mov n,eax fild n fsqrt fistp n mov eax,n;n=sqrt(x*x + y*y) shr eax,3 inc eax mov n,eax;n=(sqrt(x*x + y*y))/8 + 1 imul di,y,WIDTH_SCREEN mov ax,si add di,ax;di=y*320 + x cwd idiv word ptr n;ax=x/((sqrt(x*x + y*y))/8 + 1) mov gs:[di],al mov ax,y cwd idiv word ptr n;ax=y/((sqrt(x*x + y*y))/8 + 1) stosb ;mov es:[di],al dec y jns @b dec si jns a0 ;readbmp----------------------------------------------------------- mov dx, offset aIntel_bmp ; "intel.bmp" mov ax, 3D00h ; OPEN DISK FILE WITH HANDLE int 21h; DS:DX -> ASCIZ filename mov bx,ax xor cx,cx mov dx,1078;заголовок и палитра BMP-файла mov ax,4200h; MOVE FILE READ/WRITE POINTER (LSEEK) int 21h ; AL = method: offset from beginning of file push ds mov ds, pics mov di,HEIGHT_SCREEN-1 @@: imul dx,di,WIDTH_SCREEN mov cx,WIDTH_SCREEN mov ah, 3Fh; READ FROM FILE WITH HANDLE int 21h; BX = file handle, CX = number of bytes to read, DS:DX -> buffer dec di jnz @b push ds pop es;es=pics di=0 pop ds mov ah, 3Eh; CLOSE A FILE WITH HANDLE int 21h; BX = file handle mov cx,64000 inc si;si=0FFFFh+1=0 a1: lods byte ptr es:[si];c=fgetc(in) dec al jz @f or al,-1 @@: not al stosb ;if(c==1)pics[x+320*y]=255 else pics[x+320*y]=0 loop a1 ;blurpics----------------------------------------------------- mov di, WIDTH_SCREEN mov cx,63040 @@: movzx ax, byte ptr es:[di-WIDTH_SCREEN] add al, byte ptr es:[di-1] adc ah, 0 add al, byte ptr es:[di+1] adc ah, 0 add al, byte ptr es:[di+WIDTH_SCREEN] adc ah, 0 shr ax, 2 stosb loop @b ;setcolortable-------------------------------------------- mov cx, 255 @@: mov bl, 255 sub bl, cl shr bl, 2 mov dx, 3C8h mov al, cl;color mov ah, bl;red out dx, ax inc dx mov al,bl;green out dx,al out dx,al dec cx jns @b ;----------------------------------------------------------- a2: fld time fadd const005 fst time; time+=0,05 fmul const1_1;time*1,1 fadd const1_5;time*1,1+1,5 fsin ;sin(time*1,1+1,5) fmul const120;120*sin(time*1,1+1,5) fistp bbx ;bbx=120*sin(time*1,1+1,5) add bbx,WIDTH_SCREEN/2;bbx=160+120*sin(time*1,1+1,5) fld time fmul const08;time*0,8 fadd const1_1;1,1+time*0,8 fcos ;cos(1,1+time*0,8) fmul const90;90*cos(1,1+time*0,8) fistp bby ;bby=90*cos(1,1+time*0,8) add bby,HEIGHT_SCREEN/2;bby=100+90*cos(1,1+time*0,8) ;100 и 160 координаты середины экрана ;copypicsvirtual push ds mov ds,pics mov es,screen xor si,si xor di,di mov cx,SCREENSIZE/4 rep movsd pop ds ;radialblurscreen xor dx,dx mov bx,word ptr bby dec bx ; bx = bby - 1 imul di,bx,WIDTH_SCREEN; di = (bby - 1)*320 add di,word ptr bbx; di = (bby - 1)*320 + bbx dec di ; di = (bby - 1)*320 + bbx - 1 a3: mov cx,word ptr bbx @@: mov ah,0 mov al,es:[di] mov p1,ax mov si,dx mov al,gs:[si] mov vx,ax ; vx = gs[t] lods byte ptr fs:[si] imul ax,WIDTH_SCREEN; ax=320*fs:[t] mov si,di add si,vx add si,ax mov ah,0 lods byte ptr es:[si];movzx ax,byte ptr es:[si] add ax,p1 shr ax,1 stosb;mov es:[di], al dec di dec di inc dx dec cx jnz @b sub di,WIDTH_SCREEN add di,word ptr bbx mov ax,WIDTH_SCREEN sub ax,word ptr bbx add dx,ax dec bx jns a3 mov ax,word ptr bby dec ax imul di,ax,WIDTH_SCREEN add di,word ptr bbx xor dx,dx mov cx,word ptr bby a4: mov bx,word ptr bbx @@: movzx ax, byte ptr es:[di] mov p1,ax mov si,dx movzx ax,byte ptr gs:[si] mov vx,ax movzx ax,byte ptr fs:[si] imul ax,WIDTH_SCREEN mov si, di sub si, vx add si, ax movzx ax, byte ptr es:[si] add ax, p1 shr ax, 1 stosb inc dx inc bx cmp bx,WIDTH_SCREEN jl @b sub di,WIDTH_SCREEN*2 add di,word ptr bbx mov ax,word ptr bbx add dx,ax dec cx jnz a4 mov cx,word ptr bby imul di,cx,WIDTH_SCREEN add di,word ptr bbx dec di xor dx,dx a5: mov bx,word ptr bbx @@: movzx ax, byte ptr es:[di] mov p1,ax mov si,dx movzx ax, byte ptr gs:[si] mov vx,ax movzx ax, byte ptr fs:[si] imul ax,WIDTH_SCREEN mov si, di add si, vx sub si, ax movzx ax, byte ptr es:[si] add ax, p1 shr ax, 1 stosb;mov es:[di], al dec di dec di inc dx dec bx jnz @b add di, WIDTH_SCREEN add di,word ptr bbx mov ax, WIDTH_SCREEN sub ax,word ptr bbx add dx,ax inc cx cmp cx,HEIGHT_SCREEN jl a5 mov cx,word ptr bby imul di,cx,WIDTH_SCREEN add di,word ptr bbx xor dx,dx a6: mov bx,word ptr bbx @@: movzx ax, byte ptr es:[di] mov p1,ax mov si,dx; t mov ah,0 mov al,gs:[si] mov vx,ax lods byte ptr fs:[si] mov dx,si imul ax,WIDTH_SCREEN mov si, di sub si, vx sub si, ax movzx ax, byte ptr es:[si] add ax, p1 shr ax, 1 stosb inc bx cmp bx,WIDTH_SCREEN jl @b mov ax,word ptr bbx add di,ax add dx,ax inc cx cmp cx,HEIGHT_SCREEN jl a6 ;blurscreen -------------------------------------- mov di, WIDTH_SCREEN mov cx,63040 loc_104E7: movzx ax, byte ptr es:[di-WIDTH_SCREEN] add al, byte ptr es:[di-1] adc ah, 0 add al, byte ptr es:[di+1] adc ah, 0 add al, byte ptr es:[di+WIDTH_SCREEN] adc ah, 0 shr ax, 2 stosb loop loc_104E7 ;copyvirtualscreen mov dx, IMPUT_STATUS_0 WaitVerticalSync:in al,dx test al,8 jz WaitVerticalSync WaitNotVerticalSync:in al,dx test al,8 jnz WaitNotVerticalSync mov cx,SCREENSIZE/4 xor si,si push ds push es pop ds xor di,di push VGA_SEGMENT pop es rep movsd xor ax,ax mov ds,ax mov ax,ds:[41Ah] sub ax,ds:[41Ch] pop ds jz a2 exit: mov ax,3 int 10h ; - VIDEO - SET VIDEO MODE int 20h const005 dd 0.05 const08 dd 0.8 const1_1 dd 1.1 const1_5 dd 1.5 const90 dd 90.0 const120 dd 120.0 aIntel_bmp db 'intel.bmp',0 end start