教程
- OpenGLES入門教程1-Tutorial01-GLKit
- OpenGLES入門教程2-Tutorial02-shader入門
- OpenGLES入門教程3-Tutorial03-三維變換
- OpenGLES入門教程4-Tutorial04-GLKit進階
- OpenGLES進階教程1-Tutorial05-地球月亮
這一次的的內(nèi)容是光照。
概念準(zhǔn)備
所謂的光照,是GPU為每個三角形的頂點進行光線計算,再把結(jié)果進行插值,得出每個片元的最終顏色。
OpenGL ES的燈光模擬包括:環(huán)境光、漫反射光、鏡面反射光。
光線與幾何圖形相互作用的關(guān)鍵:計算出每個物體照射和發(fā)散出來多少光線。
光線計算依賴于表面法向量。法向量也是單位向量。
表面法向量可以通過平面內(nèi)兩個點的叉積(矢量積)來計算。
光線計算過程還包括材質(zhì)、聚光燈效果、衰減因子等,但是GLKit簡化了這一過程。
效果展示

光照
核心思路
如下圖,總共AI九個點,07八個面。E的z坐標(biāo)是可變的,隨著UISlider的數(shù)值由-1到0變化。
為了方便觀察,繞X軸和Z軸旋轉(zhuǎn)了一定角度。
燈光用GLKBaseEffect類。

頂點-平面圖
具體細(xì)節(jié)
- 頂點
總共有9個頂點,具體坐標(biāo)如下。前面為頂點坐標(biāo),后面為法線坐標(biāo)。
static const SceneVertex vertexA = {{-0.5, 0.5, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexB = {{-0.5, 0.0, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexC = {{-0.5, -0.5, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexD = {{ 0.0, 0.5, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexE = {{ 0.0, 0.0, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexF = {{ 0.0, -0.5, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexG = {{ 0.5, 0.5, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexH = {{ 0.5, 0.0, -0.5}, {0.0, 0.0, 1.0}};
static const SceneVertex vertexI = {{ 0.5, -0.5, -0.5}, {0.0, 0.0, 1.0}};
重新緩存頂點數(shù)組
- 平面
SceneVertex是頂點的數(shù)據(jù)結(jié)構(gòu)
SceneTriangle是平面(三角形)的數(shù)據(jù)結(jié)構(gòu)
//頂點
typedef struct {
GLKVector3 position; //
GLKVector3 normal;
}
SceneVertex;
//三角形
typedef struct {
SceneVertex vertices[3];
}
SceneTriangle;
- 光源
配置漫反射光的顏色,還有光源的位置
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.light0.enabled = GL_TRUE;
self.baseEffect.light0.diffuseColor = GLKVector4Make(
0.7f, // Red
0.7f, // Green
0.7f, // Blue
1.0f);// Alpha
self.baseEffect.light0.position = GLKVector4Make(
1.0f,
1.0f,
0.5f,
0.0f);
self.extraEffect = [[GLKBaseEffect alloc] init];
self.extraEffect.useConstantColor = GL_TRUE;
- 變換
先旋轉(zhuǎn),后平移
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeRotation(GLKMathDegreesToRadians(-60.0f), 1.0f, 0.0f, 0.0f);
modelViewMatrix = GLKMatrix4Rotate(
modelViewMatrix,
GLKMathDegreesToRadians(-30.0f), 0.0f, 0.0f, 1.0f);
modelViewMatrix = GLKMatrix4Translate(
modelViewMatrix,
0.0f, 0.0f, 0.25f);
self.baseEffect.transform.modelviewMatrix = modelViewMatrix;
self.extraEffect.transform.modelviewMatrix = modelViewMatrix;
- 法線繪制
先設(shè)置光源顏色為綠色,畫頂點法線
再設(shè)置光源顏色為黃色,畫光源線
self.extraEffect.useConstantColor = GL_TRUE;
self.extraEffect.constantColor =
GLKVector4Make(0.0, 1.0, 0.0, 1.0);
[self.extraEffect prepareToDraw];
[self.extraBuffer drawArrayWithMode:GL_LINES
startVertexIndex:0
numberOfVertices:NUM_NORMAL_LINE_VERTS];
self.extraEffect.constantColor =
GLKVector4Make(1.0, 1.0, 0.0, 1.0);
[self.extraEffect prepareToDraw];
[self.extraBuffer drawArrayWithMode:GL_LINES
startVertexIndex:NUM_NORMAL_LINE_VERTS
numberOfVertices:(NUM_LINE_VERTS - NUM_NORMAL_LINE_VERTS)];
關(guān)鍵函數(shù)
- 求法向量函數(shù)
GLKVector3 SceneTriangleFaceNormal(const SceneTriangle triangle);
- 通過叉積求單位法向量函數(shù)
GLKVector3 SceneVector3UnitNormal(
const GLKVector3 vectorA,
const GLKVector3 vectorB)
總結(jié)
進階教程不只是圖形學(xué)知識的進階,代碼的規(guī)范也很重要,能避免一部分錯誤。
光照原理的內(nèi)容可以參考這里,講解非常詳細(xì),但是本次使用的GLKit,所以簡化了許多。
附上源碼