Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 19.3. Ассемблерная версия программы рисования фрагмента текстуры (SLIVER.ASM).
; Эта функция является ассемблерной версией ; аналогичной функции на Си ; Она использует заранее вычисленные таблицы ; для увеличения скорости работы ; //////////////////////////// .MODEL MEDIUM, С; Используем модель MEDIUM .CODE; Начало сегмента кода EXTRN double_buffer; DWORD; Буфер в оперативной памяти EXTRN sliver_texture: DWORD; Указатель на текстуру EXTRN sliver_column: WORD; Текущий столбец текстуры EXTRN sliver_top: WORD; Начальная вертикальная позиция EXTRN sliver_scale: WORD; Общая высота текстуры ЕХТERN sliver_ray: WORD; Текущий столбец экрана EXTRN sliver_clip: WORD; Какая часть текстуры отсекается? EXTRN scale_row; WORD; Номер колонки в таблице; масштабирования PUBLIC Render_Sliver_32; Объявляем функцию общедоступной Render_Sliver_32 PROC FAR С; функция на Си .386; использовать инструкции 80386 процессора push si; сохранить регистры push di les di, doubie_buffer; установить в ES: DI адрес буфера mov dx, sliver_column; загрузить номер строки в DX lfs si, sliver_texture; FS: SI указывает на текстуру ; offset = (sprite-> y «8) + (sprite-> y «6) + sprite-> x mov bx, sliver_top; умножить Y на 320 ; для вычисления смещения shl bx, 8 mov ax, bx shr bx, 2 add bx, ax add bx, sliver_ray; добавить Х add di, bx mov bx, sliver_clip; занести константы в регистры mov ax, sliver_scale add ax, bx Sliver_Loop:; основной цикл ; double_buffer [offset] = work_sprite [work_offset+column] xchg dx, bx; обменять содержимое BX и DX, так как ; только BX можно использовать в качестве ; индексного регистра mov cl, BYTE PTR fs: [si+bx]; получить пиксель текстуры mov es: [di], cl; поместить его на экран xchg dx, bx; восстановить регистры ВХ и DX mov сх, Ьх; готовимся работать с таблицей ; row = scale_table[scale] mov dx, scale_row shl bx, 1 add bx, dx mov dx, WORD PTR [bx]; выбираем масштаб из массива add dx, sliver_column mov bx, cx ; offset += SCREEN_WIDTH; add di, 320; переходим к следующей строке inc bx; инкремент счетчика cmp bx, ax; работа закончена? jne Sliver_Loop pop di; восстанавливаем регистры pop si ret; конец работы Render_Sliver_32 ENDP END В принципе, ассемблерный вариант программы делает то же самое, что и Си-версия. Только в ассемблере используются глобальные переменные, выполняется небольшое отсечение и все работает быстрее. Я был вынужден использовать команды 386-го процессора и регистры дополнительного сегмента, чтобы ускорить работу программы, насколько возможно. Без использования регистров добавочного сегмента я был бы вынужден работать со стеком что немного уменьшило бы скорость выполнения. Теперь я должен извиниться за то, что сказал несколько раньше. Я говорил, что мы должны использовать 386 и 486 процессоры, поскольку они быстрее 8086. Это не было абсолютной правдой. Ведь применять команды, использующие 32-битовые регистры и все прочее в этом роде, можно только с привлечением ассемблера (конечно, если вы не используете DOS-расширитель вместе с 32-битным компилятором). Хотя, опять же, было бы лучше оставить эти части программы простыми и понятными. Оттенение Поиграв немного в Warlock, вы наверняка обратите внимание на отсутствие теней. На самом деле стены могут выглядеть слегка оттененными, но это не так. Просто я подготовил для каждой из стен по два варианта изображения: § Для вертикальных стен я использую одну версию текстуры; § Для горизонтальных стен я применяю просветленное изображение текстуры. Изначально в программе было оттенение, но это уменьшило скорость ее работы примерно на 5 процентов. Но не это волновало меня больше всего. Основные проблемы, связанные с используемой техникой оттенения, возникли с палитрой. Я должен был разбить ее на части внутри зон одного и того же цвета с различными оттенками, но решил, что это было бы чересчур сложно для вас. Если вы хотите иметь оттенение, вы можете создать свою собственную палитру и использовать технические приемы, описанные в шестой главе, «Третье измерение», чтобы выбрать надлежащий оттенок в зависимости от таких параметров, как угол и расстояние. Использование ассемблера Использование ассемблера только иногда является последним средством увеличения быстродействия некоторой части программы до приемлемого уровня. В Warlock я написал около 100 ассемблерных строк для оптимизации только наиболее критичных по времени выполнения кусков игры. Они, конечно, относились к визуализации графики. Существует определенная норма среди программистов игр для ПК: в основном игра пишется на Си, а затем некоторые функции, практически только относящиеся к графике, переписываются па ассемблере. (Если вы вдруг обнаружили, что, применяя ассемблер для реализации искусственного интеллекта или игровой логики, с вашей программой происходит что-то неладное, стоит хорошенько подумать, не вернуться ли к Си.) Я почти уверен, что лучшие мировые программисты могли бы сделать вашу и мою программы на Си значительно быстрее и без использования ассемблера. Запомните это, и когда найдете ассемблер пригодным не только для функций, связанных с графикой и низкоуровневым программированием, признайте, что надо сделать шаг назад (и шаг вперед... словно мы танцуем ча-ча-ча!) и начать сначала. Так или иначе, на ассемблере я переписал только две функции, которые перемещают содержимое дублирующего буфера в видеопамять и рисуют небо и землю (Листинг 19.5). Если уж на то пошло, их ассемблерный вариант занимает всего 5-10 строк.
|