当前位置: 动力学知识库 > 问答 > 编程问答 >

ios - GLDrawElements Crashing Program

问题描述:

I am trying to render some vertices to an Open GL ES window. My program keeps crashing on the GLDrawElements command. I am trying to pass some VBOs for the vertices "bindPosition", "bindNorml" and "Index" of type GLFloat.

Here is a link to my rendering method:

- (void)render:(CADisplayLink*)displayLink {

glViewport(0, 0, self.frame.size.width, self.frame.size.height);

glClearColor(0.3, 0.5, 0.9, 1.0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);

glEnable(GL_CULL_FACE);

GLKMatrix4 modelView = GLKMatrix4Make(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -10, -30, 1);

GLKMatrix4 projectionView = GLKMatrix4Make(3.6213202476501465, 0, 0, 0, 0, 2.4142136573791504, 0, 0, 0, 0, -1.0020020008087158, -1, 0, -24.142135620117188, 28.05805778503418, 30);

// Upload Transforms

glUniformMatrix4fv(_modelViewMatrixUniform, 1, 0, modelView.m);

glUniformMatrix4fv(_modelViewProjMatrixUniform, 1, 0, projectionView.m);

// Upload Bones

glUniformMatrix4fv(_bonesUniform, 1, 0, bones);

glBindBuffer(GL_ARRAY_BUFFER, _bindPositionBuffer);

glVertexAttribPointer(_VertexPositionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(bindPosition), 0);

glBindBuffer(GL_ARRAY_BUFFER, _bindNormalBuffer);

glVertexAttribPointer(_VertexNormalAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(bindNormal), 0);

// 3

glBindBuffer(GL_ARRAY_BUFFER, _indexBuffer);

glDrawElements(GL_TRIANGLE_STRIP, sizeof(Index)/sizeof(Index[0]), GL_UNSIGNED_SHORT, 0);

[_context presentRenderbuffer:GL_RENDERBUFFER];

}

Setting up VBOS:

- (void)setupVBOs {

glGenBuffers(1, &_bindPositionBuffer);

glBindBuffer(GL_ARRAY_BUFFER, _bindPositionBuffer);

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

glGenBuffers(1, &_bindNormalBuffer);

glBindBuffer(GL_ARRAY_BUFFER, _bindNormalBuffer);

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

glGenBuffers(1, &_indexBuffer);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Index), Index, GL_STATIC_DRAW);

}

Compiling Shaders:

- (void)compileShaders {

// 1

GLuint vertexShader = [self compileShader:@"SimpleVertex" withType:GL_VERTEX_SHADER];

GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];

// 2

GLuint programHandle = glCreateProgram();

glAttachShader(programHandle, vertexShader);

glAttachShader(programHandle, fragmentShader);

glLinkProgram(programHandle);

// 3

GLint linkSuccess;

glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);

if (linkSuccess == GL_FALSE) {

GLchar messages[256];

glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);

NSString *messageString = [NSString stringWithUTF8String:messages];

NSLog(@"%@", messageString);

exit(1);

}

// 4

glUseProgram(programHandle);

// 5

// Uniform Locations

_bonesUniform = glGetUniformLocation(programHandle, "Bones[0]");

_modelViewMatrixUniform = glGetUniformLocation(programHandle, "ModelViewMatrix");

_modelViewProjMatrixUniform = glGetUniformLocation(programHandle, "ModelViewProjMatrix");

_textureUniform = glGetUniformLocation(programHandle, "Texture");

// Attribute Locations

_VertexBoneWeightAttribute = glGetAttribLocation(programHandle, "VertexBoneWeight");

_VertexBoneIDAttribute = glGetAttribLocation(programHandle, "VertexBoneID");

_VertexTexCoord0Attribute = glGetAttribLocation(programHandle, "VertexTexCoord0");

_VertexNormalAttribute = glGetAttribLocation(programHandle, "VertexNormal");

_VertexPositionAttribute = glGetAttribLocation(programHandle, "VertexPosition");

// Enable vertex pointers

glEnableVertexAttribArray(_VertexBoneWeightAttribute);

glEnableVertexAttribArray(_VertexBoneIDAttribute);

glEnableVertexAttribArray(_VertexTexCoord0Attribute);

glEnableVertexAttribArray(_VertexNormalAttribute);

glEnableVertexAttribArray(_VertexPositionAttribute);

}

Here is a link to my shaders:

attribute vec3 VertexPosition;

attribute vec3 VertexNormal;

attribute vec2 VertexTexCoord0;

attribute vec4 VertexBoneID;

attribute vec4 VertexBoneWeight;

