несъответствия с матричните изчисления между GLSL и GLM, или има такова нещо като матрица с лош изглед

И така, попаднах на някои странности между GLSL и GLM.

Ако генерирам следната матрица на изглед (C++):

vec3 pos(4, 1, 1);
vec3 dir(1, 0, 0);
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1));

И след това в glsl направете:

fragColour.rgb = vec3(inverse(viewMat) * vec4(0,0,0,1)) / 4.f;

Тогава очаквам екранът да стане розово-червен или (1.0,0.25,0.25). Вместо това ми става черно.

Ако обаче направя това в GLM:

vec3 colour = vec3(glm::inverse(viewMat) * vec4(0,0,0,1)) / 4.f;
cout << glm::to_string(colour) << endl;

Получавам очаквания резултат от (1.0,0.25,0.25).

Сега, ако променя viewMat на (C++):

vec3 pos(4, 1, 1);
vec3 dir(1, 0.000001, 0);
mat4 viewMat = glm::lookAt(pos, pos+dir, vec3(0,0,1));

Тогава бам! Получавам (1.0,0.25,0.25) както в GLSL, така и в GLM.

Това няма смисъл за мен. Защо прави това? Тази матрица на изглед работи добре навсякъде другаде в GLSL - просто не мога да я обърна. Това се случва винаги, когато dirY == 0.f.

Също така, моля, предложете подобрения за заглавието на въпроса, не съм сигурен какво трябва да бъде.

Редактиране: Също така, изглежда няма нищо общо с up вектора на lookAt (който така или иначе зададох на Z). Дори и да задам (0,1,0), същото се случва. Всичко се обръща настрани, но все още не мога да обърна матрицата на изгледа в GLSL.

Редактиране: Добре, така че по предложение на derhass, опитах да изпратя матрицата на изгледа вече обърната. Бам, работи перфектно. Така че изглежда, че моята GL реализация наистина е някак неспособна да обърне тази матрица. Това би трябвало да е най-странната грешка в GL, която някога съм срещал. Все пак би било оценено някакво обяснение защо е лоша идея да се обръщат матрици в шейдъри. EditAgain: Изпращането на обърнати матрици в моя двигател доведе до огромно увеличение на честотата на кадрите. ОПРЕДЕЛЕНО ДА НАПРАВИ ТОВА.


person Jagoly    schedule 11.04.2015    source източник
comment
Е, доколкото мога да преценя, този проблем е напълно несвързан с glm. Изглежда, че това е просто проблем с обръщането в GLSL. Начинът, по който е настроена вашата матрица, трябва да е идеално обратима и числовите проблеми не трябва да са проблем. Това може просто да е проблем с внедряването на GL. Също така имайте предвид, че обръщането на матрици в шейдъра така или иначе е лоша идея в повечето случаи, но разбира се трябва да работи. Препоръчвам да тествате това с някои други реализации на GL, ако е възможно.   -  person derhass    schedule 11.04.2015
comment
@derhass Аааа, не се бях замислял да изпратя матрицата вече обърната. Ще опитам това. Също така ще се опитам да видя дали проблемът се появява и другаде. В момента използвам доста стар драйвер на nvidia (този в хранилищата на Ubuntu 14.04).   -  person Jagoly    schedule 11.04.2015
comment
Това беше първият път, когато научих, че GLSL вече има обратна функция изобщо. Това определено не е удобна за GPU операция. Винаги имайте предвид йерархията на операциите: на теглене, на връх, на фрагмент. Винаги премествайте нещата възможно най-ниско. Просто попаднахте на много малко вероятна кодова пътека, като правите инверсия за връх. Също така имайте предвид, че обикновено не е необходимо общо обратно. Повечето матрици за изглед на модел трябва да са орто нормални. Където обратното е същото като транспонирането.   -  person starmole    schedule 12.04.2015
comment
Хе... вероятно не е подходящ моментът да кажа, че го правя на фрагмент :P   -  person Jagoly    schedule 12.04.2015


Отговори (1)


Произволното обръщане на матрица 4x4 не е бърза и безопасна задача

По много причини като по-ниска точност на FPU от страна на GPU и необходимостта от много деления по време на инверсия (добре, това зависи от метода на изчисление), а не всички матрици имат обратна и т.н. (Мисля, че това също е причината, поради която GL няма такава реализация или) ... За по-добро изображение на това вижте Разбиране на матриците за хомогенна трансформация 4x4 и потърсете matrix_inv функция там колко сложно е изчислението наистина е (използва детерминанти). Има и GEM (метод за елиминиране на Гаус), но той не се използва поради странностите му и необходимостта от сортиране на редове ...

Ако матриците са статични за изобразяване на рамка, което обикновено е така, е загуба на мощност на графичния процесор, изчисляването й в шейдъри Vertex/Fragment/Geometry отново и отново за всеки Vertex/Fragment (ето защо е налице увеличение на скоростта).

Някой може да се противопостави на това, че инверсията на ортогонална хомогенна матрица е просто транспониране на матрицата, но как GL/GLSL може знайте, че работи с такава матрица (проверката също не е толкова проста) така или иначе в този случай можете да използвате transpose, който е имплементиран в GLSL и трябва да бъде бърз (това е просто пренареждане на елементи)

person Spektre    schedule 08.10.2015
comment
Очаквам, че това е отговорът. Обръщането на матрицата обикновено води до числена нестабилност и аз почти винаги бих избегнал обръщането на матрица, ако мога. - person Dietrich Epp; 08.10.2015
comment
@DietrichEpp и аз, но в графиките, особено с ефектите на камерата, не може да се избегне толкова лесно :( - person Spektre; 08.10.2015
comment
Това е често срещано погрешно схващане, обикновено е много лесно да се избегне. Можете да генерирате матрицата за нормали и да правите обратни проекции и други подобни, без изобщо да се налага да изчислявате обратното на обща матрица. - person Dietrich Epp; 10.10.2015