Pull to refresh
4
0

.Net Developer

Send message

если столкнёшься с багом

В моей практике это не если, а когда.

Про lfs не понял.

На самом деле я тоже предпочитал официальные репозитории альтернативным способам установки, так как чувствую, что это linux way. Но многократно сталкивался с багами или длительным отставанием даже мажорной версии dotnet, suricata, smbclient, grpc, terraform, terragrunt, terraspace, nodejs, а то и вовсе отсутствием для выбранного дистрибутива.

Кстати, возможно, на идеоматичность подхода со временем повлияет тот факт, что в мире docker базовый образ по умолчанию это Alpine, если ни busybox. И всё более выраженной становится потребность иметь пакет именно для него. Хотя пока что как раз из-за отсутствия многих пакетов и приходится собирать образы на centos или debian (ну это, на самом деле, вообще экзотика).

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

Есть один аргумент в пользу установки самой свежей версии, даже если она не в официальном репозитории.

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

Да, считается, что в официальном репозитории версии более стабильные, проверенные теми, кто поддерживает репозиторий и/или даже сам дистрибутив ОС. Но что дальше, в случае если баг там всё-таки обнаружится? Поддержка репозитория ничем не поможет, лишь перенаправит к авторам пакета. А те, скажут "попробуйте последнюю версию". Так зачем удлиннять этот путь?

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

Вектор нормали имел три координаты. Для преобразования делаем его четырёхмерным, дописывая ноль. После преобразования в четвёртой координате вектора уже не ноль. Если разделить все полученные координаты на четвёртую, в ней получится единица, что соответствует точке, а не вектору. Как же правильно спроецировать вектор обратно в 3d из однородных координат?

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

x и y — в порядке

Нет, с ними тоже самое.

[1, 0, 0]

Но вообще-то это наверное и правильно, если считать что источник света задаётся направлением на него, а не от.

Преобразование для нормалей пока не сделал, только интерполяцию самих нормалей вершин для начала — "если головой не вертеть, то должно быть и так нормально". Но почему-то освещение получислось такое, будто Z нормалей из obj файла указывает внутрь модели. Лицо освещено, когда вектор освещения [0, 0, 1], при том что камера, смотрит в отрицательном направлении, если я правильно помню. x и y — в порядке.

картинка

С нормалями к граням такого не было.

Спасибо. Хитро, как я и ожидал. Значит, и мне надо будет сэкономить на его вычислении.

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

Осталось ещё только подозрение, что надо в gluLookAt смещение делать не только от минус начала базиса, но ещё и от минус позиции глаза.

А вопрос под другой статьёй остался про расчёт барицентрических координат в допроективном пространстве. Вопрос по вашей реализации.

Проблема с текстурами была в ошибке copy-paste - z брался у одной и той же вершины для вычисления разных барицентрических координат.

Потратив ещё часов 5, реализовал честную цепочку преобразований на матрицах, и всё заработало.

Это лишь подчёркивает вопрос - куда же у автора пропали "r *" и "+1" из знаменателей при вычислении барицентрических координат?

Ответ прошлому себе: да всё правильно, только pointsToVector(center, eye).

Эксперименты с моделью головы (после изначального исправления pointsToVector(eye, center) на pointsToVector(center, eye), не устранившего вышеназыванные проблемы) показали, что gluLookAt в отношении направления взгляда работает хорошо, но расстояние до модели зависит от не позиции eye, как я почему-то ожидал, а от center, что закономерно, ведь для сдвига используются именно его координаты. Не понятно какой тогда смысл в параметрах gluLookAt. Не лучше ли задавать позицию камеры точкой и двумя векторами (направление взгляда и ориентация верх-низ) вместо двух точек и вектора?

После перехода на цепочку матриц стало совсем плохо.
Вот это при ([0, 0, eyeZ], [0, 0, 0], [0, 1, 0]). eyeZ вообще не влияет на изоражение (если не нулевой).

Особенно смущает, что видны только 3 из 10 горизонтальных полос на доске.

А с ([0, 0, -1], [0, -1, 0], [0, 1, 0]), вот так:

результат

Мне казалось, что ViewPort должна вписывать в экран, а не выводить за его пределы.

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

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

где d — это разрешение z-буфера (у меня 255, т.к. я храню его непосредственно в чёрно-белой картинке).

А у меня z-буффер из float. Как быть? Вводить искусственное оганичение или оставит его диапазон от -1 до 1?

А ещё есть дурацкий вопрос опять про вектор столбец vs вектор строка.

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

	function CreateViewMatrix(eye, center, up) {
		const z = normalizeVector(pointsToVector(eye, center));
		const x = normalizeVector(crossProduct(up, z));
		const y = normalizeVector(crossProduct(z, x));
		const rotation = [
			[x[0], y[0], z[0], 0],
			[x[1], y[1], z[1], 0],
			[x[2], y[2], z[2], 0],
			[0, 0, 0, 1],
		]
		const translation = [
			[1, 0, 0, 0],
			[0, 1, 0, 0],
			[0, 0, 1, 0],
			[-center[0],-center[1], -center[2], 1]
		]
		return multiplyMatrices(translation, rotation)
	}

// to use like:
//[[x, y, z, 0]] * model * view * projection * viewPort

Не вижу никакой возможности понять, как именно должны располагаться строки/столбцы в матрице rotation, кроме как пробовать оба варианта. Я с час пытался вывести из содержимого статьи и разных прмеров кода и форумов, но не могу совладать с тем, что помимо того, что где-то матрица умножается на столбец, где-то строка на матрицу, так ещё и матрицы у некоторых представляются как набор столбцов, у других как строк, а у третих хранятся в непрерывном массиве и подразумеваеется хранение по строкам, но умножение идёт как со столбцами. А тут ещё и обращение через транспонирование...

Спасибо за ответ. Про совпадение обращения и транспонирования для ортогональных, я и подозервал (хотя такие нюансы линейной алгебры я уже забыл). Но остаётся всё-таки вопрос, о том, на основании чего матрица М изначально вообще строится из единичных векторов нового базиса заданных в координатах исходного базиса? Должно быть, я упускаю что-то очевидное.

Первый раз читал на неделе, казалось всё понял.
Сейчас перечитываю, чтоб реализовать и снова спотыкаюсь.

    Matrix Minv = Matrix::identity();
    Matrix Tr   = Matrix::identity();
    for (int i=0; i<3; i++) {
        Minv[0][i] = x[i];
        Minv[1][i] = y[i];
        Minv[2][i] = z[i];

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

Осталось понять какая из двух формул тут в итоге реализуется

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

Убил ещё 2 часа, но это полный тупик.

Я заметил, что под координатам переданными в растеризатор имеются в виду исходные кординаты clip пространства (после цепочки преобразований, включая перспективное), но до проецирования из 4d в 3d. Так что это не то, что на картинке в предыдущем комментарии, но и никак не rA.z+1, rB.z+1, rC.z+1. Видимо, в коде автора, либо ошибка, которая чудом не влияет на результат, либо им таки были проделаны некие преобразования, показывающие эквивалентность применения rA.z+1, rB.z+1, rC.z+1 и A.z, B.z, C.z.

В то же время, не ясно, почему растяжение и смещение по x, y не с помощью матриц, выполненное после проецирования, ломает алгоритм, и почему домножение на 2 как будто бы помогало (когда я проверил на модели головы, проявились другие артефакты).

Наверное дело в

 rA.z+1, rB.z+1, rC.z+1 нам известны, это координаты треугольника, переданные в растеризатор

Я то подумал, что "это" имеется в виду A.z, B.z, C.z, а имеются в виду целиком выражения.
Только теперь непонятно, каким образом это могут быть координаты перданного треугольника, если они выглядели вот так

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

Но начинает казаться, что слишком стар я стал для всех этих "легко видеть, что...", и дальше кривого текстурирования мне не осилить. Где-то упоминалось, что весь курс часов на двадцать, я, кажется, на половину курса уже столько потратил.

1
23 ...

Information

Rating
Does not participate
Location
Россия
Registered
Activity