Форум программистов, компьютерный форум, киберфорум
OpenGL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771

Отрисовать кости используя данные из вершинного шейдера

25.08.2023, 10:22. Показов 2129. Ответов 32

Студворк — интернет-сервис помощи студентам
Есть следующий упрощенный (неиспользуемые части кода были удалены)
вершинный шейдер который используется игрой при рисовании игрока.

Кликните здесь для просмотра всего текста

glSlang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#version 140
#define NUM_BONES 64
 
in vec4 positionIn;
in vec4 animationData; // x = bone 1 id, y = bone 2 id, z = bone 1 weight, w = bone 2 weight, weights are not normalized
 
uniform vec4 qRotations[NUM_BONES];
uniform vec3 vTranslations[NUM_BONES];
uniform bool animated;
 
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
 
uniform float quantizationScale;
 
out vec3 fragment3DPos;
out vec3 fragment3DPosModel;
 
vec3 multiply(vec4 q, vec3 p)
{
    return p + 2.0 * cross(q.xyz, cross(q.xyz, p) + q.w * p);
}
 
void main()
{
    vec3 vertexPos_model;
 
    // Linear skinning
    vec3 positionScaled = positionIn.xyz * quantizationScale;
 
    int b1 = int(animationData.x);
    int b2 = int(animationData.y);
    
    float w1 = animationData.z / 255.0;
    float w2 = 1.0 - w1;
 
    vertexPos_model = 
        (multiply(qRotations[b1], positionScaled) + vTranslations[b1]) * w1 +
        (multiply(qRotations[b2], positionScaled) + vTranslations[b2]) * w2;
 
    vec4 vertexPos_world  = modelMatrix * vec4(vertexPos_model, 1.0);
    vec4 vertexPos_camera = viewMatrix * vertexPos_world;
    gl_Position = projectionMatrix * vertexPos_camera;
    fragment3DPos = vertexPos_world.xyz;
    fragment3DPosModel = vertexPos_model.xyz;
}


Я хочу отрисовать скелет игрока (что-то типа такого) используя
данные из шейдера, но пока-что получается какая-то фигня. На данный момент я сохраняю только
матрицы model, view и projection, а так же массивы qRotations и vTranslations.

Структура TransformMatrix
C++
1
2
3
4
5
6
7
8
struct TransformMatrix
{
    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 projection;
    glm::vec3 translations[NUM_BONES];
    glm::vec4 rotations[NUM_BONES];
};
Внутри функции которая вызывается для рисования игрока
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
TransformMatrix transformMatrix {};
 
glGetUniformfv(shaderId, uniform_locations["modelMatrix"], glm::value_ptr(transformMatrix.model));
glGetUniformfv(shaderId, uniform_locations["viewMatrix"], glm::value_ptr(transformMatrix.view));
glGetUniformfv(shaderId, uniform_locations["projectionMatrix"], glm::value_ptr(transformMatrix.projection));
 
for (int i = 0; i < NUM_BONES; i++)
{
    glGetUniformfv(shaderId, uniform_locations["qRotations[0]"] + (sizeof(glm::vec4) * i), glm::value_ptr(transformMatrix.rotations[i]));
    glGetUniformfv(shaderId, uniform_locations["vTranslations[0]"] + (sizeof(glm::vec3) * i), glm::value_ptr(transformMatrix.translations[i]));
}
 
transformMatrixes.push_back(transformMatrix);
Создание VAO
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
unsigned VAO, VBO, EBO;
 
// Я знаю что тут обычная линия, я просто хотел увидеть
// Что иду в правильном направлении
const float vertices[] =
{
     1.0f,   1.0f,  1.0f,
    -1.0f, -1.0f, -1.0f,
};
 
const unsigned int indices[] = { 0, 1 };
 
/* VAO */
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
 
/* VBO */
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
 
/* EBO */
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
 
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
В конце кадра
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for (auto& transformMatrix : transformMatrixes)
{
    for(int i = 0; i < NUM_BONES; i++)
    {
        glm::vec3 rotationAxis = glm::vec3(transformMatrix.rotations[i].x, transformMatrix.rotations[i].y, transformMatrix.rotations[i].z);
        float rotationAngle = glm::radians(transformMatrix.rotations[i].w);
 
        transformMatrix.model = glm::rotate(transformMatrix.model, rotationAngle, rotationAxis);
        transformMatrix.model = glm::translate(transformMatrix.model, transformMatrix.translations[i]);
 
        glUniformMatrix4fv(uProjection, 1, GL_FALSE, glm::value_ptr(transformMatrix.projection));
        glUniformMatrix4fv(uModel, 1, GL_FALSE, glm::value_ptr(transformMatrix.model));
        glUniformMatrix4fv(uView, 1, GL_FALSE, glm::value_ptr(transformMatrix.view));
 
        fpglDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, 0);
    }
}
 
transformMatrixes.clear();
Мой вершинный шейдер
C++
1
2
3
4
5
6
7
8
9
10
11
12
#version 140
 
in vec3 aPosition;
 
uniform mat4 uModel = mat4(1.0f);
uniform mat4 uView = mat4(1.0f);
uniform mat4 uProjection = mat4(1.0f);
 
void main()
{
    gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0f);
}
Что я делаю не так и как надо cделать?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
25.08.2023, 10:22
Ответы с готовыми решениями:

Приведение типов внутри вершинного шейдера
Хочу в атрибутах вершины передавать кроме координат в формате float, индекс в формате int uint, возможно ли в вершинном шейдере это делать...

Как отрисовать многоуровневое меню используя один запрос к базе данных
есть модель меню есть модель item для элементов меню -item связан с меню ForeignKey -так же item связан сам с собой ForeignKey...

Считать данные из BindingList и в ходе вычислений отрисовать в PictureBox график
Подскажите как при клике по кнопке можо считать данные из BindingList и в ходе вычислений отрисовать в PictureBox график? Меня устроит хотя...

32
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 12:41
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
А если, к примеру, известно? Это бы что-то изменило?
Как миниму ты не использовал бы мусор.
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
27.08.2023, 12:47  [ТС]
zayats80888, При рисовании игрока, вроде бы, используются первые 10 костей, остальные равны 0. Можно сделать так, чтобы те, которые меньше 0.001f автоматически пропускались.
0
1958 / 814 / 114
Регистрация: 01.10.2012
Сообщений: 4,744
Записей в блоге: 2
27.08.2023, 13:25
Цитата Сообщение от zayats80888 Посмотреть сообщение
Это умножение кватерниона на вектор (поворот).
Умножение вижу
cross(q.xyz, p) + q.w * p
Но это не поворот, что делается дальше (в итоге добавляется ортогональный вектор) - не понимаю. Ладно, не хочу тратить Ваше время, это просто любопытно, не более того

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
А если, к примеру, известно? Это бы что-то изменило?
Нет, там еще много чего не хватает, нужно знать парентов (иерархию) и позиции/матрицы бонов
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 13:42

Не по теме:

Цитата Сообщение от Igor3D Посмотреть сообщение
Ладно, не хочу тратить Ваше время, это просто любопытно, не более того
Можете свое потратить. Распишите формулу qpq-1, похимичте(сгруппируйте слагаемые) и получите эту формулу.



Добавлено через 8 минут

Не по теме:

Вот аналогичная реализация из GLM, если интересно:

C++
1
2
3
4
5
6
7
8
    GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
    {
        vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
        vec<3, T, Q> const uv(glm::cross(QuatVector, v));
        vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
 
        return v + ((uv * q.w) + uuv) * static_cast<T>(2);
    }

0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
27.08.2023, 13:57  [ТС]
Цитата Сообщение от Igor3D Посмотреть сообщение
нужно знать парентов (иерархию) и позиции/матрицы бонов
Но они же куда-то в шейдер передаются, значит можно вытащить. Хоть и сложно..
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 13:59
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Но они же куда-то в шейдер передаются
Кто "они"?
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
27.08.2023, 14:01  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Кто "они"?
Позиции/матрицы бонов
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 14:09
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Позиции/матрицы бонов
Это глобальные преобразования с учетом преобразований "родительских" костей и "сдвига в локальные СК костей".
Если сможешь(нет) решить матричное уравнение вида Mi*Mj*Mi+1*Mj+1...=M, где известно только M, а Mi+n из известных матриц, но неизвестно каких именно, то дерзай.
0
1958 / 814 / 114
Регистрация: 01.10.2012
Сообщений: 4,744
Записей в блоге: 2
27.08.2023, 15:03
Цитата Сообщение от zayats80888 Посмотреть сообщение
Вот аналогичная реализация из GLM, если интересно:
Да, "оно", спасибо. Оказывается никакой это не трюк, а (широко) известная формула

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Но они же куда-то в шейдер передаются, значит можно вытащить. Хоть и сложно..
Нет, нужных (Вам) данных в шейдере нет. Упрощенно: есть матрицы/повороты M1 и М2, в шейдер подается разница между ними. Шейдеру хватает, но M1 неизвестно

Цитата Сообщение от zayats80888 Посмотреть сообщение
Распишите формулу qpq-1,
Видел эту формулу много раз, но не очень понимаю как она работает. Вот напр популярное объяснение
Умножение кватернионов крайне полезная штука. Результатом умножения является кватернион, который после поворота даёт такой же результат, если последовательно выполнить развороты умножаемыми кватернионами. Причём разворот будет происходить в локальной для поворачиваемого вектора системе отчёта, т. е. система отчёта поворачиваемого вектора также двигается.
Ну хорошо, множим q * p где p - поворачиваемый вектор, его w = 0, ну стало быть, поворот на ноль ничего не меняет. Однако рез-т - совсем не q, значит меняет. Это как ?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 15:07
Цитата Сообщение от Igor3D Посмотреть сообщение
его w = 0, ну стало быть, поворот на ноль ничего не меняет
Это как так "поворот на ноль" получился? Если рассматривать w как косинус половины угла, то это не ноль.
0
1958 / 814 / 114
Регистрация: 01.10.2012
Сообщений: 4,744
Записей в блоге: 2
27.08.2023, 16:06
Цитата Сообщение от zayats80888 Посмотреть сообщение
Это как так "поворот на ноль" получился? Если рассматривать w как косинус половины угла, то это не ноль.
Да, об этом я не подумал.

cos(a/2) = 0 -> a/2 = 90, a = 180 градусов

Ну и какой смысл этого поворота на 180? И каким чудесным образом после умножения на обратный получается повернутый вектор? Я понимаю (или знаю) что "это работает", и умею (так-сяк) пользоваться этой и другими операциями, но хотелось бы понимать почему
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
27.08.2023, 16:16
Цитата Сообщение от Igor3D Посмотреть сообщение
Ну и какой смысл этого поворота на 180?
Нет никакого смысла. Если с обычными комплексными числами еще как-то можно, то пытаться визуализировать операции над комплексными числами в четырехмерном пространстве гиблое дело.
Это чистая математика,, поэтому
Цитата Сообщение от Igor3D Посмотреть сообщение
Я понимаю (или знаю) что "это работает", и умею (так-сяк) пользоваться этой и другими операциями
вполне достаточно.
0
1958 / 814 / 114
Регистрация: 01.10.2012
Сообщений: 4,744
Записей в блоге: 2
28.08.2023, 15:02
Цитата Сообщение от zayats80888 Посмотреть сообщение
Нет никакого смысла. Если с обычными комплексными числами еще как-то можно, то пытаться визуализировать операции над комплексными числами в четырехмерном пространстве гиблое дело.
Это чистая математика
Это сейчас молодые люди требуют "видеоуроки", мои запросы гораздо скромнее Тот же поворот матрицей - все понятно как/почему получается результат, без всякой "великой математики", всего лишь скалярное произведение. Можно и визуализировать нарисовав оси матрицы и проекции на них, но в этом нет необходимости. А с кватернионами - мутно. Какой-то разворот на 180, множим оттуда, потом отсюда, почему так надо делать - хз
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.08.2023, 15:02
Помогаю со студенческими работами здесь

Отрисовать данные на множестве поверхностней, а затем эти поверхности отобразить в пространстве
подскажите, мне нужно отрисовывать данные на множестве поверхностней, а затем эти поверхности отоброжать в пространстве. в поверхности...

Описать логическую фунцию, показывающую, равна ли правая цифра очередной кости левой цифре следующей кости домино
type костьдомино = record лев,правый:0..6 end; ряд= array of костьдомино. Описать логическую фунцию правильный ряд (r) (равна ли правая...

Проверка поддержки вершинного буфера
Здравствуйте! Работая некоторое время на OpenGL у меня возникло пару вопросов. Как проверить: 1) Поддерживает ли система буфер...

Передача вершинного и фрагментарного шейдоров проекту
Ку всем! Предыстория: Столкнулся с проблемой, которую я написал в этой теме. Т.к. прогресс решения проблемы не сдвигался со своего...

Используя запросы, необходимо обновить данные в таблице используя DBLookupComboBox
Здравствуйте. Есть проекте(прикреплен к топику), в нем присутствует форма, которая редактирует текущую БД, для удобства используется...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru