美文网首页
[OpenGL ES] - GLSL

[OpenGL ES] - GLSL

作者: coder_xiaoyu | 来源:发表于2018-05-11 14:57 被阅读0次

    GLSL(OpenGL Shading Language)

    1. 类型
    类型 说明
    void 空类型
    bool 布尔类型
    int 有符号整型
    vec2, vec3, vec4 二维,三维,四维浮点型向量
    bvec2, bvec3, bvec4 二维,三维,四维布尔型向量
    mat2, mat3, mat4 二维,三维,四维浮点型矩阵
    sampler1D, sampler2D, sampler3D 一维,二维,三维纹理
    1. 变量修饰符
    修饰符 说明
    attribute 全局、只读,只能存在于vertex shader中使用,一般用于修饰顶点、法线、颜色、纹理等数据
    uniform 全局、只读,由外部程序传递给vertex shader、fragment shader变量,一般用于修饰视图矩阵、投影矩阵、光源信息等环境数据
    varying 用于在vertex shader和fragment shader中传递值

    使用GLSL

    1. 设置上下文
            self.glkView = self.view as! GLKView
            
            self.context = EAGLContext.init(api: .openGLES2)
            if context == nil {
                context = EAGLContext.init(api: .openGLES2)
            }
            
            guard let ctx = context else {
                return
            }
            EAGLContext.setCurrent(ctx) // 设置当前上下文
    
    1. 着色器程序
    vertexShader.glsl
    uniform highp mat4 u_ModelViewMatrix; // 模型视图矩阵
    uniform highp mat4 u_ProjectionMatrix;  // 投影矩阵
    
    attribute vec4 a_Position;   // 顶点坐标
    attribute vec4 a_Color;  // 颜色坐标
    attribute vec2 a_TexCoord;  // 纹理坐标
    
    varying lowp vec4 frag_Color;   // 传递到片元着色器的颜色坐标
    varying lowp vec2 frag_TexCoord; // 传递到片元着色器的纹理坐标
    
    void main(void) {
        frag_Color = a_Color;
        frag_TexCoord = a_TexCoord;
        gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * a_Position;
    }
    
    fragmentShader.glsl
    uniform sampler2D u_Texture;  // 2D纹理
    
    varying lowp vec4 frag_Color;
    varying lowp vec2 frag_TexCoord;
    
    void main(void) {
        gl_FragColor = texture2D(u_Texture, frag_TexCoord);
    }
    

    2.1 编译着色器程序

        // 编译着色器
        func compileShader(_ shaderName:String, shaderType:GLenum) ->GLuint {
            // shader file path
            let path = Bundle.main.path(forResource: shaderName, ofType: nil)
            do {
                // shader file content string
                let shaderString = try NSString(contentsOfFile: path!, encoding: String.Encoding.utf8.rawValue)
                // 根据类型创建一个shader
                let shaderHandle = glCreateShader(shaderType)
                var shaderStringLength:GLint = GLint(Int32(shaderString.length))
                var shaderCString = shaderString.utf8String
                /// 将shader源码附加带shader对象上
                ///
                /// - Parameters:
                ///   - shader: shader对象
                ///   - count: 源码字符串个数
                ///   - string: 源码字符串
                ///   - length: 源码字符串长度
                glShaderSource(shaderHandle, GLsizei(1), &shaderCString, &shaderStringLength)
                
                // 编译shader
                glCompileShader(shaderHandle)
                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)
                    // 创建char数组
                    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)!)
                    exit(1)
                }
                
                return shaderHandle
                
            } catch {
                exit(1)
            }
        }
    
        // 将顶点着色器和片元着色器编译后附加到程序中然后链接程序
        func compile(vertexShader: String, fragmentShader: String) {
            // 1.编译着色器
            let vertexShader = self.compileShader(vertexShader, shaderType: GLenum(GL_VERTEX_SHADER))
            let fragmentShader = self.compileShader(fragmentShader, shaderType: GLenum(GL_FRAGMENT_SHADER))
            
            // 2.创建程序
            self.program = glCreateProgram()
            // 3.将shader附加到程序中
            glAttachShader(program, vertexShader)
            glAttachShader(program, fragmentShader)
            
            glBindAttribLocation(program, VertexAttributes.position.rawValue, "a_Position") // 顶点坐标属性
            glBindAttribLocation(program, VertexAttributes.color.rawValue, "a_Color") // 颜色坐标属性
            glBindAttribLocation(program, VertexAttributes.texCoord.rawValue, "a_TexCoord") // 纹理坐标属性
            // 4.链接
            glLinkProgram(program)
            
            self.modelViewMatrixUniform = glGetUniformLocation(program, "u_ModelViewMatrix") // 模型视图矩阵
            self.projectionMatrixUniform = glGetUniformLocation(program, "u_ProjectionMatrix") // 投影矩阵
            self.textureUniform = glGetUniformLocation(program, "u_Texture") // 纹理
            
            var linkStatus : GLint = 0
            // 获取链接状态
            glGetProgramiv(self.program, GLenum(GL_LINK_STATUS), &linkStatus)
            if linkStatus == GL_FALSE {
                var infoLength : GLsizei = 0
                let bufferLength : GLsizei = 1024
                glGetProgramiv(self.program, GLenum(GL_INFO_LOG_LENGTH), &infoLength)
                
                let info : [GLchar] = Array(repeating: GLchar(0), count: Int(bufferLength))
                var actualLength : GLsizei = 0
                
                glGetProgramInfoLog(self.program, bufferLength, &actualLength, UnsafeMutablePointer(mutating: info))
                NSLog(String(validatingUTF8: info)!)
                exit(1)
            }
        }
    
    1. 设置VAO
        func setupVAO() {
            // 申请vao空间
            glGenVertexArraysOES(1, &vao)
            glBindVertexArrayOES(vao)
            // 顶点buffer
            var vertexBuffer: GLuint = 0
            glGenBuffers(1, &vertexBuffer)
            glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
            glBufferData(GLenum(GL_ARRAY_BUFFER), vertexs.size(), vertexs, GLenum(GL_STATIC_DRAW))
            // 索引buffer
            var indexBuffer: GLuint = 0
            glGenBuffers(1, &indexBuffer)
            glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexBuffer)
            glBufferData(GLenum(GL_ELEMENT_ARRAY_BUFFER), indexList.size(), indexList, GLenum(GL_STATIC_DRAW))
            // 顶点坐标
            let positionSlotFirstComponent = UnsafePointer<Int>(bitPattern: 0)
            glEnableVertexAttribArray(VertexAttributes.position.rawValue)
            glVertexAttribPointer(VertexAttributes.position.rawValue, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<Vertex>.size), positionSlotFirstComponent)
            // 颜色坐标
            let colorSlotFirstComponent = UnsafePointer<Int>(bitPattern: MemoryLayout<GLfloat>.size * 3)
            glEnableVertexAttribArray(VertexAttributes.color.rawValue)
            glVertexAttribPointer(VertexAttributes.color.rawValue, 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<Vertex>.size), colorSlotFirstComponent)
            // 纹理坐标
            let texSlotFirstComponent = UnsafePointer<Int>(bitPattern: MemoryLayout<GLfloat>.size * 7)
            glEnableVertexAttribArray(VertexAttributes.texCoord.rawValue)
            glVertexAttribPointer(VertexAttributes.texCoord.rawValue, 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<Vertex>.size), texSlotFirstComponent)
            
            glBindVertexArrayOES(0)
            glBindBuffer(GLenum(GL_ARRAY_BUFFER), 0)
            glBindBuffer(GLenum(GL_ELEMENT_ARRAY_BUFFER), 0)
            
        }
    
    1. 设置投影矩阵和模型视图矩阵然后渲染
        // 投影矩阵
        self.projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(85.0),GLfloat(self.view.bounds.size.width / self.view.bounds.size.height),1,150)
        // 模型矩阵
        func modelMatrix() -> GLKMatrix4 {
            var modelMatrix : GLKMatrix4 = GLKMatrix4Identity
            modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, self.position.z)
            modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotationX, 1, 0, 0)
            modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotationY, 0, 1, 0)
            modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotationZ, 0, 0, 1)
            modelMatrix = GLKMatrix4Scale(modelMatrix, self.scale, self.scale, self.scale)
            return modelMatrix
        }
        // 渲染
        override func glkView(_ view: GLKView, drawIn rect: CGRect) {
            
            glClearColor(1.0, 1.0, 1.0, 1.0)
            glClear(GLbitfield(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
            
            glEnable(GLenum(GL_DEPTH_TEST))
            // 模型矩阵
            self.modelViewMatrix = modelMatrix()
            // 准备绘制
            self.prepareToDraw()
            // render
            glBindVertexArrayOES(vao)
            glDrawElements(GLenum(GL_TRIANGLES), GLsizei(indexList.count), GLenum(GL_UNSIGNED_B
        }
    

    结尾

    DEMO源码地址

    相关文章

      网友评论

          本文标题:[OpenGL ES] - GLSL

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