From d45857feb08d1eb85dfa38cc99c88b1bc95a580f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 16:57:10 +0200 Subject: [PATCH 01/46] doc: texture documentation updates. Remove duplicates, add minimal multisample docs, update GL function mapping table. --- doc/opengl-mapping.dox | 20 ++++++------- src/Magnum/AbstractTexture.h | 7 +++-- src/Magnum/BufferTexture.h | 7 ++--- src/Magnum/CubeMapTexture.h | 3 +- src/Magnum/CubeMapTextureArray.h | 46 +++++++++++++++++------------- src/Magnum/MultisampleTexture.h | 19 +++++++++---- src/Magnum/RectangleTexture.h | 48 ++++++++++++++------------------ src/Magnum/Texture.h | 41 ++++++++++++++------------- src/Magnum/TextureArray.h | 7 ++--- 9 files changed, 105 insertions(+), 93 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 7d77dc62f..5ec4fc419 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -178,8 +178,8 @@ OpenGL function | Matching API @fn_gl{GetSubroutineIndex} | | @fn_gl{GetSubroutineUniformLocation} | | @fn_gl{GetSync} | | -@fn_gl{GetTexImage}, \n @fn_gl_extension{GetTextureImage,EXT,direct_state_access}, \n @fn_gl_extension{GetnTexImage,ARB,robustness} | @ref Texture::image(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTextureArray::image() -@fn_gl{GetTexLevelParameter}, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize() +@fn_gl{GetTexImage}, \n @fn_gl_extension{GetTextureImage,EXT,direct_state_access}, \n @fn_gl_extension{GetnTexImage,ARB,robustness} | @ref Texture::image(), \n @ref TextureArray::image(), \n @ref CubeMapTexture::image(), \n @ref CubeMapTextureArray::image(), \n @ref RectangleTexture::image() +@fn_gl{GetTexLevelParameter}, \n @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} | @ref Texture::imageSize(), \n @ref TextureArray::imageSize(), \n @ref CubeMapTexture::imageSize(), \n @ref CubeMapTextureArray::imageSize(), \n @ref RectangleTexture::imageSize() @fn_gl{GetTexParameter} | | @fn_gl{GetTransformFeedbackVarying} | | @fn_gl{GetUniform} | not queryable, @ref AbstractShaderProgram::setUniform() setter only @@ -192,8 +192,8 @@ OpenGL function | Matching API @fn_gl{InvalidateBufferSubData} | @ref Buffer::invalidateSubData() @fn_gl{InvalidateFramebuffer}, \n @fn_gles_extension{DiscardFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() @fn_gl{InvalidateSubFramebuffer}, \n @fn_gles_extension{DiscardSubFramebuffer,EXT,discard_framebuffer} | @ref DefaultFramebuffer::invalidate(), \n @ref Framebuffer::invalidate() -@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref MultisampleTexture::invalidateImage(), \n @ref RectangleTexture::invalidateImage() -@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage() +@fn_gl{InvalidateTexImage} | @ref Texture::invalidateImage(), \n @ref TextureArray::invalidateImage(), \n @ref CubeMapTexture::invalidateImage(), \n @ref CubeMapTextureArray::invalidateImage(), \n @ref RectangleTexture::invalidateImage(), \n @ref MultisampleTexture::invalidateImage() +@fn_gl{InvalidateTexSubImage} | @ref Texture::invalidateSubImage(), \n @ref TextureArray::invalidateSubImage(), \n @ref CubeMapTexture::invalidateSubImage(), \n @ref CubeMapTextureArray::invalidateSubImage(), \n @ref RectangleTexture::invalidateSubImage(), \n @ref MultisampleTexture::invalidateSubImage() @fn_gl{IsBuffer}, \n @fn_gl{IsFramebuffer}, \n @fn_gl{IsProgram}, \n @fn_gl{IsProgramPipeline}, \n @fn_gl{IsQuery}, \n @fn_gl{IsRenderbuffer}, \n @fn_gl{IsSampler}, \n @fn_gl{IsShader}, \n @fn_gl{IsSync}, \n @fn_gl{IsTexture}, \n @fn_gl{IsTransformFeedback}, \n @fn_gl{IsVertexArray} | not needed, objects are strongly typed @fn_gl{IsEnabled} | not queryable, @ref Renderer::setFeature() setter only @fn_gl{LineWidth} | @ref Renderer::setLineWidth() @@ -236,12 +236,12 @@ OpenGL function | Matching API @fn_gl{StencilMask}, \n @fn_gl{StencilMaskSeparate} | @ref Renderer::setStencilMask() @fn_gl{StencilOp}, \n @fn_gl{StencilOpSeparate} | @ref Renderer::setStencilOperation() @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() -@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage() -@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | | -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setMinificationFilter(), \n @ref TextureArray::setMinificationFilter(), \n @ref CubeMapTexture::setMinificationFilter(), \n @ref CubeMapTextureArray::setMinificationFilter(), \n @ref RectangleTexture::setMinificationFilter(), \n @ref Texture::setMagnificationFilter(), \n @ref TextureArray::setMagnificationFilter(), \n @ref CubeMapTexture::setMagnificationFilter(), \n @ref CubeMapTextureArray::setMagnificationFilter(), \n @ref RectangleTexture::setMagnificationFilter(), \n @ref Texture::setBorderColor(), \n @ref TextureArray::setBorderColor(), \n @ref CubeMapTexture::setBorderColor(), \n @ref CubeMapTextureArray::setBorderColor(), \n @ref RectangleTexture::setBorderColor(), \n @ref Texture::setMaxAnisotropy(), \n @ref TextureArray::setMaxAnisotropy(), \n @ref CubeMapTexture::setMaxAnisotropy(), \n @ref CubeMapTextureArray::setMaxAnisotropy(), \n @ref RectangleTexture::setMaxAnisotropy(), \n @ref Texture::setWrapping(), \n @ref TextureArray::setWrapping(), \n @ref CubeMapTexture::setWrapping(), \n @ref CubeMapTextureArray::setWrapping(), \n @ref RectangleTexture::setWrapping() -@fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage() -@fn_gl{TexStorage2DMultisample}, \n @fn_gl{TexStorage3DMultisample} | | -@fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage() +@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() +@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()" +@fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() +@fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() +@fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() @fn_gl{TextureView} | | @fn_gl{TransformFeedbackVaryings} | | @fn_gl{Uniform}, \n @fn_gl{ProgramUniform}, \n @fn_gl_extension{ProgramUniform,EXT,direct_state_access} | @ref AbstractShaderProgram::setUniform() diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index c53b07b91..8ab0ea12b 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -39,9 +39,10 @@ namespace Implementation { struct TextureState; } /** @brief Base for textures -Encapsulates one OpenGL texture object. See @ref Texture, @ref CubeMapTexture -and @ref CubeMapTextureArray documentation for more information and usage -examples. +Encapsulates one OpenGL texture object. See @ref Texture, @ref TextureArray, +@ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture, +@ref BufferTexture and @ref MultisampleTexture documentation for more +information and usage examples. @section AbstractTexture-webgl-restrictions WebGL restrictions diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index a8a891d26..a91d85879 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -154,9 +154,8 @@ enum class BufferTextureFormat: GLenum { /** @brief %Buffer texture -This texture is, unlike classic textures such as @ref Texture or -@ref CubeMapTexture, used as simple data source, without any unnecessary -interpolation and wrapping methods. +This texture is, unlike classic textures such as @ref Texture used as simple +data source, without any unnecessary interpolation and wrapping methods. @section BufferTexture-usage Usage @@ -195,7 +194,7 @@ functions use DSA to avoid unnecessary calls to @fn_gl{ActiveTexture} and and respective function documentation for more information. @see @ref Texture, @ref TextureArray, @ref CubeMapTexture, - @ref CubeMapTextureArray, @ref MultisampleTexture, @ref RectangleTexture + @ref CubeMapTextureArray, @ref RectangleTexture, @ref MultisampleTexture @requires_gl31 %Extension @extension{ARB,texture_buffer_object} @requires_gl Texture buffers are not available in OpenGL ES. */ diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 53948a598..2714e8970 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -76,7 +76,8 @@ which intersects one of the six sides of the cube map. See @ref AbstractShaderProgram for more information about usage in shaders. @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTextureArray, - @ref Texture, @ref BufferTexture + @ref Texture, @ref TextureArray, @ref RectangleTexture, @ref BufferTexture, + @ref MultisampleTexture */ class CubeMapTexture: public AbstractTexture { public: diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 0461818e5..8529886bd 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -45,6 +45,8 @@ See @ref CubeMapTexture documentation for introduction. @section CubeMapTextureArray-usage Usage +See @ref Texture documentation for introduction. + Common usage is to specify each layer and face separately using @ref setSubImage(). You have to allocate the memory for all layers and faces first by calling @ref setStorage(). Example: array with 4 layers of cube maps, each cube map @@ -75,7 +77,8 @@ the six sides of the cube map, fourth part is layer in the array. See @ref AbstractShaderProgram for more information about usage in shaders. @see @ref Renderer::Feature::SeamlessCubeMapTexture, @ref CubeMapTexture, - @ref Texture, @ref BufferTexture + @ref Texture, @ref TextureArray, @ref RectangleTexture, @ref BufferTexture, + @ref MultisampleTexture @requires_gl40 %Extension @extension{ARB,texture_cube_map_array} @requires_gl Cube map texture arrays are not available in OpenGL ES. */ @@ -93,13 +96,7 @@ class CubeMapTextureArray: public AbstractTexture { * @brief Set base mip level * @return Reference to self (for method chaining) * - * Taken into account when generating mipmap using @ref generateMipmap() - * and when considering texture completeness when using mipmap - * filtering. Initial value is `0`. - * @see @ref setMaxLevel(), @ref setMinificationFilter(), - * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_BASE_LEVEL} + * See @ref Texture::setBaseLevel() for more information. */ CubeMapTextureArray& setBaseLevel(Int level) { AbstractTexture::setBaseLevel(level); @@ -110,14 +107,7 @@ class CubeMapTextureArray: public AbstractTexture { * @brief Set max mip level * @return Reference to self (for method chaining) * - * Taken into account when generating mipmap using @ref generateMipmap() - * and when considering texture completeness when using mipmap - * filtering. Initial value is `1000`, which is clamped to count of - * levels specified when using @ref setStorage(). - * @see @ref setBaseLevel(), @ref setMinificationFilter(), - * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_MAX_LEVEL} + * See @ref Texture::setMaxLevel() for more information. */ CubeMapTextureArray& setMaxLevel(Int level) { AbstractTexture::setMaxLevel(level); @@ -142,19 +132,37 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } - /** @copydoc RectangleTexture::setBorderColor(const Color4&) */ + /** + * @brief Set border color + * @return Reference to self (for method chaining) + * + * See @ref Texture::setBorderColor(const Color4&) for more + * information. + */ CubeMapTextureArray& setBorderColor(const Color4& color) { AbstractTexture::setBorderColor(color); return *this; } - /** @copydoc RectangleTexture::setBorderColor(const Vector4ui&) */ + /** + * @brief Set border color for integer texture + * @return Reference to self (for method chaining) + * + * See @ref Texture::setBorderColor(const Vector4ui&) for more + * information. + */ CubeMapTextureArray& setBorderColor(const Vector4ui& color) { AbstractTexture::setBorderColor(color); return *this; } - /** @copydoc RectangleTexture::setBorderColor(const Vector4i&) */ + /** + * @brief Set border color for integer texture + * @return Reference to self (for method chaining) + * + * See @ref Texture::setBorderColor(const Vector4i&) for more + * information. + */ CubeMapTextureArray& setBorderColor(const Vector4i& color) { AbstractTexture::setBorderColor(color); return *this; diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 05d54a2c3..1d3a9549f 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -57,22 +57,29 @@ enum class MultisampleTextureSampleLocations: GLboolean { /** @brief Mulitsample texture -Template class for 2D mulitsample texture and 2D multisample texture array. See +Template class for 2D mulitsample texture and 2D multisample texture array. +Used only from shaders for manual multisample resolve and other operations. See also @ref AbstractTexture documentation for more information. -@todoc Finish when fully implemented +@section Texture-usage Usage + +As multisample textures have no sampler state, the only thing you need is to +set storage: +@code +MultisampleTexture2D texture; +texture.setStorage(16, TextureFormat::RGBA8, {1024, 1024}); +@endcode In shader, the texture is used via `sampler2DMS`/`sampler2DMSArray`, `isampler2DMS`/`isampler2DMSArray` or `usampler2DMS`/`usampler2DMSArray`. See @ref AbstractShaderProgram documentation for more information about usage in shaders. +@see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture, + @ref TextureArray, @ref CubeMapTexture, @ref CubeMapTextureArray, + @ref RectangleTexture, @ref BufferTexture @requires_gl32 %Extension @extension{ARB,texture_multisample} @requires_gl Multisample textures are not available in OpenGL ES. - -@see @ref MultisampleTexture2D, @ref MultisampleTexture2DArray, @ref Texture, - @ref TextureArray, @ref BufferTexture, @ref CubeMapTexture, - @ref CubeMapTextureArray, @ref RectangleTexture */ template class MultisampleTexture: public AbstractTexture { public: diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 1e4b5ba35..3fbeefbe4 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -63,11 +63,10 @@ In shader, the texture is used via sampler2DRect`, `sampler2DRectShadow`, `isampler2DRect` or `usampler2DRect`. See @ref AbstractShaderProgram documentation for more information about usage in shaders. +@see @ref Texture, @ref TextureArray, @ref CubeMapTexture, + @ref CubeMapTextureArray, @ref BufferTexture, @ref MultisampleTexture @requires_gl31 %Extension @extension{ARB,texture_rectangle} @requires_gl Rectangle textures are not available in OpenGL ES. - -@see @ref Texture, @ref TextureArray, @ref BufferTexture, @ref CubeMapTexture, - @ref CubeMapTextureArray, @ref MultisampleTexture */ class RectangleTexture: public AbstractTexture { public: @@ -88,8 +87,9 @@ class RectangleTexture: public AbstractTexture { * texture size. If @extension{EXT,direct_state_access} is not * available, the texture is bound to some texture unit before the * operation. Initial value is @ref Sampler::Filter::Linear. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * @see @ref setMagnificationFilter(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_MIN_FILTER} */ RectangleTexture& setMinificationFilter(Sampler::Filter filter) { @@ -109,7 +109,7 @@ class RectangleTexture: public AbstractTexture { * The result is not cached in any way. If * @extension{EXT,direct_state_access} is not available, the texture * is bound to some texture unit before the operation. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @see @ref image(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WIDTH} and @def_gl{TEXTURE_HEIGHT} */ @@ -120,16 +120,17 @@ class RectangleTexture: public AbstractTexture { * @param wrapping Wrapping type for all texture dimensions * @return Reference to self (for method chaining) * - * Sets wrapping type for coordinates out of (0, textureSizeInGivenDirection-1) + * Sets wrapping type for coordinates out of @f$ [ 0, size - 1 ] @f$ * range. If @extension{EXT,direct_state_access} is not available, the * texture is bound to some texture unit before the operation. Initial * value is @ref Sampler::Wrapping::ClampToEdge. * @attention Only @ref Sampler::Wrapping::ClampToEdge and * @ref Sampler::Wrapping::ClampToBorder is supported on this * texture type. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, + * @see @ref setBorderColor(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, * @def_gl{TEXTURE_WRAP_R} */ RectangleTexture& setWrapping(const Array2D& wrapping) { @@ -141,13 +142,8 @@ class RectangleTexture: public AbstractTexture { * @brief Set border color * @return Reference to self (for method chaining) * - * Border color when wrapping is set to @ref Sampler::Wrapping::ClampToBorder. - * If @extension{EXT,direct_state_access} is not available, the texture - * is bound to some texture unit before the operation. Initial value is - * `{0.0f, 0.0f, 0.0f, 0.0f}`. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_BORDER_COLOR} + * See @ref Texture::setBorderColor(const Color4&) for more + * information. */ RectangleTexture& setBorderColor(const Color4& color) { AbstractTexture::setBorderColor(color); @@ -158,22 +154,20 @@ class RectangleTexture: public AbstractTexture { * @brief Set border color for integer texture * @return Reference to self (for method chaining) * - * Border color for integer textures when wrapping is set to - * @ref Sampler::Wrapping::ClampToBorder. If @extension{EXT,direct_state_access} - * is not available, the texture is bound to some texture unit before - * the operation. Initial value is `{0, 0, 0, 0}`. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_BORDER_COLOR} - * @requires_gl30 %Extension @extension{EXT,texture_integer} + * See @ref Texture::setBorderColor(const Vector4ui&) for more + * information. */ RectangleTexture& setBorderColor(const Vector4ui& color) { AbstractTexture::setBorderColor(color); return *this; } - /** @overload - * @requires_gl30 %Extension @extension{EXT,texture_integer} + /** + * @brief Set border color for integer texture + * @return Reference to self (for method chaining) + * + * See @ref Texture::setBorderColor(const Vector4i&) for more + * information. */ RectangleTexture& setBorderColor(const Vector4i& color) { AbstractTexture::setBorderColor(color); diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 5c387d941..0c278b022 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -90,13 +90,12 @@ In shader, the texture is used via `sampler1D`/`sampler2D`/`sampler3D`, See @ref AbstractShaderProgram documentation for more information about usage in shaders. +@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray, + @ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture, + @ref BufferTexture, @ref MultisampleTexture @requires_gles30 %Extension @es_extension{OES,texture_3D} for 3D textures in OpenGL ES 2.0 @requires_gl 1D textures are not available in OpenGL ES, only 2D and 3D ones. - -@see @ref Texture1D, @ref Texture2D, @ref Texture3D, @ref TextureArray, - @ref BufferTexture, @ref CubeMapTexture, @ref CubeMapTextureArray, - @ref MultisampleTexture, @ref RectangleTexture */ template class Texture: public AbstractTexture { public: @@ -176,7 +175,7 @@ template class Texture: public AbstractTexture { * The result is not cached in any way. If * @extension{EXT,direct_state_access} is not available, the texture * is bound to some texture unit before the operation. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @see @ref image(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{GetTexLevelParameter} or @fn_gl_extension{GetTextureLevelParameter,EXT,direct_state_access} * with @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT} or * @def_gl{TEXTURE_DEPTH} @@ -241,8 +240,9 @@ template class Texture: public AbstractTexture { * available, the texture is bound to some texture unit before the * operation. Initial value is {@ref Sampler::Filter::Nearest, * @ref Sampler::Mipmap::Linear}. - * @see @ref setBaseLevel(), @ref setMaxLevel(), @fn_gl{ActiveTexture}, - * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @see @ref setMagnificationFilter(), @ref setBaseLevel(), + * @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} + * and @fn_gl{TexParameter} or * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with * @def_gl{TEXTURE_MIN_FILTER} */ @@ -260,9 +260,10 @@ template class Texture: public AbstractTexture { * texture size. If @extension{EXT,direct_state_access} is not * available, the texture is bound to some texture unit before the * operation. Initial value is @ref Sampler::Filter::Linear. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_MAG_FILTER} + * @see @ref setMinificationFilter(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_MAG_FILTER} */ Texture& setMagnificationFilter(Sampler::Filter filter) { AbstractTexture::setMagnificationFilter(filter); @@ -274,13 +275,14 @@ template class Texture: public AbstractTexture { * @param wrapping Wrapping type for all texture dimensions * @return Reference to self (for method chaining) * - * Sets wrapping type for coordinates out of range (0.0f, 1.0f). If - * @extension{EXT,direct_state_access} is not available, the texture is - * bound to some texture unit before the operation. Initial value is + * Sets wrapping type for coordinates out of range @f$ [ 0.0, 1.0 ] @f$. + * If @extension{EXT,direct_state_access} is not available, the texture + * is bound to some texture unit before the operation. Initial value is * @ref Sampler::Wrapping::Repeat. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, + * @see @ref setBorderColor(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_WRAP_S}, @def_gl{TEXTURE_WRAP_T}, * @def_gl{TEXTURE_WRAP_R} */ Texture& setWrapping(const Array& wrapping) { @@ -296,9 +298,10 @@ template class Texture: public AbstractTexture { * If @extension{EXT,direct_state_access} is not available, the texture * is bound to some texture unit before the operation. Initial value is * `{0.0f, 0.0f, 0.0f, 0.0f}`. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} - * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} - * with @def_gl{TEXTURE_BORDER_COLOR} + * @see @ref setWrapping(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} + * and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_BORDER_COLOR} * @requires_es_extension %Extension @es_extension{NV,texture_border_clamp} */ Texture& setBorderColor(const Color4& color) { diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 4327ff006..6e38ce3ac 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -84,13 +84,12 @@ In shader, the texture is used via `sampler1DArray`/`sampler2DArray`, or `usampler1DArray`/`usampler2DArray`. See @ref AbstractShaderProgram documentation for more information about usage in shaders. +@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture, + @ref CubeMapTexture, @ref CubeMapTextureArray, @ref RectangleTexture, + @ref BufferTexture, @ref MultisampleTexture @requires_gl30 %Extension @extension{EXT,texture_array} @requires_gles30 %Array textures are not available in OpenGL ES 2.0. @requires_gl 1D array textures are not available in OpenGL ES, only 2D ones. - -@see @ref Texture1DArray, @ref Texture2DArray, @ref Texture, @ref BufferTexture, - @ref CubeMapTexture, @ref CubeMapTextureArray, @ref MultisampleTexture, - @ref RectangleTexture */ template class TextureArray: public AbstractTexture { public: From 82ccb08164c1aebc20ff5d5215b435fdf455f493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 17:18:35 +0200 Subject: [PATCH 02/46] doc: fix typo. Embarrassingly enough it was copied to two another places. --- doc/opengl-mapping.dox | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 5ec4fc419..847d6ddc8 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -48,7 +48,7 @@ OpenGL function | Matching API @fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | | @fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | | @fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation() -@fn_gl{BindBuffer} | not needed, handhled internally in @ref Buffer and elsewhere +@fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere @fn_gl{BindBufferBase} | | @fn_gl{BindBufferRange} | | @fn_gl{BindBuffersBase} | | @@ -59,12 +59,12 @@ OpenGL function | Matching API @fn_gl{BindImageTexture} | | @fn_gl{BindImageTextures} | | @fn_gl{BindProgramPipeline} | | -@fn_gl{BindRenderbuffer} | not needed, handhled internally in @ref Renderbuffer +@fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer @fn_gl{BindSampler} | | @fn_gl{BindSamplers} | | @fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTransformFeedback} | | -@fn_gl{BindVertexArray} | not needed, handhled internally in @ref Mesh +@fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh @fn_gl{BindVertexBuffer} | | @fn_gl{BindVertexBuffers} | | @fn_gl{BlendColor} | @ref Renderer::setBlendColor() From 7f653dc50e5401c31cf4b881204dc28bdd1817d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 17:25:55 +0200 Subject: [PATCH 03/46] doc: regroup gl*Draw*() commands in the table. Group similar ones together (all the *Instanced ones will probably be implemented using the same function). --- doc/opengl-mapping.dox | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 847d6ddc8..44fe71cd8 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -110,7 +110,9 @@ OpenGL function | Matching API @fn_gl{DispatchCompute} | | @fn_gl{DispatchComputeIndirect} | | @fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements} | @ref Mesh::draw() -@fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance}, \n @fn_gl{DrawRangeElementsBaseVertex} | | +@fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | +@fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | | +@fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | | @fn_gl{DrawBuffer}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() @fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | @fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature() @@ -203,7 +205,8 @@ OpenGL function | Matching API @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}, @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} | @ref Buffer::mapSub(), @ref Buffer::unmapSub() @fn_gl{MemoryBarrier} | | @fn_gl{MinSampleShading} | | -@fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElements}, \n @fn_gl{MultiDrawElementsBaseVertex}, \n @fn_gl{MultiDrawElementsIndirect} | | +@fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements} | | +@fn_gl{MultiDrawElementsBaseVertex} | | @fn_gl{ObjectLabel}, \n @fn_gl{ObjectPtrLabel}, \n @fn_gl_extension2{LabelObject,EXT,debug_label} | @ref AbstractShaderProgram::setLabel(), \n @ref AbstractQuery::setLabel(), \n @ref AbstractTexture::setLabel(), \n @ref Buffer::setLabel(), \n @ref Framebuffer::setLabel(), \n @ref Mesh::setLabel(), \n @ref Renderbuffer::setLabel(), \n @ref Shader::setLabel() @fn_gl{PatchParameter} | | @fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | | From 653804b518c7a7c6a9be06b1806eadee608e10ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 17:52:56 +0200 Subject: [PATCH 04/46] Added EXT_shader_texture_lod ES2 extension. --- doc/opengl-support.dox | 1 + src/Magnum/Context.cpp | 1 + src/Magnum/Extensions.h | 3 +++ 3 files changed, 5 insertions(+) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 409d5e9d3..273b9c9db 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -250,6 +250,7 @@ supported. @es_extension{EXT,texture_type_2_10_10_10_REV} | done @es_extension{EXT,discard_framebuffer} | done @es_extension2{EXT,blend_minmax,blend_minmax} | done +@es_extension{EXT,shader_texture_lod} | done (shading language only) @es_extension{EXT,occlusion_query_boolean} | done @es_extension{EXT,texture_rg} | done @es_extension{EXT,texture_storage} | done diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 2c5e16127..9c607433f 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -219,6 +219,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,texture_type_2_10_10_10_REV), _extension(GL,EXT,discard_framebuffer), _extension(GL,EXT,blend_minmax), + _extension(GL,EXT,shader_texture_lod), _extension(GL,EXT,occlusion_query_boolean), _extension(GL,EXT,texture_rg), _extension(GL,EXT,texture_storage), diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index e2f07f16d..032fd4a90 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -232,6 +232,9 @@ namespace GL { _extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65 #endif _extension(GL,EXT,read_format_bgra, GLES200, None) // #66 + #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,EXT,shader_texture_lod, GLES200, GLES300) // #77 + #endif _extension(GL,EXT,debug_label, GLES200, None) // #98 _extension(GL,EXT,debug_marker, GLES200, None) // #99 #ifdef MAGNUM_TARGET_GLES2 From 4f4131b320c1225b8a234edc2c8e9c5bbb519002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 17:52:17 +0200 Subject: [PATCH 05/46] Implemented texture LOD parameters. --- doc/opengl-mapping.dox | 4 +- src/Magnum/AbstractTexture.cpp | 28 ++++++++ src/Magnum/AbstractTexture.h | 21 +++++- src/Magnum/CubeMapTexture.h | 22 +++++++ src/Magnum/CubeMapTextureArray.h | 33 ++++++++++ src/Magnum/Implementation/TextureState.cpp | 2 +- src/Magnum/Implementation/TextureState.h | 3 +- src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 3 + src/Magnum/Test/CubeMapTextureGLTest.cpp | 5 ++ src/Magnum/Test/TextureArrayGLTest.cpp | 8 +++ src/Magnum/Test/TextureGLTest.cpp | 13 ++++ src/Magnum/Texture.h | 64 +++++++++++++++++++ src/Magnum/TextureArray.h | 22 +++++++ 13 files changed, 223 insertions(+), 5 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 44fe71cd8..d06fdef20 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -241,7 +241,7 @@ OpenGL function | Matching API @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()" +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()" @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() @@ -340,7 +340,7 @@ OpenGL function | Matching API @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS} | @ref Buffer::maxShaderStorageBindings() @def_gl{MAX_TEXTURE_BUFFER_SIZE} | | @def_gl_extension{MAX_TEXTURE_MAX_ANISOTROPY,EXT,texture_filter_anisotropic} | @ref Sampler::maxMaxAnisotropy() -@def_gl{MAX_TEXTURE_LOD_BIAS} | | +@def_gl{MAX_TEXTURE_LOD_BIAS} | @ref AbstractTexture::maxLodBias() @def_gl{MAX_UNIFORM_BLOCK_SIZE} | @ref AbstractShaderProgram::maxUniformBlockSize() @def_gl{MAX_UNIFORM_BUFFER_BINDINGS} | @ref Buffer::maxUniformBindings() @def_gl{MAX_UNIFORM_LOCATIONS} | @ref AbstractShaderProgram::maxUniformLocations() diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 81c71fe9c..c7921e411 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -50,6 +50,18 @@ namespace Magnum { Int AbstractTexture::maxLayers() { return Shader::maxCombinedTextureImageUnits(); } #endif +#ifndef MAGNUM_TARGET_GLES2 +Float AbstractTexture::maxLodBias() { + GLfloat& value = Context::current()->state().texture->maxLodBias; + + /* Get the value, if not already cached */ + if(value == 0.0f) + glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &value); + + return value; +} +#endif + #ifndef MAGNUM_TARGET_GLES Int AbstractTexture::maxColorSamples() { if(!Context::current()->isExtensionSupported()) @@ -236,6 +248,22 @@ void AbstractTexture::setMagnificationFilter(const Sampler::Filter filter) { (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); } +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::setMinLod(const Float lod) { + (this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod); +} + +void AbstractTexture::setMaxLod(const Float lod) { + (this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::setLodBias(const Float bias) { + (this->*Context::current()->state().texture->parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias); +} +#endif + void AbstractTexture::setBorderColor(const Color4& color) { #ifndef MAGNUM_TARGET_GLES (this->*Context::current()->state().texture->parameterfvImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 8ab0ea12b..0054b1294 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -105,7 +105,6 @@ functions do nothing. then deleting it immediately? @todo ES2 - proper support for pixel unpack buffer when extension is in headers @todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense? -@todo `GL_MAX_TEXTURE_LOD_BIAS` when `TEXTURE_LOD_BIAS` is implemented @todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done @todo Query for immutable levels (@extension{ARB,ES3_compatibility}) @@ -127,6 +126,19 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { static CORRADE_DEPRECATED("use Shader::maxCombinedTextureImageUnits() instead") Int maxLayers(); #endif + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Max level-of-detail bias + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_LOD_BIAS} + * @requires_gles30 %Texture LOD bias doesn't have + * implementation-defined range in OpenGL ES 2.0. + */ + static Float maxLodBias(); + #endif + #ifndef MAGNUM_TARGET_GLES /** * @brief Max supported color sample count @@ -273,6 +285,13 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setMaxLevel(Int level); void setMinificationFilter(Sampler::Filter filter, Sampler::Mipmap mipmap); void setMagnificationFilter(Sampler::Filter filter); + #ifndef MAGNUM_TARGET_GLES2 + void setMinLod(Float lod); + void setMaxLod(Float lod); + #endif + #ifndef MAGNUM_TARGET_GLES + void setLodBias(Float bias); + #endif void setBorderColor(const Color4& color); void setBorderColor(const Vector4i& color); void setBorderColor(const Vector4ui& color); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 2714e8970..b23da70f3 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -125,6 +125,28 @@ class CubeMapTexture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setMinLod() */ + CubeMapTexture& setMinLod(Float lod) { + AbstractTexture::setMinLod(lod); + return *this; + } + + /** @copydoc Texture::setMaxLod() */ + CubeMapTexture& setMaxLod(Float lod) { + AbstractTexture::setMaxLod(lod); + return *this; + } + #endif + + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setLodBias() */ + CubeMapTexture& setLodBias(Float bias) { + AbstractTexture::setLodBias(bias); + return *this; + } + #endif + /** @copydoc Texture::setWrapping() */ CubeMapTexture& setWrapping(const Array3D& wrapping) { DataHelper<3>::setWrapping(*this, wrapping); diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 8529886bd..2c64085cc 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -126,6 +126,39 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } + /** + * @brief Set minimum level-of-detail parameter + * @return Reference to self (for method chaining) + * + * See @ref Texture::setMinLod() for more information. + */ + CubeMapTextureArray& setMinLod(Float lod) { + AbstractTexture::setMinLod(lod); + return *this; + } + + /** + * @brief Set maximum level-of-detail parameter + * @return Reference to self (for method chaining) + * + * See @ref Texture::setMaxLod() for more information. + */ + CubeMapTextureArray& setMaxLod(Float lod) { + AbstractTexture::setMaxLod(lod); + return *this; + } + + /** + * @brief Set level-of-detail bias + * @return Reference to self (for method chaining) + * + * See @ref Texture::setLodBias() for more information. + */ + CubeMapTextureArray& setLodBias(Float bias) { + AbstractTexture::setLodBias(bias); + return *this; + } + /** @copydoc Texture::setWrapping() */ CubeMapTextureArray& setWrapping(const Array3D& wrapping) { DataHelper<3>::setWrapping(*this, wrapping); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 60d362f43..1463be29d 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -36,7 +36,7 @@ namespace Magnum { namespace Implementation { -TextureState::TextureState(Context& context, std::vector& extensions): maxTextureUnits(0), maxMaxAnisotropy(0.0f), currentTextureUnit(0) +TextureState::TextureState(Context& context, std::vector& extensions): maxTextureUnits(0), maxLodBias(0.0f), maxMaxAnisotropy(0.0f), currentTextureUnit(0) #ifndef MAGNUM_TARGET_GLES , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index a3057eca4..28b5335d5 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -75,7 +75,8 @@ struct TextureState { #endif GLint maxTextureUnits; - GLfloat maxMaxAnisotropy; + GLfloat maxLodBias, + maxMaxAnisotropy; GLint currentTextureUnit; #ifndef MAGNUM_TARGET_GLES GLint maxColorSamples, diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index e6f9fdf63..3b0c6fb50 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -123,6 +123,9 @@ void CubeMapTextureArrayGLTest::sampling() { CubeMapTextureArray texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setMinLod(-750.0f) + .setMaxLod(750.0f) + .setLodBias(0.5f) .setBaseLevel(1) .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index c820d365c..b55e7b252 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -141,6 +141,11 @@ void CubeMapTextureGLTest::sampling() { texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) #ifndef MAGNUM_TARGET_GLES2 + .setMinLod(-750.0f) + .setMaxLod(750.0f) + #ifndef MAGNUM_TARGET_GLES + .setLodBias(0.5f) + #endif .setBaseLevel(1) .setMaxLevel(750) #endif diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index d7c2d2f68..b3caf3532 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -263,6 +263,9 @@ void TextureArrayGLTest::sampling1D() { Texture1DArray texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setMinLod(-750.0f) + .setMaxLod(750.0f) + .setLodBias(0.5f) .setBaseLevel(1) .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) @@ -297,6 +300,11 @@ void TextureArrayGLTest::sampling2D() { texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) #ifndef MAGNUM_TARGET_GLES2 + .setMinLod(-750.0f) + .setMaxLod(750.0f) + #ifndef MAGNUM_TARGET_GLES + .setLodBias(0.5f) + #endif .setBaseLevel(1) .setMaxLevel(750) #endif diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index ee23b0316..e8aaccf72 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -333,6 +333,9 @@ void TextureGLTest::sampling1D() { Texture1D texture; texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) + .setMinLod(-750.0f) + .setMaxLod(750.0f) + .setLodBias(0.5f) .setBaseLevel(1) .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) @@ -348,6 +351,11 @@ void TextureGLTest::sampling2D() { texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) #ifndef MAGNUM_TARGET_GLES2 + .setMinLod(-750.0f) + .setMaxLod(750.0f) + #ifndef MAGNUM_TARGET_GLES + .setLodBias(0.5f) + #endif .setBaseLevel(1) .setMaxLevel(750) #endif @@ -411,6 +419,11 @@ void TextureGLTest::sampling3D() { texture.setMinificationFilter(Sampler::Filter::Linear, Sampler::Mipmap::Linear) .setMagnificationFilter(Sampler::Filter::Linear) #ifndef MAGNUM_TARGET_GLES2 + .setMinLod(-750.0f) + .setMaxLod(750.0f) + #ifndef MAGNUM_TARGET_GLES + .setLodBias(0.5f) + #endif .setBaseLevel(1) .setMaxLevel(750) #endif diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 0c278b022..e7eebf850 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -270,6 +270,70 @@ template class Texture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set minimum level-of-detail parameter + * @return Reference to self (for method chaining) + * + * Limits selection of highest resolution mipmap. If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some texture unit before the operation. Initial value is + * `-1000.0f`. + * @see @ref setMaxLod(), @ref setLodBias(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_MIN_LOD} + * @requires_gles30 %Texture LOD parameters are not available in OpenGL + * ES 2.0. + */ + Texture& setMinLod(Float lod) { + AbstractTexture::setMinLod(lod); + return *this; + } + + /** + * @brief Set maximum level-of-detail parameter + * @return Reference to self (for method chaining) + * + * Limits selection of lowest resolution mipmap. If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some texture unit before the operation. Initial value is + * `1000.0f`. + * @see @ref setMinLod(), @ref setLodBias(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_MAX_LOD} + * @requires_gles30 %Texture LOD parameters are not available in OpenGL + * ES 2.0. + */ + Texture& setMaxLod(Float lod) { + AbstractTexture::setMaxLod(lod); + return *this; + } + #endif + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set level-of-detail bias + * @return Reference to self (for method chaining) + * + * Fixed bias value that is added to the level-of-detail parameter. If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some texture unit before the operation. Initial value is + * `0.0f`. + * @see @ref maxLodBias(), @ref setMinLod(), @ref setMaxLod(), + * @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} + * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * with @def_gl{TEXTURE_LOD_BIAS} + * @requires_gl %Texture LOD bias can be specified only directly in + * fragment shader in OpenGL ES. + */ + Texture& setLodBias(Float bias) { + AbstractTexture::setLodBias(bias); + return *this; + } + #endif + /** * @brief Set wrapping * @param wrapping Wrapping type for all texture dimensions diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 6e38ce3ac..e21fba8f1 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -130,6 +130,28 @@ template class TextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setMinLod() */ + TextureArray& setMinLod(Float lod) { + AbstractTexture::setMinLod(lod); + return *this; + } + + /** @copydoc Texture::setMaxLod() */ + TextureArray& setMaxLod(Float lod) { + AbstractTexture::setMaxLod(lod); + return *this; + } + #endif + + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setLodBias() */ + TextureArray& setLodBias(Float bias) { + AbstractTexture::setLodBias(bias); + return *this; + } + #endif + /** @copydoc Texture::setWrapping() */ TextureArray& setWrapping(const Array& wrapping) { DataHelper::setWrapping(*this, wrapping); From 7afe12910a0ee8805d7505847e7ddbb24672df86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 17:52:36 +0200 Subject: [PATCH 06/46] Platform: display max lod bias in magnum-info. --- src/Magnum/Platform/magnum-info.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 0728e5ab5..8c050ab05 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -249,6 +249,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(AbstractTexture::maxDepthSamples()) _l(AbstractTexture::maxIntegerSamples()) #endif + #ifndef MAGNUM_TARGET_GLES2 + _l(AbstractTexture::maxLodBias()) + #endif #ifndef MAGNUM_TARGET_GLES if(c->isExtensionSupported()) { From 1e60a306cada07b141bc57381bfe6ad3e519862f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 18:41:47 +0200 Subject: [PATCH 07/46] doc: updated Sampler documentation. Reference actual *Texture methods from there, it will be some time until actual sampler objects are implemented. --- src/Magnum/Sampler.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index 51a6ba890..9f5819530 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class Magnum::Sampler + * @brief Class @ref Magnum::Sampler */ #include "Magnum/Magnum.h" @@ -38,14 +38,16 @@ namespace Magnum { /** @brief %Texture sampler -@see Texture, CubeMapTexture, CubeMapTextureArray +@see @ref Texture, @ref TextureArray, @ref CubeMapTexture, + @ref CubeMapTextureArray, @ref RectangleTexture */ class MAGNUM_EXPORT Sampler { public: /** * @brief %Texture filtering * - * @see setMagnificationFilter() and setMinificationFilter() + * @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", + * @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()" */ enum class Filter: GLint { Nearest = GL_NEAREST, /**< Nearest neighbor filtering */ @@ -65,7 +67,7 @@ class MAGNUM_EXPORT Sampler { /** * @brief Mip level selection * - * @see setMinificationFilter() + * @see @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()" */ enum class Mipmap: GLint { Base = GL_NEAREST & ~GL_NEAREST, /**< Select base mip level */ @@ -91,7 +93,7 @@ class MAGNUM_EXPORT Sampler { /** * @brief %Texture wrapping * - * @see setWrapping() + * @see @ref Texture::setWrapping() "*Texture::setWrapping()" */ enum class Wrapping: GLint { /** Repeat texture. **Unavailable on rectangle textures.** */ @@ -110,7 +112,8 @@ class MAGNUM_EXPORT Sampler { /** * Clamp to border color. Coordinates out of range will be clamped - * to border color (set with setBorderColor()). + * to border color (set with + * @ref Texture::setBorderColor() "*Texture::setBorderColor()"). * @requires_es_extension %Extension @es_extension{NV,texture_border_clamp} */ #ifndef MAGNUM_TARGET_GLES @@ -139,7 +142,7 @@ class MAGNUM_EXPORT Sampler { * The result is cached, repeated queries don't result in repeated * OpenGL calls. If extension @extension{EXT,texture_filter_anisotropic} * (desktop or ES) is not available, returns `0.0f`. - * @see setMaxAnisotropy(), @fn_gl{Get} with @def_gl{MAX_TEXTURE_MAX_ANISOTROPY_EXT} + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_MAX_ANISOTROPY_EXT} */ static Float maxMaxAnisotropy(); From 424526a7c867ee89795c48dbf717feb88e1269a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 18:52:23 +0200 Subject: [PATCH 08/46] Integer texture borders are not available in OpenGL ES. --- src/Magnum/AbstractTexture.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 0054b1294..18feb72f5 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -293,8 +293,10 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setLodBias(Float bias); #endif void setBorderColor(const Color4& color); + #ifndef MAGNUM_TARGET_GLES void setBorderColor(const Vector4i& color); void setBorderColor(const Vector4ui& color); + #endif void setMaxAnisotropy(Float anisotropy); void invalidateImage(Int level); void generateMipmap(); From af9772bdc070e37a569d188d83b239cf8aa9868d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 19:23:26 +0200 Subject: [PATCH 09/46] Add forgotten check to extension-dependent texture tests. --- src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 2 ++ src/Magnum/Test/RectangleTextureGLTest.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 3b0c6fb50..514cb87ea 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -136,6 +136,8 @@ void CubeMapTextureArrayGLTest::sampling() { } void CubeMapTextureArrayGLTest::samplingBorderInteger() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index 91404f694..540985f10 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -132,6 +132,8 @@ void RectangleTextureGLTest::sampling() { } void RectangleTextureGLTest::samplingBorderInteger() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); From 8a98ab06756a77a10b93e51e208900c6950f9f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 10 Apr 2014 19:27:54 +0200 Subject: [PATCH 10/46] Implementation of ARB_stencil_texturing. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 6 ++++ src/Magnum/AbstractTexture.h | 3 ++ src/Magnum/CubeMapTexture.h | 8 +++++ src/Magnum/CubeMapTextureArray.h | 8 +++++ src/Magnum/RectangleTexture.h | 8 +++++ src/Magnum/Sampler.cpp | 13 +++++++ src/Magnum/Sampler.h | 22 ++++++++++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 14 ++++++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 12 +++++++ src/Magnum/Test/RectangleTextureGLTest.cpp | 14 ++++++++ src/Magnum/Test/SamplerTest.cpp | 18 +++++++++- src/Magnum/Test/TextureArrayGLTest.cpp | 24 +++++++++++++ src/Magnum/Test/TextureGLTest.cpp | 36 +++++++++++++++++++ src/Magnum/Texture.h | 20 +++++++++++ src/Magnum/TextureArray.h | 8 +++++ src/Magnum/TextureFormat.h | 3 ++ 18 files changed, 218 insertions(+), 3 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index d06fdef20..0d1c4cac9 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -241,7 +241,7 @@ OpenGL function | Matching API @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()" +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 273b9c9db..c5ca18e64 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -184,7 +184,7 @@ following: @extension{ARB,robust_buffer_access_behavior} | done (nothing to do) @extension{ARB,shader_image_size} | done (shading language only) @extension{ARB,shader_storage_buffer_object} | only limit queries -@extension{ARB,stencil_texturing} | | +@extension{ARB,stencil_texturing} | done @extension{ARB,texture_buffer_range} | done @extension{ARB,texture_query_levels} | done (shading language only) @extension{ARB,texture_storage_multisample} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index c7921e411..1fb3143d4 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -286,6 +286,12 @@ void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); } +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::setDepthStencilMode(const Sampler::DepthStencilMode mode) { + (this->*Context::current()->state().texture->parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode)); +} +#endif + void AbstractTexture::invalidateImage(const Int level) { (this->*Context::current()->state().texture->invalidateImageImplementation)(level); } diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 18feb72f5..f6797bb02 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -298,6 +298,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setBorderColor(const Vector4ui& color); #endif void setMaxAnisotropy(Float anisotropy); + #ifndef MAGNUM_TARGET_GLES + void setDepthStencilMode(Sampler::DepthStencilMode mode); + #endif void invalidateImage(Int level); void generateMipmap(); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index b23da70f3..b3b8f4574 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -179,6 +179,14 @@ class CubeMapTexture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setDepthStencilMode() */ + CubeMapTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) { + AbstractTexture::setDepthStencilMode(mode); + return *this; + } + #endif + #ifndef MAGNUM_TARGET_GLES /** * @brief %Image size in given mip level diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 2c64085cc..88ae9e584 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -207,6 +207,14 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setDepthStencilMode() */ + CubeMapTextureArray& setDepthStencilMode(Sampler::DepthStencilMode mode) { + AbstractTexture::setDepthStencilMode(mode); + return *this; + } + #endif + /** * @brief %Image size in given mip level * @param level Mip level diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 3fbeefbe4..452fdfe75 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -180,6 +180,14 @@ class RectangleTexture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setDepthStencilMode() */ + RectangleTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) { + AbstractTexture::setDepthStencilMode(mode); + return *this; + } + #endif + /** * @brief Set storage * @param internalFormat Internal format diff --git a/src/Magnum/Sampler.cpp b/src/Magnum/Sampler.cpp index 35de1dab4..9a6138c72 100644 --- a/src/Magnum/Sampler.cpp +++ b/src/Magnum/Sampler.cpp @@ -99,6 +99,19 @@ Debug operator<<(Debug debug, const Sampler::Wrapping value) { return debug << "Sampler::Wrapping::(invalid)"; } + +#ifndef MAGNUM_TARGET_GLES +Debug operator<<(Debug debug, const Sampler::DepthStencilMode value) { + switch(value) { + #define _c(value) case Sampler::DepthStencilMode::value: return debug << "Sampler::DepthStencilMode::" #value; + _c(DepthComponent) + _c(StencilIndex) + #undef _c + } + + return debug << "Sampler::DepthStencilMode::(invalid)"; +} +#endif #endif } diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index 9f5819530..674e5a807 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -136,6 +136,23 @@ class MAGNUM_EXPORT Sampler { #endif }; + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Depth/stencil texture mode + * + * @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" + * @requires_gl43 %Extension @extension{ARB,stencil_texturing} + * @requires_gl Stencil texturing is not available in OpenGL ES. + */ + enum class DepthStencilMode: GLenum { + /** Sample depth component */ + DepthComponent = GL_DEPTH_COMPONENT, + + /** Sample stencil index (as unsigned integer texture) */ + StencilIndex = GL_STENCIL_INDEX + }; + #endif + /** * @brief Max supported max anisotropy * @@ -165,6 +182,11 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Mipmap value); /** @debugoperator{Magnum::Sampler} */ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Wrapping value); +#ifndef MAGNUM_TARGET_GLES +/** @debugoperator{Magnum::Sampler} */ +Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::DepthStencilMode value); +#endif + } #endif diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 514cb87ea..847ffe9e3 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -44,6 +44,7 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester { void sampling(); void samplingBorderInteger(); + void samplingDepthStencilMode(); void storage(); @@ -64,6 +65,7 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { &CubeMapTextureArrayGLTest::sampling, &CubeMapTextureArrayGLTest::samplingBorderInteger, + &CubeMapTextureArrayGLTest::samplingDepthStencilMode, &CubeMapTextureArrayGLTest::storage, @@ -151,6 +153,18 @@ void CubeMapTextureArrayGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } +void CubeMapTextureArrayGLTest::samplingDepthStencilMode() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + CubeMapTextureArray texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} + void CubeMapTextureArrayGLTest::storage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index b55e7b252..892bc249c 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -51,6 +51,7 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { #endif #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger(); + void samplingDepthStencilMode(); #endif void storage(); @@ -81,6 +82,7 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { #endif #ifndef MAGNUM_TARGET_GLES &CubeMapTextureGLTest::samplingBorderInteger, + &CubeMapTextureGLTest::samplingDepthStencilMode, #endif &CubeMapTextureGLTest::storage, @@ -182,6 +184,16 @@ void CubeMapTextureGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } + +void CubeMapTextureGLTest::samplingDepthStencilMode() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + CubeMapTexture texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif void CubeMapTextureGLTest::storage() { diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index 540985f10..ade0e0b03 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -45,6 +45,7 @@ class RectangleTextureGLTest: public AbstractOpenGLTester { void sampling(); void samplingBorderInteger(); + void samplingDepthStencilMode(); void storage(); @@ -63,6 +64,7 @@ RectangleTextureGLTest::RectangleTextureGLTest() { &RectangleTextureGLTest::sampling, &RectangleTextureGLTest::samplingBorderInteger, + &RectangleTextureGLTest::samplingDepthStencilMode, &RectangleTextureGLTest::storage, @@ -147,6 +149,18 @@ void RectangleTextureGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } +void RectangleTextureGLTest::samplingDepthStencilMode() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} + void RectangleTextureGLTest::storage() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/SamplerTest.cpp b/src/Magnum/Test/SamplerTest.cpp index 48d4e947b..812734c02 100644 --- a/src/Magnum/Test/SamplerTest.cpp +++ b/src/Magnum/Test/SamplerTest.cpp @@ -37,12 +37,19 @@ class SamplerTest: public TestSuite::Tester { void debugFilter(); void debugMipmap(); void debugWrapping(); + #ifndef MAGNUM_TARGET_GLES + void debugDepthStencilMode(); + #endif }; SamplerTest::SamplerTest() { addTests({&SamplerTest::debugFilter, &SamplerTest::debugMipmap, - &SamplerTest::debugWrapping}); + &SamplerTest::debugWrapping, + #ifndef MAGNUM_TARGET_GLES + &SamplerTest::debugDepthStencilMode + #endif + }); } void SamplerTest::debugFilter() { @@ -66,6 +73,15 @@ void SamplerTest::debugWrapping() { CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge\n"); } +#ifndef MAGNUM_TARGET_GLES +void SamplerTest::debugDepthStencilMode() { + std::ostringstream out; + + Debug(&out) << Sampler::DepthStencilMode::StencilIndex; + CORRADE_COMPARE(out.str(), "Sampler::DepthStencilMode::StencilIndex\n"); +} +#endif + }} CORRADE_TEST_MAIN(Magnum::Test::SamplerTest) diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index b3caf3532..4dbc82dfa 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -62,6 +62,8 @@ class TextureArrayGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger1D(); void samplingBorderInteger2D(); + void samplingDepthStencilMode1D(); + void samplingDepthStencilMode2D(); #else void samplingBorder2D(); #endif @@ -127,6 +129,8 @@ TextureArrayGLTest::TextureArrayGLTest() { #ifndef MAGNUM_TARGET_GLES &TextureArrayGLTest::samplingBorderInteger1D, &TextureArrayGLTest::samplingBorderInteger2D, + &TextureArrayGLTest::samplingDepthStencilMode1D, + &TextureArrayGLTest::samplingDepthStencilMode2D, #else &TextureArrayGLTest::samplingBorder2D, #endif @@ -288,6 +292,16 @@ void TextureArrayGLTest::samplingBorderInteger1D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureArrayGLTest::samplingDepthStencilMode1D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif void TextureArrayGLTest::sampling2D() { @@ -345,6 +359,16 @@ void TextureArrayGLTest::samplingBorderInteger2D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureArrayGLTest::samplingDepthStencilMode2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #else void TextureArrayGLTest::samplingBorder2D() { if(!Context::current()->isExtensionSupported()) diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index e8aaccf72..2ef5f9f35 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -68,6 +68,9 @@ class TextureGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger2D(); void samplingBorderInteger3D(); + void samplingDepthStencilMode1D(); + void samplingDepthStencilMode2D(); + void samplingDepthStencilMode3D(); #else void samplingBorder2D(); void samplingBorder3D(); @@ -154,6 +157,9 @@ TextureGLTest::TextureGLTest() { #ifndef MAGNUM_TARGET_GLES &TextureGLTest::samplingBorderInteger2D, &TextureGLTest::samplingBorderInteger3D, + &TextureGLTest::samplingDepthStencilMode1D, + &TextureGLTest::samplingDepthStencilMode2D, + &TextureGLTest::samplingDepthStencilMode3D, #else &TextureGLTest::samplingBorder2D, &TextureGLTest::samplingBorder3D, @@ -344,6 +350,16 @@ void TextureGLTest::sampling1D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureGLTest::samplingDepthStencilMode1D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + Texture1D texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif void TextureGLTest::sampling2D() { @@ -396,6 +412,16 @@ void TextureGLTest::samplingBorderInteger2D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureGLTest::samplingDepthStencilMode2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + Texture2D texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #else void TextureGLTest::samplingBorder2D() { if(!Context::current()->isExtensionSupported()) @@ -466,6 +492,16 @@ void TextureGLTest::samplingBorderInteger3D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureGLTest::samplingDepthStencilMode3D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); + + Texture3D texture; + texture.setDepthStencilMode(Sampler::DepthStencilMode::StencilIndex); + + MAGNUM_VERIFY_NO_ERROR(); +} #else void TextureGLTest::samplingBorder3D() { #ifdef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index e7eebf850..85ad55cb6 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -425,6 +425,26 @@ template class Texture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set depth/stencil texture mode + * + * Selects which component of packed depth/stencil texture is used for + * texturing. If @extension{EXT,direct_state_access} is not available, + * the texture is bound to some texture unit before the operation. + * Initial value is @ref Sampler::DepthStencilMode::DepthComponent. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} + * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} + * with @def_gl{DEPTH_STENCIL_TEXTURE_MODE} + * @requires_gl43 %Extension @extension{ARB,stencil_texturing} + * @requires_gl Stencil texturing is not available in OpenGL ES. + */ + Texture& setDepthStencilMode(Sampler::DepthStencilMode mode) { + AbstractTexture::setDepthStencilMode(mode); + return *this; + } + #endif + /** * @brief Set storage * @param levels Mip level count diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index e21fba8f1..ce8413b60 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -184,6 +184,14 @@ template class TextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES + /** @copydoc Texture::setDepthStencilMode() */ + TextureArray& setDepthStencilMode(Sampler::DepthStencilMode mode) { + AbstractTexture::setDepthStencilMode(mode); + return *this; + } + #endif + #ifndef MAGNUM_TARGET_GLES /** @copydoc Texture::imageSize() */ typename DimensionTraits::VectorType imageSize(Int level) { diff --git a/src/Magnum/TextureFormat.h b/src/Magnum/TextureFormat.h index b173c7960..55f83fa44 100644 --- a/src/Magnum/TextureFormat.h +++ b/src/Magnum/TextureFormat.h @@ -834,6 +834,7 @@ enum class TextureFormat: GLenum { * Depth and stencil component, size implementation-dependent. Not * supported in 3D textures, not allowed in unemulated * @ref Texture::setStorage() "*Texture::setStorage()" calls. + * @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" * @deprecated_gl Prefer to use exactly specified version of this format, * e.g. @ref Magnum::TextureFormat::Depth24Stencil8 "TextureFormat::Depth24Stencil8". * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} or @@ -847,6 +848,7 @@ enum class TextureFormat: GLenum { /** * 24bit depth and 8bit stencil component. Not supported in 3D textures. + * @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" * @requires_gl30 %Extension @extension{ARB,framebuffer_object} * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} and * (@es_extension{OES,required_internalformat} or @@ -863,6 +865,7 @@ enum class TextureFormat: GLenum { /** * 32bit float depth component and 8bit stencil component. Not supported in * 3D textures. + * @see @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" * @requires_gl30 %Extension @extension{ARB,depth_buffer_float} * @requires_gles30 Only integral depth textures are available in OpenGL ES * 2.0. From 004e94abda541c49ea797aea61d5131a5550e5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 11 Apr 2014 21:57:35 +0200 Subject: [PATCH 11/46] doc: more GL command mapping updates. --- doc/opengl-mapping.dox | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 0d1c4cac9..5ebc5dd65 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -40,7 +40,7 @@ Legend: OpenGL function | Matching API -------------------------------------- | ------------ -@fn_gl{ActiveShaderProgram} | | +@fn_gl{ActiveShaderProgram} | not needed as @fn_gl{ProgramUniform} calls are used @fn_gl{ActiveTexture} | @ref AbstractTexture::bind() @fn_gl{AttachShader} | @ref AbstractShaderProgram::attachShader() @fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender() @@ -49,24 +49,18 @@ OpenGL function | Matching API @fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | | @fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation() @fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere -@fn_gl{BindBufferBase} | | -@fn_gl{BindBufferRange} | | -@fn_gl{BindBuffersBase} | | -@fn_gl{BindBuffersRange} | | +@fn_gl{BindBufferBase}, \n @fn_gl{BindBuffersBase}, \n @fn_gl{BindBufferRange}, \n @fn_gl{BindBuffersRange} | | @fn_gl{BindFragDataLocation} | @ref AbstractShaderProgram::bindFragmentDataLocation() @fn_gl{BindFragDataLocationIndexed} | @ref AbstractShaderProgram::bindFragmentDataLocationIndexed() @fn_gl{BindFramebuffer} | @ref Framebuffer::bind() -@fn_gl{BindImageTexture} | | -@fn_gl{BindImageTextures} | | +@fn_gl{BindImageTexture}, \n @fn_gl{BindImageTextures} | | @fn_gl{BindProgramPipeline} | | @fn_gl{BindRenderbuffer} | not needed, handled internally in @ref Renderbuffer -@fn_gl{BindSampler} | | -@fn_gl{BindSamplers} | | +@fn_gl{BindSampler}, \n @fn_gl{BindSamplers} | | @fn_gl{BindTexture}, \n @fn_gl{BindTextures}, \n @fn_gl_extension{BindMultiTexture,EXT,direct_state_access} | @ref AbstractTexture::bind() @fn_gl{BindTransformFeedback} | | @fn_gl{BindVertexArray} | not needed, handled internally in @ref Mesh -@fn_gl{BindVertexBuffer} | | -@fn_gl{BindVertexBuffers} | | +@fn_gl{BindVertexBuffer}, \n @fn_gl{BindVertexBuffers} | | @fn_gl{BlendColor} | @ref Renderer::setBlendColor() @fn_gl{BlendEquation}, \n @fn_gl{BlendEquationSeparate} | @ref Renderer::setBlendEquation() @fn_gl{BlendFunc}, \n @fn_gl{BlendFuncSeparate} | @ref Renderer::setBlendFunction() @@ -123,11 +117,10 @@ OpenGL function | Matching API @fn_gl{FlushMappedBufferRange}, \n @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access} | @ref Buffer::flushMappedRange() @fn_gl2{FramebufferParameter,FramebufferParameteri} | | @fn_gl{FramebufferRenderbuffer}, \n @fn_gl_extension{NamedFramebufferRenderbuffer,EXT,direct_state_access} | @ref Framebuffer::attachRenderbuffer() -@fn_gl{FramebufferTexture} | | -@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access} | @ref Framebuffer::attachTexture1D() -@fn_gl2{FramebufferTexture2D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture2D,EXT,direct_state_access} | @ref Framebuffer::attachTexture2D() -@fn_gl2{FramebufferTexture3D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture3D,EXT,direct_state_access} | @ref Framebuffer::attachTexture3D() -@fn_gl{FramebufferTextureLayer} | | +@fn_gl{FramebufferTexture} | not used, the functions below are used instead for compatibility reasons +@fn_gl2{FramebufferTexture1D,FramebufferTexture}, \n @fn_gl_extension{NamedFramebufferTexture1D,EXT,direct_state_access}, \n `glFramebufferTexture2D()`, \n `glNamedFramebufferTexture2DEXT()` | @ref Framebuffer::attachTexture() +@fn_gl2{FramebufferTexture3D,FramebufferTexture} | not used, @fn_gl{FramebufferTextureLayer} has more complete features +@fn_gl{FramebufferTextureLayer}, \n @fn_gl_extension{NamedFramebufferTextureLayer,EXT,direct_state_access} | @ref Framebuffer::attachTextureLayer() @fn_gl{FrontFace} | @ref Renderer::setFrontFace() @fn_gl{GenBuffers}, @fn_gl{DeleteBuffers} | @ref Buffer constructor and destructor @fn_gl{GenFramebuffers}, @fn_gl{DeleteFramebuffers} | @ref Framebuffer constructor and destructor From 99281a1bd1172e6c9914527529ccd1abae5f3b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 00:51:52 +0200 Subject: [PATCH 12/46] Cleaned up duplicate stuff in CMakeLists. --- src/Magnum/CMakeLists.txt | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 5ff0d2030..a9ef0bf8c 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -75,18 +75,6 @@ set(Magnum_SRCS Trade/SceneData.cpp Trade/TextureData.cpp) -# Desktop-only code -if(NOT TARGET_GLES) - set(Magnum_SRCS ${Magnum_SRCS} - BufferTexture.cpp) -endif() - -# Not-ES2 code -if(NOT TARGET_GLES2) - set(Magnum_SRCS ${Magnum_SRCS} - BufferImage.cpp) -endif() - set(Magnum_HEADERS AbstractFramebuffer.h AbstractImage.h @@ -133,21 +121,25 @@ if(BUILD_DEPRECATED) DebugMarker.h) endif() -# Desktop-only headers and libraries +# Desktop-only stuff if(NOT TARGET_GLES) set(Magnum_HEADERS ${Magnum_HEADERS} BufferTexture.h CubeMapTextureArray.h MultisampleTexture.h RectangleTexture.h) - set(Magnum_SRCS ${Magnum_SRCS} $) + set(Magnum_SRCS ${Magnum_SRCS} + BufferTexture.cpp + $) endif() -# Not-ES2 headers +# Non-ES2 stuff if(NOT TARGET_GLES2) set(Magnum_HEADERS ${Magnum_HEADERS} BufferImage.h TextureArray.h) + set(Magnum_SRCS ${Magnum_SRCS} + BufferImage.cpp) endif() # Files shared between main library and math unit test library From f9e49283e6a6971777a0a78f1841e7534b28c098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 01:55:38 +0200 Subject: [PATCH 13/46] Fix includes. Vector3 was used but not included. --- src/Magnum/CubeMapTextureArray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 88ae9e584..ddf173da8 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -33,7 +33,7 @@ #include "Magnum/AbstractTexture.h" #include "Magnum/Array.h" -#include "Magnum/Math/Vector2.h" +#include "Magnum/Math/Vector3.h" #ifndef MAGNUM_TARGET_GLES namespace Magnum { From 2cbcdeaeb45b0d62e31a708f71fc2179f7da444e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 02:14:04 +0200 Subject: [PATCH 14/46] Queries for max supported texture size. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 4 +- src/Magnum/AbstractTexture.h | 1 - src/Magnum/BufferTexture.cpp | 12 +++ src/Magnum/BufferTexture.h | 20 ++++- src/Magnum/CMakeLists.txt | 9 ++- src/Magnum/CubeMapTexture.cpp | 36 +++++++++ src/Magnum/CubeMapTexture.h | 13 +++- src/Magnum/CubeMapTextureArray.cpp | 45 ++++++++++++ src/Magnum/CubeMapTextureArray.h | 13 ++++ src/Magnum/Implementation/TextureState.h | 8 ++ src/Magnum/Implementation/maxTextureSize.cpp | 77 ++++++++++++++++++++ src/Magnum/Implementation/maxTextureSize.h | 39 ++++++++++ src/Magnum/MultisampleTexture.cpp | 51 +++++++++++++ src/Magnum/MultisampleTexture.h | 19 ++++- src/Magnum/RectangleTexture.cpp | 50 +++++++++++++ src/Magnum/RectangleTexture.h | 22 ++++-- src/Magnum/Texture.cpp | 54 ++++++++++++++ src/Magnum/Texture.h | 28 +++++-- src/Magnum/TextureArray.cpp | 58 +++++++++++++++ src/Magnum/TextureArray.h | 15 +++- 21 files changed, 553 insertions(+), 23 deletions(-) create mode 100644 src/Magnum/CubeMapTexture.cpp create mode 100644 src/Magnum/CubeMapTextureArray.cpp create mode 100644 src/Magnum/Implementation/maxTextureSize.cpp create mode 100644 src/Magnum/Implementation/maxTextureSize.h create mode 100644 src/Magnum/MultisampleTexture.cpp create mode 100644 src/Magnum/RectangleTexture.cpp create mode 100644 src/Magnum/Texture.cpp create mode 100644 src/Magnum/TextureArray.cpp diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 5ebc5dd65..dcec0aff7 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -299,7 +299,7 @@ OpenGL function | Matching API `GL_MAX_*_UNIFORM_BLOCKS`, \n @def_gl{MAX_COMBINED_UNIFORM_BLOCKS} | @ref Shader::maxUniformBlocks(), \n @ref Shader::maxCombinedUniformBlocks() `GL_MAX_*_UNIFORM_COMPONENTS`, \n @def_gl{MAX_VERTEX_UNIFORM_VECTORS}, \n @def_gl{MAX_FRAGMENT_UNIFORM_VECTORS} | @ref Shader::maxUniformComponents() `GL_MAX_COMBINED_*_UNIFORM_COMPONENTS` | @ref Shader::maxCombinedUniformComponents() -@def_gl{MAX_3D_TEXTURE_SIZE}, \n @def_gl{MAX_ARRAY_TEXTURE_LAYERS}, \n @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE}, \n @def_gl{MAX_RECTANGLE_TEXTURE_SIZE}, \n @def_gl{MAX_TEXTURE_SIZE} | | +@def_gl{MAX_3D_TEXTURE_SIZE}, \n @def_gl{MAX_ARRAY_TEXTURE_LAYERS}, \n @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE}, \n @def_gl{MAX_RECTANGLE_TEXTURE_SIZE}, \n @def_gl{MAX_TEXTURE_SIZE} | @ref Texture::maxSize(), \n @ref TextureArray::maxSize(), \n @ref CubeMapTexture::maxSize(), \n @ref CubeMapTextureArray::maxSize(), \n @ref RectangleTexture::maxSize(), \n @ref BufferTexture::maxSize(), \n @ref MultisampleTexture::maxSize() @def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE} | @ref AbstractShaderProgram::maxAtomicCounterBufferSize() @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS} | @ref Buffer::maxAtomicCounterBindings() @def_gl{MAX_COLOR_ATTACHMENTS} | @ref Framebuffer::maxColorAttachments() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index c5ca18e64..a8498f323 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -81,9 +81,9 @@ following: %Extension | Status -------------------------------------------- | ------ -@extension{ARB,texture_rectangle} | missing limit query +@extension{ARB,texture_rectangle} | done @extension{ARB,draw_instanced} | | -@extension{ARB,texture_buffer_object} | missing limit query +@extension{ARB,texture_buffer_object} | done @extension{ARB,uniform_buffer_object} | | @extension{ARB,copy_buffer} | done @extension{EXT,texture_snorm} | done diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index f6797bb02..64d75591b 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -104,7 +104,6 @@ functions do nothing. @todo Move constructor/assignment - how to avoid creation of empty texture and then deleting it immediately? @todo ES2 - proper support for pixel unpack buffer when extension is in headers -@todo `GL_MAX_3D_TEXTURE_SIZE`, `GL_MAX_ARRAY_TEXTURE_LAYERS`, `GL_MAX_CUBE_MAP_TEXTURE_SIZE`, `GL_MAX_RECTANGLE_TEXTURE_SIZE`, `GL_MAX_TEXTURE_SIZE`, `GL_MAX_TEXTURE_BUFFER_SIZE` enable them only where it makes sense? @todo `GL_NUM_COMPRESSED_TEXTURE_FORMATS` when compressed textures are implemented @todo `GL_MAX_SAMPLE_MASK_WORDS` when @extension{ARB,texture_multisample} is done @todo Query for immutable levels (@extension{ARB,ES3_compatibility}) diff --git a/src/Magnum/BufferTexture.cpp b/src/Magnum/BufferTexture.cpp index 1c91f129e..84b5ad87b 100644 --- a/src/Magnum/BufferTexture.cpp +++ b/src/Magnum/BufferTexture.cpp @@ -35,6 +35,18 @@ namespace Magnum { +Int BufferTexture::maxSize() { + if(!Context::current()->isExtensionSupported()) + return 0; + + GLint& value = Context::current()->state().texture->maxBufferSize; + + if(value == 0) + glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &value); + + return value; +} + Int BufferTexture::offsetAlignment() { if(!Context::current()->isExtensionSupported()) return 0; diff --git a/src/Magnum/BufferTexture.h b/src/Magnum/BufferTexture.h index a91d85879..987695d98 100644 --- a/src/Magnum/BufferTexture.h +++ b/src/Magnum/BufferTexture.h @@ -202,6 +202,16 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture { friend struct Implementation::TextureState; public: + /** + * @brief Max supported buffer texture size + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If @extension{ARB,texture_buffer_object} (part of + * OpenGL 3.1) is not available, returns `0`. + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_BUFFER_SIZE} + */ + static Int maxSize(); + /** * @brief Minimum required alignment for texture buffer offsets * @@ -229,8 +239,9 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture { * Binds given buffer to this texture. The buffer itself can be then * filled with data of proper format at any time using @ref Buffer "Buffer"'s * own data setting functions. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBuffer} - * or @fn_gl_extension{TextureBuffer,EXT,direct_state_access} + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexBuffer} or + * @fn_gl_extension{TextureBuffer,EXT,direct_state_access} */ BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer); @@ -245,9 +256,10 @@ class MAGNUM_EXPORT BufferTexture: public AbstractTexture { * Binds range of given buffer to this texture. The buffer itself can * be then filled with data of proper format at any time using @ref Buffer "Buffer"'s * own data setting functions. + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexBufferRange} or + * @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} * @requires_gl43 %Extension @extension{ARB,texture_buffer_range} - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexBufferRange} - * or @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} */ BufferTexture& setBuffer(BufferTextureFormat internalFormat, Buffer& buffer, GLintptr offset, GLsizeiptr size); diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index a9ef0bf8c..765addc03 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -35,6 +35,7 @@ set(Magnum_SRCS AbstractShaderProgram.cpp Buffer.cpp ColorFormat.cpp + CubeMapTexture.cpp Context.cpp DebugMessage.cpp DefaultFramebuffer.cpp @@ -49,6 +50,7 @@ set(Magnum_SRCS Resource.cpp Sampler.cpp Shader.cpp + Texture.cpp Timeline.cpp Version.cpp @@ -60,6 +62,7 @@ set(Magnum_SRCS Implementation/ShaderProgramState.cpp Implementation/State.cpp Implementation/TextureState.cpp + Implementation/maxTextureSize.cpp Implementation/setupDriverWorkarounds.cpp Trade/AbstractImageConverter.cpp @@ -130,6 +133,9 @@ if(NOT TARGET_GLES) RectangleTexture.h) set(Magnum_SRCS ${Magnum_SRCS} BufferTexture.cpp + CubeMapTextureArray.cpp + MultisampleTexture.cpp + RectangleTexture.cpp $) endif() @@ -139,7 +145,8 @@ if(NOT TARGET_GLES2) BufferImage.h TextureArray.h) set(Magnum_SRCS ${Magnum_SRCS} - BufferImage.cpp) + BufferImage.cpp + TextureArray.cpp) endif() # Files shared between main library and math unit test library diff --git a/src/Magnum/CubeMapTexture.cpp b/src/Magnum/CubeMapTexture.cpp new file mode 100644 index 000000000..f53d297d4 --- /dev/null +++ b/src/Magnum/CubeMapTexture.cpp @@ -0,0 +1,36 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CubeMapTexture.h" + +#include "Implementation/maxTextureSize.h" + +namespace Magnum { + +Vector2i CubeMapTexture::maxSize() { + return Vector2i{Implementation::maxCubeMapTextureSideSize()}; +} + +} diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index b3b8f4574..b784d5104 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -79,7 +79,7 @@ which intersects one of the six sides of the cube map. See @ref Texture, @ref TextureArray, @ref RectangleTexture, @ref BufferTexture, @ref MultisampleTexture */ -class CubeMapTexture: public AbstractTexture { +class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { public: /** @brief Cube map coordinate */ enum class Coordinate: GLenum { @@ -91,6 +91,15 @@ class CubeMapTexture: public AbstractTexture { NegativeZ = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z /**< -Z cube side */ }; + /** + * @brief Max supported size of one side of cube map texture + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. + * @see @fn_gl{Get} with @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE} + */ + static Vector2i maxSize(); + /** * @brief Constructor * @@ -205,6 +214,7 @@ class CubeMapTexture: public AbstractTexture { * @brief Set storage * * See @ref Texture::setStorage() for more information. + * @see @ref maxSize() */ CubeMapTexture& setStorage(Int levels, TextureFormat internalFormat, const Vector2i& size) { DataHelper<2>::setStorage(*this, _target, levels, internalFormat, size); @@ -251,6 +261,7 @@ class CubeMapTexture: public AbstractTexture { * @return Reference to self (for method chaining) * * See @ref Texture::setImage() for more information. + * @see @ref maxSize() */ CubeMapTexture& setImage(Coordinate coordinate, Int level, TextureFormat internalFormat, const ImageReference2D& image) { DataHelper<2>::setImage(*this, GLenum(coordinate), level, internalFormat, image); diff --git a/src/Magnum/CubeMapTextureArray.cpp b/src/Magnum/CubeMapTextureArray.cpp new file mode 100644 index 000000000..6a0866716 --- /dev/null +++ b/src/Magnum/CubeMapTextureArray.cpp @@ -0,0 +1,45 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "CubeMapTextureArray.h" + +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +#include "Implementation/maxTextureSize.h" + +namespace Magnum { + +Vector3i CubeMapTextureArray::maxSize() { + if(!Context::current()->isExtensionSupported()) + return {}; + + return Vector3i{Vector2i{Implementation::maxCubeMapTextureSideSize()}, + Implementation::maxTextureArrayLayers()}; +} + +} +#endif diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index ddf173da8..f30f5b537 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -92,6 +92,17 @@ class CubeMapTextureArray: public AbstractTexture { */ explicit CubeMapTextureArray(): AbstractTexture(GL_TEXTURE_CUBE_MAP_ARRAY) {} + /** + * @brief Max supported size of one side of cube map texture array + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If @extension{ARB,texture_cube_map_array} (part of + * OpenGL 4.0) is not available, returns zero vector. + * @see @fn_gl{Get} with @def_gl{MAX_CUBE_MAP_TEXTURE_SIZE} and + * @def_gl{MAX_ARRAY_TEXTURE_LAYERS} + */ + static Vector3i maxSize(); + /** * @brief Set base mip level * @return Reference to self (for method chaining) @@ -230,6 +241,7 @@ class CubeMapTextureArray: public AbstractTexture { * * Z coordinate of @p size must be multiple of 6. See * @ref Texture::setStorage() for more information. + * @see @ref maxSize() */ CubeMapTextureArray& setStorage(Int levels, TextureFormat internalFormat, const Vector3i& size) { DataHelper<3>::setStorage(*this, _target, levels, internalFormat, size); @@ -274,6 +286,7 @@ class CubeMapTextureArray: public AbstractTexture { * images are in order of (+X, -X, +Y, -Y, +Z, -Z). * * See @ref Texture::setImage() for more information. + * @see @ref maxSize() */ CubeMapTextureArray& setImage(Int level, TextureFormat internalFormat, const ImageReference3D& image) { DataHelper<3>::setImage(*this, GL_TEXTURE_CUBE_MAP_ARRAY, level, internalFormat, image); diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 28b5335d5..9e44a68aa 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -74,6 +74,14 @@ struct TextureState { void(BufferTexture::*setBufferRangeImplementation)(BufferTextureFormat, Buffer&, GLintptr, GLsizeiptr); #endif + GLint maxSize, + max3DSize, + maxArrayLayers, + maxCubeMapSize; + #ifndef MAGNUM_TARGET_GLES + GLint maxRectangleSize, + maxBufferSize; + #endif GLint maxTextureUnits; GLfloat maxLodBias, maxMaxAnisotropy; diff --git a/src/Magnum/Implementation/maxTextureSize.cpp b/src/Magnum/Implementation/maxTextureSize.cpp new file mode 100644 index 000000000..e43b78c70 --- /dev/null +++ b/src/Magnum/Implementation/maxTextureSize.cpp @@ -0,0 +1,77 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "maxTextureSize.h" + +#include "Magnum/Context.h" + +#include "State.h" +#include "TextureState.h" + +namespace Magnum { namespace Implementation { + +GLint maxTextureSideSize() { + GLint& value = Context::current()->state().texture->maxSize; + + if(value == 0) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); + + return value; +} + +GLint max3DTextureDepth() { + GLint& value = Context::current()->state().texture->max3DSize; + + if(value == 0) + #ifndef MAGNUM_TARGET_GLES2 + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &value); + #else + glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_OES, &value); + #endif + + return value; +} + +#ifndef MAGNUM_TARGET_GLES2 +GLint maxTextureArrayLayers() { + GLint& value = Context::current()->state().texture->maxArrayLayers; + + if(value == 0) + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &value); + + return value; +} +#endif + +GLint maxCubeMapTextureSideSize() { + GLint& value = Context::current()->state().texture->maxCubeMapSize; + + if(value == 0) + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &value); + + return value; +} + +}} diff --git a/src/Magnum/Implementation/maxTextureSize.h b/src/Magnum/Implementation/maxTextureSize.h new file mode 100644 index 000000000..b269c1463 --- /dev/null +++ b/src/Magnum/Implementation/maxTextureSize.h @@ -0,0 +1,39 @@ +#ifndef Magnum_Implementation_maxTextureSize_h +#define Magnum_Implementation_maxTextureSize_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Magnum/OpenGL.h" + +namespace Magnum { namespace Implementation { + +GLint maxTextureSideSize(); +GLint max3DTextureDepth(); +GLint maxTextureArrayLayers(); +GLint maxCubeMapTextureSideSize(); + +}} + +#endif diff --git a/src/Magnum/MultisampleTexture.cpp b/src/Magnum/MultisampleTexture.cpp new file mode 100644 index 000000000..7705168ce --- /dev/null +++ b/src/Magnum/MultisampleTexture.cpp @@ -0,0 +1,51 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "MultisampleTexture.h" + +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +#include "Implementation/maxTextureSize.h" + +namespace Magnum { namespace Implementation { + +template<> Vector2i MAGNUM_EXPORT maxMultisampleTextureSize<2>() { + if(!Context::current()->isExtensionSupported()) + return {}; + + return Vector2i{Implementation::maxTextureSideSize()}; +} + +template<> Vector3i MAGNUM_EXPORT maxMultisampleTextureSize<3>() { + if(!Context::current()->isExtensionSupported()) + return {}; + + return {Vector2i{Implementation::maxTextureSideSize()}, Implementation::max3DTextureDepth()}; +} + +}} +#endif diff --git a/src/Magnum/MultisampleTexture.h b/src/Magnum/MultisampleTexture.h index 1d3a9549f..882aaff60 100644 --- a/src/Magnum/MultisampleTexture.h +++ b/src/Magnum/MultisampleTexture.h @@ -42,6 +42,10 @@ namespace Implementation { template constexpr GLenum multisampleTextureTarget(); template<> inline constexpr GLenum multisampleTextureTarget<2>() { return GL_TEXTURE_2D_MULTISAMPLE; } template<> inline constexpr GLenum multisampleTextureTarget<3>() { return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; } + + template typename DimensionTraits::VectorType maxMultisampleTextureSize(); + template<> Vector2i maxMultisampleTextureSize<2>(); + template<> Vector3i maxMultisampleTextureSize<3>(); } /** @@ -85,6 +89,19 @@ template class MultisampleTexture: public AbstractTextur public: static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ + /** + * @brief Max supported multisample texture size + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{ARB,texture_multisample} (part + * of OpenGL 3.2) is not available, returns zero vector. + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE} and + * @def_gl{MAX_3D_TEXTURE_SIZE} + */ + static typename DimensionTraits::VectorType maxSize() { + return Implementation::maxMultisampleTextureSize(); + } + /** * @brief Constructor * @@ -127,7 +144,7 @@ template class MultisampleTexture: public AbstractTextur * @extension{ARB,texture_storage} functionality (which unfortunately * doesn't have any DSA alternative, so the texture must be bound * to some texture unit before). - * @see @ref maxColorSamples(), @ref maxDepthSamples(), + * @see @ref maxSize(), @ref maxColorSamples(), @ref maxDepthSamples(), * @ref maxIntegerSamples(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} * and @fn_gl{TexStorage2DMultisample}/@fn_gl{TexStorage3DMultisample} * or @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}/ diff --git a/src/Magnum/RectangleTexture.cpp b/src/Magnum/RectangleTexture.cpp new file mode 100644 index 000000000..8fcf6ec00 --- /dev/null +++ b/src/Magnum/RectangleTexture.cpp @@ -0,0 +1,50 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "RectangleTexture.h" + +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +#include "Implementation/State.h" +#include "Implementation/TextureState.h" + +namespace Magnum { + +Vector2i RectangleTexture::maxSize() { + if(!Context::current()->isExtensionSupported()) + return {}; + + GLint& value = Context::current()->state().texture->maxRectangleSize; + + if(value == 0) + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &value); + + return Vector2i{value}; +} + +} +#endif diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 452fdfe75..15bcbab2c 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -68,8 +68,18 @@ documentation for more information about usage in shaders. @requires_gl31 %Extension @extension{ARB,texture_rectangle} @requires_gl Rectangle textures are not available in OpenGL ES. */ -class RectangleTexture: public AbstractTexture { +class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { public: + /** + * @brief Max supported rectangle texture size + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If @extension{ARB,texture_rectangle} (part of + * OpenGL 3.1) is not available, returns zero vector. + * @see @fn_gl{Get} with @def_gl{MAX_RECTANGLE_TEXTURE_SIZE} + */ + static Vector2i maxSize(); + /** * @brief Constructor * @@ -205,8 +215,9 @@ class RectangleTexture: public AbstractTexture { * @extension{ARB,texture_storage} (part of OpenGL 4.2), OpenGL ES 3.0 * or @es_extension{EXT,texture_storage} in OpenGL ES 2.0 is not * available, the feature is emulated with @ref setImage() call. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexStorage2D} - * or @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexStorage2D} or + * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, * eventually @fn_gl{TexImage2D} or * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}. */ @@ -263,8 +274,9 @@ class RectangleTexture: public AbstractTexture { * * If @extension{EXT,direct_state_access} is not available, the * texture is bound to some texture unit before the operation. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexImage2D} - * or @fn_gl_extension{TextureImage2D,EXT,direct_state_access} + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexImage2D} or + * @fn_gl_extension{TextureImage2D,EXT,direct_state_access} */ RectangleTexture& setImage(TextureFormat internalFormat, const ImageReference2D& image) { DataHelper<2>::setImage(*this, _target, 0, internalFormat, image); diff --git a/src/Magnum/Texture.cpp b/src/Magnum/Texture.cpp new file mode 100644 index 000000000..a7566f218 --- /dev/null +++ b/src/Magnum/Texture.cpp @@ -0,0 +1,54 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Texture.h" + +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +#include "Implementation/maxTextureSize.h" +#include "Implementation/State.h" +#include "Implementation/TextureState.h" + +namespace Magnum { namespace Implementation { + +template typename DimensionTraits::VectorType maxTextureSize() { + return typename DimensionTraits::VectorType{Implementation::maxTextureSideSize()}; +} + +#ifndef MAGNUM_TARGET_GLES +template MAGNUM_EXPORT Math::Vector<1, Int> maxTextureSize<1>(); +#endif +template MAGNUM_EXPORT Vector2i maxTextureSize<2>(); + +template<> MAGNUM_EXPORT Vector3i maxTextureSize<3>() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + return {}; + #endif + return {Vector2i(Implementation::maxTextureSideSize()), Implementation::max3DTextureDepth()}; +} + +}} diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 85ad55cb6..3badc846c 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -51,6 +51,9 @@ namespace Implementation { return GL_TEXTURE_3D_OES; #endif } + + template typename DimensionTraits::VectorType maxTextureSize(); + template<> Vector3i maxTextureSize<3>(); } /** @@ -139,6 +142,20 @@ template class Texture: public AbstractTexture { #endif #endif + /** + * @brief Max supported texture size + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. For 3D textures in OpenGL ES 2.0, if + * @es_extension{OES,texture_3D} extension is not available, returns + * zero vector. + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE}, + * @def_gl{MAX_3D_TEXTURE_SIZE} + */ + static typename DimensionTraits::VectorType maxSize() { + return Implementation::maxTextureSize(); + } + /** * @brief Constructor * @@ -466,13 +483,14 @@ template class Texture: public AbstractTexture { * calls. * @todo allow the user to specify ColorType explicitly to avoid * issues in WebGL (see setSubImage()) - * @see @ref setMaxLevel(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} - * and @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} + * @see @ref maxSize(), @ref setMaxLevel(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and + * @fn_gl{TexStorage1D}/@fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} * or @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, - * eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or - * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ + * eventually @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} + * or @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} */ @@ -537,7 +555,7 @@ template class Texture: public AbstractTexture { * * If @extension{EXT,direct_state_access} is not available, the * texture is bound to some texture unit before the operation. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexImage1D}/@fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl_extension{TextureImage1D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ diff --git a/src/Magnum/TextureArray.cpp b/src/Magnum/TextureArray.cpp new file mode 100644 index 000000000..fafd9d47b --- /dev/null +++ b/src/Magnum/TextureArray.cpp @@ -0,0 +1,58 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "TextureArray.h" + +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/Context.h" +#include "Magnum/Extensions.h" + +#include "Implementation/maxTextureSize.h" + +namespace Magnum { + +namespace { + template struct VectorOrScalar; + template<> struct VectorOrScalar<1> { typedef Int Type; }; + template<> struct VectorOrScalar<2> { typedef Vector2i Type; }; +} + +template typename DimensionTraits::VectorType TextureArray::maxSize() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + return {}; + #endif + + return {typename VectorOrScalar::Type{Implementation::maxTextureSideSize()}, + Implementation::maxTextureArrayLayers()}; +} + +#ifndef MAGNUM_TARGET_GLES +template class MAGNUM_EXPORT TextureArray<1>; +#endif +template class MAGNUM_EXPORT TextureArray<2>; + +} +#endif diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index ce8413b60..8816425d9 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -95,6 +95,17 @@ template class TextureArray: public AbstractTexture { public: static const UnsignedInt Dimensions = dimensions; /**< @brief %Texture dimension count */ + /** + * @brief Max supported texture array size + * + * The result is cached, repeated queries don't result in repeated + * OpenGL calls. If extension @extension{EXT,texture_array} (part of + * OpenGL 3.0) is not available, returns zero vector. + * @see @fn_gl{Get} with @def_gl{MAX_TEXTURE_SIZE} and + * @def_gl{MAX_ARRAY_TEXTURE_LAYERS} + */ + static typename DimensionTraits::VectorType maxSize(); + /** * @brief Constructor * @@ -217,7 +228,7 @@ template class TextureArray: public AbstractTexture { * @extension{ARB,texture_storage} (part of OpenGL 4.2) or OpenGL ES * 3.0 is not available, the feature is emulated with sequence of * @ref setImage() calls. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexStorage2D}/@fn_gl{TexStorage3D} or * @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureStorage3D,EXT,direct_state_access}, @@ -256,7 +267,7 @@ template class TextureArray: public AbstractTexture { * * If @extension{EXT,direct_state_access} is not available, the * texture is bound to some texture unit before the operation. - * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @see @ref maxSize(), @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and * @fn_gl{TexImage2D}/@fn_gl{TexImage3D} or * @fn_gl_extension{TextureImage2D,EXT,direct_state_access}/ * @fn_gl_extension{TextureImage3D,EXT,direct_state_access} From f16a607a6f965cce770ea3b0544de4c9cfd27f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 02:15:02 +0200 Subject: [PATCH 15/46] Platform: display max texture size in magnum-info. --- src/Magnum/Platform/magnum-info.cpp | 56 +++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 8c050ab05..5ec2ff5bb 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -40,8 +40,16 @@ #include "Magnum/Extensions.h" #include "Magnum/Framebuffer.h" #include "Magnum/Mesh.h" +#ifndef MAGNUM_TARGET_GLES +#include "Magnum/MultisampleTexture.h" +#include "Magnum/RectangleTexture.h" +#endif #include "Magnum/Renderbuffer.h" #include "Magnum/Shader.h" +#include "Magnum/Texture.h" +#ifndef MAGNUM_TARGET_GLES2 +#include "Magnum/TextureArray.h" +#endif #ifndef CORRADE_TARGET_NACL #include "Magnum/Platform/WindowlessGlxApplication.h" #else @@ -252,6 +260,13 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #ifndef MAGNUM_TARGET_GLES2 _l(AbstractTexture::maxLodBias()) #endif + #ifndef MAGNUM_TARGET_GLES + _l(Texture1D::maxSize()) + #endif + _l(Texture2D::maxSize()) + #ifndef MAGNUM_TARGET_GLES2 + _l(Texture3D::maxSize()) + #endif #ifndef MAGNUM_TARGET_GLES if(c->isExtensionSupported()) { @@ -337,11 +352,30 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(Shader::maxTessellationEvaluationOutputComponents()) } + if(c->isExtensionSupported()) { + _h(ARB::texture_buffer_object) + + _l(BufferTexture::maxSize()) + } + if(c->isExtensionSupported()) { _h(ARB::texture_buffer_range) _l(BufferTexture::offsetAlignment()) } + + if(c->isExtensionSupported()) { + _h(ARB::texture_multisample) + + _l(MultisampleTexture2D::maxSize()) + _l(MultisampleTexture2DArray::maxSize()) + } + + if(c->isExtensionSupported()) { + _h(ARB::texture_rectangle) + + _l(RectangleTexture::maxSize()) + } #endif /** @todo Somehow sort the following into previous list for ES3 */ @@ -387,6 +421,20 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(AbstractShaderProgram::minTexelOffset()) _l(AbstractShaderProgram::maxTexelOffset()) } + + #ifndef MAGNUM_TARGET_GLES + if(c->isExtensionSupported()) + #endif + { + #ifndef MAGNUM_TARGET_GLES + _h(EXT::texture_array) + #endif + + #ifndef MAGNUM_TARGET_GLES + _l(Texture1DArray::maxSize()) + #endif + _l(Texture2DArray::maxSize()) + } #endif if(c->isExtensionSupported()) { @@ -403,6 +451,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(DebugMessage::maxMessageLength()) } + #ifdef MAGNUM_TARGET_GLES2 + if(c->isExtensionSupported()) { + _h(OES::texture_3D) + + _l(Texture3D::maxSize()) + } + #endif + #undef _l #undef _h } From bbd1d94e73fbeddb5356fdc05c6258724a54f51d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 02:20:50 +0200 Subject: [PATCH 16/46] Platform: nicer vector value display in magnum-info. --- src/Magnum/Platform/magnum-info.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Magnum/Platform/magnum-info.cpp b/src/Magnum/Platform/magnum-info.cpp index 5ec2ff5bb..3930c0eb9 100644 --- a/src/Magnum/Platform/magnum-info.cpp +++ b/src/Magnum/Platform/magnum-info.cpp @@ -218,9 +218,10 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat /* Limits and implementation-defined values */ #define _h(val) Debug() << "\n " << Extensions::GL::val::string() + std::string(":"); #define _l(val) Debug() << " " << #val << (sizeof(#val) > 64 ? "\n" + std::string(68, ' ') : std::string(64 - sizeof(#val), ' ')) << val; + #define _lvec(val) Debug() << " " << #val << (sizeof(#val) > 48 ? "\n" + std::string(52, ' ') : std::string(48 - sizeof(#val), ' ')) << val; Debug() << "Limits and implementation-defined values:"; - _l(AbstractFramebuffer::maxViewportSize()) + _lvec(AbstractFramebuffer::maxViewportSize()) _l(AbstractFramebuffer::maxDrawBuffers()) _l(Framebuffer::maxColorAttachments()) #ifndef MAGNUM_TARGET_GLES2 @@ -261,11 +262,11 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat _l(AbstractTexture::maxLodBias()) #endif #ifndef MAGNUM_TARGET_GLES - _l(Texture1D::maxSize()) + _lvec(Texture1D::maxSize()) #endif - _l(Texture2D::maxSize()) + _lvec(Texture2D::maxSize()) #ifndef MAGNUM_TARGET_GLES2 - _l(Texture3D::maxSize()) + _lvec(Texture3D::maxSize()) #endif #ifndef MAGNUM_TARGET_GLES @@ -367,14 +368,14 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat if(c->isExtensionSupported()) { _h(ARB::texture_multisample) - _l(MultisampleTexture2D::maxSize()) - _l(MultisampleTexture2DArray::maxSize()) + _lvec(MultisampleTexture2D::maxSize()) + _lvec(MultisampleTexture2DArray::maxSize()) } if(c->isExtensionSupported()) { _h(ARB::texture_rectangle) - _l(RectangleTexture::maxSize()) + _lvec(RectangleTexture::maxSize()) } #endif @@ -431,9 +432,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat #endif #ifndef MAGNUM_TARGET_GLES - _l(Texture1DArray::maxSize()) + _lvec(Texture1DArray::maxSize()) #endif - _l(Texture2DArray::maxSize()) + _lvec(Texture2DArray::maxSize()) } #endif @@ -455,7 +456,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat if(c->isExtensionSupported()) { _h(OES::texture_3D) - _l(Texture3D::maxSize()) + _lvec(Texture3D::maxSize()) } #endif From 3e40bdd443821b0f8dc3eca7cc53df5a8c905b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 12:07:07 +0200 Subject: [PATCH 17/46] Doc++ Also remove redundant preprocessor branches. --- src/Magnum/CubeMapTextureArray.h | 25 ++++++++++++++----------- src/Magnum/RectangleTexture.h | 15 +++++++++------ src/Magnum/Texture.h | 2 ++ src/Magnum/TextureArray.h | 8 +++++++- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index f30f5b537..771413391 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -104,7 +104,7 @@ class CubeMapTextureArray: public AbstractTexture { static Vector3i maxSize(); /** - * @brief Set base mip level + * @copybrief Texture::setBaseLevel() * @return Reference to self (for method chaining) * * See @ref Texture::setBaseLevel() for more information. @@ -115,7 +115,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set max mip level + * @copybrief Texture::setMaxLevel() * @return Reference to self (for method chaining) * * See @ref Texture::setMaxLevel() for more information. @@ -138,7 +138,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set minimum level-of-detail parameter + * @copybrief Texture::setMinLod() * @return Reference to self (for method chaining) * * See @ref Texture::setMinLod() for more information. @@ -149,7 +149,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set maximum level-of-detail parameter + * @copybrief Texture::setMaxLod() * @return Reference to self (for method chaining) * * See @ref Texture::setMaxLod() for more information. @@ -160,7 +160,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set level-of-detail bias + * @copybrief Texture::setLodBias() * @return Reference to self (for method chaining) * * See @ref Texture::setLodBias() for more information. @@ -177,7 +177,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set border color + * @copybrief Texture::setBorderColor(const Color4&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Color4&) for more @@ -189,7 +189,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set border color for integer texture + * @copybrief Texture::setBorderColor(const Vector4ui&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Vector4ui&) for more @@ -201,7 +201,7 @@ class CubeMapTextureArray: public AbstractTexture { } /** - * @brief Set border color for integer texture + * @copybrief Texture::setBorderColor(const Vector4ui&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Vector4i&) for more @@ -218,13 +218,16 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } - #ifndef MAGNUM_TARGET_GLES - /** @copydoc Texture::setDepthStencilMode() */ + /** + * @copybrief Texture::setDepthStencilMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setDepthStencilMode() for more information. + */ CubeMapTextureArray& setDepthStencilMode(Sampler::DepthStencilMode mode) { AbstractTexture::setDepthStencilMode(mode); return *this; } - #endif /** * @brief %Image size in given mip level diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 15bcbab2c..3f8ac4c49 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -149,7 +149,7 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { } /** - * @brief Set border color + * @copybrief Texture::setBorderColor(const Color4&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Color4&) for more @@ -161,7 +161,7 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { } /** - * @brief Set border color for integer texture + * @copybrief Texture::setBorderColor(const Vector4ui&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Vector4ui&) for more @@ -173,7 +173,7 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { } /** - * @brief Set border color for integer texture + * @copybrief Texture::setBorderColor(const Vector4ui&) * @return Reference to self (for method chaining) * * See @ref Texture::setBorderColor(const Vector4i&) for more @@ -190,13 +190,16 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { return *this; } - #ifndef MAGNUM_TARGET_GLES - /** @copydoc Texture::setDepthStencilMode() */ + /** + * @copybrief Texture::setDepthStencilMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setDepthStencilMode() for more information. + */ RectangleTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) { AbstractTexture::setDepthStencilMode(mode); return *this; } - #endif /** * @brief Set storage diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 3badc846c..af9d725e2 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -445,11 +445,13 @@ template class Texture: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES /** * @brief Set depth/stencil texture mode + * @return Reference to self (for method chaining) * * Selects which component of packed depth/stencil texture is used for * texturing. If @extension{EXT,direct_state_access} is not available, * the texture is bound to some texture unit before the operation. * Initial value is @ref Sampler::DepthStencilMode::DepthComponent. + * @note Depth textures can be only 1D or 2D. * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and @fn_gl{TexParameter} * or @fn_gl_extension{TextureParameter,EXT,direct_state_access} * with @def_gl{DEPTH_STENCIL_TEXTURE_MODE} diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index 8816425d9..b1891d137 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -90,6 +90,7 @@ documentation for more information about usage in shaders. @requires_gl30 %Extension @extension{EXT,texture_array} @requires_gles30 %Array textures are not available in OpenGL ES 2.0. @requires_gl 1D array textures are not available in OpenGL ES, only 2D ones. +@todo Fix this when @es_extension{NV,texture_array} is in ES2 extension headers */ template class TextureArray: public AbstractTexture { public: @@ -196,7 +197,12 @@ template class TextureArray: public AbstractTexture { } #ifndef MAGNUM_TARGET_GLES - /** @copydoc Texture::setDepthStencilMode() */ + /** + * @copybrief Texture::setDepthStencilMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setDepthStencilMode() for more information. + */ TextureArray& setDepthStencilMode(Sampler::DepthStencilMode mode) { AbstractTexture::setDepthStencilMode(mode); return *this; From ef897de79e780aec271a0ab01422f3a261b2d2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 12:36:39 +0200 Subject: [PATCH 18/46] Implemented depth texture compare mode and function. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 3 + src/Magnum/AbstractTexture.cpp | 20 +++++ src/Magnum/AbstractTexture.h | 2 + src/Magnum/Context.cpp | 3 + src/Magnum/CubeMapTexture.h | 26 +++++++ src/Magnum/CubeMapTextureArray.h | 22 ++++++ src/Magnum/Extensions.h | 3 + src/Magnum/RectangleTexture.h | 22 ++++++ src/Magnum/Sampler.cpp | 28 +++++++ src/Magnum/Sampler.h | 76 +++++++++++++++++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 4 +- src/Magnum/Test/CubeMapTextureGLTest.cpp | 21 ++++- src/Magnum/Test/RectangleTextureGLTest.cpp | 4 +- src/Magnum/Test/SamplerTest.cpp | 18 +++++ src/Magnum/Test/TextureArrayGLTest.cpp | 24 +++++- src/Magnum/Test/TextureGLTest.cpp | 21 ++++- src/Magnum/Texture.h | 40 ++++++++++ src/Magnum/TextureArray.h | 26 +++++++ 19 files changed, 357 insertions(+), 8 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index dcec0aff7..cea87b979 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -234,7 +234,7 @@ OpenGL function | Matching API @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index a8498f323..80a54eadb 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -252,6 +252,7 @@ supported. @es_extension2{EXT,blend_minmax,blend_minmax} | done @es_extension{EXT,shader_texture_lod} | done (shading language only) @es_extension{EXT,occlusion_query_boolean} | done +@es_extension{EXT,shadow_samplers} | done @es_extension{EXT,texture_rg} | done @es_extension{EXT,texture_storage} | done @es_extension{EXT,map_buffer_range} | done @@ -260,6 +261,8 @@ supported. @es_extension{NV,read_buffer} | done @es_extension{NV,framebuffer_blit} | done @es_extension{NV,framebuffer_multisample} | done +@es_extension{NV,shadow_samplers_array} | done (shading language only) +@es_extension{NV,shadow_samplers_cube} | done (shading language only) @es_extension{OES,depth24} | done @es_extension{OES,element_index_uint} | done @es_extension{OES,rgb8_rgba8} | done (desktop-compatible subset) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 1fb3143d4..34a30861f 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -286,6 +286,26 @@ void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); } +void AbstractTexture::setCompareMode(const Sampler::CompareMode mode) { + (this->*Context::current()->state().texture->parameteriImplementation)( + #ifndef MAGNUM_TARGET_GLES2 + GL_TEXTURE_COMPARE_MODE + #else + GL_TEXTURE_COMPARE_MODE_EXT + #endif + , GLenum(mode)); +} + +void AbstractTexture::setCompareFunction(const Sampler::CompareFunction function) { + (this->*Context::current()->state().texture->parameteriImplementation)( + #ifndef MAGNUM_TARGET_GLES2 + GL_TEXTURE_COMPARE_FUNC + #else + GL_TEXTURE_COMPARE_FUNC_EXT + #endif + , GLenum(function)); +} + #ifndef MAGNUM_TARGET_GLES void AbstractTexture::setDepthStencilMode(const Sampler::DepthStencilMode mode) { (this->*Context::current()->state().texture->parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode)); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 64d75591b..7420cf450 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -297,6 +297,8 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setBorderColor(const Vector4ui& color); #endif void setMaxAnisotropy(Float anisotropy); + void setCompareMode(Sampler::CompareMode mode); + void setCompareFunction(Sampler::CompareFunction function); #ifndef MAGNUM_TARGET_GLES void setDepthStencilMode(Sampler::DepthStencilMode mode); #endif diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 9c607433f..8f67e33be 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -221,6 +221,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,blend_minmax), _extension(GL,EXT,shader_texture_lod), _extension(GL,EXT,occlusion_query_boolean), + _extension(GL,EXT,shadow_samplers), _extension(GL,EXT,texture_rg), _extension(GL,EXT,texture_storage), _extension(GL,EXT,map_buffer_range), @@ -229,6 +230,8 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,NV,read_buffer), _extension(GL,NV,framebuffer_blit), _extension(GL,NV,framebuffer_multisample), + _extension(GL,NV,shadow_samplers_array), + _extension(GL,NV,shadow_samplers_cube), _extension(GL,OES,depth24), _extension(GL,OES,element_index_uint), _extension(GL,OES,rgb8_rgba8), diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index b784d5104..5fa4f4734 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -188,6 +188,32 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setCompareMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareMode() for more information. + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and + * @es_extension{NV,shadow_samplers_cube} + */ + CubeMapTexture& setCompareMode(Sampler::CompareMode mode) { + AbstractTexture::setCompareMode(mode); + return *this; + } + + /** + * @copybrief Texture::setCompareFunction() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareFunction() for more information. + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and + * @es_extension{NV,shadow_samplers_cube} + */ + CubeMapTexture& setCompareFunction(Sampler::CompareFunction function) { + AbstractTexture::setCompareFunction(function); + return *this; + } + #ifndef MAGNUM_TARGET_GLES /** @copydoc Texture::setDepthStencilMode() */ CubeMapTexture& setDepthStencilMode(Sampler::DepthStencilMode mode) { diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 771413391..3cf1da116 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -218,6 +218,28 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setCompareMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareMode() for more information. + */ + CubeMapTextureArray& setCompareMode(Sampler::CompareMode mode) { + AbstractTexture::setCompareMode(mode); + return *this; + } + + /** + * @copybrief Texture::setCompareFunction() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareFunction() for more information. + */ + CubeMapTextureArray& setCompareFunction(Sampler::CompareFunction function) { + AbstractTexture::setCompareFunction(function); + return *this; + } + /** * @copybrief Texture::setDepthStencilMode() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index 032fd4a90..4df94b3fa 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -242,6 +242,7 @@ namespace GL { #endif _extension(GL,EXT,separate_shader_objects, GLES200, None) // #101 #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,EXT,shadow_samplers, GLES200, GLES300) // #102 _extension(GL,EXT,texture_rg, GLES200, GLES300) // #103 #endif _extension(GL,EXT,sRGB, GLES200, None) // #105 @@ -270,6 +271,8 @@ namespace GL { #ifdef MAGNUM_TARGET_GLES2 _extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142 _extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143 + _extension(GL,NV,shadow_samplers_array, GLES200, GLES300) // #146 + _extension(GL,NV,shadow_samplers_cube, GLES200, GLES300) // #147 #endif _extension(GL,NV,texture_border_clamp, GLES200, None) // #149 } namespace OES { diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 3f8ac4c49..55d052734 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -190,6 +190,28 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setCompareMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareMode() for more information. + */ + RectangleTexture& setCompareMode(Sampler::CompareMode mode) { + AbstractTexture::setCompareMode(mode); + return *this; + } + + /** + * @copybrief Texture::setCompareFunction() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareFunction() for more information. + */ + RectangleTexture& setCompareFunction(Sampler::CompareFunction function) { + AbstractTexture::setCompareFunction(function); + return *this; + } + /** * @copybrief Texture::setDepthStencilMode() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Sampler.cpp b/src/Magnum/Sampler.cpp index 9a6138c72..7a886575b 100644 --- a/src/Magnum/Sampler.cpp +++ b/src/Magnum/Sampler.cpp @@ -100,6 +100,34 @@ Debug operator<<(Debug debug, const Sampler::Wrapping value) { return debug << "Sampler::Wrapping::(invalid)"; } +Debug operator<<(Debug debug, const Sampler::CompareMode value) { + switch(value) { + #define _c(value) case Sampler::CompareMode::value: return debug << "Sampler::CompareMode::" #value; + _c(None) + _c(CompareRefToTexture) + #undef _c + } + + return debug << "Sampler::CompareFunction::(invalid)"; +} + +Debug operator<<(Debug debug, const Sampler::CompareFunction value) { + switch(value) { + #define _c(value) case Sampler::CompareFunction::value: return debug << "Sampler::CompareFunction::" #value; + _c(Never) + _c(Always) + _c(Less) + _c(LessOrEqual) + _c(Equal) + _c(NotEqual) + _c(GreaterOrEqual) + _c(Greater) + #undef _c + } + + return debug << "Sampler::CompareFunction::(invalid)"; +} + #ifndef MAGNUM_TARGET_GLES Debug operator<<(Debug debug, const Sampler::DepthStencilMode value) { switch(value) { diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index 674e5a807..286c10fa1 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -136,6 +136,76 @@ class MAGNUM_EXPORT Sampler { #endif }; + /** + * @brief Depth texture comparison mode + * + * @see @ref CompareFunction, + * @ref Texture::setCompareMode() "*Texture::setCompareMode()" + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} + */ + enum class CompareMode: GLenum { + /** Directly output the depth value */ + None = GL_NONE, + + /** Use output from specified @ref CompareFunction */ + CompareRefToTexture = + #ifndef MAGNUM_TARGET_GLES2 + GL_COMPARE_REF_TO_TEXTURE + #else + GL_COMPARE_REF_TO_TEXTURE_EXT + #endif + }; + + /** + * @brief Depth texture comparison function + * + * Comparison operator used when comparison mode is set to + * @ref CompareMode::CompareRefToTexture. + * @see @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", + * @ref Texture::setCompareMode() "*Texture::setCompareMode()" + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} + */ + enum class CompareFunction: GLenum { + Never = GL_NEVER, /**< Always `0.0` */ + Always = GL_ALWAYS, /**< Always `1.0` */ + + /** + * `1.0` when texture coordinate is less than depth value, `0.0` + * otherwise + */ + Less = GL_LESS, + + /** + * `1.0` when texture coordinate is less than or equal to depth + * value, `0.0` otherwise + */ + LessOrEqual = GL_LEQUAL, + + /** + * `1.0` when texture coordinate is equal to depth value, `0.0` + * otherwise + */ + Equal = GL_EQUAL, + + /** + * `0.0` when texture coordinate is equal to depth value, `1.0` + * otherwise + */ + NotEqual = GL_NOTEQUAL, + + /** + * `1.0` when texture coordinate is greater than or equal to depth + * value, `0.0` otherwise + */ + GreaterOrEqual = GL_GEQUAL, + + /** + * `1.0` when texture coordinate is greater than depth value, `0.0` + * otherwise + */ + Greater = GL_GREATER + }; + #ifndef MAGNUM_TARGET_GLES /** * @brief Depth/stencil texture mode @@ -182,6 +252,12 @@ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Mipmap value); /** @debugoperator{Magnum::Sampler} */ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::Wrapping value); +/** @debugoperator{Magnum::Sampler} */ +Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::CompareMode value); + +/** @debugoperator{Magnum::Sampler} */ +Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::CompareFunction value); + #ifndef MAGNUM_TARGET_GLES /** @debugoperator{Magnum::Sampler} */ Debug MAGNUM_EXPORT operator<<(Debug debug, Sampler::DepthStencilMode value); diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 847ffe9e3..41427ab05 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -132,7 +132,9 @@ void CubeMapTextureArrayGLTest::sampling() { .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); MAGNUM_VERIFY_NO_ERROR(); } diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 892bc249c..5de0f2047 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -48,6 +48,7 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { void sampling(); #ifdef MAGNUM_TARGET_GLES2 void samplingMaxLevel(); + void samplingCompare(); #endif #ifndef MAGNUM_TARGET_GLES void samplingBorderInteger(); @@ -79,6 +80,7 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { &CubeMapTextureGLTest::sampling, #ifdef MAGNUM_TARGET_GLES2 &CubeMapTextureGLTest::samplingMaxLevel, + &CubeMapTextureGLTest::samplingCompare, #endif #ifndef MAGNUM_TARGET_GLES &CubeMapTextureGLTest::samplingBorderInteger, @@ -153,7 +155,12 @@ void CubeMapTextureGLTest::sampling() { #endif .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + #ifndef MAGNUM_TARGET_GLES2 + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual) + #endif + ; MAGNUM_VERIFY_NO_ERROR(); } @@ -168,6 +175,18 @@ void CubeMapTextureGLTest::samplingMaxLevel() { MAGNUM_VERIFY_NO_ERROR(); } + +void CubeMapTextureGLTest::samplingCompare() { + if(!Context::current()->isExtensionSupported() || + !Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::NV::shadow_samplers_cube::string() + std::string(" is not supported.")); + + CubeMapTexture texture; + texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index ade0e0b03..d51b29fbc 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -128,7 +128,9 @@ void RectangleTextureGLTest::sampling() { .setMagnificationFilter(Sampler::Filter::Linear) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); MAGNUM_VERIFY_NO_ERROR(); } diff --git a/src/Magnum/Test/SamplerTest.cpp b/src/Magnum/Test/SamplerTest.cpp index 812734c02..d7c241a9a 100644 --- a/src/Magnum/Test/SamplerTest.cpp +++ b/src/Magnum/Test/SamplerTest.cpp @@ -37,6 +37,8 @@ class SamplerTest: public TestSuite::Tester { void debugFilter(); void debugMipmap(); void debugWrapping(); + void debugCompareMode(); + void debugCompareFunction(); #ifndef MAGNUM_TARGET_GLES void debugDepthStencilMode(); #endif @@ -46,6 +48,8 @@ SamplerTest::SamplerTest() { addTests({&SamplerTest::debugFilter, &SamplerTest::debugMipmap, &SamplerTest::debugWrapping, + &SamplerTest::debugCompareMode, + &SamplerTest::debugCompareFunction, #ifndef MAGNUM_TARGET_GLES &SamplerTest::debugDepthStencilMode #endif @@ -73,6 +77,20 @@ void SamplerTest::debugWrapping() { CORRADE_COMPARE(out.str(), "Sampler::Wrapping::ClampToEdge\n"); } +void SamplerTest::debugCompareMode() { + std::ostringstream out; + + Debug(&out) << Sampler::CompareMode::CompareRefToTexture; + CORRADE_COMPARE(out.str(), "Sampler::CompareMode::CompareRefToTexture\n"); +} + +void SamplerTest::debugCompareFunction() { + std::ostringstream out; + + Debug(&out) << Sampler::CompareFunction::GreaterOrEqual; + CORRADE_COMPARE(out.str(), "Sampler::CompareFunction::GreaterOrEqual\n"); +} + #ifndef MAGNUM_TARGET_GLES void SamplerTest::debugDepthStencilMode() { std::ostringstream out; diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index 4dbc82dfa..d66ad6a33 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -57,6 +57,7 @@ class TextureArrayGLTest: public AbstractOpenGLTester { #ifdef MAGNUM_TARGET_GLES2 void samplingMaxLevel2D(); + void samplingCompare2D(); #endif #ifndef MAGNUM_TARGET_GLES @@ -274,7 +275,9 @@ void TextureArrayGLTest::sampling1D() { .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); MAGNUM_VERIFY_NO_ERROR(); } @@ -328,7 +331,12 @@ void TextureArrayGLTest::sampling2D() { #else .setWrapping(Sampler::Wrapping::ClampToEdge) #endif - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + #ifndef MAGNUM_TARGET_GLES + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual) + #endif + ; MAGNUM_VERIFY_NO_ERROR(); } @@ -343,6 +351,18 @@ void TextureArrayGLTest::samplingMaxLevel2D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureArrayGLTest::samplingCompare2D() { + if(!Context::current()->isExtensionSupported() || + !Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::NV::shadow_samplers_array::string() + std::string(" is not supported.")); + + Texture2DArray texture; + texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 2ef5f9f35..0cc5bd74f 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -63,6 +63,7 @@ class TextureGLTest: public AbstractOpenGLTester { #ifdef MAGNUM_TARGET_GLES2 void samplingMaxLevel2D(); void samplingMaxLevel3D(); + void samplingCompare2D(); #endif #ifndef MAGNUM_TARGET_GLES @@ -152,6 +153,7 @@ TextureGLTest::TextureGLTest() { #ifdef MAGNUM_TARGET_GLES2 &TextureGLTest::samplingMaxLevel2D, &TextureGLTest::samplingMaxLevel3D, + &TextureGLTest::samplingCompare2D, #endif #ifndef MAGNUM_TARGET_GLES @@ -346,7 +348,9 @@ void TextureGLTest::sampling1D() { .setMaxLevel(750) .setWrapping(Sampler::Wrapping::ClampToBorder) .setBorderColor(Color3(0.5f)) - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); MAGNUM_VERIFY_NO_ERROR(); } @@ -381,7 +385,9 @@ void TextureGLTest::sampling2D() { #else .setWrapping(Sampler::Wrapping::ClampToEdge) #endif - .setMaxAnisotropy(Sampler::maxMaxAnisotropy()); + .setMaxAnisotropy(Sampler::maxMaxAnisotropy()) + .setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); MAGNUM_VERIFY_NO_ERROR(); } @@ -396,6 +402,17 @@ void TextureGLTest::samplingMaxLevel2D() { MAGNUM_VERIFY_NO_ERROR(); } + +void TextureGLTest::samplingCompare2D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::shadow_samplers::string() + std::string(" is not supported.")); + + Texture2D texture; + texture.setCompareMode(Sampler::CompareMode::CompareRefToTexture) + .setCompareFunction(Sampler::CompareFunction::GreaterOrEqual); + + MAGNUM_VERIFY_NO_ERROR(); +} #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index af9d725e2..3190c70e5 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -442,6 +442,46 @@ template class Texture: public AbstractTexture { return *this; } + /** + * @brief Set depth texture comparison mode + * @return Reference to self (for method chaining) + * + * If @extension{EXT,direct_state_access} is not available, + * the texture is bound to some texture unit before the operation. + * Initial value is @ref Sampler::CompareMode::None. + * @note Depth textures can be only 1D or 2D. + * @see @ref setCompareFunction(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_COMPARE_MODE} + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} + */ + Texture& setCompareMode(Sampler::CompareMode mode) { + AbstractTexture::setCompareMode(mode); + return *this; + } + + /** + * @brief Set depth texture comparison function + * @return Reference to self (for method chaining) + * + * Comparison operator used when comparison mode is set to + * @ref CompareMode::CompareRefToTexture. If + * @extension{EXT,direct_state_access} is not available, the texture is + * bound to some texture unit before the operation. + * @note Depth textures can be only 1D or 2D. + * @todoc initial value? + * @see @ref setCompareMode(), @fn_gl{ActiveTexture}, + * @fn_gl{BindTexture} and @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_COMPARE_FUNC} + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} + */ + Texture& setCompareFunction(Sampler::CompareFunction function) { + AbstractTexture::setCompareFunction(function); + return *this; + } + #ifndef MAGNUM_TARGET_GLES /** * @brief Set depth/stencil texture mode diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index b1891d137..c8d94d0ef 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -196,6 +196,32 @@ template class TextureArray: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setCompareMode() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareMode() for more information. + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and + * @es_extension{NV,shadow_samplers_array} + */ + TextureArray& setCompareMode(Sampler::CompareMode mode) { + AbstractTexture::setCompareMode(mode); + return *this; + } + + /** + * @copybrief Texture::setCompareFunction() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setCompareFunction() for more information. + * @requires_gles30 %Extension @es_extension{EXT,shadow_samplers} and + * @es_extension{NV,shadow_samplers_array} + */ + TextureArray& setCompareFunction(Sampler::CompareFunction function) { + AbstractTexture::setCompareFunction(function); + return *this; + } + #ifndef MAGNUM_TARGET_GLES /** * @copybrief Texture::setDepthStencilMode() From 325d139353ea27a520577e616bd147d67944b6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 12:44:19 +0200 Subject: [PATCH 19/46] Doc++ --- src/Magnum/Texture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 3190c70e5..e85049abf 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -466,7 +466,7 @@ template class Texture: public AbstractTexture { * @return Reference to self (for method chaining) * * Comparison operator used when comparison mode is set to - * @ref CompareMode::CompareRefToTexture. If + * @ref Sampler::CompareMode::CompareRefToTexture. If * @extension{EXT,direct_state_access} is not available, the texture is * bound to some texture unit before the operation. * @note Depth textures can be only 1D or 2D. From 11ea906e4701f5ad4d555e7b888f6182becd2c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 12:46:35 +0200 Subject: [PATCH 20/46] Doc++ Sometimes the specification hides the information very well. --- src/Magnum/Texture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index e85049abf..7a96de6a2 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -468,9 +468,9 @@ template class Texture: public AbstractTexture { * Comparison operator used when comparison mode is set to * @ref Sampler::CompareMode::CompareRefToTexture. If * @extension{EXT,direct_state_access} is not available, the texture is - * bound to some texture unit before the operation. + * bound to some texture unit before the operation. Initial value is + * @ref Sampler::CompareFunction::LessOrEqual. * @note Depth textures can be only 1D or 2D. - * @todoc initial value? * @see @ref setCompareMode(), @fn_gl{ActiveTexture}, * @fn_gl{BindTexture} and @fn_gl{TexParameter} or * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with From 1b1ad41ae11034055b5a7ac3d192f1ff0bb5cd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 14:28:39 +0200 Subject: [PATCH 21/46] Renamed internal function to avoid name clashes. --- src/Magnum/AbstractTexture.cpp | 8 ++++---- src/Magnum/AbstractTexture.h | 8 ++++---- src/Magnum/Implementation/TextureState.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 34a30861f..7492a4028 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -757,21 +757,21 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLfloat #endif #ifndef MAGNUM_TARGET_GLES -void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLuint* values) { +void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLuint* values) { bindInternal(); glTexParameterIuiv(_target, parameter, values); } -void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLuint* values) { +void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLuint* values) { glTextureParameterIuivEXT(_id, _target, parameter, values); } -void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) { +void AbstractTexture::parameterIImplementationDefault(GLenum parameter, const GLint* values) { bindInternal(); glTexParameterIiv(_target, parameter, values); } -void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) { +void AbstractTexture::parameterIImplementationDSA(GLenum parameter, const GLint* values) { glTextureParameterIivEXT(_id, _target, parameter, values); } #endif diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 7420cf450..78f51ab76 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -334,15 +334,15 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLuint* values); - void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values); + void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLuint* values); + void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLint* values); #endif #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values); - void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLuint* values); - void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values); + void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLuint* values); + void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLint* values); #endif void MAGNUM_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 1463be29d..b08899058 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -73,8 +73,8 @@ TextureState::TextureState(Context& context, std::vector& extension parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; - parameterIuivImplementation = &AbstractTexture::parameterImplementationDSA; - parameterIivImplementation = &AbstractTexture::parameterImplementationDSA; + parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSA; + parameterIivImplementation = &AbstractTexture::parameterIImplementationDSA; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDSA; mipmapImplementation = &AbstractTexture::mipmapImplementationDSA; getImageImplementation = &AbstractTexture::getImageImplementationDSA; @@ -94,8 +94,8 @@ TextureState::TextureState(Context& context, std::vector& extension parameterfImplementation = &AbstractTexture::parameterImplementationDefault; parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; #ifndef MAGNUM_TARGET_GLES - parameterIuivImplementation = &AbstractTexture::parameterImplementationDefault; - parameterIivImplementation = &AbstractTexture::parameterImplementationDefault; + parameterIuivImplementation = &AbstractTexture::parameterIImplementationDefault; + parameterIivImplementation = &AbstractTexture::parameterIImplementationDefault; getLevelParameterivImplementation = &AbstractTexture::getLevelParameterImplementationDefault; #endif mipmapImplementation = &AbstractTexture::mipmapImplementationDefault; From 8c0c80a5c351404fe0e6485a48649943e5df83ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 12 Apr 2014 15:28:02 +0200 Subject: [PATCH 22/46] Implemented ARB_texture_swizzle. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 2 +- src/Magnum/AbstractTexture.cpp | 27 ++++++++++ src/Magnum/AbstractTexture.h | 29 +++++++++- src/Magnum/CubeMapTexture.h | 8 +++ src/Magnum/CubeMapTextureArray.h | 11 ++++ src/Magnum/Implementation/TextureState.cpp | 4 ++ src/Magnum/Implementation/TextureState.h | 3 ++ src/Magnum/RectangleTexture.h | 11 ++++ src/Magnum/Test/CubeMapTextureArrayGLTest.cpp | 14 +++++ src/Magnum/Test/CubeMapTextureGLTest.cpp | 22 ++++++-- src/Magnum/Test/RectangleTextureGLTest.cpp | 14 +++++ src/Magnum/Test/TextureArrayGLTest.cpp | 38 +++++++++++-- src/Magnum/Test/TextureGLTest.cpp | 54 +++++++++++++++++-- src/Magnum/Texture.h | 29 ++++++++++ src/Magnum/TextureArray.h | 8 +++ 16 files changed, 263 insertions(+), 13 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index cea87b979..2f5ad439d 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -234,7 +234,7 @@ OpenGL function | Matching API @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() -@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" +@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setSwizzle() "*Texture::setSwizzle()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 80a54eadb..25ba6a715 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -114,7 +114,7 @@ following: @extension{ARB,sampler_objects} | | @extension{ARB,shader_bit_encoding} | done (shading language only) @extension{ARB,texture_rgb10_a2ui} | done -@extension{ARB,texture_swizzle} | | +@extension{ARB,texture_swizzle} | done @extension{ARB,timer_query} | missing direct query @extension{ARB,vertex_type_2_10_10_10_rev} | done diff --git a/src/Magnum/AbstractTexture.cpp b/src/Magnum/AbstractTexture.cpp index 7492a4028..6e9049a4f 100644 --- a/src/Magnum/AbstractTexture.cpp +++ b/src/Magnum/AbstractTexture.cpp @@ -286,6 +286,20 @@ void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); } +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) { + #ifndef MAGNUM_TARGET_GLES + const GLint rgba[] = {r, g, b, a}; + (this->*Context::current()->state().texture->parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba); + #else + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r); + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g); + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b); + (this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a); + #endif +} +#endif + void AbstractTexture::setCompareMode(const Sampler::CompareMode mode) { (this->*Context::current()->state().texture->parameteriImplementation)( #ifndef MAGNUM_TARGET_GLES2 @@ -745,6 +759,19 @@ void AbstractTexture::parameterImplementationDSA(GLenum parameter, GLfloat value } #endif +#ifndef MAGNUM_TARGET_GLES2 +void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLint* values) { + bindInternal(); + glTexParameteriv(_target, parameter, values); +} + +#ifndef MAGNUM_TARGET_GLES +void AbstractTexture::parameterImplementationDSA(GLenum parameter, const GLint* values) { + glTextureParameterivEXT(_id, _target, parameter, values); +} +#endif +#endif + void AbstractTexture::parameterImplementationDefault(GLenum parameter, const GLfloat* values) { bindInternal(); glTexParameterfv(_target, parameter, values); diff --git a/src/Magnum/AbstractTexture.h b/src/Magnum/AbstractTexture.h index 78f51ab76..68e377828 100644 --- a/src/Magnum/AbstractTexture.h +++ b/src/Magnum/AbstractTexture.h @@ -34,7 +34,19 @@ namespace Magnum { -namespace Implementation { struct TextureState; } +namespace Implementation { + struct TextureState; + + #ifndef MAGNUM_TARGET_GLES2 + template struct TextureSwizzle; + template<> struct TextureSwizzle<'r'> { enum: GLint { Value = GL_RED }; }; + template<> struct TextureSwizzle<'g'> { enum: GLint { Value = GL_GREEN }; }; + template<> struct TextureSwizzle<'b'> { enum: GLint { Value = GL_BLUE }; }; + template<> struct TextureSwizzle<'a'> { enum: GLint { Value = GL_ALPHA }; }; + template<> struct TextureSwizzle<'0'> { enum: GLint { Value = GL_ZERO }; }; + template<> struct TextureSwizzle<'1'> { enum: GLint { Value = GL_ONE }; }; + #endif +} /** @brief Base for textures @@ -297,6 +309,17 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void setBorderColor(const Vector4ui& color); #endif void setMaxAnisotropy(Float anisotropy); + + #ifndef MAGNUM_TARGET_GLES2 + template void setSwizzle() { + setSwizzleInternal(Implementation::TextureSwizzle::Value, + Implementation::TextureSwizzle::Value, + Implementation::TextureSwizzle::Value, + Implementation::TextureSwizzle::Value); + } + void setSwizzleInternal(GLint r, GLint g, GLint b, GLint a); + #endif + void setCompareMode(Sampler::CompareMode mode); void setCompareFunction(Sampler::CompareFunction function); #ifndef MAGNUM_TARGET_GLES @@ -332,6 +355,9 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, GLfloat value); + #ifndef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLint* values); + #endif void MAGNUM_LOCAL parameterImplementationDefault(GLenum parameter, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterIImplementationDefault(GLenum parameter, const GLuint* values); @@ -340,6 +366,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject { #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLint value); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, GLfloat value); + void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLint* values); void MAGNUM_LOCAL parameterImplementationDSA(GLenum parameter, const GLfloat* values); void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLuint* values); void MAGNUM_LOCAL parameterIImplementationDSA(GLenum parameter, const GLint* values); diff --git a/src/Magnum/CubeMapTexture.h b/src/Magnum/CubeMapTexture.h index 5fa4f4734..45372823f 100644 --- a/src/Magnum/CubeMapTexture.h +++ b/src/Magnum/CubeMapTexture.h @@ -188,6 +188,14 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setSwizzle() */ + template CubeMapTexture& setSwizzle() { + AbstractTexture::setSwizzle(); + return *this; + } + #endif + /** * @copybrief Texture::setCompareMode() * @return Reference to self (for method chaining) diff --git a/src/Magnum/CubeMapTextureArray.h b/src/Magnum/CubeMapTextureArray.h index 3cf1da116..ab24ca357 100644 --- a/src/Magnum/CubeMapTextureArray.h +++ b/src/Magnum/CubeMapTextureArray.h @@ -218,6 +218,17 @@ class CubeMapTextureArray: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setSwizzle() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setSwizzle() for more information. + */ + template CubeMapTextureArray& setSwizzle() { + AbstractTexture::setSwizzle(); + return *this; + } + /** * @copybrief Texture::setCompareMode() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index b08899058..864e64716 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -72,6 +72,7 @@ TextureState::TextureState(Context& context, std::vector& extension parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; + parameterivImplementation = &AbstractTexture::parameterImplementationDSA; parameterfvImplementation = &AbstractTexture::parameterImplementationDSA; parameterIuivImplementation = &AbstractTexture::parameterIImplementationDSA; parameterIivImplementation = &AbstractTexture::parameterIImplementationDSA; @@ -92,6 +93,9 @@ TextureState::TextureState(Context& context, std::vector& extension { parameteriImplementation = &AbstractTexture::parameterImplementationDefault; parameterfImplementation = &AbstractTexture::parameterImplementationDefault; + #ifndef MAGNUM_TARGET_GLES2 + parameterivImplementation = &AbstractTexture::parameterImplementationDefault; + #endif parameterfvImplementation = &AbstractTexture::parameterImplementationDefault; #ifndef MAGNUM_TARGET_GLES parameterIuivImplementation = &AbstractTexture::parameterIImplementationDefault; diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 9e44a68aa..e33d21ae3 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -42,6 +42,9 @@ struct TextureState { void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*parameteriImplementation)(GLenum, GLint); void(AbstractTexture::*parameterfImplementation)(GLenum, GLfloat); + #ifndef MAGNUM_TARGET_GLES2 + void(AbstractTexture::*parameterivImplementation)(GLenum, const GLint*); + #endif void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*); void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*); void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*); diff --git a/src/Magnum/RectangleTexture.h b/src/Magnum/RectangleTexture.h index 55d052734..3b5e4c5f9 100644 --- a/src/Magnum/RectangleTexture.h +++ b/src/Magnum/RectangleTexture.h @@ -190,6 +190,17 @@ class MAGNUM_EXPORT RectangleTexture: public AbstractTexture { return *this; } + /** + * @copybrief Texture::setSwizzle() + * @return Reference to self (for method chaining) + * + * See @ref Texture::setSwizzle() for more information. + */ + template RectangleTexture& setSwizzle() { + AbstractTexture::setSwizzle(); + return *this; + } + /** * @copybrief Texture::setCompareMode() * @return Reference to self (for method chaining) diff --git a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp index 41427ab05..5fadb807a 100644 --- a/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureArrayGLTest.cpp @@ -44,6 +44,7 @@ class CubeMapTextureArrayGLTest: public AbstractOpenGLTester { void sampling(); void samplingBorderInteger(); + void samplingSwizzle(); void samplingDepthStencilMode(); void storage(); @@ -65,6 +66,7 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { &CubeMapTextureArrayGLTest::sampling, &CubeMapTextureArrayGLTest::samplingBorderInteger, + &CubeMapTextureArrayGLTest::samplingSwizzle, &CubeMapTextureArrayGLTest::samplingDepthStencilMode, &CubeMapTextureArrayGLTest::storage, @@ -155,6 +157,18 @@ void CubeMapTextureArrayGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } +void CubeMapTextureArrayGLTest::samplingSwizzle() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + + CubeMapTextureArray texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} + void CubeMapTextureArrayGLTest::samplingDepthStencilMode() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 5de0f2047..7f5d12d9d 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -46,7 +46,9 @@ class CubeMapTextureGLTest: public AbstractOpenGLTester { void bind(); void sampling(); - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + void samplingSwizzle(); + #else void samplingMaxLevel(); void samplingCompare(); #endif @@ -78,7 +80,9 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { &CubeMapTextureGLTest::bind, &CubeMapTextureGLTest::sampling, - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + &CubeMapTextureGLTest::samplingSwizzle, + #else &CubeMapTextureGLTest::samplingMaxLevel, &CubeMapTextureGLTest::samplingCompare, #endif @@ -165,7 +169,19 @@ void CubeMapTextureGLTest::sampling() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES2 +#ifndef MAGNUM_TARGET_GLES2 +void CubeMapTextureGLTest::samplingSwizzle() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + #endif + + CubeMapTexture texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void CubeMapTextureGLTest::samplingMaxLevel() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/RectangleTextureGLTest.cpp b/src/Magnum/Test/RectangleTextureGLTest.cpp index d51b29fbc..7a925626f 100644 --- a/src/Magnum/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/Test/RectangleTextureGLTest.cpp @@ -45,6 +45,7 @@ class RectangleTextureGLTest: public AbstractOpenGLTester { void sampling(); void samplingBorderInteger(); + void samplingSwizzle(); void samplingDepthStencilMode(); void storage(); @@ -64,6 +65,7 @@ RectangleTextureGLTest::RectangleTextureGLTest() { &RectangleTextureGLTest::sampling, &RectangleTextureGLTest::samplingBorderInteger, + &RectangleTextureGLTest::samplingSwizzle, &RectangleTextureGLTest::samplingDepthStencilMode, &RectangleTextureGLTest::storage, @@ -151,6 +153,18 @@ void RectangleTextureGLTest::samplingBorderInteger() { MAGNUM_VERIFY_NO_ERROR(); } +void RectangleTextureGLTest::samplingSwizzle() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + + RectangleTexture texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} + void RectangleTextureGLTest::samplingDepthStencilMode() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::texture_rectangle::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureArrayGLTest.cpp b/src/Magnum/Test/TextureArrayGLTest.cpp index d66ad6a33..495bcc392 100644 --- a/src/Magnum/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/Test/TextureArrayGLTest.cpp @@ -55,7 +55,12 @@ class TextureArrayGLTest: public AbstractOpenGLTester { #endif void sampling2D(); - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + void samplingSwizzle1D(); + #endif + void samplingSwizzle2D(); + #else void samplingMaxLevel2D(); void samplingCompare2D(); #endif @@ -123,7 +128,12 @@ TextureArrayGLTest::TextureArrayGLTest() { #endif &TextureArrayGLTest::sampling2D, - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + &TextureArrayGLTest::samplingSwizzle1D, + #endif + &TextureArrayGLTest::samplingSwizzle2D, + #else &TextureArrayGLTest::samplingMaxLevel2D, #endif @@ -282,6 +292,16 @@ void TextureArrayGLTest::sampling1D() { MAGNUM_VERIFY_NO_ERROR(); } +void TextureArrayGLTest::samplingSwizzle1D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + + Texture1DArray texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} + void TextureArrayGLTest::samplingBorderInteger1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::EXT::texture_integer::string() + std::string(" is not supported.")); @@ -341,7 +361,19 @@ void TextureArrayGLTest::sampling2D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES2 +#ifndef MAGNUM_TARGET_GLES2 +void TextureArrayGLTest::samplingSwizzle2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + #endif + + Texture2DArray texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureArrayGLTest::samplingMaxLevel2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Test/TextureGLTest.cpp b/src/Magnum/Test/TextureGLTest.cpp index 0cc5bd74f..8f6b6fead 100644 --- a/src/Magnum/Test/TextureGLTest.cpp +++ b/src/Magnum/Test/TextureGLTest.cpp @@ -60,7 +60,13 @@ class TextureGLTest: public AbstractOpenGLTester { void sampling2D(); void sampling3D(); - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + void samplingSwizzle1D(); + #endif + void samplingSwizzle2D(); + void samplingSwizzle3D(); + #else void samplingMaxLevel2D(); void samplingMaxLevel3D(); void samplingCompare2D(); @@ -150,7 +156,13 @@ TextureGLTest::TextureGLTest() { &TextureGLTest::sampling2D, &TextureGLTest::sampling3D, - #ifdef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES2 + #ifndef MAGNUM_TARGET_GLES + &TextureGLTest::samplingSwizzle1D, + #endif + &TextureGLTest::samplingSwizzle2D, + &TextureGLTest::samplingSwizzle3D, + #else &TextureGLTest::samplingMaxLevel2D, &TextureGLTest::samplingMaxLevel3D, &TextureGLTest::samplingCompare2D, @@ -355,6 +367,16 @@ void TextureGLTest::sampling1D() { MAGNUM_VERIFY_NO_ERROR(); } +void TextureGLTest::samplingSwizzle1D() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + + Texture1D texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} + void TextureGLTest::samplingDepthStencilMode1D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::ARB::stencil_texturing::string() + std::string(" is not supported.")); @@ -392,7 +414,19 @@ void TextureGLTest::sampling2D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES2 +#ifndef MAGNUM_TARGET_GLES2 +void TextureGLTest::samplingSwizzle2D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + #endif + + Texture2D texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureGLTest::samplingMaxLevel2D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::APPLE::texture_max_level::string() + std::string(" is not supported.")); @@ -481,7 +515,19 @@ void TextureGLTest::sampling3D() { MAGNUM_VERIFY_NO_ERROR(); } -#ifdef MAGNUM_TARGET_GLES2 +#ifndef MAGNUM_TARGET_GLES2 +void TextureGLTest::samplingSwizzle3D() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::texture_swizzle::string() + std::string(" is not supported.")); + #endif + + Texture3D texture; + texture.setSwizzle<'b', 'g', 'r', '0'>(); + + MAGNUM_VERIFY_NO_ERROR(); +} +#else void TextureGLTest::samplingMaxLevel3D() { if(!Context::current()->isExtensionSupported()) CORRADE_SKIP(Extensions::GL::OES::texture_3D::string() + std::string(" is not supported.")); diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index 7a96de6a2..c1de9599b 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -442,6 +442,35 @@ template class Texture: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set component swizzle + * @return Reference to self (for method chaining) + * + * You can use letters `r`, `g`, `b`, `a` for addressing components or + * letters `0` and `1` for zero and one, similarly as in + * @ref Math::swizzle() function. Example usage: + * @code + * texture.setSwizzle<'b', 'g', 'r', '0'>(); + * @endcode + * If @extension{EXT,direct_state_access} is not available, + * the texture is bound to some texture unit before the operation. + * Initial value is `rgba`. + * @see @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{TexParameter} or + * @fn_gl_extension{TextureParameter,EXT,direct_state_access} with + * @def_gl{TEXTURE_SWIZZLE_RGBA} (or @def_gl{TEXTURE_SWIZZLE_R}, + * @def_gl{TEXTURE_SWIZZLE_G}, @def_gl{TEXTURE_SWIZZLE_B} and + * @def_gl{TEXTURE_SWIZZLE_A} separately in OpenGL ES) + * @requires_gl33 %Extension @extension{ARB,texture_swizzle} + * @requires_gles30 %Texture swizzle is not available in OpenGL ES 2.0. + */ + template Texture& setSwizzle() { + AbstractTexture::setSwizzle(); + return *this; + } + #endif + /** * @brief Set depth texture comparison mode * @return Reference to self (for method chaining) diff --git a/src/Magnum/TextureArray.h b/src/Magnum/TextureArray.h index c8d94d0ef..0a671dbd7 100644 --- a/src/Magnum/TextureArray.h +++ b/src/Magnum/TextureArray.h @@ -196,6 +196,14 @@ template class TextureArray: public AbstractTexture { return *this; } + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc Texture::setSwizzle() */ + template TextureArray& setSwizzle() { + AbstractTexture::setSwizzle(); + return *this; + } + #endif + /** * @copybrief Texture::setCompareMode() * @return Reference to self (for method chaining) From 74ae14b44ad59a9f8b601d80e26874b43f6ef6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 13 Apr 2014 00:02:40 +0200 Subject: [PATCH 23/46] Remove unused members from ES build. --- src/Magnum/Implementation/TextureState.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index e33d21ae3..d9f558cb5 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -46,10 +46,14 @@ struct TextureState { void(AbstractTexture::*parameterivImplementation)(GLenum, const GLint*); #endif void(AbstractTexture::*parameterfvImplementation)(GLenum, const GLfloat*); + #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*parameterIuivImplementation)(GLenum, const GLuint*); void(AbstractTexture::*parameterIivImplementation)(GLenum, const GLint*); + #endif void(AbstractTexture::*setMaxAnisotropyImplementation)(GLfloat); + #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*getLevelParameterivImplementation)(GLenum, GLint, GLenum, GLint*); + #endif void(AbstractTexture::*mipmapImplementation)(); #ifndef MAGNUM_TARGET_GLES void(AbstractTexture::*storage1DImplementation)(GLenum, GLsizei, TextureFormat, const Math::Vector<1, GLsizei>&); From ee403494fb2c1e67512704ba0dd8b258cb1cae26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 20 Apr 2014 11:39:34 +0200 Subject: [PATCH 24/46] Doc++ --- src/Magnum/Mesh.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index bf7f899f1..1514e3d9e 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -287,14 +287,14 @@ mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color( @section Mesh-drawing Rendering meshes Basic workflow is: bind specific framebuffer for drawing (if needed), set up -respective shader, bind required textures (see +respective shader (see @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" for more infromation) and call @ref Mesh::draw(). @section Mesh-webgl-restrictions WebGL restrictions @ref MAGNUM_TARGET_WEBGL "WebGL" puts some restrictions on vertex buffer -layout, see @ref addVertexBuffer() for details. +layout, see @ref addVertexBuffer() documentation for details. @section Mesh-performance-optimization Performance optimizations From 153f57f5b1c7222bfec341bcf184c4befafa9bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 24 Apr 2014 23:48:43 +0200 Subject: [PATCH 25/46] Fix CubeMapTexture mipmap generation test. On new NVidia drivers 337.12 it reports that the texture is not cube map complete. --- src/Magnum/Test/CubeMapTextureGLTest.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Magnum/Test/CubeMapTextureGLTest.cpp b/src/Magnum/Test/CubeMapTextureGLTest.cpp index 7f5d12d9d..2dd8454dc 100644 --- a/src/Magnum/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/Test/CubeMapTextureGLTest.cpp @@ -406,6 +406,16 @@ void CubeMapTextureGLTest::generateMipmap() { CubeMapTexture texture; texture.setImage(CubeMapTexture::Coordinate::PositiveX, 0, TextureFormat::RGBA8, ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + texture.setImage(CubeMapTexture::Coordinate::PositiveY, 0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + texture.setImage(CubeMapTexture::Coordinate::PositiveZ, 0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + texture.setImage(CubeMapTexture::Coordinate::NegativeX, 0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + texture.setImage(CubeMapTexture::Coordinate::NegativeY, 0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); + texture.setImage(CubeMapTexture::Coordinate::NegativeZ, 0, TextureFormat::RGBA8, + ImageReference2D(ColorFormat::RGBA, ColorType::UnsignedByte, Vector2i(32))); /** @todo How to test this on ES? */ #ifndef MAGNUM_TARGET_GLES From 54cb177bb0118b14b94cafa685ac10c88e45da3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 26 Apr 2014 11:13:42 +0200 Subject: [PATCH 26/46] Properly initialize variables for texture limits in state tracker. And I was wondering how it is possible that there new NVidia drivers were allowing up to 32 PB textures on my humble laptop graphics :) --- src/Magnum/Implementation/TextureState.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 864e64716..a2b04cc2e 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -36,7 +36,11 @@ namespace Magnum { namespace Implementation { -TextureState::TextureState(Context& context, std::vector& extensions): maxTextureUnits(0), maxLodBias(0.0f), maxMaxAnisotropy(0.0f), currentTextureUnit(0) +TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, max3DSize{}, maxArrayLayers{}, maxCubeMapSize{}, + #ifndef MAGNUM_TARGET_GLES + maxRectangleSize{}, maxBufferSize{}, + #endif + maxTextureUnits(0), maxLodBias(0.0f), maxMaxAnisotropy(0.0f), currentTextureUnit(0) #ifndef MAGNUM_TARGET_GLES , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif From d772f51050c8326b4d4c4b3c22935d9196cddda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 26 Apr 2014 11:24:08 +0200 Subject: [PATCH 27/46] Hide texture state members which are not used on ES. Shaved eight bytes off total memory footprint, yay! --- src/Magnum/Implementation/TextureState.cpp | 11 +++++++++-- src/Magnum/Implementation/TextureState.h | 10 +++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index a2b04cc2e..3ac20d023 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -36,11 +36,18 @@ namespace Magnum { namespace Implementation { -TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, max3DSize{}, maxArrayLayers{}, maxCubeMapSize{}, +TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, max3DSize{}, maxCubeMapSize{}, + #ifndef MAGNUM_TARGET_GLES2 + maxArrayLayers{}, + #endif #ifndef MAGNUM_TARGET_GLES maxRectangleSize{}, maxBufferSize{}, #endif - maxTextureUnits(0), maxLodBias(0.0f), maxMaxAnisotropy(0.0f), currentTextureUnit(0) + maxTextureUnits(0), + #ifndef MAGNUM_TARGET_GLES + maxLodBias{0.0f}, + #endif + maxMaxAnisotropy(0.0f), currentTextureUnit(0) #ifndef MAGNUM_TARGET_GLES , maxColorSamples(0), maxDepthSamples(0), maxIntegerSamples(0), bufferOffsetAlignment(0) #endif diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index d9f558cb5..668fd5f53 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -83,15 +83,19 @@ struct TextureState { GLint maxSize, max3DSize, - maxArrayLayers, maxCubeMapSize; + #ifndef MAGNUM_TARGET_GLES2 + GLint maxArrayLayers; + #endif #ifndef MAGNUM_TARGET_GLES GLint maxRectangleSize, maxBufferSize; #endif GLint maxTextureUnits; - GLfloat maxLodBias, - maxMaxAnisotropy; + #ifndef MAGNUM_TARGET_GLES + GLfloat maxLodBias; + #endif + GLfloat maxMaxAnisotropy; GLint currentTextureUnit; #ifndef MAGNUM_TARGET_GLES GLint maxColorSamples, From bfa2a42638a52572e930f20bc145b082aedf966f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 13 Apr 2014 01:40:25 +0200 Subject: [PATCH 28/46] Don't differentiate between vertex and index count in Mesh. Only one value from these two was used in the end, wasting precious bytes. Also these two values were used to differentiate between indexed and non-indexed mesh (instead of relying on actual index buffer being bound), which was very confusing. This approach looks more clean. The MeshView class is not yet updated, as the change would expose some features that aren't possible in current implementation (base vertex specification). Merged Mesh::setVertexCount() and Mesh::setIndexCount() into one Mesh::setCount(), the two original functions are now guarded aliases to the new one, are marked as deprecated and will be removed in future release, similarly for the getters. In particular, if the mesh is indexed, setVertexCount() does nothing and vertexCount() returns 0. The setIndexCount() and indexCount() do and return the same regardless of whether the mesh is indexed or not. --- src/Magnum/DebugTools/ForceRenderer.cpp | 2 +- .../Implementation/AbstractShapeRenderer.cpp | 10 +- src/Magnum/DebugTools/ObjectRenderer.cpp | 2 +- src/Magnum/Mesh.cpp | 28 ++-- src/Magnum/Mesh.h | 138 +++++++++++------- src/Magnum/MeshTools/Compile.cpp | 16 +- src/Magnum/MeshTools/CompressIndices.cpp | 2 +- src/Magnum/MeshTools/CompressIndices.h | 6 +- src/Magnum/MeshTools/FullScreenTriangle.cpp | 2 +- src/Magnum/MeshTools/Interleave.h | 13 +- src/Magnum/MeshView.cpp | 10 +- src/Magnum/MeshView.h | 6 +- src/Magnum/Test/MeshGLTest.cpp | 8 +- src/Magnum/Test/PrimitiveQueryGLTest.cpp | 2 +- src/Magnum/Test/SampleQueryGLTest.cpp | 4 +- src/Magnum/Text/Renderer.cpp | 8 +- src/Magnum/TextureTools/DistanceField.cpp | 2 +- 17 files changed, 143 insertions(+), 116 deletions(-) diff --git a/src/Magnum/DebugTools/ForceRenderer.cpp b/src/Magnum/DebugTools/ForceRenderer.cpp index e763955a7..dd785c12f 100644 --- a/src/Magnum/DebugTools/ForceRenderer.cpp +++ b/src/Magnum/DebugTools/ForceRenderer.cpp @@ -88,7 +88,7 @@ template ForceRenderer::ForceRenderer(SceneG Mesh* mesh = new Mesh; mesh->setPrimitive(MeshPrimitive::Lines) - .setIndexCount(indices.size()) + .setCount(indices.size()) .addVertexBuffer(*vertexBuffer, 0, typename Shaders::Flat::Position(Shaders::Flat::Position::Components::Two)) .setIndexBuffer(*indexBuffer, 0, Mesh::IndexType::UnsignedByte, 0, positions.size()); diff --git a/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp b/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp index 1927770e8..fee897954 100644 --- a/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp @@ -53,7 +53,6 @@ template<> void create<2>(Trade::MeshData2D& data, Resource& meshResource, /* Mesh configuration */ Mesh* mesh = new Mesh; mesh->setPrimitive(data.primitive()) - .setVertexCount(data.positions(0).size()) .addVertexBuffer(*buffer, 0, Shaders::Flat2D::Position()); ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); @@ -63,7 +62,9 @@ template<> void create<2>(Trade::MeshData2D& data, Resource& meshResource, Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); - } + + /* The mesh is not indexed, set proper vertex count */ + } else mesh->setCount(data.positions(0).size()); } template<> void create<3>(Trade::MeshData3D& data, Resource& meshResource, Resource& vertexBufferResource, Resource& indexBufferResource) { @@ -75,7 +76,6 @@ template<> void create<3>(Trade::MeshData3D& data, Resource& meshResource, /* Mesh configuration */ Mesh* mesh = new Mesh; mesh->setPrimitive(data.primitive()) - .setVertexCount(data.positions(0).size()) .addVertexBuffer(*vertexBuffer, 0, Shaders::Flat3D::Position()); ResourceManager::instance().set(meshResource.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); @@ -85,7 +85,9 @@ template<> void create<3>(Trade::MeshData3D& data, Resource& meshResource, Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); - } + + /* The mesh is not indexed, set proper vertex count */ + } else mesh->setCount(data.positions(0).size()); } } diff --git a/src/Magnum/DebugTools/ObjectRenderer.cpp b/src/Magnum/DebugTools/ObjectRenderer.cpp index 669f8806a..b3f1d2b2f 100644 --- a/src/Magnum/DebugTools/ObjectRenderer.cpp +++ b/src/Magnum/DebugTools/ObjectRenderer.cpp @@ -166,7 +166,7 @@ template ObjectRenderer::ObjectRenderer(Scen ResourceManager::instance().set(this->indexBuffer.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); mesh->setPrimitive(MeshPrimitive::Lines) - .setIndexCount(Renderer::indices.size()) + .setCount(Renderer::indices.size()) .addVertexBuffer(*vertexBuffer, 0, typename Shaders::VertexColor::Position(), typename Shaders::VertexColor::Color()) diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 0ed703735..cc5bbc0ec 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -72,7 +72,7 @@ std::size_t Mesh::indexSize(IndexType type) { CORRADE_ASSERT_UNREACHABLE(); } -Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _vertexCount(0), _indexCount(0) +Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif @@ -92,7 +92,7 @@ Mesh::~Mesh() { (this->*Context::current()->state().mesh->destroyImplementation)(); } -Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _vertexCount(other._vertexCount), _indexCount(other._indexCount) +Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(other._indexStart), _indexEnd(other._indexEnd) #endif @@ -110,8 +110,7 @@ Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), Mesh& Mesh::operator=(Mesh&& other) noexcept { std::swap(_id, other._id); std::swap(_primitive, other._primitive); - std::swap(_vertexCount, other._vertexCount); - std::swap(_indexCount, other._indexCount); + std::swap(_count, other._count); #ifndef MAGNUM_TARGET_GLES2 std::swap(_indexStart, other._indexStart); std::swap(_indexEnd, other._indexEnd); @@ -153,6 +152,7 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi "Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::Target::ElementArray << "but got" << buffer.targetHint(), *this); #endif + _indexBuffer = &buffer; _indexOffset = offset; _indexType = type; #ifndef MAGNUM_TARGET_GLES2 @@ -167,29 +167,29 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi } #ifndef MAGNUM_TARGET_GLES2 -void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd) +void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) #else -void Mesh::drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount) +void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) #endif { /* Nothing to draw */ - if(!vertexCount && !indexCount) return; + if(!count) return; (this->*Context::current()->state().mesh->bindImplementation)(); /* Non-indexed mesh */ - if(!indexCount) - glDrawArrays(GLenum(_primitive), firstVertex, vertexCount); + if(!_indexBuffer) + glDrawArrays(GLenum(_primitive), firstVertex, count); #ifndef MAGNUM_TARGET_GLES2 /* Indexed mesh with specified range */ else if(indexEnd) - glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, indexCount, GLenum(_indexType), reinterpret_cast(indexOffset)); + glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); #endif /* Indexed mesh without specified range */ else - glDrawElements(GLenum(_primitive), indexCount, GLenum(_indexType), reinterpret_cast(indexOffset)); + glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); (this->*Context::current()->state().mesh->unbindImplementation)(); } @@ -329,9 +329,7 @@ void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) { #endif #endif -void Mesh::bindIndexBufferImplementationDefault(Buffer& buffer) { - _indexBuffer = &buffer; -} +void Mesh::bindIndexBufferImplementationDefault(Buffer&) {} void Mesh::bindIndexBufferImplementationVAO(Buffer& buffer) { bindVAO(_id); @@ -359,7 +357,7 @@ void Mesh::bindImplementationDefault() { #endif /* Bind index buffer, if the mesh is indexed */ - if(_indexCount) _indexBuffer->bind(Buffer::Target::ElementArray); + if(_indexBuffer) _indexBuffer->bind(Buffer::Target::ElementArray); } void Mesh::bindImplementationVAO() { diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 1514e3d9e..c731de8a4 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -122,29 +122,30 @@ namespace Implementation { struct MeshState; } @section Mesh-configuration Mesh configuration -You have to specify at least primitive and vertex count using @ref setPrimitive() -and @ref setVertexCount(). Then fill your vertex buffers with data, add them to -the mesh and specify @ref AbstractShaderProgram::Attribute "shader attribute" -layout inside the buffers using @ref addVertexBuffer(). You can also -use @ref MeshTools::interleave() conveniently fill interleaved vertex buffer. -The function itself calls @ref setVertexCount(), so you don't have to do it -again, but you still have to specify the layout using @ref addVertexBuffer(). - -If you have indexed mesh, you need to call @ref setIndexCount() instead of -@ref setVertexCount(). Then fill your index buffer with data and specify its +You have to specify at least primitive and vertex/index count using +@ref setPrimitive() and @ref setCount(). Then fill your vertex buffers with +data, add them to the mesh and specify +@ref AbstractShaderProgram::Attribute "shader attribute" layout inside the +buffers using @ref addVertexBuffer(). You can also use +@ref MeshTools::interleave() conveniently fill interleaved vertex buffer. +The function itself calls @ref setCount(), so you don't have to, but you still +have to specify the primitive using @ref setPrimitive() and the layout using +@ref addVertexBuffer(). + +If you want indexed mesh, fill your index buffer with data and specify its layout using @ref setIndexBuffer(). You can also use @ref MeshTools::compressIndices() to conveniently compress the indices, fill the index buffer and configure the -mesh instead of calling @ref setIndexCount() and @ref setIndexBuffer() manually. +mesh. It will call @ref setCount() and @ref setIndexBuffer(), so you don't have +to do anything else. Note that neither vertex buffers nor index buffer is managed (e.g. deleted on destruction) by the mesh, so you have to manage them on your own and ensure that they are available for whole mesh lifetime. On the other hand it allows you to use one buffer for more meshes (each mesh for example configured for -different shader) or store data for more meshes in one buffer. +different usage) or store data for more meshes in one buffer. -If the mesh has non-zero index count, it is treated as indexed mesh, otherwise -it is treated as non-indexed mesh. If both index and vertex count is zero, the -mesh is empty and no draw commands are issued when calling @ref draw(). +If vertex/index count is zero, the mesh is empty and no draw commands are +issued when calling @ref draw(). @subsection Mesh-configuration-examples Example mesh configuration @@ -169,7 +170,7 @@ vertexBuffer.setData(positions, BufferUsage::StaticDraw); // Set primitive and vertex count, add the buffer and specify its layout mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(30) + .setCount(30) .addVertexBuffer(vertexBuffer, 0, MyShader::Position()); @endcode @@ -218,7 +219,7 @@ indexBuffer.setData(indices, BufferUsage::StaticDraw); // Set primitive, index count, specify the buffers mesh.setPrimitive(MeshPrimitive::Triangles) - .setIndexCount(75) + .setCount(75) .addVertexBuffer(vertexBuffer, 0, MyShader::Position()) .setIndexBuffer(indexBuffer, 0, Mesh::IndexType::UnsignedByte, 176, 229); @endcode @@ -395,7 +396,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @param primitive Primitive type * * Creates mesh with no vertex buffers and zero vertex count. - * @see @ref setPrimitive(), @ref setVertexCount(), @fn_gl{GenVertexArrays} + * @see @ref setPrimitive(), @ref setCount(), @fn_gl{GenVertexArrays} * (if @extension{APPLE,vertex_array_object} is available) */ explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles); @@ -454,6 +455,13 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { */ Mesh& setLabel(const std::string& label); + /** + * @brief Whether the mesh is indexed + * + * @see @ref setIndexBuffer(), @ref setCount() + */ + bool isIndexed() const { return _indexBuffer; } + /** * @brief Index size * @@ -469,44 +477,63 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @return Reference to self (for method chaining) * * Default is @ref MeshPrimitive::Triangles. - * @see @ref setVertexCount(), @ref addVertexBuffer() + * @see @ref setCount() */ Mesh& setPrimitive(MeshPrimitive primitive) { _primitive = primitive; return *this; } - /** @brief Vertex count */ - Int vertexCount() const { return _vertexCount; } + /** @brief Vertex/index count */ + Int count() const { return _count; } /** - * @brief Set vertex count - * @return Reference to self (for method chaining) + * @brief Set vertex/index count * - * Default is zero. - * @see @ref setPrimitive(), @ref addVertexBuffer(), - * @ref MeshTools::interleave() + * If the mesh is indexed, the value is treated as index count, + * otherwise the value is vertex count. Default is `0`. This value is + * set automatically by @ref MeshTools::interleave() and + * @ref MeshTools::compressIndices() functions. + * @see @ref isIndexed() */ - Mesh& setVertexCount(Int vertexCount) { - _vertexCount = vertexCount; + Mesh& setCount(Int count) { + _count = count; return *this; } - /** @brief Index count */ - Int indexCount() const { return _indexCount; } + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copybrief count() + * @deprecated Use @ref Magnum::Mesh::count() "count()" instead. + */ + CORRADE_DEPRECATED("use count() instead") Int vertexCount() const { + return isIndexed() ? 0 : count(); + } /** - * @brief Set index count - * @return Reference to self (for method chaining) - * - * Default is zero. - * @see @ref setIndexBuffer(), @ref MeshTools::compressIndices() + * @copybrief setCount() + * @deprecated Use @ref Magnum::Mesh::setCount() "setCount()" instead. */ - Mesh& setIndexCount(Int count) { - _indexCount = count; + CORRADE_DEPRECATED("use setCount() instead") Mesh& setVertexCount(Int count) { + if(!isIndexed()) setCount(count); return *this; } + /** + * @copybrief count() + * @deprecated Use @ref Magnum::Mesh::count() "count()" instead. + */ + CORRADE_DEPRECATED("use count() instead") Int indexCount() const { + return count(); + } + + /** + * @copybrief setCount() + * @deprecated Use @ref Magnum::Mesh::setCount() "setCount()" instead. + */ + CORRADE_DEPRECATED("use setCount() instead") Mesh& setIndexCount(Int count) { return setCount(count); } + #endif + /** * @brief Add buffer with (interleaved) vertex attributes for use with given shader * @return Reference to self (for method chaining) @@ -565,7 +592,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * but doing so may have performance benefits. * * @see @ref maxVertexAttributes(), @ref setPrimitive(), - * @ref setVertexCount(), @fn_gl{BindVertexArray}, + * @ref setCount(), @fn_gl{BindVertexArray}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{VertexAttribPointer} or * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, @@ -594,9 +621,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this * functionality is not available there. * @see @ref maxElementsIndices(), @ref maxElementsVertices(), - * @ref setIndexCount(), @ref MeshTools::compressIndices(), - * @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if - * @extension{APPLE,vertex_array_object} is available) + * @ref setCount(), @ref isIndexed(), + * @ref MeshTools::compressIndices(), @fn_gl{BindVertexArray}, + * @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} is + * available) */ Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end); @@ -607,11 +635,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @param type Index data type * @return Reference to self (for method chaining) * - * Prefer to use @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt) - * for better performance. - * @see @ref setIndexCount(), @ref MeshTools::compressIndices(), - * @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} (if - * @extension{APPLE,vertex_array_object} is available) + * Alternative to @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt) + * with unspecified index limits, see its documentation for more + * information. Prefer to set index limits for better performance. */ Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type) { return setIndexBuffer(buffer, offset, type, 0, 0); @@ -629,15 +655,15 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} - * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}. + * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements} */ void draw(AbstractShaderProgram& shader) { shader.use(); #ifndef MAGNUM_TARGET_GLES2 - drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(0, _vertexCount, _indexOffset, _indexCount); + drawInternal(_count, 0, _indexOffset); #endif } @@ -649,11 +675,11 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @deprecated Use @ref Magnum::Mesh::draw(AbstractShaderProgram&) "draw(AbstractShaderProgram&)" * instead. */ - void draw() { + CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() { #ifndef MAGNUM_TARGET_GLES2 - drawInternal(0, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(0, _vertexCount, _indexOffset, _indexCount); + drawInternal(_count, 0, _indexOffset); #endif } #endif @@ -774,9 +800,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #ifndef MAGNUM_TARGET_GLES2 - void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount, Int indexStart, Int indexEnd); + void drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); #else - void drawInternal(Int firstVertex, Int vertexCount, GLintptr indexOffset, Int indexCount); + void drawInternal(Int count, Int firstVertex, GLintptr indexOffset); #endif void MAGNUM_LOCAL createImplementationDefault(); @@ -805,7 +831,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #endif - void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer& buffer); + void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&); void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer); void MAGNUM_LOCAL bindImplementationDefault(); @@ -816,7 +842,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLuint _id; MeshPrimitive _primitive; - Int _vertexCount, _indexCount; + Int _count; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index bc586f77a..3b42aa07b 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/src/Magnum/MeshTools/Compile.cpp @@ -72,17 +72,17 @@ std::tuple, std::unique_ptr> compile(const stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); } - /* Fill vertex buffer with interleaved data and finalize mesh - configuration */ + /* Fill vertex buffer with interleaved data */ vertexBuffer->setData(data, BufferUsage::StaticDraw); - mesh.setVertexCount(vertexCount); /* Fill index buffer */ std::unique_ptr indexBuffer; if(meshData.isIndexed()) { indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); - } + + /* Else set proper vertex count */ + } else mesh.setCount(vertexCount); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); } @@ -139,17 +139,17 @@ std::tuple, std::unique_ptr> compile(const stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); } - /* Fill vertex buffer with interleaved data and finalize mesh - configuration */ + /* Fill vertex buffer with interleaved data */ vertexBuffer->setData(data, BufferUsage::StaticDraw); - mesh.setVertexCount(vertexCount); /* Fill index buffer */ std::unique_ptr indexBuffer; if(meshData.isIndexed()) { indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); - } + + /* Else set proper vertex count */ + } mesh.setCount(vertexCount); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); } diff --git a/src/Magnum/MeshTools/CompressIndices.cpp b/src/Magnum/MeshTools/CompressIndices.cpp index 7d4f53074..d8be145d1 100644 --- a/src/Magnum/MeshTools/CompressIndices.cpp +++ b/src/Magnum/MeshTools/CompressIndices.cpp @@ -82,7 +82,7 @@ void compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::v Containers::Array data; std::tie(indexCount, indexType, data) = compressIndicesInternal(indices, *minmax.second); - mesh.setIndexCount(indices.size()) + mesh.setCount(indices.size()) .setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second); buffer.setData(data, usage); } diff --git a/src/Magnum/MeshTools/CompressIndices.h b/src/Magnum/MeshTools/CompressIndices.h index e1e847910..2b3b777f9 100644 --- a/src/Magnum/MeshTools/CompressIndices.h +++ b/src/Magnum/MeshTools/CompressIndices.h @@ -65,9 +65,9 @@ std::tuple> MAGNUM_MESHTOO @param indices Index array The same as @ref compressIndices(const std::vector&), but this -function writes the output to given buffer and calls @ref Mesh::setIndexCount() -and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for -mesh index configuration. +function writes the output to given buffer and calls @ref Mesh::setCount() and +@ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh +index configuration. @see @ref MeshTools::interleave(), @ref MeshTools::compile() */ diff --git a/src/Magnum/MeshTools/FullScreenTriangle.cpp b/src/Magnum/MeshTools/FullScreenTriangle.cpp index 5d3b728bf..b7ce1cc63 100644 --- a/src/Magnum/MeshTools/FullScreenTriangle.cpp +++ b/src/Magnum/MeshTools/FullScreenTriangle.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace MeshTools { std::pair, Mesh> fullScreenTriangle(Version version) { Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(3); + .setCount(3); std::unique_ptr buffer; #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index d14913d5d..2c623cbb4 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -184,9 +184,10 @@ template std::tuple interleaveInt @param usage Vertex buffer usage @param attributes Attribute arrays and gaps -The same as @ref interleave(const T&, const U&...), but this function writes the -output to given array buffer and updates vertex count in the mesh accordingly, -so you don't have to call @ref Mesh::setVertexCount() on your own. +The same as @ref interleave(const T&, const U&...), but this function also +writes the output to given array buffer. If given mesh is not indexed, it also +updates vertex count in the mesh accordingly, so you don't have to call +@ref Mesh::setCount() on your own. @attention You still must call @ref Mesh::setPrimitive() and @ref Mesh::addVertexBuffer() on the mesh afterwards. @@ -199,7 +200,7 @@ template void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usa std::size_t attributeCount; std::tie(attributeCount, std::ignore, data) = interleave(attributes...); - mesh.setVertexCount(attributeCount); + if(!mesh.isIndexed()) mesh.setCount(attributeCount); buffer.setData(data, usage); } @@ -210,11 +211,11 @@ Simplified specialization of the above function for only one attribute array, equivalent to the following: @code buffer.setData(attribute, usage); -mesh.setVertexCount(attribute.size()); +if(!mesh.isIndexed()) mesh.setVertexCount(attribute.size()); @endcode */ template typename std::enable_if::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { - mesh.setVertexCount(attribute.size()); + if(!mesh.isIndexed()) mesh.setCount(attribute.size()); buffer.setData(attribute, usage); } diff --git a/src/Magnum/MeshView.cpp b/src/Magnum/MeshView.cpp index 893b50c02..fdcfeef32 100644 --- a/src/Magnum/MeshView.cpp +++ b/src/Magnum/MeshView.cpp @@ -36,7 +36,7 @@ MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt, UnsignedInt #endif { _indexOffset = _original->_indexOffset + first*_original->indexSize(); - _indexCount = count; + _count = count; #ifndef MAGNUM_TARGET_GLES2 _indexStart = start; _indexEnd = end; @@ -48,18 +48,18 @@ void MeshView::draw(AbstractShaderProgram& shader) { shader.use(); #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + _original->drawInternal(_count, _firstVertex, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); + _original->drawInternal(_count, _firstVertex, _indexOffset); #endif } #ifdef MAGNUM_BUILD_DEPRECATED void MeshView::draw() { #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount, _indexStart, _indexEnd); + _original->drawInternal(_count, _firstVertex, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_firstVertex, _vertexCount, _indexOffset, _indexCount); + _original->drawInternal(_count, _firstVertex, _indexOffset); #endif } #endif diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index d283d6410..53e510188 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -83,7 +83,7 @@ class MAGNUM_EXPORT MeshView { */ MeshView& setVertexRange(Int first, Int count) { _firstVertex = first; - _vertexCount = count; + _count = count; return *this; } @@ -135,14 +135,14 @@ class MAGNUM_EXPORT MeshView { private: Mesh* _original; - Int _firstVertex, _vertexCount, _indexCount; + Int _firstVertex, _count; GLintptr _indexOffset; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif }; -inline MeshView::MeshView(Mesh& original): _original(&original), _firstVertex(0), _vertexCount(0), _indexCount(0), _indexOffset(0) +inline MeshView::MeshView(Mesh& original): _original(&original), _firstVertex(0), _count(0), _indexOffset(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index f9a608780..803f0591f 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -393,8 +393,8 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.bind(FramebufferTarget::ReadDraw); - mesh.setVertexCount(2) - .setPrimitive(MeshPrimitive::Points); + mesh.setPrimitive(MeshPrimitive::Points) + .setCount(2); /* Skip first vertex so we test also offsets */ MeshView(mesh).setVertexRange(1, 1).draw(shader); @@ -1147,8 +1147,8 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); framebuffer.bind(FramebufferTarget::ReadDraw); - mesh.setIndexCount(2) - .setPrimitive(MeshPrimitive::Points); + mesh.setPrimitive(MeshPrimitive::Points) + .setCount(2); /* Skip first vertex so we test also offsets */ MeshView(mesh).setIndexRange(1, 1).draw(MultipleShader{}); diff --git a/src/Magnum/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/Test/PrimitiveQueryGLTest.cpp index d2509454e..7099cd0ae 100644 --- a/src/Magnum/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/Test/PrimitiveQueryGLTest.cpp @@ -88,7 +88,7 @@ void PrimitiveQueryGLTest::query() { Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(9) + .setCount(9) .addVertexBuffer(vertices, 0, MyShader::Position()); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Magnum/Test/SampleQueryGLTest.cpp b/src/Magnum/Test/SampleQueryGLTest.cpp index 39b6ffdd6..1d5acb6fd 100644 --- a/src/Magnum/Test/SampleQueryGLTest.cpp +++ b/src/Magnum/Test/SampleQueryGLTest.cpp @@ -112,7 +112,7 @@ void SampleQueryGLTest::querySamplesPassed() { Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(3) + .setCount(3) .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); MyShader shader; @@ -161,7 +161,7 @@ void SampleQueryGLTest::conditionalRender() { Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(3) + .setCount(3) .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); MyShader shader; diff --git a/src/Magnum/Text/Renderer.cpp b/src/Magnum/Text/Renderer.cpp index 2256ecd9c..ed767bca0 100644 --- a/src/Magnum/Text/Renderer.cpp +++ b/src/Magnum/Text/Renderer.cpp @@ -215,7 +215,7 @@ std::tuple renderInternal(AbstractFont& font, const GlyphCache& c in subclass) */ Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setIndexCount(indexCount) + .setCount(indexCount) .setIndexBuffer(indexBuffer, 0, indexType, 0, vertices.size()); return std::make_tuple(std::move(mesh), rectangle); @@ -342,7 +342,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert #ifdef CORRADE_TARGET_EMSCRIPTEN _vertexBufferData = Containers::Array(vertexCount*sizeof(Vertex)); #endif - _mesh.setVertexCount(0); + _mesh.setCount(0); /* Render indices */ Containers::Array indexData; @@ -354,7 +354,7 @@ void AbstractRenderer::reserve(const uint32_t glyphCount, const BufferUsage vert #ifdef CORRADE_TARGET_EMSCRIPTEN _indexBufferData = Containers::Array(indexData.size()); #endif - _mesh.setIndexCount(0) + _mesh.setCount(0) .setIndexBuffer(_indexBuffer, 0, indexType, 0, vertexCount); /* Prefill index buffer */ @@ -386,7 +386,7 @@ void AbstractRenderer::render(const std::string& text) { bufferUnmapImplementation(_vertexBuffer); /* Update index count */ - _mesh.setIndexCount(indexCount); + _mesh.setCount(indexCount); } #ifndef DOXYGEN_GENERATING_OUTPUT diff --git a/src/Magnum/TextureTools/DistanceField.cpp b/src/Magnum/TextureTools/DistanceField.cpp index ccb2aefd6..1145732bd 100644 --- a/src/Magnum/TextureTools/DistanceField.cpp +++ b/src/Magnum/TextureTools/DistanceField.cpp @@ -179,7 +179,7 @@ void distanceField(Texture2D& input, Texture2D& output, const Range2Di& rectangl Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) - .setVertexCount(3); + .setCount(3); /* Older GLSL doesn't have gl_VertexID, vertices must be supplied explicitly */ Buffer buffer; From 7c2ef760486c00fa558a00156066f7c36b3143d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 20 Apr 2014 11:26:51 +0200 Subject: [PATCH 29/46] Ability to specify base vertex in Mesh. The well-known issue is that gl*DrawElements*BaseVertex() is not supported in OpenGL ES. It is possible to work around it by reconfiguring whole VAO, but that seems to be a bit overkill. Currently the draw() function just asserts that base vertex is not specified for indexed meshes. --- doc/opengl-mapping.dox | 3 +-- src/Magnum/Mesh.cpp | 44 +++++++++++++++++++++++++++++------------- src/Magnum/Mesh.h | 34 +++++++++++++++++++++++--------- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 2f5ad439d..2014e2859 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -103,10 +103,9 @@ OpenGL function | Matching API @fn_gl{DetachShader} | | @fn_gl{DispatchCompute} | | @fn_gl{DispatchComputeIndirect} | | -@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements} | @ref Mesh::draw() +@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | @ref Mesh::draw(), \n @ref MeshView::draw() @fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | | -@fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | | @fn_gl{DrawBuffer}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() @fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | @fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature() diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index cc5bbc0ec..e31755309 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -72,7 +72,7 @@ std::size_t Mesh::indexSize(IndexType type) { CORRADE_ASSERT_UNREACHABLE(); } -Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0) +Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif @@ -167,9 +167,9 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi } #ifndef MAGNUM_TARGET_GLES2 -void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) +void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) #else -void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) +void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset) #endif { /* Nothing to draw */ @@ -178,18 +178,36 @@ void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) (this->*Context::current()->state().mesh->bindImplementation)(); /* Non-indexed mesh */ - if(!_indexBuffer) - glDrawArrays(GLenum(_primitive), firstVertex, count); + if(!_indexBuffer) { + glDrawArrays(GLenum(_primitive), baseVertex, count); - #ifndef MAGNUM_TARGET_GLES2 - /* Indexed mesh with specified range */ - else if(indexEnd) - glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); - #endif + /* Indexed mesh with base vertex */ + } else if(baseVertex) { + #ifndef MAGNUM_TARGET_GLES + /* Indexed mesh with specified range */ + if(indexEnd) { + glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + + /* Indexed mesh without specified range */ + } else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + #else + CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", ); + #endif + + /* Indexed mesh without base vertex */ + } else { + /* Indexed mesh with specified range */ + #ifndef MAGNUM_TARGET_GLES2 + if(indexEnd) { + glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); - /* Indexed mesh without specified range */ - else - glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + /* Indexed mesh without specified range */ + } else + #endif + { + glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + } + } (this->*Context::current()->state().mesh->unbindImplementation)(); } diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index c731de8a4..6487fa391 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -318,7 +318,6 @@ drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @ref draw() for more information. @todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. -@todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ class MAGNUM_EXPORT Mesh: public AbstractObject { friend class MeshView; @@ -501,6 +500,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { return *this; } + /** @brief Base vertex */ + Int baseVertex() const { return _baseVertex; } + + /** + * @brief Set base vertex + * + * Sets number of vertices of which the vertex buffer will be offset + * when drawing. + * @requires_gl Desktop OpenGL is required for base vertex + * specification in indexed meshes. + */ + Mesh& setBaseVertex(Int baseVertex) { + _baseVertex = baseVertex; + return *this; + } + #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief count() @@ -655,15 +670,16 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} - * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements} + * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}/ + * @fn_gl{DrawElementsBaseVertex}/@fn_gl{DrawRangeElementsBaseVertex} */ void draw(AbstractShaderProgram& shader) { shader.use(); #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); + drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, 0, _indexOffset); + drawInternal(_count, _baseVertex, _indexOffset); #endif } @@ -677,9 +693,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { */ CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() { #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); + drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, 0, _indexOffset); + drawInternal(_count, _baseVertex, _indexOffset); #endif } #endif @@ -800,9 +816,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #ifndef MAGNUM_TARGET_GLES2 - void drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); + void drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); #else - void drawInternal(Int count, Int firstVertex, GLintptr indexOffset); + void drawInternal(Int count, Int baseVertex, GLintptr indexOffset); #endif void MAGNUM_LOCAL createImplementationDefault(); @@ -842,7 +858,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLuint _id; MeshPrimitive _primitive; - Int _count; + Int _count, _baseVertex; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif From 5e06b776cf911e4579c9e790233d888efb5ce47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 20 Apr 2014 13:56:24 +0200 Subject: [PATCH 30/46] Updated MeshView to reflect changes in Mesh. Added base vertex specification, not differentiating between vertex and index count. The old setVertexRange(), setIndexRange(4) and setIndexRange(2) are now aliases to new setCount(), setBaseVertex(), setIndexRange(3) and setIndexRangge(1) functions, are marked as deprecated and will be removed in future release. --- .../Implementation/CapsuleRenderer.cpp | 18 ++- src/Magnum/MeshView.cpp | 20 +--- src/Magnum/MeshView.h | 107 ++++++++++++++---- 3 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp index 2c46cd430..5c359e593 100644 --- a/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/CapsuleRenderer.cpp @@ -46,21 +46,24 @@ AbstractCapsuleRenderer<2>::AbstractCapsuleRenderer(): AbstractShapeRenderer<2>( /* Bottom hemisphere */ if(!(bottom = ResourceManager::instance().get("capsule2d-bottom"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(0, rings*4, 0, rings*2+1); + view->setCount(rings*4) + .setIndexRange(0, 0, rings*2+1); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Cylinder */ if(!(cylinder = ResourceManager::instance().get("capsule2d-cylinder"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(rings*4, 4, rings*2+1, rings*2+3); + view->setCount(4) + .setIndexRange(rings*4, rings*2+1, rings*2+3); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Top hemisphere */ if(!(top = ResourceManager::instance().get("capsule2d-top"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(rings*4+4, rings*4, rings*2+3, rings*4+4); + view->setCount(rings*4) + .setIndexRange(rings*4+4, rings*2+3, rings*4+4); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } } @@ -73,21 +76,24 @@ AbstractCapsuleRenderer<3>::AbstractCapsuleRenderer(): AbstractShapeRenderer<3>( /* Bottom hemisphere */ if(!(bottom = ResourceManager::instance().get("capsule3d-bottom"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(0, rings*8, 0, rings*4+1); + view->setCount(rings*8) + .setIndexRange(0, 0, rings*4+1); ResourceManager::instance().set(bottom.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Cylinder */ if(!(cylinder = ResourceManager::instance().get("capsule3d-cylinder"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(rings*8, segments*4+8, rings*4+1, rings*4+segments*2+5); + view->setCount(segments*4+8) + .setIndexRange(rings*8, rings*4+1, rings*4+segments*2+5); ResourceManager::instance().set(cylinder.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } /* Top */ if(!(top = ResourceManager::instance().get("capsule3d-top"))) { auto view = new MeshView(*wireframeMesh); - view->setIndexRange(rings*8+segments*4+8, rings*8, rings*4+segments*2+5, rings*8+segments*2+6); + view->setCount(rings*8) + .setIndexRange(rings*8+segments*4+8, rings*4+segments*2+5, rings*8+segments*2+6); ResourceManager::instance().set(top.key(), view, ResourceDataState::Final, ResourcePolicy::Manual); } } diff --git a/src/Magnum/MeshView.cpp b/src/Magnum/MeshView.cpp index fdcfeef32..c935612c1 100644 --- a/src/Magnum/MeshView.cpp +++ b/src/Magnum/MeshView.cpp @@ -29,18 +29,8 @@ namespace Magnum { -#ifndef MAGNUM_TARGET_GLES2 -MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end) -#else -MeshView& MeshView::setIndexRange(Int first, Int count, UnsignedInt, UnsignedInt) -#endif -{ +MeshView& MeshView::setIndexRange(Int first) { _indexOffset = _original->_indexOffset + first*_original->indexSize(); - _count = count; - #ifndef MAGNUM_TARGET_GLES2 - _indexStart = start; - _indexEnd = end; - #endif return *this; } @@ -48,18 +38,18 @@ void MeshView::draw(AbstractShaderProgram& shader) { shader.use(); #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_count, _firstVertex, _indexOffset, _indexStart, _indexEnd); + _original->drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_count, _firstVertex, _indexOffset); + _original->drawInternal(_count, _baseVertex, _indexOffset); #endif } #ifdef MAGNUM_BUILD_DEPRECATED void MeshView::draw() { #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_count, _firstVertex, _indexOffset, _indexStart, _indexEnd); + _original->drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_count, _firstVertex, _indexOffset); + _original->drawInternal(_count, _baseVertex, _indexOffset); #endif } #endif diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 53e510188..90cb6b172 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -72,48 +72,102 @@ class MAGNUM_EXPORT MeshView { MeshView& operator=(MeshView&& other) = delete; /** - * @brief Set vertex range - * @param first First vertex - * @param count Vertex count + * @brief Set vertex/index count * @return Reference to self (for method chaining) * - * Default is zero @p offset and zero @p count. If index range is - * non-zero, vertex range is ignored, see main class documentation for - * more information. + * Default is `0`. */ - MeshView& setVertexRange(Int first, Int count) { - _firstVertex = first; + MeshView& setCount(Int count) { _count = count; return *this; } + /** + * @brief Set base vertex + * + * Sets number of vertices of which the vertex buffer will be offset + * when drawing. Default is `0`. + * @requires_gl Desktop OpenGL is required for base vertex + * specification in indexed meshes. + */ + MeshView& setBaseVertex(Int baseVertex) { + _baseVertex = baseVertex; + return *this; + } + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Set vertex range + * @param first First vertex + * @param count Vertex count + * + * @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and + * @ref Magnum::MeshView::setBaseVertex() "setBaseVertex()" + * instead. + */ + CORRADE_DEPRECATED("use setCount() and setBaseVertex() instead") MeshView& setVertexRange(Int first, Int count) { + return setCount(count), setBaseVertex(first); + } + #endif + + /** + * @brief Set index range + * @param first First vertex + * @param start Minimum array index contained in the buffer + * @param end Maximum array index contained in the buffer + * @return Reference to self (for method chaining) + * + * The @p start and @p end parameters may help to improve memory access + * performance, as only a portion of vertex buffer needs to be + * acccessed. On OpenGL ES 2.0 this function behaves the same as + * @ref setIndexRange(Int), as index range functionality is not + * available there. + * @see @ref setCount() + */ + MeshView& setIndexRange(Int first, UnsignedInt start, UnsignedInt end); + + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Set index range * @param first First index * @param count Index count * @param start Minimum array index contained in the buffer * @param end Maximum array index contained in the buffer + * + * @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and + * @ref Magnum::MeshView::setIndexRange(Int, UnsignedInt, UnsignedInt) "setIndexRange(Int, UnsignedInt, UnsignedInt)" + * instead. + */ + CORRADE_DEPRECATED("use setCount() and setIndexRange(Int, UnsignedInt, UnsignedInt) instead") MeshView& setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end) { + return setCount(count), setIndexRange(first, start, end); + } + #endif + + /** + * @brief Set index range + * @param first First index * @return Reference to self (for method chaining) * - * Specifying `0` for both @p start and @p end behaves the same as - * @ref setIndexRange(Int, Int). On OpenGL ES 2.0 this function behaves - * always as @ref setIndexRange(Int, Int), as this functionality is - * not available there. + * Prefer to use @ref setIndexRange(Int, UnsignedInt, UnsignedInt) for + * better performance. + * @see @ref setCount() */ - MeshView& setIndexRange(Int first, Int count, UnsignedInt start, UnsignedInt end); + MeshView& setIndexRange(Int first); + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Set index range * @param first First index * @param count Index count - * @return Reference to self (for method chaining) * - * Prefer to use @ref setIndexRange(Int, Int, UnsignedInt, UnsignedInt) - * for better performance. + * @deprecated Use @ref Magnum::MeshView::setCount() "setCount()" and + * @ref Magnum::MeshView::setIndexRange(Int) "setIndexRange(Int)" + * instead. */ - MeshView& setIndexRange(Int first, Int count) { - return setIndexRange(first, count, 0, 0); + CORRADE_DEPRECATED("use setCount() and setIndexRange(Int) instead") MeshView& setIndexRange(Int first, Int count) { + return setCount(count), setIndexRange(first); } + #endif /** * @brief Draw the mesh @@ -135,19 +189,32 @@ class MAGNUM_EXPORT MeshView { private: Mesh* _original; - Int _firstVertex, _count; + Int _count, _baseVertex; GLintptr _indexOffset; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif }; -inline MeshView::MeshView(Mesh& original): _original(&original), _firstVertex(0), _count(0), _indexOffset(0) +inline MeshView::MeshView(Mesh& original): _original(&original), _count(0), _baseVertex(0), _indexOffset(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif {} +inline MeshView& MeshView::setIndexRange(Int first, UnsignedInt start, UnsignedInt end) { + setIndexRange(first); + #ifndef MAGNUM_TARGET_GLES2 + _indexStart = start; + _indexEnd = end; + #else + static_cast(start); + static_cast(end); + #endif + return *this; +} + + } #endif From 2834e6029e8286fa10811bda5e9f208626caf425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 20 Apr 2014 13:59:07 +0200 Subject: [PATCH 31/46] Added test for mesh base vertex. --- src/Magnum/Test/MeshGLTest.cpp | 72 +++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 803f0591f..5ff11396d 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -106,6 +106,10 @@ class MeshGLTest: public AbstractOpenGLTester { void setIndexBuffer(); void setIndexBufferRange(); void setIndexBufferUnsignedInt(); + + #ifndef MAGNUM_TARGET_GLES + void setBaseVertex(); + #endif }; MeshGLTest::MeshGLTest() { @@ -168,7 +172,12 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::setIndexBuffer, &MeshGLTest::setIndexBufferRange, - &MeshGLTest::setIndexBufferUnsignedInt}); + &MeshGLTest::setIndexBufferUnsignedInt, + + #ifndef MAGNUM_TARGET_GLES + &MeshGLTest::setBaseVertex + #endif + }); } void MeshGLTest::construct() { @@ -397,7 +406,7 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh .setCount(2); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setVertexRange(1, 1).draw(shader); + MeshView(mesh).setCount(1).setBaseVertex(1).draw(shader); } template T Checker::get(ColorFormat format, ColorType type) { @@ -1108,7 +1117,7 @@ void MeshGLTest::addVertexBufferMultipleGaps() { namespace { struct IndexChecker { - explicit IndexChecker(Mesh& mesh); + explicit IndexChecker(Mesh& mesh, Int baseVertex = 0); Color4ub get(); Renderbuffer renderbuffer; @@ -1138,7 +1147,7 @@ namespace { } #ifndef DOXYGEN_GENERATING_OUTPUT -IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { +IndexChecker::IndexChecker(Mesh& mesh, Int baseVertex): framebuffer({{}, Vector2i(1)}) { #ifndef MAGNUM_TARGET_GLES2 renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(1)); #else @@ -1151,7 +1160,7 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { .setCount(2); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setIndexRange(1, 1).draw(MultipleShader{}); + MeshView(mesh).setCount(1).setBaseVertex(baseVertex).setIndexRange(1).draw(MultipleShader{}); } Color4ub IndexChecker::get() { @@ -1229,6 +1238,59 @@ void MeshGLTest::setIndexBufferUnsignedInt() { CORRADE_COMPARE(value, indexedResult); } +#ifndef MAGNUM_TARGET_GLES +void MeshGLTest::setBaseVertex() { + const Float indexedVertexData[] = { + 0.0f, 0.0f, /* Offset */ + + /* First attribute */ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + + /* Second attribute */ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + + /* Third attribute */ + Math::normalize(64), + Math::normalize(17), + Math::normalize(56), + Math::normalize(15), + Math::normalize(164), + Math::normalize(17), + Math::normalize(97), + Math::normalize(28), + + /* Fourth attribute */ + 0.3f, 0.1f, 0.5f, + 0.4f, 0.0f, -0.9f, + 1.0f, -0.5f + }; + + Buffer vertices; + vertices.setData(indexedVertexData, BufferUsage::StaticDraw); + + constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + Buffer indices(Buffer::Target::ElementArray); + indices.setData(indexData, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), + MultipleShader::Normal(), MultipleShader::TextureCoordinates()) + .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + + /* base vertex is 2 */ + const auto value = IndexChecker(mesh, 2).get(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, indexedResult); +} +#endif + }} CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) From 51a14b9e0b5c5df1af69d10dcc1c264fbc80441e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 23 Apr 2014 20:58:41 +0200 Subject: [PATCH 32/46] MeshTools: deprecate mesh/buffer-modifying vertex/index tools. The point of this change is to allow greater flexibility and reduce confusion. When instanced meshes are implemented, MeshTools::interleave() can be used for creating interleaved buffers with per-instance data and then the call to Mesh::setCount() will be harmful and/or confusing, becuase the user would in fact want to call Mesh::setInstanceCount() instead. Similarly, MeshTools::compressIndices() can be used to create index buffer for more than one mesh. GL 4.4 has ARB_buffer_storage, which (in relatively distant future) will mean that the current way of Buffer::setData() will be deprecated in favor of Buffer::setStorage(), similarly as Texture::setStorage() replaced Texture::setImage(). Thus any function which calls Buffer::setData() internally is not future-proof. The old MeshTools::compressIndices() and MeshTools::interleave() overloads are marked as deprecated and will be removed in future release. --- .../Implementation/AbstractShapeRenderer.cpp | 22 ++++- src/Magnum/DebugTools/ObjectRenderer.cpp | 3 +- src/Magnum/Mesh.h | 89 +++++++++++-------- src/Magnum/MeshTools/Compile.cpp | 43 +++++---- src/Magnum/MeshTools/CompressIndices.cpp | 47 +++++----- src/Magnum/MeshTools/CompressIndices.h | 35 +++++--- src/Magnum/MeshTools/Interleave.h | 84 +++++++++-------- .../MeshTools/Test/CompressIndicesTest.cpp | 33 +++---- src/Magnum/MeshTools/Test/InterleaveTest.cpp | 23 +---- 9 files changed, 216 insertions(+), 163 deletions(-) diff --git a/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp b/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp index fee897954..0258e6609 100644 --- a/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp +++ b/src/Magnum/DebugTools/Implementation/AbstractShapeRenderer.cpp @@ -59,8 +59,17 @@ template<> void create<2>(Trade::MeshData2D& data, Resource& meshResource, /* Index buffer, if needed, if not, resource key doesn't have to be set */ if(data.isIndexed()) { CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey()); + + Containers::Array indexData; + Mesh::IndexType indexType; + UnsignedInt indexStart, indexEnd; + std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices()); + Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); - MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); + indexBuffer->setData(indexData, BufferUsage::StaticDraw); + mesh->setCount(data.indices().size()) + .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); + ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); /* The mesh is not indexed, set proper vertex count */ @@ -82,8 +91,17 @@ template<> void create<3>(Trade::MeshData3D& data, Resource& meshResource, /* Index buffer, if needed, if not, resource key doesn't have to be set */ if(data.isIndexed()) { CORRADE_INTERNAL_ASSERT(indexBufferResource.key() != ResourceKey()); + + Containers::Array indexData; + Mesh::IndexType indexType; + UnsignedInt indexStart, indexEnd; + std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(data.indices()); + Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); - MeshTools::compressIndices(*mesh, *indexBuffer, BufferUsage::StaticDraw, data.indices()); + indexBuffer->setData(indexData, BufferUsage::StaticDraw); + mesh->setCount(data.indices().size()) + .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); + ResourceManager::instance().set(indexBufferResource.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); /* The mesh is not indexed, set proper vertex count */ diff --git a/src/Magnum/DebugTools/ObjectRenderer.cpp b/src/Magnum/DebugTools/ObjectRenderer.cpp index b3f1d2b2f..ee3da5fce 100644 --- a/src/Magnum/DebugTools/ObjectRenderer.cpp +++ b/src/Magnum/DebugTools/ObjectRenderer.cpp @@ -26,6 +26,7 @@ #include "ObjectRenderer.h" #include "Magnum/Buffer.h" +#include "Magnum/Mesh.h" #include "Magnum/DebugTools/ResourceManager.h" #include "Magnum/MeshTools/Interleave.h" #include "Magnum/SceneGraph/AbstractCamera.h" @@ -159,7 +160,7 @@ template ObjectRenderer::ObjectRenderer(Scen Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); Mesh* mesh = new Mesh; - MeshTools::interleave(*mesh, *vertexBuffer, BufferUsage::StaticDraw, Renderer::positions, Renderer::colors); + vertexBuffer->setData(MeshTools::interleave(Renderer::positions, Renderer::colors), BufferUsage::StaticDraw); ResourceManager::instance().set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); indexBuffer->setData(Renderer::indices, BufferUsage::StaticDraw); diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 6487fa391..b2bafd179 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -127,16 +127,15 @@ You have to specify at least primitive and vertex/index count using data, add them to the mesh and specify @ref AbstractShaderProgram::Attribute "shader attribute" layout inside the buffers using @ref addVertexBuffer(). You can also use -@ref MeshTools::interleave() conveniently fill interleaved vertex buffer. -The function itself calls @ref setCount(), so you don't have to, but you still -have to specify the primitive using @ref setPrimitive() and the layout using -@ref addVertexBuffer(). +@ref MeshTools::interleave() to conveniently interleave vertex data. If you want indexed mesh, fill your index buffer with data and specify its layout using @ref setIndexBuffer(). You can also use @ref MeshTools::compressIndices() -to conveniently compress the indices, fill the index buffer and configure the -mesh. It will call @ref setCount() and @ref setIndexBuffer(), so you don't have -to do anything else. +to conveniently compress the indices based on the range used. + +There is also @ref MeshTools::compile() function which operates directly on +@ref Trade::MeshData2D / @ref Trade::MeshData3D and returns fully configured +mesh and vertex/index buffers for use with stock shaders. Note that neither vertex buffers nor index buffer is managed (e.g. deleted on destruction) by the mesh, so you have to manage them on your own and ensure @@ -159,19 +158,19 @@ class MyShader: public AbstractShaderProgram { // ... }; -Buffer vertexBuffer; -Mesh mesh; // Fill vertex buffer with position data static constexpr Vector3 positions[30] = { // ... }; +Buffer vertexBuffer; vertexBuffer.setData(positions, BufferUsage::StaticDraw); -// Set primitive and vertex count, add the buffer and specify its layout +// Configure the mesh, add vertex buffer +Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .setCount(30) - .addVertexBuffer(vertexBuffer, 0, MyShader::Position()); + .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}); @endcode @subsubsection Mesh-configuration-examples-nonindexed-phong Interleaved vertex data @@ -179,17 +178,16 @@ mesh.setPrimitive(MeshPrimitive::Triangles) @code // Non-indexed primitive with positions and normals Trade::MeshData3D plane = Primitives::Plane::solid(); -Buffer vertexBuffer; -Mesh mesh; // Fill vertex buffer with interleaved position and normal data -MeshTools::interleave(mesh, buffer, BufferUsage::StaticDraw, - plane.positions(0), plane.normals(0)); +Buffer vertexBuffer; +vertexBuffer.setData(MeshTools::interleave(plane.positions(0), plane.normals(0)), BufferUsage::StaticDraw); -// Set primitive and specify layout of interleaved vertex buffer, vertex count -// has been already set by MeshTools::interleave() +// Configure the mesh, add vertex buffer +Mesh mesh; mesh.setPrimitive(plane.primitive()) - .addVertexBuffer(buffer, 0, Shaders::Phong::Position(), Shaders::Phong::Normal()); + .setCount(plane.positions(0).size()) + .addVertexBuffer(buffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}); @endcode @subsubsection Mesh-configuration-examples-indexed-phong Indexed mesh @@ -202,48 +200,60 @@ class MyShader: public AbstractShaderProgram { // ... }; -Buffer vertexBuffer, indexBuffer; -Mesh mesh; // Fill vertex buffer with position data static constexpr Vector3 positions[300] = { // ... }; +Buffer vertexBuffer; vertexBuffer.setData(positions, BufferUsage::StaticDraw); // Fill index buffer with index data static constexpr GLubyte indices[75] = { // ... }; +Buffer indexBuffer; indexBuffer.setData(indices, BufferUsage::StaticDraw); -// Set primitive, index count, specify the buffers +// Configure the mesh, add both vertex and index buffer +Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .setCount(75) - .addVertexBuffer(vertexBuffer, 0, MyShader::Position()) + .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}) .setIndexBuffer(indexBuffer, 0, Mesh::IndexType::UnsignedByte, 176, 229); @endcode +Or using @ref MeshTools::interleave() and @ref MeshTools::compressIndices(): + @code // Indexed primitive Trade::MeshData3D cube = Primitives::Cube::solid(); -Buffer vertexBuffer, indexBuffer; -Mesh mesh; // Fill vertex buffer with interleaved position and normal data -MeshTools::interleave(mesh, vertexBuffer, BufferUsage::StaticDraw, - cube.positions(0), cube.normals(0)); +Buffer vertexBuffer; +vertexBuffer.setData(MeshTools::interleave(cube.positions(0), cube.normals(0)), BufferUsage::StaticDraw); -// Fill index buffer with compressed index data -MeshTools::compressIndices(mesh, indexBuffer, BufferUsage::StaticDraw, - cube.indices()); +// Compress index data +Containers::Array indexData; +Mesh::IndexType indexType; +UnsignedInt indexStart, indexEnd; +std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(cube.indices()); -// Set primitive and specify layout of interleaved vertex buffer. Index count -// and index buffer has been already specified by MeshTools::compressIndices(). +// Fill index buffer +Buffer indexBuffer; +indexBuffer.setData(data); + +// Configure the mesh, add both vertex and index buffer +Mesh mesh; mesh.setPrimitive(plane.primitive()) - .addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position(), Shaders::Phong::Normal()); + .setCount(cube.indices().size()) + .addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}) + .setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd); @endcode +Or, if you plan to use the mesh with stock shaders, you can just use +@ref MeshTools::compile(). + @subsubsection Mesh-configuration-examples-data-options Specific formats of vertex data @code @@ -255,34 +265,39 @@ class MyShader: public AbstractShaderProgram { // ... }; + +// Initial mesh configuration Mesh mesh; +mesh.setPrimitive(...) + .setCount(30); // Fill position buffer with positions specified as two-component XY (i.e., // no Z component, which is meant to be always 0) -Buffer positionBuffer; Vector2 positions[30] = { // ... }; +Buffer positionBuffer; +positionBuffer.setData(positions, BufferUsage::StaticDraw); // Specify layout of positions buffer -- only two components, unspecified Z // component will be automatically set to 0 mesh.addVertexBuffer(positionBuffer, 0, - MyShader::Position(MyShader::Position::Components::Two)); + MyShader::Position{MyShader::Position::Components::Two}); // Fill color buffer with colors specified as four-byte BGRA (e.g. directly // from TGA file) -Buffer colorBuffer; GLubyte colors[4*30] = { // ... }; +Buffer colorBuffer; colorBuffer.setData(colors, BufferUsage::StaticDraw); // Specify layout of color buffer -- BGRA, each component unsigned byte and we // want to normalize them from [0, 255] to [0.0f, 1.0f] -mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color( +mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color{ MyShader::Color::Components::BGRA, MyShader::Color::DataType::UnsignedByte, - MyShader::Color::DataOption::Normalized)); + MyShader::Color::DataOption::Normalized}); @endcode @section Mesh-drawing Rendering meshes diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index 3b42aa07b..b7243cf79 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/src/Magnum/MeshTools/Compile.cpp @@ -25,6 +25,7 @@ #include "Compile.h" +#include "Magnum/Buffer.h" #include "Magnum/Math/Vector3.h" #include "Magnum/MeshTools/CompressIndices.h" #include "Magnum/MeshTools/Interleave.h" @@ -51,9 +52,7 @@ std::tuple, std::unique_ptr> compile(const std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; /* Interleave positions */ - std::size_t vertexCount; - Containers::Array data; - std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + Containers::Array data = MeshTools::interleave( meshData.positions(0), stride - sizeof(Shaders::Generic2D::Position::Type)); mesh.addVertexBuffer(*vertexBuffer, 0, @@ -73,16 +72,23 @@ std::tuple, std::unique_ptr> compile(const } /* Fill vertex buffer with interleaved data */ - vertexBuffer->setData(data, BufferUsage::StaticDraw); + vertexBuffer->setData(data, usage); - /* Fill index buffer */ + /* If indexed, fill index buffer and configure indexed mesh */ std::unique_ptr indexBuffer; if(meshData.isIndexed()) { + Containers::Array indexData; + Mesh::IndexType indexType; + UnsignedInt indexStart, indexEnd; + std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices()); + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); - MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + indexBuffer->setData(data, usage); + mesh.setCount(meshData.indices().size()) + .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); - /* Else set proper vertex count */ - } else mesh.setCount(vertexCount); + /* Else set vertex count */ + } else mesh.setCount(meshData.positions(0).size()); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); } @@ -106,9 +112,7 @@ std::tuple, std::unique_ptr> compile(const std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; /* Interleave positions */ - std::size_t vertexCount; - Containers::Array data; - std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + Containers::Array data = MeshTools::interleave( meshData.positions(0), stride - sizeof(Shaders::Generic3D::Position::Type)); mesh.addVertexBuffer(*vertexBuffer, 0, @@ -140,16 +144,23 @@ std::tuple, std::unique_ptr> compile(const } /* Fill vertex buffer with interleaved data */ - vertexBuffer->setData(data, BufferUsage::StaticDraw); + vertexBuffer->setData(data, usage); - /* Fill index buffer */ + /* If indexed, fill index buffer and configure indexed mesh */ std::unique_ptr indexBuffer; if(meshData.isIndexed()) { + Containers::Array indexData; + Mesh::IndexType indexType; + UnsignedInt indexStart, indexEnd; + std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(meshData.indices()); + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); - MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + indexBuffer->setData(data, usage); + mesh.setCount(meshData.indices().size()) + .setIndexBuffer(*indexBuffer, 0, indexType, indexStart, indexEnd); - /* Else set proper vertex count */ - } mesh.setCount(vertexCount); + /* Else set vertex count */ + } mesh.setCount(meshData.positions(0).size()); return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); } diff --git a/src/Magnum/MeshTools/CompressIndices.cpp b/src/Magnum/MeshTools/CompressIndices.cpp index d8be145d1..b931af946 100644 --- a/src/Magnum/MeshTools/CompressIndices.cpp +++ b/src/Magnum/MeshTools/CompressIndices.cpp @@ -41,50 +41,53 @@ template<> constexpr Mesh::IndexType indexType() { return Mesh::In template<> constexpr Mesh::IndexType indexType() { return Mesh::IndexType::UnsignedShort; } template<> constexpr Mesh::IndexType indexType() { return Mesh::IndexType::UnsignedInt; } -template inline std::tuple> compress(const std::vector& indices) { +template inline std::pair, Mesh::IndexType> compress(const std::vector& indices) { Containers::Array buffer(indices.size()*sizeof(T)); for(std::size_t i = 0; i != indices.size(); ++i) { T index = static_cast(indices[i]); std::memcpy(buffer.begin()+i*sizeof(T), &index, sizeof(T)); } - return std::make_tuple(indices.size(), indexType(), std::move(buffer)); + return {std::move(buffer), indexType()}; } -std::tuple> compressIndicesInternal(const std::vector& indices, UnsignedInt max) { - switch(Math::log(256, max)) { +} + +std::tuple, Mesh::IndexType, UnsignedInt, UnsignedInt> compressIndices(const std::vector& indices) { + /** @todo Performance hint when range can be represented by smaller value? */ + auto minmax = std::minmax_element(indices.begin(), indices.end()); + std::pair, Mesh::IndexType> typeData; + switch(Math::log(256, *minmax.second)) { case 0: - return compress(indices); + typeData = compress(indices); + break; case 1: - return compress(indices); + typeData = compress(indices); + break; case 2: case 3: - return compress(indices); + typeData = compress(indices); + break; default: - CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << max << "elements.", {}); + CORRADE_ASSERT(false, "MeshTools::compressIndices(): no type able to index" << *minmax.second << "elements.", {}); } -} - -} -std::tuple> compressIndices(const std::vector& indices) { - return compressIndicesInternal(indices, *std::max_element(indices.begin(), indices.end())); + return std::make_tuple(std::move(typeData.first), typeData.second, *minmax.first, *minmax.second); } +#ifdef MAGNUM_BUILD_DEPRECATED void compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector& indices) { - auto minmax = std::minmax_element(indices.begin(), indices.end()); - - /** @todo Performance hint when range can be represented by smaller value? */ - - std::size_t indexCount; - Mesh::IndexType indexType; Containers::Array data; - std::tie(indexCount, indexType, data) = compressIndicesInternal(indices, *minmax.second); + Mesh::IndexType type; + UnsignedInt start, end; + std::tie(data, type, start, end) = compressIndices(indices); - mesh.setCount(indices.size()) - .setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second); buffer.setData(data, usage); + + mesh.setCount(indices.size()) + .setIndexBuffer(buffer, 0, type, start, end); } +#endif }} diff --git a/src/Magnum/MeshTools/CompressIndices.h b/src/Magnum/MeshTools/CompressIndices.h index 2b3b777f9..75ef1b2e4 100644 --- a/src/Magnum/MeshTools/CompressIndices.h +++ b/src/Magnum/MeshTools/CompressIndices.h @@ -39,24 +39,34 @@ namespace Magnum { namespace MeshTools { /** @brief Compress vertex indices @param indices Index array -@return Index count, type and compressed index array +@return Index range, type and compressed index array This function takes index array and outputs them compressed to smallest possible size. For example when your indices have maximum number 463, it's wasteful to store them in array of 32bit integers, array of 16bit integers is -sufficient. Example usage: +sufficient. + +Example usage: @code -std::size_t indexCount; +std::vector indices; + +Containers::Array indexData; Mesh::IndexType indexType; -Containers::Array data; -std::tie(indexCount, indexType, data) = MeshTools::compressIndices(indices); -@endcode +UnsignedInt indexStart, indexEnd; +std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(indices); + +Buffer indexBuffer; +indexBuffer.setData(indexData, BufferUsage::StaticDraw); -See also @ref compressIndices(Mesh&, Buffer&, BufferUsage, const std::vector&), -which writes the compressed data directly into index buffer of given mesh. +Mesh mesh; +mesh.setCount(indices.size()) + .setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd); +@endcode +@todo Extract IndexType out of Mesh class */ -std::tuple> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector& indices); +std::tuple, Mesh::IndexType, UnsignedInt, UnsignedInt> MAGNUM_MESHTOOLS_EXPORT compressIndices(const std::vector& indices); +#ifdef MAGNUM_BUILD_DEPRECATED /** @brief Compress vertex indices and write them to index buffer @param mesh Output mesh @@ -64,14 +74,17 @@ std::tuple> MAGNUM_MESHTOO @param usage Index buffer usage @param indices Index array +@deprecated Use general-purpose + @ref Magnum::MeshTools::compressIndices(const std::vector&) "compressIndices(const std::vector&)" + instead. + The same as @ref compressIndices(const std::vector&), but this function writes the output to given buffer and calls @ref Mesh::setCount() and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh index configuration. - -@see @ref MeshTools::interleave(), @ref MeshTools::compile() */ void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector& indices); +#endif }} diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 2c623cbb4..5316d5eea 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -30,12 +30,16 @@ */ #include -#include -#include -#include +#include +#include -#include "Magnum/Mesh.h" +#include "Magnum/Magnum.h" + +#ifdef MAGNUM_BUILD_DEPRECATED +#include #include "Magnum/Buffer.h" +#include "Magnum/Mesh.h" +#endif namespace Magnum { namespace MeshTools { @@ -94,20 +98,21 @@ template void writeInterleaved(std::size_t stride, char* st @brief %Interleave vertex attributes This function takes list of attribute arrays and returns them interleaved, so -data for each attribute are in continuous place in memory. Returned tuple -contains attribute count, stride and data array. Deleting the data array is up -to the user. +data for each attribute are in continuous place in memory. -Size of the data buffer can be computed from attribute count and stride, as -shown below. Example usage: +Example usage: @code -std::vector positions; +MeshPrimitive primitive; +std::vector positions; std::vector textureCoordinates; -std::size_t attributeCount; -std::size_t stride; -Containers::Array data; -std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, textureCoordinates); -// ... + +Buffer vertexBuffer; +vertexBuffer.setData(MeshTools::interleave(positions, textureCoordinates), BufferUsage::StaticDraw); + +Mesh mesh; +mesh.setPrimitive(primitive) + .setCount(positions.count()) + .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}, MyShader::TextureCoordinates{}); @endcode It's often desirable to align data for one vertex on 32bit boundaries. To @@ -116,10 +121,8 @@ achieve that, you can specify gaps between the attributes: std::vector positions; std::vector weights; std::vector vertexColors; -std::size_t attributeCount; -std::size_t stride; -Containers::Array data; -std::tie(attributeCount, stride, data) = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1); + +auto data = MeshTools::interleave(positions, weights, 2, textureCoordinates, 1); @endcode All gap bytes are set zero. This way vertex stride is 24 bytes, without gaps it would be 21 bytes, causing possible performance loss. @@ -131,13 +134,13 @@ would be 21 bytes, causing possible performance loss. for) and function `size()` returning count of elements. In most cases it will be `std::vector` or `std::array`. -See also @ref interleave(Mesh&, Buffer&, BufferUsage, const T&...), -which writes the interleaved array directly into buffer of given mesh or -@ref interleaveInto() which writes the data into existing buffer instead of -creating new one. +@see @ref interleaveInto() +@todo remove `std::enable_if` when deprecated overloads are removed */ /* enable_if to avoid clash with overloaded function below */ -template typename std::enable_if::value, std::tuple>>::type interleave(const T& first, const U&... next) { +template typename std::enable_if::value, Containers::Array>::type + interleave(const T& first, const U&... next) +{ /* Compute buffer size and stride */ const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); const std::size_t stride = Implementation::Stride{}(first, next...); @@ -147,10 +150,10 @@ template typename std::enable_if::va Containers::Array data = Containers::Array::zeroInitialized(attributeCount*stride); Implementation::writeInterleaved(stride, data.begin(), first, next...); - return std::make_tuple(attributeCount, stride, std::move(data)); + return data; /* Otherwise return nullptr */ - } else return std::make_tuple(0, stride, nullptr); + } else return nullptr; } /** @@ -165,18 +168,17 @@ parameters. arrays have the same size. The passed buffer must also be large enough to contain the interleaved data. */ -template std::tuple interleaveInto(Containers::ArrayReference buffer, const T& first, const U&... next) { +template void interleaveInto(Containers::ArrayReference buffer, const T& first, const U&... next) { /* Verify expected buffer size */ const std::size_t attributeCount = Implementation::AttributeCount{}(first, next...); const std::size_t stride = Implementation::Stride{}(first, next...); - CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), {}); + CORRADE_ASSERT(attributeCount*stride <= buffer.size(), "MeshTools::interleaveInto(): the data buffer is too small, expected" << attributeCount*stride << "but got" << buffer.size(), ); /* Write data */ Implementation::writeInterleaved(stride, buffer.begin(), first, next...); - - return std::make_tuple(attributeCount, stride); } +#ifdef MAGNUM_BUILD_DEPRECATED /** @brief %Interleave vertex attributes, write them to array buffer and configure the mesh @param mesh Output mesh @@ -184,6 +186,10 @@ template std::tuple interleaveInt @param usage Vertex buffer usage @param attributes Attribute arrays and gaps +@deprecated Use general-purpose + @ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)" + instead. + The same as @ref interleave(const T&, const U&...), but this function also writes the output to given array buffer. If given mesh is not indexed, it also updates vertex count in the mesh accordingly, so you don't have to call @@ -193,20 +199,19 @@ updates vertex count in the mesh accordingly, so you don't have to call @ref Mesh::addVertexBuffer() on the mesh afterwards. @see @ref compressIndices(), @ref compile() -@todo rework so Mesh & Buffer doesn't need to be included in header */ -template void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { - Containers::Array data; - std::size_t attributeCount; - std::tie(attributeCount, std::ignore, data) = interleave(attributes...); - - if(!mesh.isIndexed()) mesh.setCount(attributeCount); - buffer.setData(data, usage); +template CORRADE_DEPRECATED("Use interleave(const T&...) instead") void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { + if(!mesh.isIndexed()) mesh.setCount(Implementation::AttributeCount{}(attributes...)); + buffer.setData(interleave(attributes...), usage); } /** @brief Write vertex attribute to array buffer and configure the mesh +@deprecated Use general-purpose + @ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)" + instead. + Simplified specialization of the above function for only one attribute array, equivalent to the following: @code @@ -214,10 +219,11 @@ buffer.setData(attribute, usage); if(!mesh.isIndexed()) mesh.setVertexCount(attribute.size()); @endcode */ -template typename std::enable_if::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { +template CORRADE_DEPRECATED("Use interleave(const T&...) instead") typename std::enable_if::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { if(!mesh.isIndexed()) mesh.setCount(attribute.size()); buffer.setData(attribute, usage); } +#endif }} diff --git a/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp b/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp index d2b2e6475..83ab2b0a1 100644 --- a/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp +++ b/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp @@ -47,27 +47,29 @@ CompressIndicesTest::CompressIndicesTest() { } void CompressIndicesTest::compressChar() { - std::size_t indexCount; - Mesh::IndexType indexType; Containers::Array data; - std::tie(indexCount, indexType, data) = MeshTools::compressIndices( + Mesh::IndexType type; + UnsignedInt start, end; + std::tie(data, type, start, end) = MeshTools::compressIndices( std::vector{1, 2, 3, 0, 4}); - CORRADE_COMPARE(indexCount, 5); - CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedByte); + CORRADE_COMPARE(start, 0); + CORRADE_COMPARE(end, 4); + CORRADE_COMPARE(type, Mesh::IndexType::UnsignedByte); CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ 0x01, 0x02, 0x03, 0x00, 0x04 })); } void CompressIndicesTest::compressShort() { - std::size_t indexCount; - Mesh::IndexType indexType; Containers::Array data; - std::tie(indexCount, indexType, data) = MeshTools::compressIndices( + Mesh::IndexType type; + UnsignedInt start, end; + std::tie(data, type, start, end) = MeshTools::compressIndices( std::vector{1, 256, 0, 5}); - CORRADE_COMPARE(indexCount, 4); - CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedShort); + CORRADE_COMPARE(start, 0); + CORRADE_COMPARE(end, 256); + CORRADE_COMPARE(type, Mesh::IndexType::UnsignedShort); if(!Utility::Endianness::isBigEndian()) { CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ 0x01, 0x00, @@ -84,14 +86,15 @@ void CompressIndicesTest::compressShort() { } void CompressIndicesTest::compressInt() { - std::size_t indexCount; - Mesh::IndexType indexType; Containers::Array data; - std::tie(indexCount, indexType, data) = MeshTools::compressIndices( + Mesh::IndexType type; + UnsignedInt start, end; + std::tie(data, type, start, end) = MeshTools::compressIndices( std::vector{65536, 3, 2}); - CORRADE_COMPARE(indexCount, 3); - CORRADE_VERIFY(indexType == Mesh::IndexType::UnsignedInt); + CORRADE_COMPARE(start, 2); + CORRADE_COMPARE(end, 65536); + CORRADE_COMPARE(type, Mesh::IndexType::UnsignedInt); if(!Utility::Endianness::isBigEndian()) { CORRADE_COMPARE(std::vector(data.begin(), data.end()), diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index a4f43878e..a74e23851 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -87,16 +87,11 @@ void InterleaveTest::strideGaps() { } void InterleaveTest::write() { - std::size_t attributeCount; - std::size_t stride; - Containers::Array data; - std::tie(attributeCount, stride, data) = MeshTools::interleave( + const Containers::Array data = MeshTools::interleave( std::vector{0, 1, 2}, std::vector{3, 4, 5}, std::vector{6, 7, 8}); - CORRADE_COMPARE(attributeCount, std::size_t(3)); - CORRADE_COMPARE(stride, std::size_t(7)); if(!Utility::Endianness::isBigEndian()) { CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, @@ -113,17 +108,11 @@ void InterleaveTest::write() { } void InterleaveTest::writeGaps() { - std::size_t attributeCount; - std::size_t stride; - Containers::Array data; - std::tie(attributeCount, stride, data) = MeshTools::interleave( + const Containers::Array data = MeshTools::interleave( std::vector{0, 1, 2}, 3, std::vector{3, 4, 5}, std::vector{6, 7, 8}, 2); - CORRADE_COMPARE(attributeCount, std::size_t(3)); - CORRADE_COMPARE(stride, std::size_t(12)); - if(!Utility::Endianness::isBigEndian()) { /* byte, _____________gap, int___________________, short_____, _______gap */ CORRADE_COMPARE(std::vector(data.begin(), data.end()), (std::vector{ @@ -142,8 +131,6 @@ void InterleaveTest::writeGaps() { } void InterleaveTest::interleaveInto() { - std::size_t attributeCount; - std::size_t stride; auto data = Containers::Array::from( 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, @@ -151,11 +138,7 @@ void InterleaveTest::interleaveInto() { 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77 ); - std::tie(attributeCount, stride) = MeshTools::interleaveInto(data, - 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3); - - CORRADE_COMPARE(attributeCount, std::size_t{4}); - CORRADE_COMPARE(stride, std::size_t{12}); + MeshTools::interleaveInto(data, 2, std::vector{4, 5, 6, 7}, 1, std::vector{0, 1, 2, 3}, 3); if(!Utility::Endianness::isBigEndian()) { /* _______gap, int___________________, _gap, short_____, _____________gap */ From 55feeb22e56e119ab7839ecde7f569d0a5b0784c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 23 Apr 2014 21:10:51 +0200 Subject: [PATCH 33/46] Added some TODOs related to buffer storage. --- src/Magnum/AbstractFramebuffer.h | 2 ++ src/Magnum/BufferImage.h | 4 ++++ src/Magnum/Texture.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/Magnum/AbstractFramebuffer.h b/src/Magnum/AbstractFramebuffer.h index 1f279f9a9..dfa05dc66 100644 --- a/src/Magnum/AbstractFramebuffer.h +++ b/src/Magnum/AbstractFramebuffer.h @@ -314,6 +314,8 @@ class MAGNUM_EXPORT AbstractFramebuffer { * See @ref read(const Vector2i&, const Vector2i&, Image2D&) for more * information. * @requires_gles30 Pixel buffer objects are not available in OpenGL ES 2.0. + * @todo Make it more flexible (usable with + * @extension{ARB,buffer_storage}, avoiding relocations...) */ void read(const Vector2i& offset, const Vector2i& size, BufferImage2D& image, BufferUsage usage); #endif diff --git a/src/Magnum/BufferImage.h b/src/Magnum/BufferImage.h index 651e15f15..6715d579f 100644 --- a/src/Magnum/BufferImage.h +++ b/src/Magnum/BufferImage.h @@ -61,6 +61,8 @@ template class BufferImage: public AbstractImage { * * Note that the image data are not copied on construction, but they * are deleted on class destruction. + * @todo Make it more flexible (usable with + * @extension{ARB,buffer_storage}, avoiding relocations...) */ explicit BufferImage(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, const void* data, BufferUsage usage); @@ -108,6 +110,8 @@ template class BufferImage: public AbstractImage { * Updates the image buffer with given data. The data are not deleted * after filling the buffer. * @see @ref Buffer::setData() + * @todo Make it more flexible (usable with + * @extension{ARB,buffer_storage}, avoiding relocations...) */ void setData(ColorFormat format, ColorType type, const typename DimensionTraits::VectorType& size, const void* data, BufferUsage usage); diff --git a/src/Magnum/Texture.h b/src/Magnum/Texture.h index c1de9599b..84802999e 100644 --- a/src/Magnum/Texture.h +++ b/src/Magnum/Texture.h @@ -606,6 +606,8 @@ template class Texture: public AbstractTexture { * * See @ref image(Int, Image&) for more information. * @requires_gl %Texture image queries are not available in OpenGL ES. + * @todo Make it more flexible (usable with + * @extension{ARB,buffer_storage}, avoiding relocations...) */ void image(Int level, BufferImage& image, BufferUsage usage) { AbstractTexture::image(_target, level, image, usage); From 2ae7bfaf14d90af08a3bfd974982e5db5301be18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 12:54:18 +0200 Subject: [PATCH 34/46] Max texture LOD bias _is_ available in OpenGL ES 3. --- src/Magnum/Implementation/TextureState.cpp | 2 +- src/Magnum/Implementation/TextureState.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Implementation/TextureState.cpp b/src/Magnum/Implementation/TextureState.cpp index 3ac20d023..0e5c5e23b 100644 --- a/src/Magnum/Implementation/TextureState.cpp +++ b/src/Magnum/Implementation/TextureState.cpp @@ -44,7 +44,7 @@ TextureState::TextureState(Context& context, std::vector& extension maxRectangleSize{}, maxBufferSize{}, #endif maxTextureUnits(0), - #ifndef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES2 maxLodBias{0.0f}, #endif maxMaxAnisotropy(0.0f), currentTextureUnit(0) diff --git a/src/Magnum/Implementation/TextureState.h b/src/Magnum/Implementation/TextureState.h index 668fd5f53..9075a58f8 100644 --- a/src/Magnum/Implementation/TextureState.h +++ b/src/Magnum/Implementation/TextureState.h @@ -92,7 +92,7 @@ struct TextureState { maxBufferSize; #endif GLint maxTextureUnits; - #ifndef MAGNUM_TARGET_GLES + #ifndef MAGNUM_TARGET_GLES2 GLfloat maxLodBias; #endif GLfloat maxMaxAnisotropy; From 6e0d22095efece0b83117f0d078be42a7eef910f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 14:29:35 +0200 Subject: [PATCH 35/46] Fixed Mesh move constructor/assignment. Missed copying of base vertex. --- src/Magnum/Mesh.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index e31755309..53da906a2 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -92,7 +92,7 @@ Mesh::~Mesh() { (this->*Context::current()->state().mesh->destroyImplementation)(); } -Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count) +Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex} #ifndef MAGNUM_TARGET_GLES2 , _indexStart(other._indexStart), _indexEnd(other._indexEnd) #endif @@ -111,6 +111,7 @@ Mesh& Mesh::operator=(Mesh&& other) noexcept { std::swap(_id, other._id); std::swap(_primitive, other._primitive); std::swap(_count, other._count); + std::swap(_baseVertex, other._baseVertex); #ifndef MAGNUM_TARGET_GLES2 std::swap(_indexStart, other._indexStart); std::swap(_indexEnd, other._indexEnd); From 35bd25201ff3ea97fe023db792d0e603b7426536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 16:20:59 +0200 Subject: [PATCH 36/46] Fix usage of reserved GLSL keyword in test. --- src/Magnum/Test/MeshGLTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 5ff11396d..b00867ac6 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -328,8 +328,8 @@ FloatShader::FloatShader(const std::string& type, const std::string& conversion) "void main() { gl_FragColor = " + conversion + "; }\n"); #else frag.addSource("in mediump " + type + " valueInterpolated;\n" - "out mediump vec4 output;\n" - "void main() { output = " + conversion + "; }\n"); + "out mediump vec4 result;\n" + "void main() { result = " + conversion + "; }\n"); #endif CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); attachShader(frag); From 072710bb8a7717c8454f8374f1566e151579364d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 16:21:30 +0200 Subject: [PATCH 37/46] Be less strict in OpenGL ES context version. I didn't yet have time to add more complete support for ES 3.1, but the engine should at least work on it. If the driver reports ES 3.0 or 3.1 it is taken as valid value in both ES2 and ES3 builds (i.e. the engine can work in ES2 mode also on ES3 driver). --- src/Magnum/Context.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 8f67e33be..58c3c5cb2 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -316,13 +316,15 @@ Context::Context() { "Context: cannot retrieve OpenGL version:" << versionNumberError, ); #endif + /* Allow ES2 context on driver that reports ES3 as supported */ const std::string version = versionString(); #ifndef MAGNUM_TARGET_GLES if(version.compare(0, 4, "2.1 ") == 0) #elif defined(MAGNUM_TARGET_WEBGL) if(version.find("WebGL 1") != std::string::npos) #else - if(version.find("OpenGL ES 2.0") != std::string::npos) + if(version.find("OpenGL ES 2.0") != std::string::npos || + version.find("OpenGL ES 3.") != std::string::npos) #endif { _majorVersion = 2; @@ -354,7 +356,7 @@ Context::Context() { #elif defined(MAGNUM_TARGET_GLES2) if(_version != Version::GLES200) #else - if(_version != Version::GLES300) + if(!isVersionSupported(Version::GLES300)) #endif { #ifndef MAGNUM_TARGET_GLES From 7d0726e5a5ecd703169d75585f37f607498c03a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 16:24:46 +0200 Subject: [PATCH 38/46] Doc++ --- src/Magnum/Mesh.h | 16 ++++++++-------- src/Magnum/MeshTools/Interleave.h | 2 +- src/Magnum/MeshView.h | 5 +++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index b2bafd179..6ca138de5 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -503,11 +503,11 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { /** * @brief Set vertex/index count + * @return Reference to self (for method chaining) * * If the mesh is indexed, the value is treated as index count, - * otherwise the value is vertex count. Default is `0`. This value is - * set automatically by @ref MeshTools::interleave() and - * @ref MeshTools::compressIndices() functions. + * otherwise the value is vertex count. If set to `0`, no draw commands + * are issued when calling @ref draw(). Default is `0`. * @see @ref isIndexed() */ Mesh& setCount(Int count) { @@ -520,11 +520,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { /** * @brief Set base vertex + * @return Reference to self (for method chaining) * * Sets number of vertices of which the vertex buffer will be offset - * when drawing. - * @requires_gl Desktop OpenGL is required for base vertex - * specification in indexed meshes. + * when drawing. Default is `0`. + * @requires_gl Base vertex cannot be specified for indexed meshes in + * OpenGL ES. */ Mesh& setBaseVertex(Int baseVertex) { _baseVertex = baseVertex; @@ -651,8 +652,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this * functionality is not available there. * @see @ref maxElementsIndices(), @ref maxElementsVertices(), - * @ref setCount(), @ref isIndexed(), - * @ref MeshTools::compressIndices(), @fn_gl{BindVertexArray}, + * @ref setCount(), @ref isIndexed(), @fn_gl{BindVertexArray}, * @fn_gl{BindBuffer} (if @extension{APPLE,vertex_array_object} is * available) */ diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index 5316d5eea..40bb0c963 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -215,8 +215,8 @@ template CORRADE_DEPRECATED("Use interleave(const T&...) instead") v Simplified specialization of the above function for only one attribute array, equivalent to the following: @code +if(!mesh.isIndexed()) mesh.setCount(attribute.size()); buffer.setData(attribute, usage); -if(!mesh.isIndexed()) mesh.setVertexCount(attribute.size()); @endcode */ template CORRADE_DEPRECATED("Use interleave(const T&...) instead") typename std::enable_if::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 90cb6b172..25f114866 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -84,11 +84,12 @@ class MAGNUM_EXPORT MeshView { /** * @brief Set base vertex + * @return Reference to self (for method chaining) * * Sets number of vertices of which the vertex buffer will be offset * when drawing. Default is `0`. - * @requires_gl Desktop OpenGL is required for base vertex - * specification in indexed meshes. + * @requires_gl Base vertex cannot be specified for indexed meshes in + * OpenGL ES. */ MeshView& setBaseVertex(Int baseVertex) { _baseVertex = baseVertex; From 2ea0a416ed48a073a8c831b43eba8ef074e67a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 16:38:15 +0200 Subject: [PATCH 39/46] Cleanup and code reorganization in MeshGLTest. --- src/Magnum/Test/MeshGLTest.cpp | 85 ++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index b00867ac6..751fe3cec 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -406,7 +406,10 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh .setCount(2); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setCount(1).setBaseVertex(1).draw(shader); + MeshView(mesh) + .setCount(1) + .setBaseVertex(1) + .draw(shader); } template T Checker::get(ColorFormat format, ColorType type) { @@ -1117,7 +1120,7 @@ void MeshGLTest::addVertexBufferMultipleGaps() { namespace { struct IndexChecker { - explicit IndexChecker(Mesh& mesh, Int baseVertex = 0); + explicit IndexChecker(Mesh& mesh); Color4ub get(); Renderbuffer renderbuffer; @@ -1127,7 +1130,7 @@ namespace { const Float indexedVertexData[] = { 0.0f, /* Offset */ - /* First attribute */ + /* First vertex */ Math::normalize(64), Math::normalize(17), Math::normalize(56), @@ -1137,7 +1140,36 @@ namespace { Math::normalize(97), Math::normalize(28), - /* Second attribute */ + /* Second vertex */ + 0.3f, 0.1f, 0.5f, + 0.4f, 0.0f, -0.9f, + 1.0f, -0.5f + }; + + const Float indexedVertexDataBaseVertex[] = { + 0.0f, 0.0f, /* Offset */ + + /* First vertex */ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + + /* Second vertex */ + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, + + /* Third vertex */ + Math::normalize(64), + Math::normalize(17), + Math::normalize(56), + Math::normalize(15), + Math::normalize(164), + Math::normalize(17), + Math::normalize(97), + Math::normalize(28), + + /* Fourth vertex */ 0.3f, 0.1f, 0.5f, 0.4f, 0.0f, -0.9f, 1.0f, -0.5f @@ -1147,7 +1179,7 @@ namespace { } #ifndef DOXYGEN_GENERATING_OUTPUT -IndexChecker::IndexChecker(Mesh& mesh, Int baseVertex): framebuffer({{}, Vector2i(1)}) { +IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { #ifndef MAGNUM_TARGET_GLES2 renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(1)); #else @@ -1160,7 +1192,11 @@ IndexChecker::IndexChecker(Mesh& mesh, Int baseVertex): framebuffer({{}, Vector2 .setCount(2); /* Skip first vertex so we test also offsets */ - MeshView(mesh).setCount(1).setBaseVertex(baseVertex).setIndexRange(1).draw(MultipleShader{}); + MeshView(mesh) + .setCount(1) + .setBaseVertex(mesh.baseVertex()) + .setIndexRange(1) + .draw(MultipleShader{}); } Color4ub IndexChecker::get() { @@ -1240,51 +1276,22 @@ void MeshGLTest::setIndexBufferUnsignedInt() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::setBaseVertex() { - const Float indexedVertexData[] = { - 0.0f, 0.0f, /* Offset */ - - /* First attribute */ - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, - - /* Second attribute */ - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, - - /* Third attribute */ - Math::normalize(64), - Math::normalize(17), - Math::normalize(56), - Math::normalize(15), - Math::normalize(164), - Math::normalize(17), - Math::normalize(97), - Math::normalize(28), - - /* Fourth attribute */ - 0.3f, 0.1f, 0.5f, - 0.4f, 0.0f, -0.9f, - 1.0f, -0.5f - }; - Buffer vertices; - vertices.setData(indexedVertexData, BufferUsage::StaticDraw); + vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); constexpr UnsignedShort indexData[] = { 2, 1, 0 }; Buffer indices(Buffer::Target::ElementArray); indices.setData(indexData, BufferUsage::StaticDraw); Mesh mesh; - mesh.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), + mesh.setBaseVertex(2) + .addVertexBuffer(vertices, 2*4, MultipleShader::Position(), MultipleShader::Normal(), MultipleShader::TextureCoordinates()) .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); MAGNUM_VERIFY_NO_ERROR(); - /* base vertex is 2 */ - const auto value = IndexChecker(mesh, 2).get(); + const auto value = IndexChecker(mesh).get(); MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(value, indexedResult); From 6488be5e91f96e759378ceab64bd20585f5dcf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 16:58:32 +0200 Subject: [PATCH 40/46] glDrawElementsBaseVertex() needs ARB_draw_elements_base_vertex. --- src/Magnum/Mesh.h | 2 ++ src/Magnum/MeshView.h | 2 ++ src/Magnum/Test/MeshGLTest.cpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 6ca138de5..ce9142d03 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -524,6 +524,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * * Sets number of vertices of which the vertex buffer will be offset * when drawing. Default is `0`. + * @requires_gl32 %Extension @extension{ARB,draw_elements_base_vertex} + * for indexed meshes * @requires_gl Base vertex cannot be specified for indexed meshes in * OpenGL ES. */ diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 25f114866..31c0b6ca4 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -88,6 +88,8 @@ class MAGNUM_EXPORT MeshView { * * Sets number of vertices of which the vertex buffer will be offset * when drawing. Default is `0`. + * @requires_gl32 %Extension @extension{ARB,draw_elements_base_vertex} + * for indexed meshes * @requires_gl Base vertex cannot be specified for indexed meshes in * OpenGL ES. */ diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 751fe3cec..d3da77b2c 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -1276,6 +1276,9 @@ void MeshGLTest::setIndexBufferUnsignedInt() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::setBaseVertex() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + Buffer vertices; vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); From 20df20de0f6891b00738169a1435df4163e30ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 17:17:25 +0200 Subject: [PATCH 41/46] Support for instanced mesh drawing and base instance. On desktop GL this is provided by ARB_draw_instanced (GL 3.1). Base instance is available only on desktop GL (4.2, ARB_base_instance). In ES2 the instanced functionality is provided by three (!) different extensions (ANGLE_instanced_arrays, EXT_draw_instanced, NV_draw_instanced), the proper implementation is chosen on context creation based on what extension is available. Though we don't have extension loader for ES yet, thus all these extensions are disabled and the implementation has assertion in it. Added blind test which tests only that something has been drawn and no errors were emitted, but not whether the right command is used. I'll probably need to check this later, because the Mesh::draw() behemoth is going slightly out of hand :) --- doc/opengl-mapping.dox | 3 +- doc/opengl-support.dox | 9 +- src/Magnum/Context.cpp | 3 + src/Magnum/Extensions.h | 5 + src/Magnum/Implementation/MeshState.cpp | 26 ++ src/Magnum/Implementation/MeshState.h | 5 + .../Implementation/setupDriverWorkarounds.cpp | 3 + src/Magnum/Mesh.cpp | 201 ++++++++++++--- src/Magnum/Mesh.h | 103 ++++++-- src/Magnum/MeshView.cpp | 16 +- src/Magnum/MeshView.h | 48 +++- src/Magnum/Test/MeshGLTest.cpp | 239 +++++++++++++++++- 12 files changed, 585 insertions(+), 76 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 2014e2859..7c82f8f40 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -103,9 +103,8 @@ OpenGL function | Matching API @fn_gl{DetachShader} | | @fn_gl{DispatchCompute} | | @fn_gl{DispatchComputeIndirect} | | -@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | @ref Mesh::draw(), \n @ref MeshView::draw() +@fn_gl{DrawArrays}, \n @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | @ref Mesh::draw(), \n @ref MeshView::draw() @fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | -@fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | | @fn_gl{DrawBuffer}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() @fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | @fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature() diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index 25ba6a715..cc16ada03 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -82,7 +82,7 @@ following: %Extension | Status -------------------------------------------- | ------ @extension{ARB,texture_rectangle} | done -@extension{ARB,draw_instanced} | | +@extension{ARB,draw_instanced} | done @extension{ARB,texture_buffer_object} | done @extension{ARB,uniform_buffer_object} | | @extension{ARB,copy_buffer} | done @@ -95,7 +95,7 @@ following: -------------------------------------------- | ------ @extension{ARB,geometry_shader4} | missing layered attachments @extension{ARB,depth_clamp} | done -@extension{ARB,draw_elements_base_vertex} | | +@extension{ARB,draw_elements_base_vertex} | missing `Multi*` command @extension{ARB,fragment_coord_conventions} | done (shading language only) @extension{ARB,provoking_vertex} | done @extension{ARB,seamless_cube_map} | done @@ -152,7 +152,7 @@ following: %Extension | Status -------------------------------------------- | ------ @extension{ARB,texture_compression_bptc} | done -@extension{ARB,base_instance} | | +@extension{ARB,base_instance} | done @extension{ARB,shading_language_420pack} | done (shading language only) @extension{ARB,transform_feedback_instanced} | | @extension{ARB,compressed_texture_pixel_storage} | | @@ -243,6 +243,7 @@ supported. -------------------------------------------- | ------ @es_extension{ANGLE,framebuffer_blit} | done @es_extension{ANGLE,framebuffer_multisample} | done +@es_extension{ANGLE,instanced_arrays} | missing vertex attrib divisor @es_extension{ANGLE,depth_texture} | done @es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset) @es_extension{APPLE,texture_max_level} | done @@ -256,9 +257,11 @@ supported. @es_extension{EXT,texture_rg} | done @es_extension{EXT,texture_storage} | done @es_extension{EXT,map_buffer_range} | done +@es_extension2{EXT,draw_instanced,draw_instanced} | done @es_extension{NV,draw_buffers} | done @es_extension{NV,fbo_color_attachments} | done @es_extension{NV,read_buffer} | done +@es_extension{NV,draw_instanced} | done @es_extension{NV,framebuffer_blit} | done @es_extension{NV,framebuffer_multisample} | done @es_extension{NV,shadow_samplers_array} | done (shading language only) diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index 58c3c5cb2..c8847bc3d 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -212,6 +212,7 @@ const std::vector& Extension::extensions(Version version) { static const std::vector extensionsES300{ _extension(GL,ANGLE,framebuffer_blit), _extension(GL,ANGLE,framebuffer_multisample), + _extension(GL,ANGLE,instanced_arrays), _extension(GL,ANGLE,depth_texture), _extension(GL,APPLE,framebuffer_multisample), _extension(GL,APPLE,texture_max_level), @@ -225,9 +226,11 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,texture_rg), _extension(GL,EXT,texture_storage), _extension(GL,EXT,map_buffer_range), + _extension(GL,EXT,draw_instanced), _extension(GL,NV,draw_buffers), _extension(GL,NV,fbo_color_attachments), _extension(GL,NV,read_buffer), + _extension(GL,NV,draw_instanced), _extension(GL,NV,framebuffer_blit), _extension(GL,NV,framebuffer_multisample), _extension(GL,NV,shadow_samplers_array), diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index 4df94b3fa..c41039c9f 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -205,6 +205,7 @@ namespace GL { #ifdef MAGNUM_TARGET_GLES2 _extension(GL,ANGLE,framebuffer_blit, GLES200, GLES300) // #83 _extension(GL,ANGLE,framebuffer_multisample, GLES200, GLES300) // #84 + _extension(GL,ANGLE,instanced_arrays, GLES200, GLES300) // #109 _extension(GL,ANGLE,depth_texture, GLES200, GLES300) // #138 #endif } namespace APPLE { @@ -253,6 +254,9 @@ namespace GL { _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 #endif _extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 + #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157 + #endif #ifndef MAGNUM_TARGET_GLES2 _extension(GL,EXT,shader_integer_mix, GLES300, None) // #161 #endif @@ -269,6 +273,7 @@ namespace GL { _extension(GL,NV,read_stencil, GLES200, None) // #94 _extension(GL,NV,read_depth_stencil, GLES200, None) // #94 #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,NV,draw_instanced, GLES200, GLES300) // #141 _extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142 _extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143 _extension(GL,NV,shadow_samplers_array, GLES200, GLES300) // #146 diff --git a/src/Magnum/Implementation/MeshState.cpp b/src/Magnum/Implementation/MeshState.cpp index 3c9ac875a..b7946673f 100644 --- a/src/Magnum/Implementation/MeshState.cpp +++ b/src/Magnum/Implementation/MeshState.cpp @@ -92,6 +92,32 @@ MeshState::MeshState(Context& context, std::vector& extensions): cu unbindImplementation = &Mesh::unbindImplementationDefault; } #endif + + #ifdef MAGNUM_TARGET_GLES2 + /* Instanced draw ímplementation on ES2 */ + if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::ANGLE::instanced_arrays::string()); + + drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationANGLE; + drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationANGLE; + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::draw_instanced::string()); + + drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationEXT; + drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationEXT; + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::NV::draw_instanced::string()); + + drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationNV; + drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationNV; + + } else { + drawArraysInstancedImplementation = nullptr; + drawElementsInstancedImplementation = nullptr; + } + #endif } }} diff --git a/src/Magnum/Implementation/MeshState.h b/src/Magnum/Implementation/MeshState.h index ea4885b4f..f91dd4e5c 100644 --- a/src/Magnum/Implementation/MeshState.h +++ b/src/Magnum/Implementation/MeshState.h @@ -48,6 +48,11 @@ struct MeshState { void(Mesh::*bindImplementation)(); void(Mesh::*unbindImplementation)(); + #ifdef MAGNUM_TARGET_GLES2 + void(Mesh::*drawArraysInstancedImplementation)(GLint, GLsizei, GLsizei); + void(Mesh::*drawElementsInstancedImplementation)(GLsizei, GLintptr, GLsizei); + #endif + GLuint currentVAO; #ifndef MAGNUM_TARGET_GLES2 GLint maxElementsIndices, maxElementsVertices; diff --git a/src/Magnum/Implementation/setupDriverWorkarounds.cpp b/src/Magnum/Implementation/setupDriverWorkarounds.cpp index 7d5d7f8be..08f311c96 100644 --- a/src/Magnum/Implementation/setupDriverWorkarounds.cpp +++ b/src/Magnum/Implementation/setupDriverWorkarounds.cpp @@ -68,6 +68,7 @@ void Context::setupDriverWorkarounds() { #ifdef MAGNUM_TARGET_GLES2 _setRequiredVersion(GL::ANGLE::framebuffer_blit, None); _setRequiredVersion(GL::ANGLE::framebuffer_multisample, None); + _setRequiredVersion(GL::ANGLE::instanced_arrays, None); _setRequiredVersion(GL::APPLE::framebuffer_multisample, None); _setRequiredVersion(GL::EXT::discard_framebuffer, None); _setRequiredVersion(GL::EXT::blend_minmax, None); @@ -76,9 +77,11 @@ void Context::setupDriverWorkarounds() { #endif _setRequiredVersion(GL::EXT::texture_storage, None); _setRequiredVersion(GL::EXT::map_buffer_range, None); + _setRequiredVersion(GL::EXT::draw_instanced, None); _setRequiredVersion(GL::NV::draw_buffers, None); _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? _setRequiredVersion(GL::NV::read_buffer, None); + _setRequiredVersion(GL::NV::draw_instanced, None); _setRequiredVersion(GL::NV::framebuffer_blit, None); _setRequiredVersion(GL::NV::framebuffer_multisample, None); _setRequiredVersion(GL::OES::texture_3D, None); diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 53da906a2..422f32d16 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -72,11 +72,14 @@ std::size_t Mesh::indexSize(IndexType type) { CORRADE_ASSERT_UNREACHABLE(); } -Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0) +Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0), _instanceCount{1}, + #ifndef MAGNUM_TARGET_GLES + _baseInstance{0}, + #endif #ifndef MAGNUM_TARGET_GLES2 - , _indexStart(0), _indexEnd(0) + _indexStart(0), _indexEnd(0), #endif - , _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) + _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) { (this->*Context::current()->state().mesh->createImplementation)(); } @@ -92,11 +95,14 @@ Mesh::~Mesh() { (this->*Context::current()->state().mesh->destroyImplementation)(); } -Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex} +Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _count(other._count), _baseVertex{other._baseVertex}, _instanceCount{other._instanceCount}, + #ifndef MAGNUM_TARGET_GLES + _baseInstance{other._baseInstance}, + #endif #ifndef MAGNUM_TARGET_GLES2 - , _indexStart(other._indexStart), _indexEnd(other._indexEnd) + _indexStart(other._indexStart), _indexEnd(other._indexEnd), #endif - , _indexOffset(other._indexOffset), _indexType(other._indexType), _indexBuffer(other._indexBuffer), _attributes(std::move(other._attributes)) + _indexOffset(other._indexOffset), _indexType(other._indexType), _indexBuffer(other._indexBuffer), _attributes(std::move(other._attributes)) #ifndef MAGNUM_TARGET_GLES2 , _integerAttributes(std::move(other._integerAttributes)) #ifndef MAGNUM_TARGET_GLES @@ -112,6 +118,10 @@ Mesh& Mesh::operator=(Mesh&& other) noexcept { std::swap(_primitive, other._primitive); std::swap(_count, other._count); std::swap(_baseVertex, other._baseVertex); + std::swap(_instanceCount, other._instanceCount); + #ifndef MAGNUM_TARGET_GLES + std::swap(_baseInstance, other._baseInstance); + #endif #ifndef MAGNUM_TARGET_GLES2 std::swap(_indexStart, other._indexStart); std::swap(_indexEnd, other._indexEnd); @@ -167,50 +177,111 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi return *this; } -#ifndef MAGNUM_TARGET_GLES2 -void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) +#ifndef MAGNUM_TARGET_GLES +void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd) +#elif !defined(MAGNUM_TARGET_GLES2) +void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd) #else -void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset) +void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset) #endif { - /* Nothing to draw */ - if(!count) return; - - (this->*Context::current()->state().mesh->bindImplementation)(); - /* Non-indexed mesh */ - if(!_indexBuffer) { - glDrawArrays(GLenum(_primitive), baseVertex, count); + const Implementation::MeshState& state = *Context::current()->state().mesh; - /* Indexed mesh with base vertex */ - } else if(baseVertex) { - #ifndef MAGNUM_TARGET_GLES - /* Indexed mesh with specified range */ - if(indexEnd) { - glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); - - /* Indexed mesh without specified range */ - } else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); - #else - CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", ); - #endif + /* Nothing to draw */ + if(!count || !instanceCount) return; + + (this->*state.bindImplementation)(); + + /* Non-instanced mesh */ + if(instanceCount == 1) { + /* Non-indexed mesh */ + if(!_indexBuffer) { + glDrawArrays(GLenum(_primitive), baseVertex, count); + + /* Indexed mesh with base vertex */ + } else if(baseVertex) { + #ifndef MAGNUM_TARGET_GLES + /* Indexed mesh with specified range */ + if(indexEnd) { + glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + + /* Indexed mesh */ + } else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + #else + CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", ); + #endif + + /* Indexed mesh */ + } else { + #ifndef MAGNUM_TARGET_GLES2 + /* Indexed mesh with specified range */ + if(indexEnd) { + glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); + + /* Indexed mesh */ + } else + #endif + { + glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + } + } - /* Indexed mesh without base vertex */ + /* Instanced mesh */ } else { - /* Indexed mesh with specified range */ - #ifndef MAGNUM_TARGET_GLES2 - if(indexEnd) { - glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); - - /* Indexed mesh without specified range */ - } else - #endif - { - glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + /* Non-indexed mesh */ + if(!_indexBuffer) { + #ifndef MAGNUM_TARGET_GLES + /* Non-indexed mesh with base instance */ + if(baseInstance) { + glDrawArraysInstancedBaseInstance(GLenum(_primitive), baseVertex, count, instanceCount, baseInstance); + + /* Non-indexed mesh */ + } else + #endif + { + #ifndef MAGNUM_TARGET_GLES2 + glDrawArraysInstanced(GLenum(_primitive), baseVertex, count, instanceCount); + #else + (this->*state.drawArraysInstancedImplementation)(baseVertex, count, instanceCount); + #endif + } + + /* Indexed mesh with base vertex */ + } else if(baseVertex) { + #ifndef MAGNUM_TARGET_GLES + /* Indexed mesh with base vertex and base instance */ + if(baseInstance) + glDrawElementsInstancedBaseVertexBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount, baseVertex, baseInstance); + + /* Indexed mesh with base vertex */ + else + glDrawElementsInstancedBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount, baseVertex); + #else + CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", ); + #endif + + /* Indexed mesh */ + } else { + #ifndef MAGNUM_TARGET_GLES + /* Indexed mesh with base instance */ + if(baseInstance) { + glDrawElementsInstancedBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount, baseInstance); + + /* Instanced mesh */ + } else + #endif + { + #ifndef MAGNUM_TARGET_GLES2 + glDrawElementsInstanced(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount); + #else + (this->*state.drawElementsInstancedImplementation)(count, indexOffset, instanceCount); + #endif + } } } - (this->*Context::current()->state().mesh->unbindImplementation)(); + (this->*state.unbindImplementation)(); } void Mesh::bindVAO(GLuint vao) { @@ -400,6 +471,56 @@ void Mesh::unbindImplementationDefault() { void Mesh::unbindImplementationVAO() {} +#ifdef MAGNUM_TARGET_GLES2 +void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { + //glDrawArraysInstancedANGLE(GLenum(_primitive), baseVertex, count, instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(baseVertex); + static_cast(count); + static_cast(instanceCount); +} + +void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { + //glDrawArraysInstancedEXT(GLenum(_primitive), baseVertex, count, instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(baseVertex); + static_cast(count); + static_cast(instanceCount); +} + +void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { + //glDrawArraysInstancedNV(GLenum(_primitive), baseVertex, count, instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(baseVertex); + static_cast(count); + static_cast(instanceCount); +} + +void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { + //glDrawElementsInstancedANGLE(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(count); + static_cast(indexOffset); + static_cast(instanceCount); +} + +void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { + //glDrawElementsInstancedEXT(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(count); + static_cast(indexOffset); + static_cast(instanceCount); +} + +void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { + //glDrawElementsInstancedNV(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), instanceCount); + CORRADE_INTERNAL_ASSERT(false); + static_cast(count); + static_cast(indexOffset); + static_cast(instanceCount); +} +#endif + #ifndef DOXYGEN_GENERATING_OUTPUT Debug operator<<(Debug debug, MeshPrimitive value) { switch(value) { diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index ce9142d03..080d85bcd 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -143,8 +143,8 @@ that they are available for whole mesh lifetime. On the other hand it allows you to use one buffer for more meshes (each mesh for example configured for different usage) or store data for more meshes in one buffer. -If vertex/index count is zero, the mesh is empty and no draw commands are -issued when calling @ref draw(). +If vertex/index count or instance count is zero, the mesh is empty and no draw +commands are issued when calling @ref draw(). @subsection Mesh-configuration-examples Example mesh configuration @@ -331,8 +331,6 @@ calls to @fn_gl{BindBuffer} and @fn_gl{BindVertexArray}. See documentation of If index range is specified in @ref setIndexBuffer(), range-based version of drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @ref draw() for more information. - -@todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. */ class MAGNUM_EXPORT Mesh: public AbstractObject { friend class MeshView; @@ -567,6 +565,44 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { CORRADE_DEPRECATED("use setCount() instead") Mesh& setIndexCount(Int count) { return setCount(count); } #endif + /** @brief Instance count */ + Int instanceCount() const { return _instanceCount; } + + /** + * @brief Set instance count + * @return Reference to self (for method chaining) + * + * If set to `1`, non-instanced draw commands are issued when calling + * @ref draw(). If set to `0`, no draw commands are issued altogether. + * Default is `1`. + * @requires_gl31 %Extension @extension{ARB,draw_instanced} + * @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays}, + * @es_extension2{EXT,draw_instanced,draw_instanced} or + * @es_extension{NV,draw_instanced} in OpenGL ES 2.0. + */ + Mesh& setInstanceCount(Int count) { + _instanceCount = count; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** @brief Base instance */ + UnsignedInt baseInstance() const { return _baseInstance; } + + /** + * @brief Set base instance + * @return Reference to self (for method chaining) + * + * Default is `0`. + * @requires_gl42 %Extension @extension{ARB,base_instance} + * @requires_gl Base instance cannot be specified in OpenGL ES. + */ + Mesh& setBaseInstance(UnsignedInt baseInstance) { + _baseInstance = baseInstance; + return *this; + } + #endif + /** * @brief Add buffer with (interleaved) vertex attributes for use with given shader * @return Reference to self (for method chaining) @@ -680,23 +716,31 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @param shader Shader to use for drawing * * Expects that the shader is compatible with this mesh and is fully - * set up. See also + * set up. If vertex/index count or instance count is `0`, no draw + * commands are issued. See also * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * for more information. - * @see @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray}, - * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, - * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if - * @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} - * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}/ - * @fn_gl{DrawElementsBaseVertex}/@fn_gl{DrawRangeElementsBaseVertex} + * @see @ref setCount(), @ref setInstanceCount(), @fn_gl{UseProgram}, + * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, + * @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} + * or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} + * is available), @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/ + * @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/ + * @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/ + * @fn_gl{DrawRangeElementsBaseVertex}/@fn_gl{DrawElementsInstanced}/ + * @fn_gl{DrawElementsInstancedBaseInstance}/ + * @fn_gl{DrawElementsInstancedBaseVertex}/ + * @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} */ void draw(AbstractShaderProgram& shader) { shader.use(); - #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); + #ifndef MAGNUM_TARGET_GLES + drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); + #elif !defined(MAGNUM_TARGET_GLES2) + drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, _baseVertex, _indexOffset); + drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); #endif } @@ -709,10 +753,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * instead. */ CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() { - #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); + #ifndef MAGNUM_TARGET_GLES + drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); + #elif !defined(MAGNUM_TARGET_GLES2) + drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, _baseVertex, _indexOffset); + drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); #endif } #endif @@ -832,10 +878,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #endif - #ifndef MAGNUM_TARGET_GLES2 - void drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); + #ifndef MAGNUM_TARGET_GLES + void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd); + #elif !defined(MAGNUM_TARGET_GLES2) + void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd); #else - void drawInternal(Int count, Int baseVertex, GLintptr indexOffset); + void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset); #endif void MAGNUM_LOCAL createImplementationDefault(); @@ -873,9 +921,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { void MAGNUM_LOCAL unbindImplementationDefault(); void MAGNUM_LOCAL unbindImplementationVAO(); + #ifdef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL drawArraysInstancedImplementationANGLE(GLint baseVertex, GLsizei count, GLsizei instanceCount); + void MAGNUM_LOCAL drawArraysInstancedImplementationEXT(GLint baseVertex, GLsizei count, GLsizei instanceCount); + void MAGNUM_LOCAL drawArraysInstancedImplementationNV(GLint baseVertex, GLsizei count, GLsizei instanceCount); + + void MAGNUM_LOCAL drawElementsInstancedImplementationANGLE(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); + void MAGNUM_LOCAL drawElementsInstancedImplementationEXT(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); + void MAGNUM_LOCAL drawElementsInstancedImplementationNV(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); + #endif + GLuint _id; MeshPrimitive _primitive; - Int _count, _baseVertex; + Int _count, _baseVertex, _instanceCount; + #ifndef MAGNUM_TARGET_GLES + UnsignedInt _baseInstance; + #endif #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif diff --git a/src/Magnum/MeshView.cpp b/src/Magnum/MeshView.cpp index c935612c1..6db77e719 100644 --- a/src/Magnum/MeshView.cpp +++ b/src/Magnum/MeshView.cpp @@ -37,19 +37,23 @@ MeshView& MeshView::setIndexRange(Int first) { void MeshView::draw(AbstractShaderProgram& shader) { shader.use(); - #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); + #ifndef MAGNUM_TARGET_GLES + _original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); + #elif !defined(MAGNUM_TARGET_GLES2) + _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_count, _baseVertex, _indexOffset); + _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); #endif } #ifdef MAGNUM_BUILD_DEPRECATED void MeshView::draw() { - #ifndef MAGNUM_TARGET_GLES2 - _original->drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); + #ifndef MAGNUM_TARGET_GLES + _original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); + #elif !defined(MAGNUM_TARGET_GLES2) + _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); #else - _original->drawInternal(_count, _baseVertex, _indexOffset); + _original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); #endif } #endif diff --git a/src/Magnum/MeshView.h b/src/Magnum/MeshView.h index 31c0b6ca4..94d5ac7f2 100644 --- a/src/Magnum/MeshView.h +++ b/src/Magnum/MeshView.h @@ -172,6 +172,42 @@ class MAGNUM_EXPORT MeshView { } #endif + /** @brief Instance count */ + Int instanceCount() const { return _instanceCount; } + + /** + * @brief Set instance count + * @return Reference to self (for method chaining) + * + * Default is `1`. + * @requires_gl31 %Extension @extension{ARB,draw_instanced} + * @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays}, + * @es_extension2{EXT,draw_instanced,draw_instanced} or + * @es_extension{NV,draw_instanced} in OpenGL ES 2.0. + */ + MeshView& setInstanceCount(Int count) { + _instanceCount = count; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES + /** @brief Base instance */ + UnsignedInt baseInstance() const { return _baseInstance; } + + /** + * @brief Set base instance + * @return Reference to self (for method chaining) + * + * Default is `0`. + * @requires_gl42 %Extension @extension{ARB,base_instance} + * @requires_gl Base instance cannot be specified in OpenGL ES. + */ + MeshView& setBaseInstance(UnsignedInt baseInstance) { + _baseInstance = baseInstance; + return *this; + } + #endif + /** * @brief Draw the mesh * @@ -192,14 +228,21 @@ class MAGNUM_EXPORT MeshView { private: Mesh* _original; - Int _count, _baseVertex; + Int _count, _baseVertex, _instanceCount; + #ifndef MAGNUM_TARGET_GLES + UnsignedInt _baseInstance; + #endif GLintptr _indexOffset; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif }; -inline MeshView::MeshView(Mesh& original): _original(&original), _count(0), _baseVertex(0), _indexOffset(0) +inline MeshView::MeshView(Mesh& original): _original(&original), _count(0), _baseVertex(0), _instanceCount{1}, + #ifndef MAGNUM_TARGET_GLES + _baseInstance{0}, + #endif + _indexOffset(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif @@ -217,7 +260,6 @@ inline MeshView& MeshView::setIndexRange(Int first, UnsignedInt start, UnsignedI return *this; } - } #endif diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index d3da77b2c..28f9bde6b 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -110,6 +110,14 @@ class MeshGLTest: public AbstractOpenGLTester { #ifndef MAGNUM_TARGET_GLES void setBaseVertex(); #endif + void setInstanceCount(); + void setInstanceCountIndexed(); + #ifndef MAGNUM_TARGET_GLES + void setInstanceCountBaseInstance(); + void setInstanceCountBaseInstanceIndexed(); + void setInstanceCountBaseVertex(); + void setInstanceCountBaseVertexBaseInstance(); + #endif }; MeshGLTest::MeshGLTest() { @@ -175,7 +183,15 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::setIndexBufferUnsignedInt, #ifndef MAGNUM_TARGET_GLES - &MeshGLTest::setBaseVertex + &MeshGLTest::setBaseVertex, + #endif + &MeshGLTest::setInstanceCount, + &MeshGLTest::setInstanceCountIndexed, + #ifndef MAGNUM_TARGET_GLES + &MeshGLTest::setInstanceCountBaseInstance, + &MeshGLTest::setInstanceCountBaseInstanceIndexed, + &MeshGLTest::setInstanceCountBaseVertex, + &MeshGLTest::setInstanceCountBaseVertexBaseInstance #endif }); } @@ -409,6 +425,10 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh MeshView(mesh) .setCount(1) .setBaseVertex(1) + .setInstanceCount(mesh.instanceCount()) + #ifndef MAGNUM_TARGET_GLES + .setBaseInstance(mesh.baseInstance()) + #endif .draw(shader); } @@ -1195,6 +1215,10 @@ IndexChecker::IndexChecker(Mesh& mesh): framebuffer({{}, Vector2i(1)}) { MeshView(mesh) .setCount(1) .setBaseVertex(mesh.baseVertex()) + .setInstanceCount(mesh.instanceCount()) + #ifndef MAGNUM_TARGET_GLES + .setBaseInstance(mesh.baseInstance()) + #endif .setIndexRange(1) .draw(MultipleShader{}); } @@ -1301,6 +1325,219 @@ void MeshGLTest::setBaseVertex() { } #endif +void MeshGLTest::setInstanceCount() { + /* Verbatim copy of addVertexBufferFloat() with added extension check and + setInstanceCount() call. It would just render three times the same + value. I'm too lazy to invent proper test case, so I'll just check that + it didn't generate any error and rendered something */ + + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + #elif defined(MAGNUM_TARGET_GLES2) + if(!Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available."); + #endif + + typedef AbstractShaderProgram::Attribute<0, Float> Attribute; + + const Float data[] = { 0.0f, -0.7f, Math::normalize(96) }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .addVertexBuffer(buffer, 4, Attribute()); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + mesh).get(ColorFormat::RGBA, ColorType::UnsignedByte); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 96); +} + +void MeshGLTest::setInstanceCountIndexed() { + /* Verbatim copy of setIndexBuffer() with added extension check and + setInstanceCount() call. It would just render three times the same + value. I'm too lazy to invent proper test case, so I'll just check that + it didn't generate any error and rendered something */ + + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + #elif defined(MAGNUM_TARGET_GLES2) + if(!Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required extension is not available."); + #endif + + Buffer vertices; + vertices.setData(indexedVertexData, BufferUsage::StaticDraw); + + constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + Buffer indices(Buffer::Target::ElementArray); + indices.setData(indexData, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .addVertexBuffer(vertices, 1*4, MultipleShader::Position(), + MultipleShader::Normal(), MultipleShader::TextureCoordinates()) + .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = IndexChecker(mesh).get(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, indexedResult); +} + +#ifndef MAGNUM_TARGET_GLES +void MeshGLTest::setInstanceCountBaseInstance() { + /* Verbatim copy of setInstanceCount() with additional extension check and + setBaseInstance() call. It would just render three times the same + value. I'm too lazy to invent proper test case, so I'll just check that + it didn't generate any error and rendered something */ + + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); + + typedef AbstractShaderProgram::Attribute<0, Float> Attribute; + + const Float data[] = { 0.0f, -0.7f, Math::normalize(96) }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .setBaseInstance(72) + .addVertexBuffer(buffer, 4, Attribute()); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + mesh).get(ColorFormat::RGBA, ColorType::UnsignedByte); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 96); +} + +void MeshGLTest::setInstanceCountBaseInstanceIndexed() { + /* Verbatim copy of setInstanceCountIndexed() with additional extension + check and setBaseInstance() call. It would just render three times the + same value. I'm too lazy to invent proper test case, so I'll just check + that it didn't generate any error and rendered something */ + + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); + + Buffer vertices; + vertices.setData(indexedVertexData, BufferUsage::StaticDraw); + + constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + Buffer indices(Buffer::Target::ElementArray); + indices.setData(indexData, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .setBaseInstance(72) + .addVertexBuffer(vertices, 1*4, MultipleShader::Position(), + MultipleShader::Normal(), MultipleShader::TextureCoordinates()) + .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = IndexChecker(mesh).get(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, indexedResult); +} + +void MeshGLTest::setInstanceCountBaseVertex() { + /* Verbatim copy of setBaseVertex() with additional extension check and + setInstanceCount() call. It would just render three times the same + value. I'm too lazy to invent proper test case, so I'll just check + that it didn't generate any error and rendered something */ + + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + + Buffer vertices; + vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); + + constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + Buffer indices(Buffer::Target::ElementArray); + indices.setData(indexData, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setBaseVertex(2) + .setInstanceCount(3) + .addVertexBuffer(vertices, 2*4, MultipleShader::Position(), + MultipleShader::Normal(), MultipleShader::TextureCoordinates()) + .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = IndexChecker(mesh).get(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, indexedResult); +} + +void MeshGLTest::setInstanceCountBaseVertexBaseInstance() { + /* Verbatim copy of setInstanceCountBaseVertex() with added extension check + and setBaseInstance() call. It would just render three times the same + value. I'm too lazy to invent proper test case, so I'll just check + that it didn't generate any error and rendered something */ + + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); + + Buffer vertices; + vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); + + constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + Buffer indices(Buffer::Target::ElementArray); + indices.setData(indexData, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setBaseVertex(2) + .setInstanceCount(3) + .setBaseInstance(72) + .addVertexBuffer(vertices, 2*4, MultipleShader::Position(), + MultipleShader::Normal(), MultipleShader::TextureCoordinates()) + .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = IndexChecker(mesh).get(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, indexedResult); +} +#endif + }} CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) From c0056f76d2652de0e8a12ef783d9ab58b13d9137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 17:35:31 +0200 Subject: [PATCH 42/46] Code reorganization. --- src/Magnum/Mesh.cpp | 70 ++++++++++++++++++++------------------------- src/Magnum/Mesh.h | 24 +++++----------- 2 files changed, 38 insertions(+), 56 deletions(-) diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 422f32d16..1c9ee808d 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -297,44 +297,6 @@ void Mesh::bindVAO(GLuint vao) { } } -void Mesh::attributePointerInternal(const Attribute& attribute) { - (this->*Context::current()->state().mesh->attributePointerImplementation)(attribute); -} - -#ifndef MAGNUM_TARGET_GLES2 -void Mesh::attributePointerInternal(const IntegerAttribute& attribute) { - (this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute); -} - -#ifndef MAGNUM_TARGET_GLES -void Mesh::attributePointerInternal(const LongAttribute& attribute) { - (this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute); -} -#endif -#endif - -void Mesh::vertexAttribPointer(const Attribute& attribute) { - glEnableVertexAttribArray(attribute.location); - attribute.buffer->bind(Buffer::Target::Array); - glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast(attribute.offset)); -} - -#ifndef MAGNUM_TARGET_GLES2 -void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) { - glEnableVertexAttribArray(attribute.location); - attribute.buffer->bind(Buffer::Target::Array); - glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); -} - -#ifndef MAGNUM_TARGET_GLES -void Mesh::vertexAttribPointer(const LongAttribute& attribute) { - glEnableVertexAttribArray(attribute.location); - attribute.buffer->bind(Buffer::Target::Array); - glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); -} -#endif -#endif - void Mesh::createImplementationDefault() { _id = 0; } void Mesh::createImplementationVAO() { @@ -359,6 +321,10 @@ void Mesh::destroyImplementationVAO() { #endif } +void Mesh::attributePointerInternal(const Attribute& attribute) { + (this->*Context::current()->state().mesh->attributePointerImplementation)(attribute); +} + void Mesh::attributePointerImplementationDefault(const Attribute& attribute) { #if defined(CORRADE_TARGET_NACL) || defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(attribute.buffer->targetHint() == Buffer::Target::Array, @@ -385,7 +351,17 @@ void Mesh::attributePointerImplementationDSA(const Attribute& attribute) { } #endif +void Mesh::vertexAttribPointer(const Attribute& attribute) { + glEnableVertexAttribArray(attribute.location); + attribute.buffer->bind(Buffer::Target::Array); + glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast(attribute.offset)); +} + #ifndef MAGNUM_TARGET_GLES2 +void Mesh::attributePointerInternal(const IntegerAttribute& attribute) { + (this->*Context::current()->state().mesh->attributeIPointerImplementation)(attribute); +} + void Mesh::attributePointerImplementationDefault(const IntegerAttribute& attribute) { _integerAttributes.push_back(attribute); } @@ -402,7 +378,18 @@ void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) } #endif +void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) { + glEnableVertexAttribArray(attribute.location); + attribute.buffer->bind(Buffer::Target::Array); + glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); +} +#endif + #ifndef MAGNUM_TARGET_GLES +void Mesh::attributePointerInternal(const LongAttribute& attribute) { + (this->*Context::current()->state().mesh->attributeLPointerImplementation)(attribute); +} + void Mesh::attributePointerImplementationDefault(const LongAttribute& attribute) { _longAttributes.push_back(attribute); } @@ -416,7 +403,12 @@ void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) { glEnableVertexArrayAttribEXT(_id, attribute.location); glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); } -#endif + +void Mesh::vertexAttribPointer(const LongAttribute& attribute) { + glEnableVertexAttribArray(attribute.location); + attribute.buffer->bind(Buffer::Target::Array); + glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); +} #endif void Mesh::bindIndexBufferImplementationDefault(Buffer&) {} diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 080d85bcd..81788c55e 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -862,22 +862,6 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { static void MAGNUM_LOCAL bindVAO(GLuint vao); - void attributePointerInternal(const Attribute& attribute); - #ifndef MAGNUM_TARGET_GLES2 - void attributePointerInternal(const IntegerAttribute& attribute); - #ifndef MAGNUM_TARGET_GLES - void attributePointerInternal(const LongAttribute& attribute); - #endif - #endif - - void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); - #ifndef MAGNUM_TARGET_GLES2 - void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute); - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute); - #endif - #endif - #ifndef MAGNUM_TARGET_GLES void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd); #elif !defined(MAGNUM_TARGET_GLES2) @@ -892,24 +876,30 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { void MAGNUM_LOCAL destroyImplementationDefault(); void MAGNUM_LOCAL destroyImplementationVAO(); + void attributePointerInternal(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const Attribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const Attribute& attribute); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL attributePointerImplementationDSA(const Attribute& attribute); #endif + void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); #ifndef MAGNUM_TARGET_GLES2 + void attributePointerInternal(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const IntegerAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const IntegerAttribute& attribute); #ifndef MAGNUM_TARGET_GLES void MAGNUM_LOCAL attributePointerImplementationDSA(const IntegerAttribute& attribute); #endif + void MAGNUM_LOCAL vertexAttribPointer(const IntegerAttribute& attribute); + #endif #ifndef MAGNUM_TARGET_GLES + void attributePointerInternal(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDefault(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationVAO(const LongAttribute& attribute); void MAGNUM_LOCAL attributePointerImplementationDSA(const LongAttribute& attribute); - #endif + void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute); #endif void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&); From 71a576659467ef93c3897d74b7480b8cff4aa027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 18:48:18 +0200 Subject: [PATCH 43/46] Added Mesh::addVertexBufferInstanced(). Functionality provided by GL 3.3 and ARB_instanced_arrays, on ES2 this is again implemented in three different extensions -- {ANGLE,EXT,NV}_instanced_arrays. They are disabled until Magnum has proper extension loading on ES. --- doc/opengl-mapping.dox | 2 +- doc/opengl-support.dox | 6 +- src/Magnum/Context.cpp | 2 + src/Magnum/Extensions.h | 2 + src/Magnum/Implementation/MeshState.cpp | 18 +++ src/Magnum/Implementation/MeshState.h | 3 + .../Implementation/setupDriverWorkarounds.cpp | 2 + src/Magnum/Mesh.cpp | 35 +++++ src/Magnum/Mesh.h | 65 +++++++-- src/Magnum/Test/MeshGLTest.cpp | 133 +++++++++++++++++- 10 files changed, 251 insertions(+), 17 deletions(-) diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 7c82f8f40..dae5de8ee 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -247,7 +247,7 @@ OpenGL function | Matching API @fn_gl{ValidateProgramPipeline} | | @fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details") @fn_gl{VertexAttribBinding} | | -@fn_gl{VertexAttribDivisor} | | +@fn_gl{VertexAttribDivisor}, \n @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} | @ref Mesh::addVertexBufferInstanced() @fn_gl{VertexAttribFormat} | | @fn_gl{VertexAttribPointer}, \n @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} | @ref Mesh::addVertexBuffer() @fn_gl{VertexBindingDivisor} | | diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index cc16ada03..bfd5ea51e 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -107,7 +107,7 @@ following: %Extension | Status -------------------------------------------- | ------ -@extension{ARB,instanced_arrays} | | +@extension{ARB,instanced_arrays} | done @extension{ARB,blend_func_extended} | missing limit query @extension{ARB,explicit_attrib_location} | done (shading language only) @extension{ARB,occlusion_query2} | done @@ -243,7 +243,7 @@ supported. -------------------------------------------- | ------ @es_extension{ANGLE,framebuffer_blit} | done @es_extension{ANGLE,framebuffer_multisample} | done -@es_extension{ANGLE,instanced_arrays} | missing vertex attrib divisor +@es_extension{ANGLE,instanced_arrays} | done @es_extension{ANGLE,depth_texture} | done @es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset) @es_extension{APPLE,texture_max_level} | done @@ -257,6 +257,7 @@ supported. @es_extension{EXT,texture_rg} | done @es_extension{EXT,texture_storage} | done @es_extension{EXT,map_buffer_range} | done +@es_extension{EXT,instanced_arrays} | done @es_extension2{EXT,draw_instanced,draw_instanced} | done @es_extension{NV,draw_buffers} | done @es_extension{NV,fbo_color_attachments} | done @@ -264,6 +265,7 @@ supported. @es_extension{NV,draw_instanced} | done @es_extension{NV,framebuffer_blit} | done @es_extension{NV,framebuffer_multisample} | done +@es_extension{NV,instanced_arrays} | done @es_extension{NV,shadow_samplers_array} | done (shading language only) @es_extension{NV,shadow_samplers_cube} | done (shading language only) @es_extension{OES,depth24} | done diff --git a/src/Magnum/Context.cpp b/src/Magnum/Context.cpp index c8847bc3d..e835284ae 100644 --- a/src/Magnum/Context.cpp +++ b/src/Magnum/Context.cpp @@ -226,6 +226,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,EXT,texture_rg), _extension(GL,EXT,texture_storage), _extension(GL,EXT,map_buffer_range), + _extension(GL,EXT,instanced_arrays), _extension(GL,EXT,draw_instanced), _extension(GL,NV,draw_buffers), _extension(GL,NV,fbo_color_attachments), @@ -233,6 +234,7 @@ const std::vector& Extension::extensions(Version version) { _extension(GL,NV,draw_instanced), _extension(GL,NV,framebuffer_blit), _extension(GL,NV,framebuffer_multisample), + _extension(GL,NV,instanced_arrays), _extension(GL,NV,shadow_samplers_array), _extension(GL,NV,shadow_samplers_cube), _extension(GL,OES,depth24), diff --git a/src/Magnum/Extensions.h b/src/Magnum/Extensions.h index c41039c9f..dc4dc0cab 100644 --- a/src/Magnum/Extensions.h +++ b/src/Magnum/Extensions.h @@ -255,6 +255,7 @@ namespace GL { #endif _extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 #ifdef MAGNUM_TARGET_GLES2 + _extension(GL,EXT,instanced_arrays, GLES200, GLES300) // #156 _extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157 #endif #ifndef MAGNUM_TARGET_GLES2 @@ -276,6 +277,7 @@ namespace GL { _extension(GL,NV,draw_instanced, GLES200, GLES300) // #141 _extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142 _extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143 + _extension(GL,NV,instanced_arrays, GLES200, GLES300) // #145 _extension(GL,NV,shadow_samplers_array, GLES200, GLES300) // #146 _extension(GL,NV,shadow_samplers_cube, GLES200, GLES300) // #147 #endif diff --git a/src/Magnum/Implementation/MeshState.cpp b/src/Magnum/Implementation/MeshState.cpp index b7946673f..66d56fb57 100644 --- a/src/Magnum/Implementation/MeshState.cpp +++ b/src/Magnum/Implementation/MeshState.cpp @@ -117,6 +117,24 @@ MeshState::MeshState(Context& context, std::vector& extensions): cu drawArraysInstancedImplementation = nullptr; drawElementsInstancedImplementation = nullptr; } + + /* Instanced arrays implementation on ES2 */ + if(context.isExtensionSupported()) { + /* Extension added above */ + + vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE; + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::EXT::instanced_arrays::string()); + + vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT; + + } else if(context.isExtensionSupported()) { + extensions.push_back(Extensions::GL::NV::instanced_arrays::string()); + + vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV; + + } else vertexAttribDivisorImplementation = nullptr; #endif } diff --git a/src/Magnum/Implementation/MeshState.h b/src/Magnum/Implementation/MeshState.h index f91dd4e5c..2c39037fc 100644 --- a/src/Magnum/Implementation/MeshState.h +++ b/src/Magnum/Implementation/MeshState.h @@ -44,6 +44,9 @@ struct MeshState { void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&); #endif #endif + #ifdef MAGNUM_TARGET_GLES2 + void(Mesh::*vertexAttribDivisorImplementation)(GLuint, GLuint); + #endif void(Mesh::*bindIndexBufferImplementation)(Buffer&); void(Mesh::*bindImplementation)(); void(Mesh::*unbindImplementation)(); diff --git a/src/Magnum/Implementation/setupDriverWorkarounds.cpp b/src/Magnum/Implementation/setupDriverWorkarounds.cpp index 08f311c96..e909bf48f 100644 --- a/src/Magnum/Implementation/setupDriverWorkarounds.cpp +++ b/src/Magnum/Implementation/setupDriverWorkarounds.cpp @@ -77,6 +77,7 @@ void Context::setupDriverWorkarounds() { #endif _setRequiredVersion(GL::EXT::texture_storage, None); _setRequiredVersion(GL::EXT::map_buffer_range, None); + _setRequiredVersion(GL::EXT::instanced_arrays, None); _setRequiredVersion(GL::EXT::draw_instanced, None); _setRequiredVersion(GL::NV::draw_buffers, None); _setRequiredVersion(GL::NV::fbo_color_attachments, None); // ?? @@ -84,6 +85,7 @@ void Context::setupDriverWorkarounds() { _setRequiredVersion(GL::NV::draw_instanced, None); _setRequiredVersion(GL::NV::framebuffer_blit, None); _setRequiredVersion(GL::NV::framebuffer_multisample, None); + _setRequiredVersion(GL::NV::instanced_arrays, None); _setRequiredVersion(GL::OES::texture_3D, None); _setRequiredVersion(GL::OES::vertex_array_object, None); #endif diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index 1c9ee808d..219b004ff 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -348,6 +348,7 @@ void Mesh::attributePointerImplementationVAO(const Attribute& attribute) { void Mesh::attributePointerImplementationDSA(const Attribute& attribute) { glEnableVertexArrayAttribEXT(_id, attribute.location); glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset); + if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); } #endif @@ -355,6 +356,13 @@ void Mesh::vertexAttribPointer(const Attribute& attribute) { glEnableVertexAttribArray(attribute.location); attribute.buffer->bind(Buffer::Target::Array); glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast(attribute.offset)); + if(attribute.divisor) { + #ifndef MAGNUM_TARGET_GLES2 + glVertexAttribDivisor(attribute.location, attribute.divisor); + #else + (this->*Context::current()->state().mesh->vertexAttribDivisorImplementation)(attribute.location, attribute.divisor); + #endif + } } #ifndef MAGNUM_TARGET_GLES2 @@ -375,6 +383,7 @@ void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute) void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) { glEnableVertexArrayAttribEXT(_id, attribute.location); glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); + if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); } #endif @@ -382,6 +391,7 @@ void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) { glEnableVertexAttribArray(attribute.location); attribute.buffer->bind(Buffer::Target::Array); glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); + if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor); } #endif @@ -402,12 +412,37 @@ void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) { void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) { glEnableVertexArrayAttribEXT(_id, attribute.location); glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset); + if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor); } void Mesh::vertexAttribPointer(const LongAttribute& attribute) { glEnableVertexAttribArray(attribute.location); attribute.buffer->bind(Buffer::Target::Array); glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast(attribute.offset)); + if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor); +} +#endif + +#ifdef MAGNUM_TARGET_GLES2 +void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLuint divisor) { + //glVertexAttribDivisorANGLE(index, divisor); + CORRADE_INTERNAL_ASSERT(false); + static_cast(index); + static_cast(divisor); +} + +void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint divisor) { + //glVertexAttribDivisorEXT(index, divisor); + CORRADE_INTERNAL_ASSERT(false); + static_cast(index); + static_cast(divisor); +} + +void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) { + //glVertexAttribDivisorNV(index, divisor); + CORRADE_INTERNAL_ASSERT(false); + static_cast(index); + static_cast(divisor); } #endif diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index 81788c55e..50c5d7d3b 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -669,7 +669,34 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * if @extension{APPLE,vertex_array_object} is available */ template inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) { - addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), attributes...); + addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...); + return *this; + } + + /** + * @brief Add instanced vertex buffer + * @return Reference to self (for method chaining) + * + * Similar to the above function, the @p divisor parameter specifies + * number of instances that will pass until new data are fetched from + * the buffer. Setting it to `0` is equivalent to calling + * @ref addVertexBuffer(). + * @see @ref maxVertexAttributes(), @ref setPrimitive(), + * @ref setCount(), @ref setInstanceCount(), @ref setBaseInstance(), + * @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray}, + * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, + * @fn_gl{VertexAttribDivisor} or + * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, + * @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access}, + * @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} + * if @extension{APPLE,vertex_array_object} is available + * @requires_gl33 %Extension @extension{ARB,instanced_arrays} + * @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays}, + * @es_extension{EXT,instanced_arrays} or + * @es_extension{NV,instanced_arrays} in OpenGL ES 2.0. + */ + template inline Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) { + addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...); return *this; } @@ -773,6 +800,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { bool normalized; GLintptr offset; GLsizei stride; + GLuint divisor; }; #ifndef MAGNUM_TARGET_GLES2 @@ -783,6 +811,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLenum type; GLintptr offset; GLsizei stride; + GLuint divisor; }; #ifndef MAGNUM_TARGET_GLES @@ -793,6 +822,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLenum type; GLintptr offset; GLsizei stride; + GLuint divisor; }; #endif #endif @@ -808,19 +838,19 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { static GLsizei strideOfInterleaved() { return 0; } /* Adding interleaved vertex attributes */ - template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { - addVertexAttribute(buffer, attribute, offset, stride); + template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, const AbstractShaderProgram::Attribute& attribute, const U&... attributes) { + addVertexAttribute(buffer, attribute, offset, stride, divisor); /* Add size of this attribute to offset for next attribute */ - addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount, stride, attributes...); + addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute::VectorCount, stride, divisor, attributes...); } - template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { + template void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) { /* Add the gap to offset for next attribute */ - addVertexBufferInternal(buffer, offset+gap, stride, attributes...); + addVertexBufferInternal(buffer, offset+gap, stride, divisor, attributes...); } - void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {} + void addVertexBufferInternal(Buffer&, GLsizei, GLuint, GLintptr) {} - template void addVertexAttribute(typename std::enable_if::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(Attribute{ &buffer, @@ -829,24 +859,26 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLenum(attribute.dataType()), bool(attribute.dataOptions() & AbstractShaderProgram::Attribute::DataOption::Normalized), GLintptr(offset+i*attribute.vectorSize()), - stride + stride, + divisor }); } #ifndef MAGNUM_TARGET_GLES2 - template void addVertexAttribute(typename std::enable_if::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { attributePointerInternal(IntegerAttribute{ &buffer, location, GLint(attribute.components()), GLenum(attribute.dataType()), offset, - stride + stride, + divisor }); } #ifndef MAGNUM_TARGET_GLES - template void addVertexAttribute(typename std::enable_if::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride) { + template void addVertexAttribute(typename std::enable_if::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute& attribute, GLintptr offset, GLsizei stride, GLuint divisor) { for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute::VectorCount; ++i) attributePointerInternal(LongAttribute{ &buffer, @@ -854,7 +886,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLint(attribute.components()), GLenum(attribute.dataType()), GLintptr(offset+i*attribute.vectorSize()), - stride + stride, + divisor }); } #endif @@ -902,6 +935,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute); #endif + #ifdef MAGNUM_TARGET_GLES2 + void MAGNUM_LOCAL vertexAttribDivisorImplementationANGLE(GLuint index, GLuint divisor); + void MAGNUM_LOCAL vertexAttribDivisorImplementationEXT(GLuint index, GLuint divisor); + void MAGNUM_LOCAL vertexAttribDivisorImplementationNV(GLuint index, GLuint divisor); + #endif + void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&); void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer); diff --git a/src/Magnum/Test/MeshGLTest.cpp b/src/Magnum/Test/MeshGLTest.cpp index 28f9bde6b..3248676fb 100644 --- a/src/Magnum/Test/MeshGLTest.cpp +++ b/src/Magnum/Test/MeshGLTest.cpp @@ -118,6 +118,14 @@ class MeshGLTest: public AbstractOpenGLTester { void setInstanceCountBaseVertex(); void setInstanceCountBaseVertexBaseInstance(); #endif + + void addVertexBufferInstancedFloat(); + #ifndef MAGNUM_TARGET_GLES2 + void addVertexBufferInstancedInteger(); + #endif + #ifndef MAGNUM_TARGET_GLES + void addVertexBufferInstancedDouble(); + #endif }; MeshGLTest::MeshGLTest() { @@ -191,7 +199,15 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::setInstanceCountBaseInstance, &MeshGLTest::setInstanceCountBaseInstanceIndexed, &MeshGLTest::setInstanceCountBaseVertex, - &MeshGLTest::setInstanceCountBaseVertexBaseInstance + &MeshGLTest::setInstanceCountBaseVertexBaseInstance, + #endif + + &MeshGLTest::addVertexBufferInstancedFloat, + #ifndef MAGNUM_TARGET_GLES2 + &MeshGLTest::addVertexBufferInstancedInteger, + #endif + #ifndef MAGNUM_TARGET_GLES + &MeshGLTest::addVertexBufferInstancedDouble #endif }); } @@ -1538,6 +1554,121 @@ void MeshGLTest::setInstanceCountBaseVertexBaseInstance() { } #endif +void MeshGLTest::addVertexBufferInstancedFloat() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available.")); + #elif defined(MAGNUM_TARGET_GLES2) + if(!Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required instancing extension is not available."); + if(!Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported() && !Context::current()->isExtensionSupported()) + CORRADE_SKIP("Required drawing extension is not available."); + #endif + + typedef AbstractShaderProgram::Attribute<0, Float> Attribute; + + const Float data[] = { + 0.0f, /* Offset */ + /* Base vertex is ignored for instanced arrays */ + -0.7f, /* First instance */ + 0.3f, /* Second instance */ + Math::normalize(96) /* Third instance */ + }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .addVertexBufferInstanced(buffer, 1, 4, Attribute{}); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + mesh).get(ColorFormat::RGBA, ColorType::UnsignedByte); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 96); +} + +#ifndef MAGNUM_TARGET_GLES2 +void MeshGLTest::addVertexBufferInstancedInteger() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); + #endif + + typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute; + + constexpr UnsignedInt data[] = { + 0, /* Offset */ + /* Base vertex is ignored for instanced arrays */ + 157, /* First instance */ + 25, /* Second instance */ + 35681 /* Third instance */ + }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .addVertexBufferInstanced(buffer, 1, 4, Attribute{}); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R32UI, mesh) + .get(ColorFormat::RedInteger, ColorType::UnsignedInt); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 35681); +} +#endif + +#ifndef MAGNUM_TARGET_GLES +void MeshGLTest::addVertexBufferInstancedDouble() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available.")); + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + + typedef AbstractShaderProgram::Attribute<0, Double> Attribute; + + const Double data[] = { + 0.0, /* Offset */ + /* Base vertex is ignored for instanced arrays */ + -0.7, /* First instance */ + 0.3, /* Second instance */ + Math::normalize(45828) /* Third instance */ + }; + Buffer buffer; + buffer.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setInstanceCount(3) + .addVertexBufferInstanced(buffer, 1, 8, Attribute{}); + + MAGNUM_VERIFY_NO_ERROR(); + + const auto value = Checker(DoubleShader("double", "float", "vec4(value, 0.0, 0.0, 0.0)"), + RenderbufferFormat::R16, mesh).get(ColorFormat::Red, ColorType::UnsignedShort); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(value, 45828); +} +#endif + }} CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) From 4573c357a24a73e99b63e4b82fa1fcd895c19671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 20:42:42 +0200 Subject: [PATCH 44/46] Platform: default to non-resizable window in Sdl2Application. The user is not required to provide viewportEvent() implementation, thus it's not wise to allow resizing by default. --- src/Magnum/Platform/Sdl2Application.cpp | 2 +- src/Magnum/Platform/Sdl2Application.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 14cd04f21..c1d606990 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -334,7 +334,7 @@ Sdl2Application::Configuration::Configuration(): #ifndef CORRADE_TARGET_EMSCRIPTEN _title("Magnum SDL2 Application"), #endif - _size(800, 600), _windowFlags(WindowFlag::Resizable), _sampleCount(0) + _size(800, 600), _windowFlags{}, _sampleCount(0) #ifndef CORRADE_TARGET_EMSCRIPTEN , _version(Version::None) #endif diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index caab3163a..cf445465e 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -530,7 +530,7 @@ class Sdl2Application::Configuration { * @brief Set window flags * @return Reference to self (for method chaining) * - * Default is @ref WindowFlag::Resizable. + * Default are none. */ Configuration& setWindowFlags(WindowFlags flags) { _windowFlags = flags; From 8a412f1d5de998be1552e2118686fcc2316c3ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 20:22:42 +0200 Subject: [PATCH 45/46] Use SDL 2 instead of GLUT as the default and recommended toolkit. --- README.md | 8 ++--- doc/building.dox | 4 +-- doc/cmake.dox | 2 +- doc/getting-started-blue.png | Bin 7677 -> 7538 bytes doc/getting-started.dox | 26 +++++++------- doc/getting-started.png | Bin 7630 -> 7696 bytes doc/mainpage.dox | 4 +-- doc/platform.dox | 38 +++++++++++---------- package/archlinux/magnum-git/PKGBUILD | 4 +-- src/Magnum/DebugTools/Profiler.h | 2 +- src/Magnum/DefaultFramebuffer.h | 4 +-- src/Magnum/Platform/AbstractXApplication.h | 8 ++--- src/Magnum/Platform/AndroidApplication.h | 4 +-- src/Magnum/Platform/GlxApplication.h | 4 +-- src/Magnum/Platform/NaClApplication.h | 4 +-- src/Magnum/Platform/XEglApplication.h | 4 +-- src/Magnum/Renderer.h | 2 +- 17 files changed, 61 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 68cfeae81..5a22c7889 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ Graphics APIs: Platforms: * **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through - GLUT or SDL2 toolkit) -* **Windows** (through GLUT or SDL2 toolkit) + SDL2 or GLUT toolkit) +* **Windows** (through SDL2 or GLUT toolkit) * **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) * **Android** 2.3 (API Level 9) and higher * **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), @@ -97,13 +97,13 @@ Note that full feature set is available only on GCC 4.8.1 and Clang 3.1. Compilation, installation ------------------------- -The library (for example with support for GLUT applications) can be built and +The library (for example with support for SDL2 applications) can be built and installed using these four commands: mkdir -p build && cd build cmake .. \ -DCMAKE_INSTALL_PREFIX=/usr \ - -DWITH_GLUTAPPLICATION=ON + -DWITH_SDL2APPLICATION=ON make make install diff --git a/doc/building.dox b/doc/building.dox index c513a58da..53ac127ee 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -66,13 +66,13 @@ assuming you have at least basic knowledge of CMake. @subsection building-linux Via command-line (on Linux/Unix) -On Unix-based OSs, the library (for example with support for GLUT applications) +On Unix-based OSs, the library (for example with support for SDL2 applications) can be built and installed using these four commands: mkdir build && cd build cmake .. \ -DCMAKE_INSTALL_PREFIX=/usr \ - -DWITH_GLUTAPPLICATION=ON + -DWITH_SDL2APPLICATION=ON make make install diff --git a/doc/cmake.dox b/doc/cmake.dox index d5b7aa086..c8cb7b1cb 100644 --- a/doc/cmake.dox +++ b/doc/cmake.dox @@ -120,7 +120,7 @@ in build and use it with CMake. Example usage with specifying additional components is: - find_package(Magnum REQUIRED MeshTools Primitives GlutApplication) + find_package(Magnum REQUIRED MeshTools Primitives Sdl2Application) For each component is then defined: diff --git a/doc/getting-started-blue.png b/doc/getting-started-blue.png index 50b64d15cd99bdfa15f7e23c70f6422459b6ebcd..10e381ddb879ffda7aadd237e46960040bd6fbbc 100644 GIT binary patch literal 7538 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 diff --git a/doc/getting-started.dox b/doc/getting-started.dox index adcdd39a7..35b90f9ad 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -33,10 +33,11 @@ namespace Magnum { Get latest version from GitHub and install it. Read full guide on @ref building "how to download, build and install Magnum" on platform of your -choice. For our first project we will use GLUT toolkit, don't forget to enable -it for building using `WITH_GLUTAPPLICATION` CMake parameter. On newer systems, -Mac OS X and Windows you might want to use SDL2 toolkit instead, it is enabled -using `WITH_SDL2APPLICATION` CMake parameter. +choice. For our first project we will use SDL2 toolkit, don't forget to enable +it for building using `WITH_SDL2APPLICATION` CMake parameter. On older Linux +distributions which don't have SDL2 in the repositories you might want to use +GLUT toolkit instead, it is enabled using `WITH_GLUTAPPLICATION` CMake +parameter. @section getting-started-bootstrap Download bootstrap project @@ -54,8 +55,8 @@ extract it somewhere. Do it rather than cloning the full repository, as it's better to init your own repository from scratch to avoid having the history polluted. -If you want to use SDL2 instead of GLUT, download the `base-sdl2` branch -[archive](https://github.com/mosra/magnum-bootstrap/archive/base-sdl2.zip). +If you want to use GLUT instead of SDL2, download the `base-glut` branch +[archive](https://github.com/mosra/magnum-bootstrap/archive/base-glut.zip). The code will be slightly different from what is presented below, but the changes are only minor (two modified lines and one additional file) and the main principles are the same. @@ -67,6 +68,7 @@ CMake build system, see @ref cmake for more information. modules/FindCorrade.cmake modules/FindMagnum.cmake + modules/FindSDL2.cmake src/MyApplication.cpp src/CMakeLists.txt CMakeLists.txt @@ -86,8 +88,8 @@ add_subdirectory(src) @endcode Directory `modules/` contains CMake modules for finding the needed -dependencies. Unlike modules for finding e.g. GLUT and OpenGL, which are part -of standard CMake installation, these aren't part of it and thus must be +dependencies. Unlike modules for finding e.g. OpenGL, which are part of +standard CMake installation, these aren't part of it and thus must be distributed with the project. These files are just verbatim copied from %Magnum repository. @@ -95,7 +97,7 @@ Directory `src/` contains the actual project. To keep things simple, the project consists of just one source file with the most minimal code possible: @code #include -#include +#include using namespace Magnum; @@ -127,7 +129,7 @@ default (dark gray) color and then does buffer swap to actually display it on the screen. `CMakeLists.txt` finds %Magnum, sets up compiler flags, creates the executable and links it to all needed libraries: @code -find_package(Magnum REQUIRED GlutApplication) +find_package(Magnum REQUIRED Sdl2Application) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) @@ -169,8 +171,8 @@ where to create build directory, allows you to specify initial CMake parameters everything is ready to be built. If CMake isn't able to find the dependencies on Windows, you might want to look -at @ref building-windows. If CMake complains about `GlutApplication` missing, -you forgot to enable `WITH_GLUTAPPLICATION` when building %Magnum, +at @ref building-windows. If CMake complains about `Sdl2Application` missing, +you forgot to enable `WITH_SDL2APPLICATION` when building %Magnum, @ref getting-started-download "go back and fix it". @image html getting-started.png diff --git a/doc/getting-started.png b/doc/getting-started.png index 7f4cf8c3ab82fa72f45aff6272a7df0332fa6a75..2df2b37b3f233f83b2bece7db7c39b69be096ef4 100644 GIT binary patch literal 7696 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 literal 7630 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 diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 920ad37cb..64774d72e 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -75,8 +75,8 @@ Graphics APIs: Platforms: - **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through - GLUT or SDL2 toolkit) -- **Windows** (through GLUT or SDL2 toolkit) + SDL2 or GLUT toolkit) +- **Windows** (through SDL2 or GLUT toolkit) - **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt)) - **Android** 2.3 (API Level 9) and higher - **Google Chrome** (through [Native Client](https://developers.google.com/native-client/), diff --git a/doc/platform.dox b/doc/platform.dox index 44c6700a5..633f38057 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -45,12 +45,12 @@ to subclass the chosen `*Application` class and implement required methods. @section platform-windowed Windowed applications Windowed applications provide a window and keyboard and mouse handling. The -most basic toolkit (and toolkit packaged for most systems) is GLUT, which is -implemented in @ref Platform::GlutApplication. As said above, the usage is -similar for all toolkits, you must provide one-argument constructor and -implement at least @ref GlutApplication::drawEvent() "drawEvent()" function. -The class can be then used directly in `main()`, but for convenience and -portability it's better to use @ref MAGNUM_GLUTAPPLICATION_MAIN() macro. +de-facto standard and most widely used toolkit is SDL2, which is implemented in +@ref Platform::Sdl2Application. As said above, the usage is similar for all +toolkits, you must provide one-argument constructor and implement at least +@ref Sdl2Application::drawEvent() "drawEvent()" function. The class can be then +used directly in `main()`, but for convenience and portability it's better to +use @ref MAGNUM_SDL2APPLICATION_MAIN() macro. To simplify the porting, the library provides `Platform::Application` typedef and `MAGNUM_APPLICATION_MAIN()` macro (but only if only one application header @@ -69,7 +69,7 @@ blue color is shown in the following code listing. #include #include #include -#include +#include using namespace Magnum; @@ -103,7 +103,7 @@ MAGNUM_APPLICATION_MAIN(MyApplication) By default the application doesn't respond to window size changes in any way, as the window has fixed size in most cases. To respond to size change for example by resizing the default framebuffer, you need to reimplement -@ref GlutApplication::viewportEvent() "viewportEvent()" function and pass the +@ref Sdl2Application::viewportEvent() "viewportEvent()" function and pass the new size to the framebuffer: @code class MyApplication: public Platform::Application { @@ -177,19 +177,21 @@ MAGNUM_WINDOWLESSAPPLICATION_MAIN(MyApplication) @section platform-compilation Compilation with CMake Barebone compilation consists just of finding %Magnum library with required -`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and application-specific `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path, compilation of the -executable and linking `${MAGNUM_LIBRARIES}` and `${MAGNUM_GLUTAPPLICATION_LIBRARIES}` -to it. +`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and +application-specific `${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path, +compilation of the executable and linking `${MAGNUM_LIBRARIES}` and +`${MAGNUM_SDL2APPLICATION_LIBRARIES}` to it. Again, to simplify porting, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` -and `${MAGNUM_WAPPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`, `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but +and `${MAGNUM_WAPPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`, +`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but only if only one application (windowless application) component is requested to avoid ambiguity. Changing the build script to use different toolkit is then matter of replacing only the requested `*Application` component (and one #`include` line in the actual code, as said above). @code -find_package(Magnum REQUIRED GlutApplication) +find_package(Magnum REQUIRED Sdl2Application) include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) @@ -203,7 +205,7 @@ target_link_libraries(myapplication By default the application is created with some reasonable defaults (e.g. window size 800x600 pixels). If you want something else, you can pass -@ref GlutApplication::Configuration "Configuration" instance to application +@ref Sdl2Application::Configuration "Configuration" instance to application constructor. Using method chaining it can be done conveniently like this: @code MyApplication::MyApplication(int& argc, char** argv): @@ -217,8 +219,8 @@ MyApplication::MyApplication(int& argc, char** argv): However, sometimes you would need to configure the application based on some configuration file or system introspection. In that case you can pass `nullptr` -instead of @ref GlutApplication::Configuration "Configuration" instance and -then specify it later with @ref GlutApplication::createContext() "createContext()": +instead of @ref Sdl2Application::Configuration "Configuration" instance and +then specify it later with @ref Sdl2Application::createContext() "createContext()": @code MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) { // ... @@ -231,9 +233,9 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc } @endcode -If the context creation in constructor or @ref GlutApplication::createContext() "createContext()" +If the context creation in constructor or @ref Sdl2Application::createContext() "createContext()" fails, the application exits. However, it is also possible to negotiate the -context using @ref GlutApplication::tryCreateContext() "tryCreateContext()". +context using @ref Sdl2Application::tryCreateContext() "tryCreateContext()". The only difference is that this function returns `false` instead of exiting. You can for example try enabling MSAA and if the context creation fails, fall back to no-AA rendering: diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index 660b77f98..26335fba5 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -6,7 +6,7 @@ pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)" arch=('i686' 'x86_64') url="http://mosra.cz/blog/magnum.php" license=('MIT') -depends=('corrade-git' 'openal' 'freeglut') +depends=('corrade-git' 'openal' 'sdl2') makedepends=('cmake' 'git') provides=('magnum') conflicts=('magnum') @@ -40,7 +40,7 @@ build() { -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DWITH_AUDIO=ON \ - -DWITH_GLUTAPPLICATION=ON \ + -DWITH_SDL2APPLICATION=ON \ -DWITH_GLXAPPLICATION=ON \ -DWITH_WINDOWLESSGLXAPPLICATION=ON \ -DWITH_MAGNUMFONT=ON \ diff --git a/src/Magnum/DebugTools/Profiler.h b/src/Magnum/DebugTools/Profiler.h index 85b2070df..9c6a4cfff 100644 --- a/src/Magnum/DebugTools/Profiler.h +++ b/src/Magnum/DebugTools/Profiler.h @@ -43,7 +43,7 @@ namespace Magnum { namespace DebugTools { @brief %Profiler Measures time passed during specified sections of each frame. It's meant to be -used in rendering and event loops (e.g. Platform::GlutApplication::drawEvent()), +used in rendering and event loops (e.g. Platform::Sdl2Application::drawEvent()), but it's possible to use it standalone elsewhere. Example usage: @code DebugTools::Profiler p; diff --git a/src/Magnum/DefaultFramebuffer.h b/src/Magnum/DefaultFramebuffer.h index 347d3e3dd..b28353fea 100644 --- a/src/Magnum/DefaultFramebuffer.h +++ b/src/Magnum/DefaultFramebuffer.h @@ -45,7 +45,7 @@ surface. When you are using only the default framebuffer, the usage is simple. You must ensure that it is properly resized when application surface is resized, -i.e. you must pass the new size in your @ref Platform::GlutApplication::viewportEvent() "viewportEvent()" +i.e. you must pass the new size in your @ref Platform::Sdl2Application::viewportEvent() "viewportEvent()" implementation, for example: @code void viewportEvent(const Vector2i& size) { @@ -56,7 +56,7 @@ void viewportEvent(const Vector2i& size) { @endcode Next thing you probably want is to clear all used buffers before performing -any drawing in your @ref Platform::GlutApplication::drawEvent() "drawEvent()" +any drawing in your @ref Platform::Sdl2Application::drawEvent() "drawEvent()" implementation, for example: @code void drawEvent() { diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 00eee6066..2d95ec5cc 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -220,19 +220,19 @@ class AbstractXApplication::Configuration { return *this; } - /** @copydoc GlutApplication::Configuration::size() */ + /** @copydoc Sdl2Application::Configuration::size() */ Vector2i size() const { return _size; } - /** @copydoc GlutApplication::Configuration::setSize() */ + /** @copydoc Sdl2Application::Configuration::setSize() */ Configuration& setSize(const Vector2i& size) { _size = size; return *this; } - /** @copydoc GlutApplication::Configuration::version() */ + /** @copydoc Sdl2Application::Configuration::version() */ Version version() const { return _version; } - /** @copydoc GlutApplication::Configuration::setVersion() */ + /** @copydoc Sdl2Application::Configuration::setVersion() */ Configuration& setVersion(Version version) { _version = version; return *this; diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 38d482c4b..4b9a2431f 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -59,14 +59,14 @@ CMake. ## Bootstrap application -Fully contained base application using @ref GlutApplication for desktop build +Fully contained base application using @ref Sdl2Application for desktop build and @ref AndroidApplication for Android build along with full Android packaging stuff and CMake setup is available in `base-android` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-android.tar.gz) or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-android.zip) file. After extracting the downloaded archive, you can do the desktop build in the -same way as with @ref GlutApplication. For the Android build you also +same way as with @ref Sdl2Application. For the Android build you also need to put the contents of toolchains repository from https://github.com/mosra/toolchains in `toolchains/` subdirectory. Don't forget to adapt `ANDROID_NDK_ROOT` in `toolchains/generic/Android-*.cmake` to path where NDK is installed. Default is diff --git a/src/Magnum/Platform/GlxApplication.h b/src/Magnum/Platform/GlxApplication.h index 8aead290a..f714c1a0c 100644 --- a/src/Magnum/Platform/GlxApplication.h +++ b/src/Magnum/Platform/GlxApplication.h @@ -76,10 +76,10 @@ to simplify porting. */ class GlxApplication: public AbstractXApplication { public: - /** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */ + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ explicit GlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); - /** @copydoc Sdl2Application::GlutApplication(const Arguments&, std::nullptr_t) */ + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ explicit GlxApplication(const Arguments& arguments, std::nullptr_t); protected: diff --git a/src/Magnum/Platform/NaClApplication.h b/src/Magnum/Platform/NaClApplication.h index 63fe8c491..641067e7c 100644 --- a/src/Magnum/Platform/NaClApplication.h +++ b/src/Magnum/Platform/NaClApplication.h @@ -68,14 +68,14 @@ CMake. ## Bootstrap application -Fully contained base application using @ref GlutApplication for desktop build +Fully contained base application using @ref Sdl2Application for desktop build and @ref NaClApplication for Native Client build along with full HTML markup and CMake setup is available in `base-nacl` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository, download it as [tar.gz](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.tar.gz) or [zip](https://github.com/mosra/magnum-bootstrap/archive/base-nacl.zip) file. After extracting the downloaded archive, you can do the desktop build in the -same way as with @ref GlutApplication. For the Native Client build you also +same way as with @ref Sdl2Application. For the Native Client build you also need to put the contents of toolchains repository from https://github.com/mosra/toolchains in `toolchains/` subdirectory. Don't forget to adapt `NACL_PREFIX` variable in `toolchains/generic/NaCl-newlib-x86-32.cmake` and diff --git a/src/Magnum/Platform/XEglApplication.h b/src/Magnum/Platform/XEglApplication.h index 067cd8476..e930b313b 100644 --- a/src/Magnum/Platform/XEglApplication.h +++ b/src/Magnum/Platform/XEglApplication.h @@ -76,10 +76,10 @@ to simplify porting. */ class XEglApplication: public AbstractXApplication { public: - /** @copydoc Sdl2Application::GlutApplication(const Arguments&, const Configuration&) */ + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, const Configuration&) */ explicit XEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()); - /** @copydoc Sdl2Application::GlutApplication(const Arguments&, std::nullptr_t) */ + /** @copydoc Sdl2Application::Sdl2Application(const Arguments&, std::nullptr_t) */ explicit XEglApplication(const Arguments& arguments, std::nullptr_t); protected: diff --git a/src/Magnum/Renderer.h b/src/Magnum/Renderer.h index ff2226294..b26bd93f2 100644 --- a/src/Magnum/Renderer.h +++ b/src/Magnum/Renderer.h @@ -145,7 +145,7 @@ class MAGNUM_EXPORT Renderer { /** * Multisampling. Enabled by default. Note that the actual presence * of this feature in default framebuffer depends on context - * configuration, see for example Platform::GlutApplication::Configuration::setSampleCount(). + * configuration, see for example @ref Platform::Sdl2Application::Configuration::setSampleCount(). * @requires_gl Always enabled in OpenGL ES. */ Multisampling = GL_MULTISAMPLE, From cb1649a3f983c6162f171c40f6a14f5156854389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 27 Apr 2014 20:55:25 +0200 Subject: [PATCH 46/46] package: update ArchLinux PKGBUILD. --- package/archlinux/magnum-git/PKGBUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/archlinux/magnum-git/PKGBUILD b/package/archlinux/magnum-git/PKGBUILD index 26335fba5..176a5bf9b 100644 --- a/package/archlinux/magnum-git/PKGBUILD +++ b/package/archlinux/magnum-git/PKGBUILD @@ -1,6 +1,6 @@ # Author: mosra pkgname=magnum-git -pkgver=20140123 +pkgver=20140427 pkgrel=1 pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Git version)" arch=('i686' 'x86_64')