罗大柚OpenGL ES教程系列_LessonTwo(Part 4)_使用shader绘制一个立方体

这一次,我们还是绘制一个立方体,但是采用的是shader, 需要说明的是, 我们用的是Xcode5.02中系统提供的顶点数据 和 shader, 写shader并不难,这里图个省事了。

 

 

罗大柚OpenGL ES教程系列_LessonTwo(Part 4)_使用shader绘制一个立方体_第1张图片

 

 

 

#import "ViewController.h"

#defineBUFFER_OFFSET(i) ((char *)NULL + (i))

 

//Uniform index.

enum

{

    UNIFORM_MODELVIEWPROJECTION_MATRIX,

    UNIFORM_NORMAL_MATRIX,

    NUM_UNIFORMS

};

GLintuniforms[NUM_UNIFORMS];

 

//Attribute index.

enum

{

    ATTRIB_VERTEX,

    ATTRIB_NORMAL,

    NUM_ATTRIBUTES

};

 

GLfloatgCubeVertexData[216] =

{

    // Data layout for each line below is:

    // positionX, positionY, positionZ,     normalX, normalY, normalZ,

    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,

    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,

    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,

    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,

    0.5f, 0.5f, -0.5f,          1.0f, 0.0f, 0.0f,

    0.5f, 0.5f, 0.5f,         1.0f, 0.0f, 0.0f,

   

    0.5f, 0.5f, -0.5f,         0.0f, 1.0f, 0.0f,

    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,

    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,

    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,

    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,

    -0.5f, 0.5f, 0.5f,         0.0f, 1.0f, 0.0f,

   

    -0.5f, 0.5f, -0.5f,        -1.0f, 0.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,

    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,

    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,

    -0.5f, -0.5f, 0.5f,        -1.0f, 0.0f, 0.0f,

   

    -0.5f, -0.5f, -0.5f,       0.0f, -1.0f, 0.0f,

    0.5f,-0.5f, -0.5f,        0.0f, -1.0f, 0.0f,

    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,

    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,

    0.5f, -0.5f, -0.5f,        0.0f, -1.0f, 0.0f,

    0.5f, -0.5f, 0.5f,         0.0f, -1.0f, 0.0f,

   

    0.5f,0.5f, 0.5f,          0.0f, 0.0f, 1.0f,

    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,

    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,

    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,

    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,

    -0.5f, -0.5f, 0.5f,        0.0f, 0.0f, 1.0f,

   

    0.5f, -0.5f, -0.5f,        0.0f, 0.0f, -1.0f,

    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -1.0f,

    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,

    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,

    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -1.0f,

    -0.5f, 0.5f, -0.5f,        0.0f, 0.0f, -1.0f

};

 

 

@interfaceViewController ()

{

 

    GLuint _program;

   

    GLKMatrix4 _modelViewProjectionMatrix;

    GLKMatrix3 _normalMatrix;

    float _rotation;

   

    GLuint _vertexArray;

    GLuint _vertexBuffer;

}

 

@property (strong,nonatomic)EAGLContext*context;

@property (strong,nonatomic)GLKBaseEffect*baseEffect;

 

- (void)setupGL;

- (void)tearDownGL;

 

- (BOOL)loadShaders;

- (BOOL)compileShader:(GLuint*)shader type:(GLenum)type file:(NSString *)file;

- (BOOL)linkProgram:(GLuint)prog;

- (BOOL)validateProgram:(GLuint)prog;

 

@end

 

@implementationViewController

 

- (void)viewDidLoad

{

    [super viewDidLoad];

   

    self.context = [[EAGLContextalloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];

   

    if (!self.context) {

        NSLog(@"Failedto create ES context");

    }

   

    GLKView *view = (GLKView *)self.view;

    view.context = self.context;

    view.drawableDepthFormat =GLKViewDrawableDepthFormat24;

   

    [selfsetupGL];

}

 

- (void)dealloc

{

    [self tearDownGL];

   

    if ([EAGLContext currentContext] ==self.context) {

        [EAGLContext setCurrentContext:nil];

    }

}

 

- (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

   

    if ([self isViewLoaded] && ([[selfview]window] == nil)) {

        self.view =nil;

       

        [self tearDownGL];

       

        if ([EAGLContextcurrentContext] ==self.context) {

           [EAGLContextsetCurrentContext:nil];

        }

        self.context =nil;

    }

   

    // Dispose of any resources that can berecreated.

}

 

- (void)setupGL

{

    [EAGLContextsetCurrentContext:self.context];

   

    [self loadShaders];

   

    self.baseEffect = [[GLKBaseEffect alloc]init];

    self.baseEffect.light0.enabled = GL_TRUE;

    self.baseEffect.light0.diffuseColor = GLKVector4Make(1.0f,0.4f, 0.4f, 1.0f);

   

    glEnable(GL_DEPTH_TEST);

   

    glGenVertexArraysOES(1,&_vertexArray);

    glBindVertexArrayOES(_vertexArray);

   

    glGenBuffers(1, &_vertexBuffer);

    glBindBuffer(GL_ARRAY_BUFFER,_vertexBuffer);

    glBufferData(GL_ARRAY_BUFFER,sizeof(gCubeVertexData),gCubeVertexData,GL_STATIC_DRAW);

   

    glEnableVertexAttribArray(GLKVertexAttribPosition);

    glVertexAttribPointer(GLKVertexAttribPosition, 3,GL_FLOAT,GL_FALSE, 24, BUFFER_OFFSET(0));

    glEnableVertexAttribArray(GLKVertexAttribNormal);

    glVertexAttribPointer(GLKVertexAttribNormal, 3,GL_FLOAT,GL_FALSE, 24, BUFFER_OFFSET(12));

   

    glBindVertexArrayOES(0);

}

 

- (void)tearDownGL

{

    [EAGLContext setCurrentContext:self.context];

   

    glDeleteBuffers(1, &_vertexBuffer);

    glDeleteVertexArraysOES(1,&_vertexArray);

   

    self.baseEffect =nil;

   

    if (_program) {

        glDeleteProgram(_program);

        _program = 0;

    }

}

 

#pragmamark - GLKView and GLKViewController delegate methods

 

- (void)update

{

    //设置投影矩阵

    float aspect= fabsf(self.view.bounds.size.width / self.view.bounds.size.height);

    GLKMatrix4 projectionMatrix =GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);

   

    self.baseEffect.transform.projectionMatrix = projectionMatrix;

 

    //设置模型视图矩阵

    GLKMatrix4 baseModelViewMatrix =GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);

    GLKMatrix4 modelViewMatrix =GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);

   modelViewMatrix =GLKMatrix4Rotate(modelViewMatrix,_rotation, 1.0f, 1.0f, 1.0f);

   modelViewMatrix =GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

   

    _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

   

    _modelViewProjectionMatrix =GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);

   

    _rotation += self.timeSinceLastUpdate * 0.5f;

   

}

 

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

