PDA

Просмотр полной версии : О рисовании прямых



Higgins
26.12.2009, 13:29
Здесь несколько раз поднималась тема рисования прямых, конкретных реализаций и способов их сравнения.

Я составил сравнительный график для трех упоминавшихся реализаций, для горизонтально ориентированных линий. По вертикали отложены количества тактов на рисование одной линии. По горизонтали отложены количества горизонтальных фрагментов (прогонов), из которых составлены линии.

Все линии выводились из верхнего левого угла к правому краю, всего 192 линии длиной 256 точек.

Задержки ULA по памяти не учитывались.

* * *

Третий и четвертый графики -- для вертикально ориентированных линий плюс часть горизонтально ориентированных до большой диагонали.

* * *

Ссылки по теме:
http://zx.pk.ru/showthread.php?t=5905
http://zx.pk.ru/showthread.php?t=358

* * *

UPDATE: Графики для вертикально и горизонтально ориентированных теперь слиты вместе, для наглядности. По горизонтали отложены номера тестов от 1 до 447 включительно. В тестах 1...192 строятся линии (0,0)-(255, 0...191). В тестах 193...447 -- линии (0,0)-(254...0, 191).

Кроме того, добавлен график для процедуры DRAW_LINE в ROM. Поскольку строить линии в двух нижних строках знакомест она не умеет, в тестах 1...192 шестнадцать последних тестов не выполняются, а тесты 193...447 строят линии (0,0)-(254...0,175).

Далее, разбирательство в происхождении "пилы" на графике для реализации Vitamin показало, что ее ("пилы") там нет. :) Видимо, в прежние графики попала таблица значений, полученная еще до отключения задержек по памяти. На общий вид и основные значения на графике, однако, это никак не повлияло.

На всякий случай добавлены использованные исходные тексты и получившиеся таблицы. Исходные тексты транслировались ассемблером pasmo. В таблицах в первой колонке указан номер теста, во второй -- количество тактов. Для пропущенных тестов вместо количества тактов стоит знак вопроса ("?").

Titus
26.12.2009, 14:17
Лучше б тест оценивал не количество фрагментов, а количество точек. Т.е. чтобы можно было примерно сказать, сколько тактов на точку в среднем тратит та или иная процедура рисования линии.

Vitamin
26.12.2009, 14:19
Круто. А тест вертикально-ориентированных линий? Т.е. (если я правильно понял суть имеющегося теста), "закрасить" вторую половину экрана.

Higgins
26.12.2009, 16:27
Лучше б тест оценивал не количество фрагментов, а количество точек. Т.е. чтобы можно было примерно сказать, сколько тактов на точку в среднем тратит та или иная процедура рисования линии.

Ну, из этих графиков можно сделать такую оценку.

Пара замечаний:

1) Смысл такого подхода к тестированию именно в том, что он не дает никаких усредненных значений, т.е. его результаты никаких не зависят от конкретных выборок.

2) Я смотрю на этот тест не как на бенчмарк, а как на характеристический тест, который отражает фундаментальные свойства реализаций. В этом смысле графики важны не абсолютными значениями, которые показывают реализации, а самими видами кривых как вообще, так и локально, на интересующих участках.

Почему этот тест является характеристическим, на этот счет есть (у меня в голове) довольно длинное теоретическое обоснование, но, во-первых, стоит ли оно времени, потраченного на его изложение, а во-вторых, для людей в теме оно должно быть достаточно очевидным. Судя по ответу, Vitamin, например, уже для себя оценил идею. :)


А тест вертикально-ориентированных линий? Т.е. (если я правильно понял суть имеющегося теста), "закрасить" вторую половину экрана.

Да, есть желание сделать то же для вертикально ориентированных. Попробую.

Не совсем половину. Вертикально ориентированные получаются с координатами конца от (0,191) до (190,191), т.е. всего 191 линия 192 точки каждая.

Titus
26.12.2009, 18:48
1) Смысл такого подхода к тестированию именно в том, что он не дает никаких усредненных значений, т.е. его результаты никаких не зависят от конкретных выборок.

2) Я смотрю на этот тест не как на бенчмарк, а как на характеристический тест, который отражает фундаментальные свойства реализаций. В этом смысле графики важны не абсолютными значениями, которые показывают реализации, а самими видами кривых как вообще, так и локально, на интересующих участках.

В таком случае этот тест сам в себе, им нельзя пользоваться, чтобы сравнить, быстрее иная процедура рисования линии, нежели представленные в этом тесте, или медленнее.

Мы в свое время пользовались методикой сравнения в тактах на точку. Сразу было понятно, какая линия быстрее, какая медленнее.

Vitamin
26.12.2009, 19:51
Не совсем половину. Вертикально ориентированные получаются с координатами конца от (0,191) до (190,191), т.е. всего 191 линия 192 точки каждая.
Ну почему же- у тебя были линии с координатами конца от (255,0) до (255,191). А теперь надо от (0,191) до (255,191). Или подразбить его на два теста- (0,191)...(191,191) и (192,191)...(255,191).

Higgins
26.12.2009, 20:07
В таком случае этот тест сам в себе, им нельзя пользоваться, чтобы сравнить, быстрее иная процедура рисования линии, нежели представленные в этом тесте, или медленнее.

Мы в свое время пользовались методикой сравнения в тактах на точку. Сразу было понятно, какая линия быстрее, какая медленнее.

Попробую объяснить на пальцах: одна и та же процедура может быть "быстрее" на одной линии и "медленнее" на другой. Среднее значение тактов на точку будет зависить от соотношения тех и других в выборке. Данных на графике достаточно, чтобы оценить среднее значение тактов на точку для любой заданной выборки.

---------- Post added at 20:07 ---------- Previous post was at 19:56 ----------


Ну почему же- у тебя были линии с координатами конца от (255,0) до (255,191). А теперь надо от (0,191) до (255,191). Или подразбить его на два теста- (0,191)...(191,191) и (192,191)...(255,191).

Линия (0,0)-(255,191) -- горизонтально ориентированная (delta X > delta Y).

Вторую часть (192,191)...(255,191) сделать можно, но длина линий будет уже другой, это придется учитывать. Плюс, все линии в этом диапазоне попадают в ту же категорию горизонтальной ориентированных линий с отношением DX/DY меньше двойки (длины прогонов 1-2 точки), что и линии в диапазоне (255,128) ... (255,191), поэтому в общем-то эти линии уже оказываются представленными в графиках.

Vitamin
26.12.2009, 20:19
поэтому в общем-то эти линии уже оказываются представленными в графиках.
Ну значит только первую часть- вертикально ориентированные.

Titus
26.12.2009, 20:23
Попробую объяснить на пальцах: одна и та же процедура может быть "быстрее" на одной линии и "медленнее" на другой. Среднее значение тактов на точку будет зависить от соотношения тех и других в выборке. Данных на графике достаточно, чтобы оценить среднее значение тактов на точку для любой заданной выборки.
Какой же я невнимательный. Очевидно фрагменты - это и есть точки)

Vitamin
26.12.2009, 20:30
Очевидно фрагменты - это и есть точки)
Не. Фрагмент- горизонтальная последовательность точек. Именно поэтому их 1 для полностью горизонтальной линии, 2 для линии с разницей концов в 1 пиксел и т.д. до 191.

Higgins
26.12.2009, 21:29
Ну значит только первую часть- вертикально ориентированные.

Да, постараюсь сделать.


Какой же я невнимательный. Очевидно фрагменты - это и есть точки)

В общем да, длина линии в точках разбивается на горизонтальные фрагменты соответственно протяженности линии по вертикали (DY). Для любой линии количество фрагментов равно (DY + 1). Длина фрагментов колеблется между значениями [DX/DY] и [DX/DY + 1]. И все линии, по которым составлены графики длиной 256 точек независимо от количества фрагментов, на которые они разбиты. Поэтому для линии с заданной геометрией можно легко оценить количество тактов на точку. Значит, и для любого набора линий с заданной геометрией можно сделать такую оценку.

К слову о вертикально ориентированных. Штука в том, что, коротко говоря, на Спектруме, из-за нерегулярного и несимметричного относительно осей строения видеопамяти, даже вертикально ориентированные линии нужно рассматривать в терминах горизонтальных прогонов. То есть понятно, что никакая самая эффективная реализация не отменит того факта, что соседние точки группируются в байты видеопамяти по горизонтали и нет способа оперировать сразу несколькими точками по вертикали, либо даже просто оперировать вертикальными фрагментами так же эффективно, как горизонтальными.

В этом один из главных принципов, на которых стоит модель процедуры рисования линии, для которой этот тест собственно и придуман.

Higgins
29.12.2009, 15:03
В первом сообщении добавлены графики для вертикально ориентированных.

Vitamin
29.12.2009, 15:50
Очень интересная картина для SE: видно, что меняется тангенс, но резкого скачка нет.

Higgins
30.12.2009, 17:01
Очень интересная картина для SE: видно, что меняется тангенс, но резкого скачка нет.

Да, в купе с подозрительно гладкой кривой в целом дает пищу для подозрений в том, что есть еще куда стремиться. Все-таки такую пилу логичнее ожидать внизу графика, а не наверху.

Lethargeek
31.12.2009, 01:37
Да, в купе с подозрительно гладкой кривой в целом дает пищу для подозрений в том, что есть еще куда стремиться. Все-таки такую пилу логичнее ожидать внизу графика, а не наверху.
У меня когда-то были мысли сыграть на периодичности
Чтобы чем длиннее, тем больше выигрыш

alone
01.01.2010, 02:26
Типичная линия в более-менее культурном проволочном 3D будет не 256 пикселей, а порядка 10. Этот случай и надо оптимизировать.

Lethargeek
02.01.2010, 00:01
Типичная линия в более-менее культурном проволочном 3D будет не 256 пикселей, а порядка 10. Этот случай и надо оптимизировать.
Нет на Спеке типичных линий. Как всегда придется процедуру подгонять под задачу.

10 пикселей это очень мало, разве что объект довольно далеко.
И зачем оптимизировать его отрисовку, если тормоза начнутся ближе?

Higgins
02.01.2010, 02:29
У меня когда-то были мысли сыграть на периодичности
Чтобы чем длиннее, тем больше выигрыш

Вообще, любая прямая в растре будет регулярной 1) на уровне точек, которые складываются в прогоны и 2) на уровне прогонов, которые точно так же регулярно складываются в, скажем так, части линии.

О прогонах уже говорили. А вот на эти части можно посмотреть так. Пусть требуется построить в растре некоторую горизонтально ориентированную прямую с [DX/DY] = 1. Теперь представим себе в том же растре соответствующую диагональ (с соотношением DX/DY точно равным единице, т.е. DX = DY). Так вот искомую прямую можно получить заменив в диагонали часть точек на горизонтальные прогоны длиной в две точки (помним, что прогоны в такой линии у нас могут быть только длиной в одну или две точки). Таким образом каждый такой прогон в две точки будет увеличивать DX диагонали на одну точку. То есть для искомой прямой нужно добавить (DX-DY) таких прогонов. При этом, чтобы прямая была похожа на прямую, все эти длиные прогоны должны быть расположены, насколько позволяет шаг растра, на одинаковом расстоянии. Сбалансированная линия, в терминах таких частей линий, означает одинаковое, опять же, насколько это позволяет растр, отстояние длинных прогонов от концов линии. Так вот последовательность коротких прогонов в купе с одним длинным дает одну часть линии.

Арифметика получается такая. Всего в горизонтально ориентированной линии с геометрией R = [DX/DY] = 1 будет N = (DX - DY) частей. Размер части по вертикали будет равен PY = (DY / N). Если отношение PY нецелое, тогда линия будет составлена из частей двух размеров, а именно [PY] и [PY] + 1. Большая часть (размером [PY] + 1) -- это малая часть плюс один короткий прогон. Размер части по горизонтали в любом случае будет равен PX = PY + 1.


Типичная линия в более-менее культурном проволочном 3D будет не 256 пикселей, а порядка 10. Этот случай и надо оптимизировать.

Даже если так, что специального может сделать процедура рисования прямой для линий из десяти точек?

Lethargeek
02.01.2010, 04:20
Не, я не о том. Вот смотри, периодичность может возникнуть по трем параметрам:
- по укладыванию в знакоместную строку по вертикали
- по укладыванию в байт по горизонтали
- по длине фрагментов

Может даже по всем трем сразу, причем порядок вложенности любой
Так что сначала выбираем подходящую процедуру

Фокус в том, чтобы честно отрисовать только один период
одновременно запоминая последовательность операций
(конкретно как это сделать - вопрос отдельный)
чтобы потом по порядку печатать байты-фрагменты
без сопутствующих расчетов и проверок

alone
02.01.2010, 14:25
Нет на Спеке типичных линий. Как всегда придется процедуру подгонять под задачу.

10 пикселей это очень мало, разве что объект довольно далеко.
И зачем оптимизировать его отрисовку, если тормоза начнутся ближе?
10 пикселей - нормально для объекта приличной сложности (я не говорю про всякий примитив типа кубика или там тетраэдра).
Чем ближе, тем больше деталей должно показываться на объекте, соответственно больше линий, но всё равно мелких.
Ещё надо оптимизировать отсечение линий по границам экрана.

Lethargeek
03.01.2010, 05:18
10 пикселей - нормально для объекта приличной сложности (я не говорю про всякий примитив типа кубика или там тетраэдра).
Где ж ты видал на Спектруме "объекты приличной сложности"?
Кляча сдохнет уже во время расчета координат :rolleyes:

psndcj
03.01.2010, 07:41
Brainwave - 2001 - Stellar Contour [CC001]

Lethargeek
03.01.2010, 21:45
Не тянет. Один к тому же.

alone
03.01.2010, 22:24
Тормозит не расчёт координат, а рисование линий. Координатами можно навертеть хоть 200 вершин за фрейм. А вот линий столько не нарисуешь даже близко.

Lethargeek
04.01.2010, 03:08
Ты случайно демы с играми не попутал?
200+ матричных операций с приличной точностью :rolleyes:
Двадцати не вытянешь!

psb
04.01.2010, 03:18
лол:) вы еще поспорьте на что-нить:)
что мешает использовать в играх технику демок? ну, я понимаю, что для некоторых эффектов надо много памяти, но для поворота точки-то много не надо. и всяко можно вытянуть больше 20. уж около ста, я думаю, точно можно. а то и 200. по заготовленным таблицам.

Lethargeek
04.01.2010, 07:04
что мешает использовать в играх технику демок?
Необходимость в рилтайме адекватно реагировать на юзверя :p


ну, я понимаю, что для некоторых эффектов надо много памяти, но для поворота точки-то много не надо.
Для "честных" трехмерных операций как нужно умножать вектора и матрицы 4x4
Сколько там в 1/200 кадра? 350 тактов? Ну-ну :)
А "нечестные" в игрушках не прокатят
(разве что трехмерность урезанная)

psb
04.01.2010, 11:12
350 тактов?
типа того. имея заготовленные таблицы с синусами не вижу проблем сделать это. и реакция на юзверя тут не при чем, раз считать в реалтайме.
то бишь задача повернуть 200 точек за фрейм - наверняка решаемая, но бесполезная из-за медленной отрисовки.

Lethargeek
05.01.2010, 04:30
типа того. имея заготовленные таблицы с синусами не вижу проблем сделать это.
Что ты собрался делать с таблицей синусов за 350 тактов на вершину? Вокруг одной оси поворачивать? Бугога.


и реакция на юзверя тут не при чем, раз считать в реалтайме.
Юзверь вносит стохастические помехи в стройный процесс расчетов, потому приходится считать общий случай.
Умножение вектора на матрицу преобразования емнип 16 умножений, 12 сложений с нужной точностью.

psb
05.01.2010, 10:12
Вокруг одной оси поворачивать? Бугога.

бугогакай дальше, фигли...

Юзверь вносит стохастические помехи в стройный процесс расчетов
т.е. ты вот умножаешь, а в это время юзверь тебе мешает, нажимая кнопки:))) лол:))) не смеши мои новые тапочки:)

с нужной точностью.
круто сказал: с нужной:)))))))) сразу все стало понятно, в 350 тактов никак не улезть:)

Sinus
05.01.2010, 11:24
Умножение вектора на матрицу преобразования емнип 16 умножений, 12 сложений с нужной точностью.

не могу не вмешаться :)

9 умножений и 9 сложений на точку. если пренебречь дрожащими вершинами, то точность не важна.

и единоразово (на всю сцену) рассчёт матрицы - 25 умножений и 6 сложений/вычитаний.

это в самом общем случае для абсолютно любого объекта.
гораздо более ресурсоёмкие операции - отсечения заведомо не отрисовыемых частей полигонов.

----

самое быстрое и не пригодное для реальных условий умножение:



; BC = A * L
; A от 0 до 255, L от 0 до 255
; DE должно быть == #4000

add a,'MULTBL
ld h,a
ld c,(hl)
add hl,de
ld b,(hl)


итого 7+4+7+11+7 = 36 (причём это наиболее быстрое и наименее пригодное в реальной жизни умножение)
36 * 9 = 324 такта тольно на умножение

с реальным умножением (пусть оно и умжножает от -128 до 127 по таблице), будет гораздо больше.
так что ни 200 ни 100 точек за фрейм "честно" не повернуть.

----

с другой стороны в 3D игре важно не насколько оно фреймово, а просто насколько быстро.
и вот тут есть разница - поворот 2х точек намного быстрее отрисовки линии, как не крути.

Higgins
05.01.2010, 15:20
9 умножений и 9 сложений на точку. если пренебречь дрожащими вершинами, то точность не важна.

Есть хитрости. Во-первых, координату глубины можно считать, когда и если ее вообще нужно считать, не для каждой вершины, а для всего объекта. То есть три из этих девяти умножений могут быть опущены.

Во-вторых, если шаг координатной сетки велик (т.е. количество делений на каждой из осей небольшое), можно сначала посчитать проекции радиус-векторов до всех точек осей, а затем получить координаты вершин простыми сложениями.

Наверное, можно и еще что-нибудь выдумать.

Sinus
05.01.2010, 15:54
это "честный" поворот.


Во-первых, координату глубины можно считать, когда и если ее вообще нужно считать, не для каждой вершины, а для всего объекта. То есть три из этих девяти умножений могут быть опущены.

мм. и изомерическая проекция? нафих.

----

а если делать прекальк до для не сложных объектов можно обойтись от 4х до 6ти умножений (про это писалось в каком-то Spectrum Expert). но эти хитрости для демок больше, а тут разговор про игры идёт.

alone
05.01.2010, 17:49
Качаем сорцы The Link и в эффекте с ёжиком смотрим вертелку JTN'а. Оставляем 2 оси из 3, как раз будет около 350 тактов. Есть также аналогичная вертелка Vitamin'а.

Titus
05.01.2010, 18:10
Качаем сорцы The Link и в эффекте с ёжиком смотрим вертелку JTN'а. Оставляем 2 оси из 3, как раз будет около 350 тактов. Есть также аналогичная вертелка Vitamin'а.
Прикольная дема, жаль, практически под абстрактное железо - пентагон 1024кб с 110000 тактами и GS. Вот сделать это же под обычный пентагон 128кб ;-)

Sinus
06.01.2010, 12:53
Оставляем 2 оси из 3
про что и говорилось изначально (начиная с поста #25).

в деме можно и 2 оси оставить, и одну, и прекальк сделать, и т.д.
а в игрушке низзя :)

Lethargeek
16.01.2011, 05:27
Higgins, есть вопросы:

1) Мерил целиком, или только основной цикл (от первой поставленной точки до последней)?
2) Точки только ставились, или можно было ксорить заменой нескольких кодов?
3) Сколько процедурки жрут памяти именно в рабочем состоянии?

Тут, возможно, скоро будет новый кандидат на тестирование ;)
13000 на диагональ многовато...

Higgins
16.01.2011, 14:29
1) Мерил целиком, или только основной цикл (от первой поставленной точки до последней)?

Измерялась разница значений счетчика тактов непосредственно до исполнения инструкции CALL, вызывающей процедуру рисования линии и сразу после возврата управления из этой процедуры.

Код, устанавливающий значения регистров и все прочие приготовления не учитывались.

Задержки по памяти и портам не учитывались тоже.


) Точки только ставились, или можно было ксорить заменой нескольких кодов?

Это определяется реализацией. Понятно, что при использовании SET быстрой ксорки не будет.

Возможно, для каждой реализации следует делать пометку о том, может ли она ксорить.


3) Сколько процедурки жрут памяти именно в рабочем состоянии?


Ох, надо покопать архив. :)

Да, и может быть это тоже следует указывать при сравнении.


Тут, возможно, скоро будет новый кандидат на тестирование

Было бы отлично. Штука-то фундаментальная. :)


13000 на диагональ многовато...

:)

GriV
25.01.2011, 16:40
не могу не вмешаться :)

самое быстрое и не пригодное для реальных условий умножение:



; BC = A * L
; A от 0 до 255, L от 0 до 255
; DE должно быть == #4000

add a,'MULTBL
ld h,a
ld c,(hl)
add hl,de
ld b,(hl)


итого 7+4+7+11+7 = 36 (причём это наиболее быстрое и наименее пригодное в реальной жизни умножение)
36 * 9 = 324 такта тольно на умножение

с реальным умножением (пусть оно и умжножает от -128 до 127 по таблице), будет гораздо больше.
так что ни 200 ни 100 точек за фрейм "честно" не повернуть.

Читаю код... не понимаю... объясни? Если правильно понимаю, то 255*255 = около 65025.
При умножении 255*255 тебе надо две таблицы - одна с младшим байтом, другая с старшим, количество значений - 65025 на старший и столько же на младший байт, итого 130050 байт. Может где то обманул??? У тебя там вижу всё в основную память падает + смещение по базовому адресу таблицы.

Destr
25.01.2011, 17:58
Похоже что на входе А от 0 до 63:
Тогда да, памяти хватит (16384 байт на старший байт и столько-же на младший ).
Я такое умножение в DotsElka делал.
А если А от 0 до 255 то получается что ВСЯ память (включая ПЗУ) занята под табличку (причём только одного полуслова)

Sinus
25.01.2011, 21:17
Destr, да, так и есть, A от 0 до 63.

GriV
28.01.2011, 13:18
не могу не вмешаться :)

самое быстрое и не пригодное для реальных условий умножение:



; BC = A * L
; A от 0 до 255, L от 0 до 255
; DE должно быть == #4000

add a,'MULTBL
ld h,a
ld c,(hl)
add hl,de
ld b,(hl)


итого 7+4+7+11+7 = 36 (причём это наиболее быстрое и наименее пригодное в реальной жизни умножение)
36 * 9 = 324 такта тольно на умножение

с реальным умножением (пусть оно и умжножает от -128 до 127 по таблице), будет гораздо больше.
так что ни 200 ни 100 точек за фрейм "честно" не повернуть.

----


Вот тебе ещё быстрее:



; BC = A * L
; A от 0 до 63, L от 0 до 255
; DE должно быть == #4000

add a,'MULTBL
ld h,a
ld c,(hl)
; add hl,de - добавление #40 это тоже самое что set 6,h
set 6,h
ld b,(hl)


это будет 7+4+7+8+7= 33 такта :-) экономия однако, итого на 9 точек - 33*9 = 297 тактов

Однако 64*256 - не самый правильный объём расчётов с точки зрения изображения на экране (одна треть экрана)

Можно сделать 128*192 (по оси X дискретность выше, по Y полный экран; или экран с X=0..191, Y=0..127)
Разместив таблицу последовательно (в каждые 256 байт 128 слов)
будет:



; BC = H * L
; L от 0 до 127, H от 0 до 191

set 6,h - задали адрес откуда начинается таблица - #4000
; тут возможен вариант set 7,h - #8000, но тогда будет 0..127*0..127
rlc l - получили адрес младшего байта
ld c,(hl)
inc l
ld b,(hl)


итого: 8+4+4+7+4+7=34 такта, зато считается половина экрана, и свободны DE и A :-)

В голом остатке получаем 297 тактов * 200 точек = 59400 тактов, т.е. теоретические шансы по "уложиться в фрейм 200 точек" есть, вопрос по производительности прорисовки остаётся актуальным.


Здесь несколько раз поднималась тема рисования прямых, конкретных реализаций и способов их сравнения.
Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах.

И ещё, ты строишь линии на 256 по X... будет ли меняться характер распределения (и если да, то насколько сильно), если использовать другое количество по X? Например 128, или то самое 10-20? У любой рисовалки есть подготовительная обязательная часть... Тут это станет сильно заметным...

И ещё, подправь наименования графиков (сгруппируй, чтобы удобнее читать было) в верхнем посте, не вижу что показывает второй график...

Sinus
28.01.2011, 16:52
добавление #40 это тоже самое что set 6,h
не тоже самое; добавь-ка мне #40 через set 6,h к, скажем, #6000 :)


Можно сделать 128*192
а код куда размещать? в ПЗУ? :)

кстати,


set 6,h - задали адрес откуда начинается таблица - #4000
для H от 64 до 127 будет выдавать неправильные значения.


Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах
кстати да :) так, чтоб поржать.

Higgins
28.01.2011, 17:56
Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах.


Отличная идея. Постараюсь сделать.


И ещё, ты строишь линии на 256 по X... будет ли меняться характер распределения (и если да, то насколько сильно), если использовать другое количество по X? Например 128, или то самое 10-20? У любой рисовалки есть подготовительная обязательная часть... Тут это станет сильно заметным...

Если я правильно помню, я такие графики строил и ничего нового на них не увидел. Выглядят они по-другому, но только из-за того, что при изменении дельты по X незибежно меняются углы наклона, а прямые с одним и тем же углом наклона рисуются за время, пропорциональное их длине за вычетом тех самых подготовительной и финальных частей. Сравнивать такие графики корректно трудно, т.к. только часть линий (0,0)-(127,Y) имеет углы наклона в точности такие же, как линии (0,0)-(255,Y). Плюс к тому, могут быть небольшие отклонения, вызванные тем, что линии разной длины, даже одного и того же угла наклона, строятся по-разному из-за балансирования. (К слову, балансировку тоже, наверное, следовало бы отмечать при сравнении процедур.)

Что касается времени подготовки, наверное, достаточно для каждой процедуры дать время на короткой линии.


И ещё, подправь наименования графиков (сгруппируй, чтобы удобнее читать было) в верхнем посте, не вижу что показывает второй график...

Ничего не понял. :)

Lethargeek
28.01.2011, 19:04
Кстати, по поводу быстрых умножений-делений для прорисовки
Нужно быстрое преобразование dx; dy ---> dy1; dy2 для dx=256
причем dy1 - округленное (256*dy)/dx, а dy2 = dy1 + ((256*dy)/dx - dy1)*8
Например, для диагонали dx=255; dy=191 получится dy1=192; dy2=190

Зачем это надо? Чтоб избавиться от лишнего сложения в конструкции sub dy:jrnc:add dx
И тогда семь раз можно вычитать dy1, а на восьмой вычесть dy2, чтобы скорректировать ошибку
Экономия прямая по 4 такта на ступеньку (и вдвое больше косвенная в некоторых вариантах)

Есть вообще-то уже несколько набросков и без того заметно быстрей рассмотренных
но пока что я недоволен, надо еще быстрее (и попутно желательно покороче)

Higgins
29.01.2011, 00:25
Знаешь, очень не хватает встроенной DRAW бейсика в этих диаграммах.

У меня получилось от 169946 тактов на (0,0)-(255,0) до 170832 такта на (0,0)-(255,175). Если это вставить в общий график, линии для Expert, Raider и Vitamin практически сольются. :)

Но: в отличие от названных процедур, бейсик выводит линии в цвете. Получается, полноценного конкурента у него все-таки нет. :)

Lethargeek
29.01.2011, 02:27
У меня получилось от 169946 тактов на (0,0)-(255,0) до 170832 такта на (0,0)-(255,175).
Гы, так он же плотами точки ставит по координатам :)


Но: в отличие от названных процедур, бейсик выводит линии в цвете
Причем красит атрибут после каждой точки :rolleyes:


Получается, полноценного конкурента у него все-таки нет.
Поищи на WoS-форуме, я там как-то видел чье-то альтернативное творчество с окрашиванием

GriV
29.01.2011, 12:37
И ещё, подправь наименования графиков (сгруппируй, чтобы удобнее читать было) в верхнем посте, не вижу что показывает второй график...


Ничего не понял.

У тебя 4 графика, их описание разбросано в посте (что не так важно, но несколько путает), но я не смог описание 2го графика вытащить :-) то ли это следует из дальнейшего обсуждения, то ли я читать разучился :-)


для H от 64 до 127 будет выдавать неправильные значения.

Согласен, моя ошибка... тогда так



; BC = A * L
; L от 0 до 127, A от 0 до 191

add a,'MULTABL
ld h,a
rlc l - получили адрес младшего байта
ld c,(hl)
inc l
ld b,(hl)


Итого конечно на 3 такта больше (37 тактов), зато не используется тем не менее DE (что есть бонус на отсутствии затрат сохранения контекста этого регистра).



а код куда размещать? в ПЗУ?

Можно в теневое ПЗУ/ОЗУ. А можно сделать ограничения 0..176 точек (вместо 0..192), это около 4КБ даст, туда и код ложить. Однако цепляться вот не надо, у тебя там вообще 128кб надо было под одну таблицу...


не тоже самое; добавь-ка мне #40 через set 6,h к, скажем, #6000
Не хочу что то :-)


Что касается времени подготовки, наверное, достаточно для каждой процедуры дать время на короткой линии.

Построить линию длиной 1-2 точки и дать справочно базовое время работы.


У меня получилось от 169946

Тем не менее информация интересная.
Кроме того, интересно как она построит (в тактах конечно) минимальной длины линию. Есть некий шанс что она это сделает быстрее указанных процедур. И ещё, Хотя бы 1 график на DRAW можно было бы сделать? Один из графиков (например 1й), уточночнить и добавить туда DRAW. И ещё, можно было бы графики сделать логарифмическими по оси тактов, тогда там лучшее видно будет.

Higgins
13.02.2011, 15:34
У тебя 4 графика, их описание разбросано в посте (что не так важно, но несколько путает), но я не смог описание 2го графика вытащить :-)

Смысл обоих графиков один и тот же, но на втором показаны только две быстрейшие реализации, чтобы лучше видеть разницу.

Сейчас эти графики слиты в один и в таком виде выложены в первом сообщении темы.


Построить линию длиной 1-2 точки и дать справочно базовое время работы.


Вот какие еще бродят мысли: сделать гистограммку, в которой для линий разных длин были бы даны минимальное и максимальное времена рисования. Тогда имея на руках сцену, разложенную по линиям с известными длиной и количеством можно было бы прикинуть возможное время построения, причем для любых углов, то есть как бы она ни была повернута.


И ещё, можно было бы графики сделать логарифмическими по оси тактов, тогда там лучшее видно будет.

Ну, на графиках такты все-таки не по экспоненте растут. ;-)

alone
18.06.2011, 14:58
Чтобы вращать совсем быстро, надо использовать таблицу умножения 64(координаты в объекте)*256(рассчитанные координаты осей).

Каждая вершина n разворачивается в процедуру
x=OXx*X[n]+OYx*Y[n]+OZx*Z[n]
y=OXy*X[n]+OYy*Y[n]+OZy*Z[n]

;c=OXx
;e=OYx
;l=Ozx
ld b,X[n]
ld d,Y[n]
ld h,Z[n]
ld a,(bc)
add a,(hl)
exd
add a,(hl)
ld (scrX[n]),a
---
ld b,X[n+1]
ld h,Y[n+1]
ld d,Z[n+1]
ld a,(bc)
add a,(hl)
exd
add a,(hl)
ld (scrX[n+1]),a
...

59 тактов на координату.

Проверено, работает.

---------- Post added at 14:58 ---------- Previous post was at 14:53 ----------

Сейчас тут будут возгласы типа "точность никакая", так вот я отвечу.

1. Во-первых, точность принципиально выше, чем у JtN'а и аналогичных движков, потому что нет умножения умноженного.
2. Таблицы умножения, составленные с округлением вниз, - типичная ошибка, убивающая точность насмерть (JtN её тоже не избежал). Округлять надо правильно. См. исходники The Link.

GriV
19.06.2011, 00:38
2Alone> можно подробнее, что делается? Не понял с набегу.

alone
19.06.2011, 00:53
Есть координаты в объекте: -32..31 каждая. В условном масштабе.
Есть координаты реальные: -128..127 каждая. В другом условном масштабе.
Есть оси OX (127,0,0), OY (0,127,0), OZ (0,0,127). В начале кадра мы их вертим и получаем координаты OXx,OXy,OXz, OYx,OYy,OYz, OZx,OZy,OZz.

Потом считаем вершины по три умножения на координату, как показано выше.

GriV
21.06.2011, 14:15
А почему ты говоришь про условный масштаб? Или таблица умножения разной может быть?

alone
21.06.2011, 17:57
Разумеется!

GriV
22.06.2011, 15:27
Т.е. грубость обсчёта кроется только в неравномерности перехода более дальней плоскости обсчёта к более близкой (условном масштабе)? Чем больше страниц на обсчёт, тем качественней? Или иначе?

alone
22.06.2011, 17:58
Грубость обсчёта заключается в том, что у суммы трёх чисел с ошибкой +-0.5 пикс. получается ошибка +-1.5 пикс. И число страниц на это не влияет.

Raider
29.06.2011, 20:35
Прикольно.
А у линии от Expert большие таблицы или строится в памяти код?

DrBars невольно ввел в заблуждение. У меня не самая быстрая линия, конечно. Если была бы нужна самая быстрая, она была бы написана совсем по-другому, с гигантскими таблицами, с гигантским кодом, выжимая каждый такт. А здесь стояла задача написать и быструю и вместе с тем компактную процедуру линии (для игры).

Sinus тоже ввел в заблуждение. Он что-то попутал. Никаких гигантских таблиц данных и кодов я не строю. Стек не использую.

Я использую "стандартные" для таких дел как установка точки 4 таблицы по 256 байт (то есть в сумме килобайт), чтобы по координатам x,y рассчитать экранный адрес и взять точку. Эти таблицы универсальны - они используются везде: и для того чтобы через plot выставить точку, и для того чтобы рассчитать адрес спрайта.

Размещаются таблицы по адресу выравненному на границу 256 байт и выглядят так:
256 байт - координата x -> начальное положение точки в байте.
256 байт - координата x -> x/8, это x-компонента добавляемая к след.экр. адресу:
256 байт - координата y -> младший байт адреса
256 байт - координата y -> старший байт адреса

В процедуре обращение к таблицам производится один раз, в самом начале, при вычислении экранного адреса по координате x,y (и взятии байта точки).

Таблицы можно или уменьшить до (384 байт экр.адр. + 8 байт сдвинутой точки), или совсем убрать, заменив на чуть более длинный расчет адреса, по типу как это делается процедурой в ROM. Это добавит лишних ~100..200 тактов на линию, но избавит от таблиц вообще.

Все это может оказаться ключевым значением для того, кто пишет игру.

alone
09.07.2011, 21:50
можно сэкономить страничку на вертелку, если строить таблицы только для 32 засечек на каждой проекции каждой оси (9 таблиц):
ld hl,0
ld (OXxMUL),hl
ld (OXyMUL),hl
ld (OXzMUL),hl
ld (OYxMUL),hl
ld (OYyMUL),hl
ld (OYzMUL),hl
ld (OZxMUL),hl
ld (OZyMUL),hl
ld (OZzMUL),hl
...
macro zasec
add hl,de
ld (\0MUL+\1),hl
endm
macro tzasec
ld hl,(\0)
ld d,h,e,l
ld (\0MUL+2),hl
_=2
dup 30
_=_+2
zasec \0,_
edup
endm
tzasec OXx
tzasec OXy
tzasec OXz
tzasec OYx
tzasec OYy
tzasec OYz
tzasec OZx
tzasec OZy
tzasec OZz
(это 7700 тактов на кадр),

а координаты считать через
ld hl,(OXxMULx)
[xor a:sub l:ld l,a:sbc a,h:sub l:ld h,a]
ld de,(OYxMULx)
add/sbc hl,de
ld de,(OZxMULx)
add/sbc hl,de
:94*3

для 16-битных координат:
ld hl,(OXxMULX)
[xor a:sub l:ld l,a:sbc a,h:sub l:ld h,a]
ld de,(OXxMULx)
add/sbc hl,de
ld de,(OYxMULX)
add/sbc hl,de
ld de,(OYxMULx)
add/sbc hl,de
ld de,(OZxMULX)
add/sbc hl,de
ld de,(OZxMULx)
add/sbc hl,de
:193*3
Разделение на X и x - биты пополам
16 бит - 18 таблиц по 128 элементов (62208 t)
14 бит - 18 таблиц по 64 элемента (31104 t)
12 бит - 18 таблиц по 32 элемента (15552 t)

На практике 16-битные координаты внутри объекта не нужны.
Лучше с 16-битной точностью считать только координаты всего объекта, а сами вершины относительно объекта с 8-битной точностью.

Cheburashka
03.05.2013, 11:43
Не прошло и 100 лет...
Вот моё "творчество" в виде быстрой и компактной процедуры рисования линий.
Пробовал более быстрые варианты, но предварительные расчеты в процедуре сжирают всю выгоду для небольших линий.

alone
03.05.2013, 11:53
Неплохо! Я насчитал 244 такта на вход, не считая CALL. Но пока что по скорости обвязки ещё никто не переплюнул линию в Dies Irae (#9F6A) - там 192/227 тактов вход-выход.

drbars
06.05.2013, 06:41
Вот бы ещё фон за линией быстро восстанавливать :)

Lethargeek
22.05.2013, 13:01
Cheburashka, и что делать с этим файлом, куда пихать?
дай исходник текстовый обычный для кросс-ассемблера

GM BIT
22.05.2013, 15:28
+1
Я тоже не в курсе, LINE.H - это чьих будет?

SaNchez
22.05.2013, 15:44
+1
Я тоже не в курсе, LINE.H - это чьих будет?

Alasm же...

GM BIT
28.08.2013, 09:45
Vitamin, Можешь переделать свою процедуру рисования линии чтоб она работала без таблички, а точку (или координаты рассчитывала) ставила простой процедурой?

Vitamin
28.08.2013, 09:47
GM BIT, это не моя процедура. Если не ошибаюсь, ее автор- Unwinder.

GM BIT
28.08.2013, 10:03
Понятно.
Есть у кого процедура рисования линии (не ПЗУ)? Чем меньше тем лучше (скорость не важна)
Кроме этой http://zxpress.ru/article.php?id=7388 - она косячно рисует с апофисами на концах (как в Vibration) - ну или кто подскажет как это исправить

newart
28.08.2013, 12:52
Что есть апофис?

GM BIT
29.08.2013, 05:31
Что есть апофис?
Ну хрен знает как это назвать :)
http://s2.ipicture.ru/uploads/20130829/M5wxSvjR.png
http://s2.ipicture.ru/uploads/20130829/opvxpsh3.png

Процедура http://zxpress.ru/article.php?id=7388 рисует именно так (та которая коротенькая)

jerri
29.08.2013, 09:18
GM BIT, оно из этой точки рисует?

research
29.08.2013, 11:46
"апофис" никуда не денешь. он останется в любой процедуре. убирать только искуственно, т.е. разбивать линию на две, и рисовать их от краев к общей точке

GM BIT
29.08.2013, 12:24
GM BIT, оно из этой точки рисует?
С краев линии такая пертушка, развернутые процедуры как и бейсик рисуют правильно

introspec
29.08.2013, 12:32
"апофис" никуда не денешь. он останется в любой процедуре. убирать только искуственно, т.е. разбивать линию на две, и рисовать их от краев к общей точке
Я могу быть неправ, конечно, но чисто внешне мне кажется, что это скорее похоже на неправильную инициализацию переменных для алгоритма Брезенхэма. Т.е. должно достаточно просто лечиться.

GM BIT
29.08.2013, 12:37
Согласен

Destr
29.08.2013, 13:35
Я могу быть неправ, конечно, но чисто внешне мне кажется, что это скорее похоже на неправильную инициализацию переменных для алгоритма Брезенхэма. Т.е. должно достаточно просто лечиться.
Помнится программка из Spectrum Expert.


(edit)
10 LЕТ DX=255:LЕТ DY=175:LЕТ Y=0
20 LЕТ Е=DX/2
30 FОR X=0 ТО DX
40 РLОТ X,Y
50 LЕТ Е=Е-DY
60 IF Е<0 ТНЕN LET Е=Е+DX:LЕТ Y=Y+1
70 NЕXТ X


Если в строке 20 будет LET E=DX, то будут эти самые хвостики.
Т.е. накопитель нужно приравнивать к DX/2.
Когда переводил её в асм то тоже пропустил деление, типа и так сойдет. А вот фиг...

GM BIT
29.08.2013, 18:44
Помнится программка из Spectrum Expert.
Нумерация строк разная :) и LET в 50 строке пропущен


Когда переводил её в асм
Результат покажешь?

Destr
29.08.2013, 21:19
Нумерация строк разная и LET в 50 строке пропущен
Ну да.
Та что 50 строка должна быть после 60 (ну например 65)
И выглядеть как:
65 IF Е<0 ТНЕN LET Е=Е+DX:LЕТ Y=Y+1


Результат покажешь?
Да когда это было!
(в год выхода того эксперта или чуть попозже)
С тех пор уж и дисков не осталось...
Позже я юзал линии из адвенчура или самописаные (но на основе того-же алгоритма "Б-Х") но без оптимизаций.
Хвастать нечем.
А поскольку вы тут ловите самую-присамую быструю - в том-же номере эксперта есть примеры на асме (правда только для одного квадранта)
так что желающие смогут сами дописать и потестить...

drbars
30.08.2013, 21:38
кстати, "Б-Х" можно поюзать и не для рисования линий, а например для задания вектора движения спрайтов :)

GM BIT
30.08.2013, 22:08
например для задания вектора движения спрайтов
Вот этого я и хочу, для создания больших таблиц. Только помощи маловато :(

drbars
30.08.2013, 23:28
Вот этого я и хочу, для создания больших таблиц. Только помощи маловато :(
Я собираюсь в реальном времени считать, под таблицы нет места.

Destr
31.08.2013, 08:59
Я собираюсь в реальном времени считать, под таблицы нет места.
Я так делал (и собираюсь ещё) - получалось вроде.
Правда переменные держал в массиве который обрабатывал IX.
Это не шибко шустро. Хотя всего 8 спрайтов, но всё равно нужно как-то исхитрится и хранить данные как-нибудь так, чтоб максимально ускорить вычисления.

Sergey
05.09.2013, 16:31
К слову.
Все исходники пересмотрел, но, к сожалению, осилить не смог. Пришлось идти в обход. :)
Взял сишный исходник с википедии (http://www.google.ru/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCoQFjAA&url=http%3A%2F%2Fru.wikipedia.org%2Fwiki%2F%25D0%2 590%25D0%25BB%25D0%25B3%25D0%25BE%25D1%2580%25D0%2 5B8%25D1%2582%25D0%25BC_%25D0%2591%25D1%2580%25D0% 25B5%25D0%25B7%25D0%25B5%25D0%25BD%25D1%2585%25D1% 258D%25D0%25BC%25D0%25B0&ei=6nUoUsvJG8jDswbPwYCIDQ&usg=AFQjCNHgqbCedyvRFjC79RPR9kFsngkjQQ&bvm=bv.51773540,d.Yms&cad=rjt):

void drawLine(int x1, int y1, int x2, int y2) {
const int deltaX = abs(x2 - x1);
const int deltaY = abs(y2 - y1);
const int signX = x1 < x2 ? 1 : -1;
const int signY = y1 < y2 ? 1 : -1;
//
int error = deltaX - deltaY;
//
setPixel(x2, y2);
while(x1 != x2 || y1 != y2) {
setPixel(x1, y1);
const int error2 = error * 2;
//
if(error2 > -deltaY) {
error -= deltaY;
x1 += signX;
}
if(error2 < deltaX) {
error += deltaX;
y1 += signY;
}
}

}
и скомпилил в SDCC. Как ни странно, работает замечательно, даже без правки ручками. Рисует линии с любым тангенсом и направлением. Сейчас избавлюсь от операций с индексными регистрами, и, вообще, благодать наступит. :v2_dizzy_roll:
ЗЫ. Рисую под TS-Config/16c

drbars
06.09.2013, 09:25
и скомпилил в SDCC.
Кто же так делает? 16С сам по себе тормозной, а тут ещё линия без оптимизации :)

Хотя, сам по молодости делал процедуру расчета следующей строки экрана на бейсике, потом компилил на тобосе и дизасемблировал. :) Работало даже как-то :)

Sergey
06.09.2013, 15:35
Кто же так делает? 16С сам по себе тормозной, а тут ещё линия без оптимизации :)
Ну это ж не тот 16с, который от AloneCoder`а, а линейный: 2 пиксела на байт по 256 байт в строке, 512 строк (8 последовательных страниц). С учетом того, что рисуется, всё равно, по одной точке, скорость отрисовки такая же как на стандартном zx-экране (или это дело рук 14Мгц?! :) ). При этом расчет адреса по координатам проще и быстрее.
Старшие 3 бита координаты Y - смещение в страницах относительно начала экрана.
Младшие шесть бит указывают на начало стоки Y внутри страницы памяти
Старшие 8 бит координаты X указывают на байт в строке, которому принадлежит точка.
Младший указывает, левый или правый полубайт используется.

Впрочем, иногда видно, что линия не мгновенно появляется. Но за рисуемыми пикселами уследить невозможно.


Хотя, сам по молодости делал процедуру расчета следующей строки экрана на бейсике, потом компилил на тобосе и дизасемблировал. :) Работало даже как-то :)
Эх, молодость!:rolleyes_std:

GriV
11.03.2015, 20:45
UPDATE: Графики для вертикально и горизонтально ориентированных теперь слиты вместе, для наглядности. По горизонтали отложены номера тестов от 1 до 447 включительно. В тестах 1...192 строятся линии (0,0)-(255, 0...191). В тестах 193...447 -- линии (0,0)-(254...0, 191).
Я думаю, весьма характеристичным было бы ещё и проверка тех же наклонов для коротких линий. Коротких - это в два раза меньше, то есть для горизонтальных - это 256, 128, 64, 32, 16, 8, 4, 2, 1 пиксель длины. Если речь про горизонтальные - это 192, 96, 48, 24, 12, 6, 3, 1 пиксель длины. Ведь есть ещё "стоимость" тактов обвязки, когда что-то предварительно вычисляется.
Как весьма логично говорит Дима Быстров, чаще рисуются, как ни странно, не линии длиной 256 пикселей, а линии длиной 10 пикселей, а если обвязка съедает половину тактов - результат на коротких линиях понятно какой будет. Как это изобразить на гистограмме: для этого нужно отдельно график тактов построения линии, скажем, процедуры витамина, а на нём - ещё и сравнительные графики в тактах, но уже для линий короче. Вот тут то логарифмическая шкала будет очень в помощь :-)

Lethargeek
13.11.2018, 19:13
эта тема интересна еще кому-то? ;)

https://i69.servimg.com/u/f69/19/84/49/23/graph-10.jpg

DenisGrachev
22.11.2018, 09:20
эта тема интересна еще кому-то? ;)

https://i69.servimg.com/u/f69/19/84/49/23/graph-10.jpg

графики никому, там можно что угодно нарисовать

Shiny
22.11.2018, 10:05
Я бы порисовал.

интересный подход к рисованию линий - строить точку на основании готовых координат (x,y). В 1ddkit использовался другой вариант, который позже нагло стырили.

Lethargeek
22.11.2018, 17:56
графики никому, там можно что угодно нарисовать
могу завтра тестовый снапшот выложить, сам проверишь
(исходник рано, ибо он воистину ужасен, чистить и чистить)

- - - Добавлено - - -


интересный подход к рисованию линий - строить точку на основании готовых координат (x,y)
что в нём интересного-то такого, это же очень медленно

DenisGrachev
22.11.2018, 18:06
могу завтра тестовый снапшот выложить, сам проверишь
(исходник рано, ибо он воистину ужасен, чистить и чистить)

Выкладывай! и исходники потом тоже, а то пропадёт всё добро и пиши пропало :)
А так может в демках заюзаем хоть!

Shiny
22.11.2018, 18:22
Выкладывай! и исходники потом тоже, а то пропадёт всё добро и пиши пропало :)
А так может в демках заюзаем хоть!

кризис жанра или исписался?(:

Dart Alver
22.11.2018, 23:43
Честно говоря не очень вкурил что как и зачем сравнивается ) . Когда переделывал линзу для BGE, понадобилась прога для линии (встроенная не пришлась по душе )) ), правда скорость была не на первом месте по важности. Отыскал в нете алгоритм брезенхейма и состряпал что-то такое :


LINE
; Bresenham's line algorithm
; de - first pixel , hl - last pixel

.lineB call .plot ; вывод начальной точки
.lineN
push hl
or a
sbc hl,de ; проверяем на нулевую длину
pop hl
ret z

.noequ ; de - y0x0 , hl - y1x1

ld a,l
ld l,#1C ; inc e
sub e ;dx x1-x0
jr nc, 1F
neg
inc l ; l=#1D - dec e : dx<0 (.Xstep)
1
ld b,a ; b = |x1-x0| (.dX)

ld a,h
ld h,#14 ; inc d
sub d ; dy y1-y0
jr nc, 1F
neg
inc h ; h=#15 - dec d : dy<0 (.Ystep)
1
ld c,a ; c = |y1-y0| (.dY)

cp b ; dx > dy ведём линию по X , dy > dx ведём линию по Y
jr c,1F
ld c,b ; меняем местами X и Y
ld b,a
ld a,h
ld h,l
ld l,a
ld a,c
1
ld (.dERR),a
ld a,b
ld (.dM),a
ld a,l
ld (.Step1),a
ld a,h
ld (.Step2),a


ld hl,0 ; err- проверка ; de - y0x0
.loopln
push bc

.Step1 inc e ;Xstep x=x+1 / x=x-1 / y=y+1 / y=y-1
ld bc,0

.dERR EQU $-2 ;dERR dY or dX
add hl,bc ; err=err+dY or err+dX
1
ld bc,0
.dM EQU $-2 ; dX or dY
bit 7,h
jr nz,1F
push hl
add hl,hl
or a
sbc hl,bc
pop hl
jr c,1F ; if (err*2 < dM) goto 1F
sbc hl,bc ; err = err-dM
.Step2 inc d ;Ystep y=y+1 / y=y-1 / x=x+1 / x=x-1
1
call .plot
pop bc
djnz .loopln
ret

.plot ; вход de: e=x , d=y
push hl,de,bc
call PLOT_SNP ; вывод точки меняется от условий
.plotADR EQU $-2
pop bc,de,hl
ret

Может кому и сгодиться на что-нибудь. Прогу вывода точек не привожу, это не существенно, там разные варианты использовались.

DenisGrachev
23.11.2018, 04:18
кризис жанра или исписался?(:

демки писАть не переписАть ещё, тыщи идей, желания ноль :)

Lethargeek
23.11.2018, 05:34
ну вот как-то так https://cloud.mail.ru/public/JBi8/MJJP72BQM
можно ставить бряки на call и сразу после (адреса даны в txt)
сейчас дб даже чуть быстрей чем на графике

krt17
23.11.2018, 23:29
Для элиты бесполезно, 8кб перебор, выигрыш максимум процентов 5, тормозят там совсем не линии.
Думаю интересующиеся помнят что в элите используется dx/dy, для универсальности, ибо клиппинг еще то развлечение. На маленьких линиях это да, тормозит. Точно надо 2 линии сделать DDA и Брезенхэма, вот это ускорит ... наверное.
Почитал на хупе, тоже хотелось бы узнать, как это DDA без деления, дальше начался понос в теме, а в нем ковыряться уже не охота.

Lethargeek
24.11.2018, 05:59
Для элиты бесполезно, 8кб перебор
при переделке под 128k не так страшно


выигрыш максимум процентов 5
скорее "минимум процентов 5"


тормозят там совсем не линии.
тормозят неслабо и линии, с одним близким кораблём тормозит сильнее, чем с 2-3 вдалеке

Но суть совсем в другом: эта процедура - именно для спектрумовской раскладки (больше для 128k демок, где переключают экраны, для векторных эффектов и анимаций). Элита же сначала долго рисует в буфер, потом в два захода чересстрочно перебрасывает в экран, да еще процедура ксорить должна уметь, и с учётом этого всего во-1 выгоднее изменить алгоритм, во-2 отдачи еще больше будет от смены структуры буфера на другую, при которой процедуры будут и быстрыми, и маленькими. Например, на всё ту же пресловутую раскладку в столбики (можно в два сегмента слева направо) - скорость переброски на zx-экран из которой лишь чуть медленней оригинальной цепочки ldi.


Почитал на хупе, тоже хотелось бы узнать, как это DDA без деления,
а там и не DDA :p а такой типа "сдвоенный Хорн": в каждой основной ветке-по-наклону есть две подветки, одна для движения по прямой (по вертикали/горизонтали) и вторая - для диагональных шагов. Между ними и мечется программный счётчик по результатам вычитания из ошибки, причём в каждой подветке вычитаем разные числа с разным типом перехода по переносу: для горизонтально-наклонных линий dy и (dy-dx), для вертикально-наклонных соответственно dx и (dx-dy). Что и позволяет избавиться от коррекции ошибки после ступеньки (а это, между прочим, 16 тактов на ступеньку в оригинальной процедуре spectrum expert) за счёт лишь одного предварительного вычитания. Но код сильно раздувается (в том числе еще из-за отдельной отрисовки хвоста, так как две ловушки уже ставить слишком накладно, да и с одной ловушкой в среднем медленней выходило бы; и еще кое-каких улучшений для коротких отрезков). Хотя в принципе можно этот же приём и без разворачивания использовать.

вот и весь секрет :)

DenisGrachev
24.11.2018, 13:34
ну вот как-то так https://cloud.mail.ru/public/JBi8/MJJP72BQM
можно ставить бряки на call и сразу после (адреса даны в txt)
сейчас дб даже чуть быстрей чем на графике

красиво, быстро, молодец!

Totem
24.11.2018, 17:00
красиво, быстро, молодец!

лично мне ,уже страшно представить как ему скучно. замахнулся на святое хехе. Подозреваю, что и "тексурить" МК скоро начнет втихаря :)

krt17
25.11.2018, 21:52
Возвращаясь к элите есть вполне конкретная задача. Требуется код который строит отрезок на экране x1 (-255,255), y1 (-255,255), x2 (-255,255), y2 (-255,255) с нулем в центре. На ксор можно забить, во первых этот код этого в принципе не сможет, а во вторых ну не видно на фоне солнца нифига и это нормально. Как к этой задаче адаптировать 10 байт этой быстрой линии без конкретного замедления результата мне пока не ясно. Вся эта этюдная софистика хороша максимум для дем к сожалению. Призывы просто поменять саму отрисовку не принимаются, 90% времени когда корабль на экране он состоит из дюжины небольших отрезков, ускорение в этом случае будет пару процентов, это того не стоит.
Я совсем не против быстрой демолинии, просто она лично мне не нужна. В любом случае классно что для интересующихся есть готовое решение. Как кстати она по скорости в сравнении с другими для отрезков в 1-40 пикселей?

- - - Добавлено - - -

И да конечно, говоря про -255,255 имеется ввиду отсечение невидимых частей.

Lethargeek
25.11.2018, 23:53
Возвращаясь к элите есть вполне конкретная задача. Требуется код который строит отрезок на экране x1 (-255,255), y1 (-255,255), x2 (-255,255), y2 (-255,255) с нулем в центре.
нет, требуется код, который строит отрезок в буфере, а координаты - просто параметры
отсечение - отдельная задача до построения


На ксор можно забить, во первых этот код этого в принципе не сможет,
ну так этот и не надо, сказал же сразу


а во вторых ну не видно на фоне солнца нифига и это нормально.
в будущем, где космические корабли бороздят просторы 8 галактик, фильтров не придумали, тыщитаеш? :D
к тому же ксорка применяется не только у звезды, но еще для отрисовки эспов емнип; мож еще чего


Как к этой задаче адаптировать 10 байт этой быстрой линии без конкретного замедления результата мне пока не ясно.
нифига не понял про "10 байт"


Призывы просто поменять саму отрисовку не принимаются, 90% времени когда корабль на экране он состоит из дюжины небольших отрезков,
так проблема именно в условных 10% оставшихся, "средняя температура" здесь не прокатит
тормоза могут длиться непрерывные десятки секунд, а не распределяются равномерно
и что еще хуже, тормоза не только графические, а от них страдает и управление
притом обычно в самые критические моменты ближнего боя

следственно, аргумент против смены отрисовки не принимается


ускорение в этом случае будет пару процентов, это того не стоит.
повторю, ошибаешься с процентом в несколько раз
например, при отлёте глядя в задний экран время отрисовки станции = 80-90 тыщ тактов
пауза между отрисовками, то есть всё остальное время игрового кадра ~480 тыщ тактов
из которых надо сразу вычесть еще 90 тыщ на очистку и переброску буфера
минус неизвестно сколько на управление и анимацию приборной панели
минус время на вывод "пыли", вывод текста и другие вспомогательные задачи

уже выходит, что из общих временных затрат на объект
при сближении отрисовка может жрать >20% времени
а ведь её реально ускорить вдвое (с тем же размером)

- - - Добавлено - - -


Я совсем не против быстрой демолинии, просто она лично мне не нужна. В любом случае классно что для интересующихся есть готовое решение. Как кстати она по скорости в сравнении с другими для отрезков в 1-40 пикселей?
можешь сам замерить, в основном зависит от постоянных накладных расходов на вход
(~330 тактов, что всё же меньше, чем у двух других вариантов с графика)
меньше - от положения "хвоста"; вход, наверно, можно слегка поджать
для анимаций можно сократить проверки, добавить поддержку ломаных итд

krt17
26.11.2018, 00:42
отдельная задача
Спасибо, далее стало не интересно.

Lethargeek
26.11.2018, 01:34
Спасибо, далее стало не интересно.
??? а мне вот интересна причина столь неадекватной реакции :v2_conf2:
да, отдельная, потому что её можно решать отдельно
без оглядки на способы собственно построения
и даже отдельно сгруппировать

PATHNK
12.01.2019, 09:00
Порекомендую книгу (http://mirknig.su/knigi/programming/324797-sintez-izobrazheniy-bazovye-algoritmy.html)
Название: Синтез изображений. Базовые алгоритмы
Автор: Эгрон Ж.
Издательство: Радио и связь
Год: 1993
Страниц: 218