iOS下OpenGL ES 3.0编程入门(二 ):画一个简单三角形

 上文我们讲解了如何构建一个hello world开发环境,那么这一篇我们就来画一个简单的三角形出来。

       首先,我要向大家介绍下opengl es的渲染流程,在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> 世界坐标变换 ->观察坐标变换->背面消除->光照->裁剪->投影->视口计算->光栅化,程序员只需要调用固定的api修改一些配置参数就可以完成整个渲染流程了。而到了2.0,固定管线改成了可编程管线,我们对整个渲染流程可以再编程,没有固定的api给你调用,一切都依靠shader来完成。那么什么是shader呢:

Shader分为Vertex Shader 顶点着色器和Pixel Shader 像素着色器两种。其中Vertex Shader主要负责顶点的几何关系等的运算,Pixel Shader主要负责片源颜色等的计算。
着色器替代了传统的固定渲染管线,可以实现3D图形学计算中的相关计算,由于其可编辑性,可以实现各种各样的图像效果而不用受显卡的固定渲染管线限制。这极大的提高了图像的画质。
好了,介绍完渲染流程,我们变进入正题,如何在上一篇的基础上完成一个简单三角形的渲染呢?
首先,我们要建立一个三角形的局部坐标系,也就是三角形每个点的顶点坐标。
[objc]  view plain  copy
  1. GLKVector3 vec[3]={  
  2.     {0.5,0.5,0.5},  
  3.     {-0.5,-0.5,0.5},  
  4.     {0.5,-0.5,-0.5}  
  5. };  
        然后,因为我们介绍的是opengl es3.0的编程,所以我们用的是可编程管线,那么我们就应该建立一个vertex shader文件和一个pixel shader文件,分别命名为shader.vsh和shader.fsh。
shader.vsh:
[objc]  view plain  copy
  1. attribute vec3 position;   //入参,主程序会将数值传入  
  2. void main()  
  3. {  
  4.     gl_Position = vec4(position,1);  //顶点经过投影变换变换后的位置  
  5. }  
       shader.fsh:
[objc]  view plain  copy
  1. void main()  
  2. {  
  3.     gl_FragColor = vec4(0.5,0.5,0.5,1);   //顶点的颜色  
  4. }  
       可以看到,每一个着色器文件都一个类似于c语言的main函数入口,这个就是着色器的入口,所有的代码都从这里开始执行。
编写完着色器后,我们便需要在主程序里加载shader了,加载shader的代码基本上不需要变动什么,直接copy过来就可以了。
[objc]  view plain  copy
  1. - (BOOL)loadShaders  
  2. {  
  3.     GLuint vertShader, fragShader;  
  4.     NSString *vertShaderPathname, *fragShaderPathname;  
  5.       
  6.     // Create shader program.  
  7.     program = glCreateProgram();  
  8.       
  9.     // Create and compile vertex shader.  
  10.     vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];  
  11.     if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {  
  12.         NSLog(@"Failed to compile vertex shader");  
  13.         return NO;  
  14.     }  
  15.       
  16.     // Create and compile fragment shader.  
  17.     fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];  
  18.     if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {  
  19.         NSLog(@"Failed to compile fragment shader");  
  20.         return NO;  
  21.     }  
  22.       
  23.     // Attach vertex shader to program.  
  24.     glAttachShader(program, vertShader);  
  25.       
  26.     // Attach fragment shader to program.  
  27.     glAttachShader(program, fragShader);  
  28.       
  29.     // Link program.  
  30.     if (![self linkProgram:program]) {  
  31.         NSLog(@"Failed to link program: %d", program);  
  32.           
  33.         if (vertShader) {  
  34.             glDeleteShader(vertShader);  
  35.             vertShader = 0;  
  36.         }  
  37.         if (fragShader) {  
  38.             glDeleteShader(fragShader);  
  39.             fragShader = 0;  
  40.         }  
  41.         if (program) {  
  42.             glDeleteProgram(program);  
  43.             program = 0;  
  44.         }  
  45.           
  46.         return NO;  
  47.     }  
  48.     // Release vertex and fragment shaders.  
  49.     if (vertShader) {  
  50.         glDetachShader(program, vertShader);  
  51.         glDeleteShader(vertShader);  
  52.     }  
  53.     if (fragShader) {  
  54.         glDetachShader(program, fragShader);  
  55.         glDeleteShader(fragShader);  
  56.     }  
  57.       
  58.     return YES;  
  59. }  
  60.   
  61. - (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file  
  62. {  
  63.     GLint status;  
  64.     const GLchar *source;  
  65.       
  66.     source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];  
  67.     if (!source) {  
  68.         NSLog(@"Failed to load vertex shader");  
  69.         return NO;  
  70.     }  
  71.       
  72.     *shader = glCreateShader(type);  
  73.     glShaderSource(*shader, 1, &source, NULL);  
  74.     glCompileShader(*shader);  
  75.       
  76. #if defined(DEBUG)  
  77.     GLint logLength;  
  78.     glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);  
  79.     if (logLength > 0) {  
  80.         GLchar *log = (GLchar *)malloc(logLength);  
  81.         glGetShaderInfoLog(*shader, logLength, &logLength, log);  
  82.         NSLog(@"Shader compile log:\n%s", log);  
  83.         free(log);  
  84.     }  
  85. #endif  
  86.       
  87.     glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);  
  88.     if (status == 0) {  
  89.         glDeleteShader(*shader);  
  90.         return NO;  
  91.     }  
  92.       
  93.     return YES;  
  94. }  
  95.   
  96. - (BOOL)linkProgram:(GLuint)prog  
  97. {  
  98.     GLint status;  
  99.     glLinkProgram(prog);  
  100.       
  101. #if defined(DEBUG)  
  102.     GLint logLength;  
  103.     glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);  
  104.     if (logLength > 0) {  
  105.         GLchar *log = (GLchar *)malloc(logLength);  
  106.         glGetProgramInfoLog(prog, logLength, &logLength, log);  
  107.         NSLog(@"Program link log:\n%s", log);  
  108.         free(log);  
  109.     }  
  110. #endif  
  111.       
  112.     glGetProgramiv(prog, GL_LINK_STATUS, &status);  
  113.     if (status == 0) {  
  114.         return NO;  
  115.     }  
  116.       
  117.     return YES;  
  118. }  
  119.   
  120. - (BOOL)validateProgram:(GLuint)prog  
  121. {  
  122.     GLint logLength, status;  
  123.       
  124.     glValidateProgram(prog);  
  125.     glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);  
  126.     if (logLength > 0) {  
  127.         GLchar *log = (GLchar *)malloc(logLength);  
  128.         glGetProgramInfoLog(prog, logLength, &logLength, log);  
  129.         NSLog(@"Program validate log:\n%s", log);  
  130.         free(log);  
  131.     }  
  132.       
  133.     glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);  
  134.     if (status == 0) {  
  135.         return NO;  
  136.     }  
  137.       
  138.     return YES;  
  139. }  
      然后再viewdidload里面添加如下代码:
[objc]  view plain  copy
  1. [self loadShaders];  
  2.     glEnable(GL_DEPTH_TEST);  
  3.     glClearColor(0.10.20.31);  
  4.     glGenVertexArrays(1, &vertexID);//生成一个vao对象  
  5.     glBindVertexArray(vertexID); //绑定vao  
  6.     GLuint bufferID;  
  7.     glGenBuffers(1, &bufferID);  //生成vbo  
[objc]  view plain  copy
  1. glBindBuffer(GL_ARRAY_BUFFER, bufferID);  //绑定  
  2.     glBufferData(GL_ARRAY_BUFFER, sizeof(vec), vec, GL_STATIC_DRAW); //填充缓冲对象  
  3.     GLuint loc=glGetAttribLocation(program, "position");   //获得shader里position变量的索引  
  4.     glEnableVertexAttribArray(loc);     //启用这个索引  
  5.     glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, sizeof(GLKVector3), 0);  //设置这个索引需要填充的内容  
  6.     glBindVertexArray(0);   //释放vao  
  7.     glBindBuffer(GL_ARRAY_BUFFER, 0);  //释放vbo  
       这里我们用到了es 3.0里面的新技术vao(vertex array object)以及2.0里面的vbo。关于vao和vbo,我们会专门展开一章来探讨,现在大家知道就行啦。
       接下来便到了渲染阶段,这里的代码需要写在 -( void )glkView:( GLKView  *)view drawInRect:( CGRect )rect方法里。
[objc]  view plain  copy
  1. -(void)glkView:(GLKView *)view drawInRect:(CGRect)rect  
  2. {  
  3.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   //清除颜色缓冲和深度缓冲  
  4.     glBindVertexArray(vertexID);      
  5.     glUseProgram(program);      //使用shader  
  6.     glDrawArrays(GL_TRIANGLES, 03);     //绘制三角形  
  7.     glBindVertexArray(0);  
  8.     glBindBuffer(GL_ARRAY_BUFFER, 0);  
  9.     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);  
  10. }  
      代码阶段便编写完成啦,保存运行,出现如下界面便大功告成啦。



你可能感兴趣的:(ios,OpenGL,ES,转载,ios,OpenGL,ES)