OpenGLES初探(五)GLSL使用索引绘图并开启颜色和图片混合

使用语言是Swift
效果图:
在这里插入图片描述

步骤

与绘制图片的步骤基本一致,所以引用了上一篇文章中步骤图。
在这里插入图片描述

自定义顶点着色器和片元着色器

顶点着色器

文件名:shaderv.glsl


attribute vec4 position;
attribute vec4 positionColor;
attribute vec2 textCoordinate;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

varying lowp vec4 varyColor;
varying lowp vec2 varyTextCoord;

void main(){
    
    varyColor = positionColor;
    varyTextCoord = textCoordinate;
    
    vec4 vpos;
    vpos = projectionMatrix * modelViewMatrix * position;
    
    gl_Position = vpos;
}

片元着色器

文件名:shaderf.glsl

precision highp float;
varying lowp vec4 varyColor;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;

void main(){
    vec4 weakMask = texture2D(colorMap,varyTextCoord);
    vec4 weak = varyColor;
    float alpha = 0.5;
    
    vec4 tempColor = weak * (1.0 - alpha) + weakMask * alpha;
    gl_FragColor = tempColor;
}

设置View

属性与定时器

class meView: UIView {

   
    fileprivate var meLayer : CAEAGLLayer!
    fileprivate var meContext : EAGLContext!
    
    fileprivate var meColorReaderBuffer : GLuint = GLuint()
    fileprivate var meColorFrameBuffer : GLuint = GLuint()
    
    fileprivate var meProgram : GLuint = GLuint()
    fileprivate var meVertices : GLuint = GLuint()
    
    fileprivate var xDegree : Float = 0.0
    fileprivate var yDegree : Float = 0.0
    fileprivate var zDegree : Float = 0.0
    
    fileprivate var bX :Bool = false
    fileprivate var bY :Bool = false
    fileprivate var bZ :Bool = false
    
    fileprivate var timer: Timer?
    
    override class var layerClass : AnyClass{
        return CAEAGLLayer.self
    }
    
    override func layoutSubviews() {
        self.setupLayer()
        self.setContext()
        self.setClearBuffer()
        self.setReaderBuffer()
        self.setFrameBuffer()
        self.renderLayer()
    }
    
    @IBAction func clickX(_ sender: Any) {
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true)
        }
        
        bX = !bX
        
    }
    @IBAction func clickY(_ sender: Any) {
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true)
        }
        
        bY = !bY
    }
    @IBAction func clickZ(_ sender: Any) {
        if timer == nil {
            timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true)
        }
        
        bZ = !bZ
    }
    
    @objc private func reDegree(){
        xDegree += (bX ? 1 : 0) * 0.5
        yDegree += (bY ? 1 : 0) * 0.5
        zDegree += (bZ ? 1 : 0) * 0.5
        self.renderLayer()
    }
}

准备工作与绘制

