当我通过OpenGLES自定义imageView时怎么了?

时间:2019-06-11 01:22:00

标签: ios swift opengl-es

我想通过OpenGLES定制UIImageView。因为我不熟悉swift。也许某些代码是错误的,所以我无法显示我的图像。我已将名为png的{​​{1}}类型图像拖到me。我的代码如下:

Assets.xcassets

import UIKit import OpenGLES import CoreGraphics class DowImageView: UIView { private var mEaglLayer: CAEAGLLayer? private var mContext: EAGLContext? private var mColorRenderBuffer = GLuint() private var mColorFrameBuffer = GLuint() private var mprograme = GLuint() //How do you override layerClass in swift: https://stackoverflow.com/questions/24351102/how-do-you-override-layerclass-in-swift override class var layerClass: AnyClass { get { return CAEAGLLayer.self } } override func layoutSubviews() { setupLayer() setupContext() deleteRenderAndFrameBuffer() setupRenderBuffer() setupFrameBuffer() renderLayer() } private func setupLayer() { mEaglLayer = self.layer as? CAEAGLLayer self.contentScaleFactor = UIScreen.main.scale mEaglLayer?.drawableProperties = [kEAGLDrawablePropertyRetainedBacking: false, kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8] } private func setupContext() { let context = EAGLContext(api: EAGLRenderingAPI.openGLES3) EAGLContext.setCurrent(context) mContext = context } private func deleteRenderAndFrameBuffer() { glDeleteBuffers(1, &mColorRenderBuffer) mColorRenderBuffer = 0 glDeleteBuffers(1, &mColorFrameBuffer) mColorFrameBuffer = 0 } private func setupRenderBuffer() { var buffer = GLuint() glGenRenderbuffers(1, &buffer) mColorRenderBuffer = buffer glBindRenderbuffer(GLenum(GL_RENDERBUFFER), mColorRenderBuffer) //https://developer.apple.com/documentation/opengles/eaglcontext/1622262-renderbufferstorage mContext?.renderbufferStorage(Int(GL_RENDERBUFFER), from: mEaglLayer) } private func setupFrameBuffer() { var buffer = GLuint() glGenFramebuffers(1, &buffer) mColorFrameBuffer = buffer glBindFramebuffer(GLenum(GL_FRAMEBUFFER), mColorFrameBuffer) glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), mColorRenderBuffer) } private func renderLayer() { glClearColor(0.9, 0.8, 0.5, 1.0) glClear(GLbitfield(GL_COLOR_BUFFER_BIT)) let scale = UIScreen.main.scale let frame = self.frame glViewport(GLint(frame.origin.x * scale), GLint(frame.origin.y * scale), GLsizei(frame.size.width * scale), GLsizei(frame.size.height * scale)) let verFile = Bundle.main.path(forResource: "shaderv", ofType: "vsh") let fragFile = Bundle.main.path(forResource: "shaderf", ofType: "fsh") attachToProgram(with: verFile, fragFIle: fragFile) glLinkProgram(mprograme) var linkStatus = GLint() glGetProgramiv(mprograme, GLenum(GL_LINK_STATUS), &linkStatus) if linkStatus == GL_FALSE { var message = [GLchar]() glGetProgramInfoLog(mprograme, GLsizei(MemoryLayout<GLchar>.size * 512), nil, &message) let errorInfo = String(cString: message, encoding: .utf8) print(errorInfo) return } print("?? link success") glUseProgram(mprograme) //坐标数据 let attrArr: [GLfloat] = [ 0.5, -0.5, -1.0, 1.0, 0.0, -0.5, 0.5, -1.0, 0.0, 1.0, -0.5, -0.5, -1.0, 0.0, 0.0, 0.5, 0.5, -1.0, 1.0, 1.0, -0.5, 0.5, -1.0, 0.0, 1.0, 0.5, -0.5, -1.0, 1.0, 0.0, ] var attrBuffer = GLuint() glGenBuffers(1, &attrBuffer) glBindBuffer(GLenum(GL_ARRAY_BUFFER), attrBuffer) glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size * 30, attrArr, GLenum(GL_DYNAMIC_DRAW)) let position = glGetAttribLocation(mprograme, "position") glEnableVertexAttribArray(GLuint(position)) glVertexAttribPointer(GLuint(position), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 5), nil) let textCoor = glGetAttribLocation(mprograme, "textCoordinate") glEnableVertexAttribArray(GLuint(textCoor)) glVertexAttribPointer(GLuint(textCoor), 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 5), BUFFER_OFFSET(3)) loadTexture(with: "me") glUniform1i(glGetUniformLocation(mprograme, "colorMap"), 0) glDrawArrays(GLenum(GL_TRIANGLES), 0, 6) mContext?.presentRenderbuffer(Int(GL_RENDERBUFFER)) } private func BUFFER_OFFSET(_ i: Int) -> UnsafeRawPointer? { return UnsafeRawPointer(bitPattern: i) } private func loadTexture(with name: String) { guard let spriteImage = UIImage(named: name)?.cgImage else { return } let width = spriteImage.width let height = spriteImage.height let spriteData = calloc(width * height * 4, MemoryLayout<GLubyte>.size) //https://stackoverflow.com/questions/24109149/cgbitmapcontextcreate-error-with-swift let spriteContext = CGContext(data: spriteData, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: spriteImage.colorSpace!, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) let rect = CGRect(x: 0, y: 0, width: width, height: height) spriteContext?.draw(spriteImage, in: rect) 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), GL_CLAMP_TO_EDGE) glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE) glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(width), GLsizei(height), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), spriteData) free(spriteData) } private func attachToProgram(with verFile: String?, fragFIle: String?) { guard let verFile = verFile, let fragFIle = fragFIle else { return } var verShader = GLuint() var fragShader = GLuint() let program = glCreateProgram() compileshader(with: &verShader, type: GLenum(GL_VERTEX_SHADER), file: verFile) compileshader(with: &fragShader, type: GLenum(GL_FRAGMENT_SHADER), file: fragFIle) glAttachShader(program, verShader) glAttachShader(program, fragShader) glDeleteShader(verShader) glDeleteShader(fragShader) mprograme = program } private func compileshader(with shader: inout GLuint, type: GLenum, file: String) { let content = try? String(contentsOfFile: file, encoding: String.Encoding.utf8) var source = UnsafePointer<GLchar>(content) shader = glCreateShader(type) glShaderSource(shader, 1,&source, nil) glCompileShader(shader) } } 的代码如下:

shaderv.vsh

attribute vec4 position; attribute vec2 textCoordinate; varying lowp vec2 varyTextCoord; void main() { varyTextCoord = textCoordinate; gl_Position = position; } 的代码如下:

shaderf.fsh

编译不会显示错误信息,因此很难找到错误。您能帮我找到错误吗?

1 个答案:

答案 0 :(得分:4)

如果绑定了一个非零缓冲区对象,则glVertexAttribPointer的第5个参数将被视为缓冲区对象数据存储区中的字节偏移量

因此,纹理坐标的偏移量为MemoryLayout<GLfloat>.size * 3

glVertexAttribPointer(..., BUFFER_OFFSET(3))

glVertexAttribPointer(GLuint(textCoor), 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE),
   GLsizei(MemoryLayout<GLfloat>.size * 5), BUFFER_OFFSET(MemoryLayout<GLfloat>.size * 3))