We've explained how to build a Hello World development environment, so we'll draw a simple triangle out of this one.
First of all, I would like to introduce the OpenGL ES rendering process, before 2.0, ES rendering using fixed pipeline, what is fixed pipeline, is a set of fixed template flow, Local coordinate transformation, world coordinate transformation, observation coordinate transformation-- > Lighting -----projection-------rasterization, a programmer just needs to call a fixed API to modify some configuration parameters to complete the entire rendering process. By the 2.0, the fixed pipeline changed to a programmable pipeline, we can re-program the entire rendering process, there is no fixed API for you to call, everything depends on shader to complete. So what is shader:
shader is divided into vertex shader vertex shader and pixel shader pixel shader. Vertex shader is mainly responsible for the geometric relations of vertices, Pixel shader mainly responsible for the calculation of the color of the film source. The shader replaces the traditional fixed rendering pipeline, can realize the calculation of 3D graphics computing, because of its editable, can achieve a variety of image effects without being limited by the fixed rendering pipeline of the video card. This greatly improves the image quality. Well, after introducing the rendering process, we get to the point, how to complete a simple triangle rendering on the basis of the previous article? First, we will create a local coordinate system of the triangle, which is the vertex coordinate of each point of the triangle.
GLKVector3 vec[3]={ {0.5,0.5,0.5}, { -0.5,-0.5,0.5}, {0.5,-0.5,-0.5}};
then, because we're introducing OpenGL es3.0 programming, so we're using a programmable pipeline, then we should build a vertex shader file and a pixel shader file, Named Shader.vsh and Shader.fsh, respectively. shader.vsh:
attribute VEC3 position; Entry, the main program passes the value to void Main () { gl_position = VEC4 (position,1); The position of the vertex after the transformation of the projection transform}
Shader.fsh:
void Main () { Gl_fragcolor = VEC4 (0.5,0.5,0.5,1); The color of the vertex}
as you can see, each shader file is a C-like main function entry, and this is the entry for the shader, and all the code starts here. after the shader is written, we need to load shader in the main program, and the code that loads the shader basically doesn't need to change anything, just copy it over.
-(BOOL) loadshaders{gluint Vertshader, Fragshader; NSString *vertshaderpathname, *fragshaderpathname; Create shader program. program = Glcreateprogram (); Create and compile vertex shader. Vertshaderpathname = [[NSBundle mainbundle] pathforresource:@ "Shader" oftype:@ "Vsh"]; if (![ Self Compileshader:&vertshader type:gl_vertex_shader file:vertshaderpathname]) {NSLog (@ "Failed to compile Vert Ex shader "); return NO; }//Create and compile fragment shader. Fragshaderpathname = [[NSBundle mainbundle] pathforresource:@ "Shader" oftype:@ "FSH"]; if (![ Self Compileshader:&fragshader type:gl_fragment_shader file:fragshaderpathname]) {NSLog (@ ' Failed to compile FR Agment shader "); return NO; }//Attach vertex shader to program. Glattachshader (program, Vertshader); Attach fragment shader to program. Glattachshader (program, Fragshader); Link program. if (![ Self LINKPROGRAM:PROgram]) {NSLog (@ "Failed to link Program:%d", program); if (Vertshader) {gldeleteshader (Vertshader); Vertshader = 0; } if (Fragshader) {gldeleteshader (Fragshader); Fragshader = 0; } if (program) {Gldeleteprogram (program); program = 0; } return NO; }//Release vertex and fragment shaders. if (Vertshader) {Gldetachshader (program, Vertshader); Gldeleteshader (Vertshader); } if (Fragshader) {Gldetachshader (program, Fragshader); Gldeleteshader (Fragshader); } return YES; -(BOOL) Compileshader: (Gluint *) shader type: (glenum) type file: (NSString *) file{glint status; Const Glchar *source; Source = (Glchar *) [[NSString stringwithcontentsoffile:file encoding:nsutf8stringencoding Error:nil] UTF8String]; if (!source) {NSLog (@ "Failed to load vertex shader"); return NO; } *shader = Glcreateshader (type); Glshadersource (*shader, 1, &source, NULL); Glcompileshader (*shader); #if defined (DEBUG) glint loglength; Glgetshaderiv (*shader, Gl_info_log_length, &loglength); if (Loglength > 0) {Glchar *log = (Glchar *) malloc (loglength); Glgetshaderinfolog (*shader, loglength, &loglength, log); NSLog (@ "Shader compile log:\n%s", log); Free (log); } #endif Glgetshaderiv (*shader, Gl_compile_status, &status); if (status = = 0) {gldeleteshader (*shader); return NO; } return YES; -(BOOL) Linkprogram: (gluint) prog{glint status; Gllinkprogram (Prog); #if defined (DEBUG) glint loglength; GLGETPROGRAMIV (Prog, gl_info_log_length, &loglength); if (Loglength > 0) {Glchar *log = (Glchar *) malloc (loglength); Glgetprograminfolog (Prog, loglength, &loglength, log); NSLog (@ "program link log:\n%s", log); Free (log); } #endif GLGETPROGRAMIV (Prog, gl_link_status, &status); if (status = = 0) {return NO; } return YES; -(BOOL) Validateprogram: (gluint) prog{glint loglength, status; Glvalidateprogram (Prog); GLGETPROGRAMIV (Prog, gl_info_log_length, &loglength); if (Loglength > 0) {Glchar *log = (Glchar *) malloc (loglength); Glgetprograminfolog (Prog, loglength, &loglength, log); NSLog (@ "program validate log:\n%s", log); Free (log); } glgetprogramiv (Prog, gl_validate_status, &status); if (status = = 0) {return NO; } return YES;
then add the following code to the Viewdidload:
[Self loadshaders]; Glenable (gl_depth_test); Glclearcolor (0.1, 0.2, 0.3, 1); Glgenvertexarrays (1, &VERTEXID);//Generate a Vao object Glbindvertexarray (VERTEXID);//bind Vao gluint bufferid ; Glgenbuffers (1, &bufferid); Generate VBO
Glbindbuffer (Gl_array_buffer, Bufferid); Bind Glbufferdata (gl_array_buffer, sizeof (VEC), VEC, Gl_static_draw);//Fill Buffer object gluint loc= Glgetattriblocation (program, "position"); Obtain the index Glenablevertexattribarray (Loc) of the position variable in the shader; Enable this index glvertexattribpointer (LOC, 3, gl_float, Gl_false, sizeof (GLKVECTOR3), 0); Set the contents of this index to be populated glbindvertexarray (0); Release Vao glbindbuffer (gl_array_buffer, 0); Release VBO
Here we use the new technology Vao (vertex array object) Inside ES 3.0 and the VBO inside the 2.0. About Vao and VBO, we will specialize in a chapter to explore, now you know the line.
Next comes the rendering phase, where the code needs to be written in -(void) Glkview: (glkview *) View Drawinrect: ( CGRect) in the Rect method.
-(void) Glkview: (Glkview *) View Drawinrect: (cgrect) rect{ glclear (gl_color_buffer_bit | Gl_depth_buffer_bit); Clear the color buffer and depth buffer Glbindvertexarray (VERTEXID); Gluseprogram (program); Using shader gldrawarrays (gl_triangles, 0, 3); Draw Triangle Glbindvertexarray (0); Glbindbuffer (gl_array_buffer, 0); Glbindbuffer (gl_element_array_buffer, 0);}
The code phase is written and finished, save the run, the following interface is done.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Getting Started with OpenGL ES 3.0 programming in iOS (ii): Draw a simple triangle