AGL
A graphics library
agl::Renderer Class Reference

The Renderer class draws meshes to the screen using shaders. More...

#include <renderer.h>

Public Member Functions

void init ()
 Initialize this class for drawing. More...
 
void cleanup ()
 Cleanup all resources used for drawing. More...
 
bool initialized () const
 Return whether the Renderer is ready for drawing. More...
 
void blendMode (BlendMode mode)
 Mode for combining colors when drawing. More...
 
Projections and view
void perspective (float fovRadians, float aspect, float near, float far)
 Set the current projection to a perspective view. More...
 
void ortho (float minx, float maxx, float miny, float maxy, float minz, float maxz)
 Set the current projection to an orthographic view. More...
 
void lookAt (const glm::vec3 &lookfrom, const glm::vec3 &lookat, const glm::vec3 &up=glm::vec3(0.0f, 1.0f, 0.0f))
 Set the camera position and orientation. More...
 
glm::vec3 cameraPosition () const
 Get the current camera position. More...
 
glm::mat4 projectionMatrix () const
 Get the current projection matrix. More...
 
glm::mat4 viewMatrix () const
 Get the current view matrix. More...
 
Shaders
void loadShader (const std::string &name, const std::string &vs, const std::string &fs)
 Load a GLSL shader from files. More...
 
void beginShader (const std::string &shaderName)
 Set active shader to use for rendering. More...
 
void endShader ()
 Clear active shader to use for rendering. More...
 
void beginRenderTexture (const std::string &targetName)
 Render to a texture instead of to the screen @targetName The name of the texture target. More...
 
void endRenderTexture ()
 Revert to rendering to the screen. More...
 
The name of the render target and corresponding render texture. Use

Load and configure a render texture target

this name to activate the target and to use the rendered texture later. @slot The texture slot associated with the rendered texture @width The width in pixels of the rendered texture @height The height in pixels of the rendered texture

See also
beginRenderTexture
endRenderTexture
// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;
class MyWindow : public agl::Window {
  void setup() {
    renderer.loadRenderTexture("teapotTex", 0, 512, 512);
  }

  void draw() {
    renderer.beginRenderTexture("teapotTex");
    background(vec3(0.5, 1.0, 0.0));
    renderer.setUniform("MainTexture.enabled", false);
    renderer.scale(vec3(sin(elapsedTime())));
    renderer.teapot();
    renderer.endRenderTexture();

    background(vec3(0.3));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.texture("MainTexture.texture", "teapotTex");
    renderer.identity();
    renderer.rotate(elapsedTime(), vec3(1, 1, 0));
    renderer.cube();
  }
};

int main() {
  MyWindow window;
  window.run();
}
void loadRenderTexture (const std::string &name, int slot, int width, int height)
 
void cleanupShaders ()
 Clear all active shaders. More...
 
void setUniform (const std::string &name, float x, float y, float z)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, float x, float y, float z, float w)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, const glm::vec2 &v)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, const glm::vec3 &v)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, const glm::vec4 &v)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, const glm::mat4 &m)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, const glm::mat3 &m)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, float val)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, int val)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, bool val)
 Set a uniform parameter in the currently active shader. More...
 
void setUniform (const std::string &name, GLuint val)
 Set a uniform parameter in the currently active shader. More...
 
void texture (const std::string &uniformName, const std::string &textureName)
 Set a uniform sampler parameter in the currently active shader. More...
 
void cubemap (const std::string &uniformName, const std::string &texName)
 Set a uniform sampler parameter in the currently active shader. More...
 
Loading textures

Textures should typically be loaded from setup()

void loadTexture (const std::string &name, const std::string &filename, int slot)
 Load a texture from a file. More...
 
void loadTexture (const std::string &name, const Image &img, int slot)
 Load a texture from an Image.
 
void loadCubemap (const std::string &name, const std::string &dir, int slot)
 Load a cube map.
 
void loadCubemap (const std::string &name, const std::vector< std::string > &names, int slot)
 Load a cube map.
 
void loadCubemap (const std::string &name, const std::vector< Image > &images, int slot)
 Load a cube map.
 
Positioning
void push ()
 Push the current matrix onto the matrix stack. More...
 
void pop ()
 Pop the current matrix off the matrix stack. More...
 
void identity ()
 Clear the current transform. More...
 
void scale (const glm::vec3 &xyz)
 Scale an object. More...
 
void translate (const glm::vec3 &xyz)
 Translate an object. More...
 
void rotate (float angleRad, const glm::vec3 &axis)
 Rotates an object. More...
 
void transform (const glm::mat4 &trs)
 Transforms an object by the given matrix. More...
 
Drawing
void sprite (const glm::vec3 &pos, const glm::vec4 &color, float size)
 Draws a sprite using a point billboard. More...
 
void line (const glm::vec3 &p1, const glm::vec3 &p2, const glm::vec3 &c1, const glm::vec3 &c2)
 Draws a sprite using a point billboard. More...
 
void text (const std::string &text, float x, float y)
 Draws text using the current font size and color. More...
 
void fontColor (const glm::vec4 &color)
 Set font color for drawing text. More...
 
void fontSize (int s)
 Set font size for drawing text. More...
 
float textWidth (const std::string &text)
 Get the width of a string (font metrics) More...
 
float textHeight ()
 Get the height of a string (font metrics) More...
 
void sphere ()
 Draws a sphere centered at the origin with radius 0.5. More...
 
void cube ()
 Draws a cube centered at the origin with width, height, and depth equal to 1.0. More...
 
void cone ()
 Draws a cone centered at the origin, with the tip towards +Z. More...
 
void teapot ()
 Draws a teapot with largest side with width 1. More...
 
void plane ()
 Draws a plane. More...
 
void cylinder ()
 Draws a teapot with largest side with width 1. More...
 
void capsule ()
 Draws a capsule with endpoints at (0,0,0) and (0,0,1). The cap radius is 0.25 and the width is 0.5. More...
 
void torus ()
 Draws a torus. More...
 
void skybox (float size=10.0)
 Draws a skybox (typically with a cubemap) More...
 
void mesh (const Mesh &m)
 Draws a custom mesh. More...
 

Detailed Description

The Renderer class draws meshes to the screen using shaders.

Member Function Documentation

◆ beginRenderTexture()

void agl::Renderer::beginRenderTexture ( const std::string &  targetName)

Render to a texture instead of to the screen @targetName The name of the texture target.

After calling this function, all subsequent draw calls will be rendered to the associated texture target instead of the screen. The render target should be initialized in setup() using loadRenderTexture. Only one render target can be active at a time. Calling beginRenderTexture more than one without calling endRenderTexture will result in an error.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;
class MyWindow : public agl::Window {
  void setup() {
    renderer.loadRenderTexture("teapotTex", 0, 512, 512);
  }

  void draw() {
    renderer.beginRenderTexture("teapotTex");
    background(vec3(0.5, 1.0, 0.0));
    renderer.setUniform("MainTexture.enabled", false);
    renderer.scale(vec3(sin(elapsedTime())));
    renderer.teapot();
    renderer.endRenderTexture();

    background(vec3(0.3));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.texture("MainTexture.texture", "teapotTex");
    renderer.identity();
    renderer.rotate(elapsedTime(), vec3(1, 1, 0));
    renderer.cube();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ beginShader()

void agl::Renderer::beginShader ( const std::string &  shaderName)

Set active shader to use for rendering.

One shadr must always be enabled for drawing to work. By default, "phong" is enabled. The shader needs to be already loaded (in setup) using loadShader The renderer automatically loads shaders for "phong", "sprites", and "cubemap".

Usage

beginShader("myShader");
// draw primitives
See also
loadShader

◆ blendMode()

void agl::Renderer::blendMode ( BlendMode  mode)

Mode for combining colors when drawing.

The alpha component controls how colors will be combined based on the current mode. Transparent objects should be drawn back to front in relation to the camera.

  • DEFAULT Ignore alpha and draw all objects as opaque
  • ADD Add colors using formula: cSrc + c * c.alpha
  • ALPHA Blend colors using formula: cSrc * alpha + c * (1 - c.alpha)
    // Copyright 2020, Savvy Sine, Aline Normoyle
    
    #include "agl/window.h"
    
    using glm::vec3;
    
    class MyWindow : public agl::Window {
      void setup() {
        renderer.loadTexture("cloud", "../textures/cloud.png", 0);
        renderer.loadTexture("particle", "../textures/particle.png", 0);
        renderer.blendMode(agl::ADD);
      }
    
      void draw() {
        renderer.beginShader("sprite");
        renderer.texture("image", "cloud");
        renderer.sprite(vec3(-0.5f, 0.0f, 0.0f), red, 0.25f);
        renderer.sprite(vec3(0.5f, 0.0f, 0.0f), green, 0.25f);
    
        renderer.texture("image", "particle");
        renderer.sprite(vec3(0.0f, 0.25f, 0.0f), blue, 0.25f);
        renderer.endShader();
      }
    
      const glm::vec4 red = glm::vec4(1, 0, 0, 1);
      const glm::vec4 green = glm::vec4(0, 1, 0, 1);
      const glm::vec4 blue = glm::vec4(0, 0, 1, 1);
    };
    
    int main() {
      MyWindow window;
      window.run();
    }
    

◆ cameraPosition()

vec3 agl::Renderer::cameraPosition ( ) const

Get the current camera position.

 

◆ capsule()

void agl::Renderer::capsule ( )

Draws a capsule with endpoints at (0,0,0) and (0,0,1). The cap radius is 0.25 and the width is 0.5.

◆ cleanup()

void agl::Renderer::cleanup ( )

Cleanup all resources used for drawing.

This method must be called before any draw or shader calls. Window calls this method automatically. Users should not call this method.

◆ cleanupShaders()

void agl::Renderer::cleanupShaders ( )

Clear all active shaders.

Resets all active shaders (e.g. those for which beginShader has been called but endShader() hasn't). This function is called by Window at the end up each frame (users shouldn't need to call this function)

See also
endShader

◆ cone()

void agl::Renderer::cone ( )

Draws a cone centered at the origin, with the tip towards +Z.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;
using glm::vec4;
using glm::mat3;
using glm::mat4;

class MyWindow : public agl::Window {
  void draw() {
    // point forward direction of cone towards n
    // and shift base of cone to (0, 0, 0)
    vec3 n(1, 1, 0);
    vec3 z = normalize(n);
    vec3 x = glm::cross(vec3(0, 1, 0), z);
    vec3 y = glm::cross(z, x);

    mat4 T(vec4(x, 0),
           vec4(y, 0),
           vec4(z, 0),
           vec4(0.25, 0.25, 0, 1));

    renderer.transform(T);
    renderer.cone();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ cube()

void agl::Renderer::cube ( )

Draws a cube centered at the origin with width, height, and depth equal to 1.0.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    float angleRad = elapsedTime();  // angle is in radians
    renderer.rotate(angleRad, glm::vec3(0.707f, 0.707f, 0.0f));
    renderer.cube();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ cubemap()

void agl::Renderer::cubemap ( const std::string &  uniformName,
const std::string &  texName 
)

Set a uniform sampler parameter in the currently active shader.

The name should match the name of the uniform parameter. The cubemap should already be loaded. The textureName should match the key given when the texture is loaded.

See also
loadCubemap
// Copyright (c) 2020, Savvy Sine, Aline Normoyle
// Visualize a cubemap texture using the skybox primitive

#include "agl/window.h"

class MyWindow : public agl::Window {
  void setup() {
    renderer.loadCubemap("cubemap", "../textures/sea", 0);
    perspective(glm::radians<float>(60.0f), 1.0f, 0.1f, 100.0f);
  }

  void draw() {
    renderer.beginShader("cubemap");
    renderer.skybox(10);
    renderer.endShader();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ cylinder()

void agl::Renderer::cylinder ( )

Draws a teapot with largest side with width 1.

◆ endRenderTexture()

void agl::Renderer::endRenderTexture ( )

Revert to rendering to the screen.

Calling this method without a matching beginRenderTexture method results in an error.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;
class MyWindow : public agl::Window {
  void setup() {
    renderer.loadRenderTexture("teapotTex", 0, 512, 512);
  }

  void draw() {
    renderer.beginRenderTexture("teapotTex");
    background(vec3(0.5, 1.0, 0.0));
    renderer.setUniform("MainTexture.enabled", false);
    renderer.scale(vec3(sin(elapsedTime())));
    renderer.teapot();
    renderer.endRenderTexture();

    background(vec3(0.3));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.texture("MainTexture.texture", "teapotTex");
    renderer.identity();
    renderer.rotate(elapsedTime(), vec3(1, 1, 0));
    renderer.cube();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ endShader()

void agl::Renderer::endShader ( )

Clear active shader to use for rendering.

See also
beginShader

◆ fontColor()

void agl::Renderer::fontColor ( const glm::vec4 &  color)

Set font color for drawing text.

Parameters
colorA RGBA color with values in range [0,1]

◆ fontSize()

void agl::Renderer::fontSize ( int  s)

Set font size for drawing text.

Parameters
sizeThe point size of the font

◆ identity()

void agl::Renderer::identity ( )

Clear the current transform.

Sets the current matrix to the identity matrix (e.g. no transform)

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec2;
using glm::vec3;
using glm::vec4;

class MyWindow : public agl::Window {
  void setup() {
    renderer.setUniform("Fog.enabled", true);
    renderer.setUniform("Fog.color", vec3(0.9f));
    renderer.setUniform("Fog.minDist", 5.0f);
    renderer.setUniform("Fog.maxDist", 9.0f);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("MainTexture.tile", vec2(20.0));

    int halfw = 32;
    int halfh = 32;
    agl::Image checker(halfw*2, halfh*2);
    for (int i = 0; i < checker.height(); i++) {
      for (int j = 0; j < checker.width(); j++) {
        if ((i < halfh && j < halfw) || (i > halfh && j > halfw)) {
          checker.setVec4(i, j, vec4(0.7, 0.7, 0.7, 1));
        } else {
          checker.setVec4(i, j, vec4(1, 1, 1, 1));
        }
      }
    }
    renderer.loadTexture("checker", checker, 0);

    setupPerspectiveScene(vec3(0.0), vec3(5.0));
    background(vec3(0.9f));
  }

  void draw() {
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("Material.diffuse", vec3(1));
    renderer.texture("MainTexture.texture", "checker");
    renderer.identity();
    renderer.translate(vec3(0));
    renderer.scale(vec3(20.0f));
    renderer.plane();

    renderer.setUniform("MainTexture.enabled", false);
    renderer.setUniform("Material.specular", vec3(1));
    renderer.setUniform("Material.diffuse", vec3(1, 0, 0));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 1, 0));
    renderer.capsule();

    renderer.setUniform("Material.diffuse", vec3(0.5, 1, 0));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.cone();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 1));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.sphere();

    renderer.setUniform("Material.diffuse", vec3(1, 1, 0.3));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(-0.5, 0.5, 0));
    renderer.cube();

    renderer.setUniform("Material.diffuse", vec3(1, 0.8, 0.1));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(1, 0.5, 0));
    renderer.cylinder();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 0.5));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 0));
    renderer.scale(vec3(0.75));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.teapot();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ init()

void agl::Renderer::init ( )

Initialize this class for drawing.

This method must be called before any draw or shader calls. Window calls this method automatically. Users should not call this method.

◆ initialized()

bool agl::Renderer::initialized ( ) const

Return whether the Renderer is ready for drawing.

Returns
Returns true if initialized; false otherwise

◆ line()

void agl::Renderer::line ( const glm::vec3 &  p1,
const glm::vec3 &  p2,
const glm::vec3 &  c1,
const glm::vec3 &  c2 
)

Draws a sprite using a point billboard.

Parameters
p1The location of the first point
p2The location of the second point
c1The color of the first point
c2The color of the second point

◆ loadShader()

void agl::Renderer::loadShader ( const std::string &  name,
const std::string &  vs,
const std::string &  fs 
)

Load a GLSL shader from files.

Parameters
nameA nickname for the shader to be used in beginShader()
vsThe vertex shader file name
vsThe fragment shader file name

Shaders should be loaded in setup() The default shader is "phong". The renderer automatically loads shaders for "phong", "sprites", and "cubemap". Paths are relative to the directory from which you run your application.

See also
beginShader

◆ loadTexture()

void agl::Renderer::loadTexture ( const std::string &  name,
const std::string &  filename,
int  slot 
)

Load a texture from a file.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;

class MyWindow : public agl::Window {
  void setup() {
    renderer.loadTexture("cloud", "../textures/cloud.png", 0);
    renderer.loadTexture("particle", "../textures/particle.png", 0);
    renderer.blendMode(agl::ADD);
  }

  void draw() {
    renderer.beginShader("sprite");
    renderer.texture("image", "cloud");
    renderer.sprite(vec3(-0.5f, 0.0f, 0.0f), red, 0.25f);
    renderer.sprite(vec3(0.5f, 0.0f, 0.0f), green, 0.25f);

    renderer.texture("image", "particle");
    renderer.sprite(vec3(0.0f, 0.25f, 0.0f), blue, 0.25f);
    renderer.endShader();
  }

  const glm::vec4 red = glm::vec4(1, 0, 0, 1);
  const glm::vec4 green = glm::vec4(0, 1, 0, 1);
  const glm::vec4 blue = glm::vec4(0, 0, 1, 1);
};

int main() {
  MyWindow window;
  window.run();
}

◆ lookAt()

void agl::Renderer::lookAt ( const glm::vec3 &  lookfrom,
const glm::vec3 &  lookat,
const glm::vec3 &  up = glm::vec3(0.0f, 1.0f, 0.0f) 
)

Set the camera position and orientation.

Parameters
lookfromThe position of the camera (default is vec3(0,0,2))
lookatThe target the camera is facing (default is vec3(0,0,0))
upThe "up" direction of the camera (typically vec3(0,1,0))

If you are using Renderer from the Window class, you should call Window::lookAt instead of this method. NOTE: lookfrom and lookat should never be equal!

The current shader should define the following uniform variables

  • uniform mat4 MVP A 4x4 matrix containing the product of projection * view * modelTransform
  • uniform mat4 ModelViewMatrix A 4x4 matrix containing the product of view * modelTransform
  • uniform mat4 NormalMatrix A 3x3 matrix for transforming normals.

◆ mesh()

void agl::Renderer::mesh ( const Mesh m)

Draws a custom mesh.

Meshes can be loaded from a file or created procedurally. Subclasses of leMesh should minimally define positions, normals, and indices. Texture (UV) coordinates and tangents may also be defined.

See also
TriangleMesh
LineMesh
PointMesh

◆ ortho()

void agl::Renderer::ortho ( float  minx,
float  maxx,
float  miny,
float  maxy,
float  minz,
float  maxz 
)

Set the current projection to an orthographic view.

Parameters
minxThe left side of the projection
maxxThe right side of the projection
minyThe bottom side of the projection
maxyThe top side of the projection
minzThe back side of the projection
maxzThe front side of the projection

If you are using Renderer from the Window class, you should call Window::ortho instead of this method.

An orthographic projection maintains parallel lines. All objects maintain their size regardless of distance to the camera. Only objects within the extents of the orthographic cuboid volume will be drawn.

The current shader should define the following uniform variables

uniform mat4 MVP A 4x4 matrix containing the product of projection * view * modelTransform

◆ perspective()

void agl::Renderer::perspective ( float  fovRadians,
float  aspect,
float  near,
float  far 
)

Set the current projection to a perspective view.

Parameters
fovRadiansThe field of view
aspectThe aspect ratio (width divided by height) of the screen
nearThe distance to the near plane from the camera
farThe distance to the far plane from the camera

If you are using Renderer from the Window class, you should call Window::perspective instead of this method.

Perspective projections foreshorten objects should that closer objects are larger than further objects. Only objects within the view volume will be drawn. For example, objects a distance further from the far plane will not be visible.

The current shader should define the following uniform variables

uniform mat4 MVP A 4x4 matrix containing the product of projection * view * modelTransform

◆ plane()

void agl::Renderer::plane ( )

Draws a plane.

◆ pop()

void agl::Renderer::pop ( )

Pop the current matrix off the matrix stack.

Push the current matrix onto the matrix stack. Use push() and pop() matrix to position objects relative to other objects. For example, a character might have an arm which rotates relative to the rest of its body as it moves forward.

renderer.translate(..);
// draw body
renderer.push();
renderer.rotate(...);
// draw arm
renderer.pop();
// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec2;
using glm::vec3;
using glm::vec4;

class MyWindow : public agl::Window {
  void setup() {
    renderer.setUniform("Fog.enabled", true);
    renderer.setUniform("Fog.color", vec3(0.9f));
    renderer.setUniform("Fog.minDist", 5.0f);
    renderer.setUniform("Fog.maxDist", 9.0f);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("MainTexture.tile", vec2(20.0));

    int halfw = 32;
    int halfh = 32;
    agl::Image checker(halfw*2, halfh*2);
    for (int i = 0; i < checker.height(); i++) {
      for (int j = 0; j < checker.width(); j++) {
        if ((i < halfh && j < halfw) || (i > halfh && j > halfw)) {
          checker.setVec4(i, j, vec4(0.7, 0.7, 0.7, 1));
        } else {
          checker.setVec4(i, j, vec4(1, 1, 1, 1));
        }
      }
    }
    renderer.loadTexture("checker", checker, 0);

    setupPerspectiveScene(vec3(0.0), vec3(5.0));
    background(vec3(0.9f));
  }

  void draw() {
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("Material.diffuse", vec3(1));
    renderer.texture("MainTexture.texture", "checker");
    renderer.identity();
    renderer.translate(vec3(0));
    renderer.scale(vec3(20.0f));
    renderer.plane();

    renderer.setUniform("MainTexture.enabled", false);
    renderer.setUniform("Material.specular", vec3(1));
    renderer.setUniform("Material.diffuse", vec3(1, 0, 0));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 1, 0));
    renderer.capsule();

    renderer.setUniform("Material.diffuse", vec3(0.5, 1, 0));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.cone();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 1));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.sphere();

    renderer.setUniform("Material.diffuse", vec3(1, 1, 0.3));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(-0.5, 0.5, 0));
    renderer.cube();

    renderer.setUniform("Material.diffuse", vec3(1, 0.8, 0.1));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(1, 0.5, 0));
    renderer.cylinder();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 0.5));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 0));
    renderer.scale(vec3(0.75));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.teapot();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ projectionMatrix()

glm::mat4 agl::Renderer::projectionMatrix ( ) const
inline

Get the current projection matrix.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include <vector>
#include "agl/window.h"

using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::mat4;

class MyWindow : public agl::Window {
  void setup() {
    setCameraEnabled(false);  // distance orbit camera
    renderer.loadTexture("particle", "../textures/particle.png", 0);
    renderer.blendMode(agl::ADD);
    _particlePos = vec3(0.0f);
    _lastParticlePos = _particlePos;
  }

  void draw() {
    renderer.beginShader("sprite");
    renderer.texture("image", "particle");
    renderer.sprite(_particlePos, _color, 0.5f);
    renderer.endShader();
  }

  void mouseMotion(int x, int y, int dx, int dy) {
    if (_selected) {
      // convert movement into an amount to change the particle (in world space)
      vec2 screenDir(dx, -dy);
      vec2 ndcDir = (2.0f * screenDir / vec2(width(), height()));

      mat4 projection = renderer.projectionMatrix();
      mat4 view = renderer.viewMatrix();

      vec3 pDir = vec3(ndcDir, 0.0);
      mat4 PV = projection * view;
      vec3 delta = vec3(inverse(PV) * vec4(pDir, 0.0));

      _particlePos = _lastParticlePos + delta;
    }
  }

  void mouseDown(int button, int mods) {
    vec2 mousePos = mousePosition();

    // Convert the particle position to screen coords
    mat4 projection = renderer.projectionMatrix();
    mat4 view = renderer.viewMatrix();

    vec4 projectedPos = projection * view * vec4(_particlePos, 1.0);
    vec3 ndcPos = vec3(projectedPos) / projectedPos.w;

    vec2 screenPos = (vec2(ndcPos) + vec2(1.0)) * 0.5f;
    screenPos = screenPos * vec2(width(), height());

    // flip y coordinate because positive Y goes down instead of up
    screenPos.y = height() - screenPos.y;

    if (length(screenPos - mousePos) < _threshold) {
      _color = vec4(1, 1, 0, 1);
      _selected = true;
      _lastParticlePos = _particlePos;
    }
  }

  void mouseUp(int button, int mods) {
    _color = vec4(0, 0, 1, 1);
    _selected = false;
  }

 private:
  vec3 _particlePos;
  vec3 _lastParticlePos;
  vec4 _color = vec4(0, 0, 1, 1);
  bool _selected = false;
  float _threshold = 10;
};

int main() {
  MyWindow window;
  window.run();
}

◆ push()

void agl::Renderer::push ( )

Push the current matrix onto the matrix stack.

Use push() and pop() matrix to position objects relative to other objects. For example, a character might have an arm which rotates relative to the rest of its body as it moves forward.

renderer.translate(..);
// draw body
renderer.push();
renderer.rotate(...);
// draw arm
renderer.pop();
// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec2;
using glm::vec3;
using glm::vec4;

class MyWindow : public agl::Window {
  void setup() {
    renderer.setUniform("Fog.enabled", true);
    renderer.setUniform("Fog.color", vec3(0.9f));
    renderer.setUniform("Fog.minDist", 5.0f);
    renderer.setUniform("Fog.maxDist", 9.0f);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("MainTexture.tile", vec2(20.0));

    int halfw = 32;
    int halfh = 32;
    agl::Image checker(halfw*2, halfh*2);
    for (int i = 0; i < checker.height(); i++) {
      for (int j = 0; j < checker.width(); j++) {
        if ((i < halfh && j < halfw) || (i > halfh && j > halfw)) {
          checker.setVec4(i, j, vec4(0.7, 0.7, 0.7, 1));
        } else {
          checker.setVec4(i, j, vec4(1, 1, 1, 1));
        }
      }
    }
    renderer.loadTexture("checker", checker, 0);

    setupPerspectiveScene(vec3(0.0), vec3(5.0));
    background(vec3(0.9f));
  }

  void draw() {
    renderer.setUniform("MainTexture.enabled", true);
    renderer.setUniform("Material.specular", vec3(0.0));
    renderer.setUniform("Material.diffuse", vec3(1));
    renderer.texture("MainTexture.texture", "checker");
    renderer.identity();
    renderer.translate(vec3(0));
    renderer.scale(vec3(20.0f));
    renderer.plane();

    renderer.setUniform("MainTexture.enabled", false);
    renderer.setUniform("Material.specular", vec3(1));
    renderer.setUniform("Material.diffuse", vec3(1, 0, 0));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 1, 0));
    renderer.capsule();

    renderer.setUniform("Material.diffuse", vec3(0.5, 1, 0));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.cone();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 1));
    renderer.identity();
    renderer.translate(vec3(0, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.sphere();

    renderer.setUniform("Material.diffuse", vec3(1, 1, 0.3));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 1));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(-0.5, 0.5, 0));
    renderer.cube();

    renderer.setUniform("Material.diffuse", vec3(1, 0.8, 0.1));
    renderer.identity();
    renderer.translate(vec3(-1, 0.5, 0));
    renderer.scale(vec3(0.5));
    renderer.rotate(elapsedTime(), vec3(1, 0.5, 0));
    renderer.cylinder();

    renderer.setUniform("Material.diffuse", vec3(1, 0, 0.5));
    renderer.identity();
    renderer.translate(vec3(1, 0.5, 0));
    renderer.scale(vec3(0.75));
    renderer.rotate(elapsedTime(), vec3(0.5, 0.5, 0));
    renderer.teapot();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ rotate()

void agl::Renderer::rotate ( float  angleRad,
const glm::vec3 &  axis 
)

Rotates an object.

Parameters
angleRadThe angle to rotate in radians
axisThe axis to rotate around

Rotates the object by angleRad around the given axis. Transformations are relative to the current position, size, and rotation of the object.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    float angleRad = elapsedTime();  // angle is in radians
    renderer.rotate(angleRad, glm::vec3(0.707f, 0.707f, 0.0f));
    renderer.cube();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ scale()

void agl::Renderer::scale ( const glm::vec3 &  xyz)

Scale an object.

Parameters
xyzThe proportions to resize the object.

Changes the size of an object in each of the XYZ directions. For example, an x-component of 0.5 halves the size of the object in the X direction. Transformations are relative to the current position, size, and rotation of the object.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    renderer.scale(glm::vec3(0.75f, 0.5f, 1.0f));
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [1/11]

void agl::Renderer::setUniform ( const std::string &  name,
bool  val 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [2/11]

void agl::Renderer::setUniform ( const std::string &  name,
const glm::mat3 &  m 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [3/11]

void agl::Renderer::setUniform ( const std::string &  name,
const glm::mat4 &  m 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [4/11]

void agl::Renderer::setUniform ( const std::string &  name,
const glm::vec2 &  v 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [5/11]

void agl::Renderer::setUniform ( const std::string &  name,
const glm::vec3 &  v 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [6/11]

void agl::Renderer::setUniform ( const std::string &  name,
const glm::vec4 &  v 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [7/11]

void agl::Renderer::setUniform ( const std::string &  name,
float  val 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [8/11]

void agl::Renderer::setUniform ( const std::string &  name,
float  x,
float  y,
float  z 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [9/11]

void agl::Renderer::setUniform ( const std::string &  name,
float  x,
float  y,
float  z,
float  w 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [10/11]

void agl::Renderer::setUniform ( const std::string &  name,
GLuint  val 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ setUniform() [11/11]

void agl::Renderer::setUniform ( const std::string &  name,
int  val 
)

Set a uniform parameter in the currently active shader.

The name should match the name of the uniform parameter. Overrides correspond to different uniform variable types (which should also match).

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    // Set diffuse color in shaders/phong.fs to blue
    renderer.setUniform("Material.diffuse", 0.4f, 0.6f, 1.0f);
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ skybox()

void agl::Renderer::skybox ( float  size = 10.0)

Draws a skybox (typically with a cubemap)

// Copyright (c) 2020, Savvy Sine, Aline Normoyle
// Visualize a cubemap texture using the skybox primitive

#include "agl/window.h"

class MyWindow : public agl::Window {
  void setup() {
    renderer.loadCubemap("cubemap", "../textures/sea", 0);
    perspective(glm::radians<float>(60.0f), 1.0f, 0.1f, 100.0f);
  }

  void draw() {
    renderer.beginShader("cubemap");
    renderer.skybox(10);
    renderer.endShader();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ sphere()

void agl::Renderer::sphere ( )

Draws a sphere centered at the origin with radius 0.5.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ sprite()

void agl::Renderer::sprite ( const glm::vec3 &  pos,
const glm::vec4 &  color,
float  size 
)

Draws a sprite using a point billboard.

Parameters
posThe location of the center of the sprite
colorThe color of the sprite
sizeThe size (width/height) of the billboard
// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;

class MyWindow : public agl::Window {
  void setup() {
    renderer.loadTexture("cloud", "../textures/cloud.png", 0);
    renderer.loadTexture("particle", "../textures/particle.png", 0);
    renderer.blendMode(agl::ADD);
  }

  void draw() {
    renderer.beginShader("sprite");
    renderer.texture("image", "cloud");
    renderer.sprite(vec3(-0.5f, 0.0f, 0.0f), red, 0.25f);
    renderer.sprite(vec3(0.5f, 0.0f, 0.0f), green, 0.25f);

    renderer.texture("image", "particle");
    renderer.sprite(vec3(0.0f, 0.25f, 0.0f), blue, 0.25f);
    renderer.endShader();
  }

  const glm::vec4 red = glm::vec4(1, 0, 0, 1);
  const glm::vec4 green = glm::vec4(0, 1, 0, 1);
  const glm::vec4 blue = glm::vec4(0, 0, 1, 1);
};

int main() {
  MyWindow window;
  window.run();
}

◆ teapot()

void agl::Renderer::teapot ( )

Draws a teapot with largest side with width 1.

◆ text()

void agl::Renderer::text ( const std::string &  text,
float  x,
float  y 
)

Draws text using the current font size and color.

Parameters
textThe phrase to display
xThe x-location of the text (left-most point). Range [0, screenwidth]
yThe y-location of the text (bottom-most point). Range [0, screenheight]

◆ textHeight()

float agl::Renderer::textHeight ( )

Get the height of a string (font metrics)

Returns
The height of the string in screen coordinates

◆ texture()

void agl::Renderer::texture ( const std::string &  uniformName,
const std::string &  textureName 
)

Set a uniform sampler parameter in the currently active shader.

The name should match the name of the uniform parameter. The texture should already be loaded. The textureName should match the key given when the texture is loaded.

See also
loadTexture
// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;

class MyWindow : public agl::Window {
  void setup() {
    renderer.loadTexture("cloud", "../textures/cloud.png", 0);
    renderer.loadTexture("particle", "../textures/particle.png", 0);
    renderer.blendMode(agl::ADD);
  }

  void draw() {
    renderer.beginShader("sprite");
    renderer.texture("image", "cloud");
    renderer.sprite(vec3(-0.5f, 0.0f, 0.0f), red, 0.25f);
    renderer.sprite(vec3(0.5f, 0.0f, 0.0f), green, 0.25f);

    renderer.texture("image", "particle");
    renderer.sprite(vec3(0.0f, 0.25f, 0.0f), blue, 0.25f);
    renderer.endShader();
  }

  const glm::vec4 red = glm::vec4(1, 0, 0, 1);
  const glm::vec4 green = glm::vec4(0, 1, 0, 1);
  const glm::vec4 blue = glm::vec4(0, 0, 1, 1);
};

int main() {
  MyWindow window;
  window.run();
}

◆ textWidth()

float agl::Renderer::textWidth ( const std::string &  text)

Get the width of a string (font metrics)

Parameters
textThe phrase to display
Returns
The width of the string in screen coordinates

◆ torus()

void agl::Renderer::torus ( )

Draws a torus.

◆ transform()

void agl::Renderer::transform ( const glm::mat4 &  trs)

Transforms an object by the given matrix.

Parameters
trsThe matrix transform

Typically this matrix will be the product of translation * rotate * scale matrices. Transformations are relative to the current position, size, and rotation of the object.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

using glm::vec3;
using glm::vec4;
using glm::mat3;
using glm::mat4;

class MyWindow : public agl::Window {
  void draw() {
    // point forward direction of cone towards n
    // and shift base of cone to (0, 0, 0)
    vec3 n(1, 1, 0);
    vec3 z = normalize(n);
    vec3 x = glm::cross(vec3(0, 1, 0), z);
    vec3 y = glm::cross(z, x);

    mat4 T(vec4(x, 0),
           vec4(y, 0),
           vec4(z, 0),
           vec4(0.25, 0.25, 0, 1));

    renderer.transform(T);
    renderer.cone();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ translate()

void agl::Renderer::translate ( const glm::vec3 &  xyz)

Translate an object.

Parameters
xyzThe direction to move the object.

Moves the object in each of the XYZ directions. For example, an x-component of 10 will move the object in the positive X direction. Transformations are relative to the current position, size, and rotation of the object.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include "agl/window.h"

class MyWindow : public agl::Window {
  void draw() {
    float x = sin(elapsedTime());
    renderer.translate(glm::vec3(x, 0.0, 0.0));
    renderer.sphere();
  }
};

int main() {
  MyWindow window;
  window.run();
}

◆ viewMatrix()

glm::mat4 agl::Renderer::viewMatrix ( ) const
inline

Get the current view matrix.

// Copyright 2020, Savvy Sine, Aline Normoyle

#include <vector>
#include "agl/window.h"

using glm::vec2;
using glm::vec3;
using glm::vec4;
using glm::mat4;

class MyWindow : public agl::Window {
  void setup() {
    setCameraEnabled(false);  // distance orbit camera
    renderer.loadTexture("particle", "../textures/particle.png", 0);
    renderer.blendMode(agl::ADD);
    _particlePos = vec3(0.0f);
    _lastParticlePos = _particlePos;
  }

  void draw() {
    renderer.beginShader("sprite");
    renderer.texture("image", "particle");
    renderer.sprite(_particlePos, _color, 0.5f);
    renderer.endShader();
  }

  void mouseMotion(int x, int y, int dx, int dy) {
    if (_selected) {
      // convert movement into an amount to change the particle (in world space)
      vec2 screenDir(dx, -dy);
      vec2 ndcDir = (2.0f * screenDir / vec2(width(), height()));

      mat4 projection = renderer.projectionMatrix();
      mat4 view = renderer.viewMatrix();

      vec3 pDir = vec3(ndcDir, 0.0);
      mat4 PV = projection * view;
      vec3 delta = vec3(inverse(PV) * vec4(pDir, 0.0));

      _particlePos = _lastParticlePos + delta;
    }
  }

  void mouseDown(int button, int mods) {
    vec2 mousePos = mousePosition();

    // Convert the particle position to screen coords
    mat4 projection = renderer.projectionMatrix();
    mat4 view = renderer.viewMatrix();

    vec4 projectedPos = projection * view * vec4(_particlePos, 1.0);
    vec3 ndcPos = vec3(projectedPos) / projectedPos.w;

    vec2 screenPos = (vec2(ndcPos) + vec2(1.0)) * 0.5f;
    screenPos = screenPos * vec2(width(), height());

    // flip y coordinate because positive Y goes down instead of up
    screenPos.y = height() - screenPos.y;

    if (length(screenPos - mousePos) < _threshold) {
      _color = vec4(1, 1, 0, 1);
      _selected = true;
      _lastParticlePos = _particlePos;
    }
  }

  void mouseUp(int button, int mods) {
    _color = vec4(0, 0, 1, 1);
    _selected = false;
  }

 private:
  vec3 _particlePos;
  vec3 _lastParticlePos;
  vec4 _color = vec4(0, 0, 1, 1);
  bool _selected = false;
  float _threshold = 10;
};

int main() {
  MyWindow window;
  window.run();
}

The documentation for this class was generated from the following files:
agl::Renderer::beginShader
void beginShader(const std::string &shaderName)
Set active shader to use for rendering.
Definition: renderer.cpp:460
agl::Renderer::endShader
void endShader()
Clear active shader to use for rendering.
Definition: renderer.cpp:468