Напишите свой упрощенный OpenGL для ржавчины — часть 1 (нарисовать линию)

Напишите свой упрощенный OpenGL для ржавчины — часть 1 (нарисовать линию)

598

И было бы чрезвычайно любопытно испытать еще написать все эти красивости в одиночку. Я желал новейший язык, испытать в деле и, в то же время, любопытно провести время программирования что-то интригующее. При этом думая, что здесь расте писать, я вспомнил недавние статьи о компьютерной графике, который я лишь обезжиренное. На данный момент он завлекает большой энтузиазм, и не так давно в конце концов-то вышла 1-ая стабильная версия 1.0 ржавчины, которая знаменует собой стабилизацию функции языка. Мне постоянно импонировала система ЛП, и мысль системы языка, обеспечивая наиболее высшую сохранность, языки высочайшего уровня, заинтересованы даже больше. И так родилась мысль этого хобби-проекта и данной статьи. Наверняка, не достаточно кто на хабре не знают что такое ржавчина-это новейший язык программирования от Mozilla.
И, естественно, упомяну перечень ресурсов, которые были применены во время разработки. Побеседуем о личных впечатлениях от знакомства с языком. Я постараюсь обрисовать грабли, на которые довелось наткнуться, а также в качестве вопросца. Как и в уникальной статье кропотливо rasselyayutsya все аспекты, касающиеся конкретного программирования в графической составляющей, я в собственной серии статей я остановлюсь основным образом на то, что касается конкретно ржавчины и спортсменов. Так что, кому любопытно, Добро пожаловать под кат.
Раз вы про раста, может быть, посмотрев на мои пробы, ты хочешь, чтоб больно стукнуть чем-нибудь томным. В этом случае рекомендую воздержаться от чтения. Предупреждение: статья написана с точки зрения новенького и обрисовывает глуповатых ошибок новенького.

(игра слов, ржавчины британский «ржавчина») Вот ржавчина, которые я надеюсь получить в конце.
Подготовка
Обрисовывать установку компилятора, я не буду, все довольно разумеется. Синаптические даже не демонстрируют груза в перечне доступных пакетов. Но, у меня есть этот репозиторий не устанавливается. Установочный пакет с официального веб-сайта установлен в Ubuntu 14.04 пару команд. Почему-то ржавчина была установлена, но без груза. Следует отметить, что существует репозиторий для Ubuntu, который также на теоретическом уровне может быть установить ржавчины. Ржавчины без груза достаточно бессмысленная штучка, так что указанный НПА я не употреблял.
Сделать файл main.РС: Так что, как постоянно, знакомство с новеньким языком, мы начнем с Привет мир.

юзер@юзер-все-серии:~$ Здрасти миреосновные клавиши FN() {
код println!(«Здравствуй, Мир!»);
}

Результатом такового приложения очевидна в консоли:
юзер@юзер-все-серии:~$ rustc основное.РС
юзер@юзер-все-серии:~$ ./главные
Здравствуй, Мир!
Сходу бы не работала, но трекер был баг-репорт, который объяснил причину трудности. Цвета ржавчины синтаксис для этого редактора можно ознакомиться по последующей ссылке. Обычный патча решила делему, так что сейчас у вас есть цветочки, чтоб заработать без каких-или доп танцев с бубном. Вы сможете написать код, используя в gedit.
Как правило, новейший проект создается с помощью команды новейший грузовой rust_project —Бен , но тогда я о этом не знала, потому пришлось сделать структуру вручную, это не трудно:

Структура новейшего проекта- Карго».томл
в src/основная.РС

Содержимое Груза.томл:
[пакет]
имя = «rust_project»
версия = «0.0.1»
создатели = [ «Cepreu <cepreu.mail@gmail.com>» ]

Этот проект запускается по команде перевозки груза .
не разрешают этого делать. Почему СДЛ? Я желал для вывода результата с внедрением SDL. Все другие графические примитивы мы рисуем сами, так что раз вы желаете бэкэнд вывода изображения можно поменять чрезвычайно просто, просто реализует 2 функции: набор(х, Y, цвет); и новейшие(xsize и, и ysize). Может быть, даже игрушки, чтоб написать обычный ТГА… На самом деле, мы из данной библиотеки необходимо будет лишь сделать окно и Выходная точка с данным цветом в указанной позиции. Для отображения рисунки, я решил не переписывать TGAImage предоставлены создателем уникальной статьи. В будущем я желал бы иметь возможность поменять точку обзора с клавиатуры.
1-ая ссылка в Гугле вывел меня на веб-сайт проекта ржавчины-SDL2 — неотклонимые для SDL2 ржавчины. Чтоб применять эту библиотеку Добавить в конец груза.томл последующую декларацию зависимости:
[зависимостей]
sdl2 = «0.5.0»

