如何使用glkit,opengl es2绘制数千个方块?

时间:2012-07-12 15:08:33

标签: ios opengl-es opengl-es-2.0 glkit

我正在尝试在屏幕上绘制多达200,000个方格。或者基本上是很多方格。我相信我只是打电话给很多画电话,这会削弱应用程序的性能。只有按下按钮时,方块才会更新,所以我不一定要每帧更新一次。

这是我现在的代码:

- (void)glkViewControllerUpdate:(GLKViewController *)controller
{

//static float transY = 0.0f;
//float y = sinf(transY)/2.0f;
//transY += 0.175f;

GLKMatrix4 modelview = GLKMatrix4MakeTranslation(0, 0, -5.f);
effect.transform.modelviewMatrix = modelview;

//GLfloat ratio = self.view.bounds.size.width/self.view.bounds.size.height;
GLKMatrix4 projection = GLKMatrix4MakeOrtho(0, 768, 1024, 0, 0.1f, 20.0f);    
effect.transform.projectionMatrix = projection;
_isOpenGLViewReady = YES;
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
if(_model.updateView && _isOpenGLViewReady)
{

    glClear(GL_COLOR_BUFFER_BIT);
    [effect prepareToDraw];
    int pixelSize = _model.pixelSize;
    if(!_model.isReady)
        return;
    //NSLog(@"UPDATING: %d, %d", _model.rows, _model.columns);
    for(int i = 0; i < _model.rows; i++)
    {
        for(int ii = 0; ii < _model.columns; ii++)
        {
            ColorModel *color = [_model getColorAtRow:i andColumn:ii];
            CGRect rect = CGRectMake(ii * pixelSize, i*pixelSize, pixelSize, pixelSize);
            //[self drawRectWithRect:rect withColor:c];
            GLubyte squareColors[] = {
                color.red, color.green, color.blue, 255,
                color.red, color.green, color.blue, 255,
                color.red, color.green, color.blue, 255,
                color.red, color.green, color.blue, 255
            };

            // NSLog(@"Drawing color with red: %d", color.red);


            int xVal = rect.origin.x;
            int yVal = rect.origin.y;
            int width = rect.size.width;
            int height = rect.size.height;
            GLfloat squareVertices[] = {
                xVal, yVal, 1,
                xVal + width, yVal, 1,
                xVal,  yVal + height, 1,
                xVal + width,  yVal + height, 1
            };    

            glEnableVertexAttribArray(GLKVertexAttribPosition);
            glEnableVertexAttribArray(GLKVertexAttribColor);

            glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, squareVertices);
            glVertexAttribPointer(GLKVertexAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, squareColors);

            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

            glDisableVertexAttribArray(GLKVertexAttribPosition);
            glDisableVertexAttribArray(GLKVertexAttribColor);


        }
    }   
    _model.updateView = YES;
}

3 个答案:

答案 0 :(得分:1)

首先,你真的需要画出200,000个方格吗?您的视口总共只有786,000像素。您可以减少绘制对象的数量,而不会显着影响场景的整体质量。

也就是说,如果这些是较小的正方形,您可以将它们绘制为像素大小足以覆盖正方形区域的点。这需要在顶点着色器中将gl_PointSize设置为适当的像素宽度。然后,您可以生成坐标并将它们全部发送到GL_POINTS。这应该可以消除三角形的额外几何体的开销以及您在此处使用的各个绘制调用。

即使您不使用点,最好先计算所需的所有三角形几何,然后在一次绘制调用中发送所有这些。这将显着降低您的OpenGL ES API调用开销。

您可以研究的另一件事是使用顶点缓冲区对象来存储此几何体。如果几何图形是静态的,则可以避免在每个绘制的框架上发送它,或者仅更新已更改的几何图形。即使您只是更改每帧的数据,我相信使用VBO进行动态几何在现代iOS设备上具有性能优势。

答案 1 :(得分:0)

你能不能尝试以某种方式优化它?我对图形类型的东西并不十分熟悉,但我想如果你正在绘制200,000个方格的机会,那么它们实际上都是可见的似乎不太可能。你能否为mySquare类添加某种isVisible标签,以确定你想要绘制的方块是否实际可见?然后明显的下一步是修改你的绘图功能,这样如果方形不可见,你就不会绘制它。

或者您是否要求某人尝试改进您当前的代码,因为如果您的表现与您说的一样糟糕,我认为对上述代码进行少量更改将无法解决您的问题。你必须重新考虑你的绘画方式。

答案 2 :(得分:0)

看起来您的代码实际上要执行的操作是获取_model.rows×_model.columns 2D图像并将其绘制为_model.pixelSize。如果-[ColorModel getColorAtRow:andColumn:]一次从颜色值数组中检索3个字节,那么您可能需要考虑将该数组颜色值作为GL_RGB / GL_UNSIGNED_BYTE数据上传到OpenGL纹理中,让GPU一次扩大所有像素。

或者,如果放大ColorModel的内容是您使用OpenGL ES和GLKit的唯一原因,那么最好将颜色值包装到CGImage中并允许UIKit和Core Animation执行为你绘图。 ColorModel中的颜色值多久更新一次?