【OpenGL】-010 使用shader
阿新 • • 發佈:2018-11-05
【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使用流程:
-
- 從檔案或記憶體中,取得shader的字串內容,獲得字串之後可以關閉檔案;
-
- 使用glCreateShader建立shader;
-
- 指定該shader對應的source,指定後可以刪除shader字串的記憶體;
-
- 對shader進行編譯,判斷編譯結果,出錯的話獲取並顯示錯誤資訊;
-
- 迴圈1-4步,將需要用到的shader全部都編譯好;
-
- 使用glCreateProgram建立shader Program;
-
- 使用glAttachShader將program和shader相互關聯;
-
- 關聯了所有shader之後,使用glLinkProgram對program進行連結;
-
- 連結之後可以刪除上述用到的編譯好的shader;
-
- 此時,shader program已經編譯完成,在渲染時可以使用glUseProgram進行使用。