Passing pointer as function parameter will now mean that it is possible
to pass `nullptr`. Some code examples now look like the parameter is
copied instead of referenced, which is misleading. Updated the
documentation to reflect that more clearly.
Makes some cases less consistent (and some convenience shortcuts
impossible), but goes well with the attitude "don't use pointer when it
can't be null".
Inspired in STL, base templated class is renamed to BasicColor{3,4} and
typedef'd with Float type to Color{3, 4}. It is much nicer to write
this:
Color3(1.0f)
Color3::fromHSV(25.0_degf, 0.5f, 0.9f);
instead of this:
Color3<>(1.0f);
Color3<>::fromHSV(25.0_degf, 0.5f, 0.9f);
Avoids some nullptr-related errors and leads to simpler implementation,
as we need to only handle ImageReference and BufferImage types. All
other Image classes are implicitly convertible to ImageReference and
implicit conversion works only with references, not with pointers. The
usage might be clumsy at this point, as Trade::*Importer classes return
pointer to Trade::ImageData which then needs to be dereferenced.
Hopefully introducing C++14's std::optional (or equivalent) might help
solve that issue.
Also removed "convenience" overloads for setting e.g. 2D subdata of 3D
texture. The convenience overload doesn't cover all subdata cases (only
XY plane, not YZ or XZ ones) and overly complicates the implementation.
This can be done in the future in Image classes themselves.
Moreover when the deleted function was private, the compilation failed
with (rather cryptic) error that the function is private instead of
noticing that the function is deleted.
Separated EXT_framebuffer_object, EXT_framebuffer_blit,
EXT_framebuffer_multisample and EXT_packed_depth_stencil don't have the
same functionality as ARB_framebuffer_object (e.g. missing
GL_FRAMEBUFFER_UNDEFINED in glCheckFramebufferStatus()) and separated
read/draw binding is only in EXT_framebuffer_blit, which complicates the
internals.
Checked with Mesa 8/9 and OpenGL 2.1, current one has
ARB_framebuffer_object and also all these four, Mesa 7.7 didn't have
EXT_framebuffer_multisample, but that's a long time ago, so not
supporting these separate extensions shouldn't be an issue.
The problem with unavailable separate binding points remains on OpenGL
ES 2.0, there are three different extensions bringing that
functionality, thus the code managing the available binding points
remains there.
It's now possible to call *Texture::setStorage() even if
OpenGL 4.2, ARB_texture_storage, OpenGL ES 3.0 or EXT_texture_storage in
ES 2.0 is not available, the function will internally use sequence of
setImage() calls as fallback.
It seems to me that this behavior is better than forcing the user to
always check for extension presence and then implementing this
functionality again and again. The huge switches for setting proper
image format and type are ugly though, but according to specs they must
be set even if we are sending no data (which is weird).
Solves another trivial choice (similar to the one with TextureFormat
etc. in 7de45c98b1), less typing and also
preparation for ARB_sampler_objects extension.
Advantages:
* The enums were large (600-800 lines) and they polluted the header,
now they are in separate files (except for BufferTexture, which has
the enum small enough to be left in the same file).
* Image classes now don't need to include OpenGL headers, as they were
needed only for the enum values. With advantage of C++11's forward
enum declarations there is no need to include the enum headers
anywhere in implementation, only when particular values are needed.
* The values are now less verbose:
AbstractTexture::InternalFormat::RGB8 // before
TextureFormat::RGB8 // now
* Resolved another "trivial choice" problem (thanks @JanDupal for
introducing this term to me): how to specify the format if there are
ten ways to do it (some being massively confusing):
Image2D::Format f = AbstractImage::Format::RGB; // too long...
Image2D::Format f = Image3D::Format::RGBA; // why 3D? this works?
Image2D::Format f = BufferImage1D::Format::RGBA; // wat?
It is even worse (and more verbose) with textures:
Texture2D::InternalFormat f =
CubeMapTextureArray::InternalFormat::RGB8; // this is allowed?
To have consistent naming this change was done also with
BufferTexture::InternalFormat (now BufferTextureFormat), although there
were no trivial choice issues and the enum isn't too large. But at least
it is now less typing.
If ARB_invalidate_subdata is not available, these functions do nothing,
instead of crashing on null pointer dereference. It results in more
convenient usage, enabling users to call them whenever they want,
improving performance on implementations which supports that.
It prevents unwanted implicit conversions from e.g. nullptr to Camera,
Vector2 to Physics::Point etc. By making all the constructors explicit
it is easier to routinely add the keyword to all new classes instead of
thinking about cases when to add and when not to.
Got rid of InternalFormat class, now it is all in one big enum, as each
version (desktop, ES2, ES3) has different requirements and it can't be
done that way anymore (moreover that was terribly ugly solution).
Allows simple and convenient call with one value for all axes instead of
that unholy mess:
texture.setWrapping(Texture2D::Wrapping::ClampToEdge);
Previous way (for entertainment purposes):
textute.setWrapping(Math::Vector2<Texture2D::Wrapping>(
Texture2D::Wrapping::ClampToEdge));