Из журнала 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, Кемерово >-