Задать вопрос
NimuraF
@NimuraF

Как правильно организовать соприкосновения поверхностей при инстансинге?

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

Моделирую ситуацию: делаю анимацию дождя при помощи инстансинга, беру базовую каплю, которая представляет собой 2 точки в верхнем левом углу, соединённых линией, после чего на основе смещения по X и Y координатам создаю ещё 200 таких же каплей в отображаемой области, а так же применяю к ним матрицу трансформации. Вот, собственно, сам шейдер:

#version 460 core

layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aOffset;

uniform mat4 raindropsdown;

vec4 result;

void main()
    {
    result = raindropsdown * vec4(aPos + aOffset, 0.0, 1.0);
    if ((result.x < -0.5 && result.y > -0.5) || (result.x > 0.5 && result.y > -0.5) || (result.x >= -0.5 && result.x <= 0.5 && result.y > 0.5))
    gl_Position = result;
    };

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

glm::mat4 transformic;
        transformic = glm::translate(transformic, glm::vec3(0.0f, (GLfloat)raindropY, 0.0f));

        if (raindropY <= 3 * floor[4] + 0.05) {
            raindropY = -(float)0.1f;
        }

        GLint transformLocRainDrops = glGetUniformLocation(shaderProgramForRaindrops, "raindropsdown");
        glUniformMatrix4fv(transformLocRainDrops, 1, GL_FALSE, glm::value_ptr(transformic));

        glBindVertexArray(VAOs[2]);
        glDrawArraysInstanced(GL_LINES, 0, 2, 200);
        glBindVertexArray(0);

        raindropY = raindropY - 0.003;

Очевидно, так как я отрисовываю линию, то при отсутствии отрисовки одной из точек происходит коллапс и билеберда, появляются линии на пол экрана, которые на следующем кадре исчезают и т.д. И я, честно говоря, даже не могу толком сообразить, как это исправить. Пытался играть с прозрачностью, назначая в точке соприкосновения точке полную прозрачность, но это ведь прозрачность точке, а не линии, следовательно, думаю не в ту сторону. Может есть у кого идеи как это правильно реализовать? Есть вариант с тем, чтобы в этой самой точке соприкосновения возвращать точку с точной координатой сопротивления и нулевой прозрачностью, что-то вроде этого:
#version 460 core

layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aOffset;

uniform mat4 raindropsdown;

vec4 result;
void main()
    {
    result = raindropsdown * vec4(aPos + aOffset, 0.0, 1.0);
    if (result.x < -0.5 && result.y < -0.5)
    gl_Position = vec4(result.x, -0.5f, 0.0f, 0.0f);
    else if (result.x > 0.5 && result.y < -0.5)
    gl_Position = vec4(result.x, -0.5f, 0.0f, 0.0f);
    else if (result.x >= -0.5 && result.x <= 0.5 && result.y <= 0.5)
    gl_Position = vec4(result.x, 0.5f, 0.0f, 0.0f);
    else
    gl_Position = result;
    };

Но тут возникает сразу две проблемы, и точки продолжают отрисовываться и по сути теряется идея оптимизации и при этом чудные линии вообще никуда не деваются и всё становится ещё хуже, вот скрин:
6352f6a3ea2e2739157084.png
Ну и ещё небольшой нюанс, на который я не нашёл внятного ответа в гугле, есть ли какой-то универсальный механизм создания событий изнутри шейдера? Например, для той же анимации разбивающихся капель? А то у меня вообще нет идей, как мне нарисовать даже пару линий в стороны в точке соприкосновения поверхностей.
  • Вопрос задан
  • 119 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
В такой постановке вопрос тянет уже на полноценную разработку игр. И суть вот в чем.

Игровое пространство может быть единым и предлагать самые разные функции, однако это не значит что всех нужно делать каким-то одним способом.
Да, к взаимодействию с пространством относятся как звук с графикой, так и физика с обработкой столкновений.
Однако, OpenGL, как и любой другой GAPI, реализует только функционал вывода графики. Иными словами, у данных через OpenGL дорожка только в один конец - на монитор и все. Большего от него и требовать не нужно.
А обработка столкновений подразумевает обратную связь и реализуется уже отдельными средствами.

Это все должно работать слоями. Параллельно существующими математическими моделями. Параллельность существования тут означает только то, что между собой модели явным образом не взаимодействуют, но обмениваются результатами своей работы через свойства и атрибуты объектов игры, модифицируя их во время своей работы.
Вот у тебя уже есть какая-то модель отображения мира. Тебе надо просто рядом реализовать параллельную модель обработки столкновений.
В этой модели у тебя должны быть подвижные акторы и коллизионная геометрия. Для твоего случая достаточно это все посчитать на CPU в отдельной функции. В качестве геометрии коллизий можно взять прямо те же данные вершин, которыми ты рисуешь мир. Данные акторов можно взять прямо там, где готовятся позиции инстансов капель.
Сама модель обработки столкновений - это набор математических формул из уроков геометрии в средней школе.
Есть капля, с момента прошлого такта она пролетела какое-то расстояние. Проверяем пересечение капли с геометрией дома и генерируем событие столкновения когда оно зафиксировано.
Для капель неподвижным можно даже человека считать.

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

В сложных высокотехнологичных движках множество моделей используют собственную память для представления акторов, вводя многократную избыточность использования памяти, но позволяя работу в полностью параллельном режиме на нескольких потоках. В таких движках существует отдельная стадия сборки представлений из разных подсистем в единое представление актора с попутным разрешением коллизий, если они возникают.
Тебе подобные сложности точно не нужны на текущем этапе. Реализовать можно просто парой-тройкой моделей (графика, столкновения и физика) поверх единой системы объектов мира, обработку которых пустить последовательно в одном потоке.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы