Shaderを再読み込みして三角形の色を変えるiPhoneアプリのコードで描いてみます。
動かすとこんな感じです
サンプルコード
#import “ViewController.h”
@interface ViewController ()
@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) GLKBaseEffect *effect;
@property GLuint programObject;
@property int counter; // change fragment program
@end
@implementation ViewController
– (void)loadView
{
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
if (!self.context) {
NSLog(@”Failed to create ES context”);
}
self.view = [[GLKView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) context:self.context];
}
– (void)viewDidLoad
{
[super viewDidLoad];
[EAGLContext setCurrentContext:self.context];
GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[self createButton];
[self setup];
}
– (void)createButton
{
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:@”Reload Shader” forState:UIControlStateNormal];
[btn sizeToFit];
btn.center = CGPointMake(160, 400);
[self.view addSubview:btn];
[btn addTarget:self action:@selector(reloadShader) forControlEvents:UIControlEventTouchUpInside];
}
– (void)reloadShader
{
self.counter = (self.counter + 1) % 3;
self.paused = YES;
glDeleteProgram(self.programObject);
[self setup];
self.paused = NO;
}
– (int)setup
{
char vShaderStr[] =
“#version 300 es \n”
“layout(location = 0) in vec4 vPosition; \n”
“void main() \n”
“{ \n”
” gl_Position = vPosition; \n”
“} \n”;
char fShaderRedStr[] =
“#version 300 es \n”
“precision mediump float; \n”
“out vec4 fragColor; \n”
“void main() \n”
“{ \n”
” fragColor = vec4 (1.0, 0.0, 0.0, 1.0); \n”
“} \n”;
char fShaderGreenStr[] =
“#version 300 es \n”
“precision mediump float; \n”
“out vec4 fragColor; \n”
“void main() \n”
“{ \n”
” fragColor = vec4 (0.0, 1.0, 0.0, 1.0); \n”
“} \n”;
char fShaderBlueStr[] =
“#version 300 es \n”
“precision mediump float; \n”
“out vec4 fragColor; \n”
“void main() \n”
“{ \n”
” fragColor = vec4 (0.0, 0.0, 1.0, 1.0); \n”
“} \n”;
GLuint vertexShader;
GLuint fragmentShader;
GLuint programObjedt;
GLint linked;
vertexShader = loadShader(GL_VERTEX_SHADER, vShaderStr);
switch (self.counter) {
case 0:
fragmentShader = loadShader(GL_FRAGMENT_SHADER, fShaderRedStr);
break;
case 1:
fragmentShader = loadShader(GL_FRAGMENT_SHADER, fShaderGreenStr);
break;
default:
fragmentShader = loadShader(GL_FRAGMENT_SHADER, fShaderBlueStr);
break;
}
programObjedt = glCreateProgram();
if (programObjedt == 0) {
return 0;
}
glAttachShader(programObjedt, vertexShader);
glAttachShader(programObjedt, fragmentShader);
glLinkProgram(programObjedt);
glGetProgramiv(programObjedt, GL_LINK_STATUS, &linked);
if (!linked) {
GLint infoLen = 0;
glGetProgramiv(programObjedt, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
GLchar *infoLog = (GLchar *)malloc(sizeof(infoLen));
glGetProgramInfoLog(programObjedt, infoLen, NULL, infoLog);
NSLog(@”Error linking pogram:\n%s\n”, infoLog);
free(infoLog);
}
glDeleteProgram(programObjedt);
return FALSE;
}
self.programObject = programObjedt;
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
return TRUE;
}
GLuint loadShader(GLenum type, const char *shaderSrc)
{
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if (shader == 0) {
return 0;
}
glShaderSource(shader, 1, &shaderSrc, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
GLchar *infoLog = (GLchar *)malloc(infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
NSLog(@”Shader compile log:\n%s”, infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
– (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
–0.5f, –0.5f, 0.0f,
0.5f, –0.5f, 0.0f
};
glViewport(0, 0, CGRectGetMaxX(self.view.bounds) * 2.0, CGRectGetMaxY(self.view.bounds) * 2.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(self.programObject);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
– (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end