VBO和着色器的性能不佳

时间:2014-02-09 12:23:31

标签: opengl glsl lwjgl

我尝试使用VBO和着色器在现代OpenGL中渲染2048个四边形。但表现太可怕了。通过使用以下代码,我只有大约50 FPS。我想,我每一帧都会调用一些东西,这会减慢应用程序的速度,但我不知道它是什么。

另外我认为,如果仅更改了对象的位置,那么将每个帧的位置,视图和投影矩阵发送到着色器的速度非常慢。

如何才能更快地获取此代码?

型号代码:

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.Arrays;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

public abstract class Model
{
    private TexturedVertex[] vertices;
    private byte[] indices;

    private FloatBuffer verticesBuffer;
    private ByteBuffer indicesBuffer;

    private Vector3f position;
    private Vector3f angle;
    private Vector3f scale;

    int shaderProgram;
    int indicesCount;

    private int projectionMatrixLocation;
    private int viewMatrixLocation;
    private int modelMatrixLocation;

    int vaoID;
    int vboID;
    int vboiID;


    public void load (TexturedVertex[] vertices, byte[] indices, Shader shader)
    {
        this.position = new Vector3f(0, 0, -1);
        this.angle    = new Vector3f(0, 0, 0);
        this.scale    = new Vector3f(1, 1, 1);

        this.vertices = vertices;
        this.indices = indices;
        this.shaderProgram = shader.getProgramID();

        this.generateBuffer();
        this.generateArrayBufferObjects();
        this.configureShader();
    }


    private void generateBuffer()
    {
        // === Vertices Buffer === //
            this.verticesBuffer = BufferUtils.createFloatBuffer(vertices.length * TexturedVertex.elementCount);

            for (int i = 0; i < vertices.length; i++)
            {
                verticesBuffer.put(vertices[i].getElements());
                System.out.print   ("XYZW: " + Arrays.toString(vertices[i].getXYZW()));
                System.out.print   (" RGBA: " + Arrays.toString(vertices[i].getRGBA()));
                System.out.println (" ST: " + Arrays.toString(vertices[i].getST()));
            }
            verticesBuffer.flip();

        // === Generate Indices Buffer === //
            this.indicesCount = indices.length;         
            this.indicesBuffer = BufferUtils.createByteBuffer(indicesCount);
            indicesBuffer.put(indices);
            indicesBuffer.flip();
    }

    private void generateArrayBufferObjects()
    {
        // === Generate VAO & VBO === //
            this.vaoID = GL30.glGenVertexArrays();
            GL30.glBindVertexArray(vaoID);

            this.vboID = GL15.glGenBuffers();
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
            GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);

            this.vboiID = GL15.glGenBuffers();              
            GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiID);
            GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW);

            System.out.println ();
            System.out.println ("VAO-ID: #" + vaoID);
            System.out.println ("VBO-ID: #" + vboID);   
            System.out.println ("VBOI-ID: #" + vboiID); 

        // === Put informations to shader === //
            GL20.glVertexAttribPointer(0, TexturedVertex.positionElementCount,  GL11.GL_FLOAT, false, TexturedVertex.stride, TexturedVertex.positionByteOffset);
            GL20.glVertexAttribPointer(1, TexturedVertex.colorElementCount,     GL11.GL_FLOAT, false, TexturedVertex.stride, TexturedVertex.colorByteOffset);
            GL20.glVertexAttribPointer(2, TexturedVertex.textureElementCount,   GL11.GL_FLOAT, false, TexturedVertex.stride, TexturedVertex.textureByteOffset);

        // === Unbind Buffers === //
            GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0); 
            GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
            GL30.glBindVertexArray(0);

    }


    private void configureShader()
    {
        // === Bind shader === //
            GL20.glUseProgram(shaderProgram);

        // === Get matrix location === //
            this.projectionMatrixLocation = GL20.glGetUniformLocation(shaderProgram, "projectionMatrix");
            this.viewMatrixLocation       = GL20.glGetUniformLocation(shaderProgram, "viewMatrix");
            this.modelMatrixLocation      = GL20.glGetUniformLocation(shaderProgram, "modelMatrix");        

        // === Update the matrix === //
            this.updateMatrix();

        // === Unbind shader === //
            GL20.glUseProgram(0);
    }   

    void updateMatrix()
    {
        // === Bind shader === //
            GL20.glUseProgram(shaderProgram);

        // === Load matrix === //
            Matrix4f projectionMatrix = GameManager.camera.getProjectionMatrix();
            Matrix4f viewMatrix = GameManager.camera.getViewMatrix();
            Matrix4f modelMatrix = new Matrix4f();

        // === Scale, translate and rotate matrix === //
            Matrix4f.scale(scale, modelMatrix, modelMatrix);
            Matrix4f.translate(position, modelMatrix, modelMatrix);
            Matrix4f.rotate(Util.degreesToRadians(angle.z), new Vector3f(0, 0, 1), modelMatrix, modelMatrix);
            Matrix4f.rotate(Util.degreesToRadians(angle.y), new Vector3f(0, 1, 0), modelMatrix, modelMatrix);
            Matrix4f.rotate(Util.degreesToRadians(angle.x), new Vector3f(1, 0, 0), modelMatrix, modelMatrix);

        // === Apply uniform matrix to shader  === //
            FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);

            projectionMatrix.store(matrixBuffer);
            matrixBuffer.flip();
            GL20.glUniformMatrix4(projectionMatrixLocation, false, matrixBuffer);

            viewMatrix.store(matrixBuffer);
            matrixBuffer.flip();
            GL20.glUniformMatrix4(viewMatrixLocation,       false, matrixBuffer);

            modelMatrix.store(matrixBuffer);
            matrixBuffer.flip();
            GL20.glUniformMatrix4(modelMatrixLocation,      false, matrixBuffer);

        // === Unbind shader === //
            GL20.glUseProgram(0);
    }

    public void setPosition (Vector3f newPosition)
    {
        this.position = newPosition;
        this.updateMatrix();
    }

    public void setAngle (Vector3f newAngle)
    {
        this.angle = newAngle;
        this.updateMatrix();
    }

    public void setScale (Vector3f newAngle)
    {
        this.scale = newAngle;
        this.updateMatrix();
    }
}

呈现代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.vector.Vector3f;

import de.matthiasmann.twl.utils.PNGDecoder;
import de.matthiasmann.twl.utils.PNGDecoder.Format;

public class GameManager
{
    private Logger logger;
    private Profiler profiler;
    private Window window;
    public static Camera camera;

    public GameManager()
    {

        init();     

        ModelChest[] chests = new ModelChest[2048];
        for (int i = 0; i < 2048; i++)
        {
            chests[i] = new ModelChest();   
        }


        ModelChest chest = new ModelChest();        
        ModelChest chestB = new ModelChest();       

        int textureID = loadPNGTexture ("Getigerte-Katze-Baby-Decke.png", GL13.GL_TEXTURE0);

        while (!window.isCloseRequested())
        {           
            GL11.glEnable(GL11.GL_DEPTH_TEST);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            {               
                chest.setPosition(new Vector3f(1, 0, -0.5F));               
                GL20.glUseProgram(chest.shaderProgram);

                    GL13.glActiveTexture(GL13.GL_TEXTURE0);
                    GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);

                    GL30.glBindVertexArray(chest.vaoID);
                    GL20.glEnableVertexAttribArray(0);
                    GL20.glEnableVertexAttribArray(1);
                    GL20.glEnableVertexAttribArray(2);

                    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, chest.vboiID);
                    {
                        GL11.glDrawElements(GL11.GL_TRIANGLES, chest.indicesCount, GL11.GL_UNSIGNED_BYTE, 0);       
                    }
                    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

                    GL20.glDisableVertexAttribArray(0);
                    GL20.glDisableVertexAttribArray(1);
                    GL20.glDisableVertexAttribArray(2);
                    GL30.glBindVertexArray(0);

                //GL20.glUseProgram(0);


                for (float i = 0; i < 2048; i++)
                {           
                    chests[(int)i].setPosition(new Vector3f(-1F + ((float)i / 30F), 0, -0.5F)); 
                GL20.glUseProgram(chests[(int)i].shaderProgram);

                    GL30.glBindVertexArray(chests[(int)i].vaoID);
                    GL20.glEnableVertexAttribArray(0);
                    GL20.glEnableVertexAttribArray(1);
                    GL20.glEnableVertexAttribArray(2);

                    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, chests[(int)i].vboiID);
                    {
                        GL11.glDrawElements(GL11.GL_TRIANGLE_STRIP , chests[(int)i].indicesCount, GL11.GL_UNSIGNED_BYTE, 0);        

                    }
                    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

                    GL20.glDisableVertexAttribArray(0);
                    GL20.glDisableVertexAttribArray(1);
                    GL20.glDisableVertexAttribArray(2);
                    GL30.glBindVertexArray(0);

                    GL20.glUseProgram(0);
                }
            }


            Display.update();
        }

        destroy();
    }

    public void init()
    {       
        logger = new Logger();
        logger.init();

        profiler = new Profiler();
        profiler.init();

        window = new Window();
        window.init();

        camera = new Camera();
        camera.init();
    }

    public void destroy()
    {
        logger.destroy();       
        profiler.destroy(); 
        window.destroy();
        camera.destroy();

        System.exit(0);
    }

    private int loadPNGTexture(String filename, int textureUnit) {
        ByteBuffer buf = null;
        int tWidth = 0;
        int tHeight = 0;

        try {
            // Open the PNG file as an InputStream
            InputStream in = new FileInputStream(filename);
            // Link the PNG decoder to this stream
            PNGDecoder decoder = new PNGDecoder(in);

            // Get the width and height of the texture
            tWidth = decoder.getWidth();
            tHeight = decoder.getHeight();


            // Decode the PNG file in a ByteBuffer
            buf = ByteBuffer.allocateDirect(
                    4 * decoder.getWidth() * decoder.getHeight());
            decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
            buf.flip();

            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

        // Create a new texture object in memory and bind it
        int texId = GL11.glGenTextures();
        GL13.glActiveTexture(textureUnit);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);

        // All RGB bytes are aligned to each other and each component is 1 byte
        GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);

        // Upload the texture data and generate mip maps (for scaling)
        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, tWidth, tHeight, 0, 
                GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
        GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);

        // Setup the ST coordinate system
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);

        // Setup what to do when the texture has to be scaled
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, 
                GL11.GL_NEAREST);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, 
                GL11.GL_LINEAR_MIPMAP_LINEAR);


        return texId;
    }

}

