glDrawArrays上的OpenGL ES EXC_BAD_ACCESS

时间:2011-05-27 09:40:57

标签: iphone opengl-es render exc-bad-access

我正在使用OpenGL ES 1.1渲染我正在构建的iPhone游戏。

简而言之,我渲染了3个项目:

  1. 背景(工作正常)
  2. 许多球形物体(工作正常)
  3. 一个改变大小的简单线圈(我在这里遇到问题)。
  4. 基本上,当我在圆圈上调用drawArrays时,我收到一个EXC_BAD_ACCESS错误。我已经测试了基本的iPhone OpenGL模板中的代码,它工作正常,所以我无法真正跟踪它为什么不在这里工作。有人能以正确的方式指出我吗?

    以下是用于渲染圆圈的drawCircle代码。

    - (void) drawCircles
    {
    if (!m_circleEffects.empty())
    {
        int segments = 24;
        for (int i = 0; i < m_circleEffects.size(); i++)
        {
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glTranslatef(m_circleEffects[i].position.x, m_circleEffects[i].position.y, 0);
    
            float radius;
            if(m_circleEffects[i].isPulseOutward)
                radius = cos(m_circleEffects[i].frameCounter * M_PI / 720);
            else
                radius = sin(m_circleEffects[i].frameCounter * M_PI / 720);
    
            GLfloat circlePoints[segments * 3];                    
            int count = 0;
    
            for (GLfloat i = 0; i < 360.0f; i += (360.0f / segments))
            {
                circlePoints[count++] = (cos(i * M_PI / 180) * radius);
                circlePoints[count++] = (sin(i * M_PI / 180) * radius);
                circlePoints[count++] = z + 1;
            }
    
            glEnableClientState(GL_VERTEX_ARRAY);  
            glVertexPointer(3, GL_FLOAT, 0, circlePoints);                       
            glDrawArrays(GL_LINE_LOOP, 0, segments);   
            glDisableClientState(GL_VERTEX_ARRAY);
        }      
        m_circleEffects.clear();
    }
    }
    

    以下是我的其他渲染代码。它在运行循环中的上述代码之前调用。以下所有内容似乎都可以正常工作。

    - (void)passInVisualsToUse:(vector<Visual>)visuals
    {
    frameCounter += 0.2;
    if (frameCounter >= 360)
        frameCounter -= 360;
    
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    
    glDepthMask(GL_FALSE);
    
    glBindTexture(GL_TEXTURE_2D, m_backgroundTexture);
    
    glDrawTexfOES(0, 0, 0, 480, 320);
    glDepthMask(GL_TRUE);
    
    vector<Visual>::const_iterator visual = visuals.begin();
    for (int visualIndex = 0;
         visual != visuals.end();
         ++visual, ++visualIndex)
    {        
    
        if (visual->ObjectType == 1)
            glBindTexture(GL_TEXTURE_2D, m_oneTexture);
        else if (visual->ObjectType == 2)
            glBindTexture(GL_TEXTURE_2D, m_twoTexture);
        else if (visual->ObjectType == 3)
            glBindTexture(GL_TEXTURE_2D, m_threeTexture);
        else
            glBindTexture(GL_TEXTURE_2D, m_fourTexture);
    
        // Set the viewport transform.
        vec3 position = visual->Position;
    
        // Set the light position.
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    
        glTranslatef(position.x, position.y, position.z);
        float rotationAngle = visual->RotationAngle;
        glRotatef(rotationAngle, 0, 1, 0);
    
        float scale = visual->Scale;   
    
        if (visual->ShouldThrob)
        {
            float scaleFactor = scale + sin(frameCounter) / 25;
            glScalef(scaleFactor, scaleFactor, scale);
    
            BOOL isPulseOutward;
            if (visual->isPulseOutward)
                isPulseOutward = YES;
            else
                isPulseOutward = NO;
    
            CircleEffect toAdd;
            toAdd.position = position;
            toAdd.frameCounter = frameCounter;
            toAdd.isPulseOutward = isPulseOutward;
            m_circleEffects.push_back(toAdd);
        }
        else
            glScalef(scale, scale, scale);
    
        // Set the projection transform.
        float h = (float)screenSize.size.height / (float)screenSize.size.width;
    
        mat4 projection = mat4::Ortho(xleft, xright, h * xleft, h * xright, znear, zfar);
    
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixf(projection.Pointer());
    
        // Draw the surface.
        int stride = sizeof(vec3) + sizeof(vec3) + sizeof(vec2);
        const GLvoid* texCoordOffset = (const GLvoid*) (2 * sizeof(vec3));
        const Drawable& drawable = m_drawables[visualIndex];
        glBindBuffer(GL_ARRAY_BUFFER, drawable.VertexBuffer);
        glVertexPointer(3, GL_FLOAT, stride, 0);
        const GLvoid* normalOffset = (const GLvoid*) sizeof(vec3);
        glNormalPointer(GL_FLOAT, stride, normalOffset);
        glTexCoordPointer(2, GL_FLOAT, stride, texCoordOffset);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, drawable.IndexBuffer);
        glDrawElements(GL_TRIANGLES, drawable.IndexCount, GL_UNSIGNED_SHORT, 0);
    }
    
    
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    }
    

    相关缓冲区已在其他地方设置,如上所述,第二个代码都可以正常工作。

    基本上,我在顶部代码片段中的drawArrays代码上获得了EXC_BAD_ACCESS。任何人都有任何想法?

    由于

3 个答案:

答案 0 :(得分:10)

我的猜测是GL状态还有一个不应该绑定的数组。

如果它自己工作,那么该方法可能没问题。但是之前的方法可能没有将状态返回到应该是什么状态。

答案 1 :(得分:2)

当尝试从图形库或引擎内部进行低级OpenGL调用时,也会发生这种崩溃,例如: Cocos2D中。例如,Cocos2D设置了一些启用的GL状态:GL_TEXTURE_COORD_ARRAY,GL_VERTEX_ARRAY,GL_COLOR_ARRAY。 在此示例中,如果您的代码不使用纹理,除非您禁用GL_TEXTURE_COORD_ARRAY,否则它将崩溃。

感谢v01d提示!

答案 2 :(得分:0)

正如v01d所说,你忘了解除先前状态的缓冲区,使用后面的代码清除它。

glBindBuffer(GL_ARRAY_BUFFER, 0)