From 190a7e11237351f6b730c28f7b16f183e8adc69c Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 30 Oct 2021 22:51:30 +0300 Subject: [PATCH] Update and improve documentation --- shaderlib/cooktorrance.glsl | 3 +- source/core/batch.h | 27 ++++++++++++---- source/core/blend.h | 2 +- source/core/buffer.h | 24 ++++++++------ source/core/bufferable.h | 25 ++++++++++----- source/core/color.h | 1 + source/core/commands.h | 5 +++ source/core/datatype.h | 8 +++-- source/core/deviceinfo.h | 7 ++++ source/core/framebuffer.h | 34 +++++++++++--------- source/core/frameformat.h | 8 +++-- source/core/mesh.h | 21 ++++++++++-- source/core/module.h | 31 +++++++++++++++++- source/core/pipelinestate.h | 5 +++ source/core/pixelformat.h | 14 ++++---- source/core/program.h | 6 ++-- source/core/query.h | 6 ++++ source/core/sampler.h | 30 ++++++++++-------- source/core/texture.h | 28 ++++++++++------ source/core/texture1d.h | 20 ++++++++++-- source/core/texture2d.h | 35 ++++++++------------ source/core/texture2darray.h | 11 +++++-- source/core/texture2dmultisample.h | 13 +++++++- source/core/texture3d.h | 44 ++++++++++++-------------- source/core/texturecube.h | 47 ++++++++++++++------------- source/core/uniformblock.h | 11 +++++-- source/core/vertexarray.h | 25 +++++++++------ source/core/vertexformat.h | 14 ++++++-- source/core/vertexsetup.h | 20 ++++++++++-- source/effects/ambientocclusion.h | 2 +- source/effects/bloom.h | 9 +++--- source/effects/colorcurve.h | 9 ++++-- source/effects/effect.h | 16 ++++++++-- source/effects/environmentmap.h | 26 ++++++++++----- source/effects/postprocessor.h | 11 ++++--- source/effects/shadowmap.h | 51 ++++++++++++++++++++---------- source/effects/sky.h | 11 +++++-- source/glsl/optimize.h | 1 + source/materials/basicmaterial.h | 7 ++++ source/materials/light.h | 8 ++--- source/materials/lighting.h | 8 +++-- source/materials/material.h | 11 ++++++- source/materials/pbrmaterial.h | 9 ++++++ source/materials/pointlight.h | 3 ++ source/materials/rendermethod.h | 21 ++++++++++-- source/materials/unlitmaterial.h | 4 +++ source/render/camera.h | 29 +++++++++++++++++ source/render/instancearray.h | 12 +++++-- source/render/object.h | 29 ++++++++++------- source/render/objectinstance.h | 10 ++++-- source/render/occludedscene.h | 5 ++- source/render/offscreenview.h | 3 ++ source/render/orderedscene.h | 3 +- source/render/placeable.h | 4 +++ source/render/programdata.h | 11 ++++--- source/render/renderable.h | 21 ++++++------ source/render/renderer.h | 43 ++++++++++++++----------- source/render/rendertarget.h | 6 ++++ source/render/scene.h | 12 +++++-- source/render/sequence.h | 24 ++++++++------ source/render/simplescene.h | 2 +- source/render/text.h | 19 +++++++---- source/render/view.h | 9 +++++- source/render/windowview.h | 8 +++++ source/render/zsortedscene.h | 7 ++-- source/resources/resources.h | 40 +++++++++++++++++++++-- 66 files changed, 724 insertions(+), 305 deletions(-) diff --git a/shaderlib/cooktorrance.glsl b/shaderlib/cooktorrance.glsl index d8e07b29..ff1a56c7 100644 --- a/shaderlib/cooktorrance.glsl +++ b/shaderlib/cooktorrance.glsl @@ -74,7 +74,8 @@ virtual vec3 get_emission_color() /* 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; } diff --git a/source/core/batch.h b/source/core/batch.h index 1e0b4c47..45101d43 100644 --- a/source/core/batch.h +++ b/source/core/batch.h @@ -14,12 +14,12 @@ namespace GL { 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 { @@ -39,17 +39,32 @@ private: 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 &); + + /** 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(); } diff --git a/source/core/blend.h b/source/core/blend.h index 1d39b08f..da7c8c7f 100644 --- a/source/core/blend.h +++ b/source/core/blend.h @@ -46,7 +46,7 @@ enum ColorWriteMask }; /** -Blends incoming fragments with those already in the framebuffer. +Blends incoming fragment color values with those already in the framebuffer. */ struct Blend { diff --git a/source/core/buffer.h b/source/core/buffer.h index 810bfc1a..b642738e 100644 --- a/source/core/buffer.h +++ b/source/core/buffer.h @@ -16,9 +16,14 @@ public: }; /** -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 { @@ -28,17 +33,16 @@ private: 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; } diff --git a/source/core/bufferable.h b/source/core/bufferable.h index 60ce3072..4a4114d0 100644 --- a/source/core/bufferable.h +++ b/source/core/bufferable.h @@ -7,7 +7,9 @@ namespace GL { 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. @@ -15,6 +17,11 @@ 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: @@ -42,21 +49,23 @@ public: 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: @@ -70,11 +79,11 @@ public: 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 diff --git a/source/core/color.h b/source/core/color.h index e376e330..999960ed 100644 --- a/source/core/color.h +++ b/source/core/color.h @@ -23,6 +23,7 @@ struct Color 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); } diff --git a/source/core/commands.h b/source/core/commands.h index 869c41b6..32adeddd 100644 --- a/source/core/commands.h +++ b/source/core/commands.h @@ -6,6 +6,11 @@ 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: diff --git a/source/core/datatype.h b/source/core/datatype.h index a03b6bda..22c72f6a 100644 --- a/source/core/datatype.h +++ b/source/core/datatype.h @@ -8,9 +8,11 @@ namespace Msp { 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 @@ -23,7 +25,7 @@ __ds addd ccrr _bfg ssss ssss └──────────────────────────╴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 { diff --git a/source/core/deviceinfo.h b/source/core/deviceinfo.h index 8550d85f..e121a8ca 100644 --- a/source/core/deviceinfo.h +++ b/source/core/deviceinfo.h @@ -6,6 +6,9 @@ namespace Msp { namespace GL { +/** +Contains information about various limits imposed by the graphics device. +*/ struct Limits { unsigned max_vertex_attributes; @@ -19,6 +22,9 @@ struct Limits Limits(); }; +/** +Contains information about a graphics device. +*/ struct DeviceInfo { Limits limits; @@ -26,6 +32,7 @@ struct DeviceInfo DeviceInfo(); + /** Returns information for the device currently in use. */ static const DeviceInfo &get_global(); }; diff --git a/source/core/framebuffer.h b/source/core/framebuffer.h index 262e4248..d2029022 100644 --- a/source/core/framebuffer.h +++ b/source/core/framebuffer.h @@ -23,16 +23,12 @@ public: }; /** -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 { @@ -86,13 +82,21 @@ public: 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 &); diff --git a/source/core/frameformat.h b/source/core/frameformat.h index df436375..4662ae8f 100644 --- a/source/core/frameformat.h +++ b/source/core/frameformat.h @@ -8,8 +8,10 @@ namespace Msp { 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 @@ -18,7 +20,7 @@ nnnn nn_f _sss _ccc └────────────╴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 { diff --git a/source/core/mesh.h b/source/core/mesh.h index 14b08a96..5544ed1f 100644 --- a/source/core/mesh.h +++ b/source/core/mesh.h @@ -17,9 +17,12 @@ class Buffer; 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 { @@ -79,8 +82,10 @@ public: 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); @@ -90,15 +95,25 @@ public: 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 &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; diff --git a/source/core/module.h b/source/core/module.h index 9ac54d32..1ccbbf3d 100644 --- a/source/core/module.h +++ b/source/core/module.h @@ -21,6 +21,14 @@ public: 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: @@ -37,13 +45,24 @@ 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: @@ -61,6 +80,15 @@ public: 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: @@ -210,6 +238,7 @@ private: 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 &); diff --git a/source/core/pipelinestate.h b/source/core/pipelinestate.h index 6d4d2f64..47870536 100644 --- a/source/core/pipelinestate.h +++ b/source/core/pipelinestate.h @@ -20,6 +20,11 @@ class Texture; 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; diff --git a/source/core/pixelformat.h b/source/core/pixelformat.h index 71a8bd4c..c1804514 100644 --- a/source/core/pixelformat.h +++ b/source/core/pixelformat.h @@ -9,8 +9,9 @@ namespace Msp { 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 @@ -20,7 +21,7 @@ _grs dccc └───────╴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 { @@ -37,8 +38,9 @@ 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) @@ -49,7 +51,7 @@ tnfg ssss cccc cccc └──────────────────╴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 { diff --git a/source/core/program.h b/source/core/program.h index 770c6bad..dab249f4 100644 --- a/source/core/program.h +++ b/source/core/program.h @@ -13,8 +13,10 @@ namespace Msp { 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 { diff --git a/source/core/query.h b/source/core/query.h index 5bcae284..d5b83b96 100644 --- a/source/core/query.h +++ b/source/core/query.h @@ -11,9 +11,15 @@ class Renderer; 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; diff --git a/source/core/sampler.h b/source/core/sampler.h index c7906877..7cf3d83a 100644 --- a/source/core/sampler.h +++ b/source/core/sampler.h @@ -48,18 +48,12 @@ enum TextureWrap /** -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 { @@ -112,7 +106,12 @@ private: 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 @@ -122,6 +121,9 @@ public: 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; } @@ -132,7 +134,9 @@ public: 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. */ @@ -140,7 +144,7 @@ public: /** 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); diff --git a/source/core/texture.h b/source/core/texture.h index c593c0ad..13ff5bc9 100644 --- a/source/core/texture.h +++ b/source/core/texture.h @@ -12,13 +12,20 @@ namespace Msp { 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 { @@ -86,12 +93,13 @@ public: 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; } diff --git a/source/core/texture1d.h b/source/core/texture1d.h index c4230d31..7ef55f80 100644 --- a/source/core/texture1d.h +++ b/source/core/texture1d.h @@ -7,6 +7,9 @@ namespace Msp { namespace GL { +/** +One-dimensional texture, consisting of a single row of texels. +*/ class Texture1D: public Texture1DBackend { friend Texture1DBackend; @@ -30,10 +33,21 @@ private: 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; } diff --git a/source/core/texture2d.h b/source/core/texture2d.h index c6654df6..427e1795 100644 --- a/source/core/texture2d.h +++ b/source/core/texture2d.h @@ -9,9 +9,7 @@ namespace Msp { 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 { @@ -39,27 +37,22 @@ private: 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; } diff --git a/source/core/texture2darray.h b/source/core/texture2darray.h index 662fbad8..98cb1bdc 100644 --- a/source/core/texture2darray.h +++ b/source/core/texture2darray.h @@ -7,9 +7,10 @@ namespace Msp { 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 { @@ -25,7 +26,11 @@ public: 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(); } diff --git a/source/core/texture2dmultisample.h b/source/core/texture2dmultisample.h index 77f4c542..82ab0818 100644 --- a/source/core/texture2dmultisample.h +++ b/source/core/texture2dmultisample.h @@ -6,6 +6,15 @@ 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; @@ -16,7 +25,9 @@ private: 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); diff --git a/source/core/texture3d.h b/source/core/texture3d.h index d791633d..9d5104c9 100644 --- a/source/core/texture3d.h +++ b/source/core/texture3d.h @@ -9,8 +9,7 @@ namespace Msp { 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 { @@ -40,28 +39,25 @@ protected: 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; } diff --git a/source/core/texturecube.h b/source/core/texturecube.h index e738ab53..aa43c9da 100644 --- a/source/core/texturecube.h +++ b/source/core/texturecube.h @@ -19,16 +19,13 @@ enum TextureCubeFace }; /** -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 { @@ -58,25 +55,27 @@ private: 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; } @@ -94,7 +93,7 @@ public: /** 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; } diff --git a/source/core/uniformblock.h b/source/core/uniformblock.h index 5e88f0f8..a71dab25 100644 --- a/source/core/uniformblock.h +++ b/source/core/uniformblock.h @@ -11,8 +11,15 @@ namespace Msp { 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 { diff --git a/source/core/vertexarray.h b/source/core/vertexarray.h index 60e035f9..8e56ee22 100644 --- a/source/core/vertexarray.h +++ b/source/core/vertexarray.h @@ -11,14 +11,17 @@ namespace Msp { 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 { @@ -39,24 +42,28 @@ private: 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; diff --git a/source/core/vertexformat.h b/source/core/vertexformat.h index 4ff34017..d5835013 100644 --- a/source/core/vertexformat.h +++ b/source/core/vertexformat.h @@ -8,7 +8,8 @@ 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 @@ -29,7 +30,7 @@ nnnn nn_f gsss iccc └────────────╴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 { @@ -70,6 +71,9 @@ enum VertexAttribute: std::uint16_t RAW_ATTRIB_I4 = 0xFCCC }; +/** +Describes the attributes of a vertex. Up to 15 attributes are allowed. +*/ class VertexFormat { private: @@ -91,7 +95,13 @@ public: 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; }; diff --git a/source/core/vertexsetup.h b/source/core/vertexsetup.h index 208e55d3..1cdedc79 100644 --- a/source/core/vertexsetup.h +++ b/source/core/vertexsetup.h @@ -12,8 +12,11 @@ class Buffer; 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 { @@ -36,12 +39,25 @@ private: 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; } diff --git a/source/effects/ambientocclusion.h b/source/effects/ambientocclusion.h index efaa2f37..a9ffb81e 100644 --- a/source/effects/ambientocclusion.h +++ b/source/effects/ambientocclusion.h @@ -11,7 +11,7 @@ namespace GL { 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 */ diff --git a/source/effects/bloom.h b/source/effects/bloom.h index 94057b2f..30e98f7e 100644 --- a/source/effects/bloom.h +++ b/source/effects/bloom.h @@ -11,12 +11,11 @@ namespace GL { 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 { diff --git a/source/effects/colorcurve.h b/source/effects/colorcurve.h index 5cebcb00..99263407 100644 --- a/source/effects/colorcurve.h +++ b/source/effects/colorcurve.h @@ -11,9 +11,12 @@ namespace GL { 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 diff --git a/source/effects/effect.h b/source/effects/effect.h index 0d794a3a..ac458361 100644 --- a/source/effects/effect.h +++ b/source/effects/effect.h @@ -9,13 +9,23 @@ namespace Msp { 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