iPhoneリロード シェダー

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