opengl3.3 api overview

1. Introduction to OpenGL

OpenGL (Open Graphics Library) is a cross-platform API for rendering 2D and 3D vector graphics. The API is used to interact with a GPU, allowing developers to create graphics programs, primarily for real-time rendering in games, simulations, and other visualizations.

2. Context Creation

OpenGL requires a context to function, which is typically created by a windowing library such as GLFW, SDL, or native platform APIs. OpenGL context holds the state that affects rendering and is necessary for OpenGL commands to work.

3. OpenGL Shading Language (GLSL)

3.1 Shaders

OpenGL uses shaders written in GLSL for programmable rendering. The main types of shaders are:

3.2 Shader Compilation

Shaders are written in GLSL and must be compiled and linked into a program object:

Use case: When creating shaders for your graphics pipeline, you will first create shader objects, load the source, compile them, link them into a program, and finally use that program for rendering.

4. Buffers

4.1 Vertex Buffer Object (VBO)

A VBO stores vertex data in GPU memory:

Use case: When setting up vertex data for rendering, a VBO is created to store the data on the GPU. It can be used for efficient real-time rendering, particularly in 3D graphics.

4.2 Element Buffer Object (EBO)

An EBO stores indices for drawing with vertex array objects:

Use case: When using indexed drawing (i.e., sharing vertices between primitives), an EBO can store indices that reference the vertex data in a VBO.

4.3 Vertex Array Object (VAO)

VAOs store state related to vertex attribute configuration:

Use case: VAOs are crucial for organizing vertex attribute state, especially when working with multiple objects and buffers. They make switching between different sets of vertex attributes easy.

5. Texturing

5.1 Texture Creation

Textures are used to map images onto geometric surfaces:

what kind of targets are there?

1. GL_TEXTURE_2D

Description: Represents a 2D texture with width and height (e.g., an image or texture used in most 3D applications).

Usage Example: Standard texture for mapping on a 3D model surface.

glBindTexture(GL_TEXTURE_2D, textureID);

2. GL_TEXTURE_1D

Description: Represents a 1D texture, which has only a width (e.g., a gradient or color ramp).

Usage Example: Rarely used in modern applications.

glBindTexture(GL_TEXTURE_1D, textureID);

3. GL_TEXTURE_3D

Description: Represents a 3D texture, which has width, height, and depth. Useful for volume textures.

Usage Example: Used in volumetric rendering, like for simulating fog or 3D data fields.

glBindTexture(GL_TEXTURE_3D, textureID);

4. GL_TEXTURE_CUBE_MAP

Description: Represents a cube map texture, which consists of six square 2D textures arranged into a cube. Useful for environment mapping, reflections, and skyboxes.

Usage Example: Used for reflective surfaces like water or mirrors.

glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

5. GL_TEXTURE_RECTANGLE

Description: Represents a non-power-of-two texture (i.e., dimensions don't have to be powers of 2). Texture coordinates are not normalized, meaning they map directly to pixel coordinates.

Usage Example: Used for special cases where non-power-of-two textures are needed.

glBindTexture(GL_TEXTURE_RECTANGLE, textureID);

6. GL_TEXTURE_2D_ARRAY

Description: Represents an array of 2D textures stacked together. Each element in the array is a 2D texture.

Usage Example: Used for texture atlases or handling multiple textures in a single uniform.

glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);

7. GL_TEXTURE_BUFFER

Description: A buffer texture, which allows you to use a buffer object's data (like a vertex buffer) as a texture. This is useful for reading large amounts of data directly into a shader.

Usage Example: For large data sets like particle systems.

glBindTexture(GL_TEXTURE_BUFFER, textureID);

Use case: When applying textures to objects, you'll first create a texture, bind it to the correct target, load the texture image, and set parameters for how it should be applied.

    
GLuint texture_map;
glGenTextures(1, &texture_map);
glBindTexture(GL_TEXTURE_2D, texture_map);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo_width, fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

glBindTexture(GL_TEXTURE_2D, 0);
    

5.2 Texture Units

One way to think about texture units are as picture frames on a wall somewhere, the picture frames are futuristic, and have options, for example if you slide a picture into a picture frame and it doesn't take up the full frame, then you can choose options for that picture frame so that it either repeats the image or tries to extend it in a certain direction, the picture frames support different types of images (texture targets), with their own custom options.

Now drawing the textures is like an art exhibit, at first you have a bunch of empty frames, so we go up to a certain frame glActiveTexture(GL_TEXTURE0), slide our art into it glBindTexture(GL_TEXTURE_2D, texture_map);, in this context shaders are like the art buyers, they go around and sample (bind the texture unit number to the sampler) the artwork then they select what art they like and buy it (draw it), now that they own the art they can do anything they want with it

more on this whole process

Texture Target

Texture targets refer to the different types of textures (2D, 3D, etc.). You can bind multiple textures, one of each type, to the same texture unit. For example:

glBindTexture(GL_TEXTURE_2D, texId1);
glBindTexture(GL_TEXTURE_3D, texId2);

Both texId1 and texId2 are bound to the same texture unit, as they are bound to different targets. It is recommended to bind different textures to different texture units to avoid confusion.

Texture Object

Texture objects are created with glGenTextures() and bound with glBindTexture(). A texture object contains:

  • Texture data.
  • State for sampling the texture, such as filtering attributes set with glTexParameteri().
  • Information about the texture format/type specified with the data.

Texture Unit

Texture units allow multiple textures to be bound at once, supporting multi-texturing. You use glActiveTexture() to specify the active texture unit. For example:

glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texId);

This binds texId to texture unit 3.

Sampler Object

Sampler objects, introduced in OpenGL 3.3, decouple texture data from sampling parameters. This allows one texture to be sampled with different parameters (e.g., LINEAR and NEAREST) in the same shader without needing multiple copies of the texture data.

Texture View

Texture views, available in OpenGL 4.3, decouple raw texture data from its format. This allows the same texture data to be used with different formats.

Connecting Textures to Shaders

To connect textures to shaders, texture units bridge shaders and texture objects. A shader samples from texture units using sampler uniform variables.

Example

If "MyFirstTexture" is a sampler variable in the shader, this code associates it with texture unit 3:

GLint loc = glGetUniformLocation(prog, "MyFirstTexture");
glUniform1i(loc, 3);

Then, bind the texture object to the texture unit:

glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, texId);

The shader will sample from the texture bound to unit 3.

Multi-Texturing Example

For two textures, using texture units 0 and 1:

glUseProgram(prog);

GLint loc = glGetUniformLocation(prog, "MyFirstTexture");
glUniform1i(loc, 0);
loc = glGetUniformLocation(prog, "MySecondTexture");
glUniform1i(loc, 1);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texId0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texId1);

The shader will read data from the textures plugged into the corresponding texture units.

OpenGL allows multiple textures to be bound at once, each to a different texture unit:

Use case: When using multiple textures in a shader, texture units are used to assign textures to different slots, which can be sampled in the shader.

You can get by without understanding texture units, but it will catch up to you, for example the example above when we talked about regular textures showed code that seemed to never use texture units but still works, this is because by default the shader uniform varaible of the sampler is the value 0, moreover when you bind a texture usually GL_TEXTURE0 is already bound, and thus it just so happens that by chance that the uniform is the correct matching value, and the texture shows up, but if you then bind a different texture it will overwrite it and you might start getting confused, so better to understand texture units sooner rather than later.

6. Drawing

6.1 Primitive Drawing

OpenGL supports various drawing primitives such as points, lines, and triangles:

Use case: When drawing shapes in OpenGL, these functions are used to render arrays or elements (indexed drawing) as primitives like triangles, lines, or points.

7. Framebuffers

7.1 Default Framebuffer

By default, OpenGL renders to a window provided by the OS.

7.2 Framebuffer Object (FBO)

FBOs allow off-screen rendering for post-processing, shadow maps, etc.:

Use case: FBOs are used when you want to render off-screen, such as for effects like shadow mapping or post-processing (e.g., bloom, HDR).

8. State Management

8.1 Enabling and Disabling Capabilities

OpenGL has many state variables that control rendering behavior:

Use case: Proper state management is critical in OpenGL. Depth testing, blending, and other features need to be explicitly enabled or disabled based on the rendering requirements.

9. Conclusion

OpenGL is a powerful API for creating 2D and 3D graphics applications. By understanding its core concepts such as context creation, shaders, buffers, texturing, and drawing, developers can effectively utilize OpenGL to create high-performance, real-time visualizations and simulations.


edit this page