Lwjgl как упростить карту высот, чтобы получить более высокий fps?

Я немного разочарован fps в моей игре. Я все еще в начале разработки игры. Когда я впервые запустил игру, у меня было около 350 кадров в секунду. После того, как я добавил в программу карту высот и еще немного кода, логично ли падение фпс. Теперь у меня 39 кадров в секунду. Я еще в начале и фпс уже низкий. Интересно, что произойдет, когда я закончу проект, я думаю, что fps будет настолько низким, что это раздражает. Я знаю, что прошу очень многого от программы, карта высот - большая проблема. Карта имеет площадь 200*200 вершин, каждая вершина имеет высоту. 200 * 200 = 40000 вершин, каждый кадр. Я думал упростить карту. Моя идея состоит в том, чтобы создать метод, который упрощает всю карту высот. Каждые 4 вершины принадлежат четырехугольнику. Когда есть два или более четырехугольника рядом друг с другом, которые имеют одинаковую высоту в каждой вершине, их можно объединить в один четырехугольник. Дело в том, что вершин должно быть меньше. (Я думаю)

Я покажу пример кода моей карты высот.

package rgc.area;

import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

public class HeightMap {

    public int width;  // Vertices (width)
    public int height; // Vertices (height)

    public List<Float> map = new ArrayList<Float>();

    /**
     * 
     * @param width The width of the map (x-axis)
     * @param height The height of the map (z-axiz, NOT y-axis);
     */
    public HeightMap(int width, int height) {

        this.width = width;
        this.height = height;

        for(int i = 0; i < width * height; i++) {

            map.add(1.0f);
        }
    }

    public Dimension getSize() {

        return new Dimension(this.width, this.height);
    }

    public int getWidth() {

        return this.width;
    }

    public int getHeight() {

        return this.height;
    }

    /**
    * Set the height of a vertex of the map
    */
    public void setHeight(int x, int y, float h) {

        int index = x;

        if(y > 0) {

            index += (y - 1) * width;
        }

        map.set(index - 1, h);

        /* DEBUG
        for(int i = 0; i < map.size(); i++) {

            System.out.println(i + "   height: " + map.get(i));
        }
        */
    }

    public float getHeight(int x, int y) {

        int index = x;

        if(y > 0) {

            index += (y - 1) * width;
        }

        return map.get(index);
    }

    public float getHeight(float x, float y) {

        return this.getHeight((int)x, (int)y);
    }

    /**
     * This method simplifies the heightmap.
     * It will merge seperate quads with the same vertex heights.
     * This is to save memory and render faster.
     * 
     * This method should only be called when the heightmap is changed.
     * So this method should NOT be called every frame.
     */
    public void simplify() {

            // Don't really know how to do this.
        for(int i = 0; i < width * height; i++) {

            for(int w = 1; w < width - 1; w++) {

                if(map.get(i) == map.get(i + w)) {


                }
            }
        }
    }

}

Есть ли у кого-нибудь опыт с этим? Есть ли идеи или улучшения, и правильно ли я это делаю? Заранее спасибо.


person user2190492    schedule 12.03.2014    source источник
comment
Возможно, вы можете получить дополнительную помощь здесь   -  person Leviathan    schedule 13.03.2014
comment
Что ж. Это карта высот. Важно следующее: как вы отрисовываете это? 40 тысяч вершин должны быть едва заметны на современной видеокарте. Но если есть что-то вроде glVertex3f(x,y,map.getHeight(x,y)), то я могу себе представить, что это ужасно медленно. (Кстати: заметного улучшения можно было бы добиться, заменив List<Float> простым массивом float[], но для действительно высокой производительности вам следует рассмотреть Vertex Buffer Objects (VBO) и другие современные вещи OpenGL)   -  person Marco13    schedule 13.03.2014
comment
Используйте ВБО. Это поможет.   -  person Anubian Noob    schedule 01.04.2014


Ответы (1)


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

float[][] map;
public HeightMap(int width, int height) {
    this.map = new float[width][height];
    ...
}

Использование двумерного массива также упростит ваши методы getHeight(x, y) и setHeihgt(x, y, height). Помимо этого, это сильно зависит от вашего метода рендеринга. Я рекомендую использовать объекты буфера вершин с GL_TRIANGLE_STRIP для карт высот.
Для получения дополнительной информации об объектах буфера вершин см. http://lwjgl.org/wiki/index.php?title=Using_Vertex_Buffer_Objects_%28VBO%29
Кроме этого, попробуйте использовать отбраковку. Это может еще больше повысить производительность.
Кроме того, вы можете установить расстояние рендеринга для больших уровней, чтобы повысить производительность.

Я знаю, что, возможно, это не тот ответ, который вы искали, но я надеюсь. хотя это поможет.

Редактировать:
О, кажется, вы используете квадроциклы. Одна вещь, которую я сделал для карт высот, — я назначил вершину для каждого пикселя и соединил их с помощью GL_TRIANGLE_STRIP (как было предложено выше). Кроме этого, вы все еще можете использовать QUADS, я думаю, что это не будет иметь никакого значения. Если вы будете следовать приведенным выше советам, вы, вероятно, сможете получить карту высот 1000 * 1000 с частотой 200 кадров в секунду. (Это то, что у меня сейчас есть в одном проекте).

person uwap    schedule 18.04.2014