浏览器版本低!无法浏览完整内容,建议升级或更换浏览器。
OpenGL绘制简介

iOS SDK开放了OpenGL绘制功能,开发者可利用OpenGL的绘制来实现更多复杂的覆盖物绘制。

BMKMapViewDelegate中的-mapView:onDrawMapFrame:,地图渲染每一帧画面过程中,以及每次需要重绘地图时(例如添加覆盖物)都会调用此接口。开发者可以在这个接口中进行opengl的绘制。

不需要用户自己创建context和buffer,V5.0.0新增OpenGL映射矩阵(getProjectionMatrix)和视图矩阵(getViewMatrix)接口,用于3D绘制场景,具体代码请参考BaiduMap_IOSSDK_Sample BMKOpenGLESPage。

下面代码以在地图上绘制3D立方体为例,介绍如何使用OpenGL绘制接口。

绘制3D立方体
1初始化着色器
- (void)init3DShader
{
    //顶点着色器
    NSString *vertexShader = @"precision highp float;\n\
    attribute vec3 aVertex;\n\
    attribute vec4 aColor;\n\
    uniform mat4 aViewMatrix;\n\
    uniform mat4 aProjectionMatrix;\n\
    uniform mat4 aTransformMatrix;\n\
    uniform mat4 aScaleMatrix;\n\
    varying vec4 color;\n\
    void main(){\n\
    gl_Position = aProjectionMatrix * aViewMatrix * vec4(aVertex, 1.0);\n\
    color = aColor;\n\
    }";
    //片段着色器
    NSString *fragmentShader = @"\n\
    precision highp float;\n\
    varying vec4 color;\n\
    void main(){\n\
    gl_FragColor = color;\n\
    }";
    // program对象是可以附加着色器对象的对象
    // 创建一个空program并返回一个可以被引用的非零值(program ID)
    _program3D = glCreateProgram();
    GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
    GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
    GLint vlength = (GLint)[vertexShader length];
    GLint flength = (GLint)[fragmentShader length];
    
    const GLchar *vByte = [vertexShader UTF8String];
    const GLchar *fByte = [fragmentShader UTF8String];
    
    glShaderSource(vShader, 1, &vByte, &vlength);
    glShaderSource(fShader, 1, &fByte, &flength);
    //成功编译着色器对象
    glCompileShader(vShader);
    glCompileShader(fShader);
    //成功地将着色器对象附加到program 对象
    glAttachShader(_program3D, vShader);
    glAttachShader(_program3D, fShader);
    //成功的链接program 对象之后
    glLinkProgram(_program3D);
    
    //查询由program指定的先前链接的程序对象
    _vertexLocation3D  = glGetAttribLocation(_program3D, "aVertex");
    //表示程序对象中特定统一变量的位置
    _viewMatrixLocation3D = glGetUniformLocation(_program3D,"aViewMatrix");
    //得到名字为“aProjectionMatrix”在shader中的位置
    _projectionMatrixLocation3D = glGetUniformLocation(_program3D,"aProjectionMatrix");
    _colorLocation3D = glGetAttribLocation(_program3D,"aColor");
    
}
2准备立方体数据并初始化
- (void)init3DVertext
{
    //创建vertex
    float vertext[] = {
        0.0, 0.0, 0.0,
        1.0, 0.0, 0.0,
        1.0, 1.0, 0.0,
        0.0, 1.0, 0.0,
        0.0, 0.0, 1.0,
        1.0, 0.0, 1.0,
        1.0, 1.0, 1.0,
        0.0, 1.0, 1.0,
    };
    
    for (int i = 0; i < 24; i++) {
         // 对标墨卡托坐标
        _vertext[i] = vertext[i] * 10000;
    }

    short indices[] = {
        0, 4, 5,
        0, 5, 1,
        1, 5, 6,
        1, 6, 2,
        2, 6, 7,
        2, 7, 3,
        3, 7, 4,
        3, 4, 0,
        4, 7, 6,
        4, 6, 5,
        3, 0, 1,
        3, 1, 2,
    };
    
    for (int i = 0; i < 36; i++) {
        _indecies[i] = indices[i];
    }
    
    float colors[] = {
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 0.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 1.0f,
    };
    
    for (int i = 0; i < 32; i++) {
        _color[i] = colors[i];
    }
}

3实现绘制方法
-(void)drawFrameFor3DCube {
    if (_program3D == 0) {
        [self init3DShader];
        [self init3DVertext];
    }
    
    GLboolean depthMask = 0;
    glGetBooleanv(GL_DEPTH_WRITEMASK,&depthMask);
    
    glUseProgram(_program3D);
    
    glEnable(GL_DEPTH_TEST);
    if (depthMask == GL_FALSE) {
        glDepthMask(GL_TRUE);
    }
    
    glEnableVertexAttribArray(_vertexLocation3D);
    glVertexAttribPointer(_vertexLocation3D, 3, GL_FLOAT, false, 0, _vertext);
    
    glEnableVertexAttribArray(_colorLocation3D);
    glVertexAttribPointer(_colorLocation3D, 4, GL_FLOAT, false, 0, _color);
    
    BMKMapPoint center = BMKMapPointForCoordinate(CLLocationCoordinate2DMake(39.965, 116.404));
    CGPoint offsetPoint = [self.mapView glPointForMapPoint:center];
    
    float *viewMatrix = [self.mapView getViewMatrix];
    translateM(viewMatrix, 0, offsetPoint.x, offsetPoint.y, 0);
    
    float *projectionMatrix = [self.mapView getProjectionMatrix];
    //传值函数,该函数的第一个参数是该变量在shader中的位置,第二个参数是被赋值的矩阵的数目。第三个参数表明在向uniform变量赋值时该矩阵是否需要转置
    //vec4类型的变量赋值,我们可以使用glUniform4f或者glUniform4fv。v代表数组
    glUniformMatrix4fv(_viewMatrixLocation3D, 1, false, viewMatrix);
    glUniformMatrix4fv(_projectionMatrixLocation3D, 1, false, projectionMatrix);
    
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, _indecies);
    
    glDisableVertexAttribArray(_vertexLocation3D);
    glDisableVertexAttribArray(_colorLocation3D);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(depthMask);
}

4在onDrawMapFrame调用drawFrameFor3DCube进行绘制
/**
 地图渲染每一帧画面过程中,以及每次需要重新绘制地图时(例如添加覆盖物)都会调用此方法
 
 @param mapView 地图View
 @param status 地图的状态
 */
- (void)mapView:(BMKMapView *)mapView onDrawMapFrame:(BMKMapStatus *)status {
        [self drawFrameFor3DCube];
}
5运行程序

效果如图:

newIos%2Fcustomoverlay3Dv5.png

  • 文档根本没法用

  • 文档水平很差

  • 文档水平一般

  • 文档不错

  • 文档写的很好

如发现文档错误,或对此文档有更好的建议,请在下方反馈。问题咨询请前往反馈平台提交工单咨询。

提交反馈

拖动标注工具

添加矩形标注

添加箭头标注

完成

取消