LWJGL glBufferData太慢,无法分配

时间:2018-10-10 06:51:29

标签: java opengl lwjgl voxel

我已经为此苦苦挣扎了几个星期。我正在制作一个体素游戏,该游戏生成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);
    }
}

0 个答案:

没有答案