Форум программистов, компьютерный форум, киберфорум
SFML
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
396 / 32 / 7
Регистрация: 09.01.2019
Сообщений: 140

Оптимизация массива вершин при отрисовке тайловой карты

11.08.2022, 10:09. Показов 837. Ответов 1

Студворк — интернет-сервис помощи студентам
Добрый день! Написал класс для отрисовки тайловых карт, используемая библиотека - SFML. Карты составляются с помощью TiledMapEditor`а, каждый слой тайлов представлен массивом sf::Vertex. Отрисовка всех слоёв в общем случае выглядит так:

C++
1
2
3
4
5
6
7
// ..
 
std::vector<std::vector<sf::Vertex>> tile_layers;
 
// Draw call
for (auto& layer : tile_layers)
        target.draw(layer.data(), layer.size(), sf::Quads, states);
где каждый тайл в векторе представлен 4-мя вершинами. Теперь, непосредственный вопрос: в качестве графического примитива я указываю sf::Quads, версия SFML-2.5.1 ещё позволяет его использовать, но уже разработчики SFML предупреждают, что он устаревший и скоро будет исключён:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum PrimitiveType
{
    Points,        ///< List of individual points
    Lines,         ///< List of individual lines
    LineStrip,     ///< List of connected lines, a point uses the previous point to form a line
    Triangles,     ///< List of individual triangles
    TriangleStrip, ///< List of connected triangles, a point uses the two previous points to form a triangle
    TriangleFan,   ///< List of connected triangles, a point uses the common center and the previous point to form a triangle
    Quads,         ///< List of individual quads (deprecated, don't work with OpenGL ES)
 
    // Deprecated names
    LinesStrip     = LineStrip,     ///< \deprecated Use LineStrip instead
    TrianglesStrip = TriangleStrip, ///< \deprecated Use TriangleStrip instead
    TrianglesFan   = TriangleFan    ///< \deprecated Use TriangleFan instead
};
Это и произошло уже, в SFML-3.0, текущей разрабатываемой версии, sf::Quads отсутствует. Остаётся использовать sf::Triangles, sf::TriangleStrip или sf::TriangleFan, но тогда у меня уже не получается отрисовать весь непрерывный массив вершин одним вызовом - отрисовка ломается. Костыльный способ: обходя циклом массив как i +=4; и рисуя каждый тайл отдельным вызовом, sf::TriangleFan сохраняет отрисовку, но теряется смысл оптимизации из-за количества draw(...).
И совсем тупиковая ситуация возникает, если использовать sf::VertexBuffer - у меня нет доступа к любой вершине, они все на видеокарте и рисуются одним вызовом draw(...). Остаётся использовать sf::Triangles и, как следствие, на один тайл уже приходится 6 вершин( 2 треугольника), т.к. я не нашёл способа использовать буфер индексов для тайловых карт ни в SFML, ни в чистом OpenGl.

Какой может быть способ сократить количество вершин до 4-ёх на тайл, как в SFML 2.5.1?
Также, вопрос уже в сторону OpenGl: как можно использовать буфер индексов, чтобы для отрисовки тайловой карты с разными тайлами (т.е. без GL_REPEAT), например, размером 9х9 тайлов использовалось 100( 10х10 ) вершин?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.08.2022, 10:09
Ответы с готовыми решениями:

Не обновляет переменную при отрисовке обновлённой карты
Собственно проблема такова. Есть карта. И когда персонаж взаимодействует с объектами, изменения не отрисовываются. Хотя все переменные...

Скроллинг тайловой карты на openGL
Доброго времени суток! Сегодня я хотела бы обратиться к вам за помощью по следующему вопросу: как реализовать прокрутку карты, основанную...

Оптимизация бесконечной карты
На сцене присутствует Plane 5x5 с триггером, при входе в который Plane скрипт создаёт ещё восемь клонов вокруг изначального объекта Plane....

1
 Аватар для zayats80888
6344 / 3515 / 1428
Регистрация: 07.02.2019
Сообщений: 8,981
11.08.2022, 16:38
Лучший ответ Сообщение было отмечено EugeneNN как решение

Решение

Цитата Сообщение от EugeneNN Посмотреть сообщение
Остаётся использовать sf::Triangles и, как следствие, на один тайл уже приходится 6 вершин( 2 треугольника)
Это проблема? Это не то, на чем стоит экономить...
Цитата Сообщение от EugeneNN Посмотреть сообщение
я не нашёл способа использовать буфер индексов для тайловых карт ни в SFML, ни в чистом OpenGl.
В SFML их нет и вряд ли скоро появятся.
В OpenGl они доступны с версии 1.1.
Цитата Сообщение от EugeneNN Посмотреть сообщение
Также, вопрос уже в сторону OpenGl: как можно использовать буфер индексов, чтобы для отрисовки тайловой карты с разными тайлами (т.е. без GL_REPEAT), например, размером 9х9 тайлов использовалось 100( 10х10 ) вершин?
Раз уж решил в opengl, то переходи полностью (забудь про SFML/Graphics.hpp) и желательно на core profile.
Ну а так, вот простой пример средствами OpenGL 1.1:
Кликните здесь для просмотра всего текста
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
 
#include <cassert>
#include <algorithm>
// пример индексированной на legacy open gl (то что есть на десктопной версии SFML/OpenGL.hpp, если поддерживается GL 1.1)
void draw(sf::RenderTarget &target,
          sf::VertexBuffer const &vertices,
          const GLushort *indices,
          std::size_t count,
          sf::RenderStates const &states)
{
  if (vertices.getVertexCount() == 0 || indices == nullptr || count == 0)
    return;
 
  // с vertices.getPrimitiveType() и states.blendMode придется возится вручную, я тут делать этого не буду
  assert(vertices.getPrimitiveType() == sf::PrimitiveType::Triangles && states.blendMode == sf::BlendNone);
 
  // максимальный индекс не может превышать колличество вершин
  assert(*std::max_element(indices, indices + count) < vertices.getVertexCount());
 
  target.setActive();
 
  if (states.shader)
    sf::Shader::bind(states.shader);
 
  if (states.texture)
  {
    sf::Texture::bind(states.texture, sf::Texture::CoordinateType::Pixels);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  }
  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_COLOR_ARRAY);
 
  sf::VertexBuffer::bind(&vertices);
  glVertexPointer(2, GL_FLOAT, sizeof(sf::Vertex), reinterpret_cast<const void *>(offsetof(sf::Vertex, position)));
  glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(sf::Vertex), reinterpret_cast<const void *>(offsetof(sf::Vertex, color)));
  glTexCoordPointer(2, GL_FLOAT, sizeof(sf::Vertex), reinterpret_cast<const void *>(offsetof(sf::Vertex, texCoords)));
 
  auto viewport = target.getViewport(target.getView());
  glViewport(viewport.left, target.getSize().y - viewport.top - viewport.height, viewport.width, viewport.height);
 
  glMatrixMode(GL_PROJECTION);
  glLoadMatrixf(target.getView().getTransform().getMatrix());
 
  glMatrixMode(GL_MODELVIEW);
  glLoadMatrixf(states.transform.getMatrix());
 
  glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, indices);
 
  glDisableClientState(GL_COLOR_ARRAY);
  glDisableClientState(GL_VERTEX_ARRAY);
  if (states.texture)
  {
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    sf::Texture::bind(nullptr);
  }
 
  if (states.shader)
    sf::Shader::bind(nullptr);
}
 
int main()
{
  const unsigned int width = 400;
  const unsigned int height = 400;
  sf::RenderWindow window(sf::VideoMode(width, height), "Test", sf::Style::Close);
  window.setFramerateLimit(60);
 
  sf::VertexBuffer vertices{sf::PrimitiveType::Triangles, sf::VertexBuffer::Usage::Static};
  const unsigned bufsize = 8; // 2 прямоугольника
  if (!vertices.create(bufsize))
    return -1;
 
  {
    sf::Vertex const data[bufsize] =
        {
            // первй прямоугольник
            sf::Vertex(sf::Vector2f(50, 50), sf::Color::Red),
            sf::Vertex(sf::Vector2f(50, 100), sf::Color::Red),
            sf::Vertex(sf::Vector2f(150, 100), sf::Color::Green),
            sf::Vertex(sf::Vector2f(150, 50), sf::Color::Green),
            // второй прямоугольник
            sf::Vertex(sf::Vector2f(300, 100), sf::Color::Yellow),
            sf::Vertex(sf::Vector2f(300, 300), sf::Color::Blue),
            sf::Vertex(sf::Vector2f(350, 300), sf::Color::Blue),
            sf::Vertex(sf::Vector2f(350, 100), sf::Color::Yellow),
        };
    vertices.update(data);
  }
 
  GLushort const indices[6 + 6] =
      {
          0, 1, 2, 0, 2, 3, // два треугольника первого прямоугольника
          4, 5, 6, 4, 6, 7  // два треугольника второго прямоугольника
      };
  GLushort const *pIndices = indices;
 
  while (window.isOpen())
  {
    sf::Event e;
    while (window.pollEvent(e))
    {
      if (e.type == sf::Event::Closed)
        window.close();
      else if (e.type == sf::Event::MouseButtonReleased)
      {
        if (pIndices == indices)
          pIndices += 6;
        else
          pIndices = indices;
      }
    }
    window.clear();
    draw(window, vertices, pIndices, 6, sf::BlendNone);
    window.display();
  }
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.08.2022, 16:38
Помогаю со студенческими работами здесь

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

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

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

Ошибка при отрисовке линии
Добрый день гении! Пытаюсь разобраться с QPainter, QPaintEvent для того, чтобы рисовать собственно в своих программах. Только начал и...

Мерцание при отрисовке на pictureBox
Вызываю функцию по тику таймера: public void Draw(float x, float y) { Graphics g =...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Квантовые алгоритмы и обработка строк в Q#
EggHead 07.06.2025
Квантовые вычисления перевернули наше представление о том, как работать с данными, а Q# стал одним из ключевых языков для разработки квантовых алгоритмов. В традиционых системах мы оперируем битами —. . .
NUnit и C#
UnmanagedCoder 07.06.2025
В . NET существует несколько фреймворков для тестирования: MSTest (встроенный в Visual Studio), xUnit. net (более новый фреймворк) и, собственно, NUnit. Каждый имеет свои преимущества, но NUnit. . .
с++ Что нового?
russiannick 06.06.2025
Продолжаю обзор dev-cpp5. 11. Посмотрев на проекты, предоставленные нам для обучения, становится видно, что они разные по содержащимся файлам где: . dev обязательно присутствует . cpp/ . c один из них. . .
WebAssembly в Kubernetes
Mr. Docker 06.06.2025
WebAssembly изначально разрабатывался как бинарный формат инструкций для виртуальной машины, обеспечивающий высокую производительность в браузерах. Но потенциал технологии оказался гораздо шире - она. . .
Как создать первый микросервис на C# с ASP.NET Core, step by step
stackOverflow 06.06.2025
Если говорить простыми словами, микросервисная архитектура — это подход к разработке, при котором приложение строится как набор небольших, слабо связанных сервисов, каждый из которых отвечает за. . .
Рисование коллайдеров Box2D v2 на Three.js с помощью порта @box2d/core
8Observer8 06.06.2025
Используется порт Box2D v2 под названием @box2d/ core - пакет NPM. Загрузил документацию Box2D v2 на Netlify: https:/ / box2d-v2-docs. netlify. app/ Документацию Box2D v2 можно скачать с официального. . .
Как создать стек в Python
AI_Generated 05.06.2025
Как архитектор с более чем десятилетним опытом работы с Python, я неоднократно убеждался, что знание низкоуровневых механизмов работы стеков дает конкурентное преимущество при решении сложных задач. . . .
Server-Sent Events (SSE) в Node.js
run.dev 05.06.2025
Потоковая передача данных с сервера прямо в браузер стала повседневной потребностью - от биржевых графиков и спортивных трансляций до чатов и умных дашбордов. Много лет разработчики полагались на. . .
Создаем RESTful API на Golang с Fiber
golander 04.06.2025
Я перепробовал десятки фреймворков для создания RESTful API за последние годы, и когда впервые столкнулся с Fiber, понял, что это совсем другой уровень. Нет, я не собираюсь рассказывать сказки о. . .
Как работать с куки в ASP.NET Core
UnmanagedCoder 04.06.2025
Когда я впервые начал работать с куки в ASP. NET Core, меня поразило, насколько отличается работа с ними от классического ASP. NET. В Core все стало более декомпозированным - больше нет удобного. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
OSZAR »