GLSL(OpenGL Shading Language)
- 類型
類型 |
說明 |
void |
空類型 |
bool |
布爾類型 |
int |
有符號(hào)整型 |
vec2, vec3, vec4 |
二維,三維,四維浮點(diǎn)型向量 |
bvec2, bvec3, bvec4 |
二維结榄,三維暮的,四維布爾型向量 |
mat2, mat3, mat4 |
二維,三維廷支,四維浮點(diǎn)型矩陣 |
sampler1D, sampler2D, sampler3D |
一維,二維,三維紋理 |
- 變量修飾符
修飾符 |
說明 |
attribute |
全局森爽、只讀,只能存在于vertex shader中使用嚣镜,一般用于修飾頂點(diǎn)爬迟、法線、顏色菊匿、紋理等數(shù)據(jù) |
uniform |
全局雕旨、只讀扮匠,由外部程序傳遞給vertex shader、fragment shader變量凡涩,一般用于修飾視圖矩陣棒搜、投影矩陣、光源信息等環(huán)境數(shù)據(jù) |
varying |
用于在vertex shader和fragment shader中傳遞值 |
使用GLSL
- 設(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)前上下文
- 著色器程序
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ù)類型創(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)
}
}
- 設(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)
}
- 設(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源碼地址