Question

I am using Java/LWJGL and am in the process of creating my own light object-orientated framework around LWJGL, during the process of learning OpenGL, however I am quite confused on what to do with glVertexAttribPointer.

Take my following code:

public class GameController extends Controller {
    //<editor-fold defaultstate="collapsed" desc="keep-imports">    
    static {
        int KEEP_LWJGL_IMPORTS = GL_2_BYTES | GL_ALIASED_LINE_WIDTH_RANGE | GL_ACTIVE_TEXTURE | GL_BLEND_COLOR | GL_ARRAY_BUFFER | GL_ACTIVE_ATTRIBUTE_MAX_LENGTH | GL_COMPRESSED_SLUMINANCE | GL_ALPHA_INTEGER | GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH | GL_ALREADY_SIGNALED | GL_ANY_SAMPLES_PASSED | GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH | GL_ACTIVE_PROGRAM | GL_ACTIVE_ATOMIC_COUNTER_BUFFERS | GL_ACTIVE_RESOURCES | GL_BUFFER_IMMUTABLE_STORAGE;
        int KEEP_OWN_IMPORTS = PROJECTION_MATRIX.getLocation();
    }
//</editor-fold>

    private Program testProgram;
    private VertexArray vertexArray;
    private ArrayBuffer arrayBuffer;

    private final Matrix4f modelviewMatrix = new Matrix4f();
    private final FloatBuffer modelViewMatrixBuffer = BufferUtils.createFloatBuffer(16);

    private float aspect;
    private Matrix4f projectionMatrix;

    final float[] vertexPositions = new float[] {
        -0.25f,  0.25f, -0.25f,
        -0.25f, -0.25f, -0.25f,
         0.25f, -0.25f, -0.25f,

         0.25f, -0.25f, -0.25f,
         0.25f,  0.25f, -0.25f,
        -0.25f,  0.25f, -0.25f,

         0.25f, -0.25f, -0.25f,
         0.25f, -0.25f,  0.25f,
         0.25f,  0.25f, -0.25f,

         0.25f, -0.25f,  0.25f,
         0.25f,  0.25f,  0.25f,
         0.25f,  0.25f, -0.25f,

         0.25f, -0.25f,  0.25f,
        -0.25f, -0.25f,  0.25f,
         0.25f,  0.25f,  0.25f,

        -0.25f, -0.25f,  0.25f,
        -0.25f,  0.25f,  0.25f,
         0.25f,  0.25f,  0.25f,

        -0.25f, -0.25f,  0.25f,
        -0.25f, -0.25f, -0.25f,
        -0.25f,  0.25f,  0.25f,

        -0.25f, -0.25f, -0.25f,
        -0.25f,  0.25f, -0.25f,
        -0.25f,  0.25f,  0.25f,

        -0.25f, -0.25f,  0.25f,
         0.25f, -0.25f,  0.25f,
         0.25f, -0.25f, -0.25f,

         0.25f, -0.25f, -0.25f,
        -0.25f, -0.25f, -0.25f,
        -0.25f, -0.25f,  0.25f,

        -0.25f,  0.25f, -0.25f,
         0.25f,  0.25f, -0.25f,
         0.25f,  0.25f,  0.25f,

         0.25f,  0.25f,  0.25f,
        -0.25f,  0.25f,  0.25f,
        -0.25f,  0.25f, -0.25f
    };

    public GameController(final boolean debug) {
        super(debug);
    }

    @Override
    protected void init() {
        glViewport(0, 0, 800, 600);
        testProgram = new Program(
                new VertexShader("shaders/test.vert.glsl").compile(),
                new FragmentShader("shaders/test.frag.glsl").compile()
                ).compile();
        testProgram.use();

        vertexArray = new VertexArray().create().bind();
        arrayBuffer = new StaticDrawArrayBuffer().create().fillData(vertexPositions);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(0);

        aspect = 800f / 600f;
        projectionMatrix = new Matrix4f().identity().perspective(50.0f, aspect, 0.1f, 1000.0f);
        Uniforms.setUniformMatrix4(PROJECTION_MATRIX, false, projectionMatrix);

        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CW);

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
    }

    @Override
    protected void render(final double msDelta) {
        glClearColor(0.0f, 0.25f, 0.0f, 1.0f);
        glClearDepthf(1f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        testProgram.use();

        for (int i = 0; i < 24000; i++) {
            float fVar = i + currentTime / 1000f * 0.3f;
            modelviewMatrix.identity()
                    .translate(0.0f, 0.0f, -8.0f)   //translate
                    .rotate(currentTime / 1000f * 45.0f, 0.0f, 1.0f, 0.0f)  //rotate around Y
                    .rotate(currentTime / 1000f * 21.0f, 1.0f, 0.0f, 0.0f)  //rotate around X
                    .translate(
                        (float)Math.sin(2.1f * fVar) * 2.0f,
                        (float)Math.cos(1.7f * fVar) * 2.0f,
                        (float)Math.sin(1.3f * fVar) * (float)Math.cos(1.5f * fVar) * 2.0f
                    );  //translate
            Uniforms.setUniformMatrix4(MODELVIEW_MATRIX, false, modelviewMatrix.writeToFloatBuffer(modelViewMatrixBuffer));
            testProgram.drawArrays(GL_TRIANGLES, 0, 36);
        }
    }

    @Override
    protected void shutdown() {
        testProgram.delete();
        vertexArray.delete();
        arrayBuffer.delete();
    }

    @Override
    protected void windowResized(final int width, final int height) {
        aspect = width * 1.0f / height;
        projectionMatrix = new Matrix4f().identity().perspective(50.0f, aspect, 0.1f, 1000.0f);
        Uniforms.setUniformMatrix4(PROJECTION_MATRIX, false, projectionMatrix);
    }

    public static void main(String[] args) {
        Controller controller = new GameController(false);
        controller.start();
    }
}

I hope someone can explain me exactly where I should put glVertexAttribPointer and glEnableVertexAttribArray in my object-orientated model, for example in VertexArray, or in ArrayBuffer (Buffer is superclass) or maybe even in Program?
I think that all my underlying calls to the framework are pretty self-explanetory, else feel free to ask.

Was it helpful?

Solution

It is difficult to say without seeing how this statement is implemented:

   arrayBuffer = new StaticDrawArrayBuffer().create().fillData(vertexPositions);

Assuming in order to create and fill your arrayBuffer with vertexPositions, the function has a side-effect of glBindBuffer (GL_ARRAY_BUFFER, ...) then you can call glVertexAttribPointer (...) meaningfully.

I would make it clear, however, that fillData (...) has said side-effect. As your code stands right now, nobody is going to know from looking at it that that line of code actually binds a buffer object. For consistency, you might even consider adding a bind (...) method to your StaticDrawArrayBuffer class and call that immediately before glVertexAttribPointer (...).

As for which class should wrap the functions you discussed, those are all stored per-Vertex Array Object. So add them to VertexArray. You may even want to modify the VertexAttribPointer wrapper interface so that it takes a reference to a buffer object, rather than using a selector / latch mechanism like the GL API does.

OTHER TIPS

You should enable them before you draw and disable them when you are done drawing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top