Difference between revisions of "Example Code"

From OpenGL.org
Jump to: navigation, search
(GLSL full compile/link example)
(Texture example.)
Line 1: Line 1:
 
This is a list of all of the [[:Category:Example Code|significant example code used throughout the wiki]].
 
This is a list of all of the [[:Category:Example Code|significant example code used throughout the wiki]].
 +
 +
== Texture ==
 +
{{:Example/Texture Array Creation}}
  
 
== GLSL error testing ==
 
== GLSL error testing ==

Revision as of 05:33, 3 May 2013

This is a list of all of the significant example code used throughout the wiki.

Texture

This example code shows how to create a 2D array texture.

GLuint texture = 0;
 
GLsizei width = 2;
GLsizei height = 2;
GLsizei layerCount = 2;
GLsizei mipLevelCount = 1;
 
//Read you texels here. In the current example, we have 2*2*2 = 8 texels, with each texel being 4 GLubytes.
GLubyte texels[32] = 
{
     //Texels for first image.
     0,   0,   0,   255,
     255, 0,   0,   255,
     0,   255, 0,   255,
     0,   0,   255, 255,
     //Texels for second image.
     255, 255, 255, 255,
     255, 255,   0, 255,
     0,   255, 255, 255,
     255, 0,   255, 255,
};
 
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D_ARRAY,texture);
//Allocate the storage.
glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount);
//Upload pixel data.
//The first 0 refers to the mipmap level (level 0, since there's only 1)
//The following 2 zeroes refers to the x and y offsets in case you only want to specify a subrectangle.
//The final 0 refers to the layer index offset (we start from index 0 and have 2 levels).
//Altogether you can specify a 3D box subset of the overall texture, but only one mip level at a time.
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGBA, GL_UNSIGNED_BYTE, texels);
 
//Always set reasonable texture parameters
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);

GLSL error testing

Shader compilation error checking.

GLuint shader = glCreateShader(...);
 
// Get strings for glShaderSource.
glShaderSource(shader, ...);
 
glCompileShader(shader);
 
GLint isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
	GLint maxLength = 0;
	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
 
	// The maxLength includes the NULL character
	std::vector<GLchar> errorLog(maxLength);
	glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
 
	// Provide the infolog in whatever manor you deem best.
	// Exit with failure.
	glDeleteShader(shader); // Don't leak the shader.
	return;
}
 
// Shader compilation is successful.


Program Linking error checking.

GLuint program = glCreateProgram();
 
//Attach shaders as necessary.
glAttachShader(program, ...);
...
 
//Link the program.
glLinkProgram(program);
 
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
if(isLinked == GL_FALSE)
{
	GLint maxLength = 0;
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
 
	//The maxLength includes the NULL character
	std::vector<GLchar> infoLog(maxLength);
	glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
 
	//The program is useless now. So delete it.
	glDeleteProgram(program);
 
	//Provide the infolog in whatever manner you deem best.
	//Exit with failure.
	return;
}


GLSL shader compilation examples

Full compile/link of a Vertex and Fragment Shader.

//Read our shaders into the appropriate buffers
std::string vertexSource = //Get source code for vertex shader.
std::string fragmentSource = //Get source code for fragment shader.
 
//Create an empty vertex shader handle
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
 
//Send the vertex shader source code to GL
//Note that std::string's .c_str is NULL character terminated.
const GLchar *source = (const GLchar *)vertexSource.c_str();
glShaderSource(vertexShader, 1, &source, 0);
 
//Compile the vertex shader
glCompileShader(vertexShader);
 
GLint isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
	GLint maxLength = 0;
	glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
 
	//The maxLength includes the NULL character
	std::vector<GLchar> infoLog(maxLength);
	glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &infoLog[0]);
 
	//We don't need the shader anymore.
	glDeleteShader(vertexShader);
 
	//Use the infoLog as you see fit.
 
	//In this simple program, we'll just leave
	return;
}
 
//Create an empty fragment shader handle
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
 
//Send the fragment shader source code to GL
//Note that std::string's .c_str is NULL character terminated.
source = (const GLchar *)fragmentSource.c_str();
glShaderSource(fragmentShader, 1, &source, 0);
 
//Compile the fragment shader
glCompileShader(fragmentShader);
 
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
if(isCompiled == GL_FALSE)
{
	GLint maxLength = 0;
	glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &maxLength);
 
	//The maxLength includes the NULL character
	std::vector<GLchar> infoLog(maxLength);
	glGetShaderInfoLog(fragmentShader, maxLength, &maxLength, &infoLog[0]);
 
	//We don't need the shader anymore.
	glDeleteShader(fragmentShader);
	//Either of them. Don't leak shaders.
	glDeleteShader(vertexShader);
 
	//Use the infoLog as you see fit.
 
	//In this simple program, we'll just leave
	return;
}
 
//Vertex and fragment shaders are successfully compiled.
//Now time to link them together into a program.
//Get a program object.
GLuint program = glCreateProgram();
 
//Attach our shaders to our program
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
 
//Link our program
glLinkProgram(program);
 
//Note the different functions here: glGetProgram* instead of glGetShader*.
GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int *)&isLinked);
if(isLinked == GL_FALSE)
{
	GLint maxLength = 0;
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
 
	//The maxLength includes the NULL character
	std::vector<GLchar> infoLog(maxLength);
	glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
 
	//We don't need the program anymore.
	glDeleteProgram(program);
	//Don't leak shaders either.
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);
 
	//Use the infoLog as you see fit.
 
	//In this simple program, we'll just leave
	return;
}
 
//Always detach shaders after a successful link.
glDetachShader(program, vertexShader);
glDetachShader(program, fragmentShader);

Creating two separable programs, one with a vertex shader and one with a fragment shader.

//Create two separable program objects from a 
//single source string respectively (vertSrc and fragSrc)
GLuint vertProg = glCreateShaderProgramv(GL_VERTEX_SHADER  , 1, &vertSrc);
GLuint fragProg = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fragSrc);
 
//CHECK FOR ERRORS HERE!.
 
//Generate a program pipeline and attach the programs to their respective stages
glGenProgramPipelines(1, &pipeline);
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT  , vertProg);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fragProg);
 
//Query and set any uniforms
GLint colorLoc = glGetUniformLocation(fragProg, "Color");
glProgramUniform4f(fragProg, colorLoc, 1.f, 0.f, 0.f, 1.f);


Creates a separate program, where some of the stages are directly linked together.

//Create two programs. One with just the vertex shader, and 
//one with both geometry and fragment stages.
GLuint vertexProgram   = glCreateProgram();
GLuint geomFragProgram = glCreateProgram();
 
//Declare that programs are separable - this is crucial!
glProgramParameteri(vertexProgram  , GL_PROGRAM_SEPARABLE, GL_TRUE);
glProgramParameteri(geomFragProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
 
//Generate and compile shader objects, as normal.
GLuint vertShader  = glCreateShader(GL_VERTEX_SHADER);
GLuint geomShader  = glCreateShader(GL_GEOMETRY_SHADER);
GLuint fragShader  = glCreateShader(GL_FRAGMENT_SHADER);
 
glShaderSource(vertShader, 1, &vertSrc, NULL);
glShaderSource(geomShader, 1, &geomSrc, NULL);
glShaderSource(fragShader, 1, &fragSrc, NULL);
 
glCompileShader(vertShader);
glCompileShader(geomShader);
glCompileShader(fragShader);
 
//Attach the shaders to their respective programs
glAttachShader(vertexProgram  , vertShader);
glAttachShader(geomFragProgram, geomShader);
glAttachShader(geomFragProgram, fragShader);
 
//Perform any pre-linking steps.
glBindAttribLocation(vertexProgram    , 0, "Position");
glBindFragDataLocation(geomFragProgram, 0, "FragColor");
 
//Link the programs
glLinkProgram(vertexProgram);
glLinkProgram(geomFragProgram);
 
//Detach and delete the shader objects
glDetachShader(vertexProgram, vertShader);
glDeleteShader(vertShader);
 
glDetachShader(geomFragProgram, geomShader);
glDetachShader(geomFragProgram, fragShader);
glDeleteShader(geomShader);
glDeleteShader(fragShader);
 
//Generate a program pipeline
glGenProgramPipelines(1, &pipeline);
 
//Attach the first program to the vertex stage, and the second program
//to the geometry and fragment stages
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vertexProgram);
glUseProgramStages(pipeline, GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, geomFragProgram);


Program introspection

Iteration over all non-block uniform variables, fetching their names, types, and locations:

GLint numUniforms = 0;
glGetProgramInterfaceiv(prog, GL_UNIFORM, GL_ACTIVE_RESOURCES, &numUniforms);
const GLenum properties[4] = {GL_BLOCK_INDEX​, GL_TYPE​, GL_NAME_LENGTH​, GL_LOCATION};
 
for(int unif = 0; unif < numUniforms; ++unif)
{
  GLint values[4];
  glGetProgramResourceiv(prog, GL_UNIFORM, unif, 4, properties, 4, NULL, values);
 
  //Skip any uniforms that are in a block.
  if(values[0] != -1)
    continue;
 
  //Get the name. Must use a std::vector rather than a std::string for C++03 standards issues.
  //C++11 would let you use a std::string directly.
  std::vector<char> nameData(values[2]);
  glGetProgramResourceName(prog, GL_UNIFORM, unif, nameData.size(), NULL, &nameData[0]);
  std::string name(nameData.begin(), nameData.end() - 1);
}


Iteration over all uniforms within each uniform block.

GLint numBlocks = 0;
glGetProgramInterfaceiv(prog, GL_UNIFORM_BLOCK, GL_ACTIVE_RESOURCES, &numBlocks);
const GLenum blockProperties[1] = {GL_NUM_ACTIVE_VARIABLES};
const GLenum activeUnifProp[1] = {GL_ACTIVE_VARIABLES};
const GLenum unifProperties[3] = {GL_NAME_LENGTH​, GL_TYPE​, GL_LOCATION};
 
for(int blockIx = 0; blockIx < numBlocks; ++blockIx)
{
  GLint numActiveUnifs = 0;
  glGetProgramResourceiv(prog, GL_UNIFORM_BLOCK, blockIx, 1, blockProperties, 1, NULL, numActiveUnifs);
 
  if(!numActiveUnifs)
    continue;
 
  std::vector<GLint> blockUnifs(numActiveUnifs);
  glGetProgramResourceiv(prog, GL_UNIFORM_BLOCK, blockIx, 1, activeUnifProp, numActiveUnifs, NULL, &blockUnifs[0]);
 
  for(int unifIx = 0; unifIx < numActiveUnifs; ++unifIx)
  {
    GLint values[3];
    glGetProgramResourceiv(prog, GL_UNIFORM, blockUnifs[unifIx], 3, unifProperties, 3, NULL, values);
 
    //Get the name. Must use a std::vector rather than a std::string for C++03 standards issues.
    //C++11 would let you use a std::string directly.
    std::vector<char> nameData(values[0]);
    glGetProgramResourceName(prog, GL_UNIFORM, blockUnifs[unifIx], nameData.size(), NULL, &nameData[0]);
    std::string name(nameData.begin(), nameData.end() - 1);
  }
}