// shader.vsh
attribute vec4 position; // 頂點座標
attribute vec4 positionColor; // 頂點顏色
uniform mat4 projectionMatrix; // 投影矩陣
uniform mat4 modelViewMatrix; // 模型視圖矩陣
varying lowp vec4 varyColor; // 橋接的頂點顏色
void main()
{
varyColor = positionColor;
vec4 vPos;
vPos = projectionMatrix * modelViewMatrix * position;
gl_Position = vPos;
}
// shader.fsh
varying lowp vec4 varyColor;
void main()
{
gl_FragColor = varyColor;
}
複製代碼
這裏咱們只會把頂點顏色傳遞給片元着色器,系統則會自動將頂點之間的顏色
進行計算和渲染.數組
GLSL索引繪圖的案例,與EGL&OpenGL着色語言及案例中前五步驟如出一轍,不一樣的在於第六步中的
6.3 頂點、紋理數據
和6.4 開始繪製、顯示
,markdown
// 頂點座標、頂點顏色
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //左上0
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //右上1
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //左下2
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //右下3
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //頂點4
};
// 索引數組
GLuint indices[] =
{
0, 3, 2,
0, 1, 3,
0, 2, 4,
0, 4, 1,
2, 3, 4,
1, 4, 3,
};
GLuint vBuffer;
glGenBuffers(1, &vBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);
// 傳遞頂點數據
GLuint position = glGetAttribLocation(self.myProgram, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
// 傳遞頂點顏色
GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
glEnableVertexAttribArray(positionColor);
glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, (GLfloat *)NULL+3);
GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectionMatrix");
GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix");
// 投影矩陣
float width = self.frame.size.width;
float height = self.frame.size.height;
KSMatrix4 _projectionMatrix;
ksMatrixLoadIdentity(&_projectionMatrix);
float aspect = width / height;
ksPerspective(&_projectionMatrix, 30.0f, aspect, 5.0f, 20.0f);
// 傳遞投影矩陣數據
glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
// 模型視圖矩陣
KSMatrix4 _modelViewMatrix;
ksMatrixLoadIdentity(&_modelViewMatrix);
ksTranslate(&_modelViewMatrix, 0, 0, -10.0f);
KSMatrix4 _rotateMatrix;
ksMatrixLoadIdentity(&_rotateMatrix);
//XYZ
ksRotate(&_rotateMatrix, xDegree, 1.0, 0.0, 0.0);
ksRotate(&_rotateMatrix, yDegree, 0.0, 1.0, 0.0);
ksRotate(&_rotateMatrix, zDegree, 0.0, 0.0, 1.0);
// 矩陣相乘
ksMatrixMultiply(&_modelViewMatrix, &_rotateMatrix, &_modelViewMatrix);
// 傳遞模型矩陣數據
glUniformMatrix4fv(modelViewMatrixSlot, 1, GL_FALSE, (GLfloat*)&_modelViewMatrix.m[0][0]);
// 正背面剔除
glEnable(GL_CULL_FACE);
複製代碼
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);
複製代碼
由於GLKit已經幫咱們省略了不少工做,這裏只須要兩個步驟函數
// 初始化設置
- (void)setupContext{
self.mContext = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
GLKView *glkView = (GLKView *)self.view;
glkView.context = self.mContext;
// 設置顏色格式
glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
// 設置深度測試精度
glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[EAGLContext setCurrentContext:self.mContext];
glEnable(GL_DEPTH_TEST);
}
複製代碼
- (void)render{
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //左上
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, //右上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //左下
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, //右下
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //頂點
};
//2.繪圖索引
GLuint indices[] =
{
0, 3, 2,
0, 1, 3,
0, 2, 4,
0, 4, 1,
2, 3, 4,
1, 4, 3,
};
// 將頂點數據放入數組緩衝區
GLuint vBuffer;
glGenBuffers(1, &vBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, (float *)NULL+3);
// 將索引數組存儲到索引緩衝區
GLuint iBuffer;
glGenBuffers(1, &iBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 基礎着色器
self.mEffect = [[GLKBaseEffect alloc]init];
// 設置投影矩陣
CGSize size = self.view.bounds.size;
float aspect = fabs(size.width / size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 100.0f);
projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0, 1.0, 1.0);
self.mEffect.transform.projectionMatrix = projectionMatrix;
// 設置模型視圖矩陣
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
self.mEffect.transform.modelviewMatrix = modelViewMatrix;
// 索引數據個數
self.count = sizeof(indices)/sizeof(indices[0]);
// 定時器
double seconds = 0.1;
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC, 0.0);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(timer, ^{
weakSelf.xDegree += 0.1f * weakSelf.XB;
weakSelf.yDegree += 0.1f * weakSelf.YB;
weakSelf.zDegree += 0.1f * weakSelf.ZB;
});
dispatch_resume(timer);
// 設置顏色
glClearColor(0.3, 0.3, 0.3, 1.0);
}
複製代碼
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self.mEffect prepareToDraw];
glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
}
複製代碼
// GLSL
GLuint position = glGetAttribLocation(self.myProgram, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
// GLKit
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
複製代碼
GLKit封裝了着色器源碼,使用GLKVertexAttribPosition
通道用於頂點數據的傳輸,而在GLSL使用中,使用本身編寫的着色器源碼中的position
做爲頂點數據傳輸通道,因此首先須要glGetAttribLocation
進行獲取後將通道開啓進行傳輸。post
// GLSL
glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);
// 最後的參數傳遞索引數組
// GLKit
GLuint iBuffer;
glGenBuffers(1, &iBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
// 最後參數傳遞0
複製代碼
GLKit利用索引緩衝區保存索引數組進行渲染,GLSL是直接將索引數組經過傳遞給glDrawElements
函數來渲染。測試
// GLSL
glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat*)&_projectionMatrix.m[0][0]);
// GLKit
self.mEffect.transform.projectionMatrix = projectionMatrix;
複製代碼
GLSL頂點着色器源碼中uniform
修飾投影矩陣參數,因此使用glUniformMatrix4fv
來進行傳遞,uniform
修飾的參數不用開啓開關的操做。GLKit由於已通過封裝的緣故,能夠直接傳遞給基礎着色器。ui