zoukankan      html  css  js  c++  java
  • swift 使用GLKit加载一张图片

     GLKit框架是苹果为快速实现OpenGL ES功能所提供的轻型框架

     GLKit框架提供的函数和类减少了创建新的基于着色器的应用程序,减少了现有app所需的依赖于OpenGL ES或OpenGL早期版本提供的顶点着色器或者片元着色器程序的工作。

     GLKit主要提供了一下四方面的功能:

     1纹理加载让你很容易的从资源文件中加载纹理图片,仅通过几行简单的代码就能让你在后台线程一步加载纹理,更多详细内容请看GLKTextureLoader

     2.数学库提供了常用的向量、四元数和矩阵运算。这些实现进行了优化,以提供出色的性能。

     3Effects类提供了通用着色效果的标准实现。您可以配置效果和关联的顶点数据;effect将会自动创建并加载一个适当的着色器,GLKit包含三个效果:GLKBaseEffect类实现了OpenGL ES1.1中明暗模型的一个关键子集,GLKReflectionMapEffect类扩展了基本效果以包含反射映射支持,而GLKSkyboxEffect类提供了一个skybox效果的实现。

     4.视图和视图控制器提供了OpenGL ES视图和相应视图控制器的标准实现。这减少了创建使用OpenGL ES的iOS应用程序所需的代码量。有关更多信息,请参见GLKView和GLKViewController。

      详情请看苹果官方文档:https://developer.apple.com/documentation/glkit

       

     下面介绍如何使用GLKit加载一张纹理图片

    //
    //  ViewController.swift
    //  GLKitTest
    //
    //  Created by dzq_mac on 2020/5/14.
    //  Copyright © 2020 dzq_mac. All rights reserved.
    //
    
    import UIKit
    import GLKit
    
    @available(*, deprecated, message: "ios13")//消除警告
    class ViewController: UIViewController {
    
        var glView:GLKView!
        var context:EAGLContext?
        var effect:GLKBaseEffect!
        var bufferID : GLuint = GLuint()
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            //1.初始化
            config()
            
            //2.顶点/纹理 坐标
            setUpVertexData()
            
            //设置纹理数据
            setImage()
            
        }
    
        func config(){
            //1创建GKLKView
            glView = GLKView(frame: CGRect(x: 20, y: 100,  UIScreen.main.bounds.width - 40, height: self.view.bounds.size.height - 200))
            
            self.view.addSubview(glView)
            //2.设置Context
            context = EAGLContext(api: EAGLRenderingAPI.openGLES3)
            if let con = context {
                EAGLContext.setCurrent(con)
                
                glView.context = con
            }
            /*3.配置视图创建的渲染缓存区.
            
            (1). drawableColorFormat: 颜色缓存区格式.
            简介:  OpenGL ES 有一个缓存区,它用以存储将在屏幕中显示的颜色。你可以使用其属性来设置缓冲区中的每个像素的颜色格式。
            
            GLKViewDrawableColorFormatRGBA8888 = 0,
            默认.缓存区的每个像素的最小组成部分(RGBA)使用8个bit,(所以每个像素4个字节,4*8个bit)。
            
            GLKViewDrawableColorFormatRGB565,
            如果你的APP允许更小范围的颜色,即可设置这个。会让你的APP消耗更小的资源(内存和处理时间)
            
            (2). drawableDepthFormat: 深度缓存区格式
            GLKViewDrawableDepthFormatNone = 0,意味着完全没有深度缓冲区
            GLKViewDrawableDepthFormat16,
            GLKViewDrawableDepthFormat24,
            如果你要使用这个属性(一般用于3D游戏),你应该选择GLKViewDrawableDepthFormat16
            或GLKViewDrawableDepthFormat24。这里的差别是使用GLKViewDrawableDepthFormat16
            将消耗更少的资源
            
            */
            glView.drawableColorFormat = .RGBA8888
            glView.drawableDepthFormat = .format16
            glView.delegate = self
            //4.设置背景颜色
            glClearColor(1, 1, 0, 1)
        }
        
        func setUpVertexData(){
            //1.设置顶点数组(顶点坐标,纹理坐标)
            /*
             纹理坐标系取值范围[0,1];原点是左下角(0,0);
             故而(0,0)是纹理图像的左下角, 点(1,1)是右上角.
             */
            let vertexs:[GLfloat]  = [
                0.5, -0.5, 0.0,    1.0, 0.0, //右下
                0.5, 0.5, -0.0,    1.0, 1.0, //右上
                -0.5, 0.5, 0.0,    0.0, 1.0, //左上
                
                0.5, -0.5, 0.0,    1.0, 0.0, //右下
                -0.5, 0.5, 0.0,    0.0, 1.0, //左上
                -0.5, -0.5, 0.0,   0.0, 0.0, //左下
            ]
    
            
               /*
                顶点数组: 开发者可以选择设定函数指针,在调用绘制方法的时候,直接由内存传入顶点数据,也就是说这部分数据之前是存储在内存当中的,被称为顶点数组
                
                顶点缓存区: 性能更高的做法是,提前分配一块显存,将顶点数据预先传入到显存当中。这部分的显存,就被称为顶点缓冲区
                */
            ////2.开辟顶点缓存区
            //(1).创建顶点缓存区标识符ID
            glGenBuffers(1, &bufferID)
            //(2).绑定顶点缓存区.(明确作用)
            glBindBuffer(GLenum(GL_ARRAY_BUFFER), bufferID)
            let size = MemoryLayout<[GLfloat]>.size * 30
            glBufferData(GLenum(GL_ARRAY_BUFFER), size, vertexs, GLenum(GL_STATIC_DRAW))
           //3.打开读取通道.
            /*
             (1)在iOS中, 默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的.
             意味着,顶点数据在着色器端(服务端)是不可用的. 即使你已经使用glBufferData方法,将顶点数据从内存拷贝到顶点缓存区中(GPU显存中).
             所以, 必须由glEnableVertexAttribArray 方法打开通道.指定访问属性.才能让顶点着色器能够访问到从CPU复制到GPU的数据.
             注意: 数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。
           
            (2)方法简介
            glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
           
            功能: 上传顶点数据到显存的方法(设置合适的方式从buffer里面读取数据)
            参数列表:
                index,指定要修改的顶点属性的索引值,例如
                size, 每次读取数量。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a),纹理则是2个.)
                type,指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。
                normalized,指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)
                stride,指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0
                ptr指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0
             */
            
            glEnableVertexAttribArray(GLuint(GLKVertexAttrib.position.rawValue))
            glVertexAttribPointer(GLuint(GLKVertexAttrib.position.rawValue), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 5), UnsafeRawPointer(bitPattern: 0))
            //
            glEnableVertexAttribArray(GLuint(GLKVertexAttrib.texCoord0.rawValue))
            glVertexAttribPointer(GLuint(GLKVertexAttrib.texCoord0.rawValue), 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 5), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 3))
            
        }
    
        func setImage() {
            
            guard  let imagePath = Bundle.main.path(forResource: "timg", ofType: "jpeg", inDirectory: nil),
                   let image = UIImage(contentsOfFile: imagePath)?.cgImage
            else {
                return
                
            }
            let texture = try? GLKTextureLoader.texture(with: image, options: [GLKTextureLoaderOriginBottomLeft:true,GLKTextureLoaderGrayscaleAsAlpha:true,GLKTextureLoaderApplyPremultiplication:true])
            effect = GLKBaseEffect()
            if let textureInfo = texture{
                effect.texture2d0.enabled = GLboolean(GL_TRUE)
                effect.texture2d0.name = textureInfo.name
            }
            
            
            
        }
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            //present(GLKViewController(), animated: true, completion: nil)
        }
        
        deinit {
            glDeleteBuffers(1, &bufferID)
        }
    }
    //绘制视图的内容
    /*
     GLKView对象使其OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES呈现命令的目标。然后,委托方法应该绘制视图的内容。
    */
    @available(*, deprecated, message: "ios13")
    extension ViewController :GLKViewDelegate{
        
        func glkView(_ view: GLKView, drawIn rect: CGRect) {
            
            glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
            effect.prepareToDraw()
            
            glDrawArrays(GLenum(GL_TRIANGLES), 0, 6)
            
            
        }
        
        
    }
  • 相关阅读:
    C#遍历List并删除某个或者几个元素的方法
    7月清北学堂培训 Day 4
    7月清北学堂培训 Day 3
    7月清北学堂培训 Day 2
    7月清北学堂培训 Day 1
    P1383 高级打字机
    P2401 不等数列
    P1412 经营与开发
    P1314 聪明的质监员
    2019.7.9 校内测试 T3 15数码问题
  • 原文地址:https://www.cnblogs.com/duzhaoquan/p/12890273.html
Copyright © 2011-2022 走看看