LWJGL glBufferData слишком медленно для размещения - PullRequest
0 голосов
/ 10 октября 2018

Я боролся с этим уже несколько недель.Я делаю воксельную игру, которая генерирует 16 ^ 3 фрагментов в виде одного чередуемого буфера для рендеринга.Я перенес большую часть работы в ThreadExecutor, но есть задержка OpenGL, которую я просто не могу устранить.

Приведенный ниже код - это мой класс Chunk (ChunkMesh.java), его конструктор вызывается в другом потоке, а функция init - это функция, которая выполняется в главном потоке для инициализации данных OpenGl.Это должно занимать менее миллисекунды, но регулярно занимает 5 и более и редко замораживается в течение более двух секунд, что недопустимо.

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

package client.engine.graphics;

import org.lwjgl.system.MemoryUtil;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL13.GL_TEXTURE0;
import static org.lwjgl.opengl.GL13.glActiveTexture;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;


public class ChunkMesh {
    private int vaoID;
    private List<Integer> vboIDList;
    private int vertexCount;
    public Material material;

    private float[] interleaved;
    private int[] indices;

    public ChunkMesh(float[] positions, float[] texCoords, float[] normals, int[] indices) {
        vertexCount = indices.length;
        vboIDList = new ArrayList<>();

        this.indices = indices;

        long buffTime = System.nanoTime();

        interleaved = new float[positions.length + texCoords.length + normals.length];
        int ind = 0;

        for (var i = 0; i < positions.length / 3; i++) {
            interleaved[ind++] = positions[i*3];
            interleaved[ind++] = positions[i*3+1];
            interleaved[ind++] = positions[i*3+2];

            interleaved[ind++] = normals[i*3];
            interleaved[ind++] = normals[i*3+1];
            interleaved[ind++] = normals[i*3+2];

            interleaved[ind++] = texCoords[i*2];
            interleaved[ind++] = texCoords[i*2+1];
        }

        buffTime = System.nanoTime() - buffTime;
    }

    public void init() {


        FloatBuffer interleavedBuffer = MemoryUtil.memAllocFloat(interleaved.length).put(interleaved).flip();
        interleaved = null;
        IntBuffer indicesBuffer = MemoryUtil.memAllocInt(indices.length).put(indices).flip();
        indices = null;

        vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);

        int vboID = glGenBuffers();
        vboIDList.add(vboID);

        long allocTime = System.nanoTime();

        glBindBuffer(GL_ARRAY_BUFFER, vboID);
        glBufferData(GL_ARRAY_BUFFER, interleavedBuffer, GL_STATIC_DRAW);

        int stride = (3 + 3 + 2) * 4;

        //Position VBO
        glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0);

        //Normals VBO
        glVertexAttribPointer(1, 3, GL_FLOAT, false, stride, 3 * 4);

        //TexCoord VBO
        glVertexAttribPointer(2, 2, GL_FLOAT, false, stride, 6 * 4);

        allocTime = System.nanoTime() - allocTime;
        float totalMs = allocTime / 1_000_000f;
        if (totalMs > 5) System.err.println(totalMs);
        else System.out.println(totalMs);

        //Index VBO
        vboID = glGenBuffers();
        vboIDList.add(vboID);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);

        MemoryUtil.memFree(interleavedBuffer);
        MemoryUtil.memFree(indicesBuffer);
    }

    public int getVaoID() {
        return vaoID;
    }

    public int getVertexCount() {
        return vertexCount;
    }

    public void initChunksRender() {
        Texture texture = material.getTexture();
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture.getID());
    }

    public void endChunksRender() {
        glBindTexture(GL_TEXTURE_2D, 0);
    }

    private void initRender() {

        //Draw the mesh
        glBindVertexArray(getVaoID());
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(2);
    }

    private void endRender() {
        //Restore State
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);
        glBindVertexArray(0);
    }

    public void render() {
        initRender();
        glDrawElements(GL_TRIANGLES, getVertexCount(), GL_UNSIGNED_INT, 0);
        endRender();
    }

    public void cleanup() {
        glDisableVertexAttribArray(0);

        //Delete the VBOs
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        for (int vboID : vboIDList) {
            glDeleteBuffers(vboID);
        }

        glBindVertexArray(0);
        glDeleteBuffers(vaoID);
    }

    public void deleteBuffers() {
        glDisableVertexAttribArray(0);

        //Delete the VBOs
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        for (int vboID : vboIDList) {
            glDeleteBuffers(vboID);
        }

        //Delete the VAO
        glBindVertexArray(0);
        glDeleteVertexArrays(vaoID);
    }
}
...