Он добавляет в проект так именуемый контейнер (ящик) sdl2. Для компиляции употребляется библиотека SDL в заголовочных файлах, потому необходимо не запамятовать установить их. В Ubuntu 14.04 это делает команда:
суда apt-получить установку libsdl2-дев

Опосля этого, груз командного построения удачного сбора нам со всеми необходимыми зависимостями.
user@user-All-Series:~/temp/rust_project$ выстроить грузов
Обновление реестра `https://github.com/rust-lang/crates.io-index`
Загрузка числ версии V0.1.25
Скачивая rustc-сериализации версии V0.3.15
Составление sdl2-sys для версии V0.5.0
Составление rustc-сериализации версии V0.3.15
Компиляция библиотеки libc версии V0.1.8
Составление bitflags версии V0.2.1
Составление Ранд версии V0.3.8
Составление числ версии V0.1.25
Составление sdl2 версии V0.5.0
Составление rust_project версии V0.1.0 (файл:///дома/юзер/темп/rust_project)
user@user-All-Series:~/temp/rust_project$

Опыты с СДЛ
Всю функциональность, связанную с взаимодействием с SDL (либо иной графической библиотеки в будущем), я решил поместить в отдельный класс — холст.РС. Поначалу, просто чтоб проверить библиотеку я скопировал туда содержимое теста из репозитория ржавчины-SDL2, идя на базе его позднее готов написать класс.
Оказалось, что хоть какое объявление экстерн ящик заглавие_пакета в библиотеке также должны быть продублированы в главном.РС приложение. Вот у меня была 1-ая рейка. Потребовалось время, чтоб осознать это, но опосля всех мучений, я в конце концов-то проект, который Вы сможете узреть на снимке на github.
В итоге, в файле холст.RS был таковой код:
// Авторское право (C) Cepreu <cepreu.mail@gmail.com> под лицензией gplv2 и выше
экстерн ящик sdl2;

применять sdl2::пикселей::PixelFormatEnum;
применять sdl2::прямоугольник::прямоугольник;
применять sdl2::клавиатура::код клавиши;

паб ФН тест() {
дайте мут sdl_context = sdl2::инит().видео().развернуть();

пусть окно = sdl_context.окно(«Руст-sdl2 демо: видео», 800, 600)
.position_centered()
.в OpenGL()
.выстроить()
.развернуть();

дайте мут рендер = окно.рендерер().выстроить().развернуть();

// Fixme: на переделке
дайте мут текстуры = рендер.create_texture_streaming(PixelFormatEnum::24 бита на точку, (256, 256)).развернуть();
// Создание красно-зеленоватый градиент
текстуры.with_lock(нет |буфер: &мут [у8], шаг: usize| {
для Y в (0..256) {
для X в (0..256) {
пусть смещение = у*питч + х*3;
буфер[смещение + 0] = x как у8;
буфер[смещение + 1] = Y как у8;
буфер[смещение + 2] = 0;
}
}
}).развернуть();

рендерер.очистить();
рендерер.копия (и текстуру, ни один, некие(прямоугольник rect::new_unwrap(100, 100, 256, 256)));
рендерер.copy_ex(&текстуры, ни один, некие(прямоугольник rect::new_unwrap(450, 100, 256, 256)), 30.0, никто, (ересь, ересь));
рендерер.настоящее();

дайте мут работает = истина;

во время бега {
для мероприятия в sdl_context.event_pump().poll_iter() {
применять sdl2::мероприятия::мероприятия;

матч событие {
Действия::кинуть {..} | действия::действия keydown { код клавиши: некие(ключ::Побег), .. } => {
бег = ересь
},
_ => {}
}
}
}
}

Этот код выводит вот это расчудесное окно:
Скриншот
Последующий пункт у нас переработка кода, указанного с целью получения объекта Canvas, который имеет: Напишите код
Раз вы поглядите на сам код, есть тривиальные 3 частей: инициализации, рисования, ожидая ввода.

конструктор, который производит нужную инициализацию
функция вывода точки (заместо сегодняшних выходных текстуры)
функция ожидания ввода клавиши ESC с клавиатуры
Чтоб не усложнять все сверх меры, но решил бросить его в том же классе. Вы понимаете, клавиатура не самая пригодная функция для холста класс, но неувязка заключалась в том, что ожидания я употреблял sdl_context, что опосля этого конфигурации будут в окне холста. В любом случае предпосылки либо клавиатуру объекта будет зависеть от холста, либо оба они должны будут зависеть от неких 3-го класса. Раз перегрузка на полотно будет расти, позже будет сделать некие его функции и до сих пор сделать вышеуказанную работу.
Я просто спустил различных кусков кода из различных мест и собрать их совместно, даже не зная синтаксиса языка. На разных ресурсах я упомянул в качестве ориентира, чтоб осознать, как сделать мне нужен был определенный кусочек. Язык является совсем неповторимым и попробовать осознать как сделать класс либо объект, там было узенькое место. Более языки и технологии чрезвычайно похожи, потому заморочек с сиим подходом появляются. Потому, чтоб получить Общее воспоминание о синтаксисе языка уроки были пройдены Угадайку и обедающих Философах из официальной документации и ржавчины. Вы сможете начать программировать сходу же, даже без познания языка. Это в британском языке, стоит отметить наличие перевода на российский язык. Стоит отметить, что до этого мое развитие процесса отлично охарактеризовывают слова «переполнение стека управляемое развитие». Но в то время я не знал, что читать на языке оригинала. С ржавчиной таковой номер не прошел. Ну, вы осознаете. В книжке раста не было статей с заглавием классов/объектов/конструкторы и др., выяснилось, что во-первых, незначительно домашнее задание. Нужно МОК, погуглив неплохой ответ на stackoverflow. Нужен цикл, чтоб прочесть статью о циклах в языке. Это обычный метод для меня, чтоб выучить новейший язык либо технологию — просто начать писать код.
Хотя пришлось повоевать с системой владения и заимствования ржавчины. Во внедрении констатируется, что сложность исследования — стоимость, которую приходится платить за сохранность, но без излишеств. В общем то, работа пошла. Официальная документация отмечает, что этот шаг проходит каждый новичок, но призывает нас, что как практика код можно писать с легкостью, обычно ограничений, накладываемых компилятором. Вот в этот код: Раз я пробовал инициализировать поле ссылка, компилятор ругался, что не может сделать переменную заимствования («ошибка: не удается заимствовать данные mutably в `&` ссылки ). Непосредственно неувязка была в том, что в способе New (), который делает структуру поля данной структуры нужно инициализировать несколько объектов из SDL, чтоб позже применять их в способы, структуры.
Неувязка в этом кусочке: <‘_>. новейший паб ФН(х: u32, г: u32) -> холст<‘_> {
… Но удаление это так же нереально. паб структура холста<‘_> {
рендер: &’_ муте Рендерер<‘_>,
}
… Надеюсь, что исправим это. Это обозначение срок службы (длительность жизни) — полностью для себя верный синтаксис для ржавчины. дайте мут рендер = окно.рендерер().выстроить().развернуть();
Холст { рендер: &мут визуализации }
}

Кстати, на хабре сломана подсветка синтаксиса ржавчины, из-за чего же приведенный выше код не одетые, хотя и должны. Просто имя: мут типа в структурах можно не писать. Не знаю где написать, потому написали тут. Потом я пробовал сделать переменную неизменяемой (неизменяемыми), но, что сломал остальные код: Раз ее вытащить, то все нормально одетые.
паб структура холста<‘_> {
рендер: Рендерер<‘_>,
}
… }

Компилятор жаловался, что не может одолжить неизменяемые поля рендеринга в качестве переменных («ошибка: не удается заимствовать неизменяемые поля самоорганизации.рендер` как мутабельный ). пусть рендер = окно.рендерер().выстроить().развернуть();
Холст { рендер: рендер }
}
паб ФН точки(&собственн, х: u32, г: u32) {
… Таковым образом, верный код: Ларчик открылся просто. Ржавчина все поля в структуру, рассматриваются как изменяемые либо неизменяемые в зависимости от того, является ли пройденный структура способу в качестве изменяемых либо неизменяемых. новейший паб ФН(х: u32, г: u32) -> холст<‘_> {
… самостоятельная.рендерер.очистить();

самостоятельная.рендерер.очистить();
… пусть рендер = окно.рендерер().выстроить().развернуть();
Холст { рендер: рендер }
}
паб ФН точки(&мут собственн, х: u32, г: u32) {
… паб структура холста<‘_> {
рендер: Рендерер<‘_>,
}
… }

Как видите тут я изменил сигнатуру способа точкой. новейший паб ФН(х: u32, г: u32) -> холст<‘_> {

Сейчас незначительно о граблях:
Там были огромные трудности в работе с кодом, который взаимодействует с библиотекой ржавчины-SDL2. Автоматическое определение типа ржавчины упрощает и ускоряет написание кода, но она игралась со мной и злую шуточку, когда мне необходимо было осознать, какой тип возвращает звонок sdl2::инит().видео().развернуть(), поэтому что этот итог нужно сохранить в поле в структуре, и тогда Тип указан очевидно постоянно. Вуаля! Просто укажите поле в хоть какой случайный Тип, ржавчины при компиляции жалуется на несоответствие типов, принося в сообщении о ошибке типа, которые должны быть. Мне пришлось прочесть начальный код библиотеки, хотя позднее я отыскал и наименее трудозатратный метод. К примеру о способе sdl2::инит() в документации ничего. У нее есть документация, но там еще не достаточно говорит, но о существовании неких способов молчит. Его не существует.
}

В остальных частях кода все упоминания о длительности жизни может быть удалена. Раз есть понимающие люди, буду рад, раз вы просветите меня в комментах. Вообщем говоря в Русте каждую переменную и связать свою жизнь. Упор делается на длительности жизни является параметром — он равен ‘статические. Поначалу я попробовал найти поле как обычный рендер: рендер , но компилятор меня поругал: ошибка: неверное количество характеристик срок службы: ожидаемый 1, найдено 0. Почему это, а не любые остальные знаки опосля апострофа? На самом деле я просто добавил эти странноватые <‘_> где бы компилятор указал на ошибку с неуказанным жизни, и не понимая, почему он от меня нужно. Я была незавидная. Окна.рендерер().выстроить().развернуть() возвращает sdl2::видео::Рендерер<‘статические>. Таковым образом правильное объявление структуры смотрится так:
паб структура холст {
рендер: Рендерер<‘статические>,
… Он просто выводится компилятором автоматом на базе определенных правил. Чтение статей о жизни время от заказать раста не прояснило. Отдельного упоминания заслуживает такое понятие, как время жизни (время жизни) в Русте. Это особенное время жизни, обозначающих то, что может жить до конца всей программы. Но, время от времени требуется указать очевидно. Просто в сообщении о ошибке о несоответствии типов был sdl2::рендер::Рендерер<‘_>. (хотя я ее 3 раза перечитывал) я не понимаю, почему в моем случае ржавчины было предложено указать срок службы. УПД: Юзер Гуголплекс в собственном комменты объяснил этот момент.

Я думаю, что мои мытарства кому-то может показаться тестов мортышка с гранатой. Но я тебя предупредил.
О, это чувство благоговения, когда я, в конце концов, увидел на экране темный экран с малеханькой белоснежной точкой в центре… Пишем строку
Так что опосля решения всех заморочек, обрисованных выше, итог моей работы был в том, что вы сможете узреть в снимок репозитория.
Точка
Ее неочевидные и недокументированные, время от времени даже незаконченные API был неизменным источником сложностей. Дела отправь легче, поэтому что суровых взаимодействий с библиотекой ржавчины-SDL2 был не нужен. И тогда большая часть работ было соединено с тем, что я решил не готов воплотить метод и написать собственный свой, используя уравнение прямой у=КХ+б, в качестве базы, и все остальные формулы двигаются сами по для себя. Все арифметические и управляющие структуры в ржавчину не очень различаются от остальных японцев. Так линия была написана всего за несколько часов (заместо пары дней в прошлых шагах). Вот функция, которую я получил итог:
Так родилась мысль написания первой настоящей версии я отказался. 🙂 Я практически сходу пришел писать целые версии, не используя настоящую математику. Но своя — родная. Много кода, а позже все равно в итоге будет переписано так, чтоб она не тормозила. паб ФН полосы(&мут самостоятельная, х1: i32, У1: i32, х2: i32, У2: i32, цвет: u32) {
раз (х1 == х2) && (У1 == У2) {
самостоятельная.набор(х1, У1, цвет);
}
раз (х1-х2).АБС() > (У1-У2).АБС() {
раз х1 < х2 {
дайте мут Йи = У1;
для XI в х1..х2+1 {
пусть p = (У2-У1)*ХІ + х2*У1 — х1*У2;
раз Yi*(х2-х1) < р + (У2-У1)/2 {
яй = яй+1;
}
самостоятельная.набор(XI и Yi, цвет);
}
} еще {
дайте мут этом Yi = У2;
для XI в..х2 х1+1 {
пусть p = (У1-У2)*ХІ + х1*У2 — х2*У1;
раз Yi*(х1-х2) < р + (У1-У2)/2 {
яй = яй+1;
}
самостоятельная.набор(XI и Yi, цвет);
}
}
} еще {
раз У1 < У2 {
дайте мут ХІ = х1;
для Yi в У1..У2+1 {
пусть p = Йи*(х2-х1) — х2*У1 + х1*У2;
раз XI*(У2-У1) < р + (У2-У1)/2 {
ХІ = ХІ+1;
}
самостоятельная.набор(XI и Yi, цвет);
}
} еще {
дайте мут ХІ = х2;
для Yi в У2 У1..+1 {
пусть p = Йи*(х1-х2) — х1*У2 + х2*У1;
раз XI*(У1-У2) < р + (У1-У2)/2 {
ХІ = ХІ+1;
}
самостоятельная.набор(XI и Yi, цвет);
}
}
}
}

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

Все было изготовлено просто для наслаждения. И вот фото моего расчеты на бумаге (для истории)
Знатоки арифметики, пожалуйста не пинайте.
Есть несколько новых, но я не желаю залипать на их бета(Альфа?)-тест. Чтоб применять отладчик, консоль мне не в удовлетворенность. В любом случае ведение журнальчика нужная вещь. Постарайтесь приучить себя применять бревна заместо отладчика, так как он дозволяет писать логи, которые позже вправду осознать, что есть неувязка с конечным юзером (по последней мере, раз ему получится запустить ведение журнальчика отладки). Раз кто-то воспользовался и увидел, что она стабильна и отлично работает, отпишитесь, пожалуйста, в комментах. В ходе написания данной портянки мне необходимо журналирование, как подтверждено IDE для ржавчины пока нет.
Напишите последующее в грузовые.томл: Для входа в поставках ржавчина есть Библиотека журнальчика. Так, ведение журнальчика. Я употреблял env_logger, которая предлагается в документации для журнальчика. Но это просто абстрактный API, и определенную реализацию необходимо выбрать для себя.
[зависимостей]
sdl2 = «0.5.0»
журнальчик = «0.3»
env_logger = «0.3»

Чтоб применять этот набор чрезвычайно прост:
#[macro_use]
экстерн ящик журнальчика;
экстерн ящик env_logger;

главные клавиши FN() {
env_logger::инит().развернуть();
инфо!(«пуск»);

Нужно лишь не забывать, что контейнер (ящик) env_logger настраивается через переменные окружения. Я использую последующую команду перед началом проекта:
Все остальные модули остаются с уровнем, предусмотренным по умолчанию, так что лог при запуске программы не загрязняется всякими отладки мусора от груза либо СДЛ. При запуске наша программа показывает эту красоту: Результат работы на данном шаге может рассматриваться в снимок репозитория. набор RUST_LOG=rust_project=отладка

Это устанавливает модуль rust_project уровень ведения журнальчика отладки.

Статья уже достаточно долго, потому на сейчас я закончу. Планы на будущее: Просто то, что было необходимо по уникальной статье. Лишь цвет 2-ой строке я изменил на голубий.

переписать его страшная функция строчка (), предложенной в уникальной статье в качестве конечного результата
напишите провода рендер
продолжать прогрессировать через уроки Лаконичный курс по компьютерной графике
В конце концов, маленькую часть собственных личных впечатлениях языка.
Я не пишу что я где-то читал. Но лишь что он сам столкнулся во время разработки. К примеру, я знаю, что ржавчина является безопасным, но пока я эту его фишку выстрел в ногу не выручили (как я могу судить), потому не могу оценить его. Опыт
Все это мои субъективные плюсы и минусы. Минусы программирования в Русте:

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

Я, как любитель поддержание 1-го стиля в проекте, чрезвычайно впечатлило. Компилятор будет инспектировать стилистические свойства код и показывает на убыль и раз стиль различается от тех, которые предлагаются разрабами.
Почти все вещи также просто писать, как на языках высочайшего уровня, но это компилируемый язык и система.
К примеру, env_logger настроить переменную среды, которая соответствует одному из 12 причин в heroku. Любовь соответствующей практики в обычной библиотеке.
Это относительно новейший, но уже отлично-признали полезность. Отлично соответствует определению «система языка 21 века». Здесь для вас и управление жизненным циклом проекта и разрешения зависимостей и тестирования. И это в обычной поставке языка. Груз.

В конце концов
Раз я потерплю неудачу, не сломается, не психовать, тогда я напишу продолжение. habrahabr.ru 🙂 И, естественно, раз меня за эту статью в «лишь чтение» не присылать.