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