extension meView{
    //1、创建图层
    fileprivate func setupLayer(){
        
        self.meLayer = self.layer as? CAEAGLLayer
        guard self.meLayer != nil else {
            return
        }
        
        self.contentScaleFactor = UIScreen.main.scale
        
        self.meLayer.drawableProperties = [kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8,kEAGLDrawablePropertyRetainedBacking: false]
    }
    //        2、创建上下文
    fileprivate func setContext(){
        
        let context = EAGLContext(api: .openGLES3)
        guard EAGLContext.setCurrent(context) else {
            return
        }
        
        self.meContext = context!
    }
    //        3、清空缓存区
    fileprivate func setClearBuffer(){
        
        glDeleteBuffers(1, &meColorFrameBuffer)
        self.meColorFrameBuffer = 0
        
        glDeleteBuffers(1, &meColorReaderBuffer)
        self.meColorReaderBuffer = 0
    }
    //        4、设置RenderBuffer
    fileprivate func setReaderBuffer(){
        
        var buffer : GLuint = GLuint()
        glGenRenderbuffers(1, &buffer)
        self.meColorReaderBuffer = buffer
        
        glBindRenderbuffer(GLenum(GL_RENDERBUFFER), self.meColorReaderBuffer)
        meContext.renderbufferStorage(Int(GL_RENDERBUFFER), from: self.meLayer)
    }
    //        5、设置FrameBuffer
    fileprivate func setFrameBuffer(){
        
        var buffer : GLuint = GLuint()
        glGenFramebuffers(1, &buffer)
        self.meColorFrameBuffer = buffer
        
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), self.meColorFrameBuffer)
        glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), self.meColorReaderBuffer)
        
    }
    //        6、开始绘制
    fileprivate func renderLayer(){
        
        glClearColor(1, 0.9, 0.4, 1)
        glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
        //
        let scale = UIScreen.main.scale
        glViewport(GLint(self.frame.origin.x), GLint(self.frame.origin.y), GLsizei(self.frame.size.width * scale), GLsizei(self.frame.size.height * scale))
        
        let vertFile = Bundle.main.path(forResource: "shaderv", ofType: "glsl") ?? ""
        let fragFile = Bundle.main.path(forResource: "shaderf", ofType: "glsl") ?? ""
        
        print("vertFile: \(vertFile)")
        print("fragFile: \(fragFile)")
        
        guard let program = self.loaderShader(vertFile, fragFile) else {
            print("program is nil")
            return
        }
        //
        self.meProgram = program
        glLinkProgram(self.meProgram)
        var linkStatus = GLint()
        glGetProgramiv(self.meProgram, GLenum(GL_LINK_STATUS), &linkStatus)
        if linkStatus == GLint(GL_FALSE){
            let count = 1024
            let message = UnsafeMutablePointer<GLchar>.allocate(capacity: count)
            message.initialize(repeating: GLchar(0), count: count)
            
            glGetProgramInfoLog(self.meProgram, GLsizei(MemoryLayout<GLchar>.size * count), nil, message)
            
            defer{
                message.deinitialize(count: count)
                message.deallocate()
            }
            print("error:\(message)")
            return
        }
        glUseProgram(self.meProgram)
        
        let attArr : [GLfloat] = [
            -0.5, 0.5, 0.0,      1.0, 0.0, 1,0.5,      0.0,1.0, //左上0
            0.5, 0.5, 0.0,       1.0, 0.0, 1,0.5,      1.0,1.0,//右上1
            -0.5, -0.5, 0.0,     1.0, 1.0, 1,0.5,      0.0,0.0, //左下2

            0.5, -0.5, 0.0,      1.0, 1.0, 1,0.5,      1.0,0.0,//右下3
            0.0, 0.0, 1.0,       0.0, 1.0, 1,0.5,      0.5,1.0,//顶点4
        ]

        
        let indices : [GLuint] = [
            0, 3, 2,
            0, 1, 3,
            0, 2, 4,
            0, 4, 1,
            2, 3, 4,
            1, 4, 3,
        ]
        
        if self.meVertices == 0{
            glGenBuffers(1, &self.meVertices)
        }
        
        glBindBuffer(GLenum(GL_ARRAY_BUFFER), self.meVertices)
        glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size*attArr.count, attArr, GLenum(GL_DYNAMIC_DRAW))
        
        let position = glGetAttribLocation(self.meProgram, "position")
        glEnableVertexAttribArray(GLuint(position))
        glVertexAttribPointer(GLuint(position), GLint(3), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer.init(bitPattern: 0))
        
        
        let positionColor = glGetAttribLocation(self.meProgram, "positionColor")
        glEnableVertexAttribArray(GLuint(positionColor))
        glVertexAttribPointer(GLuint(positionColor), GLint(4), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 3))

        
        
        let textCoordinate = glGetAttribLocation(self.meProgram, "textCoordinate")
        glEnableVertexAttribArray(GLuint(textCoordinate))
        glVertexAttribPointer(GLuint(textCoordinate), GLint(2), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 7))

        let projectionMatrix = glGetUniformLocation(self.meProgram, "projectionMatrix")
        let modelViewMatrix = glGetUniformLocation(self.meProgram, "modelViewMatrix")

        let width: Float = Float(self.frame.size.width)
        let height: Float = Float(self.frame.size.height)
        let aspect = width / height

        var _projectionMatrix : GLKMatrix4 = GLKMatrix4Identity
        
        _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(35), aspect, 1, 200)

        let count = MemoryLayout.size(ofValue: _projectionMatrix.m) / MemoryLayout.size(ofValue: _projectionMatrix.m.0)
        withUnsafePointer(to: &_projectionMatrix.m) { (pointer)  in
            pointer.withMemoryRebound(to: GLfloat.self, capacity: count, { (pon) in
                glUniformMatrix4fv((projectionMatrix), GLsizei(1), GLboolean(GL_FALSE), pon)
            })
        }

        var _modelViewMatrix = GLKMatrix4Identity,_rotationMatrix = GLKMatrix4Identity
        _modelViewMatrix = GLKMatrix4Translate(_modelViewMatrix, 0, 0, -10.0)

        _rotationMatrix = GLKMatrix4RotateX(_rotationMatrix, xDegree)
        _rotationMatrix = GLKMatrix4RotateY(_rotationMatrix, yDegree)
        _rotationMatrix = GLKMatrix4RotateZ(_rotationMatrix, zDegree)

        _modelViewMatrix = GLKMatrix4Multiply(_modelViewMatrix,_rotationMatrix )
        

        let modelCount = MemoryLayout.size(ofValue: _modelViewMatrix.m) / MemoryLayout.size(ofValue: _modelViewMatrix.m.0)
        withUnsafePointer(to: &_modelViewMatrix.m) { (pointer)  in
            pointer.withMemoryRebound(to: GLfloat.self, capacity: modelCount, { (pon)  in
                glUniformMatrix4fv((modelViewMatrix), GLsizei(1), GLboolean(GL_FALSE), pon)
            })
        }
        
