OpenGL採用右手座標系(伸出你的右手,拇指和食指垂直,中指分別和拇指,食指垂直,此時拇指表明x座標軸,食指表明y座標軸,中指表明z座標軸,這就是右手座標系)測試
OpenGL採用列向量,因此矩陣與向量運算爲矩陣左乘spa
OpenGL的glMutMatrixf等操做爲右乘指針
OpenGL採用列主序存儲矩陣code
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; self.context = context; [EAGLContext setCurrentContext:context]; glGenFramebuffersOES(1, &_framebuffer); // 建立幀緩衝區 glGenRenderbuffersOES(1, &_renderbuffer); // 建立繪製緩衝區 glBindFramebufferOES(GL_FRAMEBUFFER_OES, _framebuffer); // 綁定幀緩衝區到渲染管線 glBindRenderbufferOES(GL_RENDERBUFFER_OES, _renderbuffer); // 綁定繪製緩衝區到渲染管線 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _renderbuffer); // 綁定繪製緩衝區到幀緩衝區 GLint width; GLint height; [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer]; // 爲繪製緩衝區分配存儲區,此處將CAEAGLLayer的繪製存儲區做爲繪製緩衝區的存儲區 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &width); // 獲取繪製緩衝區的像素寬度 glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &height); // 獲取繪製緩衝區的像素高度 glGenRenderbuffersOES(1, &_depthbuffer); // 建立深度緩衝區 glBindRenderbufferOES(GL_RENDERBUFFER_OES, _depthbuffer); // 綁定深度緩衝區到渲染管線 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); // 爲深度緩衝區分配存儲區 glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, _depthbuffer); // 綁定深度緩衝區到幀緩衝區 glMatrixMode(GL_PROJECTION); // 改變矩陣變換模式到投影矩陣,之後的矩陣操做都會是對投影矩陣操做 GLfloat w = 0.5 * tanf(M_PI / 8); glFrustumf(-w, w, -w*height/width, w*height/width, 0.5, 3000); // 視錐定義 glViewport(0, 0, width, height); // 視口定義
- (void)getViewMatrix:(GLfloat *)matrix { GLfloat x = _orientation.x; GLfloat y = _orientation.y; GLfloat z = _orientation.z; GLfloat w = _orientation.w; GLfloat *rot = malloc(sizeof(GLfloat) * 16); rot[0] = 1-2*y*y-2*z*z; rot[1] = 2*x*y-2*w*z; rot[2] = 2*x*z+2*w*y; rot[3] = 0.0; rot[4] = 2*x*y+2*w*z; rot[5] = 1-2*x*2-2*z*z; rot[6] = 2*y*z-2*w*x; rot[7] = 0.0; rot[8] = 2*x*z-2*w*y; rot[9] = 2*y*z+2*w*z; rot[10] = 1-2*x*x-2*y*y; rot[11] = 0.0; rot[12] = 0; rot[13] = 0; rot[14] = 0; rot[15] = 1.0; GLfloat transX = -rot[0]*_position.x - rot[4]*_position.y - rot[8]*_position.z; GLfloat transY = -rot[1]*_position.x - rot[5]*_position.y - rot[9]*_position.z; GLfloat transZ = -rot[2]*_position.x - rot[6]*_position.y - rot[10]*_position.z; rot[12] = transX; rot[13] = transY; rot[14] = transZ; memcpy(matrix, rot, sizeof(GLfloat)*16); free(rot); }
- (void)getViewMatrix:(GLfloat *)matrix { GLfloat x = _orientation.x; GLfloat y = _orientation.y; GLfloat z = _orientation.z; GLfloat w = _orientation.w; GLfloat *rot = malloc(sizeof(GLfloat) * 16); rot[0] = 1-2*y*y-2*z*z; rot[1] = 2*x*y-2*w*z; rot[2] = 2*x*z+2*w*y; rot[3] = 0.0; rot[4] = 2*x*y+2*w*z; rot[5] = 1-2*x*2-2*z*z; rot[6] = 2*y*z-2*w*x; rot[7] = 0.0; rot[8] = 2*x*z-2*w*y; rot[9] = 2*y*z+2*w*z; rot[10] = 1-2*x*x-2*y*y; rot[11] = 0.0; rot[12] = 0; rot[13] = 0; rot[14] = 0; rot[15] = 1.0; GLfloat transX = -rot[0]*_position.x - rot[4]*_position.y - rot[8]*_position.z; GLfloat transY = -rot[1]*_position.x - rot[5]*_position.y - rot[9]*_position.z; GLfloat transZ = -rot[2]*_position.x - rot[6]*_position.y - rot[10]*_position.z; rot[12] = transX; rot[13] = transY; rot[14] = transZ; memcpy(matrix, rot, sizeof(GLfloat)*16); free(rot); }
- (void)render { glBindRenderbufferOES(GL_RENDERBUFFER_OES, _renderbuffer); // 綁定繪製緩衝區到渲染管線 //glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清空繪製緩衝區和深度緩衝區 glEnableClientState(GL_VERTEX_ARRAY); MZGLCamera *camera = self.camera; GLfloat *matrix = malloc(sizeof(GLfloat) * 16); [camera getViewMatrix:matrix]; glMatrixMode(GL_MODELVIEW_MATRIX); // 改變矩陣變換模式到模型矩陣 glLoadIdentity(); // 將模型矩陣更新爲單位矩陣 glEnable(GL_DEPTH_TEST); // 開始深度測試 glDepthFunc(GL_LESS); // 切換深度測試模式爲待繪製像素距離屏幕距離小於深度緩衝區當前值則繪製,不然不繪製 glLoadMatrixf(matrix); // 根據攝像機位置設置模型矩陣,此處的矩陣爲攝像機世界矩陣的逆矩陣 glVertexPointer(3, GL_FLOAT, 0, _lineVertexBuffer); glColor4f(1.0, 1.0, 0.0, 1.0); glDrawElements(GL_LINES, _lineVertexCount, GL_UNSIGNED_BYTE, _lineIndexBuffer); // 繪製世界座標系的座標軸 glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); // 開啓紋理繪製 glEnable(GL_ALPHA_TEST); // 開啓Alpha測試 glAlphaFunc(GL_GREATER, 0.5f); // 切換Alpha測試模式爲不透明度大於0.5則繪製,不然不繪製 glColor4f(1.0, 1.0, 1.0, 1.0); // 填充繪製緩衝區 NSArray *values = [self.entityDictionary allValues]; for (NSObject *entity in values) { if ([entity conformsToProtocol:@protocol(MZGLRenderable)]) { if ([entity isKindOfClass:[MZGLBillboard class]]) { MZGLBillboard *billboard = (MZGLBillboard *)entity; glVertexPointer(3, GL_FLOAT, 0, billboard.vertexBuffer); // 設置頂點緩衝指針 glTexCoordPointer(2, GL_FLOAT, 0, billboard.coordinates); // 設置紋理座標指針 [billboard preRender:self]; glLoadIdentity(); GLfloat *transform = [billboard worldTrasform]; // 設置模型世界矩陣 glLoadMatrixf(matrix); // 將模型矩陣設置爲攝像機世界矩陣的逆矩陣 glMultMatrixf(transform); // 右乘模型的世界矩陣 [billboard.texure bind]; // 綁定紋理 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // 繪製頂點 } } } [_context presentRenderbuffer:GL_RENDERBUFFER]; // 繪製到繪製緩衝區 }