glGetAttribLocation / glGetUniformLocation返回0,导致glDrawArrays调用(iOS)上的EXC_BAD_ACCESS

时间:2011-07-22 15:34:47

标签: ios opengl-es exc-bad-access

我正在为iOS创建一个简单的OpenGL ES 2.0应用程序,每当我调用glDrawArrays时。我发现这是在我之前为我的两个属性(位置和颜色)调用glEnableVertexAttribArray时发生的,然后发现glGetAttribLocation返回1表示位置,0表示颜色,然后还发现glGetUniformLocation为我的MVP返回0矩阵。我不确定0是否是有效值,或者为什么glEnableVertexAttribArray在调用glDrawArrays时似乎导致EXC_BAD_ACCESS。

这是我的代码:

compileShaders函数:

-(void)compileShaders {
GLuint vertShader = [self compileShader:@"Shader" ofType:GL_VERTEX_SHADER];
GLuint fragShader = [self compileShader:@"Shader" ofType:GL_FRAGMENT_SHADER];

GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);

GLint success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success == GL_FALSE) {
    GLchar messages[256];
    glGetProgramInfoLog(program, sizeof(messages), 0, &messages[0]);
    NSLog(@"%@", [NSString stringWithUTF8String:messages]);
    exit(1);
}

glUseProgram(program);

_positionSlot = glGetAttribLocation(program, "position");
_colorSlot = glGetAttribLocation(program, "color"); //Returns 0
_mvpSlot = glGetUniformLocation(program, "MVP"); //Returns 0

if (!_positionSlot || !_colorSlot || !_mvpSlot) {
    NSLog(@"Failed to retrieve the locations of the shader variables:\n Position:%i\n Color:%i\n MVP:%i", _positionSlot, _colorSlot, _mvpSlot); //Prints out the values of 1, 0, 0
}

glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);

我的渲染功能:

-(void)render:(CADisplayLink *)displayLink {
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);

GLfloat mvp[16] = {
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 1.0f,
};

glUniformMatrix4fv(_mvpSlot, 1, 0, mvp);

glViewport(0, 0, width, height);

glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(_colorSlot, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, colors);

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

[_context presentRenderbuffer:GL_RENDERBUFFER];
}

我的顶点着色器:

attribute vec4 position;
attribute vec4 color;

uniform mat4 MVP;

varying vec4 v_color;

void main(void) {
    gl_Position = MVP * position;
    v_color = color;
}

2 个答案:

答案 0 :(得分:6)

0是有效值,-1是“错误”或“未找到”值。统一位置和属性位置的空间是分开的,因此将位置0统一和位置0属性都很好。

您应该发布顶点和颜色数组以检查它们是否具有正确的大小,这可能会导致崩溃。

答案 1 :(得分:1)

我有同样的问题,没有解决方案,但是我试图进行广泛的调试,所以我想也许分享可能会有所帮助。

我将问题追溯到glCreateProgram()glCreateShader()来电。它们都返回零,这是错误返回。但是,在这两种情况下,glGetError()都会返回GL_NO_ERROR。事实上,在创建调用之后,编译和链接链中不会弹出任何错误。

我的症状与glGetAttribLocation相同,并且制服总是返回零(而不是-1表示错误!)。但我甚至可以提供破碎的着色器文件,它不会导致编译错误或任何日志信息。检查了正确的字符串以进行编译。

我对这种行为完全傻眼,因为明显glCreateProgram错误但没有设置错误。而且我不清楚它为什么会出错。特别令人困惑的是,整个GL函数调用链不会返回错误。当程序调用gl统一函数(例如glUniformMatrix4fv()glUniform1i())时,我收到第一个错误。但显然事情在此之前已经被破坏了,因为所有制服都返回0,即使它们不能都是零。

编辑:我在我的案例中找到了解决方案。设置帧缓冲区时,Opengles1似乎非常灵活。但是我需要在开始使用着色器之前强制进行帧缓冲设置以解决问题。例如如果一个跟随旧的eaglview模板,则在layoutSubviews中创建了framebuffers,但是对于initwithcoder中的着色器的典型初始化来说为时已晚。否则症状如上所述。