我想通过OpenGLES自定义UIImageView。因为我不熟悉swift
。也许某些代码是错误的,所以我无法显示我的图像。我已将名为png
的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
的代码如下:varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main() {
gl_FragColor = texture2D(colorMap, varyTextCoord);
}
编译不显示错误信息,因此很难找到错误。您能帮我找到错误吗?
最佳答案
如果绑定了一个非零缓冲区对象,则 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))
关于ios - 当我通过OpenGLES自定义imageView时怎么了?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56535272/