zoukankan      html  css  js  c++  java
  • 一个简单的GLSL Shader例子

    本例子选自OpenGL Shading Language中的第一个Shader例子,使用颜色平滑地表示一个表面的温度。温度及其颜色的范围在应用程序中进行设置。 
    //先看顶点着色器temp.vert: 
    uniform float CoolestTemp; 
    uniform float TempRange; 
    attribute float VertexTemp;//每个定点都对应一个温度值 
    varying float Temperature;//传递到片段处理器进行后续处理 
    void main(void) 
    {
     //进行插值
    Temperature = (VertexTemp - CoolestTemp) / TempRange; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    }
    //片段着色器temp.frag: 
    uniform vec3 CoolestColor; 
    uniform vec3 HottestColor;
    varying float Temperature; 
    void main(void) 

    //通过温度值寻找一个相应的颜色,位于最冷和最热之间 
    vec3 color = mix(CoolestColor, HottestColor,Temperature); 
    gl_FragColor = vec4(color,1.0); 

    下面看看如何将着色器和应用程序进行链接(第一步是创建着色器对象,指定着色器源代码,进行编译,并程序对象和着色器进行绑定和链接),同时指定了一些一致变量的值 
    /*public*/ 
    int installShaders(const GLchar *Vertex, const GLchar *Fragment) 

    GLint vertCompiled, fragCompiled; 
    // status values 
    GLint linked;
    // Create a vertex shader object and a fragment shader object 
    VertexShaderObject = glCreateShader(GL_VERTEX_SHADER); 
    FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER); /
    / Load source code strings into shaders 
    glShaderSource(VertexShaderObject, 1, &Vertex, NULL); 
    glShaderSource(FragmentShaderObject, 1, &Fragment, NULL); 
    // Compile the brick vertex shader, and print out 
    // the compiler log file. 
    glCompileShader(VertexShaderObject); 
    glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled); 
    // Compile the brick vertex shader, and print out 
    // the compiler log file. 
    glCompileShader(FragmentShaderObject); 
    glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled); 
    if (!vertCompiled || !fragCompiled) 
    return 0; 
    // Create a program object and attach the two compiled shaders 
    ProgramObject = glCreateProgram(); 
    glAttachShader(ProgramObject, VertexShaderObject); 
    glAttachShader(ProgramObject, FragmentShaderObject); 
    // Link the program object and print out the info log 
    glLinkProgram(ProgramObject); 
    glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked); 
    if (!linked) 
    return 0; 
    // Install program object as part of current state 
    glUseProgram(ProgramObject); 
    // Set up initial uniform values 
    glUniform1f(glGetUniformLocation(ProgramObject, "CoolestTemp"), 0.0f); 
    glUniform1f(glGetUniformLocation(ProgramObject, "TempRange"), 1.0f); 
    glUniform3f(glGetUniformLocation(ProgramObject, "CoolestColor"), 0.0, 0.0, 1.0); 
    glUniform3f(glGetUniformLocation(ProgramObject, "HottestColor"), 1.0, 0.0, 0.0); 
    return 1; 

    这其中用到了一些读取外部着色器代码的函数,顶点着色器后缀自定义为.vert,片段着色器自定义为.frag,我们也可以将着色器放在程序中存储在一个字符串中。 
    //Shader related functions static int shaderSize(char *fileName, EShaderType shaderType) 

    //返回顶点着色器或者片段着色器的大小 
    char name[100]; 
    strcpy(name, fileName); 
    switch (shaderType) 

    case EVertexShader: 
    strcat(name, ".vert"); 
    break; 
    case EFragmentShader: 
    strcat(name, ".frag"); 
    break; 
    default: 
    printf("ERROR: unknown shader file type "); 
    exit(1); 
    break; 

    int count = -1; 
    // Open the file, seek to the end to find its length 
    int fd = _open(name, _O_RDONLY); 
    if (fd != -1) 

    count = _lseek(fd, 0, SEEK_END) + 1;
    _close(fd); 

    return count; 


    static int readShader(char *fileName, EShaderType shaderType, char *shaderText, int size) 

    // Reads a shader from the supplied file and returns the shader in the 
    // arrays passed in. 
    Returns 1 if successful, 0 if an error occurred. 
    // The parameter size is an upper limit of the amount of bytes to read. 
    // It is ok for it to be too big.
    FILE *fh; 
    char name[100]; 
    int count; 
    strcpy(name, fileName); 
    switch (shaderType) 

    case EVertexShader: 
    strcat(name, ".vert"); 
    break; 
    case EFragmentShader: 
    strcat(name, ".frag"); 
    break; 
    default: 
    printf("ERROR: unknown shader file type "); 
    exit(1); 
    break; 

    // Open the file 
    fh = fopen(name, "r"); 
    if (!fh) 
    return -1; 
    // Get the shader from a file. 
    fseek(fh, 0, SEEK_SET); 
    count = (int) fread(shaderText, 1, size, fh); 
    shaderText[count] = ''; 
    if (ferror(fh)) 
    count = 0; 
    fclose(fh); 
    return count; 
    }

    /*public*/ 
    int readShaderSource(char *fileName, GLchar **vertexShader, GLchar **fragmentShader) 

    int vSize, fSize; 
    // // Allocate memory to hold the source of our shaders. 
    vSize = shaderSize(fileName, EVertexShader); 
    fSize = shaderSize(fileName, EFragmentShader); 
    if ((vSize == -1) || (fSize == -1)) 

    printf("Cannot determine size of the shader %s ", fileName); return 0; 

    *vertexShader = (GLchar *) malloc(vSize); 
    *fragmentShader = (GLchar *) malloc(fSize); 
    // // Read the source code // 
    if (!readShader(fileName, EVertexShader, *vertexShader, vSize)) 

    printf("Cannot read the file %s.vert ", fileName); 
    return 0; 

    if (!readShader(fileName, EFragmentShader, *fragmentShader, fSize)) 

    printf("Cannot read the file %s.frag ", fileName); 
    return 0; 

    return 1; 

    这里我们只绘制一个简单的三角形,需要为每个顶点指定一个属性值,代表其温度值,着色器中我们对其进行了读取并插值。对于复杂的图形,应当使用顶点数组进行指定。 
    static void display(void) 

    glLoadIdentity(); 
    glTranslatef(0.0, 0.0, -5.0); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //查询定点着色器属性变量VertexTemp,并对它进行设置,每个定点需要指定一个属性 
    GLint tempLoc = glGetAttribLocationARB(ProgramObject, "VertexTemp"); 
    glBegin(GL_TRIANGLES); 
    glVertexAttrib1f(tempLoc, 0.0f); 
    glVertex3f(1.0f,0.0f,0.0f); 
    glVertexAttrib1f(tempLoc, 0.5f); 
    glVertex3f(-1.0f,0.0f,0.0f); 
    glVertexAttrib1f(tempLoc, 1.0f); 
    glVertex3f(0.0f,1.0f,0.0f); 
    glEnd(); 
    glFlush(); 
    glutSwapBuffers(); 

    运行效果如下:

       
    整个程序如下: 
     

    #include
    #include
    #include
    #include
    #include
    #define GLEW_STATIC 1
    #include
    #include
    #include
     
    //窗口句柄
    static GLint window;
     
    GLuint ProgramObject = 0;                            //程序对象
    GLuint VertexShaderObject = 0;                   //顶点着色器对象
    GLuint FragmentShaderObject = 0;    //片段着色器对象
     
    //Shader类型
    typedef enum {
        EVertexShader,
             EFragmentShader,
    } EShaderType;
     
    //用来检查OpenGL版本,需要GLSL 2.0支持
    void getGlVersion( int *major, int *minor )
    {
        constchar* verstr = (constchar*)glGetString( GL_VERSION );
        if( (verstr == NULL) || (sscanf( verstr, "%d.%d", major, minor ) != 2) )
        {
            *major = *minor = 0;
            fprintf( stderr, "Invalid GL_VERSION format!!! " );
        }
    }
     
    staticvoid display(void)
    {
        glLoadIdentity();
        glTranslatef(0.0, 0.0, -5.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
             //查询定点着色器属性变量VertexTemp,并对它进行设置,每个定点需要指定一个属性
             GLint tempLoc = glGetAttribLocationARB(ProgramObject, "VertexTemp");
             glBegin(GL_TRIANGLES);
                       glVertexAttrib1f(tempLoc, 0.0f);        
                       glVertex3f(1.0f,0.0f,0.0f);
                       glVertexAttrib1f(tempLoc, 0.5f);
                       glVertex3f(-1.0f,0.0f,0.0f);
                       glVertexAttrib1f(tempLoc, 1.0f);
                       glVertex3f(0.0f,1.0f,0.0f);
             glEnd();
        glFlush();
        glutSwapBuffers();
    }
     
    staticvoid reshape(int wid, int ht)
    {
        float vp = 0.8f;
        float aspect = (float) wid / (float) ht;
            
        glViewport(0, 0, wid, ht);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        //glOrtho(-1.0, 1.0, -1.0, 1.0, -10.0, 10.0);
        glFrustum(-vp, vp, -vp / aspect, vp / aspect, 3, 10.0);
             glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
     
     
    //Shader related functions
    staticint shaderSize(char *fileName, EShaderType shaderType)
    {
             //返回顶点着色器或者片段着色器的大小
        char name[100];
        strcpy(name, fileName);
     
        switch (shaderType)
        {
            case EVertexShader:
                strcat(name, ".vert");
                break;
            case EFragmentShader:
                strcat(name, ".frag");
                break;
            default:
                printf("ERROR: unknown shader file type ");
                exit(1);
                break;
        }
     
        int count = -1;
        // Open the file, seek to the end to find its length
        int fd = _open(name, _O_RDONLY);
        if (fd != -1)
        {
            count = _lseek(fd, 0, SEEK_END) + 1;
            _close(fd);
        }
        return count;
    }
     
     
    staticint readShader(char *fileName, EShaderType shaderType, char *shaderText, int size)
    {
        //
        // Reads a shader from the supplied file and returns the shader in the
        // arrays passed in. Returns 1 if successful, 0 if an error occurred.
        // The parameter size is an upper limit of the amount of bytes to read.
        // It is ok for it to be too big.
        //
        FILE *fh;
        char name[100];
        int count;
     
        strcpy(name, fileName);
     
        switch (shaderType)
        {
            case EVertexShader:
                strcat(name, ".vert");
                break;
            case EFragmentShader:
                strcat(name, ".frag");
                break;
            default:
                printf("ERROR: unknown shader file type ");
                exit(1);
                break;
        }
     
        // Open the file
        fh = fopen(name, "r");
        if (!fh)
            return -1;
     
        // Get the shader from a file.
        fseek(fh, 0, SEEK_SET);
        count = (int) fread(shaderText, 1, size, fh);
        shaderText[count] = '';
     
        if (ferror(fh))
            count = 0;
     
        fclose(fh);
        return count;
    }
     
     
    /*public*/
    int readShaderSource(char *fileName, GLchar **vertexShader, GLchar **fragmentShader)
    {
        int vSize, fSize;
     
        //
        // Allocate memory to hold the source of our shaders.
        //
        vSize = shaderSize(fileName, EVertexShader);
        fSize = shaderSize(fileName, EFragmentShader);
     
        if ((vSize == -1) || (fSize == -1))
        {
            printf("Cannot determine size of the shader %s ", fileName);
            return 0;
        }
     
        *vertexShader = (GLchar *) malloc(vSize);
        *fragmentShader = (GLchar *) malloc(fSize);
     
        //
        // Read the source code
        //
        if (!readShader(fileName, EVertexShader, *vertexShader, vSize))
        {
            printf("Cannot read the file %s.vert ", fileName);
            return 0;
        }
     
        if (!readShader(fileName, EFragmentShader, *fragmentShader, fSize))
        {
            printf("Cannot read the file %s.frag ", fileName);
            return 0;
        }
     
        return 1;
    }
     
     
    /*public*/
    int installShaders(const GLchar *Vertex,
                            const GLchar *Fragment)
    {
        GLint vertCompiled, fragCompiled;    // status values
        GLint linked;
     
        // Create a vertex shader object and a fragment shader object
     
        VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
        FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
     
        // Load source code strings into shaders
     
        glShaderSource(VertexShaderObject, 1, &Vertex, NULL);
        glShaderSource(FragmentShaderObject, 1, &Fragment, NULL);
     
        // Compile the brick vertex shader, and print out
        // the compiler log file.
     
        glCompileShader(VertexShaderObject);
        glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled);
     
        // Compile the brick vertex shader, and print out
        // the compiler log file.
     
        glCompileShader(FragmentShaderObject);
        glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled);
     
        if (!vertCompiled || !fragCompiled)
            return 0;
     
        // Create a program object and attach the two compiled shaders
     
        ProgramObject = glCreateProgram();
        glAttachShader(ProgramObject, VertexShaderObject);
        glAttachShader(ProgramObject, FragmentShaderObject);
     
        // Link the program object and print out the info log
     
        glLinkProgram(ProgramObject);
        glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);
     
        if (!linked)
            return 0;
     
        // Install program object as part of current state
     
        glUseProgram(ProgramObject);
     
        // Set up initial uniform values
        glUniform1f(glGetUniformLocation(ProgramObject, "CoolestTemp"), 0.0f);
        glUniform1f(glGetUniformLocation(ProgramObject, "TempRange"), 1.0f);
        glUniform3f(glGetUniformLocation(ProgramObject, "CoolestColor"), 0.0, 0.0, 1.0);
        glUniform3f(glGetUniformLocation(ProgramObject, "HottestColor"), 1.0, 0.0, 0.0);
     
        return 1;
    }
     
    /******************************************************************************/
    /*
    /* Main
    /*
    /******************************************************************************/
    int main( int argc, char **argv )
    {
        int success = 0;
        int gl_major, gl_minor;
        GLchar *VertexShaderSource, *FragmentShaderSource;
            
        glutInit( &argc, argv );
        glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
        glutInitWindowSize(500, 500);
        window = glutCreateWindow( "Temperature Shader");
            
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
            
        // Initialize the "OpenGL Extension Wrangler" library
        glewInit();
            
        // Make sure that OpenGL 2.0 is supported by the driver
        getGlVersion(&gl_major, &gl_minor);
        printf("GL_VERSION major=%d minor=%d ", gl_major, gl_minor);
            
        if (gl_major < 2)
        {
            printf("GL_VERSION major=%d minor=%d ", gl_major, gl_minor);
            printf("Support for OpenGL 2.0 is required for this demo...exiting ");
            exit(1);
        }
            
        readShaderSource("temp", &VertexShaderSource, &FragmentShaderSource);
        success = installShaders(VertexShaderSource, FragmentShaderSource);
            
        if (success)
            glutMainLoop();
       
        return 0;

    }

  • 相关阅读:
    MapReduce-shuffle过程详解
    YARN中的失败分析
    HBase协处理器的使用(添加Solr二级索引)
    Flume具体应用(多案例)
    Flume架构及运行机制
    python Cmd实例之网络爬虫应用
    mongodb3 权限认证问题总结
    webpack配置
    apt软件包管理
    python笔记之编程风格大比拼
  • 原文地址:https://www.cnblogs.com/lx-hhxxttxs/p/5961047.html
Copyright © 2011-2022 走看看