GLSL(OpenGL Shading Language)
- 类型
类型 |
说明 |
void |
空类型 |
bool |
布尔类型 |
int |
有符号整型 |
vec2, vec3, vec4 |
二维,三维,四维浮点型向量 |
bvec2, bvec3, bvec4 |
二维,三维,四维布尔型向量 |
mat2, mat3, mat4 |
二维,三维,四维浮点型矩阵 |
sampler1D, sampler2D, sampler3D |
一维,二维,三维纹理 |
- 变量修饰符
修饰符 |
说明 |
attribute |
全局、只读,只能存在于vertex shader中使用,一般用于修饰顶点、法线、颜色、纹理等数据 |
uniform |
全局、只读,由外部程序传递给vertex shader、fragment shader变量,一般用于修饰视图矩阵、投影矩阵、光源信息等环境数据 |
varying |
用于在vertex shader和fragment shader中传递值 |
使用GLSL
- 设置上下文
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) // 设置当前上下文
- 着色器程序
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)
}
}
- 设置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)
}
- 设置投影矩阵和模型视图矩阵然后渲染
// 投影矩阵
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源码地址
网友评论