赞
踩
使用语言是Swift
效果图:
与绘制图片的步骤基本一致,所以引用了上一篇文章中步骤图。
文件名:shaderv.glsl
attribute vec4 position; attribute vec4 positionColor; attribute vec2 textCoordinate; uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; varying lowp vec4 varyColor; varying lowp vec2 varyTextCoord; void main(){ varyColor = positionColor; varyTextCoord = textCoordinate; vec4 vpos; vpos = projectionMatrix * modelViewMatrix * position; gl_Position = vpos; }
文件名:shaderf.glsl
precision highp float;
varying lowp vec4 varyColor;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main(){
vec4 weakMask = texture2D(colorMap,varyTextCoord);
vec4 weak = varyColor;
float alpha = 0.5;
vec4 tempColor = weak * (1.0 - alpha) + weakMask * alpha;
gl_FragColor = tempColor;
}
class meView: UIView { fileprivate var meLayer : CAEAGLLayer! fileprivate var meContext : EAGLContext! fileprivate var meColorReaderBuffer : GLuint = GLuint() fileprivate var meColorFrameBuffer : GLuint = GLuint() fileprivate var meProgram : GLuint = GLuint() fileprivate var meVertices : GLuint = GLuint() fileprivate var xDegree : Float = 0.0 fileprivate var yDegree : Float = 0.0 fileprivate var zDegree : Float = 0.0 fileprivate var bX :Bool = false fileprivate var bY :Bool = false fileprivate var bZ :Bool = false fileprivate var timer: Timer? override class var layerClass : AnyClass{ return CAEAGLLayer.self } override func layoutSubviews() { self.setupLayer() self.setContext() self.setClearBuffer() self.setReaderBuffer() self.setFrameBuffer() self.renderLayer() } @IBAction func clickX(_ sender: Any) { if timer == nil { timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true) } bX = !bX } @IBAction func clickY(_ sender: Any) { if timer == nil { timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true) } bY = !bY } @IBAction func clickZ(_ sender: Any) { if timer == nil { timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(reDegree), userInfo: nil, repeats: true) } bZ = !bZ } @objc private func reDegree(){ xDegree += (bX ? 1 : 0) * 0.5 yDegree += (bY ? 1 : 0) * 0.5 zDegree += (bZ ? 1 : 0) * 0.5 self.renderLayer() } }
extension meView{ //1、创建图层 fileprivate func setupLayer(){ self.meLayer = self.layer as? CAEAGLLayer guard self.meLayer != nil else { return } self.contentScaleFactor = UIScreen.main.scale self.meLayer.drawableProperties = [kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8,kEAGLDrawablePropertyRetainedBacking: false] } // 2、创建上下文 fileprivate func setContext(){ let context = EAGLContext(api: .openGLES3) guard EAGLContext.setCurrent(context) else { return } self.meContext = context! } // 3、清空缓存区 fileprivate func setClearBuffer(){ glDeleteBuffers(1, &meColorFrameBuffer) self.meColorFrameBuffer = 0 glDeleteBuffers(1, &meColorReaderBuffer) self.meColorReaderBuffer = 0 } // 4、设置RenderBuffer fileprivate func setReaderBuffer(){ var buffer : GLuint = GLuint() glGenRenderbuffers(1, &buffer) self.meColorReaderBuffer = buffer glBindRenderbuffer(GLenum(GL_RENDERBUFFER), self.meColorReaderBuffer) meContext.renderbufferStorage(Int(GL_RENDERBUFFER), from: self.meLayer) } // 5、设置FrameBuffer fileprivate func setFrameBuffer(){ var buffer : GLuint = GLuint() glGenFramebuffers(1, &buffer) self.meColorFrameBuffer = buffer glBindFramebuffer(GLenum(GL_FRAMEBUFFER), self.meColorFrameBuffer) glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), self.meColorReaderBuffer) } // 6、开始绘制 fileprivate func renderLayer(){ glClearColor(1, 0.9, 0.4, 1) glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) // let scale = UIScreen.main.scale glViewport(GLint(self.frame.origin.x), GLint(self.frame.origin.y), GLsizei(self.frame.size.width * scale), GLsizei(self.frame.size.height * scale)) let vertFile = Bundle.main.path(forResource: "shaderv", ofType: "glsl") ?? "" let fragFile = Bundle.main.path(forResource: "shaderf", ofType: "glsl") ?? "" print("vertFile: \(vertFile)") print("fragFile: \(fragFile)") guard let program = self.loaderShader(vertFile, fragFile) else { print("program is nil") return } // self.meProgram = program glLinkProgram(self.meProgram) var linkStatus = GLint() glGetProgramiv(self.meProgram, GLenum(GL_LINK_STATUS), &linkStatus) if linkStatus == GLint(GL_FALSE){ let count = 1024 let message = UnsafeMutablePointer<GLchar>.allocate(capacity: count) message.initialize(repeating: GLchar(0), count: count) glGetProgramInfoLog(self.meProgram, GLsizei(MemoryLayout<GLchar>.size * count), nil, message) defer{ message.deinitialize(count: count) message.deallocate() } print("error:\(message)") return } glUseProgram(self.meProgram) let attArr : [GLfloat] = [ -0.5, 0.5, 0.0, 1.0, 0.0, 1,0.5, 0.0,1.0, //左上0 0.5, 0.5, 0.0, 1.0, 0.0, 1,0.5, 1.0,1.0,//右上1 -0.5, -0.5, 0.0, 1.0, 1.0, 1,0.5, 0.0,0.0, //左下2 0.5, -0.5, 0.0, 1.0, 1.0, 1,0.5, 1.0,0.0,//右下3 0.0, 0.0, 1.0, 0.0, 1.0, 1,0.5, 0.5,1.0,//顶点4 ] let indices : [GLuint] = [ 0, 3, 2, 0, 1, 3, 0, 2, 4, 0, 4, 1, 2, 3, 4, 1, 4, 3, ] if self.meVertices == 0{ glGenBuffers(1, &self.meVertices) } glBindBuffer(GLenum(GL_ARRAY_BUFFER), self.meVertices) glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size*attArr.count, attArr, GLenum(GL_DYNAMIC_DRAW)) let position = glGetAttribLocation(self.meProgram, "position") glEnableVertexAttribArray(GLuint(position)) glVertexAttribPointer(GLuint(position), GLint(3), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer.init(bitPattern: 0)) let positionColor = glGetAttribLocation(self.meProgram, "positionColor") glEnableVertexAttribArray(GLuint(positionColor)) glVertexAttribPointer(GLuint(positionColor), GLint(4), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 3)) let textCoordinate = glGetAttribLocation(self.meProgram, "textCoordinate") glEnableVertexAttribArray(GLuint(textCoordinate)) glVertexAttribPointer(GLuint(textCoordinate), GLint(2), GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 9), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 7)) let projectionMatrix = glGetUniformLocation(self.meProgram, "projectionMatrix") let modelViewMatrix = glGetUniformLocation(self.meProgram, "modelViewMatrix") let width: Float = Float(self.frame.size.width) let height: Float = Float(self.frame.size.height) let aspect = width / height var _projectionMatrix : GLKMatrix4 = GLKMatrix4Identity _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(35), aspect, 1, 200) let count = MemoryLayout.size(ofValue: _projectionMatrix.m) / MemoryLayout.size(ofValue: _projectionMatrix.m.0) withUnsafePointer(to: &_projectionMatrix.m) { (pointer) in pointer.withMemoryRebound(to: GLfloat.self, capacity: count, { (pon) in glUniformMatrix4fv((projectionMatrix), GLsizei(1), GLboolean(GL_FALSE), pon) }) } var _modelViewMatrix = GLKMatrix4Identity,_rotationMatrix = GLKMatrix4Identity _modelViewMatrix = GLKMatrix4Translate(_modelViewMatrix, 0, 0, -10.0) _rotationMatrix = GLKMatrix4RotateX(_rotationMatrix, xDegree) _rotationMatrix = GLKMatrix4RotateY(_rotationMatrix, yDegree) _rotationMatrix = GLKMatrix4RotateZ(_rotationMatrix, zDegree) _modelViewMatrix = GLKMatrix4Multiply(_modelViewMatrix,_rotationMatrix ) let modelCount = MemoryLayout.size(ofValue: _modelViewMatrix.m) / MemoryLayout.size(ofValue: _modelViewMatrix.m.0) withUnsafePointer(to: &_modelViewMatrix.m) { (pointer) in pointer.withMemoryRebound(to: GLfloat.self, capacity: modelCount, { (pon) in glUniformMatrix4fv((modelViewMatrix), GLsizei(1), GLboolean(GL_FALSE), pon) }) } // glEnable(GLenum(GL_DEPTH_TEST)) glEnable(GLenum(GL_CULL_FACE)) glEnable(GLenum(GL_BLEND)) glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA)); self.setupTexture("108") glDrawElements(GLenum(GL_TRIANGLES), GLsizei(MemoryLayout<GLuint>.size*indices.count / MemoryLayout<GLuint>.size), GLenum(GL_UNSIGNED_INT), indices) self.meContext.presentRenderbuffer(Int(GL_RENDERBUFFER)) } //加载纹理 fileprivate func setupTexture(_ fileName: String){ guard let image = UIImage(named: fileName)?.cgImage else { print("image is nil") return } let height = image.height let width = image.width let count = MemoryLayout<GLubyte>.size * height * width * 4 let spriteData = UnsafeMutablePointer<GLubyte>.allocate(capacity: count) UIGraphicsBeginImageContext(CGSize(width: width, height: height)) let spriteContext = CGContext(data: spriteData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: image.colorSpace!, bitmapInfo: image.bitmapInfo.rawValue) let rect = CGRect(x: 0, y: 0, width: width, height: height) spriteContext?.translateBy(x: rect.origin.x, y: rect.origin.y) spriteContext?.translateBy(x: 0, y: rect.size.height) spriteContext?.scaleBy(x: 1, y: -1) spriteContext?.translateBy(x: -rect.origin.x, y: -rect.origin.y) spriteContext?.draw(image, in: rect) UIGraphicsEndImageContext() glBindTexture(GLenum(GL_TEXTURE_2D), 0) glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR) glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR) glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GLint(GL_CLAMP_TO_EDGE)) glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GLint(GL_CLAMP_TO_EDGE)) glTexImage2D(GLenum(GL_TEXTURE_2D), GLint(0), GLint(GL_RGBA), GLsizei(width), GLsizei(height), GLint(0), GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), spriteData) free(spriteData) // defer { // spriteData.deinitialize(count: count) // spriteData.deallocate() // } } }
extension meView{ fileprivate func loaderShader(_ vert : String, _ frag : String) -> GLuint?{ let programe : GLuint = glCreateProgram(); guard let vertShader = compileShader(GLenum(GL_VERTEX_SHADER), vert) else { print("顶点着色器获取为空") return nil } guard let frag = self.compileShader(GLenum(GL_FRAGMENT_SHADER), frag) else{ print("片元着色器为空") return nil } glAttachShader(programe, vertShader) glAttachShader(programe, frag) glDeleteShader(vertShader) glDeleteShader(frag) return programe } fileprivate func compileShader(_ type : GLenum, _ file : String) -> GLuint?{ let shader = glCreateShader(type) guard let fileContent = try? String(contentsOfFile: file, encoding: .utf8) else { print("文件读取为空") return nil } fileContent.withCString { (str) in var pon : UnsafePointer<GLchar>? = str glShaderSource(shader, 1, &pon, nil) } glCompileShader(shader) return shader } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。