Из журнала Deja Vu #0A, Кемерово, 2000 __________________________________________ (C) Max/CYBERAX Software/BDA Some GFX by Alex/CBX/BDA __________________________________________ _____________ __________ _____ ___ __ \__(_)_ /___ /_ _____ __________(_)____________ _ __ / / /_ /_ __/_ __ \_ _ \__ ___/_ /_ __ \_ __ `/ _ /_/ /_ / / /_ _ / / // __/_ / _ /_ / / / /_/ / /_____/ /_/ \__/ /_/ /_/ \___/ /_/ /_/ /_/ /_/_\__, / _______ __ _____________ /____/ ____/ // /___ __ \_|__ \ _ _ _ __/_ / / /___/ / /_ _ __/ / /_/ /_ __/ /_//_/ \____/ /____/ Да-а... Вторая часть как-то плохо пи- шется. Если первую вместе с исходником я набил за неделю, то работа над продолжени- ем затянулась аж на пол-года... То в лом, то некогда... Ну да ладно, приступим. На этот раз я загружу вас следующими вещами: - "цветные" точки и линии - градиентная заливка - "256-цвЕтная" графика - конверсия 256 colors -> 2 & 4 colors - примеры использования данной технологии Перед прочтением рекомендую обратиться к первой части опуса, которую можно найти в 7-м номере DEJA VU. В принципе, вторая часть статьи ничего нового из себя не представляет и является как бы следствием первой. 1) Color dots Я, конечно, несколько загнул с этим термином. Точки по-прежнему будут 2-х цветными. Просто ставиться они будут с ве- роятностью пропорциональной "цвету". Цвет у нас будет изменяться от 0 до 64. Пусть нам нужно изобразить точку с цве- том 25. Заполним обычный спектрумовский экран текстурой с номером 25 (текстуры у нас 8x8). На другом экране включим пиксел с нужными координатами. Теперь если два этих экрана сложить по AND, мы и получим так называемую "цветную" точку. На практике, конечно, лучше использо- вать другой алгоритм,дающий, тем не менее, аналогичный результат. Допустим необходи- мо поставить точку с координатами (X,Y) и цветом C. Последовательность действий бу- дет такой: 1) Находим остаток от деления координаты X на 8 (MX=X AND 7) 2) Аналогично с координатой Y (MY=Y AND 7) 3) Из матрицы D8 извлекаем число N с коор- динатами (MX,MY) 4) Если C>N, то включаем пиксел с коорди- натами (X,Y), иначе - выключаем Фактически, это не что иное как алго- ритм конверсии картинки из DV#07. Теперь исходник: ;----------------------------------------- ;IN: A - COLOR (0...64) ; B - X, C - Y DOT EX AF,AF LD H,DOT_TAB+1 LD L,B; X-координата LD A,(HL); A=X/8 INC H LD L,C; Y-координата OR (HL); мл. байт адреса LD E,A INC H LD D,(HL); ст. байт адреса INC H LD H,(HL); строка матрицы LD L,B; X-координата EX AF,AF; цвет CP (HL) RET C; не ставим точку LD H,DOT_TAB LD A,(DE); извлекаем бит OR (HL); ставим точку LD (DE),A RET ;Эту штуку надо вызвать для инициализации: DOT_INI LD HL,DOT_TAB*256 LD A,#80 DOT1 LD (HL),A; таблица битов RRCA INC L JR NZ,DOT1 INC H DOT2 LD A,L; (HL)=L/8 RRCA RRCA RRCA AND 31 LD (HL),A INC L JR NZ,DOT2 INC H LD DE,#4000 LD B,#C0 DOT3 LD (HL),E; таблица адресов INC H LD (HL),D DEC H INC D LD A,D AND 7 JP NZ,$+13 LD A,E ADD A,32 LD E,A JR C,$+6 LD A,D SUB 8 LD D,A INC L DJNZ DOT3 DOT4 LD (HL),E INC H LD (HL),E DEC H INC L JR NZ,DOT4 INC H INC H DOT5 LD A,L; таб. ст. адресов AND 7 строк матрицы ADD A,H INC A LD (HL),A INC L JR NZ,DOT5 INC H EX DE,HL LD HL,MATRIX LD C,8 DOT6 PUSH BC,DE; каждую строку LD C,8 матрицы повто- LDIR ряем 8 раз EX (SP),HL LD C,#F8 LDIR POP HL,BC DEC C JR NZ,DOT6 RET MATRIX DB 1,33,9,41,3,35,11,43 DB 49,17,57,25,51,19,59,27 DB 13,45,5,37,15,47,7,39 DB 61,29,53,21,63,31,55,23 DB 4,36,12,44,2,34,10,42 DB 52,20,60,28,50,18,58,26 DB 16,48,8,40,14,46,6,38 DB 64,32,56,24,62,30,54,22 DOT_TAB EQU #C0; ст. адр. таблицы ;----------------------------------------- "Что за шнягу он тут толкает ? Разве это цветные точки ?" - скажут некоторые. Да, одну такую точку цветной не назо- вешь. А вот когда их много - другое дело ! Вот я взял в Обероне исходник ALK'а для построения фрактала Мандельброта, заменил в нем атрибутную точку на свою и получил такую картинку:
2) Color lines Color lines - это вам не какая-нибудь игрушка, а процедура рисования "цветной" линии. От обычной линии она отличается только тем, что процедура точки заменена на процедуру "цветной" точки. Данная реализация не отличается особым быстродействием, поэтому для практического использования ее желательно оптимизнуть, а лучше - написать с нуля. Для упрощения (или усложнения - кому как...) экспериментов координаты линии и цвет берутся из BASIC'а (функция пользова- теля). Посему не забывайте приводить их к целому виду ! ;----------------------------------------- ORG #8000 ENT CALL DOT_INI EXX PUSH HL LD HL,(#5C0B); адрес пар-ров LD BC,4 ADD HL,BC LD D,(HL); Выковыриваем X1 LD C,8 ADD HL,BC LD E,(HL); Y1 ADD HL,BC LD A,(HL); X2 EX AF,AF ADD HL,BC LD A,(HL); Y2 ADD HL,BC LD B,(HL); C LD L,A EX AF,AF LD H,A LD A,B LD (COLOR+1),A LD (COLOR1+1),A LD (COLOR2+1),A EX DE,HL CALL LINE POP HL EXX RET DOT LD H,DOT_TAB+1 LD L,B LD A,(HL) INC H LD L,C OR (HL) LD E,A INC H LD D,(HL) INC H LD H,(HL) LD L,B COLOR LD A,63 CP (HL) RET C LD H,DOT_TAB LD A,(DE) OR (HL) LD (DE),A RET LINE LD A,E SUB L JR NC,NOEXCH EX DE,HL NEG NOEXCH LD C,A; Y2-Y1 LD LX,0 ORG $-1 INC D LD A,D SUB H JR NC,X_OK LD LX,0 ORG $-1 DEC D NEG X_OK EX DE,HL CP C JR C,DY>DX DX>DY LD B,A; B=A=X2-X1, C=Y2-Y1 OR A JR Z,NO_LIN1 RRA LD H,B EX AF,AF LD A,LX LD (COM1),A EX AF,AF DRW_LP1 EX AF,AF PUSH DE EXX POP BC LD H,DOT_TAB+1 LD L,B LD A,(HL) INC H LD L,C OR (HL) LD E,A INC H LD D,(HL) INC H LD H,(HL) LD L,B COLOR1 LD A,64 CP (HL) JR C,NODOT1 LD H,DOT_TAB LD A,(DE) OR (HL) LD (DE),A NODOT1 EXX COM1 INC D EX AF,AF SUB C JR NC,NOINC1 ADD A,H INC E NOINC1 DJNZ DRW_LP1 NO_LIN1 PUSH DE EXX POP BC CALL DOT EXX RET DY>DX LD B,C LD C,A LD A,B; B=A=Y2-Y1, C=X2-X1 OR A JR Z,NO_LIN2 RRA LD H,B EX AF,AF LD A,LX LD (COM2),A EX AF,AF DRW_LP2 EX AF,AF PUSH DE EXX POP BC LD H,DOT_TAB LD L,B LD A,(HL) INC H LD L,C OR (HL) LD E,A INC H LD D,(HL) INC H LD H,(HL) LD L,B COLOR2 LD A,63 CP (HL) JR C,NODOT2 LD H,DOT_TAB LD A,(DE) OR (HL) LD (DE),A NODOT2 EXX INC E EX AF,AF SUB C JR NC,NOINC2 ADD A,H COM2 INC D NOINC2 DJNZ DRW_LP2 NO_LIN2 PUSH DE EXX POP BC CALL DOT EXX RET DOT_INI LD A,#C9 LD (DOT_INI),A ; Остальная часть инициализатора такая же, ;как и для точки, поэтому я ее не привожу. LD HL,DOT_TAB*256 LD A,#80 ... ... RET MATRIX ... ... ... DOT_TAB EQU #C0 ;----------------------------------------- Вот пример работы вышеприведенной процедуры (градиентная заливка). Нечто подобное используется в качестве текстуры для менюх в DEJA VU.
Строится это при помощи следующей программы (предварительно подгрузите файл col_line.C, который содержит саму процедуру линии): 1 DEF FN L(A,B,C,D,E)=USR 32768 2 LET Y=0 : LET X1=256-64 : LET X2=X1 : LET Y1=0 : LET Y2=0 3 LET C=40+14*SIN (PI*Y/32)+12* SIN (PI*Y/20) 4 RANDOMIZE FN L(X1,Y1,X2,Y2, INT C) 5 IF X2=255 THEN LET Y2=Y2+1 6 IF Y1=191 THEN LET X1=X1+1 7 LET Y=Y+1 : IF X2<255 THEN LET X2=X2+1 8 IF Y1<191 THEN LET Y1=Y1+1 9 IF X1<256 THEN GO TO 3 10 PAUSE 0 BASIC, конечно, это ламерство, но для черновых экспериментов и так сойдет... Еще примерчик: Деелаем надпись на pC или chr-шрифтами на Спектруме (печаталка by Delirium Tremens- RULEZ!):
Генерируем градиентную текстуру:
Складываем обе картинки по AND:
А можно и так: Берем исходное изображение:
Поочередно сдвигаем его во все 4 стороны и складываем результаты по OR с исходным изображением:
Проксориваем полученное с исходным изобра- жением:
Генерим текстуру:
Складываем по AND текстуру и исходную картинку:
Складываем результаты 3-го и 5-го шагов по OR:
Я все подумываю для себя сделать некое подобие Photoshop'овского редактора градиентной заливки, чтобы не извращаться в бейсике с синусами. Т.е. задаешь значе- ние яркости в нескольких точках, а в ос- тальных она интерполируется автоматически. Для этого дела очень подходят сплайны Безье (см. Rush #02). Вообще, сплайны - удобная вещь. Применение им можно найти в самых разных областях, особенно в графике. Ну ладно, пойдем дальше. Вот еще нес- колько примерчиков. Это - пример псевдо-3D изображения:
Если менять фазу синуса, то можно полу- чить неплохую анимацию (правда, в realtime это вряд ли выйдет). А это что-то типа флага:
Обратите внимание на плавные переходы освещенности, которая на самом деле ника- кая не освещенность, а всего лишь синусои- дальная добавка к цвету. Т.е. данная технология позволяет весьма простыми средствами добиваться не таких уж и плохих результатов. Причем все происхо- дит без применения pC/Amiga и без ручного труда в графическом редакторе (хотя не- большая правка все же не помешает). 3) 256 colors Подведем некоторые итоги. Все вышеопи- санное при наличии определенного воображе- ния позволяет создавать достаточно впечат- ляющие картинки. Однако у метода есть один недостаток - после рендеринга с изображе- нием сложно производить какие-либо манипу- ляции по причине его двуцветности. Т.е. рендеринг картинки должен происходить за один проход и все эффекты должны быть ре- ализованы сразу. Поэтому можно несколько усложнить дан- ный метод. Ничто (кроме объема памяти) не мешает ставить точки в промежуточный эк- ранный буфер, причем на одну точку можно отводить целый байт. Вот что это дает: 1) 256 цветов (точнее, градаций серого) на точку. Или же можно сделать 64 цвета, а оставшиеся 2 бита использовать либо как маску, либо как альфа-канал (4 гра- дации прозрачности). 2) Можно делать многопроходный рендеринг. 3) Появляется возможность взаимообмена grayscale-картинками с тем же pC. Недостатком является необходимость пос- тоянно конвертить все в битмап, дабы полу- чить представление о созданной картинке. Процесс создания изображения может быть таким: - конвертим с какой-либо платформы или ге- нерируем по некоторому алгоритму непос- редственно на Spectrum'е 256-цветные текстуры. - помещаем в буфер одну из текстур в ка- честве background'а. - строим на фоновой текстуре, к примеру, 3D-объект и накладываем на его грани другие текстуры, можно и с учетом осве- щения (благо, в чанках все это уже реа- лизовано). Можете хоть заливку Фонга за- релизить, или рэйтрэйсинг... - при необходимости, делаем BLUR или ANTI- ALIASING - далее можно поизвращаться с полученным изображением в 2D, например: а) прогнать какой-либо фильтр б) деформировать в) по некоторому закону сложить с другим изображением, в т.ч. и с использова- нием карты прозрачности. г) сделать, скажем, надписи с масочкой д) сверху наложить (накласть :) освеще- ние (напр. bump light). е) в общем, смотри Adobe Photoshop, меню фильтров :) - после всех этих процедур (если, конечно, от картинки что-то останется...) необхо- димо сконвертить все это в битмап или в в 2-х экранный interlaced mode. Предвижу реплики типа: "Аа-а, фигня, я все это на своем pC за полчаса забабахаю!" Да, конечно, если он есть. Если же нет - читайте дальше. Конечно, все это дело вам придется сна- чала закодить, т.к. это всего лишь теория. От меня же будет всего две процедурки, ко- торые пригодятся вам на финальной стадии создания рулезных картинок - конверсии. Вообще, для конверсии можно юзать выше- приведенную процедуру точки. Правда она не понимает цвета с кодом >64, но это не страшно. Просто делите 8-битный код цвета на 4 и вызывайте эту прогу. Однако можно конвертить и в 2 битплана (см. Dithering #1, двухплановые текстуры). Для этого я написал процедуру 193-хцветной точки. Здесь уже не обойдешься делением, поэтому приходится по табличке равномерно отображать диапазон цветов 0...255 в 0... 192, и только потом ставить точку. ;----------------------------------------- ORG #6000 ENT ;IN: A - COLOR (0...255) ; B - X, C - Y ;Перед использованием процедуры точки не- ;обходимо однократно: ;- вызвать INIT ;- очистить экран 5-го банка ; (PAPER=0, INK=X, BRIGHT=1, FLASH=0) ;- очистить экран 7-го банка ; (PAPER=0, INK=X, BRIGHT=0, FLASH=0) ;- включить 7-й банк (и не убирать его ; при вызове PSET!) PSET EXX LD L,A LD H,DOT_TAB+#18 LD A,(HL) EX AF,AF INC H LD C,(HL) EXX ; LD H,DOT_TAB+12 LD L,B LD A,(HL) INC H LD L,C OR (HL) LD E,A INC H LD D,(HL) INC H LD H,(HL) LD L,B EX AF,AF CP (HL) ; EXX LD A,C EXX LD H,A LD A,(DE) JR C,NO_DOT INC H INC H NO_DOT OR (HL) LD (DE),A SET 7,D INC H LD A,(DE) OR (HL) LD (DE),A RET INIT LD HL,DOT_TAB*256 CALL DOT1 CALL DOT1 CALL DOT1 CALL DOT2 CALL DOT1 CALL DOT2 CALL DOT2 CALL DOT1 CALL DOT2 CALL DOT1 CALL DOT2 CALL DOT2 ;+12 DOT3 LD A,L RRCA RRCA RRCA AND 31 LD (HL),A INC L JR NZ,DOT3 ;+13 INC H LD DE,#4000 LD B,#C0 DOT4 LD (HL),E INC H LD (HL),D DEC H INC D LD A,D AND 7 JP NZ,DOT4_1 LD A,E ADD A,32 LD E,A JR C,DOT4_1 LD A,D SUB 8 LD D,A DOT4_1 INC L DJNZ DOT4 ;+15 INC H INC H LD L,B DOT5 LD A,L AND 7 ADD A,H INC A LD (HL),A INC L JR NZ,DOT5 ;+16 INC H EX DE,HL LD HL,MATRIX LD C,8 DOT6 PUSH BC,DE LD C,8 LDIR EX (SP),HL LD C,#F8 LDIR POP HL,BC DEC C JR NZ,DOT6 ;+24 EX DE,HL LD BC,DOT_TAB*256 LD A,#80 LD DE,#FFC0 DOT7 LD (HL),C INC H LD (HL),B DEC H SUB E JR NC,$+4 ADD A,D INC C EX AF,AF LD A,C DOT9 SUB 65 JR C,DOT8 INC A LD C,A INC B INC B INC B INC B JR DOT9 DOT8 EX AF,AF INC L JR NZ,DOT7 RET DOT1 XOR A DOT1_1 LD (HL),A INC L JR NZ,DOT1_1 INC H RET DOT2 LD A,#80 DOT2_1 LD (HL),A RRCA INC L JR NZ,DOT2_1 INC H RET MATRIX DB 1,33,9,41,3,35,11,43 DB 49,17,57,25,51,19,59,27 DB 13,45,5,37,15,47,7,39 DB 61,29,53,21,63,31,55,23 DB 4,36,12,44,2,34,10,42 DB 52,20,60,28,50,18,58,26 DB 16,48,8,40,14,46,6,38 DB 64,32,56,24,62,30,54,22 DOT_TAB EQU #70 ;----------------------------------------- Вот как сконвертится полная палитра цветов 0...255 с использованием двух экра- нов:
Вторая процедура предназначена для нас- тройки яркости и контраста 256-цветного изображения. Использовать ее можно либо как фильтр, т.е. применяя к изображению в буфере, либо встроив в процедуру конверсии (при этом она будет влиять только на ре- зультат конвертации но не на исходную кар- тинку). Результат ее работы очень близок к ре- зультату действия аналогичной опции в Adobe Photoshop. Отличия связаны с неточ- ным рассчетом таблицы контраста. ;----------------------------------------- ORG #6000 ENT BRG_TAB EQU #7000; Таблица яркости CTR_TAB EQU #7100; Таблица контраста CALL INIT ;Инициализатор необходимо вызывать каждый ;раз после смены значений яркости/контрас- ;та (переменные BRIGHT и CONTRST). ;После инициализации можно применять пре- ;образование: LD L,100; Цвет пиксела ; (например 100) ;Преобразуем: LD H,BRG_TAB&H LD D,CTR_TAB&H LD E,(HL) LD A,(DE) ;Теперь в аккумуляторе находится преобра- ;зованный цвет пиксела. ;Так попиксельно необходимо прогнать все ;изображение. RET BRIGHT DB 0-60&L ;Переменная задает значение приращения яр- ;кости. Если число больше нуля (1...127) - ;яркость повышается; если меньше нуля ;(-128...-1) - понижается; 0 - не изменя- ;ется. CONTRST DB 200 ;А здесь содержится изменение контраста. ;Контрастность можно только повысить. Чем ;меньше это число, тем контрастнее резуль- ;тат. Значение 255 картинку почти не ме- ;няет. INIT LD HL,BRG_TAB LD A,(BRIGHT) LD B,A LD A,#FF SUB B RLA SBC A,A LD C,A MK_BRG1 LD A,L ADD A,B LD (HL),A RRA XOR B RLA JR NC,$+3 LD (HL),C INC L JP NZ,MK_BRG1 LD HL,CTR_TAB XOR A MK_CTR1 LD (HL),A INC L JP P,MK_CTR1 CPL MK_CTR2 LD (HL),A INC L JR NZ,MK_CTR2 LD B,H LD C,L LD A,(CONTRST) LD E,A LD D,0 LD A,#FF SUB E SRL A LD H,A LD L,D MK_CTR3 LD A,C LD C,H LD (BC),A LD C,A ADD HL,DE INC C JP NZ,MK_CTR3 RET ;----------------------------------------- Для иллюстрации работы процедуры приве- ду примерчик. На пЦ былo взятo изображение в формате BMP grayscale. Затем при помощи вышеприведенной процедуры и процедуры "цветной" точки сконверчено с разными зна- чениями яркости/контраста:
И совсем круто все выглядит на двух битпланах (использовалась процедура двух- плановой точки):
На этом, пожалуй, и остановимся. Конеч- но, можно было еще рассказать о визуализа- ции 3D-графиков функций типа SIN (R)/R с расчетом освещения в каждой точке (смот- рится просто офигительно!) или о генера- ции background'ов, но, как говорится, хо- рошего по-немногу... Где-то в недрах приложения вы найдете несколько программок. Помимо basic'ов, рендерящих некоторые картинки из данной статьи, для любителей XAS'а там лежат и такие файлы: BRG_CTR.X - настройка яркости и контраста COL_DOT.X - исходник точки 2BP_DOT.X - исходник двухбитплановой точки COL_LINE.X - исходник линии col_line.C - откомпилированная линия -----------------< 27.08.2000, Кемерово >-