openGL 分離模式程序
GLSL Shader
glCreateProgram
glUseProgramStages( GLuint pipeline,GLbitfield stages,GLuint program)> :bind stages of a program object to a program pipeline
glProgramParameteri( GLuint program,GLenum pname,GLint value): specify a parameter for a program object
glCreateShader : to creates an empty shader object
glCompileShader( GLuint shader) : Specifies the shader object to be compiled,The compilation status will be stored as part of the shader object's state.
glCreateShaderProgramv( GLenum type,GLsizei count,const char **strings) : create a stand-alone program from an array of null-terminated source code strings
equivalent to :
const GLuint shader = glCreateShader(type);
if (shader) {
glShaderSource(shader, count, strings, NULL);
glCompileShader(shader);
const GLuint program = glCreateProgram();
if (program) {
GLint compiled = GL_FALSE;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
if (compiled) {
glAttachShader(program, shader);
glLinkProgram(program);
glDetachShader(program, shader);
}
/* append-shader-info-log-to-program-info-log */
}
glDeleteShader(shader);
return program;
} else {
return 0;
}
glAttachShader( GLuint program,GLuint shader); Attaches a shader object to a program object.
In order to create a complete shader program, there must be a way to specify the list of things that will be linked together. Program objects provide this mechanism. Shaders that are to be ** linked together ** in a program object must first be attached to that program object. glAttachShader attaches the shader object specified by shader to the program object specified by program. This indicates that shader will be included in link operations that will be performed on program.
glLinkProgram( GLuint program) : Links a program object.
So far, all of the programs you have used have been considered monolithic program objects. That is, they contain a shader for each stage that is active. You have attached a vertex shader, a fragment shader, and possibly tessellation or geometry shaders to a single program object and then called glLinkProgram() to link the program object into a single representation of the entire pipeline. This type of linking might allow a compiler to perform inter-stage optimizations such as eliminating code in a vertex shader that contributes to an output that is never used by the subsequent fragment shader. However, this scheme comes at a potential cost of flexibility and possibly performance to the application. For every combination of vertex, fragment, and possibly other shaders, you need to have a unique program object, and linking all those programs doesn’t come cheap.For example, consider the case where you want to change only a fragment shader. With a monolithic program, you would need to link the same vertex shader to two or more different fragment shaders, creating a new program object for each combination. If you have multiple fragment shaders and multiple vertex shaders, you now need a program object for each combination of shaders. This problem gets worse as you add more shaders and shader stages to the mix. Eventually, you may end up with a combinatorial explosion of shader combinations that can quickly balloon into thousands of permutations, or more.
To alleviate this problem, OpenGL supports linking program objects in separable mode. A program linked this way can contain shaders for only a single stage in the pipeline or for just a few of the stages. Multiple program objects, each representing a section of the OpenGL pipeline, can then be attached to a program pipeline object and matched together at runtime rather than at link time. Shaders attached to a single program object can still benefit from inter-stage optimizations, but the program objects attached to a program pipeline object can be switched around at will with relatively little cost in performance.
To use a program object in separable mode, you need to tell OpenGL what you plan to do before you link it by calling glProgramParameteri() with pname set to GL_PROGRAM_SEPARABLE and value set to GL_TRUE. This tells OpenGL not to eliminate any outputs from a shader that it thinks aren’t being used. It will also arrange any internal data layout such that the last shader in the program object can communicatewith the first shader in another program object with the same input layout. Next, you should create a program pipeline object with glGenProgramPipelines(), and then attach programs to it representing the sections of the pipeline you wish to use. To do so, call glUseProgramStages(), passing in the name of the program pipeline object, a bitfield indicating which stages to use, and the name of a program object that contains those stages.
// Create a vertex shader
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
// Attach source and compile
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
// Create a program for our vertex stage and attach the vertex shader to it
GLuint vs_program = glCreateProgram();
glAttachShader(vs_program, vs);
// Important part - set the GL_PROGRAM_SEPARABLE flag to GL_TRUE *then* link
glProgramParameteri(vs_program, GL_PROGRAM_SEPARABLE, GL_TRUE);
glLinkProgram(vs_program);
// Now do the same with a fragment shader
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
GLuint fs_program = glCreateProgram();
glAttachShader(fs_program, vs);
glProgramParameteri(fs_program, GL_PROGRAM_SEPARABLE, GL_TRUE);
glLinkProgram(fs_program);
// The program pipeline represents the collection of programs in use:
// Generate the name for it here.
GLuint program_pipeline;
glGenProgramPipelines(1, &program_pipeline);
// Now use the vertex shader from the first program and the fragment shader
// from the second program.
glUseProgramStages(program_pipeline, GL_VERTEX_SHADER_BIT, vs_program);
glUseProgramStages(program_pipeline, GL_FRAGMENT_SHADER_BIT, fs_program);
Although this simple example includes only two program objects, each with just a single shader in it, it’s possible to have more complex arrangements where more than two program objects are used, or where one or more of the program objects contain more than one shader. For example, tessellation control and tessellation evaluation shaders are often tightly coupled, such that one does not make much sense without the other. Also, very often when tessellation is used, it is possible to use a pass-through vertex shader and do all of the real vertex shader work either in the tessellation control shader or in the tessellation evaluation shader. In those cases, it may make sense to couple a vertex shader and both tessellation shaders in one program object, but still use separable programs to be able to switch the fragment shader on the fly. If you really do want to create a simple program object with exactly one shader object in it, you can take a shortcut and call.
posted on 2023-09-20 10:20 Ultraman_X 阅读(54) 评论(0) 收藏 举报
浙公网安备 33010602011771号