/* Computes the diffuse reflection of the macrosurface */
vec3 lambert_diffuse(vec3 base_color)
{
- // Scale by pi to get a result per steradian, suitable for integration
+ /* Scale by pi (cosine-weighted area of a hemisphere) because the light
+ scatters in every direction */
return base_color/PI;
}
class Buffer;
/**
-Stores primitive type and element indices for a single GL draw call. Data
-type for indices is automatically chosen to accommodate the largest index in
-the Batch.
+Stores primitive type and element indices for a single draw call.
-This is a pretty low-level class and mainly intended to be used by the Mesh
-class.
+Data type for indices is automatically chosen to accommodate the largest
+index, but can also be manually overridden.
+
+Batches are normally contained in a Mesh.
*/
class Batch: public BatchBackend, public Bufferable
{
unsigned max_index;
public:
- Batch(PrimitiveType t);
+ Batch(PrimitiveType);
~Batch();
PrimitiveType get_type() const { return prim_type; }
+
+ /** Sets the data type for indices. Allowed types are UNSIGNED_SHORT and
+ UNSIGNED_INT. It's an error to specify a type which can't hold the current
+ range of index values. */
void set_index_type(DataType);
+
DataType get_index_type() const { return index_type; }
+ /** Appends a single index. The data type is automatically adjusted if the
+ index is too large for the current data type. */
Batch &append(unsigned);
+
Batch &append(const std::vector<unsigned> &);
+
+ /** Checks if it's possible to append another Batch with a given primitive
+ type. */
bool can_append(PrimitiveType);
+
+ /** Appends another batch. Additional indices may be inserted in order to
+ join the primitives. */
Batch &append(const Batch &);
+
private:
void append_index(unsigned);
virtual std::size_t get_data_size() const { return data.size(); }
};
/**
-Blends incoming fragments with those already in the framebuffer.
+Blends incoming fragment color values with those already in the framebuffer.
*/
struct Blend
{
};
/**
-A buffer for storing data in GL memory. Putting vertex and index data in
-buffers can improve rendering performance. The VertexArray, Mesh and
-UniformBlock classes contain built-in support for buffers.
+Stores data in GPU memory.
+
+Memory must be allocated for the buffer by calling storage(). Contents can
+then be modified either synchronously with the data() and sub_data() functions,
+or asynchronously by memory-mapping the buffer.
+
+Applications normally don't need to deal with Buffers directly. They're
+managed by other classes such as Mesh and ProgramData.
*/
class Buffer: public BufferBackend
{
std::size_t size = 0;
public:
- /** Defines the storage size of the buffer. Must be called before data can
- be uploaded. Storage cannot be changed once set. */
+ /** Sets the storage size and allocates memory for the buffer. Size cannot
+ be changed once set. */
void storage(std::size_t);
- /** Uploads data into the buffer, completely replacing any previous
- contents. Storage must be defined beforehand. The data must have size
- matching the defined storage. */
+ /** Replaces contents of the entire buffer. Allocated storage must exist.
+ The data must have size matching the defined storage. */
void data(const void *);
- /** Overwrites part of the buffer data with new data. Storage must be
- defined beforehand. */
+ /** Replaces a range of bytes in the buffer. Allocated storage must exist.
+ The range must be fully inside the buffer. */
void sub_data(std::size_t, std::size_t, const void *);
std::size_t get_size() const { return size; }
class Buffer;
/**
-Base class for things that can store data in buffers. Supports buffer sharing.
+Base class for things that can store data in buffers. Multiple Bufferables
+may be put in the same buffer.
+
A dirty flag is provided for derived classes. It should be set when the data
in the buffer is considered out of date, and is cleared by Bufferable after
uploading fresh data to the buffer.
class Bufferable
{
public:
+ /**
+ Uploads data to the buffer asynchronously, through a memory mapping. API
+ calls are done in the constructor and desctructor, so upload_data may be
+ called from a different thread.
+ */
class AsyncUpdater
{
private:
virtual ~Bufferable();
/** Sets the buffer to use. If prev is not null, it must use the same
- buffer, and this object is inserted after it. */
- void use_buffer(Buffer *buf, Bufferable *prev = 0);
+ buffer, and this object is inserted after it.
+
+ Date is not uploaded immediately, but only when refresh() is called. */
+ void use_buffer(Buffer *, Bufferable *prev = 0);
/** Sets the buffer for the entire chain of objects. */
void change_buffer(Buffer *);
/** Returns the total amount of storage required by this object and others
- in the same chain, including any alignment between objects. */
+ in the same chain, including any padding required by object alignment. */
std::size_t get_required_buffer_size() const;
/** Uploads new data into the buffer if necessary. */
void refresh() const { if(dirty) upload_data(0); }
/** Returns an object which can be used to upload data to the buffer using
- mapped memory. */
+ mapped memory. If data is not dirty, returns null. */
AsyncUpdater *refresh_async() const { return dirty ? new AsyncUpdater(*this) : 0; }
private:
virtual std::size_t get_data_size() const = 0;
protected:
- /** Returns a pointer to the start of data in client memory. */
+ /** Returns a pointer to the start of the data in client memory. */
virtual const void *get_data_pointer() const = 0;
- /** Returns the alignment required for the data, in bytes. The offset is
- guaranteed to be a multiple of this. */
+ /** Returns the alignment required for the data, in bytes. The offset
+ within the buffer is guaranteed to be a multiple of the alignment. */
virtual std::size_t get_alignment() const { return 1; }
/** Updates the offsets for the chain so that data from different objects
Color(float v): r(v), g(v), b(v) { }
Color(float r_, float g_, float b_): r(r_), g(g_), b(b_) { }
Color(float r_, float g_, float b_, float a_): r(r_), g(g_), b(b_), a(a_) { }
+
Color operator*(float f) const { return Color(r*f, g*f, b*f, a); }
Color operator+(const Color &c) const { return Color(r+c.r, g+c.g, b+c.b, 1-(1-a)*(1-c.a)); }
bool operator==(const Color &c) const { return (r==c.r && g==c.g && b==c.b && a==c.a); }
namespace Msp {
namespace GL {
+/**
+Interface for low-level graphics commands.
+
+Applications normally use the higher-level Renderer class rather than this.
+*/
class Commands: public CommandsBackend
{
public:
namespace GL {
/**
-Identifies a data type. The values are bitfields laid as follows:
+Identifies a data type.
-__ds addd ccrr _bfg ssss ssss
+The values are bitfields laid as follows:
+
+__hm addd ccrr _bfg ssss ssss
││ │ │ │ │ │││ └╴Size (bytes)
││ │ │ │ │ ││└──────────╴Signed flag
││ │ │ │ │ │└───────────╴Floating-point flag
└──────────────────────────╴Shadow sampler flag
This information is presented for internal documentation purposes only; it is
-inadvisable for programs to rely on it.
+inadvisable for applications to rely on it.
*/
enum DataType
{
namespace Msp {
namespace GL {
+/**
+Contains information about various limits imposed by the graphics device.
+*/
struct Limits
{
unsigned max_vertex_attributes;
Limits();
};
+/**
+Contains information about a graphics device.
+*/
struct DeviceInfo
{
Limits limits;
DeviceInfo();
+ /** Returns information for the device currently in use. */
static const DeviceInfo &get_global();
};
};
/**
-Framebuffer objects can be used to perform offscreen rendering. The most
-common application is rendering to a texture, which can then be used for
-fullscreen shader effects.
+Uses one or more textures as buffers to draw into. Framebuffers can contain
+multiple color buffers to match multiple outputs from a fragment shader, but
+only one depth and stencil buffer.
-A framebuffer consist of a number of logical buffers, such as color and depth
-buffers. Textures can be attached to the logical buffers. At least one image
-must be attached for the framebuffer to be usable.
-
-Requires the GL_EXT_framebuffer_object extension. The blit functions require
-the GL_EXT_framebuffer_blit extension.
+RenderTarget provides a higher-level interface which manages the textures as
+well as the framebuffer itself.
*/
class Framebuffer: public FramebufferBackend
{
portion of attch is considered; pixel format is ignored. The framebuffer
must have a format and the format of the texture must match that defined
in the framebuffer for this attachment point. */
- void attach(FrameAttachment attch, Texture2D &tex, unsigned level = 0);
+ void attach(FrameAttachment attch, Texture2D &, unsigned level = 0);
+
+ void attach(FrameAttachment attch, Texture2DMultisample &);
+
+ /** Attaches a single layer from a 3-dimensional texture to the
+ framebuffer. */
+ void attach(FrameAttachment attch, Texture3D &, unsigned layer, unsigned level = 0);
+
+ void attach(FrameAttachment attch, TextureCube &, TextureCubeFace face, unsigned level = 0);
+
+ /** Attaches a layered texture to the framebuffer. Shaders can direct
+ output to a particular layer. */
+ void attach_layered(FrameAttachment attch, Texture3D &, unsigned level = 0);
- void attach(FrameAttachment attch, Texture2DMultisample &tex);
- void attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level = 0);
- void attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level = 0);
- void attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level = 0);
- void attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level = 0);
+ void attach_layered(FrameAttachment attch, TextureCube &, unsigned level = 0);
void detach(FrameAttachment attch);
void resize(const WindowView &);
namespace GL {
/**
-Describes a single attachment of a framebuffer. The values are bitfields laid
-as follows:
+Describes a single attachment of a framebuffer, including the type and index
+of the attachment point and the format of the attached texture.
+
+The values are bitfields laid as follows:
nnnn nn_f _sss _ccc
│ │ │ └╴Number of components
└────────────╴Attachment index
This information is presented for internal documentation purposes only; it is
-inadvisable for programs to rely on it.
+inadvisable for applications to rely on it.
*/
enum FrameAttachment: std::uint16_t
{
class Renderer;
/**
-Raw mesh data, consisting of a VertexArray and one or more Batches. Though a
-Mesh can draw itself, it's usually used as part of Renderables rather than on
-its own.
+Stores mesh data using a VertexArray and one or more Batches.
+
+Meshes can be created at runtime using the MeshBuilder class.
+
+The Object class provides a higher-level interface which associates a Mesh with
+a Technique and is usually the appropriate way to of rendering geometry.
*/
class Mesh: public Resource
{
Mesh(const VertexFormat &);
~Mesh();
+ /** Sets the vertex format for the mesh. It cannot be changed once set. */
void storage(const VertexFormat &);
+ /** Clears all vertices and batches. Vertex format is retained. */
void clear();
private:
void check_buffers(unsigned);
const VertexSetup &get_vertex_setup() const { return vtx_setup; }
const Buffer *get_index_buffer() const { return ibuf; }
std::size_t get_n_vertices() const;
+
+ /** Returns a pointer to a vertex. Offsets of individual attributes can be
+ queried from VertexFormat. */
char *modify_vertex(std::size_t);
+ /** Adds a batch to the mesh. It may be combined with the last existing
+ batch if the primitive types are compatible. */
void add_batch(const Batch &b);
+
const std::vector<Batch> &get_batches() const { return batches; }
void set_winding(FaceWinding);
void draw(Renderer &) const;
+
+ /** Draws multiple instances of the mesh. The supplied VertexSetup must use
+ the mesh's vertex array. */
void draw_instanced(Renderer &, const VertexSetup &, unsigned) const;
+
private:
void draw(Renderer &, const VertexSetup *, unsigned) const;
void resize_buffers() const;
class Resources;
+/**
+Base class for shader modules. Internal representation depends on the
+concrete type.
+
+Modules can be loaded from files.
+
+Applications normally use the Program class to access shaders.
+*/
class Module
{
public:
virtual Format get_format() const = 0;
+ /** Sets the module's content from GLSL source code. */
void set_source(const std::string &);
- void load_source(IO::Base &, Resources *, const std::string &);
+
+ /** Loads GLSL source from a file or other I/O object. Any import
+ statements are resolved using res. */
+ void load_source(IO::Base &, Resources *res, const std::string &name);
+
+ /** Loads GLSL source from a file or other I/O object. Only builtin
+ shader fragments can be imported. */
void load_source(IO::Base &, const std::string &);
+
private:
virtual void compile(SL::Compiler &) = 0;
};
+/**
+A shader module in GLSL source code format.
+*/
class GlslModule: public Module
{
private:
const SL::SourceMap &get_source_map() const { return source_map; }
};
+/**
+A shader module in SPIR-V binary format.
+
+When the module's contents are set from GLSL source, it will be automatically
+compiled to SPIR-V. Pre-compiled SPIR-V modules can also be loaded.
+
+Afterwards reflection data is available, providing information about variables
+forming the module's interface.
+*/
class SpirVModule: public Module
{
public:
public:
virtual Format get_format() const { return SPIR_V; }
+ /** Loads a SPIR-V binary from a file or other I/O object. */
void load_code(IO::Base &);
private:
virtual void compile(SL::Compiler &);
class UniformBlock;
class VertexSetup;
+/**
+Stores state for the entire GPU pipeline.
+
+Applications normally use the higher-level Renderer class rather than this.
+*/
class PipelineState: public PipelineStateBackend
{
friend PipelineStateBackend;
namespace GL {
/**
-Identifies the components of a pixel, without type information. The values
-are bitfields laid as follows:
+Identifies the components of a pixel, without type information.
+
+The values are bitfields laid as follows:
_grs dccc
│││ │ └╴Number of components
└───────╴Grayscale flag
This information is presented for internal documentation purposes only; it is
-inadvisable for programs to rely on it.
+inadvisable for applications to rely on it.
*/
enum PixelComponents
{
};
/**
-Identifies a pixel format, with components and type. The values are bitfields
-laid as follows:
+Identifies a pixel format, with components and type.
+
+The values are bitfields laid as follows:
tnfg ssss cccc cccc
││││ │ └╴Components (see PixelComponents)
└──────────────────╴sRGB flag
This information is presented for internal documentation purposes only; it is
-inadvisable for programs to rely on it.
+inadvisable for applications to rely on it.
*/
enum PixelFormat
{
namespace GL {
/**
-A complete shader program. Programs can be assembled of individual Shaders or
-generated with a set of standard features.
+A shader program consisting of one or more stages.
+
+Programs are created from Modules. Specialization values can be applied to
+customize behaviour of the module.
*/
class Program: public ProgramBackend
{
enum QueryType
{
+ /** Query result indicates if any fragments passed the depth and stencil
+ tests. */
OCCLUSION_QUERY
};
+/**
+A collection of query objects, which can be used to gather feedback from the
+GPU. Semantics of the queries depend on the query type.
+*/
class QueryPool: public QueryPoolBackend, public Msp::NonCopyable
{
friend QueryPoolBackend;
/**
-Samplers are used to access texture data in shaders. To use a sampler with a
-texture, bind it to the same texture unit. Each texture has a default sampler
-which is used if no external sampler is bound.
-
-A texture is generally rendered at a size that's either smaller or larger than
-its native size, so that the texture coordinates do not exactly correspond to
-the texels of the texture. The kind of filtering used, if any, is determined
-by the minification and magnification filter parameters. The default is LINEAR
-for magnification and NEAREST_MIPMAP_LINEAR for minification.
-
-If texture coordinates fall outside of the principal range of the texture,
-wrapping is applied. The default for all directions is REPEAT.
+Stores settings affecting how values are obtained from textures in a shader.
+Samplers are always used together with textures.
+
+Texture coordinates are first transformed according to the wrap mode for each
+axis. One or more texel values are then read and combined according to the
+filtering mode.
*/
class Sampler: public SamplerBackend
{
void update() const;
public:
+ /** Sets filter to use when the texture is drawn at a size smaller than
+ original. */
void set_min_filter(TextureFilter);
+
+ /** Sets filter to use when the texture is drawn at a size larger than
+ original. Mipmapped filters can't be used. */
void set_mag_filter(TextureFilter);
/** Sets filter for both minification and magnification. If a mipmapping
TextureFilter get_min_filter() const { return min_filter; }
TextureFilter get_mag_filter() const { return mag_filter; }
+ /** Sets the maximum aspect ratio for anisotropic filtering. If greater
+ than 1, filtering will consider more than than four samples when the texture
+ is drawn at an oblique angle. */
void set_max_anisotropy(float);
float get_max_anisotropy() const { return max_anisotropy; }
void set_wrap_t(TextureWrap);
void set_wrap_r(TextureWrap);
+ /** Sets the border color for CLAMP_TO_BORDER wrap mode. */
void set_border_color(const Color &);
+
const Color &get_border_color() const { return border_color; }
/** Disables depth comparison. */
/** Enables depth comparison and sets the compare function. Only has an
effect when used with a depth texture. When depth comparison is enabled,
- the third component of the texture coordinate is compared against the texel
+ the last component of the texture coordinate is compared against the texel
value, and the result is returned as the texture sample.*/
void set_compare(Predicate);
namespace GL {
/**
-Base class for textures. This class only defines operations common for all
-texture types and is not instantiable. For specifying images for textures,
-see one of the dimensioned texture classes.
+Base class for textures. Most operations are defined in subclasses.
-A texture can consinst of a stack of images, called a mipmap. The dimensions
-of each mipmap level are half that of the previous level. The mipmap stack
-can be used for texture minification; see the Sampler class for details.
+Memory must be allocated for the texture by calling storage(). Each subclass
+provides this function with parameters appropriate to that type of texture.
+Contents can then be modified using the image() and sub_image() functions
+provided by subclasses.
+
+Most types of textures can consist of a pyramid of images, called a mipmap.
+The dimensions of each mipmap level are half that of the previous level.
+
+Textures can be used as either a data source or target for draw commands. To
+read from a texture in a shader, it must be paired with a Sampler to determine
+how the texels are accessed. To draw into a texture, it must be attached to a
+Framebuffer.
*/
class Texture: public TextureBackend, public Resource
{
using TextureBackend::generate_mipmap;
- /// Loads a Graphics::Image from a file and uploads it to the texture.
+ /** Loads an image into the texture from a file. */
virtual void load_image(const std::string &, unsigned = 0);
- /** Uploads an image to the texture. If storage has not been defined, it
- will be set to match the image. Otherwise the image must be compatible
- with the defined storage. Semantics depend on the type of texture. */
+ /** Sets the texture's contents from an image. If storage has not been
+ allocated yet, it will be set to match the image. Otherwise the image must
+ be compatible with the existing storage. Subclasses may impose restrictions
+ on the image's dimensions. */
virtual void image(const Graphics::Image &, unsigned = 0) = 0;
virtual std::size_t get_data_size() const { return 0; }
namespace Msp {
namespace GL {
+/**
+One-dimensional texture, consisting of a single row of texels.
+*/
class Texture1D: public Texture1DBackend
{
friend Texture1DBackend;
unsigned levels = 0;
public:
- void storage(PixelFormat, unsigned, unsigned = 0);
+ /** Sets storage format and size and allocates memory for the texture. If
+ lv is zero, a complete mipmap pyramid is automatically created. Storage
+ cannot be changed once set. */
+ void storage(PixelFormat, unsigned wd, unsigned lv = 0);
+
+ /** Replaces contents of an entire mipmap level. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ must have size matching the selected mipmap level. */
+ void image(unsigned level, const void *);
+
+ /** Replaces a range of texels in the texture. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ the range must be fully inside the selected mipmap level. */
+ void sub_image(unsigned level, int x, unsigned wd, const void *);
- void image(unsigned, const void *);
- void sub_image(unsigned, int, unsigned, const void *);
virtual void image(const Graphics::Image &, unsigned = 0);
unsigned get_width() const { return width; }
namespace GL {
/**
-Two-dimensional texture. Consists of an array of texels in the shape of a
-rectangle. Texture coordinate have a range of [0, 1]. Coordinates outside of
-this range are subject to wrapping. This is the most common type of texture.
+Two-dimensional texture, consisting of a rectangular array of texels.
*/
class Texture2D: public Texture2DBackend
{
public:
virtual ~Texture2D();
- /** Defines storage structure for the texture. If lv is zero, the number
- of mipmap levels is automatically determined from storage dimensions.
+ /** Sets storage format and dimensions and allocates memory for the texture.
+ If lv is zero, a complete mipmap pyramid is automatically created. Storage
+ cannot be changed once set. */
+ void storage(PixelFormat, unsigned wd, unsigned ht, unsigned lv = 0);
- Must be called before an image can be uploaded. Once storage is defined,
- it can't be changed. */
- void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned lv = 0);
+ /** Replaces contents of an entire mipmap level. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ must have size matching the selected mipmap level. */
+ virtual void image(unsigned level, const void *);
- /** Updates the contents of the entire texture. Storage must be defined
- beforehand. The image data must have dimensions and format matching the
- defined storage. */
- virtual void image(unsigned level, const void *data);
+ /** Replaces a rectangular region of the texture. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ the region must be fully inside the selected mipmap level. */
+ void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *);
- /** Updates a rectangular region of the texture. Storage must be defined
- beforehand. The image data must be in a format mathing the defined storage
- and the update region must be fully inside the texture. */
- void sub_image(unsigned level, int x, int y, unsigned wd, unsigned ht, const void *data);
-
- /** Updates the contents of the entire texture from an image. If storage
- has not been defined, it will be set to match the image. Otherwise the
- image must match the defined storage. */
- virtual void image(const Graphics::Image &, unsigned lv = 0);
+ virtual void image(const Graphics::Image &, unsigned = 0);
unsigned get_width() const { return width; }
unsigned get_height() const { return height; }
namespace GL {
/**
-An array of two-dimensional textures. It's very much like a 3D texture, with
-two important differences: there's no filtering nor mipmapping along the third
-dimension.
+An array of two-dimensional textures. It behaves much like a 3D texture, but
+mipmapping and filtering is not applied on the third dimension. When sampling
+the texture, the third coordinate is not normalized and is rounded to the
+nearest integer to select the layer.
*/
class Texture2DArray: public Texture2DArrayBackend
{
void external_image(unsigned, const std::string &);
};
+ /** Replaces contents of a single layer. Allocated storage must exist. The
+ image data is interpreted according to the storage format and must have
+ width and height matching the selected mipmap level. */
void layer_image(unsigned, unsigned, const void *);
+
void layer_image(unsigned, unsigned, const Graphics::Image &);
unsigned get_layers() const { return get_depth(); }
namespace Msp {
namespace GL {
+/**
+Two-dimensional multisample texture, consisting of a rectancular array of
+texels with multiple samples each.
+
+The contents of multisample textures can not be set through API. Their primary
+use is as Framebuffer attachments.
+
+Multisample textures can't have mipmaps.
+*/
class Texture2DMultisample: public Texture2DMultisampleBackend
{
friend Texture2DMultisampleBackend;
unsigned samples = 0;
public:
- void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned sm);
+ /** Sets storage dimensions, format and sample count and allocates memory
+ for the texture. */
+ void storage(PixelFormat, unsigned wd, unsigned ht, unsigned sm);
virtual void image(const Graphics::Image &, unsigned = 0);
namespace GL {
/**
-Three-dimensional texture. Consists of an array of texels in the shape of a
-right cuboid. Texture coordinates have a principal range of [0, 1].
+Three-dimensional texture, consisting of a cuboid-shaped array of texels.
*/
class Texture3D: public Texture3DBackend
{
public:
Texture3D() = default;
- /** Defines storage structure for the texture. If lv is zero, the number
- of mipmap levels is automatically determined from storage dimensions.
-
- Must be called before an image can be uploaded. Once storage is defined,
- it can't be changed. */
- void storage(PixelFormat fmt, unsigned wd, unsigned ht, unsigned dp, unsigned lv = 0);
-
- /** Updates the contents of the entire texture. Storage must be defined
- beforehand. The image data must have dimensions and format matching the
- defined storage. */
- void image(unsigned level, const void *data);
-
- /** Updates a cuboid-shaped region of the texture. Storage must be defined
- beforehand. The image data must be in a format mathing the defined storage
- and the update region must be fully inside the texture. */
- void sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *data);
-
- /** Updates the contents of the entire texture from an image. If storage
- has not been defined, it will be set to match the image. In this case the
- image will be treated as a stack of square layers and its height must be
- divisible by its width. Otherwise the image must match the defined
- storage. */
+ /** Sets storage format and dimensions and allocates memory for the texture.
+ If lv is zero, a complete mipmap pyramid is automatically created. Storage
+ cannot be changed once set. */
+ void storage(PixelFormat, unsigned wd, unsigned ht, unsigned dp, unsigned lv = 0);
+
+ /** Replaces contents of an entire mipmap level. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ must have size matching the selected mipmap level. */
+ void image(unsigned level, const void *);
+
+ /** Replaces a cuboid-shaped region of the texture. Allocated storage must
+ exist. The image data is interpreted according to the storage format and
+ the region must be fully inside the texture. */
+ void sub_image(unsigned level, int x, int y, int z, unsigned wd, unsigned ht, unsigned dp, const void *);
+
+ /** Sets the texture's contents from an image. The image is treated as a
+ stack of square layers and its height must be divisible by its width. If
+ storage has not been allocated yet, it will be set to match the image.
+ Otherwise the image must be compatible with the existing storage. */
virtual void image(const Graphics::Image &, unsigned = 0);
unsigned get_width() const { return width; }
};
/**
-Cube map texture, consisting of six square faces. All of the faces must be of
-the same size. A cube map texture is addressed by three-dimensional texture
-coordinates, with a principal range of [-1, 1]. The face is first selected
-according to the largest coordinate, and the remaining two coordinates are used
-to sample the face image. The images are oriented so that the cross product of
-the s and t axes will point into the cube.
+Cube map texture, consisting of six square faces.
-All faces of a cube map texture must be allocated for it to be usable.
-
-Requires OpenGL version 1.3.
+A cube map texture is addressed by three-dimensional texture coordinates. The
+coordinate vector is projected on the unit cube, with the largest coordinate
+selecting the face and the remaining two used to sample from the face image.
+The images are oriented so that the cross product of the s and t axes will
+point into the cube.
*/
class TextureCube: public TextureCubeBackend
{
static const unsigned orientations[12];
public:
- /** Defines storage structure for the texture. If lv is zero, the number
- of mipmap levels is automatically determined from storage dimensions.
-
- Must be called before an image can be uploaded. Once storage is defined,
- it can't be changed. */
- void storage(PixelFormat fmt, unsigned size, unsigned lv = 0);
+ /** Sets storage format and dimensions and allocates memory for the texture.
+ If lv is zero, a complete mipmap pyramid is automatically created. Storage
+ cannot be changed once set. */
+ void storage(PixelFormat, unsigned size, unsigned lv = 0);
- /** Updates the contents of a face. Storage must be defined beforehand.
- The image data must have dimensions and format matching the defined
- storage. */
- void image(TextureCubeFace face, unsigned level, const void *data);
+ /** Replaces contents of a single face. Allocated storage must exist. The
+ image data is interpreted according to the storage format and must have size
+ matching the selected mipmap level. */
+ void image(TextureCubeFace, unsigned level, const void *);
- /** Updates a rectangular region of a face. Storage must be defined
- beforehand. The image data must be in a format mathing the defined storage
- and the update region must be fully inside the face. */
- void sub_image(TextureCubeFace face, unsigned level, int x, int y, unsigned w, unsigned h, const void *data);
+ /** Replaces a rectangular region of a face. Allocated storage must exist.
+ The image data is interpreted according to the storage format and the region
+ must be fully inside the face. */
+ void sub_image(TextureCubeFace, unsigned level, int x, int y, unsigned w, unsigned h, const void *);
void image(TextureCubeFace, const Graphics::Image &);
+ /** Sets the texture's contents from an image. The image is treated as a
+ stack of square layers and its height must be six times its width. If
+ storage has not been allocated yet, it will be set to match the image.
+ Otherwise the image must be compatible with the existing storage. */
virtual void image(const Graphics::Image &, unsigned = 0);
unsigned get_size() const { return size; }
/** Returns a vector in the direction of the t axis of the face. */
static const Vector3 &get_t_direction(TextureCubeFace);
- /** Returns a vector pointing to the center a texel. */
+ /** Returns a vector pointing to the center of a texel. */
Vector3 get_texel_direction(TextureCubeFace, unsigned, unsigned);
virtual AsyncLoader *load(IO::Seekable &, const Resources * = 0) { return 0; }
namespace GL {
/**
-Stores uniforms with a specific layout. Both named and default uniform blocks
-are supported.
+Stores uniform values in a block of memory.
+
+For named uniform blocks the values are stored according to the reflected
+layout of the block, ready for use by shaders. For the default uniform block,
+the location of the uniform is multiplied by 16 to obtain the memory offset.
+
+Applications normally don't need to deal with UniformBlocks directly. They're
+managed by the ProgramData class, which provides a higher-level interface for
+setting uniform values.
*/
class UniformBlock: public UniformBlockBackend, public NonCopyable, public Bufferable
{
namespace GL {
/**
-Stores vertex data.
+Stores vertex data. Each vertex has one or more attributes defined by a
+VertexFormat.
The array's contents can be modified with the append and modify methods. To
obtain the location of an individual component within the vertex, use
VertexFormat::offset.
-A higher-level interface for filling in vertex data is available in the
-VertexArrayBuilder class.
+VertexArrayBuilder provides a convenient way of filling in vertex data.
+
+Applications normally don't need to deal with VertexArrays directly. They're
+managed by the Mesh and InstanceArray classes.
*/
class VertexArray: public Bufferable
{
public:
VertexArray() = default;
- /// Construct a VertexArray and set its format.
+ /** Constructs a VertexArray and sets its format. */
VertexArray(const VertexFormat &);
- /// Sets the format of the VertexArray.
+ /** Sets the format of the VertexArray. The format cannot be changed once
+ set. */
void set_format(const VertexFormat &);
const VertexFormat &get_format() const { return format; }
- /// Clears all vertices from the array.
+ /** Clears all vertices from the array. Vertex format is retained. */
void clear();
- /// Reserve space for vertices.
+ /** Reserve space for vertices. If n is smaller than the current size,
+ nothing is done. */
void reserve(std::size_t n);
- /// Append a new vertex at the end of the array and return its location.
+ /** Append a new vertex at the end of the array and return a pointer to it.
+ The array is marked as dirty. */
char *append();
- /// Returns the location of a vertex for modification.
+ /** Returns a pointer to a vertex for modification. The array is marked as
+ dirty. */
char *modify(std::size_t);
private:
virtual std::size_t get_data_size() const;
namespace Msp {
namespace GL {
-/** A single vertex attribute. Commonly used attributes are named by their
+/**
+A single vertex attribute. Commonly used attributes are named by their
semantical meaning in the standard shaders. Texture coordinates and generic
attributes can additionally be given an index. There are four texture
coordinate attributes available. The number of available generic attributes
└────────────╴Attribute index (semantic)
This information is presented for internal documentation purposes only; it is
-inadvisable for programs to rely on it.
+inadvisable for applications to rely on it.
*/
enum VertexAttribute: std::uint16_t
{
RAW_ATTRIB_I4 = 0xFCCC
};
+/**
+Describes the attributes of a vertex. Up to 15 attributes are allowed.
+*/
class VertexFormat
{
private:
bool empty() const { return !count; }
const VertexAttribute *begin() const { return attributes; }
const VertexAttribute *end() const { return attributes+count; }
+
+ /** Returns the displacement from one vertex to the next. */
unsigned stride() const;
+
+ /** Returns the offset of an attribute within a vertex. A stored attribute
+ must have the same semantic and type and at least as many components as
+ requested to be considered a match. */
int offset(VertexAttribute) const;
};
class VertexArray;
/**
-Combines a VertexArray with an index buffer. This wraps OpenGL's vertex array
-objects. Intended for internal use.
+Combines vertex and instance attributes and an index buffer for a complete
+description of vertex input state.
+
+Applications normally don't need to deal with VertexSetups directly. They're
+managed by the Mesh and InstanceArray classes.
*/
class VertexSetup: public VertexSetupBackend
{
DataType index_type = UNSIGNED_SHORT;
public:
+ /** Sets format for vertex data. Instance attributes won't be used. The
+ format cannot be changed once set. */
void set_format(const VertexFormat &);
+
+ /** Sets formats for both vertex and instance data. The formats cannot be
+ changed once set. */
void set_format_instanced(const VertexFormat &, const VertexFormat &);
+ /** Sets the VertexArray to use as the source of vertex attribute values.
+ The array's format must match the VertexSetup's vertex format. */
void set_vertex_array(const VertexArray &);
+
+ /** Sets the VertexArray to use as the source of instance attribute values.
+ An instance format must be defined and the array's format must match it. */
void set_instance_array(const VertexArray &);
+
+ /** Sets the buffer containing index data and the type of indices. */
void set_index_buffer(const Buffer &, DataType);
+
const VertexArray *get_vertex_array() const { return vertex_array; }
const VertexArray *get_instance_array() const { return inst_array; }
const Buffer *get_index_buffer() const { return index_buffer; }
class Program;
/**
-Implements screen-space ambient occlusion.
+Darkens recessed areas of the scene to simulate the occlusion of ambient light.
http://en.wikipedia.org/wiki/Screen_Space_Ambient_Occlusion
*/
class Program;
/**
-The Bloom post-processing effect causes very bright areas of the image to bleed
-into surrounding pixels. Commonly used together with HDR rendering.
+Bleeds very bright areas of the image into surrounding pixels to simulate
+optical imperfections in lenses.
-The technique used is to gaussian blur the image and then blend the result with
-the original image. With suitable parameters, this effect may also be used as
-a blur filter.
+The input image is blurred with a gaussian kernel to simulate the Airy disc
+produced by a lens, then the blurred image is blended with the original.
*/
class Bloom: public PostProcessor
{
class Program;
/**
-Processes oversaturated colors to preserve hues. When one color component
-exceeds 1.0, the overflow is distributed to the other components, scaling the
-color towards white.
+Maps high dynamic range colors to 8-bit and applies gamma correction.
+
+An exponential curve (with exponent less than or equal to 1) is applied to
+simulate the response of the human eye. If the maximum color component of the
+result exceeds 1, the overflow is distributed to the other components to
+increase the apparent brightness without changing the hue.
Gamma or sRGB correction can also be applied to the output. It can be used to
improve color reproduction by performing lighting calculations in linear color
namespace GL {
/**
-Effects are used to wrap other renderables and give them additional visual
-properties. An Effect's render method should set up the necessary state, call
-the wrapped Renderable's render method, and clean up after itself.
+Base class for visual effects.
+
+Effects wrap other renderables and provide additional textures or uniform
+values which can be used by shaders to modify the appearance of the content
+renderable. Some material properties require certain Effects to be present in
+order to function properly.
+
+If an Effect subclass needs to do any sideband rendering to prepare for a
+frame, that should be done in setup_frame(). The render() function should only
+set up the necessary state and call the content renderable's render() function.
*/
class Effect: public Renderable
{
public:
+ /**
+ Holds the parameters for an Effect. Used with SequenceTemplate.
+ */
struct Template
{
class Loader: public DataFile::CollectionObjectLoader<Template>
class Sampler;
/**
-Creates a cube map texture of the surroundings of the renderable. This texture
-can then be used to implement effects such as reflections or refractions.
+Creates a cube map texture of the surroundings of the content renderable, for
+use in image-based lighting. Also called a light probe.
-If the EnvironmentMap is used in a Sequence, it's worth noting that the cube
-map will be prepared outside of any rendering pass. It's recommended to use
-another Sequence to define which passes should be used to render the
-environment.
+The cube map can optionally be prefiltered for varying amounts of roughness.
+An irradiance map for diffuse lighting is also created.
+
+The EnvironmentMap won't be rendered inside its own environment. This avoids
+artifacts if one is used to create reflections on a complex object.
+
+The shader fragment common.glsl provides interfaces to access the environment
+data.
*/
class EnvironmentMap: public Effect
{
unsigned update_delay = 0;
public:
- EnvironmentMap(unsigned size, PixelFormat, Renderable &rend, Renderable &env);
- EnvironmentMap(unsigned size, PixelFormat, unsigned, Renderable &rend, Renderable &env);
+ EnvironmentMap(unsigned size, PixelFormat, Renderable &content, Renderable &env);
+
+ /** Creates an EnvironmentMap with prefiltering for varying amounts of
+ roughness. Levels specifies the number of prefilter mipmap levels and must
+ be valid for the size. */
+ EnvironmentMap(unsigned size, PixelFormat, unsigned levels, Renderable &content, Renderable &env);
+ /** Sets a fixed position to render the environment map from. This can be
+ useful if the content renderable does not have a model matrix. */
void set_fixed_position(const Vector3 &);
void set_depth_clip(float, float);
class Texture2D;
/**
-Base class for post-processing effects. Post-processors receive the contents
-of the entire framebuffer as a texture and render it back, altering it in the
-process.
+Base class for post-processing effects.
+
+PostProcessors can be added to a Sequence. They receive the contents of the
+entire framebuffer as a texture and render it back, altering it in the process.
*/
class PostProcessor
{
public:
+ /**
+ Holds the parameters for a PostProcessor. Used with SequenceTemplate.
+ */
struct Template
{
class Loader: public Msp::DataFile::ObjectLoader<Template>
public:
virtual ~PostProcessor() { }
- /// Renders the effect.
virtual void render(Renderer &, const Texture2D &, const Texture2D &) = 0;
virtual void set_debug_name(const std::string &) = 0;
class PointLight;
/**
-Creates shadows on a renderable through a shadow map texture. In the setup
-phase, the scene is rendered to a depth texture from the point of view of the
-lightsource. This texture is then used in the rendering phase together with
-texture coordinate generation to determine whether each fragment is lit.
+Creates a depth texture which can be used to add shadows to a renderable.
+
+In the setup phase, the scene is rendered from the point of view of the light
+source and the depth values are recorded. This texture can be used by shaders
+to determine if the light can reach a particular position.
+
+A shadow map can be created as an atlas, containing multiple lights in the same
+depth texture. Each light is automatically allocated a region of the texture
+and region information is added to the uniform values.
+
+The shader fragment shadow.glsl provides interfaces to access the shadow map.
*/
class ShadowMap: public Effect
{
std::string debug_name;
ShadowMap(unsigned, unsigned, Renderable &, const Lighting *);
+
public:
- ShadowMap(unsigned, Renderable &, const DirectionalLight &, Renderable &);
- ShadowMap(unsigned, unsigned, Renderable &, const Lighting &);
+ /** Creates a shadow map for a single light. */
+ ShadowMap(unsigned size, Renderable &content, const DirectionalLight &, Renderable &caster);
+
+ /** Creates a shadow map atlas, to which multiple lights can be added. */
+ ShadowMap(unsigned width, unsigned height, Renderable &, const Lighting &);
+
+ /** Adds a directional light. The shadow map is rendered using an
+ orthogonal projection. */
+ void add_light(const DirectionalLight &, unsigned size, Renderable &caster);
- void add_light(const DirectionalLight &, unsigned, Renderable &);
- void add_light(const PointLight &, unsigned, Renderable &);
+ /** Adds a point light. The shadow map is rendered using a perspective
+ projection, with four views in a tetrahedral arrangement. The shader must
+ clip vertices appropriately. Occluder_thsm.glsl can be used for this. */
+ void add_light(const PointLight &, unsigned size, Renderable &caster);
private:
void add_light(const Light &, unsigned, ShadowType, Renderable &);
public:
- /** Sets the ShadowMap target point and radius. The transformation matrix is
- computed so that a sphere with the specified parameters will be completely
- covered by the ShadowMap. */
+ /** Sets the shadow volume parameters. For directional lights the shadow
+ camera will be positioned so that the spherical shadow volume fits entirely
+ in the view volume. For point lights the shadow volume's radius will be
+ used as the view distance. */
void set_target(const Vector3 &, float);
/** Sets the darkness of shadows. Must be in the range between 0.0 and 1.0,
- inclusive. Only usable with shaders, and provided through the
- shadow_darkness uniform. */
+ inclusive. Values other than 1.0 are not physically correct. */
void set_darkness(float);
- /** Sets a distance beyond objects from which the shadow starts. Expressed
- in pixel-sized units. Must be positive; values less than 1.0 are not
- recommended. Larger values produce less depth artifacts, but may prevent
- thin objects from casting shadows on nearby sufraces. */
+ /** Sets an offset for depth values to avoid surfaces incorrectly shadowing
+ themselves. Must be positive; values less than 1.0 are not recommended.
+ Larger values produce less artifacts, but may cause shadows to become
+ disconnected from the objects casting them. */
void set_depth_bias(float);
const Texture2D &get_depth_texture() const { return depth_buf; }
class Program;
/**
-Renders a procedurally generated sky at the background. Based on the paper
-"A Scalable and Production Ready Sky and Atmosphere Rendering Technique" by
-Sébastien Hillaire (https://sebh.github.io/publications/egsr2020.pdf).
+Renders a procedurally generated sky at the background.
+
+In addition to the background, the transmittance of the sun light is calculated
+to produce realistic lighting at dawn and dusk.
+
+Based on the techniques described in "A Scalable and Production Ready Sky and
+Atmosphere Rendering Technique" by Sébastien Hillaire
+(https://sebh.github.io/publications/egsr2020.pdf).
*/
class Sky: public Effect
{
virtual void visit(Iteration &);
};
+/** Removes code which is never executed due to flow control statements. */
class UnreachableCodeRemover: private TraversingVisitor
{
private:
namespace Msp {
namespace GL {
+/**
+A basic and cheap material using the Phong shading model. Results are roughly
+equivalent to legacy OpenGL materials.
+
+In addition to the usual properties of the Phong shading model, normal mapping
+and reflections are supported. Reflections require an EnvironmentMap effect.
+*/
class BasicMaterial: public Material
{
public:
Lights are usually grouped with a Lighting object, which can be used in a
Sequence::Step.
-Lights do not cast shadows by themselves. See ShadowMap for that.
+Shadows can be added to lights by using the ShadowMap effect.
*/
class Light: public Placeable
{
public:
virtual ~Light() = default;
- /** Sets the color of the Light. */
+ /** Sets the color of the light. */
void set_color(const Color &);
const Color &get_color() const { return color; }
unsigned get_generation() const { return generation; }
- /** Updates a ProgramData object with the uniforms for the Light. A light
- source index must be passed in. Primarily used by Lighting. */
+ /** Updates a ProgramData object with the uniform values for the light. A
+ light source index must be passed in. */
void update_shader_data(ProgramData &, unsigned) const;
protected:
class Light;
/**
-Encapsulates global lighting parameters and any number of individual light
-sources.
+Combines multiple light sources with global lighting parameters.
+
+This class also stores ProgramData for using the lights in shaders.
*/
class Lighting
{
public:
Lighting();
- /** Sets the ambient lighting color. Affects all surfaces in the scene. */
+ /** Sets the ambient lighting color. Affects all surfaces in an equal
+ amount. */
void set_ambient(const Color &);
const Color &get_ambient() const { return ambient; }
class Sampler;
+/**
+Base class for materials. Subclasses provide different shading models.
+*/
class Material
{
private:
public:
virtual ~Material() = default;
+ /** Returns a shader appropriate for this material. The same shader is
+ returned for materials with the same set of features. Additional
+ specialization values can be passed in to customize the shader. */
virtual const Program *create_compatible_shader(const std::map<std::string, int> & = std::map<std::string, int>()) const;
protected:
virtual void fill_program_info(std::string &, std::map<std::string, int> &) const = 0;
public:
- /** Returns the uniforms for the material. */
+ /** Returns the uniform values for the material. */
const ProgramData &get_shader_data() const { return shdata; }
+ /** Returns texture tags used by the material. The returned array is
+ terminated by an empty tag. */
virtual const Tag *get_texture_tags() const = 0;
+
virtual const Texture *get_texture(Tag) const = 0;
virtual const Sampler *get_sampler(Tag) const { return sampler; }
class Texture2D;
+/**
+A physically-based material using the Cook-Torrance BRDF.
+
+The material is characterized by base color, metalness and roughness. Fully
+metallic materials have no diffuse reflection and their specular reflection is
+tinted by the base color. For fully dielectric materials base color determines
+the color of the diffuse reflection; specular reflection is untinted.
+Roughness affects how blurry specular reflections are.
+*/
class PbrMaterial: public Material
{
public:
void set_position(const Vector3 &);
const Vector3 &get_position();
+ /** Sets the constant, linear and quadratic attentuation factors for the
+ light. */
void set_attenuation(float, float, float);
+
const float *get_attenuation() const { return attenuation; }
protected:
class Texture;
/**
-Encapsulates the data that determines the appearance of a rendered surface.
-This includes shader and data for it, material and texturing.
+Describes the appearance of a surface with a shader, uniform values and
+textures.
+
+A Material can be used to automatically populate most of the fields of a
+RenderMethod.
*/
class RenderMethod
{
void set_material_textures();
public:
+ /** Sets the shader program and uniform values. */
void set_shader_program(const Program *, const ProgramData *);
+
const Program *get_shader_program() const { return shprog; }
const ProgramData *get_shader_data() const { return shdata.get(); }
Tag get_slotted_uniform_tag(Tag) const;
+
+ /** Sets a Material to use as a basis for the render method. If a shader
+ has not been explicitly set, the material's shader will be used. */
void set_material(const Material *);
+
const Material *get_material() const { return material; }
const std::string &get_material_slot_name() const { return material_slot; }
void set_texture(Tag, const Texture *, const Sampler * = 0);
CullMode get_face_cull() const { return face_cull; }
void set_blend(const Blend &);
const Blend &get_blend() const { return blend; }
+
+ /** Toggles shadows on objects using this render method. Only affects
+ shaders created from materials. A ShadowMap effect is required. */
void set_receive_shadows(bool);
+
bool get_receive_shadows() const { return receive_shadows; }
+
+ /** Toggles the use of an environment map as a light source. Only affects
+ shaders created from materials. An EnvironmentMap effect is required. */
void set_image_based_lighting(bool);
+
bool get_image_based_lighting() const { return image_based_lighting; }
void apply(Renderer &) const;
namespace Msp {
namespace GL {
+/**
+A material which performs no lighting calculations at all. Useful for HUD
+graphics.
+*/
class UnlitMaterial: public Material
{
public:
namespace Msp {
namespace GL {
+/**
+Represents a point of view in 3D space.
+
+A Camera provides two matrices. The view matrix is the inverse of the camera's
+model matrix and transforms coordinates from world space to eye space (the
+camera's object space). The projection matrix transforms coordinates from eye
+space to clip space.
+
+Orientation of the Camera is determined by look direction and up direction.
+Look direction corresponds to the negative Z axis direction in eye space. The
+YZ plane of eye space is aligned to the plane formed by the look and up
+directions. Setting the up direction to the opposite of gravity direction is
+an easy way to keep the camera upright.
+*/
class Camera: public Placeable
{
public:
public:
Camera();
+ /** Sets the camera projection to perspective, characterised by the vertical
+ field of view. Horizontal FoV is computed with the aspect ratio. */
void set_field_of_view(const Geometry::Angle<float> &);
+
+ /** Sets the camera projection to orthogonal, characterized by the size of
+ the projection region. */
void set_orthographic(float, float);
+
void set_aspect_ratio(float);
void set_depth_clip(float, float);
+
+ /** Sets the direction of the frustum axis, which corresponds to the center
+ of the screen. The offset is expressed in terms of the neutral frustum such
+ that -1 is the left or bottom edge and 1 is the right or top edge. */
void set_frustum_axis(float, float);
+
+ /** Apply a rotation to the view frustum after projection. This can be used
+ with rotated displayes without affecting the camera's orientation. */
void set_frustum_rotation(const Geometry::Angle<float> &);
+
const Geometry::Angle<float> &get_field_of_view() const { return fov; }
bool is_orthographic() const { return fov==Geometry::Angle<float>::zero(); }
float get_orthographic_width() const { return height*aspect; }
Vector4 unproject(const Vector4 &) const;
Vector3 unproject(const Vector3 &) const;
+ /** Returns a ProgramData object containing the camera matrices. */
const ProgramData &get_shader_data() const { return shdata; }
private:
class ObjectInstance;
/**
-Renders multiple instances of an Object in an efficient manner. If instanced
-rendering is supported, only one draw call per Batch needs to be issued.
+Renders multiple instances of an Object in an efficient manner.
-Changing the Mesh of the Object while an InstanceArray exists is not supported.
+The instance specific transform is passed to the shader in an attribute with
+the name instance_transform. The attribute should have the type vec4[3]. Each
+elements of the array corresponds to a row of the transform matrix.
+
+If the Mesh or Technique of the Object is changed during the lifetime of the
+InstanceArray, behaviour is undefined.
*/
class InstanceArray: public Renderable
{
void set_matrix_attribute(const std::string &);
+ /** Adds a new instance to the array. The instance class must have a
+ constructor taking a const reference to Object as its sole parameter. */
template<typename T = ObjectInstance>
T &append();
private:
class Technique;
/**
-Combines a Mesh with a Technique to give it an appearance. The Technique will
-define which render passes the Object supports.
+Combines a Mesh with a Technique for a complete model.
-In many cases, it's desirable to include multiple copies of an Object in a
-Scene, with different model matrices. ObjectInstances can be used to alter the
-rendering of an object on a per-instance basis.
+An object does not have a model matrix and will be rendered at origin if used
+by itself. The ObjectInstance class provides a way to position objects in a
+scene and customize them in other ways.
-Objects can have multiple levels of detail. The most detailed level has index
-0, with increasing indices having less detail. When rendering an instance, the
-instance's get_level_of_detail method is called to determine which LoD to use.
+Objects can have multiple levels of detail, with different resources. The most
+detailed level has index 0, with increasing indices having less detail. When
+rendering an instance, the instance's get_level_of_detail method is called to
+determine which LoD to use.
+
+An Object can be rendered with any tag its Technique supports. Unknown tags
+are silently ignored.
*/
class Object: public Renderable, private ResourceObserver
{
/** Sets the mesh for the highest level of detail (index 0). */
void set_mesh(const Mesh *m) { set_mesh(0, m); }
- /** Sets the mesh for a given level of detail. Previous LoDs must have been
- defined. */
+ /** Sets the mesh for a specific level of detail. LoDs must be defined in
+ order, without gaps. If this call creates a new LoD, technique is copied
+ from the previous one. */
void set_mesh(unsigned, const Mesh *);
private:
/** Sets the technique for the highest level of detail (index 0). */
void set_technique(const Technique *t) { set_technique(0, t); }
- /** Sets the technique for a given level of detail. Previous LoDs must have
- been defined. */
+ /** Sets the technique for a specific level of detail. LoDs must be defined
+ in order, without gaps. If this call creates a new LoD, mesh is copied from
+ the previous one. */
void set_technique(unsigned, const Technique *);
const Technique *get_technique(unsigned = 0) const;
namespace GL {
/**
-Represents a single instance of an Object. Thanks to being derived from
-Placeable in can be positioned without additional effort. Other instance
-parameters can be set by overriding the hook functions.
+Represents a single instance of an Object. A model matrix is provided through
+the Placeable base class.
+
+The state used to render the object can be customized by overriding the
+setup_render() and finish_render() functions.
*/
class ObjectInstance: public PlacedRenderable
{
anything. */
virtual void finish_render(Renderer &, Tag) const { }
+ /** Returns the level of detail to render this instance with. This function
+ should apply LoD bias from the Renderer if desired. */
virtual unsigned get_level_of_detail(const Renderer &) const;
};
class Program;
/**
-A scene that performs occlusion queries on renderables to skip those that are
+A scene which performs occlusion queries on renderables to skip those which are
entirely occluded by others.
+
+Renderables must have valid model matrices and bounding spheres to participate
+in occlusion culling. Those lacking one or both are always rendered.
*/
class OccludedScene: public Scene
{
class Framebuffer;
class RenderTarget;
+/**
+A View targeting an offscreen framebuffer.
+*/
class OffscreenView: public View
{
public:
namespace GL {
/**
-A scene that renders its contents in a specific order. Inserting Renderables
-in the middle and removing them are O(N) operations.
+A scene which renders its contents in a specific order.
*/
class OrderedScene: public Scene
{
};
+/**
+An intermediate base class combining the functionality of Renderable and
+Placeable.
+*/
class PlacedRenderable: public Renderable, public Placeable
{
protected:
struct Color;
/**
-Stores uniform variables for shader programs. The uniforms are stored in a
-program-independent way, and UniformBlocks are created to match the uniform
-layouts of different programs. If multiple programs have the same layout, the
-same block is used for them.
+Stores uniform values for shader programs.
+
+The uniforms are stored in a program-independent way, and UniformBlocks are
+created to match the uniform layouts of different programs. If multiple
+programs have the same layout, the same block is used for them.
The class is optimized for an access pattern where the set of uniforms and
programs stays constants, with only the values changing.
std::vector<ProgramBlock>::const_iterator prepare_program(const Program &) const;
public:
+ /** Creates or updates UniformBlocks for a specific program if necessary,
+ then sets them to the PipelineState. */
void apply(const Program &, PipelineState &) const;
void set_debug_name(const std::string &);
class Renderer;
/**
-Base class for renderable objects. Rendering is performed with the help of a
-Renderer object.
+Base class for things which can be rendered. Rendering is performed with the
+help of the Renderer class.
-The render method takes a Tag to identify a render method. It can be used with
-a Technique to select alternative rendering methods, such as simplified shaders
-for a depth-only shadow pass.
+The tag parameter of render() can be used to choose between different render
+methods, such as simplified shaders for a depth-only shadow pass. Typically
+tags are defined using a Sequence.
-The setup_frame and finish_frame methods provide a mechanism for performing
+The setup_frame() and finish_frame() functions can be overridden to perform
once-per-frame operations. This is most useful for effects, which may need to
-do auxiliary rendering. With complex rendering hierarchies, these methods may
-be called multiple times for one frame, but it's guaranteed that no rendering
-will occur before a setup_frame call or after a finish_frame call.
+prepare textures or other data before actual rendering happens. With complex
+rendering graphs, these functions may be called multiple times for one frame,
+but it's guaranteed that no render() calls will occur before a setup_frame()
+call or after a finish_frame() call.
*/
class Renderable
{
/** Called when a complete frame has been rendered. */
virtual void finish_frame() { }
- /** Renders the Renderable. Implementors should take care to return the
+ /** Renders the Renderable. Subclasses should take care to return the
renderer to the state it was in, for example by using Renderer::Push. */
virtual void render(Renderer &, Tag = Tag()) const = 0;
};
class VertexSetup;
/**
-A class for supervising the rendering process. While many Renderables (in
-particular, Objects and Scenes) can by rendered without a Renderer, using one
-will often be more efficient. This is especially true for ObjectInstances.
-
-The Renderer works by deferring GL state changes until something is actually
-being drawn. This avoids many unnecessary GL calls if consecutive renderables
-use the same resources.
-
-A state stack is provided to help with state scoping. Typically a Renderable
-will push the current state on entry, set whatever state it requires, render
-itself, and pop the state when it's done. An RAII helper class is provided for
-the push/pop operation.
+Rendering supervisor. This is the primary interface for setting state and
+issuing draw commands.
+
+The Renderer class allows setting textures and uniform values by names (using
+ProgramData for the latter). The names are resolved into binding points when
+the resources are needed for a draw command.
+
+A state stack is provided to help with state management in render graphs.
+Renderables can save the state by pushing it on the stack before beginning
+their work, and pop it afterwards to restore it without disturbing state set
+by outer scopes.
*/
class Renderer
{
public:
+ /**
+ RAII helper class for pushing state on the stack.
+ */
class Push
{
private:
DEPRECATED void set_lighting(const Lighting *);
- /** Sets the shader program to use. An initial set of data can be set as
- well, with the same semantics as add_shader_data. */
+ /** Sets the shader program to use. As a convenience, uniform values may be
+ specified at the same time. */
void set_shader_program(const Program *prog, const ProgramData *data = 0);
- /** Adds another set of data to be use with shader programs. The data is
- independent of any shader program changes and remains in effect until the
- Renderer state is popped. */
+ /** Adds uniform values, which will be available for shader programs. If
+ multiple ProgramData objects with the same uniforms are added, the one added
+ last will be used. */
void add_shader_data(const ProgramData &data);
DEPRECATED void flush_shader_data() { flush_shader_data_(); }
void clear(const ClearValue *);
+ /** Draws a batch of primitives. A shader must be active. */
void draw(const Batch &);
+
+ /** Draws multiple instances of a batch of primitives. A shader must be active. */
void draw_instanced(const Batch &, unsigned);
- void resolve_multisample(Framebuffer &);
+ /** Resolves multisample attachments from the active framebuffer into
+ target. */
+ void resolve_multisample(Framebuffer &target);
void begin_query(const QueryPool &, unsigned);
void end_query(const QueryPool &, unsigned);
class Texture;
class Texture2D;
+/**
+Wraps a Framebuffer and its attachments for easier management.
+
+All attachments will be created as 2D or 2D multisample textures, depending on
+the sample count of the format.
+*/
class RenderTarget
{
private:
namespace GL {
/**
-Scenes are containers for other Renderables. This is a base class that can't
-be instantiated. Examples of available Scene types are SimpleScene,
-InstancedScene and OrderedScene.
+Container for other renderables. Subclasses provide different ways of
+rendering the contents.
+
+All types of Scenes perform frustum culling on the contents, skipping
+renderables whose bounding sphere is fully outside the view volume. If a
+bounding sphere cannot be determined, culling is not performed on that
+renderable.
+
+SimpleScene is a good default choice if there are no specific requirements.
*/
class Scene: public Renderable
{
class RenderTarget;
/**
-Top-level content class. Typically a Sequence is used as the content
-Renderable for a View or effects such as ShadowMap or EnvironmentMap.
+Top-level content class. Typically a Sequence is used as content for a View
+or sideband content for effects such as ShadowMap or EnvironmentMap.
A Sequence consists of a number of steps. Each step is defined with a
-Renderable and a tag to render it with and may also have Lighting, DepthTest
-and Blend states. Scenes can be used to further organize Renderables within a
-step.
+Renderable and a tag to render it with. Lighting, DepthTest and StencilTest
+states may also be applied to steps. Scenes can be used to organize multiple
+Renderables within a step.
+
+The target framebuffer can optionally be cleared before the first step.
PostProcessors can be applied after all of the steps in the Sequence have been
processed. Framebuffer objects are automatically used to pass render results
-to the PostProcessors. High dynamic range and multisample rendering can be
-requested for increased quality.
+to the PostProcessors. The Sequence must be created with a size and a frame
+format.
+
+A Sequence itself is normally rendered with an empty tag. A special "noclear"
+tag can be used to suppress clearing.
*/
class Sequence: public Renderable
{
void set_clear_stencil(int);
/** Adds a step to the sequence. It's permissible to add the same
- Renderable multiple times. */
+ Renderable or tag multiple times. */
Step &add_step(Tag, Renderable &);
const std::vector<Step> &get_steps() const { return steps; }
- /** Adds a postprocessor to the sequence. */
+ /** Adds a postprocessor to the sequence. A render target format must be
+ defined. */
void add_postprocessor(PostProcessor &);
const std::vector<PostProcessor *> &get_postprocessors() const { return postproc; }
namespace GL {
/**
-A simple yet efficient scene. Rendering order is unspecified.
+A simple scene which renders its contents in an unspecified order.
*/
class SimpleScene: public Scene
{
namespace GL {
/**
-Creates an object consisting of the visual representation of a string. If you
-derive from Text to customize it, make sure you call Text::setup_render or
-otherwise bind the appropriate texture.
+Creates a Mesh and an Object for rendering text.
+
+The mesh is created with a font size of 1 unit. Set the Text's model matrix to
+scale it to the desired size.
+
+If you derive from Text to customize it, make sure you call Text::setup_render
+or otherwise set the appropriate texture to the Renderer.
*/
class Text: public ObjectInstance
{
const Mesh *get_mesh() const { return &mesh; }
- /** Sets technique to render with, replacing the given texture slot with
+ /** Sets technique to render with, along with the texture slot to use for
the font texture. If no texture slot is specified, heuristics are used to
choose a suitable one. */
void set_technique(const Technique *, Tag = Tag());
const Technique *get_technique() const { return object.get_technique(); }
- /// Sets the string to be displayed.
+ /** Sets the string to be displayed, with an explicit character encoding. */
void set_text(const std::string &, StringCodec::Decoder &);
template<typename C>
set_text(t, dec);
}
+ /** Sets the string to be displayed, with UTF-8 encoding. */
void set_text(const std::string &t)
{ set_text<StringCodec::Utf8>(t); }
- /// Clears the object's contents.
+ /** Clears any previous contents. */
void clear();
- /// Sets horizontal and vertical alignment with predefined anchors.
+ /** Sets horizontal and vertical alignment with predefined anchors. */
void set_alignment(HorizontalAlign, VerticalAlign = BASELINE);
/** Sets horizontal and vertical alignment. 0.0 means left or baseline,
class Renderer;
/**
-Manages the presentation of rendering results on the screen.
+An ultimate render target, which is typically visible to the user of the
+application in some way.
+
+The content renderable's render() function is called with an empty tag. A
+Sequence can be used to specify other tags and add post-processing.
*/
class View
{
virtual unsigned get_height() const { return target.get_height(); }
float get_aspect_ratio() const { return static_cast<float>(get_width())/get_height(); }
+ /** Sets the camera to render with. The camera's aspect ratio is set to
+ match that of the view. */
void set_camera(Camera *);
+
void set_content(Renderable *);
virtual void render();
namespace Msp {
namespace GL {
+/**
+A view targeting a Graphics::Window.
+
+After rendering, buffers are swapped to show the result in the window.
+
+The aspect ratio of the view's Camera is automatically updated to match that of
+the window.
+*/
class WindowView: public View, public sigc::trackable
{
private:
};
/**
-Sorts renderables by their distance from the camera before rendering. Requires
-renderables to have a matrix.
+A scene which sorts renderables by their distance from the camera before
+rendering.
+
+Renderables must have valid model matrices to be sorted. Those without a
+matrix are sorted as closest to the camera.
*/
class ZSortedScene: public Scene
{
class Texture2D;
/**
-A collection class for GL resources. Most useful as a base class for an
-application-specific collection.
+A collection class for GL resources.
+
+The following types of objects can be loaded:
+Animation .anim
+Armature .arma
+BasicMaterial (Material) .mat
+Camera .camera
+DirectionalLight (Light) .light
+Font .font
+KeyFrame .kframe
+Lighting .lightn
+Mesh .mesh
+Module .glsl .spv
+Object (Renderable) .object
+OccludedScene (Scene, Renderable) .scene
+OrderedScene (Scene, Renderable) .scene
+PbrMaterial (Material) .mat
+PointLight (Light) .light
+SequenceTemplate .seq
+Pose .pose
+Program .shader
+Sampler .samp
+SimpleScene (Scene, Renderable) .scene
+Technique .tech
+Texture1D (Texture) .tex
+Texture2D (Texture) .tex .png .jpg
+Texture3D (Texture) .tex
+TextureCube (Texture) .tex
+Texture2DArray (Texture) .tex
+UnlitMaterial (Material) .mat
+ZSortedScene (Scene, Renderable) .scene
+
+This class is normally used by deriving from it and adding any necessary data
+sources in the derived class.
+
+A ResourceManager can be set to manage objects derived from Resource. Bulk
+data for those objects will then be loaded in the background, without blocking
+the main thread.
*/
class Resources: virtual public DataFile::Collection
{