{

    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);

   

    glBindVertexArrayOES(_vertexArray);

   

    // Render the object with GLKit

    [self.baseEffect prepareToDraw];

   

    glUseProgram(_program);

   

    //将宿主程序中的 _modelViewProjectionMatrix传到shader中的modelViewProjectionMatrix

    glUniformMatrix4fv(

                      //Location: Specifies the location of the uniform value to be modified

                      uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX],

                      //count: specifies the number of matrices(矩阵) that are to be modified. This should be 1 ifthe targeted uniform variable is not an array of matrices

                      // and 1 or more if it is an arrayof matrices.

                      1,

                      

                      //transpose: Specifies whether to transpose the matrix as the value areloaded into the uniform variable,Must be GL_FALSE.

                      0,

                      //Value: Specifies a pointer to an array of count value that will be toupdate the specified uniform variable.

                      _modelViewProjectionMatrix.m);

   

    //将宿主程序中的_normalMatrix传到shader中的normalMatrix

    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0,_normalMatrix.m);

   

    glDrawArrays(GL_TRIANGLES, 0, 36);

}

 

#pragma mark - OpenGL ES 2 shader compilation

 

- (BOOL)loadShaders

{

    GLuint vertShader, fragShader;

    NSString *vertShaderPathname, *fragShaderPathname;

   

    // Create shader program.

    _program = glCreateProgram();

   

    // Create and compile vertex shader.

   vertShaderPathname = [[NSBundle mainBundle]pathForResource:@"VertexShader"ofType:@"glsl"];

    if (![selfcompileShader:&vertShadertype:GL_VERTEX_SHADERfile:vertShaderPathname]) {

       NSLog(@"Failed to compile vertexshader");

       returnNO;

    }

   

    // Create and compile fragment shader.

   fragShaderPathname = [[NSBundle mainBundle]pathForResource:@"FragmentShader"ofType:@"glsl"];

    if (![self compileShader:&fragShadertype:GL_FRAGMENT_SHADERfile:fragShaderPathname]) {

       NSLog(@"Failed to compile fragmentshader");

       returnNO;

    }

   

    // Attach vertex shader to program.

    glAttachShader(_program, vertShader);

   

    // Attach fragment shader to program.

    glAttachShader(_program, fragShader);

   

    // Bind attribute locations.

   

    // This needs to be done prior to linking.

    //绑定shader中的position

    glBindAttribLocation(_program, GLKVertexAttribPosition, "position");

    glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");

   

    // Link program.

    if (![selflinkProgram:_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;

       }

       

       returnNO;

    }

   

    // Get uniform locations.

    uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] =glGetUniformLocation(_program,"modelViewProjectionMatrix");

    uniforms[UNIFORM_NORMAL_MATRIX] =glGetUniformLocation(_program,"normalMatrix");

   

    // Release vertex and fragment shaders.

    if(vertShader) {

       glDetachShader(_program, vertShader);

       glDeleteShader(vertShader);

    }

    if(fragShader) {

       glDetachShader(_program, fragShader);

       glDeleteShader(fragShader);

    }

   

    returnYES;

}

 

- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file

{

    GLint status;

    constGLchar *source;

   

   source = (GLchar *)[[NSString  stringWithContentsOfFile:fileencoding:NSUTF8StringEncodingerror:nil]UTF8String];

    if(!source) {

       NSLog(@"Failed to load vertex shader");

        returnNO;

    }

   

   *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);

       returnNO;

    }

   

    returnYES;

}

 

- (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) {

       returnNO;

    }

   

    returnYES;

}

 

- (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) {

       returnNO;

    }

   

    returnYES;

}

@end

 

//顶点着色器

 

attributevec4 position;

attributevec3 normal;

 

varyinglowpvec4 colorVarying;

 

uniformmat4 modelViewProjectionMatrix;

uniformmat3 normalMatrix;

 

void main()

{

    vec3 eyeNormal = normalize(normalMatrix * normal);

    vec3 lightPosition = vec3(0.0, 0.0, 1.0);

    vec4 diffuseColor = vec4(0.4, 0.4, 1.0, 1.0);

   

    float nDotVP = max(0.0,dot(eyeNormal,normalize(lightPosition)));

   

    colorVarying = diffuseColor *nDotVP;

   

    gl_Position = modelViewProjectionMatrix* position;

}

 

 

//片元着色器

varyinglowpvec4 colorVarying;

 

void main()

{

    gl_FragColor =colorVarying;

}

 

源码下载:

http://download.csdn.net/detail/luozhonglan/6992787

 

 

 

你可能感兴趣的