2013-03-09 108 views
0

我想呈現一些頂點到Open GL ES窗口。我的程序不斷在GLDrawElements命令上崩潰。我正在嘗試通過一些VBO爲GLFloat類型的頂點「bindPosition」,「bindNorml」和「Index」。GLDrawElements崩潰程序

這裏是我的渲染方法的鏈接:

- (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]; 
} 

設置維也納組織:

- (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); 

} 

編譯着色器:

- (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); 

} 

這裏是我的着色器的鏈接:

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); 
} 

破片着色器:

#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); 
} 

任何人都可以看到什麼在我的渲染方法,我有什麼錯呢?

+0

錯誤消息是:EXC_BAD_ACCESS(code = 2,address = 0x0) – samb90 2013-03-09 01:53:11

+0

也許你發佈的代碼是不完整的,但我似乎沒有看到你在哪裏調用glBufferData。就我看來,問題似乎是你實際上沒有將任何數據綁定到OpenGL。您必須調用glBufferData以將數據綁定到頂點屬性指針。 – aeskreis 2013-03-09 04:10:38

+0

你好,我已經包含了一些我的程序代碼 – samb90 2013-03-09 11:13:25

回答

0

在渲染方法中綁定索引緩衝區時,應該使用GL_ELEMENT_ARRAY_BUFFER而不是GL_ARRAY_BUFFER

+0

嘿,謝謝你的回覆。我做了你所建議的更改,但仍然遇到同樣的問題 – samb90 2013-03-09 17:12:47

+0

「glVertexAttribPointer」的第五個參數應該是一個頂點與下一個頂點之間的步長(以字節爲單位)。您也可以傳遞0來獲得緊密壓縮的屬性。我不確定你的'bindPosition'變量是什麼,但我想我會提到它。 – prideout 2013-03-10 00:06:47

0

您撥打glDrawElements看起來不正確。您撥打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); 

它看起來像你傳遞一個結構glBufferData而不是索引數組。除非你的參數被稱爲Index,但由於你的使用方式,它看起來並不如此。您需要構建一系列頂點索引並將其傳入以告訴GPU要繪製的內容。

glDrawElement的第二個參數應該是要渲染的元素的數量。我在this question有類似的問題,有人幫忙指出我犯了同樣的錯誤。希望這對你也有幫助。