Pull to refresh

Comments 120

Чуть сердечный приступ не хватил, когда открыл главную хабра. За материал спасибо!)
Возвращение чёрного властелина?)
Круто! Продолжайте пожалуйста =) Давно такого ждал.
Очень интересная статья. Примерно такой же материал нам читали в вузе, но, к сожалению, как-то не дочитали. Жду остальные части!
У нас так же читали и так же толком не дочитали, честно говоря так никто и не сделал алгоритм на лабораторных работах на сколько я помню — откуда-то честно вязли и даже все обещали разобраться… Вот видимо и настал этот момент.

Вы молодец продолжайте цикл статей. С нетерпением жду продолжения.
Супер. Именно то, что нужно для понимания основ и того, «как все работает».
UFO just landed and posted this here
Как печально, что Вы преподаете не в России. За такую статью я бы пошел учится к Вам. Я думаю каждый программист мечтает творить 3D, но времени на изучение тонны книг, не хватает. Вы за 5 минут объяснили, как отрисовать сетку.
Спасибо на добром слове, но ведь интернет для того и придумали, чтобы не сидеть рядом. Называйте темы, которые Вас интересуют, с меня обучающие статьи.
Эм. Извините заранее, не обижайтесь на сказанное дальше, просто накипело.
Почему-то у нас каждый винит не себя, а надуманное отсутсвие хорошего образования, преподавателей, страну, президента, судьбу и нехватку времени. Я закончил обычный гос. ВУЗ, бесплатно, со стипендией и общагой, коих много по стране. У меня и в мыслях не было ругать наше образование… было куча интересных предметов: линейна алгебра, аналитическая геометрия, алгоритмы и структуры, инженерная, компьютерная графика, всякие схемотехники и т.д. и т.п. После всего этого заявлять «Как печально, что Вы преподаете не в России»? Что такого сверхъестественного в отрисовке сетки? Да после всего, что проходишь в ВУЗ-е, это все выглядит смешно. Если вам нужно объяснять как отрисовать сетку, а после этого вам не стыдно, то что вы за программист и как вообще вы закончили ВУЗ?
Хватит ныть, вы инженер или кто? PHmaster еще мальчиком вон в 90-е рисовал 3Д кубики ( коммент снизу ). А сейчас в мире интернета — вообще лафа. Столько информации хоть попой кушай и благодаря таким людям как haqreu ее становится еще больше.
Вам не хватает времени? Блин мне скоро 30 лет. Вам и не снилось сколько времени нужно уделять семье, работе, отдыхать еще надо и т.п. но я каждый день нахожу время изучить что-то новое. Работа у нас такая. Не можешь — иди в макдак.

P.S. да статья очень понравилась. И я думаю многие преподаватели смогут перенять эту практику. А студенты могли бы просто преподавателю предложить данную статью как источник.
Обычный госвуз это прекрасно, и самообучение это прекрасно. Я вам только один пример приведу: родители у меня инженеры, и как-то так получилось, что я окончил матмех ЛГУ, и в итоге занимаюсь математикой и программированием.

Я абсолютно не жалуюсь на судьбу, но. Когда я выбрал эту профессию, я не отмёл сознательно все остальные одну за другой. У меня даже выбора особо не вставало, шёл по накатанным рельсам. А если бы я когда-то понял, что мне вполне по силам стать пилотом гражданских авиалиний, кто знает, как сложилась бы моя судьба? А хирургом?

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

Основная проблема (любого, не только нашего) образования в узкой зашоренности. Нам не показывают (а кому это надо, нам показывать?) всей ширины выбора. В частности мне очень нравится система, когда у нас есть некий костяк лекций, а спецкурсы выбирать можно по желанию. Только когда я учился на матмехе, у меня спецкурсов на выбор было три из трёх. Опять, я не сразу вообще понял, что могу программировать компьютерные игры или писать рендеры для 3д фильмов. Мне на это понадобилось много времени.

Цель моих статей в том, чтобы показать, что это под силу любому начинающему программисту. Если он захочет этим заниматься — прекрасно. Не захочет — его выбор. Я не хочу показать революционный метод, я хочу дать возможность человеку выбрать.
Обычно к 3му курсу люди уже вполне взрослые и осознают свою будущую профессию, пробуют лезть и туда и сюда. Интересуются кем же они могут стать в будущем. Люди пробуют работать в разных сферах. Приведу в пример моего одногруппника, который на 3м курсе понял, что хочет действительно стать пилотом гражданской авиации, сдал сессию, уехал в Ульяновск и сейчас летает международными рейсами. Кто-то осознает это раньше кто-то позже.
Я не умаляю ценности вашей статьи особенно для студентов, стоящих перед выбором дальнейшего пути своего развития. Наоборот, целиком поддерживаю. И в наших ВУЗ-ах хорошо бы расширить круг спецкурсов, но это уже совсем другая история. И вполне возможно, что это даже не проблема вузов, но если учебное заведение возьмет на себя такую ответственность, то это, наверно, очень хорошо, но мы пока к этому еще только идем. А пока нужно писать побольше таких статей, что очень сильно поможет будущим профессионалам.
P.S. но все-же я склоняюсь к тому, что всю ширину выбора можно и не показывать, интересующийся сам может придти к выбору. Но может я и ошибаюсь.
Я с Вами полностью согласен. Особенно, что касается "… Почему-то у нас каждый винит не себя, а надуманное отсутствие хорошего образования, преподавателей, страну, президента, судьбу и нехватку времени..."
Но позвольте Вам рассказать историю преподавания ПРОФИЛЬНЫХ предметов в моем госвузе. Приходил преподаватель с ноутбуком и проектором. Заводил презентацию на стене, давал нам 15-20 минут на переписывание содержимого слайдов в тетрадь, выдавал бумажку с вариантами заданий, записывал кто какую задачу выбирал и уходил. И поверьте, задачи очень часто выходили за рамки той информации из слайдов. Кому было интересно — изучали, кому было безразлично — договаривались с теми, кому было интересно. А если, не дай Бог, ты обратишься за помощью к преподавателю… Сколько презрения можно было в свой адрес получить… Таким образом нас «научили» программировать на PHP, C/C++, Java, JS. Но оба доцента кафедры безгранично гордились(уверен, что и сейчас ничего не изменилось) своими познаниями двумерных списков на Pascal'e.

ps Мне тоже скоро 30 лет :) И мне не только снится сколько времени нужно уделять семье, работе и отдыху, но даже получается все это вполне успешно совмещать. Да, работа у нас такая. Не можешь — иди в макдак! Тут в точку!
Спасибо за поддержку. Вы дополнили мою мысль. Универ — школа жизни, которая учит, что ты нахрен никому не нужен и, что никто тебе ничего не должен. Потому-то они и преподаватели, а не учителя.
У меня в МФТИ курс сравнимого содержимого был, как тех.курс по выбору. И сейчас он все еще есть, если мне не изменяет склероз.
Зачем Вы это написали? Я рад за Вас. И в то же время печален, так как уверен, что спецкурса по современному танцу там наверняка не было. А вдруг бы из Вас получился отменный танцор?
Думаю, это к тому, что есть и нормальные заведения, где вполне неплохо преподают. Но что такое МФТИ в сравнении со среднестатистическим техническим вузом?
Я окончил матмех ЛГУ, это не среднестатистический техническое ВУЗ. И преподавали на нём весьма печально. Даже если забыть про кругозор, на кафедре геометрии отделения чистой математики наисвежайшие теоремы, которые упоминались, датировались в лучшем случае сороковым годом. Все достижения современной топологии прошли мимо.
Тут мне сказать нечего, может, в ЛГУ так и есть, не знаю. С другой стороны, на Хабре есть несколько циклов статей, созданных преподавателями из не самых крутых вузов, но при этом глубина и доступность изложения достойна MIT.
И, если не секрет, какова общая картина по трудоустройству среди ваших одногруппников? Каков примерный процент уборщиц, охранников, слесарей?
И не сочтите за оскорбление, но вуз — мужского рода и маленькими буквами.
По пунктам:
1) Я вовсе не претендую на звание учителя года

2) Я не отрицаю наличие хороших учителей ни в одной точке мира

3) Среди моих одногруппников нулевой процент уборщиц, охранников, слесарей. Но это ни разу не говорит о качестве обучения. Реально, во время моего обучение приобретение адресной книги было во много, много раз ценнее приобретения знаний по функциональному анализу.

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

5) ВУЗ может быть существительным, может быть аббревиатурой. Если уж на то пошло, то в моём сообщение вовсе было несогласование родов: «среднестатистический техническое».

6) Я не знаю, как Вы, я этап граммар-наци прошёл очень, очень давно. Сообщения об ошибках уместны там, где текст можно поправить. Например, в теле статьи.
4,5,6) У меня и в мысли не было Вас обидеть, извините. Я руководствуюсь тем, что поскольку мы находимся в публичном пространстве, вполне уместно указать на популярную ошибку, чтобы люди, прочитавшие моё сообщение, возможно, в будущем её не совершили. И я не грамма-наци, сам косячу регулярно, но я считаю, что указывать на подобные ошибки необходимо, и буду рад, если мне укажут на мои, особенно публично — так усвояемость лучше. :)
www.gramota.ru/spravka/rules/?rub=sokr
Я отвечал не вам, а inook. И ответ был к тому, что и в России можно (пока ещё?) найти правильные места и правильных преподавателей.
А что до танца — ошибаетесь, на физтехе есть довольно приличная тусовка, занимающаяся историческим танцем, а что?
Вопрос качества обучения — холиворный, ни к чему, кроме как к подбитому глазу у каждого из собеседников привести не может. Предлагаю тему закрыть. Мне холиворы ещё в конце девяностых надоели.

Я доволен пятью годами, проведёнными в на матмехе ЛГУ :)
Эх, аж ностальгия пробила. Помниться, в далекие 90-е, когда еще интернета у меня не было, попался мне в прокате диск с кучей текстовиков о программировании, в том числе и о 3д-графике. И долгое время я сидел под ДОСом на видеокарте без 3d-ускорения, не желая переходить на Win95, и изобретал свой собственный велосипед в виде 3D-рендера под 320x200 (без всяких там VESA с его космическими разрешениями и DOS4GW с его «безграничными» размерами оперативки, которые я все же открыл для себя немногим позже). И вот такого структурированного и последовательного цикла статей очень сильно мне тогда не хватало. Помню даже, мне удалось таки сделать вращающийся текстурированный 3D-кубик (и для текстур я тоже использовал формат TARGA), но потом я все-таки плюнул и ушел на Win+Direct3D.

Респект за статью и за это ваше начинание. Сейчас очень многие вновь испеченные «программисты» хватают что-то вроде Unity 3D, и не обладая знаниями ни в программировании, ни в 3D-графике, сразу же бросаются в геймдев. Такие статьи помогут им хотя бы в общих чертах понять, как работает то, что они делают. Ну а для тех, кто изучает программирование систематически — это тоже может быть архиполезно.
Сейчас очень многие вновь испеченные «программисты» хватают что-то вроде Unity 3D, и не обладая знаниями ни в программировании, ни в 3D-графике, сразу же бросаются в геймдев

И я часто им завидую… Иногда кажется, что я сижу в капкане «собственный костыль» в то время, как другие хватают «Юнити», «кокос 2д» и не зная толком «нутра» и внутренних алгоритмов, штампуют кросплатформенные приложения. Но, может, в этом и есть сила пришедшего времени и к этому все идет, что рядовой разработчик не должен уметь делать «сортировку» руками, а должен уметь подключить нужную библиотеку и использовать ее?

Что толку от моих глубоких знаний и пониманий алгоритма, если он отлично реализован в доступных 100500 библиотеках? Может подрастающим программистам как раз и надо в основном учиться ориентироваться в том, что уже написано (а его — ОЧЕНЬ много)? Ведь большинство из них реже будет писать «свое» и чаще использовать «чужое». Я, честно, не знаю…

Вот последний мой отрицательный пример: понадобилось на работе делать поиск пути в графе (С++). И мне проще было написать его самому, чем разбираться в boost::graph. Что же в этом хорошего?
Наипервейшая цель пониманий алгоритма не для того, чтобы его переписывать каждый раз. А для того, чтобы не напарываться на грабли, когда используешь чёрные корбоки. Вы себе, видимо, не представляете, как часто я вижу людей, хранящих указатели на элементы std::vector. А потом однажды случается reallocation. И сегфолт. Куку. И они вообще не знают, откуда это вдруг?!

Вторая цель: бустовский путь в графе — это прекрасно. Это быстрый способ получить рабочий код. Только он работает на любых задачах. А если у вас весьма специфичный граф, например, просто решётка, то ваша собственная реализация будет работать в разы, а то и на порядки быстрее.

Мой проект рассчитан на тех, кто в ступоре останавливается перед четырёхмерными векторами в OpenGL. На тех, которые не понимают, откуда обратные (да и ещё транспонированные!) матрицы при подсчёте нормальных векторов.
Я не пытался поругать ваш проект. Его цель ясна и я ее поддерживаю. Я затронул немного философскую сторону.

Хранение указателей на элементы std::vector… Если человек знает, как устроен вектор внутри, то он не совершит такой ошибки. Но ведь все-таки это не проблема «знай, как работает контейнер», а это проблема «знай, как пользоваться контейнером». В случае с вектором — это звучит немного абсурдно, конечно.

Сейчас программисты в качестве кирпичей своих программ используют одиночные функции, небольшие классы, циклы, операторы и пр. Не идет ли все к тому, что через 100 лет мы будем использовать не кирпичи, а сразу огромные готовые дома? Уже сейчас, особенно в веб программировании, проявляются языки и библиотеки, где программа может выглядеть как-то так: {New HttpServer(); Create Forum();}. Не будетут ли через 100 лет программы выглядеть так: {do MakeVsioKruto(); SdelaiEschoKrucheNa(5%);} :-)

За время обучения в среднего человека можно запихнуть ограниченный набор знаний и навыков. Умения искать, ориентироваться, подключать и использовать, выбирать инструменты — очень важны и не тривиальны. Человек будет лишен таких навыков, если чрезмерно нагрузить «базой», тем более, если эта «база» — база прошлых лет, а не настоящего.
Да, именно do MakeVsioKruto() и будет. На мощных компьютерах. А появится мириад маломощных. Нетребовательных к питанию. Ассемблер умрёт ой как не сейчас. Будет всё большее и большее разделение между классами программистов. Вам выбирать, куда вы хотите примкнуть.
Ну, я говорю про «серую массу большинства» программистов. 20 лет назад на ассемблере писали все программисты. Сейчас их, наверное, не стало меньше, но в процентном соотношении их число ничтожно. Почти так же, как ничтожно число тех, кто ДОЛЖЕН сам писать сортировку и алгоритмы схожего уровня. Нужно ли студентам учить эту «сортировку»?

Опять же, я не ругаю ваш труд, я становлюсь на защиту «вновь испеченных «программистов»», о которых упомянул товарищ PHmaster.
Я тоже, признаться, немного завидую. Когда-то геймдев был моей мечтой, которую до сих пор я так и не осуществил. Одна поделка-клон для игры вчетвером с друзьями на одной клавиатуре не считается. А недавно я читал на хабре статью, как человек, не зная языков программирования, услышал о Unity3D, скачал, установил, научился заодно как-то что-то программировать, запилил несколько несложных игрушек и выложил их продаваться то ли в App Store, то ли в Google Play. Вот так вот незатейливо это сейчас делается. Понятно, что если дальше он захочет заниматься этим более серьезно и писать более сложные игры — ему придется разбираться в тонкостях. Рано или поздно настанет момент, когда возможностей Unity 3D ему станет не хватать. Не знаю, может, к тому времени он уже разбогатеет и сможет нанять команду толковых специалистов, а может его интерес не угаснет и он будет выискивать и читать такие вот статьи, чтобы самому участвовать в процессе разработки.
Могу всем, кому статья понравилась, посоветовать схожий цикл статей по написанию 3д движка «с нуля»:
blogs.msdn.com/b/davrous/archive/2013/06/13/tutorial-series-learning-how-to-write-a-3d-soft-engine-from-scratch-in-c-typescript-or-javascript.aspx
В качестве языков там используются c#, javascript или TypeScript одновременно.
В принципе, всё то же самое, но подобная информация лишней не бывает.
Спасибо за ссылку, я пойду немного дальше, мне интересны шейдеры.
UFO just landed and posted this here
Тоже хорошая вещь. Но я не хочу трогать OpenGL до тех пор, покуда не перепишу его с нуля сам. Ну, на пять сотен строк перепишу :)
Подобные уроки предполагают использование графической библиотеки в качестве чёрного ящика. Я хочу сделать ящик прозрачным.
Сейчас балуюсь с Irrlicht и шэйдерами и очень интересно было бы узнать побольше всяких вещей «под капотом». Жду продолжения!
UFO just landed and posted this here
Так там вроде код ну очень простой. Я, зная только пару скриптовых веб-языков сумел его портировать на go без особых проблем (не имея опыта ни в плюсах, ни в go :-) )
UFO just landed and posted this here
У меня нет никакого опыта в шарпе (и винды под руками тоже нет).
Но ценность моего кода почти нулевая. Весь цикл рассчитан на самостоятельное написание всего кода. Я только генеральную линию партии показываю. Пишите на шарпе, выкладывайте на гитхаб, я помогу (чтением, я не писатель на шарпе).

У меня студенты не все пишут на C++. Разброс идёт от питона и R до чуть ли не ассемблера.
UFO just landed and posted this here
Мне кажется в данном цикле(?) статей адаптация под какой то ЯП не очень важна. Главное знать суть/алгоритм, а язык реализации это уже одна из последних вещей.
— Вы за меня и есть будете?
— Ага
©
Вы уверены, что вам это нужно? Статья обучающая, на практике для решения задачи надо использовать OpenGL или DirectX: они многое сделают из коробки, быстрее и лучше.
UFO just landed and posted this here
Я думал, что вполне очевидно, что моим кодом нельзя пользоваться в конечном продукте. Я даю проект, который обучает OpenGL и Direct3D. А вы предлагаете воспользоваться ими сразу.
Я, например, разбирался с OpenGL, неделю медитируя на Красную книгу и теперь, в принципе, знаю, как воссоздать основной конвеер «вертексный шейдер -> создание примитивов -> пиксельный шейдер». Понятно, что сначала придется подсмотреть пару алгоритмов, но сверхъестественных препятствий не вижу.
С чем вас и поздравляю. Я с этим разбирался, тупя в файлы заголовков .h на SGI без доступа к красной книге. Мне за это медаль выдать?

Где я заявлял, что просмотреть мой туториал — это единственный способ понять, как работает видеокарта? Не нравится? Уже переросли? Ну так проходите, не задерживайте движение. Для чего вы написали ваш комментарий?

Ещё один учебник — это ещё один учебник. Ни больше, ни меньше.
Никакой революции я не предлагаю. У меня есть только одна особенность (не я первый, не я последний): я не приемлю долгого обучения без практики. Неделю медитировать не написав ни одной программы — не мой случай. Я не могу.
Я имел ввиду, что человек, не разбирающийся в вопросе, может подумать, что в реальных проектах так и надо — самому рисовать отрезки, реализовывать Брезенхэма и т.д. Чтобы этого не случилось, уточнил, что на практике используют OpenGL, DirectX.
Далее, если мы попробуем этим кодом нарисовать вот такие линии:

line(13, 20, 80, 40, image, white);
line(20, 13, 40, 80, image, red);
line(80, 40, 13, 20, image, red);

То выяснится, что одна линия хороша, вторая с дырками, а третьей вовсе нет.

Понятно, что третьей вовсе нет — первая линия рисуется из точки (13,20) в точку (80,40), а третья из точки (80,40) в точку (13,20).
Мне просто интересно, какой результат вы надеялись получить?
Третья другого цвета, я надеялся перекрасить первую в красный цвет. Это тест на симметричность: результат отрисовки сегмента не должен зависеть от порядка точек: сегмент (a,b) дожен быть ровно таким же, как и сегмент (b,a).
Желательно пояснить это в статье. Потому, что третья появится только, если тест на симметричность будет провален, во всех остальных случаях можно сказать, что третьей(n-ой) нет.
Ну, белую прямую мы видели на предыдущих тестах. В лучшем (худшем? :)) случае она будет закрашена красной. Сейчас поправлю, спасибо.
Спасибо за интересный материал.
Еще поправочка:
Обратите внимание, что первая и вторая третья строчки (в коде) дают одну и ту же линию разного цвета.
А что мешает так захотеть?
Великолепная статья, сейчас потихоньку ковыряю google go, решил практическую часть заодно писать на нём — пока никаких серьёзных проблем не возникло, а пользы — в два раза больше :-) Огромное спасибо за то, что так просто изложили очень интересные вещи. С нетерпением жду продолжения!
Подобный код ведь просто сожмет модель по оси Z и выведет её. А будете ли вы писать о матрицах трансформации (World, View, Projection и их аналоги в OpenGL) с переводом моделей в мировую систему координат, с реализацией камеры (View) для перевода в видовую систему координат и с Projection для перевода в «экранную» систему координат?
Да. Вся эта канитель с самописным OpenGL для того, чтобы рассказать, что такое шейдеры. Мне не очень ясно, почему сразу претензии к проволочному рендеру, я же дал в самом начале финальный рендер. Без шейдеров такого не получить. А для этого нужна геометрия и понимание разных систем координат.
Да, я сделал проволочный рендер с тупым преобразованием (v1.x+1.)*width/2.;
Но это только для того, чтобы мои читатели не теряли интерес. Позже это будет заменено на нормальное преобразование ModelViewPort. Но для этого сначала надо рассказать, что такое однородные координаты.

Я категорически против того, чтобы кирпичик за кирпичиком выкладывать код, который не даёт красивых картинок. Просто рисовать сегментики… Брр.

Я люблю писать код, который будет потом выкинут (переписан). Я хочу видеть сразу как можно больше. Переписать код быстро, а интерес не теряется.
Не, вы все правильно сделали: если бы в статье я увидел только, как нарисовались отрезки, то закрыл и забыл бы. А теперь есть шанс, что узнаю, что такое шейдер внутри, если вы не поленитесь писать дальше :-)
Я ни в коем случае не имею претензий к статье, очень кстати будет для новичков! Вы молодец!
Просто, я ожидал преобразование координат через матрицы ModelViewPort, и финт с (v1.x+1.)*width/2; не совсем понял.

P.S.
А пайплайн у вас в конечном счете будет иметь все стандартные этапы, типа вершинного шейдера, геометрического шейдера, растеризатора и пиксельного шейдера?
Геометрический шейдер посмотрим, у меня нет планов сделать программного монстра, хочется компактный код. Вершинный и фрагмент шейдеры будут точно.
Ну вы же ведь расстеризатору не будете передавать вершины, вы будете передавать собранные примитивы :)
Всякие значение там интерполируются между вершинами собранного примитива: UV например, для пиксельного шейдера.
Сборщик примитивов — это не геометрический шейдер. Позже разберём.
А какая по вашему стадия следует перед растеризатором и пиксельным шейдером? :)
Сборщик примитивов. А перед ним геометрический шейдер.
Подсказываю
image

А чем по вашему занят геометрический шейдер, какая у него функция в пайплайне? :)
Беру свои слова обратно, забыл, что GS способен оперировать соседними примитивами, а перед GS идет Primitive Assembly не программируемый :)
Есть замечательная книга, которую читал на заре обучения 3D, довольно старая, но там, так сказать, 3D с нуля.
«Программирование трехмерных игр для Windows. Советы профессионала по трехмерной графике и растеризации» — Андре Ламот
www.ozon.ru/context/detail/id/1692806/
Лично я был шокирован вот этой книгой. Даже без примеров с дискет она позволяла рассказать, как написать игру типа wolfenstein. И я это сделал. Да, это был 95й год, да, через полгода выйдет квейк. Но я сам написал игру. Это изменило мою жизнь :)
Шикарная книга. И сейчас стоит на полке. Но на ее освоение в то время у меня потребовалось много времени и сил.
UFO just landed and posted this here
Отличная статья! А как быстро планируете написать остальные части? А то после прочтения этой сразу хочется продолжения.
Я прямо сейчас в оффлайне читаю этот курс. Ну, чуть более развёрнутый, конечно. Так что, примерно раз в неделю, может чуть чаще.
Жуть какая :) Ну, надеюсь, следующие статьи будут намного более «ёмкие» и их содержания хватит, чтобы не сильно «голодать» в течение недели.
Автор по-видимому вдохновился книгами Андре Ламот? ;)
p.s.: ага, увидел коммент выше, так и есть ))
У меня была одна его книга в 95м году. И я на неё уже даже ссылку дал. Да, она оставила неизгладимое впечатление.
Еще, кроме ламотовских, очень классная книжка Шикина и Борескова «Компьютерная графика. Полигональные модели». Очень рад был заполучить ее и эту в бумажном виде.
С темы 2d/3d графики и начался мой путь как разработчика… Жаль, что утеряно все(
По моему опыту, бывает так, что профилировать имеет смысл только в Release-сборке с включенными оптимизациями. Когда профилируем сборку без оптимизаций, есть риск потратить время на то, с чем компилятор может справиться и сам. К тому же в Release могут отключаться разнообразные проверки на границы массива и т.п., что приведет к увеличению производительности библиотечных функций.
Согласен, но это всё не тема обсуждения. Спасибо за уточнение.

Я вообще не хочу писать здесь оптимизированный код, я просто показал, как писать целочисленного брезенхема для расширения кругозора. Всего этого в моём коде не будет, оптимизированный код зачастую гораздо длиннее и нечитабельнее, не моя цель.
Автор молодец! Интересная тема, приятное и доступное изложение материала.
Большое спасибо! Очень важное дело делаете!
Я ещё советую почитать как это делается в живых OpenGL либах к примеру на счёт линий: cgit.freedesktop.org/mesa/mesa/tree/src/mesa/swrast/s_lines.c (ну и ещё интересен вариант с AA)

Ну и конечно не всё так просто и легко когда начинаешь работать с железом, там немного иной «язык».

ЗЫ мне кажется mesa вообще классная библиотека для изучения компьютерной графики. К примеру реализация простого растеризатора через Gallium
cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/softpipe
мне кажется вполне простой и наглядной.
А Вы тестировали на производительность?
Сколько примерно линий в секунду можете нарисовать?
А почему у вас тег открывается как
script type=«text/objmodel» id=«model»
а закрывается как
/div
?
С div просто задумался, видимо, и закрыл не тем, да, это уже заметил.

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

Вот немного продолжение:
1. jsfiddle.net/2wvyga24/8/ — простейшая заливка по z-координате.
2. jsfiddle.net/2wvyga24/15/ — свет. Очень долго не понимал, в чём проблема при рисовании, а, оказывается, при вычислении нормали использовал экранные координаты вместо мировых :)

В вашей версии мне не совсем понятно использование EventEmitter и других библиотек :). Думаю, логичнее было бы подключить SylvesterJS, чтобы не писать матрицы и вектора заново.
В вашей версии мне не совсем понятно использование EventEmitter и других библиотек :).

Ну, просто мне лень было вычищать — они от другой наработки остались.

нативные линии рисуются быстрее пиксельных Брезенхэма

У меня — наоборот, моя фукция где-то процентов, наверное, на 20 быстрее работает — я не слишком глубоко проводил сравнение, но на моей машине моя функция 300 тысяч линий рисовала за 2-3 секунды, а нативная — за 3-4 секунды.
А я вот теперь задумался, а как же мне z-буфер делать, если не отказываться от использования нативных треугольников… :(
Есть идеи?
Может, можно как-нибудь извратиться с globalCompositeOperation… Впрочем, лучшим вариантом, я думаю, будет всё же отказаться от нативных треугольников.

Я переписал по-нормальному класс CanvasGL: если раньше любая точка вставлялась на canvas сразу же, то теперь функции изменяют лишь внутренний буфер класса, а функция put отдельно его вставляет.

Результаты неплохие
	Нативные / пиксельные
	- 10: 0.8 / 10
	- 100: 1 / 12
	- 1000: 130 / 22
	- 10000: 1350 / 65
	- 100000: 18220 / 482
	- 1000000: нет / 4700

(думаю, доп. тормозом был ранд, но тем не менее).
Да, я сразу сделал отрисовку через ImageData и putImageData, и _линии_ отриовывались очень даже резво — даже быстрее, чем через beginPath-stroke, но вот треугольники оказались сразу в несколько десятков раз медленнее :(

Вот думаю, как быть… Толи отказаться от производительности, то ли придумывать что…

Ссылка предыдущая нерабочая оказалась. Вот тут освещение меняется, когда мышкой водишь: jsfiddle.net/yecgozrt/4/
:)
Да, ссылку нашёл сразу, симпатично.

С треугольниками ситуация та же:
	Native / Pixel:
	1		0.4 / 15
	10		0.9 / 50
	100		1.1 / 380
	1000		10 / 3988
	10000		69 / 47210


Думаю, надо искать более подходящий алгоритм.
Ну либо производительностью придётся пожертвовать.
Например, появилась идея заливать треугольник диагональными линиями:
for(var ab_x = ax; ab_x < bx; ab_x++){
    var t = (ab_x - ax) / (bx - ax),
        ab_y = (1 - t)*ay + t*by | 0,
        bc_x = (1 - t)*cx + t*bx | 0,
        bc_y = (1 - t)*cy + t*by | 0;
    this.line(ab_x, ab_y, bc_x, bc_y, color);
}

И да, это на самом деле оказалось быстрее, но треугольник получается с дырками.
Я, наверное, тут не самого далекого ума, но я не очень понял как работает рендерер. Во-первых, почему face-ы определены три раза по три вертекса и, во-вторых, как-то не объеснено про сам рендер. Как он трехмерные полигоны выводит на двумерную плоскость. Цикл то простой, но понять его не получается.
Про z-координату треугольников в данном месте мы просто забываем, используем только xy. Это получается ортогональная проекция на плоскость Oxy.

Массивы со строчками v, vn и vt задают вершины в геометрическом и в текстурном пространствах.
f задаёт связь между этими вершинами, в строчках f хранятся индексы из массивов вершин v, vt и vn. Ссылка на формат obj в статье дана.
Во-первых, можете прочитать про алгоритм Брезенхэма и про устройство wavefront.obj.

почему face-ы определены три раза по три вертекса

Формат феса:

f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3

v* — это номер вершины в общем списке
vn* — это номер описания позиции данной вершины на текстуре
vt* — это номер нормали к поверхности в данной точке
Крутой цикл лекций, спасибо! Многое узнал.
Интересно, в рендере пакета 3DS Max тоже используются все эти описанные Вами идеи? Или, например, в рендере V-Ray…
Там используется трассировка лучей. Это не совсем то же самое, о чём говорю я, но пересечение очень немаленькое.
Каждое ребро(кроме внешних) у нас дважды прорисовывается.
Расскажите, пожалуйста, зачем нужно вот это преобразование в конце?
            int x0 = (v0.x+1.)*width/2.;
            int y0 = (v0.y+1.)*height/2.;
            int x1 = (v1.x+1.)*width/2.;
            int y1 = (v1.y+1.)*height/2.;

Преобразование координат из диапазона [-1; 1] в диапазон [0; width] или [0; heigth]. Об этом есть в статье.

UFO just landed and posted this here
Именно так. Вкратце про фичи — TGA может представлять как уровни серого, так и RGB/RGBA. Сохраняется либо вообще без сжатия, либо с RLE сжатием. А уж про то, как устроены заголовки и прочее — это точно в спецификации смотреть, там ничего хитрого.
Спасибо большое. Такую бы статью -дцать лет назад )
Как выглядит простейший код… Видимо, как-то так:

второй день пытаюсь понять, как работает формула
int x = x0*(1.-t) + x1*t;
если мне даже это так сложно, то лучше отложить это в сторонку?

Банальная математика же. Ставим точку на отрезке между x0 и x1, поделив его в отношении t:1. Возможно, формула будет более понятной в виде x0 + (x1 - x0) * t.

вот… ДА! вот теперь эта формула ясна как день!
только не пойму, почему автору её сразу было так не записать
Ну, наверное, потому, что (1-t) и t — это барицентрические координаты точки x относительно точек x0 и x1? Барицентрические — это когда мы груз общей массой в 1 килограмм кладём в две кучки: (1-t) кг в точку x0 и t кг в точку x1. Тогда центр масс системы вычисляется по правилу рычага: x = (1-t) x0 + t x1. Вам понятнее эквивалентное определение x0 + (x1-x0) * t, мне понятнее барицентрические координаты.
ясненько. но замечу, что в этом случае 2 умножения и оно немножечко медленнее.
пытаюсь прогрызться дальше. сильно мешает незнание С++
вот вычислительная сложность меня волнует в последнюю очередь :)
А C++ тут при чём? Пишите на любимом языке!
так прочесть ваши примеры — надо понимать что написано
а то я сунулся в описание класса… да и высунулся обратно
=)
А не надо читать мой код, пишите свой!
Я разбираю алгоритм из чужого кода, если не понял объяснение словами. Иногда это бывает доходчивее, особенно если учесть, что я в терминологии очень плаваю. Наконец-то разобрался в Брезинхеме. Пришлось ещё вынуть из шкафа несколько пыльных книжек — Шикин, Уилтон, в Вику слазить.
Везде разными словами, и везде становилось понятно по одной детальке — зачем домножаем на dx, зачем сравниваем с 0.5, как переворачиваем x и у, итд.
Наконец-то почти всё заработало — осталось ещё обработчики всяких исключений добавить типа выхода координат за пределы размеров изображения, отрицательных значений.
спустя 2,5 месяца, я таки это родил! :D

image

пока что на C в DOS(box)
можно двигаться дальше =)

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

Однако опыт программирования на спектруме уже был, и при отрисовке линии с 256 оттенками серого хотелось получить что-нибудь более интересное и не доступное ранее. Так у меня появилась мысль, что точку с дробными координатами можно отрисовать через 4 пикселя с яркостью, пропорциональной площади перекрытия этой точки. Результат получился не очень — при движении эти точки ощутимо моргали, и я применил грязный хак в виде функции sqrt. В последствии оказалось, что хак не такой уж и грязный и называется гамма-коррекцией — только показатель степени обычно берут не 0.5, а 0.45.

Вбивать вручную координаты вершин тоже оказалось малоинтересным, поэтому для этого привлеклись формулы для трансформации плоскости в 3d. Формулы для перспективной проекции тоже выводил самостоятельно (и без участия матриц); также пришлось ввести зависимость яркости от глубины — потому что мозг не всегда понимал, что ближе, что дальше. В 100 строк уложиться не удалось))



Sign up to leave a comment.

Articles