對(duì)最近一段時(shí)間學(xué)習(xí)OpenGL ES一個(gè)階段性的成果展示,對(duì)OpenGL ES從茫茫然,漫無(wú)目的的看資料到找到頭緒,也算經(jīng)歷了一段時(shí)間了,學(xué)習(xí)GL的API ,學(xué)習(xí)SL語(yǔ)言,看懂別人的Demo,知道GL的編程思想,到自己寫(xiě)出一些簡(jiǎn)單的效果.由于之前沒(méi)有接觸過(guò)這種底層圖形技術(shù),又重新復(fù)習(xí)了線(xiàn)性代數(shù),方便理解矩陣的變換.
這里不做基礎(chǔ)知識(shí)的講解,有很多大神的博客對(duì)此有精煉的講解,落影l(fā)oyinglin,OpenGL ES 2.0 筆記,在此分享的是沒(méi)有使用GLKit框架的情況下,繪制地球和月球的一次實(shí)踐.
Erath&Moon.PNG
GitHub(https://github.com/FengLeNever/FL-LearnOpenGL-ES---master)
1,啟用GL的流程
- (void)setupOpenGL
{
//設(shè)置FBO
[self setupFrameBuffer];
//編譯Shader并Link program
[self setupShader];
//讀取 Uniform
_samplerTexture = glGetUniformLocation(self.program, "samplerTexture");
_modleViewMatrix = glGetUniformLocation(self.program, "modelViewMatrix");
_projectionMatrix = glGetUniformLocation(self.program, "projectionMatrix");
//加載兩個(gè)紋理
_earthTexture = [self loadTextureWithImageName:@"Earth512x256.jpg"];
_moonTexture = [self loadTextureWithImageName:@"Moon.jpg"];
// 創(chuàng)建VBO,頂點(diǎn)buffer
glGenBuffers(1, &_ballVBO);
glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(sphereVerts), sphereVerts, GL_STATIC_DRAW);
// 紋理 buffer
glGenBuffers(1, &_ballTextcoord);
glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
glBufferData(GL_ARRAY_BUFFER, sizeof(sphereTexCoords), sphereTexCoords, GL_STATIC_DRAW);
}
2,綁定Framebuffer
- (void)setupFrameBuffer
{
//設(shè)置FBO,并給FBO綁定了colorRenderBuffer , depthRenderBuffer,如果不添加depthRenderBuffer深度緩沖區(qū),因?yàn)楫?huà)的是立體的東東 , 視圖顯示錯(cuò)誤
glGenRenderbuffers(1, &_colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
// 為 color renderbuffer 分配存儲(chǔ)空間
[self.mContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.mLayer];
// 拿到寬和高
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_height);
// depth renderbuffer 深度緩沖區(qū)
glGenRenderbuffers(1, &_depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);
// Framebuffers 幀緩沖區(qū)
glGenFramebuffers(1, &_frameBufferHandle);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle);
// Framebuffers bind color renderbuffer and depth renderbuffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, _colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, _depthRenderBuffer);
// 切換到color renderbuffer
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
// Check FBO satus
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"Error: Frame buffer is not completed.");
exit(1);
}
3,渲染Render
- (void)render
{
//計(jì)算轉(zhuǎn)動(dòng)角度
self.earthRotationAngleDegrees += 360.f / 60.f;
self.moonRotationAngleDegrees += 360.f / 60.f / SceneDaysPerMoonOrbit;
glEnable(GL_DEPTH_TEST);
glClearColor(0.2, 0.3,0.4, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
CGFloat scale = [UIScreen mainScreen].scale;
CGFloat x = self.frame.origin.x;
CGFloat y = self.frame.origin.y;
CGFloat w = self.frame.size.width;
CGFloat h = self.frame.size.height;
glViewport(x * scale, y * scale, w * scale, h * scale);
glUseProgram(self.program);
// ----------------------------- 繪制地球 -----------------------------//
glBindTexture(GL_TEXTURE_2D, _earthTexture);
glUniform1i(_samplerTexture, 0);
glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3 , 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE,sizeof(float) * 2, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
KSMatrix4 projectionMatrix;
ksMatrixLoadIdentity(&projectionMatrix);
//正交投影
// ksOrtho(&projectionMatrix, -1.f * w / h, 1.f * w / h, -1.f, 1.f, 1.f, 10.f);
//透視投影
ksPerspective(&projectionMatrix, 60.f, w / h, 1.f, 10.f);
glUniformMatrix4fv(_projectionMatrix, 1, GL_FALSE, &projectionMatrix.m[0][0]);
KSMatrix4 earthMatrix = [self earthMartix];
glUniformMatrix4fv(_modleViewMatrix, 1, GL_FALSE, &earthMatrix.m[0][0]);
glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
// ----------------------------- 繪制月球 -----------------------------//
glBindBuffer(GL_ARRAY_BUFFER, _ballVBO);
glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3 , 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, _ballTextcoord);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE,sizeof(float) * 2, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, _moonTexture);
KSMatrix4 moonMatrix = [self moonMartix];
glUniformMatrix4fv(_modleViewMatrix, 1, GL_FALSE, &moonMatrix.m[0][0]);
glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
[self.mContext presentRenderbuffer:GL_RENDERBUFFER];
}
4,矩陣Matrix
- (KSMatrix4)earthMartix
{
KSMatrix4 modelViewMatrix = [self getBaseModelViewMatrix];
//傾斜
KSMatrix4 rotateMatrix;
ksMatrixLoadIdentity(&rotateMatrix);
ksRotate(&rotateMatrix, -SceneEarthAxialTiltDeg, 1.f, 0.f, 0.f);
ksMatrixMultiply(&modelViewMatrix, &rotateMatrix, &modelViewMatrix);
// 自轉(zhuǎn)
KSMatrix4 rotateMatrix2;
ksMatrixLoadIdentity(&rotateMatrix2);
ksRotate(&rotateMatrix2, self.earthRotationAngleDegrees, 0.f, 1.f, 0.f);
ksMatrixMultiply(&modelViewMatrix, &rotateMatrix2, &modelViewMatrix);
return modelViewMatrix;
}
- (KSMatrix4)moonMartix
{
KSMatrix4 modelViewMatrix = [self getBaseModelViewMatrix];
// 設(shè)置公轉(zhuǎn)
KSMatrix4 rotateMarix1;
ksMatrixLoadIdentity(&rotateMarix1);
ksRotate(&rotateMarix1, self.moonRotationAngleDegrees, 0.0, 1.0, 0.0);
ksMatrixMultiply(&modelViewMatrix, &rotateMarix1, &modelViewMatrix);
// 平移
KSMatrix4 totateMatrix2;
ksMatrixLoadIdentity(&totateMatrix2);
ksTranslate(&totateMatrix2, 0.0, 0.0, SceneMoonDistanceFromEarth);
ksMatrixMultiply(&modelViewMatrix, &totateMatrix2, &modelViewMatrix);
// 縮放
KSMatrix4 scaleMatrix;
ksMatrixLoadIdentity(&scaleMatrix);
ksScale(&scaleMatrix, SceneMoonRadiusFractionOfEarth, SceneMoonRadiusFractionOfEarth, SceneMoonRadiusFractionOfEarth);
ksMatrixMultiply(&modelViewMatrix, &scaleMatrix, &modelViewMatrix);
// 自轉(zhuǎn)
KSMatrix4 rotateMatrix;
ksMatrixLoadIdentity(&rotateMatrix);
ksRotate(&rotateMatrix, self.moonRotationAngleDegrees, 0.f, 1.f, 0.f);
ksMatrixMultiply(&modelViewMatrix, &rotateMatrix, &modelViewMatrix);
return modelViewMatrix;
}
- (KSMatrix4)getBaseModelViewMatrix
{
KSMatrix4 modelViewMatrix;
ksMatrixLoadIdentity(&modelViewMatrix);
ksTranslate(&modelViewMatrix, 0.0, 0.0, -4.0);
return modelViewMatrix;
}
總結(jié)
在這種學(xué)習(xí)新知識(shí)過(guò)程中,探索是痛苦的,收獲是喜人的.愿與諸君共勉.