简体   繁体   English

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

[英]How do I draw thousands of squares with glkit, opengl es2?

I'm trying to draw up to 200,000 squares on the screen. 我正在尝试在屏幕上绘制20万个正方形。 Or a lot of squares basically. 或基本上是很多正方形。 I believe I'm just calling way to many draw calls, and it's crippling the performance of the app. 我相信我只是在打很多抽奖电话,这正在削弱应用程序的性能。 The squares only update when I press a button, so I don't necessarily have to update this every frame. 正方形仅在按下按钮时更新,因此不必一定每帧都更新一次。

Here's the code i have now: 这是我现在拥有的代码:

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

First, do you really need to draw 200,000 squares? 首先,您真的需要绘制20万个正方形吗? Your viewport only has 786,000 pixels total. 您的视口总共只有786,000像素。 You might be able to reduce the number of drawn objects without significantly impacting the overall quality of your scene. 您可能能够减少绘制对象的数量,而不会显着影响场景的整体质量。

That said, if these are smaller squares, you could draw them as points with a pixel size large enough to cover your square's area. 也就是说,如果这些是较小的正方形,则可以将其绘制为像素大小足以覆盖正方形区域的点。 That would require setting gl_PointSize in your vertex shader to the appropriate pixel width. 这将需要在顶点着色器中将gl_PointSize设置为适当的像素宽度。 You could then generate your coordinates and send them all to be drawn at once as GL_POINTS. 然后,您可以生成坐标并将其全部发送为GL_POINTS,以一次进行绘制。 That should remove the overhead of the extra geometry of the triangles and the individual draw calls you are using here. 这将消除三角形额外几何图形的开销以及您在此处使用的各个绘图调用。

Even if you don't use points, it's still a good idea to calculate all of the triangle geometry you need first, then send all that in a single draw call. 即使您不使用点,仍然要先计算所需的所有三角形几何体,然后在一次绘制调用中将所有几何体发送出去,这仍然是一个好主意。 This will significantly reduce your OpenGL ES API call overhead. 这将大大减少您的OpenGL ES API调用开销。

One other thing you could look into would be to use vertex buffer objects to store this geometry. 您可能要考虑的另一件事是使用顶点缓冲区对象来存储此几何。 If the geometry is static, you can avoid sending it on each drawn frame, or only update a part of it that has changed. 如果几何是静态的,则可以避免在每个绘制的框架上发送它,或者仅更新已更改的部分。 Even if you just change out the data each frame, I believe using a VBO for dynamic geometry has performance advantages on the modern iOS devices. 即使您只是每帧更改一次数据,我相信使用VBO进行动态几何处理在现代iOS设备上也具有性能优势。

Can you not try to optimize it somehow? 您不能尝试以某种方式对其进行优化吗? I'm not terribly familiar with graphics type stuff, but I'd imagine that if you are drawing 200,000 squares chances that all of them are actually visible seems to be unlikely. 我对图形类型的东西并不十分熟悉,但是我想如果您要绘制200,000个正方形,那么所有这些形状实际上都可见的可能性似乎很小。 Could you not add some sort of isVisible tag for your mySquare class that determines whether or not the square you want to draw is actually visible? 您是否可以为mySquare类添加某种isVisible标签,该标签确定您要绘制的正方形是否实际可见? Then the obvious next step is to modify your draw function so that if the square isn't visible, you don't draw it. 然后,显而易见的下一步是修改绘图功能,以便在看不见正方形的情况下不要绘制它。

Or are you asking for someone to try to improve the current code you have, because if your performance is as bad as you say, I don't think making small changes to the above code will solve your problem. 还是您正在要求某人尝试改进当前的代码,因为如果您的性能与您所说的一样糟糕,那么我认为对上述代码进行少量更改不会解决您的问题。 You'll have to rethink how you're doing your drawing. 您将不得不重新考虑自己的绘图方式。

It looks like what your code is actually trying to do is take a _model.rows × _model.columns 2D image and draw it upscaled by _model.pixelSize . 看起来您的代码实际想要执行的操作是拍摄_model.rows × _model.columns 2D图像并将其按_model.pixelSize放大_model.pixelSize If -[ColorModel getColorAtRow:andColumn:] is retrieving 3 bytes at a time from an array of color values, then you may want to consider uploading that array of color values into an OpenGL texture as GL_RGB / GL_UNSIGNED_BYTE data and letting the GPU scale up all of your pixels at once. 如果-[ColorModel getColorAtRow:andColumn:]一次从一个颜色值数组中检索3个字节,那么您可能要考虑将该颜色值数组作为GL_RGB / GL_UNSIGNED_BYTE数据GL_RGB OpenGL纹理中,并让GPU放大一次显示所有像素。

Alternatively, if scaling up the contents of your ColorModel is the only reason that you're using OpenGL ES and GLKit, you might be better off wrapping your color values into a CGImage and allowing UIKit and Core Animation do the drawing for you. 另外,如果按比例放大ColorModel的内容是使用OpenGL ES和GLKit的唯一原因,则最好将颜色值包装到CGImage中,并允许UIKit和Core Animation为您绘制图形。 How often do the color values in the ColorModel get updated? ColorModel的颜色值多久更新一次?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM