美文网首页OpenGL
九、OpenGL ES/Core Animation立方体贴图+

九、OpenGL ES/Core Animation立方体贴图+

作者: 收纳箱 | 来源:发表于2020-07-25 08:47 被阅读0次

    1.OpenGL ES

    1.1 透视投影

    GLfloat vertexData[] = {
        0.5, -0.5, 0.0f,    1.0f, 0.0f, //右下
        0.5, 0.5,  0.0f,    1.0f, 1.0f, //右上
        -0.5, 0.5, 0.0f,    0.0f, 1.0f, //左上
        
        0.5, -0.5, 0.0f,    1.0f, 0.0f, //右下
        -0.5, 0.5, 0.0f,    0.0f, 1.0f, //左上
        -0.5, -0.5, 0.0f,   0.0f, 0.0f, //左下
    };
    

    虽然我们的代码看起来是绘制了一个正方形,但由于视口(视图)宽高比的问题产生了拉伸问题。如下图所示:

    为了解决这个问题,我们可以设置透视投影矩阵。又由于平截头体可视范围的问题,我们需要将顶点向后移4.0单位。

    CGFloat aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0);
    _baseEffect.transform.projectionMatrix = projectionMatrix;
        
    GLKMatrix4 modelviewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -4.0);
    _baseEffect.transform.modelviewMatrix = modelviewMatrix;
    

    2.1 立方体贴图+旋转

    解决了上面的问题,完成立方体贴图+旋转就很简单了。

    • 写好立方体的顶点位置。
    • - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 会不断回调,在里面更新模型视图变换矩阵就可以了。
    OpenGL ES
    @interface DemoViewController ()
    {
        EAGLContext *_context;
        GLKBaseEffect *_baseEffect;
        int _angle;
    }
    @end
    
    @implementation DemoViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //1.OpenGL ES 相关初始化
        [self setUpConfig];
        //2.加载顶点/纹理坐标数据
        [self setUpVertexData];
        //3.加载纹理数据(使用GLBaseEffect)
        [self setUpTexture];
    }
    
    -(void)setUpTexture
    {
        NSString *filePath = [[NSBundle mainBundle]pathForResource:@"qiyu" ofType:@"jpg"];
        
        NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES)};
        GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
        // 纹理设置
        _baseEffect = [[GLKBaseEffect alloc] init];
        _baseEffect.texture2d0.enabled = GL_TRUE;
        _baseEffect.texture2d0.name = textureInfo.name;
        // 透视投影矩阵
        CGFloat aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
        GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0);
        _baseEffect.transform.projectionMatrix = projectionMatrix;
    }
    
    -(void)setUpVertexData
    {
        GLfloat vertices[] = {
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
            
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            
            -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
            
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
            0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
            -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
            -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
        };
        // 顶点缓存
        GLuint bufferID;
        glGenBuffers(1, &bufferID);
        glBindBuffer(GL_ARRAY_BUFFER, bufferID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
        //顶点坐标数据
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
        //纹理坐标数据
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
        glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);
    }
    
    - (void)setUpConfig
    {
        _context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3];
        if (!_context) {
            NSLog(@"Create ES context Failed");
        }
        //设置当前上下文
        [EAGLContext setCurrentContext:_context];
        
        GLKView *view =(GLKView *) self.view;
        view.context = _context;
        view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
        view.drawableDepthFormat = GLKViewDrawableDepthFormat16;
        
        glClearColor(0.8, 0.8, 0.8, 1.0);
    }
    
    #pragma mark -- GLKViewDelegate
    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    {
        glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // 更新旋转
        [self update];
        [_baseEffect prepareToDraw];
        glDrawArrays(GL_TRIANGLES, 0, 48);
    }
    
    - (void)update {
        _angle = (_angle + 2) % 360;
        GLKMatrix4 modelviewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -4.0);
        modelviewMatrix = GLKMatrix4Rotate(modelviewMatrix, GLKMathDegreesToRadians(_angle), 0.3, 0.5, 0.7);
        _baseEffect.transform.modelviewMatrix = modelviewMatrix;
    }
    
    @end
    

    2. Core Animation

    使用 Core Animation 完成上面的功能也非常简单,利用layer.transform的数据结构CATransform3D即可完成3D变换。

    值得一提的是,为了实现立方体整体的旋转动画,我们不需要为为一个面都专门做变换。我们只需要将它们放在同一个父视图中,利用父视图的layer.sublayerTransform即可对所有子视图进行统一变换。

    Core Animation
    @interface ViewController ()
    
    @property (nonatomic, strong) UIView *containerView;
    
    @end
    
    @implementation ViewController
    
    - (void)addFace:(int)index withTransform:(CATransform3D)transform
    {
        NSString *filePath = [[NSBundle mainBundle]pathForResource:@"qiyu" ofType:@"jpg"];
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
        imageView.image = [UIImage imageWithContentsOfFile:filePath];
        [self.containerView addSubview:imageView];
        CGSize containerSize = self.containerView.bounds.size;
        imageView.center = CGPointMake(containerSize.width / 2.0, containerSize.height / 2.0);
        // 变换
        imageView.layer.transform = transform;
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = UIColor.lightGrayColor;
        
        self.containerView = [[UIView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:self.containerView];
        
        //add cube face 1
        CATransform3D transform = CATransform3DMakeTranslation(0, 0, 100);
        [self addFace:0 withTransform:transform];
        //add cube face 2
        transform = CATransform3DMakeTranslation(100, 0, 0);
        transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
        [self addFace:1 withTransform:transform];
        //add cube face 3
        transform = CATransform3DMakeTranslation(0, -100, 0);
        transform = CATransform3DRotate(transform, M_PI_2, 1, 0, 0);
        [self addFace:2 withTransform:transform];
        //add cube face 4
        transform = CATransform3DMakeTranslation(0, 100, 0);
        transform = CATransform3DRotate(transform, -M_PI_2, 1, 0, 0);
        [self addFace:3 withTransform:transform];
        //add cube face 5
        transform = CATransform3DMakeTranslation(-100, 0, 0);
        transform = CATransform3DRotate(transform, -M_PI_2, 0, 1, 0);
        [self addFace:4 withTransform:transform];
        //add cube face 6
        transform = CATransform3DMakeTranslation(0, 0, -100);
        transform = CATransform3DRotate(transform, M_PI, 0, 1, 0);
        [self addFace:5 withTransform:transform];
        
        __block int step = 0;
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            step = (step + 2) % 360;
            self.containerView.layer.sublayerTransform = CATransform3DMakeRotation(M_PI / 180.0 * step, -0.3, 0.5, -0.7);
        }];
        [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
    
    @end
    

    相关文章

      网友评论

        本文标题:九、OpenGL ES/Core Animation立方体贴图+

        本文链接:https://www.haomeiwen.com/subject/duqplktx.html