【OpenGL】-010 使用shader

【OpenGL】-010 使用shader

1. OpenGL中的shader

  shader是使用GLSL语言编写的运行与GPU上的简短的程序,质量上佳的shader程序可以充分发挥GPU的计算能力,相比使用CPU进行渲染的软渲染方式,可以大大提高程序的渲染速度和渲染质量。

  GLSL语言的语法与C/C++基本相似,基本语法参考C/C++即可。

2. 示例

/*ogl_vs.cpp*/

#include <GL/glew.h>
#include <GL/glut.h>
#include <iostream>
#include "loadShader.h"

//用于保存shader Program ID
GLuint g_program = 0;

//初始化OpenGL环境,并进行shader编译和链接。
void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glOrtho(-5, 5, -5, 5, 5, 15);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);

    //初始化glew
    glewInit();

    //OpenGL shader使用流程:
    // 1. 从文件或内存中,取得shader的字符串内容,获得字符串之后可以关闭文件;
    // 2. 使用glCreateShader创建shader;
    // 3. 指定该shader对应的source,指定后可以删除shader字符串的内存;
    // 4. 对shader进行编译,判断编译结果,出错的话获取并显示错误信息;
    // 5. 循环1-4步,将需要用到的shader全部都编译好;
    // 6. 使用glCreateProgram创建shader Program;
    // 7. 使用glAttachShader将program和shader相互关联;
    // 8. 关联了所有shader之后,使用glLinkProgram对program进行链接;
    // 9. 链接之后可以删除上述用到的编译好的shader;
    // 10. 此时,shader program已经编译完成,在渲染时可以使用glUseProgram进行使用。
    //将shader文件读入内存
    const GLchar *pVSSource = ReadShader("vs.vert");
    if (pVSSource)
    {
        std::cout << pVSSource << std::endl;
    }
    GLuint vs = glCreateShader(GL_VERTEX_SHADER);//此处编译生成Vertex Shader
    glShaderSource(vs, 1, &pVSSource, NULL);
    delete[] pVSSource;
    glCompileShader(vs);
    GLint compiled = 0;
    glGetShaderiv(vs, GL_COMPILE_STATUS, &compiled);//检查编译错误
    if (!compiled)
    {
        GLsizei len;
        glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &len);
        GLchar *log = new GLchar[len + 1];
        glGetShaderInfoLog(vs, len, &len, log);
        std::cerr << "Shader compilation failed: " << log << std::endl;
        delete[] log;
        return;
    }

    const GLchar *pFSSource = ReadShader("vs.frag");
    if (pFSSource)
    {
        std::cout << pFSSource << std::endl;
    }
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);//此处创建fragment shader
    glShaderSource(fs, 1, &pFSSource, NULL);
    delete[] pFSSource;
    glCompileShader(fs);
    glGetShaderiv(vs, GL_COMPILE_STATUS, &compiled);//检查编译错误
    if (!compiled)
    {
        GLsizei len;
        glGetShaderiv(fs, GL_INFO_LOG_LENGTH, &len);
        GLchar *log = new GLchar[len + 1];
        glGetShaderInfoLog(fs, len, &len, log);
        std::cerr << "Shader compilation failed: " << log << std::endl;
        delete[] log;
        return;
    }

    g_program = glCreateProgram();//创建program

    glAttachShader(g_program,vs);//指定使用的vertex shader 和 fragment shader
    glAttachShader(g_program,fs);
    glLinkProgram(g_program);//链接program
    glDeleteShader(vs);//释放中间文件
    glDeleteShader(fs);

    GLint linked = 0;
    glGetProgramiv(g_program,GL_LINK_STATUS,&linked);//检查链接错误
    if(!linked)
    {
        GLsizei len;
        glGetProgramiv( g_program, GL_INFO_LOG_LENGTH, &len );

        GLchar* log = new GLchar[len+1];
        glGetProgramInfoLog( g_program, len, &len, log );
        std::cerr << "Shader linking failed: " << log << std::endl;
        delete [] log;

        glDeleteShader(vs);
        glDeleteShader(fs);
    }

    return;
}

void display(void)
{
    glUseProgram(g_program);
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0, 0);
    glBegin(GL_TRIANGLES);
    glColor3f(1, 0, 0);
    glVertex2f(-5, 5);
    glColor3f(0, 1, 0);
    glVertex2f(-5, -5);
    glColor3f(0, 0, 1);
    glVertex2f(5, -5);
    glEnd();
    glFlush();
    glUseProgram(0);
    return;
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(500, 800);
    glutCreateWindow("OGLWindow");
    init();

    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}

配套的vs和fs shader文件如下:
vs.vert——Vertex Shader

#version 400 core

layout( location = 0 ) in vec4 vPosition;

void main()
{
	gl_Position = vPosition;
}

在Vertex Shader中,保持了顶点位置不变。
vs.frag——Fragment Shader

#version 450 core

out vec4 fColor;

void main()
{
	fColor = vec4(1.0,1.0,0.5,1.0);
}

在Fragment Shader中,设定了顶点的颜色。

2. shader的使用流程

OpenGL shader使用流程:

    1. 从文件或内存中,取得shader的字符串内容,获得字符串之后可以关闭文件;
    1. 使用glCreateShader创建shader;
    1. 指定该shader对应的source,指定后可以删除shader字符串的内存;
    1. 对shader进行编译,判断编译结果,出错的话获取并显示错误信息;
    1. 循环1-4步,将需要用到的shader全部都编译好;
    1. 使用glCreateProgram创建shader Program;
    1. 使用glAttachShader将program和shader相互关联;
    1. 关联了所有shader之后,使用glLinkProgram对program进行链接;
    1. 链接之后可以删除上述用到的编译好的shader;
    1. 此时,shader program已经编译完成,在渲染时可以使用glUseProgram进行使用。

猜你喜欢

转载自blog.csdn.net/freehawkzk/article/details/83186822