当前位置:   article > 正文

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

gles shader 混合

使用语言是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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

片元着色器

文件名: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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

设置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()
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

准备工作与绘制

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()
        //        }
        
        
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225

生成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
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/574024
推荐阅读
相关标签
  

闽ICP备14008679号