美文网首页
iOS-OpenGLES-入门-三角形

iOS-OpenGLES-入门-三角形

作者: 秋叶红90 | 来源:发表于2020-06-10 01:22 被阅读0次

    定点着色器文件: shaderv.glsl
    attribute vec4 vPosition;
    attribute vec4 a_Color;需要传值过去

    attribute vec4 vPosition;
    attribute vec4 a_Color;
    
    varying lowp vec4 frag_Color;
    void main(void)
    {
        frag_Color = a_Color;
        gl_Position = vPosition;
    }
    
    

    片段着色器 shaderf.glsl

    varying lowp vec4 frag_Color;
    
    void main()
    {
        gl_FragColor = frag_Color;
    }
    
    

    写一个工具加载成字符串将 上面两文件
    GLESUtils.swift

    //
    //  GLESUtils.swift
    //  OpenGL-ES-04
    //
    //  Created by mkil on 2019/1/10.
    //  Copyright © 2019 黎宁康. All rights reserved.
    //
    
    import Foundation
    import OpenGLES
    
    struct GLESUtils {
        
        static func loadShaderFile(type:GLenum, fileName:String) -> GLuint {
            guard let path = Bundle.main.path(forResource: fileName, ofType: nil) else {
                print("Error: file does not exist !")
                return 0;
            }
            
            do {
                let shaderString = try String(contentsOfFile: path, encoding: .utf8)
                return GLESUtils.loadShaderString(type: type, shaderString: shaderString)
            } catch {
                print("Error: loading shader file: \(path)")
                return 0;
            }
        }
        
        static func loadShaderString(type:GLenum, shaderString:String) ->GLuint {
            // 创建着色器对象
            let shaderHandle = glCreateShader(type)
            
            var shaderStringLength: GLint = GLint(Int32(shaderString.count))
            var shaderCString = NSString(string: shaderString).utf8String
            
            /* 把着色器源码附加到着色器对象上
             glShaderSource(shader: GLuint, count: GLsizei, String: UnsafePointer<UnsafePointer<GLchar>?>!, length: UnsafePointer<GLint>!)
             shader: 着色器对象
             count:指定要传递的源码字符串数量,这里只有一个
             String:着色器源码
             length:源码长度
             */
            glShaderSource(shaderHandle, GLsizei(1), &shaderCString, &shaderStringLength)
            
            // 编译着色器
            glCompileShader(shaderHandle)
            
            // 编译是否成功的状态 GL_FALSE GL_TRUE
            var compileStatus: GLint = 0
            // 获取编译状态
            glGetShaderiv(shaderHandle, GLenum(GL_COMPILE_STATUS), &compileStatus)
            
            if compileStatus == GL_FALSE {
                var infoLength: GLsizei = 0
                let bufferLength: GLsizei = 1024
                glGetShaderiv(shaderHandle, GLenum(GL_INFO_LOG_LENGTH), &infoLength)
                
                let info: [GLchar] = Array(repeating: GLchar(0), count: Int(bufferLength))
                var actualLength: GLsizei = 0
                
                // 获取错误消息
                glGetShaderInfoLog(shaderHandle, bufferLength, &actualLength, UnsafeMutablePointer(mutating: info))
                NSLog(String(validatingUTF8: info)!)
                print("Error: Colourer Compilation Failure: \(String(validatingUTF8: info) ?? "")")
                return 0
            }
            
            return shaderHandle
        }
        
        static func loanProgram(verShaderFileName:String,fragShaderFileName:String) -> GLuint {
            
            let vertexShader = GLESUtils.loadShaderFile(type: GLenum(GL_VERTEX_SHADER), fileName: verShaderFileName)
            
            if vertexShader == 0 {return 0}
            
            let fragmentShader = GLESUtils.loadShaderFile(type: GLenum(GL_FRAGMENT_SHADER), fileName: fragShaderFileName)
            
            if fragmentShader == 0 {
                glDeleteShader(vertexShader)
                return 0
            }
            
            // 创建着色器程序对象
            let programHandel = glCreateProgram()
            
            if programHandel == 0 {return 0}
            
            // 将着色器附加到程序上
            glAttachShader(programHandel, vertexShader)
            glAttachShader(programHandel, fragmentShader)
            
            // 链接着色器程序
            glLinkProgram(programHandel)
            
            // 获取链接状态
            var linkStatus: GLint = 0
            glGetProgramiv(programHandel, GLenum(GL_LINK_STATUS), &linkStatus)
            if linkStatus == GL_FALSE {
                var infoLength: GLsizei = 0
                let bufferLenght: GLsizei = 1024
                glGetProgramiv(programHandel, GLenum(GL_INFO_LOG_LENGTH), &infoLength)
                
                let info: [GLchar] = Array(repeating: GLchar(0), count: Int(bufferLenght))
                var actualLenght: GLsizei = 0
                
                // 获取错误消息
                glGetProgramInfoLog(programHandel, bufferLenght, &actualLenght, UnsafeMutablePointer(mutating: info))
                print("Error: Colorer Link Failed: \(String(validatingUTF8: info) ?? "")")
                return 0
            }
            
            // 释放资源
            glDeleteShader(vertexShader)
            glDeleteShader(fragmentShader)
            
            return programHandel
        }
        
        static func createVBO(_ target:GLenum, _ usage: Int, _ datSize: Int, data:UnsafeRawPointer!) ->GLuint {
            var vbo:GLuint = 0
            glGenBuffers(1, &vbo)
            glBindBuffer(target, vbo)
            glBufferData(target, datSize, data, GLenum(usage))
            return vbo
        }
        
    }
    
    

    写一个AGLKView 渲染出来

    //
    //  AGLKView.swift
    //  Tutorial-01-三角形
    //
    //  Created by mkil on 2019/1/24.
    //  Copyright © 2019 黎宁康. All rights reserved.
    //
    
    import UIKit
    
    class AGLKView: UIView {
        
        var myContext:EAGLContext?
        var myColorFrameBuffer:GLuint = 0
        var myColorRenderBuffer:GLuint = 0
        
        var myProgram:GLuint?
        
        var positionSlot:GLuint = 0
        var colorSlot:GLuint = 0
        
        // 只有CAEAGLLayer 类型的 layer 才支持 OpenGl 描绘
        override class var layerClass : AnyClass {
            return CAEAGLLayer.self
        }
        
        override func layoutSubviews() {
            setupLayer()
            setupContext()
            destoryRenderAndFrameBuffer()
            setupBuffer()
            setupProgram()
            
            render()
        }
    }
    
    extension AGLKView {
        
        fileprivate func render() {
            
            glClearColor(0, 1.0, 0, 1.0)
            glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
            
            glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
            
            let vertices: [GLfloat] = [
                0, 0.5, 0,
                -0.5, -0.5, 0,
                0.5, -0.5, 0
            ]
            
            let colors: [GLfloat] = [
                1, 0, 0, 1,
                0, 1, 0, 1,
                0, 0, 1, 1
            ]
            
            // 加载顶点数据
            glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, vertices )
            glEnableVertexAttribArray(positionSlot)
            
            // 加载颜色数据
            glVertexAttribPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, colors )
            glEnableVertexAttribArray(colorSlot)
            
            // 绘制
            glDrawArrays(GLenum(GL_TRIANGLES), 0, 3)
            
            myContext?.presentRenderbuffer(Int(GL_RENDERBUFFER))
        }
    }
    
    
    extension AGLKView {
        // 设置不透明,
        fileprivate func setupLayer() {
            let eagLayer = layer as? CAEAGLLayer
    
            // CALayer 默认是透明的,必须将它设为不透明才能让其可见
            eagLayer?.isOpaque = true
            // 设置描绘属性,在这里设置不维持渲染内容以及颜色格式为 RGBA8
            eagLayer?.drawableProperties = [kEAGLDrawablePropertyRetainedBacking:false,kEAGLDrawablePropertyColorFormat:kEAGLColorFormatRGBA8]
        }
        // 配置上下文
        fileprivate func setupContext() {
            // 指定 OpenGL 渲染 API 的版本,在这里我们使用 OpenGL ES 3.0
            myContext = EAGLContext(api: .openGLES3)
            
            if myContext == nil {
                print("Failed to initialize OpenGLES 3.0 context")
                return
            }
            // 设置为当前上下文
            if !EAGLContext.setCurrent(myContext) {
                print("Failed to set current OpenGL context")
                return
            }
        }
        /// 销毁已经存在的  buffer
        fileprivate func destoryRenderAndFrameBuffer() {
            //        当 UIView 在进行布局变化之后,由于 layer 的宽高变化,导致原来创建的 renderbuffer不再相符,我们需要销毁既有 renderbuffer 和 framebuffer。下面,我们依然创建私有方法 destoryRenderAndFrameBuffer 来销毁生成的 buffer
            glDeleteFramebuffers(1, &myColorFrameBuffer)
            myColorFrameBuffer = 0
            glDeleteRenderbuffers(1, &myColorRenderBuffer)
            myColorRenderBuffer = 0
        }
        
        /// buffer 初始化 渲染 frame buffer  装配
        fileprivate func setupBuffer() {
            var buffer:GLuint = 0
            glGenRenderbuffers(1, &buffer)
            myColorRenderBuffer = buffer
            glBindRenderbuffer(GLenum(GL_RENDERBUFFER), myColorRenderBuffer)
            // 为 颜色缓冲区 分配存储空间
            myContext?.renderbufferStorage(Int(GL_RENDERBUFFER), from: layer as? CAEAGLLayer)
            
            glGenFramebuffers(1, &buffer)
            myColorFrameBuffer = buffer
            // 设置为当前 framebuffer
            glBindFramebuffer(GLenum(GL_FRAMEBUFFER), myColorFrameBuffer)
            // 将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上
            glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), myColorRenderBuffer)
        }
        
        fileprivate func setupProgram() {
            myProgram = GLESUtils.loanProgram(verShaderFileName: "shaderv.glsl", fragShaderFileName: "shaderf.glsl")
            guard let myProgram = myProgram else {
                return
            }
            
            glUseProgram(myProgram)
        
            positionSlot = GLuint(glGetAttribLocation(myProgram, "vPosition"))
            colorSlot = GLuint(glGetAttribLocation(myProgram, "a_Color"))
        }
    }
    
    

    相关文章

      网友评论

          本文标题:iOS-OpenGLES-入门-三角形

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