Search code examples
opengllwjgl

Separate color and vertices in separate VBOs?


I am creating a 3D cube from an array made out of vertices and colours. I would like to separate these colours and vertices into their separate arrays and render the cube with the right colors. But I do not know how to properly create the VBO so the program doesn't crash.

So this is my Cube class that holds vertices,

 private float[] vertices = {
        //Position              //Colours
        // VO
        -0.5f,  0.5f,  0.5f,    0.5f, 0.0f, 0.0f, 1.0f, //Bottom right
        // V1
        -0.5f, -0.5f,  0.5f,    0.0f, 0.5f, 0.0f, 1.0f, //Top Left
        // V2
        0.5f, -0.5f,  0.5f,     0.0f, 0.0f, 0.5f, 1.0f, //Top Right
        // V3
        0.5f,  0.5f,  0.5f,     0.0f, 0.5f, 0.5f, 1.0f, //Bottom left
        // V4
        -0.5f,  0.5f, -0.5f,    0.5f, 0.0f, 0.0f, 1.0f,
        // V5
        0.5f,  0.5f, -0.5f,     0.0f, 0.5f, 0.0f, 1.0f,
        // V6
        -0.5f, -0.5f, -0.5f,    0.0f, 0.0f, 0.5f, 1.0f,
        // V7
        0.5f, -0.5f, -0.5f,     0.0f, 0.5f, 0.5f, 1.0f,
};

private int[] triangles = {
        // Front face
        0, 1, 3, 3, 1, 2,
        // Top Face
        4, 0, 3, 5, 4, 3,
        // Right face
        3, 2, 7, 5, 3, 7,
        // Left face
        6, 1, 0, 6, 0, 4,
        // Bottom face
        2, 1, 6, 2, 6, 7,
        // Back face
        7, 6, 4, 7, 4, 5,
};

And this is how I want my arrays to be seperated (Same class as above)

    private float[] vertices = {
            //Position           
            // VO
            -0.5f,  0.5f,  0.5f,    
            // V1
            -0.5f, -0.5f,  0.5f,   
            // V2
            0.5f, -0.5f,  0.5f,   
            // V3
            0.5f,  0.5f,  0.5f,   
            // V4
            -0.5f,  0.5f, -0.5f, 
            // V5
            0.5f,  0.5f, -0.5f,  
            // V6
            -0.5f, -0.5f, -0.5f,   
            // V7
            0.5f, -0.5f, -0.5f,   
    };

   private float[] colours = {
            //Colours
            // VO
             0.5f, 0.0f, 0.0f, 1.0f,
            // V1
            0.0f, 0.5f, 0.0f, 1.0f,
            // V2
            0.0f, 0.0f, 0.5f, 1.0f,
            // V3
            0.0f, 0.5f, 0.5f, 1.0f,
            // V4
            0.5f, 0.0f, 0.0f, 1.0f,
            // V5
            0.0f, 0.5f, 0.0f, 1.0f,
            // V6
            0.0f, 0.0f, 0.5f, 1.0f,
            // V7
             0.0f, 0.5f, 0.5f, 1.0f,
    };

private int[] triangles = {
        // Front face
        0, 1, 3, 3, 1, 2,
        // Top Face
        4, 0, 3, 5, 4, 3,
        // Right face
        3, 2, 7, 5, 3, 7,
        // Left face
        6, 1, 0, 6, 0, 4,
        // Bottom face
        2, 1, 6, 2, 6, 7,
        // Back face
        7, 6, 4, 7, 4, 5,
};

So this is my Mesh class where all the rendering stuff gets procesed. My question is how can I apply the colours array into this class ? I can only render he cube with the right colors only if the vertices class contains the vertices position and colors, not if they are seperate.

 public void Init(){

        /*
        float aspectRation = (float) width / height;
        projectionMatrix = new Matrix4f().perspective(FOV, aspectRation, nearPlane, farPlane);
         */

        //COMPILE AND LINK SHADERS
        //************
        // Vertex Shader
        //************

        vertexID = glCreateShader(GL_VERTEX_SHADER); //Load shader type
        glShaderSource(vertexID, vertexShaderSrc); // Pass shader source to GPU
        glCompileShader(vertexID); // Compile shader

        //Error check in compilation process
        int success = glGetShaderi(vertexID,GL_COMPILE_STATUS);
        if(success == GL_FALSE){
            int lenght = glGetShaderi(vertexID, GL_INFO_LOG_LENGTH);
            System.out.println("ERROR: 'defaultShader.glsl: \n\t Vertex shader compilation failed !");
            System.out.println(glGetShaderInfoLog(vertexID,lenght));
        }

        //************
        // Fragment Shader
        //************

        fragmentID = glCreateShader(GL_FRAGMENT_SHADER); //Load shader type
        glShaderSource(fragmentID, fragmentShaderSrc); // Pass shader source to GPU
        glCompileShader(fragmentID); // Compile shader

        //Error check in compilation process
        success = glGetShaderi(fragmentID,GL_COMPILE_STATUS);
        if(success == GL_FALSE){
            int lenght = glGetShaderi(fragmentID, GL_INFO_LOG_LENGTH);
            System.out.println("ERROR: 'defaultShader.glsl: \n\t Vertex shader compilation failed !");
            System.out.println(glGetShaderInfoLog(fragmentID,lenght));
        }


        //************
        // Link shaders and Check for errors
        //************

        shaderProgram = glCreateProgram();
        glAttachShader(shaderProgram, vertexID);
        glAttachShader(shaderProgram, fragmentID);
        glLinkProgram(shaderProgram);

        //Check for linking errors
        success = glGetProgrami(shaderProgram, GL_LINK_STATUS);
        if(success == GL_FALSE){
            int lenght = glGetProgrami(shaderProgram, GL_INFO_LOG_LENGTH);
            System.out.println("ERROR: 'defaultShader.glsl:' \n\t Linking of shaders failed !");
            System.out.println(glGetProgramInfoLog(fragmentID,lenght));
            assert false : "";
        }

        int uniformLocation = glGetUniformLocation(shaderProgram,"projectionMatrix");
        uniforms.put("projectionMatrix",uniformLocation);

        int uniformPosLocation = glGetUniformLocation(shaderProgram,"worldMatrix");
        uniformsPosition.put("worldMatrix",uniformPosLocation);

        //************
        // Generate VAO, VBO and EBO and send them to GPU
        //************

        // GENERATE VAO
        VAO_ID = glGenVertexArrays();
        glBindVertexArray(VAO_ID);


        //Create float buffer of vertices
        FloatBuffer vertexBuffer = MemoryUtil.memAllocFloat(vertices.length);
        vertexBuffer.put(vertices).flip();


        // GENERATE VBO and upload VertexBuffer
        VBO_ID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, VBO_ID);
        glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
        memFree(vertexBuffer);

        //Create Indices and upload them
        IntBuffer elementBuffer = MemoryUtil.memAllocInt(triangles.length);
        elementBuffer.put(triangles).flip();

        //Create EBO
        EBO_ID = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO_ID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBuffer, GL_STATIC_DRAW);

        //Create vertex attribute pointers
        int positionSize = 3;
        int colorSize = 4;
        int floatSizeInBytes = 4;
        int vertexSizeInBytes = (positionSize + colorSize) * floatSizeInBytes;


        glVertexAttribPointer(0, positionSize, GL_FLOAT, false, vertexSizeInBytes, 0);
        glEnableVertexAttribArray(0);

        glVertexAttribPointer(1, colorSize, GL_FLOAT, false, vertexSizeInBytes, positionSize * floatSizeInBytes);
        glEnableVertexAttribArray(1);

        // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);



    }

    public void Render(){

        //Bind shader program
        glUseProgram(shaderProgram);
        SetUniform("projectionMatrix", projectionMatrix);
        SetUniform2("worldMatrix", worldMatrix);

        //Bind VAO currently in use
        glBindVertexArray(VAO_ID);

        //Enable vertex atribute pointers
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        //Draw triangles
        glDrawElements(GL_TRIANGLES,triangles.length, GL_UNSIGNED_INT,0);

        //Unbind everything
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glBindVertexArray(0);
        glUseProgram(0);

    }

Solution

  • From what I understand about OpenGL, it looks like as if you are closing the current buffers being send to the GPU before it can receive colour data. (I might be completely wrong about this)

    I tried this aproach on my project, so you may have to fidle little bit to make it work for your project, but the aproach should be the same. With this you should be able to use the seperated arrays for color, triangles and vertices

            //************
        // Generate VAO, VBO and EBO and send them to GPU
        //************
    
        // GENERATE VAO
        VAO_ID = glGenVertexArrays();
        glBindVertexArray(VAO_ID);
    
        //POSITION VBO
        // GENERATE VBO and upload VertexBuffer
        VBO_ID = glGenBuffers();
        //Create float buffer of vertices
        FloatBuffer vertexBuffer = MemoryUtil.memAllocFloat(vertices.length);
        vertexBuffer.put(vertices).flip();
        glBindBuffer(GL_ARRAY_BUFFER, VBO_ID);
        glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
    
        //COLOR VBO
        //GENERATE VBO and upload colourBuffer
        colourVBO_ID = glGenBuffers();
        FloatBuffer colourBuffer = MemoryUtil.memAllocFloat(colours.length);
        colourBuffer.put(colours).flip();
        glBindBuffer(GL_ARRAY_BUFFER, colourVBO_ID);
        glBufferData(GL_ARRAY_BUFFER, colourBuffer, GL_STATIC_DRAW);
        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 4, GL_FLOAT, false, 0,  0);
    
        //TRIANGLE VBO
        //Create Indices and upload them
        EBO_ID = glGenBuffers();
        IntBuffer elementBuffer = MemoryUtil.memAllocInt(triangles.length);
        elementBuffer.put(triangles).flip();
        //Create EBO
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO_ID);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementBuffer, GL_STATIC_DRAW);
    
        glBindBuffer(GL_ARRAY_BUFFER,0);
        glBindVertexArray(0);
        // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        memFree(vertexBuffer);
        memFree(colourBuffer);
        memFree(elementBuffer);