iOS-OpenGLES-入门-三角形
2020-06-10 本文已影响0人
秋叶红90
定点着色器文件: shaderv.glsl
attribute vec4 vPosition;
attribute vec4 a_Color;需要传值过去
attribute vec4 vPosition;
attribute vec4 a_Color;
varying lowp vec4 frag_Color;
void main(void)
{
frag_Color = a_Color;
gl_Position = vPosition;
}
片段着色器 shaderf.glsl
varying lowp vec4 frag_Color;
void main()
{
gl_FragColor = frag_Color;
}
写一个工具加载成字符串将 上面两文件
GLESUtils.swift
//
// GLESUtils.swift
// OpenGL-ES-04
//
// Created by mkil on 2019/1/10.
// Copyright © 2019 黎宁康. All rights reserved.
//
import Foundation
import OpenGLES
struct GLESUtils {
static func loadShaderFile(type:GLenum, fileName:String) -> GLuint {
guard let path = Bundle.main.path(forResource: fileName, ofType: nil) else {
print("Error: file does not exist !")
return 0;
}
do {
let shaderString = try String(contentsOfFile: path, encoding: .utf8)
return GLESUtils.loadShaderString(type: type, shaderString: shaderString)
} catch {
print("Error: loading shader file: \(path)")
return 0;
}
}
static func loadShaderString(type:GLenum, shaderString:String) ->GLuint {
// 创建着色器对象
let shaderHandle = glCreateShader(type)
var shaderStringLength: GLint = GLint(Int32(shaderString.count))
var shaderCString = NSString(string: shaderString).utf8String
/* 把着色器源码附加到着色器对象上
glShaderSource(shader: GLuint, count: GLsizei, String: UnsafePointer<UnsafePointer<GLchar>?>!, length: UnsafePointer<GLint>!)
shader: 着色器对象
count:指定要传递的源码字符串数量,这里只有一个
String:着色器源码
length:源码长度
*/
glShaderSource(shaderHandle, GLsizei(1), &shaderCString, &shaderStringLength)
// 编译着色器
glCompileShader(shaderHandle)
// 编译是否成功的状态 GL_FALSE GL_TRUE
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)
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)!)
print("Error: Colourer Compilation Failure: \(String(validatingUTF8: info) ?? "")")
return 0
}
return shaderHandle
}
static func loanProgram(verShaderFileName:String,fragShaderFileName:String) -> GLuint {
let vertexShader = GLESUtils.loadShaderFile(type: GLenum(GL_VERTEX_SHADER), fileName: verShaderFileName)
if vertexShader == 0 {return 0}
let fragmentShader = GLESUtils.loadShaderFile(type: GLenum(GL_FRAGMENT_SHADER), fileName: fragShaderFileName)
if fragmentShader == 0 {
glDeleteShader(vertexShader)
return 0
}
// 创建着色器程序对象
let programHandel = glCreateProgram()
if programHandel == 0 {return 0}
// 将着色器附加到程序上
glAttachShader(programHandel, vertexShader)
glAttachShader(programHandel, fragmentShader)
// 链接着色器程序
glLinkProgram(programHandel)
// 获取链接状态
var linkStatus: GLint = 0
glGetProgramiv(programHandel, GLenum(GL_LINK_STATUS), &linkStatus)
if linkStatus == GL_FALSE {
var infoLength: GLsizei = 0
let bufferLenght: GLsizei = 1024
glGetProgramiv(programHandel, GLenum(GL_INFO_LOG_LENGTH), &infoLength)
let info: [GLchar] = Array(repeating: GLchar(0), count: Int(bufferLenght))
var actualLenght: GLsizei = 0
// 获取错误消息
glGetProgramInfoLog(programHandel, bufferLenght, &actualLenght, UnsafeMutablePointer(mutating: info))
print("Error: Colorer Link Failed: \(String(validatingUTF8: info) ?? "")")
return 0
}
// 释放资源
glDeleteShader(vertexShader)
glDeleteShader(fragmentShader)
return programHandel
}
static func createVBO(_ target:GLenum, _ usage: Int, _ datSize: Int, data:UnsafeRawPointer!) ->GLuint {
var vbo:GLuint = 0
glGenBuffers(1, &vbo)
glBindBuffer(target, vbo)
glBufferData(target, datSize, data, GLenum(usage))
return vbo
}
}
写一个AGLKView 渲染出来
//
// AGLKView.swift
// Tutorial-01-三角形
//
// Created by mkil on 2019/1/24.
// Copyright © 2019 黎宁康. All rights reserved.
//
import UIKit
class AGLKView: UIView {
var myContext:EAGLContext?
var myColorFrameBuffer:GLuint = 0
var myColorRenderBuffer:GLuint = 0
var myProgram:GLuint?
var positionSlot:GLuint = 0
var colorSlot:GLuint = 0
// 只有CAEAGLLayer 类型的 layer 才支持 OpenGl 描绘
override class var layerClass : AnyClass {
return CAEAGLLayer.self
}
override func layoutSubviews() {
setupLayer()
setupContext()
destoryRenderAndFrameBuffer()
setupBuffer()
setupProgram()
render()
}
}
extension AGLKView {
fileprivate func render() {
glClearColor(0, 1.0, 0, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
let vertices: [GLfloat] = [
0, 0.5, 0,
-0.5, -0.5, 0,
0.5, -0.5, 0
]
let colors: [GLfloat] = [
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1
]
// 加载顶点数据
glVertexAttribPointer(positionSlot, 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, vertices )
glEnableVertexAttribArray(positionSlot)
// 加载颜色数据
glVertexAttribPointer(colorSlot, 4, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, colors )
glEnableVertexAttribArray(colorSlot)
// 绘制
glDrawArrays(GLenum(GL_TRIANGLES), 0, 3)
myContext?.presentRenderbuffer(Int(GL_RENDERBUFFER))
}
}
extension AGLKView {
// 设置不透明,
fileprivate func setupLayer() {
let eagLayer = layer as? CAEAGLLayer
// CALayer 默认是透明的,必须将它设为不透明才能让其可见
eagLayer?.isOpaque = true
// 设置描绘属性,在这里设置不维持渲染内容以及颜色格式为 RGBA8
eagLayer?.drawableProperties = [kEAGLDrawablePropertyRetainedBacking:false,kEAGLDrawablePropertyColorFormat:kEAGLColorFormatRGBA8]
}
// 配置上下文
fileprivate func setupContext() {
// 指定 OpenGL 渲染 API 的版本,在这里我们使用 OpenGL ES 3.0
myContext = EAGLContext(api: .openGLES3)
if myContext == nil {
print("Failed to initialize OpenGLES 3.0 context")
return
}
// 设置为当前上下文
if !EAGLContext.setCurrent(myContext) {
print("Failed to set current OpenGL context")
return
}
}
/// 销毁已经存在的 buffer
fileprivate func destoryRenderAndFrameBuffer() {
// 当 UIView 在进行布局变化之后,由于 layer 的宽高变化,导致原来创建的 renderbuffer不再相符,我们需要销毁既有 renderbuffer 和 framebuffer。下面,我们依然创建私有方法 destoryRenderAndFrameBuffer 来销毁生成的 buffer
glDeleteFramebuffers(1, &myColorFrameBuffer)
myColorFrameBuffer = 0
glDeleteRenderbuffers(1, &myColorRenderBuffer)
myColorRenderBuffer = 0
}
/// buffer 初始化 渲染 frame buffer 装配
fileprivate func setupBuffer() {
var buffer:GLuint = 0
glGenRenderbuffers(1, &buffer)
myColorRenderBuffer = buffer
glBindRenderbuffer(GLenum(GL_RENDERBUFFER), myColorRenderBuffer)
// 为 颜色缓冲区 分配存储空间
myContext?.renderbufferStorage(Int(GL_RENDERBUFFER), from: layer as? CAEAGLLayer)
glGenFramebuffers(1, &buffer)
myColorFrameBuffer = buffer
// 设置为当前 framebuffer
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), myColorFrameBuffer)
// 将 _colorRenderBuffer 装配到 GL_COLOR_ATTACHMENT0 这个装配点上
glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), myColorRenderBuffer)
}
fileprivate func setupProgram() {
myProgram = GLESUtils.loanProgram(verShaderFileName: "shaderv.glsl", fragShaderFileName: "shaderf.glsl")
guard let myProgram = myProgram else {
return
}
glUseProgram(myProgram)
positionSlot = GLuint(glGetAttribLocation(myProgram, "vPosition"))
colorSlot = GLuint(glGetAttribLocation(myProgram, "a_Color"))
}
}