iOS-OpenGLES-入门-三角形

2020-06-10  本文已影响0人  秋叶红90

定点着色器文件: 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"))
    }
}

上一篇下一篇

猜你喜欢

热点阅读