【问题标题】:GLDrawElements Crashing ProgramGLDrawElements 崩溃程序
【发布时间】:2013-07-04 16:31:43
【问题描述】:

我正在尝试将一些顶点渲染到 Open GL ES 窗口。我的程序在 GLDrawElements 命令上不断崩溃。我正在尝试为 GLFloat 类型的顶点“bindPosition”、“bindNorml”和“Index”传递一些 VBO。

这是我的渲染方法的链接:

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

设置 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);

}

编译着色器:

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

谁能看到我的渲染方法中我做错了什么?

【问题讨论】:

  • 错误信息是:EXC_BAD_ACCESS (code=2, address=0x0)
  • 也许您发布的代码不完整,但我似乎看不到您在哪里调用 glBufferData。在我看来,问题似乎在于您实际上并没有将任何数据绑定到 OpenGL。您必须调用 glBufferData 才能将数据绑定到顶点属性指针。
  • 你好,我已经从我的程序中添加了一些代码

标签: ios objective-c xcode opengl-es


【解决方案1】:

如果您将 GLFloat 值绑定到您的 GL_ELEMENT_ARRAY_BUFFER,这可能是个问题。您应该绑定 GL_UNSIGNED_BYTE 或 GL_UNSIGNED_SHORT。
http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml

【讨论】:

    【解决方案2】:

    在渲染方法中绑定索引缓冲区时,应使用GL_ELEMENT_ARRAY_BUFFER 而不是GL_ARRAY_BUFFER

    【讨论】:

    • 您好,感谢您的回复。我已经按照您的建议进行了更改,但仍然遇到同样的问题
    • glVertexAttribPointer 的第五个参数应该是一个顶点和下一个顶点之间的步幅,以字节为单位。您也可以为紧密包装的属性传递 0。我不确定你的 bindPosition 变量是什么,但我想我会提到它。
    【解决方案3】:

    您对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,以告诉 GPU 您要绘制什么。

    glDrawElement 的第二个参数应该是您要渲染的元素数量。我在this question 中遇到了类似的问题,有人很有帮助地指出我犯了同样的错误。希望对你也有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多