[OpenGL ES] - GLSL

GLSL(OpenGL Shading Language)

  1. 類(lèi)型
類(lèi)型 說(shuō)明
void 空類(lèi)型
bool 布爾類(lèi)型
int 有符號(hào)整型
vec2, vec3, vec4 二維,三維,四維浮點(diǎn)型向量
bvec2, bvec3, bvec4 二維,三維,四維布爾型向量
mat2, mat3, mat4 二維,三維,四維浮點(diǎn)型矩陣
sampler1D, sampler2D, sampler3D 一維,二維,三維紋理
  1. 變量修飾符
修飾符 說(shuō)明
attribute 全局、只讀,只能存在于vertex shader中使用,一般用于修飾頂點(diǎn)、法線、顏色、紋理等數(shù)據(jù)
uniform 全局、只讀,由外部程序傳遞給vertex shader、fragment shader變量,一般用于修飾視圖矩陣、投影矩陣、光源信息等環(huán)境數(shù)據(jù)
varying 用于在vertex shader和fragment shader中傳遞值

使用GLSL

  1. 設(shè)置上下文
        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) // 設(shè)置當(dāng)前上下文
  1. 著色器程序
vertexShader.glsl
uniform highp mat4 u_ModelViewMatrix; // 模型視圖矩陣
uniform highp mat4 u_ProjectionMatrix;  // 投影矩陣

attribute vec4 a_Position;   // 頂點(diǎn)坐標(biāo)
attribute vec4 a_Color;  // 顏色坐標(biāo)
attribute vec2 a_TexCoord;  // 紋理坐標(biāo)

varying lowp vec4 frag_Color;   // 傳遞到片元著色器的顏色坐標(biāo)
varying lowp vec2 frag_TexCoord; // 傳遞到片元著色器的紋理坐標(biāo)

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)
            // 根據(jù)類(lèi)型創(chuàng)建一個(gè)shader
            let shaderHandle = glCreateShader(shaderType)
            var shaderStringLength:GLint = GLint(Int32(shaderString.length))
            var shaderCString = shaderString.utf8String
            /// 將shader源碼附加帶shader對(duì)象上
            ///
            /// - Parameters:
            ///   - shader: shader對(duì)象
            ///   - count: 源碼字符串個(gè)數(shù)
            ///   - string: 源碼字符串
            ///   - length: 源碼字符串長(zhǎng)度
            glShaderSource(shaderHandle, GLsizei(1), &shaderCString, &shaderStringLength)
            
            // 編譯shader
            glCompileShader(shaderHandle)
            var compileStatus : GLint = 0
            // 獲取編譯狀態(tài)
            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)
                // 創(chuàng)建char數(shù)組
                let info : [GLchar] = Array(repeating: GLchar(0), count: Int(bufferLength))
                var actualLength : GLsizei = 0
                // 獲取錯(cuò)誤信息
                glGetShaderInfoLog(shaderHandle, bufferLength, &actualLength, UnsafeMutablePointer(mutating: info))
                NSLog(String(validatingUTF8: info)!)
                exit(1)
            }
            
            return shaderHandle
            
        } catch {
            exit(1)
        }
    }
    // 將頂點(diǎn)著色器和片元著色器編譯后附加到程序中然后鏈接程序
    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.創(chuàng)建程序
        self.program = glCreateProgram()
        // 3.將shader附加到程序中
        glAttachShader(program, vertexShader)
        glAttachShader(program, fragmentShader)
        
        glBindAttribLocation(program, VertexAttributes.position.rawValue, "a_Position") // 頂點(diǎn)坐標(biāo)屬性
        glBindAttribLocation(program, VertexAttributes.color.rawValue, "a_Color") // 顏色坐標(biāo)屬性
        glBindAttribLocation(program, VertexAttributes.texCoord.rawValue, "a_TexCoord") // 紋理坐標(biāo)屬性
        // 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
        // 獲取鏈接狀態(tài)
        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. 設(shè)置VAO
    func setupVAO() {
        // 申請(qǐng)vao空間
        glGenVertexArraysOES(1, &vao)
        glBindVertexArrayOES(vao)
        // 頂點(diǎn)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))
        // 頂點(diǎn)坐標(biāo)
        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)
        // 顏色坐標(biāo)
        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)
        // 紋理坐標(biāo)
        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. 設(shè)置投影矩陣和模型視圖矩陣然后渲染
    // 投影矩陣
    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()
        // 準(zhǔn)備繪制
        self.prepareToDraw()
        // render
        glBindVertexArrayOES(vao)
        glDrawElements(GLenum(GL_TRIANGLES), GLsizei(indexList.count), GLenum(GL_UNSIGNED_B
    }

結(jié)尾

DEMO源碼地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容