iOS SDK开放了OpenGL绘制功能,开发者可利用OpenGL的绘制来实现更多复杂的覆盖物绘制。
BMKMapViewDelegate中的-mapView:onDrawMapFrame:,地图渲染每一帧画面过程中,以及每次需要重绘地图时(例如添加覆盖物)都会调用此接口。开发者可以在这个接口中进行opengl的绘制。
不需要用户自己创建context和buffer,V5.0.0新增OpenGL映射矩阵(getProjectionMatrix)和视图矩阵(getViewMatrix)接口,用于3D绘制场景,具体代码请参考BaiduMap_IOSSDK_Sample BMKOpenGLESPage。
下面代码以在地图上绘制3D立方体为例,介绍如何使用OpenGL绘制接口。
- (void)init3DShader{//顶点着色器NSString *vertexShader = @"precision highp float;attribute vec3 aVertex;attribute vec4 aColor;uniform mat4 aViewMatrix;uniform mat4 aProjectionMatrix;uniform mat4 aTransformMatrix;uniform mat4 aScaleMatrix;varying vec4 color;void main(){gl_Position = aProjectionMatrix * aViewMatrix * vec4(aVertex, 1.0);color = aColor;}";//片段着色器NSString *fragmentShader = @"precision highp float;varying vec4 color;void main(){gl_FragColor = color;}";// 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");}
- (void)init3DVertext{//创建vertexfloat 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];}}
-(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);}
/**地图渲染每一帧画面过程中,以及每次需要重新绘制地图时(例如添加覆盖物)都会调用此方法@param mapView 地图View@param status 地图的状态*/- (void)mapView:(BMKMapView *)mapView onDrawMapFrame:(BMKMapStatus *)status {[self drawFrameFor3DCube];}
效果如图:
上一篇
下一篇
本篇文章对您是否有帮助?