iOS原生OPENGL之贴图

来源:互联网 发布:淘宝招聘官网首页 编辑:程序博客网 时间:2024/05/01 08:16
iOS平台上学习OpenGL的资料比较少,加上深度也不够,比如贴图,只能用系统提供的effect类去绘制,在这里我将我整理得到的一些关于贴图的知识分享出来,希望能帮到不了解又想学gl知识的人.完整代码请参照:https://github.com/xuyaxiang/TriangleMipByShader
////  ViewController.m//  GoldTower////  Created by enghou on 17/3/20.//  Copyright © 2017年 xyxorigation. All rights reserved.//#import "ViewController.h"typedef enum{    AGLK1 = 1,    AGLK2 = 2,    AGLK4 = 4,    AGLK8 = 8,    AGLK16 = 16,    AGLK32 = 32,    AGLK64 = 64,    AGLK128 = 128,    AGLK256 = 256,    AGLK512 = 512,    AGLK1024 = 1024,}AGLKPowerOf2;static NSData *AGLKDataWithResizedCGImageBytes(                                               CGImageRef cgImage,                                               size_t *widthPtr,                                               size_t *heightPtr);static AGLKPowerOf2 AGLKCalculatePowerOf2ForDimension(                                                      GLuint dimension);typedef struct {    GLKVector3  position;    GLKVector3  normal;    GLKVector4  color;    GLKVector2 texCoords;}SceneVertex;typedef struct {    SceneVertex vertices[3];}SceneTriangle;static const SceneVertex vertexA ={{-0.5,  0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{0,1}};static const SceneVertex vertexB ={{-0.5,  0.0, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{0,0.5}};static const SceneVertex vertexC ={{-0.5, -0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{0,0}};static const SceneVertex vertexD ={{ 0.0,  0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{0.5,1}};static const SceneVertex vertexE ={{ 0.0,  0.0, 0.5}, {0.0, 0.0, 1.0},{1,1,1,1},{0.5,0.5}};static const SceneVertex vertexF ={{ 0.0, -0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{0.5,0}};static const SceneVertex vertexG ={{ 0.5,  0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{1,1}};static const SceneVertex vertexH ={{ 0.5,  0.0, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{1,0.5}};static const SceneVertex vertexI ={{ 0.5, -0.5, 0}, {0.0, 0.0, 1.0},{1,1,1,1},{1,0}};SceneTriangle triangle[8];@interface ViewController ()@property(nonatomic,assign)GLuint program;@property(nonatomic,assign)int lightPositionP;@property(nonatomic,assign)int lightColor;@property(nonatomic,assign)int modelMatrix;@property(nonatomic,assign)int viewMatrix;@property(nonatomic,assign)GLint texCoords;@property(nonatomic,assign)GLuint texture;@end@implementation ViewController{    GLKBaseEffect *effect;}-(void)makeTriangles{    triangle[0] = [self makeTriangle:vertexA B:vertexB C:vertexD];    triangle[1] = [self makeTriangle:vertexG B:vertexD C:vertexH];    triangle[2] = [self makeTriangle:vertexH B:vertexF C:vertexI];    triangle[3] = [self makeTriangle:vertexB B:vertexC C:vertexF];    triangle[4] = [self makeTriangle:vertexD B:vertexB C:vertexE];    triangle[5] = [self makeTriangle:vertexD B:vertexE C:vertexH];    triangle[6] = [self makeTriangle:vertexH B:vertexE C:vertexF];    triangle[7] = [self makeTriangle:vertexF B:vertexE C:vertexB];}-(SceneTriangle)makeTriangle:(SceneVertex)A B:(SceneVertex)B C:(SceneVertex)C{    SceneTriangle triangle;    triangle.vertices[0] = A;    triangle.vertices[1] = B;    triangle.vertices[2] = C;    GLKVector3 AB = GLKVector3Make(B.position.x - A.position.x, B.position.y - A.position.y, B.position.z - B.position.z);    GLKVector3 AC = GLKVector3Make(C.position.x - A.position.x, C.position.y - A.position.y, C.position.z - B.position.z);    GLKVector3 normal = GLKVector3CrossProduct(AB, AC);    normal = GLKVector3Normalize(normal);    triangle.vertices[0].normal = normal;    triangle.vertices[1].normal = normal;    triangle.vertices[2].normal = normal;    return triangle;}- (void)viewDidLoad {    [super viewDidLoad];    GLKView *view = (GLKView *)self.view;    view.context =[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];    [EAGLContext setCurrentContext:view.context];    effect = [[GLKBaseEffect alloc]init];    effect.useConstantColor = GL_TRUE;    effect.constantColor = GLKVector4Make(0, 0, 0, 1);        [self makeTriangles];    GLuint name;    glGenBuffers(1, &name);    glBindBuffer(GL_ARRAY_BUFFER, name);    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle), triangle, GL_STATIC_DRAW);        glEnable(GL_TEXTURE_2D);    UIImage *image = [UIImage imageNamed:@"1.jpg"];    size_t width;    size_t height;    NSData *data = AGLKDataWithResizedCGImageBytes(image.CGImage, &width, &height);    glGenTextures(1, &_texture);    glActiveTexture(GL_TEXTURE_2D);    glBindTexture(GL_TEXTURE_2D, _texture);    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.bytes);        glClearColor(0, 0, 0, 1);    glEnableVertexAttribArray(GLKVertexAttribPosition);    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL);    glEnableVertexAttribArray(GLKVertexAttribNormal);    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL + offsetof(SceneVertex, normal));    glEnableVertexAttribArray(GLKVertexAttribColor);    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL+offsetof(SceneVertex, color));    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL+offsetof(SceneVertex, texCoords));    glEnable(GL_DEPTH_TEST | GL_CULL_FACE);    [self loadShaders];    glUniform1i(_texCoords, 0);}-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    static float i = 0.0;    glUseProgram(_program);    glUniform4f(_lightPositionP, 1, 0, 1, 1);    glUniform4f(_lightColor, 0, 0.5, 0.5, 1);    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0, 0, 2);    GLfloat ratio = (GLfloat)view.drawableWidth / view.drawableHeight;    modelViewMatrix = GLKMatrix4Scale(modelViewMatrix, 3, 3*ratio, 3);    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(60), 1, 0, 0);    i = i + 0.001;    GLKMatrix4 projection = GLKMatrix4MakeFrustum(-1, 1, -1, 1, 1, 50);    glUniformMatrix4fv(_modelMatrix, 1, 0, modelViewMatrix.m);    glUniformMatrix4fv(_viewMatrix, 1, 0, projection.m);    glDrawArrays(GL_TRIANGLES, 0, sizeof(triangle)/sizeof(SceneVertex));}#pragma mark -  OpenGL ES 2 shader compilation- (BOOL)loadShaders{    GLuint vertShader, fragShader;    NSString *vertShaderPathname, *fragShaderPathname;        // Create shader program.    _program = glCreateProgram();        vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];    if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {        NSLog(@"Failed to compile vertex 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 fragment shader");        return NO;    }        // Attach vertex shader to program.    glAttachShader(_program, vertShader);        // Attach fragment shader to program.    glAttachShader(_program, fragShader);        glBindAttribLocation(_program, GLKVertexAttribPosition, "position");    glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");    glBindAttribLocation(_program, GLKVertexAttribTexCoord0, "TextureCoords");    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;    }        if (vertShader) {        glDetachShader(_program, vertShader);        glDeleteShader(vertShader);    }    if (fragShader) {        glDetachShader(_program, fragShader);        glDeleteShader(fragShader);    }    char *position = "lightPosition";    char *lightColor = "lightColor";    _lightPositionP = glGetUniformLocation(_program, position);    _lightColor = glGetUniformLocation(_program, lightColor);    _modelMatrix = glGetUniformLocation(_program, "modelMatrix");    _viewMatrix = glGetUniformLocation(_program, "projectionMatrix");    _texCoords = glGetUniformLocation(_program, "tex");    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;}- (void)didReceiveMemoryWarning {    [super didReceiveMemoryWarning];    // Dispose of any resources that can be recreated.}@endstatic AGLKPowerOf2 AGLKCalculatePowerOf2ForDimension(                                                      GLuint dimension){    AGLKPowerOf2  result = AGLK1;        if(dimension > (GLuint)AGLK512)    {        result = AGLK1024;    }    else if(dimension > (GLuint)AGLK256)    {        result = AGLK512;    }    else if(dimension > (GLuint)AGLK128)    {        result = AGLK256;    }    else if(dimension > (GLuint)AGLK64)    {        result = AGLK128;    }    else if(dimension > (GLuint)AGLK32)    {        result = AGLK64;    }    else if(dimension > (GLuint)AGLK16)    {        result = AGLK32;    }    else if(dimension > (GLuint)AGLK8)    {        result = AGLK16;    }    else if(dimension > (GLuint)AGLK4)    {        result = AGLK8;    }    else if(dimension > (GLuint)AGLK2)    {        result = AGLK4;    }    else if(dimension > (GLuint)AGLK1)    {        result = AGLK2;    }        return result;}static NSData *AGLKDataWithResizedCGImageBytes(                                               CGImageRef cgImage,                                               size_t *widthPtr,                                               size_t *heightPtr){    NSCParameterAssert(NULL != cgImage);    NSCParameterAssert(NULL != widthPtr);    NSCParameterAssert(NULL != heightPtr);        GLuint originalWidth = (GLuint)CGImageGetWidth(cgImage);    GLuint originalHeight = (GLuint)CGImageGetWidth(cgImage);        NSCAssert(0 < originalWidth, @"Invalid image width");    NSCAssert(0 < originalHeight, @"Invalid image width");        // Calculate the width and height of the new texture buffer    // The new texture buffer will have power of 2 dimensions.    GLuint width = AGLKCalculatePowerOf2ForDimension(                                                     originalWidth);    GLuint height = AGLKCalculatePowerOf2ForDimension(                                                      originalHeight);        // Allocate sufficient storage for RGBA pixel color data with    // the power of 2 sizes specified    NSMutableData    *imageData = [NSMutableData dataWithLength:                                   height * width * 4];  // 4 bytes per RGBA pixel        NSCAssert(nil != imageData,              @"Unable to allocate image storage");        // Create a Core Graphics context that draws into the    // allocated bytes    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();    CGContextRef cgContext = CGBitmapContextCreate(                                                   [imageData mutableBytes], width, height, 8,                                                   4 * width, colorSpace,                                                   kCGImageAlphaPremultipliedLast);    CGColorSpaceRelease(colorSpace);        // Flip the Core Graphics Y-axis for future drawing    CGContextTranslateCTM (cgContext, 0, height);    CGContextScaleCTM (cgContext, 1.0, -1.0);        // Draw the loaded image into the Core Graphics context     // resizing as necessary    CGContextDrawImage(cgContext, CGRectMake(0, 0, width, height),                       cgImage);        CGContextRelease(cgContext);        *widthPtr = width;    *heightPtr = height;        return imageData;}

0 0
原创粉丝点击