照相机:

import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;

public class Camera extends Worker
{
    private Matrix4f projectionMatrix;
    private Matrix4f viewMatrix;

    private Vector3f position;
    private Vector3f angle;

    private float fieldOfView;
    private float aspectRatio;
    private float nearPlane;
    private float farPlane;

    private float xScale;
    private float yScale;
    private float frustumLength;

    @Override
    protected void onInitialize()
    {       
        // Apply default settings       
        this.fieldOfView = 60f;
        this.aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
        this.nearPlane = 0.1f;
        this.farPlane = 100f;

        this.position = new Vector3f(0, 0, -1);
        this.angle = new Vector3f(0, 0, 0);

        // Calculate scale and furstum length
        this.yScale = Util.coTangent(Util.degreesToRadians(fieldOfView / 2f));
        this.xScale = yScale / aspectRatio;
        this.frustumLength = farPlane - nearPlane;

        // Projection Matrix
        projectionMatrix = new Matrix4f();

        projectionMatrix.m00 = xScale;
        projectionMatrix.m11 = yScale;
        projectionMatrix.m22 = -((farPlane + nearPlane) / frustumLength);
        projectionMatrix.m23 = -1;
        projectionMatrix.m32 = -((2 * nearPlane * farPlane) / frustumLength);
        projectionMatrix.m33 = 0;

        // View Matrix
        viewMatrix = new Matrix4f();

        Matrix4f.translate(position, viewMatrix, viewMatrix);
        Matrix4f.rotate(Util.degreesToRadians(angle.z), new Vector3f(0, 0, 1), 
                viewMatrix, viewMatrix);
        Matrix4f.rotate(Util.degreesToRadians(angle.y), new Vector3f(0, 1, 0), 
                viewMatrix, viewMatrix);
        Matrix4f.rotate(Util.degreesToRadians(angle.x), new Vector3f(1, 0, 0), 
                viewMatrix, viewMatrix);
    }

    public Matrix4f getProjectionMatrix()
    {
        return this.projectionMatrix;
    }

    public Matrix4f getViewMatrix()
    {
        return this.viewMatrix;
    }

    public void setPosition (Vector3f newPosition)
    {       
        Matrix4f.translate(newPosition, viewMatrix, viewMatrix);
    }

    public void setPosition (float x, float y, float z)
    {       
        setPosition(new Vector3f (x, y, z));
    }

    public void setAngle (Vector3f newAngle)
    {       
        Matrix4f.rotate(Util.degreesToRadians(newAngle.z), new Vector3f(0, 0, 1), 
                viewMatrix, viewMatrix);
        Matrix4f.rotate(Util.degreesToRadians(newAngle.y), new Vector3f(0, 1, 0), 
                viewMatrix, viewMatrix);
        Matrix4f.rotate(Util.degreesToRadians(newAngle.x), new Vector3f(1, 0, 0), 
                viewMatrix, viewMatrix);
    }

    public void setAngle (float x, float y, float z)
    {       
        setAngle(new Vector3f (x, y, z));
    }

    @Override
    protected void onDestroy()
    {
        ;

    }

    @Override
    protected void onTick()
    {
        ;
    }
}

着色器:

#version 150 core

uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {
    gl_Position = projectionMatrix * viewMatrix * modelMatrix *  in_Position;

    pass_Color = in_Color;
    pass_TextureCoord = in_TextureCoord;
}

0 个答案:

没有答案