easy-gl › Textured Quad

Textured Quad

Demonstrates loading a 2D texture and rendering it onto a quad with index buffer. Uses alpha blending for transparent textures.

Shaders

const char* vertSrc = R"(#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aUV;
out vec2 vUV;
void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
    vUV = aUV;
})";

const char* fragSrc = R"(#version 330 core
in vec2 vUV;
uniform sampler2D uTex;
out vec4 FragColor;
void main() {
    FragColor = texture(uTex, vUV);
})";

Quad geometry (indexed)

constexpr float quadVerts[] = {
    // pos       uv
    -0.5f, -0.5f,  0.0f, 0.0f,
     0.5f, -0.5f,  1.0f, 0.0f,
     0.5f,  0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f,  0.0f, 1.0f,
};
constexpr unsigned int indices[] = { 0, 1, 2, 2, 3, 0 };

Setup

easygl::Program prog(vertSrc, fragSrc);

// VAO + VBO + IBO
easygl::VertexArray vao;
easygl::Buffer      vbo, ibo;
vao.create(); vbo.create(); ibo.create();

vao.bind();
vbo.bind(easygl::BufferTarget::Array);
vbo.set_data(easygl::BufferTarget::Array, quadVerts, sizeof(quadVerts));
ibo.bind(easygl::BufferTarget::ElementArray);
ibo.set_data(easygl::BufferTarget::ElementArray, indices, sizeof(indices));

constexpr std::size_t stride = 4 * sizeof(float);
vao.set_attribute({0, 2, easygl::DataType::Float, false, stride, 0, true});
vao.set_attribute({1, 2, easygl::DataType::Float, false, stride, 2 * sizeof(float), true});

// Texture (assume stb_image loaded pixels into imageData)
easygl::Texture tex;
tex.create();
tex.bind(easygl::TextureTarget::Texture2D);
tex.set_parameter(easygl::TextureTarget::Texture2D,
                   easygl::TextureParameter::MinFilter,
                   static_cast<int>(easygl::TextureMinFilter::LinearMipmapLinear));
tex.set_parameter(easygl::TextureTarget::Texture2D,
                   easygl::TextureParameter::MagFilter,
                   static_cast<int>(easygl::TextureMagFilter::Linear));
tex.set_storage_2d(easygl::TextureTarget::Texture2D, 4,
                    easygl::InternalFormat::Rgba8, imgWidth, imgHeight);
tex.set_sub_image_2d(easygl::TextureTarget::Texture2D,
                      0, 0, 0, imgWidth, imgHeight,
                      easygl::PixelFormat::Rgba,
                      easygl::PixelType::UnsignedByte,
                      imageData);
tex.generate_mipmap(easygl::TextureTarget::Texture2D);

// Enable alpha blending
device.set_blend_enabled(true);
device.set_blend_func(easygl::BlendFactor::SrcAlpha,
                       easygl::BlendFactor::OneMinusSrcAlpha);

Render loop draw call

device.set_clear_color(0.1f, 0.1f, 0.1f, 1.0f);
device.clear(easygl::ClearFlags::Color);

prog.use();
tex.active_bind(easygl::TextureUnit::Texture0,
                easygl::TextureTarget::Texture2D);
prog.set_uniform(prog.uniform_location("uTex"), 0); // sampler2D = unit 0

vao.bind();
device.draw_elements(easygl::PrimitiveType::Triangles,
                       6, easygl::DataType::UnsignedInt, nullptr);

Key points