1. 程式人生 > >【OpenGL】-010 使用shader

【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進行使用。