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