GLKViewControllerテンプレートからシェーダを使っている部分を残し、データを三角形が回転するだけに変えてみたものを作ってみました。Swift3です。
頂点シェーダ
Shader.vsh
attribute vec4 position;
uniform mat4 modelViewProjectionMatrix;
void main()
{
gl_Position = modelViewProjectionMatrix * position;
}
フラグメントシェーダ
Shader.fsh
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
GLKViewController本体
GameViewController.swift
import GLKit
import OpenGLES
func BUFFER_OFFSET(_ i: Int) -> UnsafeRawPointer? {
return UnsafeRawPointer(bitPattern: i)
}
let UNIFORM_MODELVIEWPROJECTION_MATRIX = 0
var uniforms = [GLint](repeating: 0, count: 1)
class GameViewController: GLKViewController {
var program: GLuint = 0
var modelViewProjectionMatrix:GLKMatrix4 = GLKMatrix4Identity
var rotation: Float = 0.0
var vertexArray: GLuint = 0
var vertexBuffer: GLuint = 0
var context: EAGLContext? = nil
deinit {
self.tearDownGL()
if EAGLContext.current() === self.context {
EAGLContext.setCurrent(nil)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.context = EAGLContext(api: .openGLES2)
if !(self.context != nil) {
print("Failed to create ES context")
}
let view = self.view as! GLKView
view.context = self.context!
view.drawableDepthFormat = .format24
self.setupGL()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
if self.isViewLoaded && (self.view.window != nil) {
self.view = nil
self.tearDownGL()
if EAGLContext.current() === self.context {
EAGLContext.setCurrent(nil)
}
self.context = nil
}
}
func setupGL() {
EAGLContext.setCurrent(self.context)
if(self.loadShaders() == false) {
print("Failed to load shaders")
}
glEnable(GLenum(GL_DEPTH_TEST))
glGenVertexArraysOES(1, &vertexArray)
glBindVertexArrayOES(vertexArray)
glGenBuffers(1, &vertexBuffer)
glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)
glBufferData(GLenum(GL_ARRAY_BUFFER), GLsizeiptr(MemoryLayout<GLfloat>.size * gVertexData.count), &gVertexData, GLenum(GL_STATIC_DRAW))
glEnableVertexAttribArray(GLuint(GLKVertexAttrib.position.rawValue))
glVertexAttribPointer(GLuint(GLKVertexAttrib.position.rawValue),
3,
GLenum(GL_FLOAT),
GLboolean(GL_FALSE),
GLsizei(MemoryLayout<GLfloat>.size)*3,
BUFFER_OFFSET(0))
glBindVertexArrayOES(0)
}
func tearDownGL() {
EAGLContext.setCurrent(self.context)
glDeleteBuffers(1, &vertexBuffer)
glDeleteVertexArraysOES(1, &vertexArray)
if program != 0 {
glDeleteProgram(program)
program = 0
}
}
// MARK: - GLKView and GLKViewController delegate methods
func update() {
let aspect = fabsf(Float(self.view.bounds.size.width / self.view.bounds.size.height))
let projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0)
var baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, -4.0)
baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, rotation, 0.0, 1.0, 0.0)
// Compute the model view matrix for the object rendered with ES2
var modelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, 1.5)
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, rotation, 1.0, 1.0, 1.0)
modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix)
modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix)
rotation += Float(self.timeSinceLastUpdate * 0.5)
}
override func glkView(_ view: GLKView, drawIn rect: CGRect) {
glClearColor(0.65, 0.65, 0.65, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT) | GLbitfield(GL_DEPTH_BUFFER_BIT))
glBindVertexArrayOES(vertexArray)
// Render the object again with ES2
glUseProgram(program)
withUnsafePointer(to: &modelViewProjectionMatrix, {
$0.withMemoryRebound(to: Float.self, capacity: 4*4, {
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, $0)
})
})
glDrawArrays(GLenum(GL_TRIANGLES), 0, Int32(gVertexData.count/3))
}
// MARK: - OpenGL ES 2 shader compilation
func loadShaders() -> Bool {
var vertShader: GLuint = 0
var fragShader: GLuint = 0
var vertShaderPathname: String
var fragShaderPathname: String
// Create shader program.
program = glCreateProgram()
// Create and compile vertex shader.
vertShaderPathname = Bundle.main.path(forResource: "Shader", ofType: "vsh")!
if self.compileShader(&vertShader, type: GLenum(GL_VERTEX_SHADER), file: vertShaderPathname) == false {
print("Failed to compile vertex shader")
return false
}
// Create and compile fragment shader.
fragShaderPathname = Bundle.main.path(forResource: "Shader", ofType: "fsh")!
if !self.compileShader(&fragShader, type: GLenum(GL_FRAGMENT_SHADER), file: fragShaderPathname) {
print("Failed to compile fragment shader")
return false
}
// Attach vertex shader to program.
glAttachShader(program, vertShader)
// Attach fragment shader to program.
glAttachShader(program, fragShader)
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(program, GLuint(GLKVertexAttrib.position.rawValue), "position")
// Link program.
if !self.linkProgram(program) {
print("Failed to link program: \(program)")
if vertShader != 0 {
glDeleteShader(vertShader)
vertShader = 0
}
if fragShader != 0 {
glDeleteShader(fragShader)
fragShader = 0
}
if program != 0 {
glDeleteProgram(program)
program = 0
}
return false
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(program, "modelViewProjectionMatrix")
// Release vertex and fragment shaders.
if vertShader != 0 {
glDetachShader(program, vertShader)
glDeleteShader(vertShader)
}
if fragShader != 0 {
glDetachShader(program, fragShader)
glDeleteShader(fragShader)
}
return true
}
func compileShader(_ shader: inout GLuint, type: GLenum, file: String) -> Bool {
var status: GLint = 0
var source: UnsafePointer<Int8>
do {
source = try NSString(contentsOfFile: file, encoding: String.Encoding.utf8.rawValue).utf8String!
} catch {
print("Failed to load vertex shader")
return false
}
var castSource:UnsafePointer<GLchar>? = UnsafePointer<GLchar>(source)
shader = glCreateShader(type)
glShaderSource(shader, 1, &castSource, nil)
glCompileShader(shader)
//#if defined(DEBUG)
// var logLength: GLint = 0
// glGetShaderiv(shader, GLenum(GL_INFO_LOG_LENGTH), &logLength)
// if logLength > 0 {
// var log = UnsafeMutablePointer<GLchar>(malloc(Int(logLength)))
// glGetShaderInfoLog(shader, logLength, &logLength, log)
// NSLog("Shader compile log: \n%s", log)
// free(log)
// }
//#endif
glGetShaderiv(shader, GLenum(GL_COMPILE_STATUS), &status)
if status == 0 {
glDeleteShader(shader)
return false
}
return true
}
func linkProgram(_ prog: GLuint) -> Bool {
var status: GLint = 0
glLinkProgram(prog)
//#if defined(DEBUG)
// var logLength: GLint = 0
// glGetShaderiv(shader, GLenum(GL_INFO_LOG_LENGTH), &logLength)
// if logLength > 0 {
// var log = UnsafeMutablePointer<GLchar>(malloc(Int(logLength)))
// glGetShaderInfoLog(shader, logLength, &logLength, log)
// NSLog("Shader compile log: \n%s", log)
// free(log)
// }
//#endif
glGetProgramiv(prog, GLenum(GL_LINK_STATUS), &status)
if status == 0 {
return false
}
return true
}
func validateProgram(_ prog: GLuint) -> Bool {
var logLength: GLsizei = 0
var status: GLint = 0
glValidateProgram(prog)
glGetProgramiv(prog, GLenum(GL_INFO_LOG_LENGTH), &logLength)
if logLength > 0 {
var log: [GLchar] = [GLchar](repeating: 0, count: Int(logLength))
glGetProgramInfoLog(prog, logLength, &logLength, &log)
print("Program validate log: \n\(log)")
}
glGetProgramiv(prog, GLenum(GL_VALIDATE_STATUS), &status)
var returnVal = true
if status == 0 {
returnVal = false
}
return returnVal
}
}
var gVertexData: [GLfloat] = [
-0.5, -0.0, 0.0,
0.5,-0.5,0.0,
-0.5,0.5,0.0
]