zoukankan      html  css  js  c++  java
  • OpenGLES入门笔记四

    原文参考地址:http://www.cnblogs.com/zilongshanren/archive/2011/08/08/2131019.html

    一、编译Vertex Shaders和Fragment Shaders

      目前为止,xcode仅仅会把这个两个文件(simple.vertsh和simple.fragsh)copy到application bundle中。我们还需要在运行编译和运行这些Shaders。

      你会很诧异,为什么要在app运行时编译代码?

      这样做的好处是:我们的Shaders不用依赖于某种图形芯片(这样可以跨平台嘛)。

      下面开始加入动态编译的代码(两种方式。1.直接在OpenGLView写入;2.创建工具类)

      我选用第二种方式创建动态编译的代码:

      在Project中,新建继承NSObject的LVApplicationShaderUtils类。

      贴下代码:

    - (GLuint)compileShader:(NSString *)shaderFileName withType:(GLenum)shaderType
    {
        NSString * shaderName = [[shaderFileName lastPathComponent] stringByDeletingPathExtension];
        NSString * shaderFileType = [shaderFileName pathExtension];
        NSLog(@"文件名称:%@ 文件类型:%@",shaderName,shaderFileType);
        
        //!> 1
        NSString * shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:shaderFileType];
        NSLog(@"文件路径:%@",shaderPath);
        
        NSError * error = nil;
        NSString * shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
        if (!shaderPath)
        {
            NSLog(@"错误加载shader(%@):%@",shaderFileName,error.localizedDescription);
            return 0;
        }
        
        //!> 2
        GLuint shaderHandle = glCreateShader(shaderType);
        
        //!> 3
        const char * shaderStringUTF8 = [shaderString UTF8String];
        GLint shaderStringLength = (GLint)[shaderString length];
        glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);
        
        //!> 4
        glCompileShader(shaderHandle);
        
        //!> 5
        GLint compileSuccess;
        glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
        if (compileSuccess == GL_FALSE)
        {
            GLchar messages[256];
            glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
            NSString * messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"错误编译shader(%@):%@",shaderFileName,messageString);
            return 0;
        }
        
        return shaderHandle;
    }

    如果你感觉跟入门笔记一中的方法有很多不同,恭喜你。

    1.找到.vertsh 和 .fragsh文件路径。

    2.调用glCreateShader来创建一个代表shader的OpenGL对象,需要一个参数

    /* Shaders */
    #define GL_FRAGMENT_SHADER 0x8B30 // 代表片元着色器类型对象
    #define GL_VERTEX_SHADER   0x8B31 // 代表顶点着色器类型对象

    3.glShaderSource,让OpenGL获取到这个Shader的源代码,把NSString文件内容转换成C-String(null-terminated string)。

    4.最后,调用glCompileShader在运行时编译Shader。

    5.使用glGetShaderiv和glGetShaderInfoLog打印error日志。

    /* Boolean */
    #define GL_FALSE                                         0
    #define GL_TRUE                                          1
    GLint compileSuccess;
        glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
        if (compileSuccess == GL_FALSE)
        {
            GLchar messages[256];
            glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
            NSString * messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"错误编译shader(%@):%@",shaderFileName,messageString);
            return 0;
        }
    判断异常常规写法

    这个代码写法一般都是这样写的。可以直接copy~~

    二、如果编译好了Vertex Shader和Fragment Shader之后,我们需要把两个Shader关联起来。

    typedef NS_ENUM(NSInteger,compileProgramError)
    {
        compileProgramErrorShaders = -1101,  //!> Shader创建失败
        compileProgramErrorProgram = -1102,  //!> Program object 创建失败
        compileProgramErrorLink    = -1103   //!> link 失败
    };
    - (NSInteger)linkProgramHandle
    {
        //!> 1
        GLuint vertexShader = [self compileShader:@"Simple.vertsh" withType:GL_VERTEX_SHADER];
        GLuint fragmentShader = [self compileShader:@"Simple.fragsh" withType:GL_FRAGMENT_SHADER];
        if ((vertexShader == 0)||(fragmentShader == 0))
        {
            NSLog(@"错误:错误编译Shaders");
            return compileProgramErrorShaders;
        }
        
        //!> 2
        GLuint programHandle = glCreateProgram();
        if (programHandle == 0)
        {
            NSLog(@"错误:不能创建Program object");
            return compileProgramErrorProgram;
        }
        glAttachShader(programHandle, vertexShader);
        glAttachShader(programHandle, fragmentShader);
        glLinkProgram(programHandle);
        
        //!>3
        GLint linkSuccess;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
        if (linkSuccess == GL_FALSE)
        {
            GLchar messages[256];
            glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
            NSString * messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"Error link Shaders:%@",messageString);
            return compileProgramErrorLink;
        }
        return programHandle;
    }

    解析:

    1.用compileShader方法动态编译了Vertex Shader和Fragment Shader两个对象。

    2.调用glCreateProgram、glAttachShader、glLinkProgram连接Vertex Shader和Fragment Shader形成一个完成的Program。

    3.调用glGetProgram、glGetProgramInfoLog方法来检查error,跟动态编译Shader的方法中检查方法类似。

    GLint linkSuccess;
        glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
        if (linkSuccess == GL_FALSE)
        {
            GLchar messages[256];
            glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
            NSString * messageString = [NSString stringWithUTF8String:messages];
            NSLog(@"Error link Shaders:%@",messageString);
            return compileProgramErrorLink;
        }
    检查是否有error

    常规方法都是这样写的,也是可以直接copy的哦~~

    最后准确无误了,就返回programHandle,项目句柄 

    三、接下来让OpenGL执行Program,使用的就是programHandle。 

    OpenGL示例代码:https://github.com/nLoser/OpenGLES_Study

  • 相关阅读:
    ASP.NET HTTP模块和处理程序(5)(转载)
    充分利用ASP.NET的三种缓存提高站点性能(转载)
    LINQ体验(4)——LINQ简介和LINQ to SQL语句之Where
    理解DataSet的数据缓存机制
    在ASP.NET中实现AJAX(一)
    ASP.NET HTTP模块和处理程序(2)(转载)
    ASP.NET HTTP模块和处理程序(1)(转载)
    aspx页面中文汉字显示为乱码
    贫血还是充血?(转载)
    ASP.NET HTTP模块和处理程序(3)(转载)
  • 原文地址:https://www.cnblogs.com/R0SS/p/5093758.html
Copyright © 2011-2022 走看看