uniform mat4 ModelViewMatrix;

uniform mat4 ModelViewProjMatrix;

uniform vec4 Bones[222];

varying vec3 Normal;

varying vec2 TexCoord0;

void main(void)

{

TexCoord0 = VertexTexCoord0;

// Build 4x3 skinning matrix.

vec4 r0 = Bones[int(VertexBoneID.x) * 3 + 0] * VertexBoneWeight.x;

vec4 r1 = Bones[int(VertexBoneID.x) * 3 + 1] * VertexBoneWeight.x;

vec4 r2 = Bones[int(VertexBoneID.x) * 3 + 2] * VertexBoneWeight.x;

r0 += Bones[int(VertexBoneID.y) * 3 + 0] * VertexBoneWeight.y;

r1 += Bones[int(VertexBoneID.y) * 3 + 1] * VertexBoneWeight.y;

r2 += Bones[int(VertexBoneID.y) * 3 + 2] * VertexBoneWeight.y;

r0 += Bones[int(VertexBoneID.z) * 3 + 0] * VertexBoneWeight.z;

r1 += Bones[int(VertexBoneID.z) * 3 + 1] * VertexBoneWeight.z;

r2 += Bones[int(VertexBoneID.z) * 3 + 2] * VertexBoneWeight.z;

r0 += Bones[int(VertexBoneID.w) * 3 + 0] * VertexBoneWeight.w;

r1 += Bones[int(VertexBoneID.w) * 3 + 1] * VertexBoneWeight.w;

r2 += Bones[int(VertexBoneID.w) * 3 + 2] * VertexBoneWeight.w;

// Skin and transform position.

float px = dot(r0, vec4(VertexPosition, 1.0));

float py = dot(r1, vec4(VertexPosition, 1.0));

float pz = dot(r2, vec4(VertexPosition, 1.0));

gl_Position = ModelViewProjMatrix * vec4(px, py, pz, 1.0);

/* Skin and transform normal into view-space. We assume that the modelview matrix

doesn't contain a scale. Should pass pass in the inverse-transpose really. */

float nx = dot(r0, vec4(VertexNormal, 0.0));

float ny = dot(r1, vec4(VertexNormal, 0.0));

float nz = dot(r2, vec4(VertexNormal, 0.0));

Normal = normalize((ModelViewMatrix * vec4(nx, ny, nz, 0.0)).xyz);

}

Frag Shader:

#ifdef GL_ES

precision highp float;

#endif

uniform sampler2D Texture;

varying vec3 Normal;

varying vec2 TexCoord0;

void main(void)

{

// Ambient term.

vec3 lighting = vec3(0.5,0.5,0.5) * 0.7;

/* Very cheap lighting. Three directional lights, one shining slighting upwards to illuminate

underneath the chin, and then one each shining from the left and right. Light directional

are in view-space and follow the camera rotation by default. */

lighting += dot(Normal, normalize(vec3( 0.0, -0.2, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.6; // Shines forwards and slightly upwards.

lighting += dot(Normal, normalize(vec3(-0.8, 0.4, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.4; // Shines forwards and from left to right.

lighting += dot(Normal, normalize(vec3( 0.8, 0.4, 0.8))) * vec3(0.8, 0.8, 0.6) * 0.4; // Shines forwards and from right to left.

//gl_FragColor = vec4(Normal * 0.5 + vec3(0.5), 1.0);

gl_FragColor = vec4(texture2D(Texture, TexCoord0).xyz * lighting, 1.0);

}

Can anyone see anything in my render method which i have done wrong?

网友答案:

If you bind GLFloat values to your GL_ELEMENT_ARRAY_BUFFER, that could be a problem. You should bind GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT.
http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml

网友答案:

When binding the index buffer in your render method, you should use GL_ELEMENT_ARRAY_BUFFER instead of GL_ARRAY_BUFFER.

网友答案:

Your call to glDrawElements doesn't look to be correct. Nor does your call to glBufferData.

glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Index), Index, GL_STATIC_DRAW);

glDrawElements(GL_TRIANGLE_STRIP, sizeof(Index)/sizeof(Index[0]), GL_UNSIGNED_SHORT, 0);

It looks like you're passing a struct to glBufferData rather than an array of indices. Unless your parameter is called Index but it doesn't seem that way due to how you're using it. You need to build an array of vertex indices and pass this in to tell the GPU what you want to draw.

The second parameter to glDrawElement should be the number of elements you want to render. I had a similar problem in this question which someone helpfully pointed out I was making the same mistake. Hopefully it will be helpful to you too.

分享给朋友:
您可能感兴趣的文章:
随机阅读: