Пятница, 22 Ноября 2024, 09:31

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 2
  • 1
  • 2
  • »
Модератор форума: Gnomov  
Помогите с приоритетом отрисовки в SFML
veeroteenДата: Воскресенье, 03 Мая 2020, 21:28 | Сообщение # 1
был не раз
Сейчас нет на сайте
застрял на отрисовке актера относительно объектов, немного не ясно как например отрисовывать под объектом если он ниже по позиции , например если координаты персонажа больше координат дерева, то персонаж отрисовывается поверх, если меньше, соответственно под деревом, была идея разделить экран на до и после персонажа, между которыми он и будет отрисовываться, но потом понял что все равно это придется как то делать для неписей
DivESДата: Воскресенье, 03 Мая 2020, 22:16 | Сообщение # 2
заслуженный участник
Сейчас нет на сайте
veeroteen, сам только что занимался этим же. В принципе, ты своим вопросом сам себе практически ответил.

Смотри, в случае с (например):
Код

background.render();
house.render();
player.render();
tree.render();


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

На этом моменте тебе уже должно было стать понятно, что тебе что-то предстоит сделать с очерёдностью отрисовки объектов на экране.
Ну а дальше уже дело за тобой. laugh
veeroteenДата: Воскресенье, 03 Мая 2020, 22:18 | Сообщение # 3
был не раз
Сейчас нет на сайте
DivES, с очередностью статичных обьектов то все ясно, но игрок и неписи двигаются, соответственно они будут отрисовываться под и поверх деревьев в зависимости от ситуации

Добавлено (03 Мая 2020, 22:21)
---------------------------------------------
как пример




Сообщение отредактировал veeroteen - Воскресенье, 03 Мая 2020, 22:23
DivESДата: Воскресенье, 03 Мая 2020, 22:22 | Сообщение # 4
заслуженный участник
Сейчас нет на сайте
Ну так ты же писал:
Цитата veeroteen ()
например если координаты персонажа больше координат дерева, то персонаж отрисовывается поверх, если меньше, соответственно под деревом

Всё верно, с этим и работай!

veeroteen, да ты, должно быть, шутишь? Я пять минут как вышел из Stardew... :D


Сообщение отредактировал DivES - Воскресенье, 03 Мая 2020, 22:23
puksus4Дата: Понедельник, 04 Мая 2020, 03:46 | Сообщение # 5
частый гость
Сейчас нет на сайте
Навскидку очевидное решение, обычная проблема приоритета рендера, с sfml не связана.

1) Определяешь для каждого спрайта точку, которой этот объект крепится к земле, у дерева будет низ ствола, посередине корней, вероятно почти у всех объектов это будет точка гдето внизу спрайта.
Для простоты можно взять тупо самую нижнюю точку спрайта по игрику и среднюю по иксу. Но возможно будут странности + будет хрень если в спрайте есть путсые области сбоков.
2) Расставляешь объекты в плоскости допустим xz, где x вправо, z от экрана. За позицию объекта считаешь позицию вышеупомянутой точки в мировом пространстве.
3) перед рендером собираешь пары позиция\реф объекта. Пихаешь сюда всё подряд без разбора, и статику и динамику.
4) сортируешь по убыванию z
5) рендеришь

Короче вводишь понятие глубины из 3д в 2д, где глубиной является позиция объекта по z, что интуитивно понятно.

Бонусный побочный эффект: Допустим у тебя есть холм, на нём дерево. Засчёт того что оно поднято относительно уровня земли, то и на экране его позиция будет выше по Y. Также есть второе дерево, оно не на холме, а сбоку на земле. Если не учитывать холм, будет казаться что дерево 2 перед деревом 1, но это не так. Если всё так же расставлять объекты по xz, сортировать, а при рендере поднимать y координату исходя из высоты объекта над землёй - получишь правильный порядок отрисовки с правильным перекрыванием объектами друг друга. То есть ствол дерева 1 перекроет листву дерева 2, как и должно быть.
Иллюстрация:
https://prnt.sc/saekf3


Сообщение отредактировал puksus4 - Понедельник, 04 Мая 2020, 04:12
veeroteenДата: Понедельник, 04 Мая 2020, 11:14 | Сообщение # 6
был не раз
Сейчас нет на сайте
puksus4, а теперь представь как этот массив будет постоянно двигаться в стороны по движению персонажа и неписей, даже массив 100x100 уже не выдержит двигать 1 непися, а что говорить о большем числе, так что метод сортировки подходит только для статичных обьектов
puksus4Дата: Понедельник, 04 Мая 2020, 11:23 | Сообщение # 7
частый гость
Сейчас нет на сайте
veeroteen, Не понял о чём вы.
Если о тайлах карты как таковой и о сложности её сортировки - представьте что это один объект (и оно так и есть. Это земля, её сортировать не надо, она всегда снизу, всегда рендерится первой. Представьте землю в коде одним объектом и рендерьте внутри как 100х100).
Либо отрисуйте сначала свои 100х100 тайлов земли как есть, а всё что сверху (персонаж, деревья, камни, ...) сортировкой.
Ну и понятно что под "всё что сверху" понимается ввиду то, что попало на экран, а не все объекты на сцене.
Если на карте есть холмы - то каждый уровень по высоте будет отдельным слоем + запихнуть "стены"

Даже если у вас 10000 объектов на экране (что вряд ли) кроме тайлов земли - сортировка вряд ли займёт очень много времени.
Есть виды сортировки которые гарантированно сортируют массив меньше чем за квадрат
В плюсах в стандартной библиотеке даже реализация такой есть std::stable_sort с O(nlog^2n). Если не хочется рисковать попаданием в худший O(n^2) случай обычного квиксорта который в среднем O(nlogn).

Ну а если прям ваще не хочется сортировать - можно получить автоматически правильный порядок отрисовки на уровне пикселей аппаратным ускорением засчёт кастомных шейдеров и включения буфера глубины при рендере. Кастомный шейдер понадобится для альфа теста, иначе в глубину отрендерятся даже прозрачные пиксели спрайтов.
Насколько я помню, в SFML можно писать кастомные шейдера, ибо сам писал 100 лет назад. А раз шейдера можно - значит и рендер стейты типа depthStencilState можно какимто образом настроить

Либо как альтернативный вариант - отсортируйте статику 1 РАЗ.
Затем КАЖДЫЙ КАДР сортируйте всех неписей.
Имея отсортированную заранее статику и отсортированные отдельно неписи, уверен, одно с другим можно быстро слить.
У вас 2 отсортированных массива, заводите 2 указателя и сливаете в отдельный общий массив, беря наименьший элемент из 2-х текущих массивов.
Сложность на кадр O(N + M + MlogM)
где N -статика, M - динамика

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


Сообщение отредактировал puksus4 - Понедельник, 04 Мая 2020, 12:08
drcrackДата: Понедельник, 04 Мая 2020, 12:09 | Сообщение # 8
старожил
Сейчас нет на сайте
Цитата veeroteen ()
puksus4, а теперь представь как этот массив будет постоянно двигаться в стороны по движению персонажа и неписей, даже массив 100x100 уже не выдержит двигать 1 непися, а что говорить о большем числе, так что метод сортировки подходит только для статичных обьектов

Почему массив двигается? Почему он стал двухмерным? Зачем массиву двигать непися?
Так много вопросов, так мало ответов...

Перечитай еще раз пост и попробуй все-таки понять о чем там речь

Цитата
veeroteen, Не понял о чём вы.

По-моему это он не понял, о чем ты :D


Сообщение отредактировал drcrack - Понедельник, 04 Мая 2020, 12:09
DivESДата: Понедельник, 04 Мая 2020, 14:49 | Сообщение # 9
заслуженный участник
Сейчас нет на сайте
puksus4, а я так сделал:
Добавил в класс текстур (спрайтов) переменную-член layer_ (аналог твоей z координаты).
Нулевой слой — передний план, больше значение layer_ — дальше план (можно и наоборот, я выбрал такой вариант).

Теперь, в редакторе уровней задаём для каждой текстуры слой, располагая так, как нам нужно.

В main loop:
Для объектов, которые могут перекрыть или могут быть перекрыты сравниваем y координату (а также, скорее всего, нужно будет проверять коллизию прямоугольников, пока что не проверял).
Для примера, для двух объектов это может выглядеть так:
Код

if (sprite0->getY() >= sprite1->getY())
{
    // Первый спрайт ниже по [b]y[/b] второго — смещаем на слой вверх (вперёд).
    sprite0->setLayer(sprite1->getLayer() - 1);
}
else
{
    // Первый спрайт выше по [b]y[/b] второго — смещаем на слой вниз (назад).
    sprite0->setLayer(sprite1->getLayer() + 1);
}


И уже при рендере:
Код

for (int i = МАКСИМАЛЬНОЕ ЗНАЧЕНИЕ СЛОЯ + 1; i >= 0; i --)
{
// Проходимся по всем спрайтам и отрисовываем в зависимости от слоя (тут и определяется очерёдность).
    if (i == текущий_спрайт->getLayer())
    {
        текущий_спрайт->render();
    }
}

Ещё не тестировал на большом количестве слоёв и спрайтов (и скорее всего тут есть подводные камни), но по идее, задумка рабочая.
Что скажете, drcrack, puksus4, имеет право на жизнь? laugh
puksus4Дата: Понедельник, 04 Мая 2020, 15:38 | Сообщение # 10
частый гость
Сейчас нет на сайте
DivES, z координата хороша тем, что тупо расставляешь объекты, какие угодно, где угодно в мировом пространстве - и вообще не паришься о том, что перед чем должно рисоваться, сортировка всё сделает за вас.
У вас же относительное положение объектов друг от друга по сути захардкожено. А вдруг вы захотите в своей схеме один из объектов слоя 2 отрисовать перед объектом слоя 1, а второй - за? Получается, придётся проворачивать дополнительную магию со слоями, городить костыли.

Понятие слоя больше подойдёт для разделения принципиально разных вещей, которые с другом не связаны, либо гарантированно не перемешиваются. Например, в слое 1 отрисовать GUI, в слое 2 отрисовать главную сцену, в слое 3 отрисовать полупрозрачные объекты, в слое 4 - постэффекты. Или вот так: в слое 1 рисуете автомобильную дорогу, в слое 2 рисуете разметку полос на этой дороге. Также слои хорошо подойдут при виде сбоку для создания параллакса. Дальний фон в один слой, средний фон в другой, ближний в третий, а всё что на экране - в четвёртый.

+ собсно главная проблема как раз и заключается в том, как отрисовать объекты, когда их много. Вы привели вариант, когда у вас 2 объекта, а интересующий сценарий - когда объектов много. Что конкретно будете делать?
+ засчёт одной Y координаты вы не сможите разруливать объекты по физической высоте. Тойсть до тех пор пока у вас земля - одна большая плоскость и все объекты назодятся прямо на ней - всё будет гут. Как только научите персонажа прыгать или введёте "холмы" на карте - всё поедет лесом. Если конечно сейчас речь об изометрии.

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

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

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


Сообщение отредактировал puksus4 - Понедельник, 04 Мая 2020, 16:53
veeroteenДата: Понедельник, 04 Мая 2020, 16:56 | Сообщение # 11
был не раз
Сейчас нет на сайте
drcrack,
Цитата puksus4 ()
1) Определяешь для каждого спрайта точку, которой этот объект крепится к земле, у дерева будет низ ствола, посередине корней, вероятно почти у всех объектов это будет точка гдето внизу спрайта.
Для простоты можно взять тупо самую нижнюю точку спрайта по игрику и среднюю по иксу. Но возможно будут странности + будет хрень если в спрайте есть путсые области сбоков.
2) Расставляешь объекты в плоскости допустим xz, где x вправо, z от экрана. За позицию объекта считаешь позицию вышеупомянутой точки в мировом пространстве.
3) перед рендером собираешь пары позиция\реф объекта. Пихаешь сюда всё подряд без разбора, и статику и динамику.
4) сортируешь по убыванию z
5) рендеришь


вроде все ясно, он предлагал внести мне актера и и неписей в один массив с обьектами, и отсортировать по позиции, но подвижные объекты , что логично двигаются , а соответственно и будут премещаться внутри массива, так как массив остсортирован по позиции, а если двигается 1 обьект посреди массива, то двигаются и все остальные
DivESДата: Понедельник, 04 Мая 2020, 17:02 | Сообщение # 12
заслуженный участник
Сейчас нет на сайте
Цитата puksus4 ()
А вдруг вы захотите в своей схеме один из объектов слоя 2 отрисовать перед объектом слоя 1, а второй - за?

Это не совсем верная формулировка.
Рендер происходит именно послойно, то есть, если я захочу отрисовать объект перед другим, я изменю его слой (объекты одного слоя отрисовываются в порядке очереди, и ничто не может на неё повлиять).

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

Этой задачей буквально полчаса занимался на момент написания поста, так что, как будут новые результаты (сделаю тестовую сцену с разными высотами и несколькими слоями), — отпишусь! ^_^
veeroteenДата: Понедельник, 04 Мая 2020, 17:04 | Сообщение # 13
был не раз
Сейчас нет на сайте
puksus4,
Цитата puksus4 ()
+ засчёт одной Y координаты вы не сможите разруливать объекты по физической высоте. Тойсть до тех пор пока у вас земля - одна большая плоскость и все объекты назодятся прямо на ней - всё будет гут. Как только научите персонажа прыгать или введёте "холмы" на карте - всё поедет лесом. Если конечно сейчас речь об изометрии.

а вот это реально не понятно, у тебя в любом случае чем ниже координаты, тем ниже объект, никакие холмы ничего не изменят, у тебя в любом случае отрисовка идет от менших координат к большим
puksus4Дата: Понедельник, 04 Мая 2020, 17:08 | Сообщение # 14
частый гость
Сейчас нет на сайте
veeroteen, ну да.
И в чём конкретно вы видите проблему? Засчёт чего конкретно, вы считаете, будет тормозить?

Добавлено (04 Мая 2020, 17:11)
---------------------------------------------

Цитата veeroteen ()
а вот это реально не понятно, у тебя в любом случае чем ниже координаты, тем ниже объект, никакие холмы ничего не изменят, у тебя в любом случае отрисовка идет от менших координат к большим

Неверно, подумайте.
veeroteenДата: Понедельник, 04 Мая 2020, 17:12 | Сообщение # 15
был не раз
Сейчас нет на сайте
puksus4, при чем тут тормозить, речь о том что не имеет смысла делать такую схему, так как она ничего совершенно не меняет при всей своей громоздкости с 3-й координатой
puksus4Дата: Понедельник, 04 Мая 2020, 17:18 | Сообщение # 16
частый гость
Сейчас нет на сайте
Цитата DivES ()
Это не совсем верная формулировка.
Рендер происходит именно послойно, то есть, если я захочу отрисовать объект перед другим, я изменю его слой (объекты одного слоя отрисовываются в порядке очереди, и ничто не может на неё повлиять).


В таком случае дайте определение понятию слоя в вашем случае, потому что я видимо не понял.

Добавлено (04 Мая 2020, 17:19)
---------------------------------------------

Цитата veeroteen ()
puksus4, при чем тут тормозить, речь о том что не имеет смысла делать такую схему, так как она ничего совершенно не меняет при всей своей громоздкости с 3-й координатой

Эта схема
1) значительно всё упрощает
2) полностью решает вашу проблему.
Что конкретно вам не нравится?
veeroteenДата: Понедельник, 04 Мая 2020, 17:27 | Сообщение # 17
был не раз
Сейчас нет на сайте
puksus4,
Цитата puksus4 ()
Эта схема
1) значительно всё упрощает
2) полностью решает вашу проблему.
Что конкретно вам не нравится?

1)упрощает? для 3 координаты надо использовать 3-х мерный массив, что само по себе неудобно
2) полностью решает проблему? ты проблему вообще читал? нет никакой проблемы отрисовывать статику, с этим ребенок справится, проблема в отрисовке динамики относительно статики, по твоей 3 координате можно только неподвижные обьекты расставлять, потому что подвижные будут постоянно двигаться внутри массива, и если 1 объект еще как то можно внести, то представьчто в твоем 3-х мерном масиве бегает 2 человечка, и как эта сортировать предлаегашь, на каждый кадр? и сколько кадров это заберет?
puksus4Дата: Понедельник, 04 Мая 2020, 17:30 | Сообщение # 18
частый гость
Сейчас нет на сайте
Учитывая твой последний пост очевидно что ты не понял.

1) Массив одномерный в любом случае, внесение z координаты вообще никоим образом не влияет ни на размерность ни на количество объектов. Да и о какой n-мерности массива может идти речь, когда речь идёт об упорядоченном списке отдаваемых на рендер объектов.
2) Я и говорю про правильную отрисовку статики и динамики вместе.

Перечитай сообщения в теме.


Сообщение отредактировал puksus4 - Понедельник, 04 Мая 2020, 17:32
veeroteenДата: Понедельник, 04 Мая 2020, 17:32 | Сообщение # 19
был не раз
Сейчас нет на сайте
puksus4, предлагаешь динамику на кадр сортировать?
DivESДата: Понедельник, 04 Мая 2020, 17:34 | Сообщение # 20
заслуженный участник
Сейчас нет на сайте
puksus4, переменная, которую я назвал "слоем" отвечает за очерёдность отрисовки объектов на экране. В принципе, довольно подходящее название.
То есть, для фонового изображения layer_ = 5 (например), для курсора мыши — 0 (отрисовывается последним, поверх всего остального), для HUD-а — 1 (отрисовывается перед курсором мыши, то есть, перекрывает всё, кроме курсора).
Я же писал, это, по сути, та же z координата, только в моём видении. laugh

veeroteen, ты всё постоянно усложняешь. А корень всех зол в том, что ты так и не удосужился изучить C++ (иначе слов о трёхмерном массиве не было бы).


Сообщение отредактировал DivES - Понедельник, 04 Мая 2020, 17:36
  • Страница 1 из 2
  • 1
  • 2
  • »
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг