iosopengl-es-2.0vertex-shadervertex-array

Using glVertexAttribPointer to draw model in OpenGL 2.0 with shaders


I've knocked up object orientated iOS app loosely based on the default template which uses OpenGLES 2.0 and also uses Shaders but I'm trying to load in a model where I used to call this:

#import "./sphere_model.h"
glVertexPointer(3, GL_FLOAT, 0, sphere_modelVerts);
glNormalPointer(GL_FLOAT, 0, sphere_modelNormals);
glDrawArrays(GL_TRIANGLES, 0, sphere_modelNumVerts);

The reason why I used that code above was because I converted my .obj file into a file I can include with all the arrays I need defined (see obj2opengl). Now, I'm not 100% but I read somewhere that glVertexPointer is deprecated and I'm struggling to get this working in my demo app. Currently I'm drawing this simple cube:

cubey!

The template where I took the OpenGL shader code from uses glVertexAttribPointer instead and the vertex array used is slightly different because it includes normals within the same array:

GLfloat gCubeVertexData[216] =
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,          1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    ....
};

I use this code to draw the cube (after loading the shader file):

glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));

glUseProgram(GetProgram());

glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

glDrawArrays(GL_TRIANGLES, 0, 36);

glDisableVertexAttribArray(GLKVertexAttribNormal);
glDisableVertexAttribArray(GLKVertexAttribPosition);

glBindVertexArrayOES(0);

Now my question is, using Open GLES 2.0, is it possible to load in the vertices defined by obj2opengl I mentioned earlier using glVertexAttribPointer instead of glVertexPointer while still using the shader?

Here is some samples from one of the model files:

unsigned int sphere_modelNumVerts = 864;

float sphere_modelVerts [] = {
    -1.93077099209747e-18, 0.49025, 0.098,
    0.098, 0.49025, -1.78225014655151e-18,
    -1.93077099209747e-18, 0.5, -1.78225014655151e-18,
    -1.93077099209747e-18, 0.44725, 0.2235,
    0.11775, 0.4715, 0.11775,
    -1.93077099209747e-18, 0.49025, 0.098,
    ...
}

float sphere_modelNormals [] = {
    0, 0.980579906452681, 0.196119981290155,
    0.196119981290155, 0.980579906452681, 0,
    0, 1, 0,
    0, 0.894429190989163, 0.447209595499104,
    ...
}

float sphere_modelTexCoords [] = {
    0.75000, 0.0628300000000001,
    1, 0.0628300000000001,
    0.87500, 0,
    0.75000, 0.14758,
    ...
}

Solution

  • Use struct of arrays. The code sample that is drawing a cube is using interleaved vertex data. It is also called array of structures. This is a recommended layout.

    To support your data format simply create individual buffer for each attribute (sphere_modelVerts, sphere_modelNormals ...) and define attributes without offsets.