OpenGL shaders are written in a language called the OpenGL Shading Language, orGLSL.
The compiler for this language is built into OpenGL. The sourcecode for your shader is placed into ashader object and compiled, and then multiple shader objects can be linked together to form aprogram object.
Each program object can contain shaders for one or moreshader stages.The shader stages of OpenGL are vertex shaders, tessellation control andevaluation shaders, geometry shaders, fragment shaders, and compute shaders.
The minimal useful pipeline configuration consists only of a vertex shader, but if you wish to see any pixels on the screen, you will also need a fragment shader.
Vertex Shader:
#version 430 core
void main(void)
{
gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
}
注解:1、#version430 core:declaration, tells the shader complier that we use version 4.3 of shading language.
The keyword core indicates that we only intend to use features from thecore profile of OpenGL.
3、gl_Position: represents the output position of the vertex in the Vertex Shader.
All variables that start withgl_are part of OpenGL and connect shaders to each otheror to the various parts of fixed functionality in OpenGL.
gl_Position = vec4(0.0, 0.0, 0.5, 1.0)places the vertex in the middle of OpenGL'sclip space.
Fragment Shader:
#version 410 core
out vec4 color;
void main(void) {
color = vec4(0.0, 0.8, 1.0, 1.0); }
注解:
1、out vec4color; declares colour as an output var using the out keyword.
In fragmentshaders, the value of output variables will be sent to the window or screen.In themain function, it assigns a constant to this output.
By default, thatvalue goes directly onto the screen.
GLuint compile_shaders(void)
{
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
// Source code for vertex shader
static const GLchar * vertex_shader_source[] = {
"#version 430 core \n"
" \n"
"void main(void) \n"
"{ \n"
" gl_Position = vec4(0.0, 0.0, 0.5, 1.0); \n"
"} \n"
};
// Source code for fragment shader
static const GLchar * fragment_shader_source[] = {
"#version 430 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
// Create and compile vertex shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex_shader, 1, vertex_shader_source, NULL); glCompileShader(vertex_shader);
// Create and compile fragment shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment_shader, 1, fragment_shader_source, NULL); glCompileShader(fragment_shader);
// Create program, attach shaders to it, and link it
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Delete the shaders as the program has them now
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
}
注解:- glCreateShader()creates an empty shader object, ready to acceptsource code and be compiled.
- glShaderSource()hands shader source code to the shader object sothat it can keep a copy of it.
- glCompileShader()compiles whatever source code is contained inthe shader object.
- glCreateProgram()creates a program object to which you can attachshader objects.
- glAttachShader()attaches a shader object to a program object.
- glLinkProgram()links all of the shader objects attached to a programobject together.
- glDeleteShader()deletes a shader object. Once a shader has beenlinked into a program object, the program contains the binary codeand the shader is no longer needed.
When we call this function, we need to keep the returned program objectsomewhere so that we can use it to draw things. Also, we really don’t wantto recompile the whole program every time we want to use it. So, we needa function that is called once when the program starts up. Thesb6application framework provides just such a function:application::startup(), which we can override in our sampleapplication and perform any one-time setup work.
One final thing that we need to do before we can draw anything is tocreate avertex array object (VAO), which is an object that represents thevertex fetch stage of the OpenGL pipeline and is used to supply input tothe vertex shader. As our vertex shader doesn’t have any inputs right now,we don’t need to do much with the VAO. Nevertheless, we still need tocreate the VAO so that OpenGL will let us draw. To create the VAO, we callthe OpenGL functionglGenVertexArrays(), and to attach it to ourcontext, we callglBindVertexArray(). Their prototypes are
void glGenVertexArrays(GLsizei n,
GLuint * arrays);
void glBindVertexArray(GLuint array);
The vertex array object maintains all of the state related to the input tothe OpenGL pipeline.
Add them to startup() function:
class my_application : public sb6::application {
public:
// <snip>
void startup()
{
rendering_program = compile_shaders(); glGenVertexArrays(1, &vertex_array_object); glBindVertexArray(vertex_array_object);
}
void shutdown()
{
glDeleteVertexArrays(1, &vertex_array_object); glDeleteProgram(rendering_program); glDeleteVertexArrays(1, &vertex_array_object);
}
private:
GLuint rendering_program; GLuint vertex_array_object;
};
From startup(), we callcompile_shadersand store theresulting program object in the rendering_programmember variable inour class.
shutdown() delete the program object ( shader objects, program objects, vertex array object ) that we created at start-up.
Now that we have a program, we need to execute the shaders in it and actually get todrawing something on the screen.
// Our rendering function
void render(double currentTime) {
const GLfloat color[] = { (float)sin(currentTime) * 0.5f + 0.5f, (float)cos(currentTime) * 0.5f + 0.5f,
0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, color);
// Use the program object we created earlier for rendering
glUseProgram(rendering_program);
// Draw one point
glDrawArrays(GL_POINTS, 0, 1);
}
glUseProgram() tell OpenGL to use our program object for rendering
glDrawArrays():(drawing command) sends vertices into the OpenGL pipeline. 原型:
void glDrawArrays(GLenum mode, GLint first,
GLsizei count);
mode: tells OpenGLwhat type of graphics primitive we want to render.
In order to make our point a little more visible, we can ask OpenGL todraw it a little larger than a single pixel. To do this, we’ll call theglPointSize()function, whose prototype is
void glPointSize(GLfloat size);
This function sets the diameter of the point in pixels to the value you specify insize.