索引繪圖案例:GLSL&GLKit

GLSL

着色器源碼

// 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

由於GLKit已經幫咱們省略了不少工做,這裏只須要兩個步驟函數

  • 初始化上下文、GLKview等準備工做
  • 渲染

初始化

// 初始化設置
- (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);
    
}

複製代碼

GLKit代理方法

- (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);
}
複製代碼

以上兩個案例的不一樣

  • attrib屬性數據傳輸
// 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

相關文章
相關標籤/搜索