看過之前一系列的文章之后潦牛,我們對ES有了一個比較基礎(chǔ)的理解了泛领,下面我們通過繪制一個隨時間旋轉(zhuǎn)的立方體一喘,來匯總前幾篇文章的內(nèi)容酝豪,以加深對OpenGL ES渲染過程的理解涛碑。
示例代碼在git倉庫
正如讀者所知,一個正方體是由六個面組成的孵淘,那這里我們拆分需求蒲障,逐次繪制六個面,然后用時間作為輸入量瘫证,改變MVP矩陣揉阎,就能最終實現(xiàn)我們的效果。在后續(xù)的文章中背捌,我都是在VSCode里編寫著色器毙籽,安裝GLSL擴展后,可以高亮顯示毡庆,比較方便坑赡。
1.首先我們先來展示一下立方體的空間示意圖
繪制與X軸垂直的平面的代碼:
- (void)drawPositiveXWithColorLocation:(GLuint)colorLocation andPositionLocation:(GLuint)positionLocation {
//每一行代表(x,y,z,r,g,b)
static GLfloat positiveX[24] = {
0.5f, 0.5f, 0.5f, 1.0f, 0.6f, 0.3f,
0.5f, -0.5f, 0.5f, 1.0f, 0.6f, 0.3f,
0.5f, -0.5f, -0.5f, 1.0f, 0.6f, 0.3f,
0.5f, 0.5f, -0.5f, 1.0f, 0.6f, 0.3f,
};
if (self.vertexBufferId == 0) {
glGenBuffers(1, &_vertexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferId);
}
glBufferData(GL_ARRAY_BUFFER, sizeof(positiveX), positiveX, GL_STATIC_DRAW);
GLuint offset = 3 * sizeof(float);
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), NULL);
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (const void *) offset);
_esContext.drawFunc(&_esContext);
}
這里我們先找出與X軸垂直相交的這個面的四個頂點坐標,因為我們繪圖采用的是GL_TRIANGLE_FAN模式么抗,所以只需要四個頂點就可以了毅否。
其它5個面也是這樣繪制的
加載MVP矩陣的代碼如下:
[super glkView:view drawInRect:rect];
_elapsedTime += 0.02;
//時間系數(shù)
float varyFactor = (sin(self.elapsedTime) + 1.0) / 2.0; //0 ~ 1
_esContext.width = view.drawableWidth;
_esContext.height = view.drawableHeight;
//開啟深度測試,為了確定繪制的時候哪一個面繪制在上面
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//獲取屬性color和position的index
GLint colorIndex = glGetAttribLocation(_esContext.program, "vColor");
GLint positionIndex = glGetAttribLocation(_esContext.program, "vPosition");
//創(chuàng)建MVP矩陣
GLint modelIndex = glGetUniformLocation(_esContext.program, "modelTransform");
GLint viewIndex = glGetUniformLocation(_esContext.program, "viewTransform");
GLint projectIndex = glGetUniformLocation(_esContext.program, "projectTransform");
GLKMatrix4 rotate = GLKMatrix4MakeRotation(varyFactor * M_PI * 2, 1, 1, 1);
GLKMatrix4 translate = GLKMatrix4MakeTranslation(-0.1, -0.1, -0.1);
GLKMatrix4 modelMatrix = GLKMatrix4Multiply(translate, rotate);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90), view.frame.size.width / view.frame.size.height, 0.2, 10.0);
GLKMatrix4 cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2 * (varyFactor + 1), 0, 0, 0, 0, 1, 0);
//加載MVP矩陣
glUniformMatrix4fv(modelIndex, 1, GL_FALSE, modelMatrix.m);
glUniformMatrix4fv(viewIndex , 1, GL_FALSE, cameraMatrix.m);
glUniformMatrix4fv(projectIndex, 1, GL_FALSE, projectionMatrix.m);
//開啟頂點屬性
glEnableVertexAttribArray(colorIndex);
glEnableVertexAttribArray(positionIndex);
//加載頂點數(shù)據(jù)蝇刀,并且依次繪制立方體的六個面
[self drawPositiveXWithColorLocation:colorIndex andPositionLocation:positionIndex];
[self drawNegativeXWithColorLocation:colorIndex andPositionLocation:positionIndex];
[self drawPositiveYWithColorLocation:colorIndex andPositionLocation:positionIndex];
[self drawNegativeYWithColorLocation:colorIndex andPositionLocation:positionIndex];
[self drawPositiveZWithColorLocation:colorIndex andPositionLocation:positionIndex];
[self drawNegativeZWithColorLocation:colorIndex andPositionLocation:positionIndex];
//關(guān)閉頂點屬性
glDisableVertexAttribArray(colorIndex);
glDisableVertexAttribArray(positionIndex);
這里需要注意兩點
1.需要開啟深度測試螟加,如果沒有開啟深度測試的話,ES是不知道你繪制面的層次吞琐,會出現(xiàn)如下效果:
2.開啟深度測試后捆探,除了需要清除顏色緩沖區(qū)外,還需要清除深度緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
最終正確的效果如下圖: