EAGL.Examples.LearnOpenGL.GettingStarted.Textures (eagl v0.3.0)

View Source

LearnOpenGL 4.1 - Textures

This example demonstrates basic texture mapping in OpenGL - applying 2D images to 3D geometry. It corresponds to the Textures tutorial in the LearnOpenGL series and showcases EAGL's comprehensive texture loading capabilities.

Original C++ Source

This example is based on the original LearnOpenGL C++ tutorial: https://github.com/JoeyDeVries/LearnOpenGL/tree/master/src/1.getting_started/4.1.textures

Framework Adaptation Notes

In the original LearnOpenGL C++ tutorial, this example introduces textures:

  • Loading image files using stb_image.h library
  • Creating OpenGL texture objects
  • Setting texture parameters (wrapping, filtering)
  • Texture coordinates and sampling
  • Binding textures before rendering

EAGL's framework preserves all these concepts while providing enhanced functionality:

  • Real Image Loading: Uses the same stb_image library as the original tutorial
  • Graceful Degradation: Automatic fallback to checkerboard patterns when images unavailable
  • Pixel Alignment Handling: Proper handling of non-4-byte-aligned image widths
  • Y-Axis Correction: Automatic Y-flip to match OpenGL coordinate conventions
  • Format Detection: Automatic channel detection (RGB, RGBA) and format selection

EAGL vs Original Implementation

Original LearnOpenGL approach: Uses stb_image.h to load container.jpg:

int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);

EAGL approach: Enhanced image loading with robust error handling:

{:ok, texture_id, width, height} = load_texture_from_file("priv/images/eagl_logo_black_on_white.png")
  • Same underlying library: Uses stb_image (optional dependency)
  • Enhanced error handling: {:ok, result} tuples and comprehensive fallbacks
  • Pixel alignment fix: glPixelStorei(GL_UNPACK_ALIGNMENT, 1) for arbitrary image widths
  • Coordinate system handling: Automatic Y-flip for OpenGL convention
  • Educational value: Works with or without external dependencies

Technical Improvements

This implementation includes several technical enhancements over basic texture loading:

  1. Pixel Alignment: Handles images whose width × channels isn't 4-byte aligned

    • The 418×418 EAGL logo tests this fix (418 × 4 = 1672 bytes per row)
    • Prevents diagonal texture skewing common with arbitrary image dimensions
  2. Y-Axis Handling: Proper coordinate system conversion

    • Images typically have (0,0) at top-left
    • OpenGL expects (0,0) at bottom-left
    • Automatic Y-flip ensures textures appear right-side up
  3. Format Detection: Automatic channel count handling

    • 1 channel → GL_RED
    • 2 channels → GL_RG
    • 3 channels → GL_RGB
    • 4 channels → GL_RGBA

Original Tutorial Concepts Demonstrated

  1. Texture Objects: Creating texture IDs with create_texture()
  2. Texture Binding: Binding textures with :gl.bindTexture()
  3. Texture Parameters: Setting wrap and filter modes with set_texture_parameters()
  4. Texture Data: Loading pixel data with load_texture_data()
  5. Mipmaps: Generating mipmaps with :gl.generateMipmap()
  6. Texture Coordinates: Adding texture coordinates to vertex data
  7. Texture Sampling: Using sampler2D and texture() in fragment shader

Key Learning Points

  • Understanding texture coordinates (0,0 to 1,1 mapping)
  • Texture wrapping modes (repeat, clamp, etc.)
  • Texture filtering (nearest vs linear)
  • The relationship between vertex attributes and fragment shader inputs
  • How textures are sampled and interpolated across triangles
  • Pixel alignment considerations for arbitrary image dimensions
  • Coordinate system differences between image formats and OpenGL

Vertex Data Structure

The rectangle uses interleaved vertex data:

  • Position (3 floats): x, y, z coordinates
  • Color (3 floats): r, g, b values (for potential mixing)
  • Texture coordinates (2 floats): s, t coordinates

Texture Mapping

The rectangle is mapped with texture coordinates:

  • Bottom-left: (0.0, 0.0)
  • Bottom-right: (1.0, 0.0)
  • Top-right: (1.0, 1.0)
  • Top-left: (0.0, 1.0)

Dependencies

  • Optional: {:stb_image, "~> 0.6"} for real image loading
  • Fallback: Procedural checkerboard generation when stb_image unavailable
  • Educational: Works in both scenarios with helpful guidance

Usage

EAGL.Examples.LearnOpenGL.GettingStarted.Textures.run_example()

Press ENTER to exit the example.

Summary

Functions

run_example()

@spec run_example() :: :ok | {:error, term()}