- 2,505
- 81
- 397
Туториал предполагает, что вы хоть как-то знакомы с рендерингом.
Модели в майне (1.7.10) рендерятся очень не очень. Уже при 30-50 моделях (~600 треугольников) на моем не очень мощном железе начинает просаживаться fps. Это нормально? Естественно нет. Лично меня это не устраивает. Что можно сделать?
Можно запилить рендер моделей через индексированные VBO + шейдеры. Это современных подход. Но в реалиях майна это не совсем хорошо. При рендере майн проходится по всем нужным сущностям и вызывает doRender для каждой. Соответственно, это постоянное включение-выключение шейдера, а это не дешевая операция. Любой нормальный движок сортирует объекты по шейдерам, тем самым переключение происходит только тогда, когда оно действительно нужно. Чтобы реализовать такое в майне потребуется переписать чуть ли не весь рендер и пачка костылей, посильных не каждому.
Есть другая устаревшая технология, но чрезвычайно простая в использовании - Display Lists. Что это такое?
Представляет собой группу команд OpenGL, которые сохранены (скомпилированы) для их последующего выполнения. После создания списка все данные вершин и пикселов оцениваются и копируются в память gpu. После того, как список скомпилирован, его можно повторно использовать без повторной передачи данных в драйвер, чтобы рисовать каждый кадр. Это является достаточно быстрым способом рисования статических данных.
В коде это выглядит примерно так.
Выглядит очень легко. А производительность растет даже не в 10-ки раз, а в сотни. Причем, если требуется отрисовать много мелких моделей, то по производительности превосходит VBO (из-за причины описанной выше).
Лично я пользуюсь своим загрузчиком obj моделей, но для туториала запилил обертку над форжевской obj моделью, которая предоставляет все обычные возможности интерфейса IModelCustom. Надеюсь, что кому-нибудь пригодится.
Использование никак не отличится от использования форжевской obj модели. Нужно всего лишь обернуть моим враппером.
P.S. Насчет новых версий. @Oldestkon где-то говорил, что тесселятор теперь использует VBO. Специально скачал на днях последнюю версию форжа и глянул. От VBO там только название. Если кто-то ( @Oldestkon С: ) сможет меня переубедить, то хорошо. Может быть я плохо разобрался. В общем, не знаю насчет новых версий. Если там obj модели такие же лагучие, то вполне можно воспользоваться данным туториалом.
P.P.S. Отдельное спасибо @GloomyFolken за советы.
Модели в майне (1.7.10) рендерятся очень не очень. Уже при 30-50 моделях (~600 треугольников) на моем не очень мощном железе начинает просаживаться fps. Это нормально? Естественно нет. Лично меня это не устраивает. Что можно сделать?
Можно запилить рендер моделей через индексированные VBO + шейдеры. Это современных подход. Но в реалиях майна это не совсем хорошо. При рендере майн проходится по всем нужным сущностям и вызывает doRender для каждой. Соответственно, это постоянное включение-выключение шейдера, а это не дешевая операция. Любой нормальный движок сортирует объекты по шейдерам, тем самым переключение происходит только тогда, когда оно действительно нужно. Чтобы реализовать такое в майне потребуется переписать чуть ли не весь рендер и пачка костылей, посильных не каждому.
Есть другая устаревшая технология, но чрезвычайно простая в использовании - Display Lists. Что это такое?
Представляет собой группу команд OpenGL, которые сохранены (скомпилированы) для их последующего выполнения. После создания списка все данные вершин и пикселов оцениваются и копируются в память gpu. После того, как список скомпилирован, его можно повторно использовать без повторной передачи данных в драйвер, чтобы рисовать каждый кадр. Это является достаточно быстрым способом рисования статических данных.
В коде это выглядит примерно так.
Код:
@SideOnly(Side.CLIENT)
public class RendererTileModel extends TileEntitySpecialRenderer
{
private int list;
public RendererTileModel(ResourceLocation res)
{
// Модель - локальный объект. Важно не оставлять в памяти информацию о вершинах.
IModelCustom model = AdvancedModelLoader.loadModel(res);
list = GL11.glGenLists(1);
GL11.glNewList(list, GL11.GL_COMPILE);
// Рендер. Да-да, прямо тут.
model.renderAll();
GL11.glEndList();
}
@Override
public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float pt)
{
GL11.glPushMatrix();
GL11.glTranslated(x, y, z);
GL11.glCallList(list);
GL11.glPopMatrix();
}
}
Выглядит очень легко. А производительность растет даже не в 10-ки раз, а в сотни. Причем, если требуется отрисовать много мелких моделей, то по производительности превосходит VBO (из-за причины описанной выше).
Лично я пользуюсь своим загрузчиком obj моделей, но для туториала запилил обертку над форжевской obj моделью, которая предоставляет все обычные возможности интерфейса IModelCustom. Надеюсь, что кому-нибудь пригодится.
Код:
public class ModelWrapperDisplayList implements IModelCustom
{
// Для каждой группы свой лист
private final Map<String, Integer> lists = new HashMap<>();
// Буффер, который будет содержать все листы. Для более быстрого рендера всей модели.
private final IntBuffer bufAll;
private final String type;
public ModelWrapperDisplayList(WavefrontObject model)
{
type = model.getType();
int list = GL11.glGenLists(model.groupObjects.size());
for (GroupObject obj : model.groupObjects) {
GL11.glNewList(list, GL11.GL_COMPILE);
model.renderPart(obj.name);
GL11.glEndList();
lists.put(obj.name, list++);
}
bufAll = initBuffer();
}
private IntBuffer initBuffer()
{
IntBuffer buf = BufferUtils.createIntBuffer(lists.size());
for (int i : lists.values()) {
buf.put(i);
}
buf.flip();
return buf;
}
@Override
public String getType()
{
return type;
}
@Override
public void renderAll()
{
GL11.glCallLists(bufAll);
}
@Override
public void renderOnly(String... groupNames)
{
if (groupNames == null || groupNames.length == 0) {
return;
}
for (String group : groupNames) {
renderPart(group);
}
}
@Override
public void renderPart(String partName)
{
Integer list = lists.get(partName);
if (list != null) {
GL11.glCallList(list);
}
}
@Override
public void renderAllExcept(String... groupNames)
{
if (groupNames == null || groupNames.length == 0) {
renderAll();
return;
}
for (Entry<String, Integer> it : lists.entrySet()) {
if (Arrays.binarySearch(groupNames, it.getKey(), String::compareTo) < 0) {
GL11.glCallList(it.getValue());
}
}
}
}
Код:
IModelCustom model;
model = AdvancedModelLoader.loadModel(resource);
model = new ModelWrapperDisplayList((WavefrontObject) model);
model.renderAll();
P.S. Насчет новых версий. @Oldestkon где-то говорил, что тесселятор теперь использует VBO. Специально скачал на днях последнюю версию форжа и глянул. От VBO там только название. Если кто-то ( @Oldestkon С: ) сможет меня переубедить, то хорошо. Может быть я плохо разобрался. В общем, не знаю насчет новых версий. Если там obj модели такие же лагучие, то вполне можно воспользоваться данным туториалом.
P.P.S. Отдельное спасибо @GloomyFolken за советы.