-
Занимаемся разработкой CAD приложения и для новой версии внедряем DirectX для ускорения отрисовки (изначально было GDI). Проблема в том что при уменьшении масштаба исчезают линии и другие мелкие объекты (отрисованные треугольниками). Можно ли как-то этого избежать. Может есть какие-то настройки рендеринга чтобы все отображалось, даже если оно меньше одного пиксела. Вопрос в принципе решается сглаживанием, но оно сильно ухудшает читабельность изображения, поэтому решили вообще его не применять. А полный пересчет картинки (с изменением размеров соответственно масштабу) при масштабировании колесом мыши сводит преимущество в скорости перед GDI на нет. Пока обошли методом пересчета через какое-то время после масштабирования, но это решение далеко от идеала, поскольку картинка исчезает при уменьшении масштаба и только через секунду появляется. При быстром увеличении тоже получаются линии и круги огромного размера и через секунду нормализуются.
Спасибо!
-
Можно скриншот того что есть, и что должно быть? Вообще проблема очень странная, я бы даже сказал что она нереальная...
-
> [1] @!!ex © (22.12.07 22:03)
Как я понял, он рисует текст и линии полигонами. Когда уменьшает масштаб, у него эти линии пропадают, потому как толкщиной становтся меньше пикселя.
-
Все объекты преобразуются в треугольники (если полигонами, прийдется часто менять режим, что очень сильно затормаживает рендеринг). При уменьшении масштаба изображение частично исчезает поскольку размер меньше пиксела. Можно сделать равным пикселу и пересчитывать картинку под каждый масштаб, что сейчас и делается через секунду после масштабирования колесом. Но было бы намного лучше если бы рисовалось все независимо от размера. Возможно есть какие-то настройки рендеринга. Скриншоты: Исходная картинка: http://www.novarm.com/pict1.gifПосле масштабирования: http://www.novarm.com/pict2.gifПосле пересчета с изменением ширины линий согласно масштабу (т.е. то что должно быть после масштабирования в идеале): http://www.novarm.com/pict3.gif
-
Чето я не понял, зачем тебе Direct3D, если там НЕТ 3D?
-
> [3] novarm (23.12.07 15:53)
Задачка - бред Средствами ГДИ рисуетс я без проблем, даже если плотность объектов будет в 10 раз больше. ПРи масштабировании конечно будет тормознее, если объектов ОЧЕНЬ много. Отрисовка на ГДИ оптимизируется очень легко, но это homm или anton лучше расскажут, они в этом деле мастера.
По сабжу. Какими средставми вы масштабируете, что такой косяк получается??? Линия рисуется ВСЕГДА, если у нее две координаты в разных пикселях. тоже самое с треугольником.
> если полигонами, прийдется часто менять режим, что очень > сильно затормаживает рендеринг
Та ну, ерунда. Сейчас тыщ пиисят поликов можно поодиночке отрисоывать в реалтайме. на средненькой машинке.
-
вот результат уменьешния в 1, 100, 200 раз. Как видите, даже в сверхамаленьком треугольнике, он никуда не пропадает. Полик рисуется ВСЕГДА, если его проекция занимает большое одного пикселя. А линия из одного пикселя в другой, ВСЕГДА больше одного пикселя. http://img145.imageshack.us/my.php?image=trianglesoz5.pngP.S. Картинки лучше присылать в формате png. При размерах сравнимых с gif, качество в разы выше.
-
> [6] @!!ex © (23.12.07 16:34) > Как видите, даже в сверхамаленьком треугольнике, он никуда > не пропадает.
А можешь сделать такую-же картинку из решетки из 10 полосок, таких, чтобы ширина на исходном рисунке у них была пикселей 5. Я чето тоже всегда считал, что полигоны будут пропадать…
-
В GDI было раньше и такой режим выбирается, но в нем тормозит при больших файлах (иногда нужно рисовать по нескольку десятков тысяч линий и больше, как оптимизировать помимо применение битмапов вместо объектов, но это сильно ограничивает функциональность - не знаю). Задача D3D ускорить отрисовку, с чем оно успешно справляется. Некоторые проекты занимают по нескольку миллионов треугольников, поэтому при переключении режимов сильные тормоза (в начале именно так и пробовалось делать, потом пришли к тому что все надо делать одним или на крайняк несколькими массивами одного типа, но не поодиночке).
Я так понял в D3D координаты в float значениях (модуль D3D писал не я, а другой программер) из-за чего попадает в тот-же самый пиксел. Сглаживание с задачей отображения справляется, но нам оно не подходит.
Может мы действительно чего-то не догоняем, поскольку с D3D собственно столкнулись впервые здесь. Возможно стоило писать на OpenGL, в CAD обычно его применяют, а не D3D
Еще по каким-то непонятным причинам отказывается работать на некоторых машинах (вылетает исключение). Причем все за бугром у пользователей, тут везде где пробовали - работает. Версии DirectX и конфигурации в порядке.
-
Работает так: Сначала вся картинка состоящая из линий, дуг, окружностей, полилиний, полигонов и т.д. перегоняется в массив треугольников (собственно пересчет), потом этот массив с заданным масштабом и смещением экрана уже попадает в память видухи на рендеринг. При масштабировании берется тот-же массив и загоняется в память с другими координатами (в зависимости от установок масштаба/смещения, но пересчет объектов не делается).
-
> [7] homm © (23.12.07 16:46)
Мне кажется, что мы говорим о разных вещах. Если ты внимательно посмотришь на http://www.novarm.com/pict2.gif, то увидишь, что там пропадают линии, которые даже в уменьшенном масштабе занимают > В GDI было раньше и такой режим выбирается, но в нем тормозит > при больших файлах (иногда нужно рисовать по нескольку десятков > тысяч линий и больше, как оптимизировать помимо применение > битмапов вместо объектов, но это сильно ограничивает функциональность > - не знаю).
значительно больше одного пикселя по длине. Неужели надо было на экране выводить сразу столько объектов? Вообще ИМХО это очень хорошо оптимизица, так как об отрисовке в реалтайме речи нет. Например, можно отрисовать мзображение на BackBuffer'e, и при отрисовке просто отрисоывваеть его. При изменении/добавлении объекта перерисовывать только часть BackBuffer'a. Все летать будет. Рисунок то сам по себе статичен. Нафига при каждой перерисовке отрисовывать все 100000 объектов? > Задача D3D ускорить отрисовку, с чем оно успешно справляется. > Некоторые проекты занимают по нескольку миллионов треугольников, > поэтому при переключении режимов сильные тормоза (в начале > именно так и пробовалось делать, потом пришли к тому что > все надо делать одним или на крайняк несколькими массивами > одного типа, но не поодиночке).
VBO - forever. ПРавда не знаю, как его реализовать на D3D. > Я так понял в D3D координаты в float значениях (модуль D3D > писал не я, а другой программер) из-за чего попадает в тот- > же самый пиксел. Сглаживание с задачей отображения справляется, > но нам оно не подходит.
Чет я не вижу на примере, чтобы попадало в один и тот же пиксель. Красным нарисована исчезнувшая линия. http://img57.imageshack.us/my.php?image=pict2zd8.pngКстати, рисунок в png, без потери качества занимает на 14 кб меньше, чем gif с офигенной потерей качества. > Может мы действительно чего-то не догоняем, поскольку с > D3D собственно столкнулись впервые здесь. Возможно стоило > писать на OpenGL, в CAD обычно его применяют, а не D3D
Без разницы... Тот же *** только сбоку. > Еще по каким-то непонятным причинам отказывается работать > на некоторых машинах (вылетает исключение). Причем все за > бугром у пользователей, тут везде где пробовали - работает. > Версии DirectX и конфигурации в порядке.
Ну так ловите в чем проблема. ЛОГ вам в помощь. RAdmin опять же, никто не отменял. > [9] novarm (23.12.07 17:05)
ИМХО нужно делать три массива. 1) Текст 2) объекты с заливкой, переведенные в треугольники. 3) объекты без заливки, переведенные в линии P.S. Если объекты стандартные, их надо хранить в нескольких вариантах, для разных масштабов.
-
> [10] @!!ex © (23.12.07 17:13) > значительно больше одного пикселя по длине.
Но значительно меньше по ширине. Как видеокарта должна отрисовывать линию, если ее ширина от 235,4 до 235,8 пикселя? А другия линия с тем же размером попадает на экранные пиксели от 236,8 до 237,2. Попробуй сделать так, как я сказал, всеже охото помотреть.
-
> [11] homm © (23.12.07 17:22)
Ну чего ты ерунду говоришь. ТОлщина линии задается отдельным параметром, на нее не распространяется матрица преобразования, через которую масштабирование делается, т.к. преобразуются только координаты.
-
Что подразумевается под BackBuffer? Если просто битмап, о чем я писал, то он не решает задачи масштабирования, только скроллинг и редактирование (отрисовка на битмапе без объекта в начале действия, а потом битмап и редактируемый объект), когда как Direct3D - решает (там тоже по сути что-то вроде BackBuffer, только вместо битмапа массив треугольников).
В плане трех массивов или просто отдельных массивов под разные типы объектов не подходит, поскольку важна последовательность прорисовки при многослойных объектах и работает в 2D режиме. В принципе, все это мы решили и даже GDI частично оптимизировали (хотя и хуже работает чем D3D).
Вопросы остались только с прорисовкой мелких объектов при изменении масштаба. Линии рисуются также треугольниками и видимо если две точки треугольника попадают при округлении в один пиксел, то D3D его уже не рисует (или делает штрих-пунктир если линий под наклоном), а надо сделать чтобы рисовал.
Логи сделали, сейчас ловим. До этого пробовал просто метки проставлять (вылетает в самых разных местах, но только в D3D режиме). RAdmin на крайняк уже будет.
-
> [12] @!!ex © (23.12.07 17:30) > ТОлщина линии задается отдельным параметром
Вот :) А автор же полигонами рисует :) И я тебе о полигонах говорю. А ты научи его (и меня заодно) линиями рисовать :)
-
-
Мне не понятно, как из треугольника сделать линию, честно говоря....
-
> Линии рисуются также треугольниками и видимо если две точки > треугольника попадают при округлении в один пиксел, то D3D > его уже не рисует (или делает штрих-пунктир если линий под > наклоном), а надо сделать чтобы рисовал.
Откуда берется щтрихпунктир? Если две точки треугольника попадают в один пиксель, треугольник вообще вырождается. Оно и понятно, толщины то у него нет... Собственно поэтому мне и непонятно, как вы треугольниками линии рисуете...
P.S. ЗАчем вообще здесь треугольники? Все чертежи, которые я виденл состояли из линий... Вы заливку где то применяете? Можно пример чертежа с заливкой?
-
> [16] @!!ex © (23.12.07 17:42)
Ну как это, линия — это такой вытянутый прямоугольник :)
А как можно рисовать линии, кроме как задания Wareframe(как-то так) в D3D, правда не знаю, в OGL кажется есть GlBegine(LINE), как-то так.
-
Подразумевается линия определенной ширины и с закругленными концами как в GDI. Вот она и формируется из залитых треугольников (два в середине и два веера на концах с кол-вом от 0 до 12 в зависимости от масштаба/ширины).
-
Хотя вопрос про заливку снят... Она нужна, смотрб на чертежи.. используется. и часто. А как вы реализуете градиент и штриховку?
-
Заливка везде применяется, поскольку это не чертеж и все объекты имеют ширину. На картинках показан только схематик, там оно не очень актуально, хотя тоже применяется. А в PCB просто чертеж не катит, там должны быть дорожки, заливка медью и т.п. (если кто знаком с тематикой).
-
Градиент и штриховка не нужны, поэтому никак.
-
> [21] novarm (23.12.07 17:50) > просто чертеж не катит, там должны быть дорожки, заливка медью
Толщина линий = Масштаб*Коэффициент.
Как тебе мой алгоритм? )
-
> [23] homm © (23.12.07 17:52)
Так оно выродится также как и полик. :) Да к томуже толщину придется для каждого элемента указывать...
-
> [24] @!!ex © (23.12.07 17:54) > Так оно выродится также как и полик. :)
Ок.
Толщина линий = Масштаб*Коэффициент. Если толщина < 1, то толшина = 1.
-
В OpenGL достаточно выводить линии при помощи GL_LINES (толщина не меняется в зависимости от проекционной матрицы)... думаю, в DX безусловно есть аналог подобного "примитива"
-
В приципе если для вас переход к представлению всего через линии(заливку через них тоже можно реализовать, кстати) не вариант, то единственно что я могу предложить - вынести расчет картинки для нового масштаба в отдельный поток, тогда не будет секунды задержки.
-
При пересчете делается ширина не меньше единицы, но при масштабировании пересчета нет, поэтому поменять ширину я не могу. Теоретически можно анализировать какие треугольники исчезают и чего-то с ними делать при перегонке из массива в видуху, вчера пробовал - не очень получилось (штрих-пунктиры, а вставлять много операций чтобы точно высчитать направление и т.п. не очень хотелось, хотя может и не замедлит сильно), возможно на днях еще раз попробую или дам задание тому кто это собственно писал.
-
> [25] homm © (23.12.07 17:55)
Медленно. Расчет для миллионов объектов... убицца ап стену...
-
Сам уже больше года занимаюсь CAD системой, поэтому рекомендую не жалеть ресурсов и использовать OpenGL. Компьютеры проектировщиков - это считай Hi-end железо обычно. Насчёт вылета на забугорных машинах, в региональных настройках системы можно изменять знак запятой в дробях. Поэтому, FloatToStr и StrToFloat могут выдавать разные результаты на разных машинах. Решение - DecimalSeparator := '.' или ','
-
Новый масштаб не известен до того момента пока он не достигнут. Секундная задержка введена специально (т.е. если масштабирование закончено, то пересчитываем новую картинку).
-
> [28] novarm (23.12.07 18:00)
Кстати, есть вариант... Берем картинку, и каждый объект представляем в двух видах... как полик, и как линию. Рисуешь полик, потом сверху линию единчной толщиной. Пока полик невырожден, линия погоды делать не будет. Как только полик вырождается, линия берет на себя отображение примитива.
-
С точками и запятыми все решено давно уже, системе все-равно что будет введено (свои функции). Тем более у нас тоже настройки забугорные и английская винда. Вылетает не у всех, а только у некоторых товарищей. Хотя может где-то внутри D3D это действительно имеет место. В общем, пока тестим
-
> [29] @!!ex © (23.12.07 18:00) > Медленно
Что медленно? Я сомневаюсь, что нужнабольшая точность, и по пикселям будут мерить реальные размеры дорожек, так что считать нужно один раз при изменении масштаба. В крайнем случае можно объеденить дорожки в группы, по признаку « большие, меньше, крохотные» и считать по группам.
-
> [34] homm © (23.12.07 18:09)
ИМХО проще рисовать полик и сверху линию. хотя х.з. статистики на сей счет не имею...
-
Хорошая мысль с линией. В общем, если настройками D3D это никак не решить, то прийдется самим либо треугольники корректировать, либо линии дорисовывать.
-
OpenGL попробуем опционально в будущем (больше для совместимости с не-Windows). В этот же модуль его встроить, думаю, проблем не составит.
-
> [37] novarm (23.12.07 18:16)
Будут проблемы. DirectX - COM, а OpenGL - нет. Довольно сложно их синхронизировать, особенно если делать это "потом"
-
У нас все в своих массивах до выхода на DirectX, поэтому просто заменить инициализацию и процедуры вывода должно быть не сложно. Так что по идее синхронизировать их не нужно - будет все раздельно. Основная сложность была в преобразовании всего в треугольники и системе работы с буфером (своим).
-
> [39] novarm (24.12.07 14:10)
Матричные операции тоже отличаються значительно... Вам виднее вобщем то, но если хотите в итоге делать поддержку нескольких систем рендеринга, этим стоит озаботиться пораьнше...
-
Матричных операций у нас нет, тут они просто не нужны. Это уже потом как будем 3D визуализацию встраивать.
-
См. статью Triangle Rasterization Rules из DX SDK. Каких-то особых настроек здесь нет, разве что D3DRS_LASTPIXEL, но это не совсем то. Теоретически можно анализировать какие треугольники исчезают и чего-то с ними делать при перегонке из массива в видуху, вчера пробовал - не очень получилось (штрих-пунктиры, а вставлять много операций чтобы точно высчитать направление и т.п. не очень хотелось, хотя может и не замедлит сильно)Ну у вас же где-то высчитывается перпендикуляр к линии и величина смещения (т.е. толщина линии) при переводе её в треугольники: Вот она и формируется из залитых треугольников (два в середине и два веера на концах с кол-вом от 0 до 12 в зависимости от масштаба/ширины).Неужели сложно в этом месте поставить If Offset < MinOffs then Offset := MinOffs, где MinOffs определяется в зависимости от текущего масштаба. Вообще в данном случае, ИМХО, вполне можно перейти на ручной пересчёт в пиксельные координаты. Это же не 3D, всего 2 умножения и сложения на каждую вершину. Или (в свете последнего заявления, что матричные операции не используются) так и делается? Ещё относительно D3D/OGL для CAD (и в частности линий): http://rsdn.ru/forum/message/2743638.flat.aspx#2743638
-
В D3D решили вопрос изменением треугольников - вроде работает. Всем спасибо за помощь.
Начали OpenGL пробовать. В принципе, в нашу систему встраивается относительно несложно и разницы в скорости не наблюдается. По словам программиста система намного более мощная по функциям и удобная.
Также можно рисовать линии с заданными шириной и точки с заданным диаметром, что может существенно уменьшить размеры массива и соответственно увеличить скорость своих процедур. Вопрос: насколько замедляет систему переключение режимов? В D3D это сделало использование разных типов треугольников не применимым в нашем случае. В OpenGL для этого нужно будет хорошо перерабатывать систему пересчета и рисования, поскольку сейчас все рисуется треугольниками. А вот стоит ли игра свеч?
-
Также можно рисовать линии с заданными шириной и точки с заданным диаметром, что может существенно уменьшить размеры массива и соответственно увеличить скорость своих процедур.Я же давал ссылку на обсуждение. Там, в частности, есть другая ссылка, где демонстрируется, насколько по-разному могут рисоваться OpenGL-ные линии и точки на разном железе: http://homepage.mac.com/arekkusu/bugs/invariance/HWAA.htmlДа и относительно скорости: Но главное — нарисовать отрезок стоит гораздо дороже чем два треугольника, его образующие — буквально в разы.В связи с чем возникает подозрение, что все эти линии-точки произвольного размера эмулируются в драйвере через треугольники. Да и обычные, однопиксельные линии могут изрядно подтормаживать - попробуйте переключить ваш рендер в wireframe и увидите. Видимо, просто никому не нужно оптимизировать их рисование, т.к. игры используют почти исключительно треугольники. Вопрос: насколько замедляет систему переключение режимов? В D3D это сделало использование разных типов треугольников не применимым в нашем случае.Что такое конкретно "переключение режимов" и "разные типы треугольников"? Если quad/strip, то дело здесь не столько в смене режима, сколько в увеличении числа вызовов DrawPrimitive (лучше - меньше). В OpenGL, как пишут знающие люди ( http://sim0nsays.livejournal.com/9502.html ), "цена вызова" ниже. Но это, видимо, относится к VBO, a с glBegin/glEnd добавляется overhead от множественных вызовов процедур. В общем, затыков хватает и там, и там.
-
По ссылке читал уже всю тему, ну видимо ту инфу не выхватил Понятно, значит не будем заморачиваться. Спасибо!
Пока еще остается открытым вопрос с вылетом D3D на некоторых машинах забугорных пользователей. Логи не помогли - все инициализации ок и вылетает все время в разных местах. Пробовал компилить на последних делфях со всеми включенными проверками в компилере (пару раз это помогло) - ошибок нема.
-
> сколько в увеличении числа вызовов DrawPrimitive (лучше > - меньше).
Вы статью не поняли.
OpenGL рализованна как машина состояний. И есть возможность быстро переключать эти состояния в отличии от DX. За счет этого можно сыкономить процессорное время.
> поскольку сейчас все рисуется треугольниками. А вот стоит > ли игра свеч? Рассчеты упростяться. Насчет вывода.
> Но главное — нарисовать отрезок стоит гораздо дороже чем > два треугольника, его образующие — буквально в разы. > В связи с чем возникает подозрение, что все эти линии-точки > произвольного размера эмулируются в драйвере через треугольники. > Да и обычные, однопиксельные линии могут изрядно подтормаживать > - попробуйте переключить ваш рендер в wireframe и увидите. > Видимо, просто никому не нужно оптимизировать их рисование, > т.к. игры используют почти исключительно треугольники.
Тут не столько дело в драйвере, а сколько в видеокарте.
-
OpenGL рализованна как машина состояний. И есть возможность быстро переключать эти состояния в отличии от DX.
D3D практически такая же машина. Даже по синтаксису видно: SetRenderState, SetTextureStageState. И вряд ли смена состояний через OpenGL принципиально быстрее. Т.е. на аппаратном уровне оно не может быть быстрее, это та же самая видеокарта. И на программном все трюки для уменьшения накладных расходов примерно одинаковы: кэширование команд (в OpenGL есть команды управления кэшированием glFlush/glFinish, про D3D написано в статье), средства для создания больших блоков команд (дисплейные списки - теоретически они более продвинуты чем D3D-шные state blocks, т.к. могут включать команды рисования; практически же именно ролью state blocks они и ограничены, а рисование, в конечном итоге, сведено к D3D-стилю - VBO). В общем же, цитируя последний комментарий к статье, в OpenGL "DIP cost [и, видимо, переключения состояний тоже] действительно меньше, но проблема балансировки рендера никуда не уходит". Точнее, проблему можно решить, если использовать вместо общепринятого у геймдевелоперов VBO старые добрые glBegin/glEnd - с ними можно не думать о количестве реальных обращений к видеокарте, драйвер сам разделит данные на блоки оптимального размера и отправит по мере необходимости. При этом следует помнить, что производительность glBegin/glEnd далеко не дотягивает до теоретического максимума видеокарт, другой вопрос, понадобится ли этот максимум для рисования чертежа. Если (что вполне вероятно) не понадобится - OpenGL действительно будет более простым решением. Впрочем, при наличии готового D3D-кода никаких преимуществ переписывание на OGL не даст, кроме разве что "отвязывания" от DX runtime.
-
В общем сделали и D3D и OpenGL (для совместимости с не-виндоус). Итог: 1. D3D чуть быстрее, вывод текстур (картинки и TrueType шрифты) проще. Из недостатков сложнее реализация и долго отлаживать (много скрытых недочетов типа зависания после хранителя экрана, попеременная работа не на всех картах, и т.п., которые то появляются, то исчезают - пришлось поиграться с инициализациями/деинициализациями, параметрами). 2. OpenGL - рисует в нашей реализации чуть медленнее (встроили в ту же модель треугольников). Сложность с реализацией текстур (программист долго разбирался и говорит что сделано через...). Также очень заметно падает скорость при появлении текстур на некоторых видеокартах. Возможно не до конца использовали возможности OpenGL (матриц нет, например), поскольку встраивали в ту же модель которая изначально писалась под Direct3D и долго с ней не возились.
p.s. Если кому нужен быстрый алгоритм (процедура на паскале) разложения любого полигона (вогнутого, с само-пересечениями и т.п.) на треугольники пишите на мыло. В инете искали - ничего толкового не нашли, сделали свое в итоге.
-
> Сложность с реализацией текстур (программист долго разбирался > и говорит что сделано через...).
Свяжись со мной по почте(BasovAV@gmail.com). Возможно вы что-то не так делаете с текстурами, ибо никаких проблем не обнаружено.
-
> Также очень заметно падает скорость при появлении текстур > на некоторых видеокартах.
в свое время была обнаружена обратная закономерность, текстуренные объекты рисуются быстрее залитых цветом... Есть основания полагать, что где то у вас косяк...
|