//        glEnable(GLenum(GL_DEPTH_TEST))
        glEnable(GLenum(GL_CULL_FACE))
        glEnable(GLenum(GL_BLEND))
        glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA));
        
        self.setupTexture("108")
        
        glDrawElements(GLenum(GL_TRIANGLES), GLsizei(MemoryLayout<GLuint>.size*indices.count / MemoryLayout<GLuint>.size), GLenum(GL_UNSIGNED_INT), indices)
        self.meContext.presentRenderbuffer(Int(GL_RENDERBUFFER))
        
    }
    //加载纹理
    fileprivate func setupTexture(_ fileName: String){
        
        guard let image = UIImage(named: fileName)?.cgImage else {
            print("image is nil")
            return
        }
        
        let height = image.height
        let width = image.width
        
        let count = MemoryLayout<GLubyte>.size * height * width * 4
        let spriteData = UnsafeMutablePointer<GLubyte>.allocate(capacity: count)
        
        UIGraphicsBeginImageContext(CGSize(width: width, height: height))
        
        let spriteContext = CGContext(data: spriteData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: image.colorSpace!, bitmapInfo: image.bitmapInfo.rawValue)
        
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        spriteContext?.translateBy(x: rect.origin.x, y: rect.origin.y)
        spriteContext?.translateBy(x: 0, y: rect.size.height)
        spriteContext?.scaleBy(x: 1, y: -1)
        spriteContext?.translateBy(x: -rect.origin.x, y: -rect.origin.y)
        spriteContext?.draw(image, in: rect)
        
        UIGraphicsEndImageContext()
        
        glBindTexture(GLenum(GL_TEXTURE_2D), 0)
        
        glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR)
        glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR)
        glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GLint(GL_CLAMP_TO_EDGE))
        glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GLint(GL_CLAMP_TO_EDGE))
        
        glTexImage2D(GLenum(GL_TEXTURE_2D), GLint(0), GLint(GL_RGBA), GLsizei(width), GLsizei(height), GLint(0), GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), spriteData)
        
        free(spriteData)
        //        defer {
        //            spriteData.deinitialize(count: count)
        //            spriteData.deallocate()
        //        }
        
        
    }
}

生成shander program

extension meView{
    
    fileprivate func loaderShader(_ vert : String, _ frag : String) -> GLuint?{
        
        let programe : GLuint = glCreateProgram();
        
        guard let vertShader = compileShader(GLenum(GL_VERTEX_SHADER), vert) else {
            
            print("顶点着色器获取为空")
            return nil
        }
        
        guard let frag = self.compileShader(GLenum(GL_FRAGMENT_SHADER), frag) else{
            print("片元着色器为空")
            return nil
        }
        
        glAttachShader(programe, vertShader)
        glAttachShader(programe, frag)
        
        glDeleteShader(vertShader)
        glDeleteShader(frag)
        
        return programe
    }
    
    fileprivate func compileShader(_ type : GLenum, _ file : String) -> GLuint?{
        
        let shader = glCreateShader(type)
        
        guard let fileContent = try? String(contentsOfFile: file, encoding: .utf8) else {
            print("文件读取为空")
            return nil
        }
        
        fileContent.withCString { (str)  in
            var pon : UnsafePointer<GLchar>? = str
            glShaderSource(shader, 1, &pon, nil)
        }
        
        glCompileShader(shader)
        
        return shader
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值