OpenGL ES 2.0: How to specify normals when using an index?
Please show the new code, including the calls to glVertexAttribPointer().
Here's the new code:
//grab locations of attribute vars
glEnableVertexAttribArray(0); //vertices
glBindAttribLocation(prog, 0, "v_position"); //bind this var to 0
glEnableVertexAttribArray(1); //normals
glBindAttribLocation(prog, 1, "v_normal"); //bind this var to 1
//generate buffers
GLuint vbuf_id[2];
glGenBuffers(2, vbuf_id); //vertex buffers
//create and bind buffer for vertices
glBindBuffer(GL_ARRAY_BUFFER, vbuf_id[0]); //vertex buffer
glBufferData(GL_ARRAY_BUFFER, (model->size*sizeof(float))*3, (void*)modeldata, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
//create and bind buffer for normals
glBindBuffer(GL_ARRAY_BUFFER, vbuf_id[1]); //normal buffer
glBufferData(GL_ARRAY_BUFFER, (model->size*sizeof(float))*3, (void*)normaldata, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER,0); //unbind
And then I draw with this:
glDrawArrays(GL_TRIANGLES,0,(model->size*sizeof(float)));
Looks very fishy when you're multiplying the size of a float by the size of the model in order to determine how many vertices to draw. It is necessary to multiply in glBufferData because there the size is the number of bytes, but in glDrawArrays it is the number of vertices.
I figured it out! The problem was the normals needed to precede the vertices when specifying the attribute arrays. So, order matters.
Here are the updated portions of the code:
And also here:
Here are the updated portions of the code:
//grab locations of attribute vars
//array of normals must come before vertices!
glEnableVertexAttribArray(0); //normals
glBindAttribLocation(prog, 0, "v_normals");
glEnableVertexAttribArray(1); //vertices
glBindAttribLocation(prog, 1, "v_position");
And also here:
//normals
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
//vertices
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
Are you using a Vertex Array Object? It may be that the code works anyway, but it is mandatory from OpenGL 3.
The VAO isn't a data buffer, it is a number of states that are saved and then easily restored when it is time to draw.
The VAO isn't a data buffer, it is a number of states that are saved and then easily restored when it is time to draw.
I figured it out! The problem was the normals needed to precede the vertices when specifying the attribute arrays. So, order matters.
I just thought I'd post an update to this. The order the attribute variables wasn't actually the problem. The problem was with the vertex shader. I didn't realize this until running it on a device with a PowerVR SGX 530 GPU (the previous GPU was an Nvidia one).
The problem was that gl_Position was being written too early in the shader. It should be the last thing written in the shader. Although some drivers may work when gl_Position is written in the middle of the vertex shader, others may fail. This behavior seems to be driver-specific.
Here is an updated version that works with every device I've tried:
//vertex shader
attribute vec3 v_position;
attribute vec3 v_normal;
varying float lightIntensity;
uniform mat4 model;
//uniform mat4 view;
uniform mat4 proj;
void main()
{
//specify direction of light
vec3 light_dir = vec3(0.9,0.8,-3.0);
vec4 newNormal = proj * model * vec4(v_normal,0.0);
lightIntensity = max(0.0, dot(newNormal.xyz, light_dir));
//gl_Position must come LAST!
vec4 newPosition = proj * model * vec4(v_position,1.0);
gl_Position = newPosition;
}
The problem was that gl_Position was being written too early in the shader. It should be the last thing written in the shader. Although some drivers may work when gl_Position is written in the middle of the vertex shader, others may fail. This behavior seems to be driver-specific.
Are you sure about that? I have many shaders where gl_Position is not the last thing. Why does it have to be last?
Are you sure about that? I have many shaders where gl_Position is not the last thing. Why does it have to be last?
Yep, I just verified this. This is with a device running a PowerVR SGX 530 GPU. Now I can't say for sure or not whether other things in the code have any influence over this. I just know that if I write anything after gl_Position, the data for the vertices and normals gets swapped (i.e. OpenGL thinks vertex data is normal data and vice versa). That's without changing anything else, just literally moving up/down two lines of code and recompiling.
I indeed did not have to put gl_Position last when the vetex shader was running on an Nvidia chip. It didn't seem to care.
I also changed my code from using separate buffers to a single OpenGL buffer to hold both vertices and normals, but that didn't seem to affect this issue.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement