Browse Source

Shaders: support object ID textures in the FlatGL shader.

pull/547/head
Vladimír Vondruš 4 years ago
parent
commit
b2a400f898
  1. 2
      doc/changelog.dox
  2. 18
      src/Magnum/Shaders/Flat.frag
  3. 6
      src/Magnum/Shaders/Flat.h
  4. 71
      src/Magnum/Shaders/FlatGL.cpp
  5. 80
      src/Magnum/Shaders/FlatGL.h
  6. 486
      src/Magnum/Shaders/Test/FlatGLTest.cpp
  7. 12
      src/Magnum/Shaders/Test/FlatGL_Test.cpp

2
doc/changelog.dox

@ -205,6 +205,8 @@ See also:
updated with an introduction the new features.
- @ref Shaders::FlatGL and @ref Shaders::PhongGL now support texture arrays,
available also in multi-draw and instanced scenarios
- @ref Shaders::FlatGL now supports object ID textures in addition to uniform
and per-vertex object ID
- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
recently added @ref Trade::MaterialAttribute::NormalTextureScale material
attribute

18
src/Magnum/Shaders/Flat.frag

@ -131,9 +131,22 @@ uniform lowp
textureData;
#endif
#ifdef OBJECT_ID_TEXTURE
#ifdef EXPLICIT_BINDING
layout(binding = 5)
#endif
uniform lowp
#ifndef TEXTURE_ARRAYS
usampler2D
#else
usampler2DArray
#endif
objectIdTextureData;
#endif
/* Inputs */
#ifdef TEXTURED
#if defined(TEXTURED) || defined(OBJECT_ID_TEXTURE)
in mediump
#ifndef TEXTURE_ARRAYS
vec2
@ -208,6 +221,9 @@ void main() {
#ifdef INSTANCED_OBJECT_ID
interpolatedInstanceObjectId +
#endif
#ifdef OBJECT_ID_TEXTURE
texture(objectIdTextureData, interpolatedTextureCoordinates).r +
#endif
objectId;
#endif
}

6
src/Magnum/Shaders/Flat.h

@ -143,8 +143,10 @@ struct FlatDrawUniform {
* uniform data. Default value is @cpp 0 @ce.
*
* Used only if @ref FlatGL::Flag::ObjectId is enabled, ignored otherwise.
* If @ref FlatGL::Flag::InstancedObjectId is enabled as well, this value
* is added to the ID coming from the @ref FlatGL::ObjectId attribute.
* If @ref FlatGL::Flag::InstancedObjectId and/or
* @ref FlatGL::Flag::ObjectIdTexture is enabled as well, this value is
* added to the ID coming from the @ref FlatGL::ObjectId attribute and/or
* the texture.
* @see @ref FlatGL::setObjectId()
*/
UnsignedInt objectId;

71
src/Magnum/Shaders/FlatGL.cpp

@ -49,7 +49,11 @@
namespace Magnum { namespace Shaders {
namespace {
enum: Int { TextureUnit = 0 };
enum: Int {
TextureUnit = 0,
/* 1/2/3 taken by Phong (D/S/N), 4 by MeshVisualizer colormap */
ObjectIdTextureUnit = 5
};
#ifndef MAGNUM_TARGET_GLES2
enum: Int {
@ -74,8 +78,17 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
, _materialCount{materialCount}, _drawCount{drawCount}
#endif
{
CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & Flag::Textured),
"Shaders::FlatGL: texture transformation enabled but the shader is not textured", );
#ifndef CORRADE_NO_ASSERT
{
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
"Shaders::FlatGL: texture transformation enabled but the shader is not textured", );
}
#endif
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
@ -85,7 +98,7 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#endif
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & Flag::Textured),
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || flags & Flag::Textured || flags >= Flag::ObjectIdTexture,
"Shaders::FlatGL: texture arrays enabled but the shader is not textured", );
CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation),
"Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", );
@ -129,7 +142,11 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
vert.addSource((flags & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
) ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2
@ -161,6 +178,7 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(flags >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
#endif
;
#ifndef MAGNUM_TARGET_GLES2
@ -189,7 +207,11 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#endif
{
bindAttributeLocation(Position::Location, "position");
if(flags & Flag::Textured)
if(flags & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
@ -241,6 +263,7 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
{
if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit);
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("TransformationProjection"), TransformationProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
@ -429,12 +452,42 @@ template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindTex
}
#endif
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindObjectIdTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags >= Flag::ObjectIdTexture,
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::FlatGL::bindObjectIdTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
texture.bind(ObjectIdTextureUnit);
return *this;
}
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindObjectIdTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags >= Flag::ObjectIdTexture,
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
texture.bind(ObjectIdTextureUnit);
return *this;
}
#endif
template class MAGNUM_SHADERS_EXPORT FlatGL<2>;
template class MAGNUM_SHADERS_EXPORT FlatGL<3>;
namespace Implementation {
Debug& operator<<(Debug& debug, const FlatGLFlag value) {
#ifndef MAGNUM_TARGET_GLES2
/* Special case coming from the FlatGLFlags printer. As both flags are a
superset of ObjectId, printing just one would result in
`Flag::InstancedObjectId|Flag(0x800)` in the output. */
if(value == FlatGLFlag(UnsignedShort(FlatGLFlag::InstancedObjectId|FlatGLFlag::ObjectIdTexture)))
return debug << FlatGLFlag::InstancedObjectId << Debug::nospace << "|" << Debug::nospace << FlatGLFlag::ObjectIdTexture;
#endif
debug << "Shaders::FlatGL::Flag" << Debug::nospace;
switch(value) {
@ -447,6 +500,7 @@ Debug& operator<<(Debug& debug, const FlatGLFlag value) {
#ifndef MAGNUM_TARGET_GLES2
_c(ObjectId)
_c(InstancedObjectId)
_c(ObjectIdTexture)
#endif
_c(InstancedTransformation)
_c(InstancedTextureOffset)
@ -470,7 +524,12 @@ Debug& operator<<(Debug& debug, const FlatGLFlags value) {
FlatGLFlag::InstancedTextureOffset, /* Superset of TextureTransformation */
FlatGLFlag::TextureTransformation,
#ifndef MAGNUM_TARGET_GLES2
/* Both are a superset of ObjectId, meaning printing just one would
result in `Flag::InstancedObjectId|Flag(0x800)` in the output. So we
pass both and let the FlatGLFlag printer deal with that. */
FlatGLFlag(UnsignedShort(FlatGLFlag::InstancedObjectId|FlatGLFlag::ObjectIdTexture)),
FlatGLFlag::InstancedObjectId, /* Superset of ObjectId */
FlatGLFlag::ObjectIdTexture, /* Superset of ObjectId */
FlatGLFlag::ObjectId,
#endif
FlatGLFlag::InstancedTransformation,

80
src/Magnum/Shaders/FlatGL.h

@ -46,6 +46,7 @@ namespace Implementation {
#ifndef MAGNUM_TARGET_GLES2
ObjectId = 1 << 4,
InstancedObjectId = (1 << 5)|ObjectId,
ObjectIdTexture = (1 << 11)|ObjectId,
#endif
InstancedTransformation = 1 << 6,
InstancedTextureOffset = (1 << 7)|TextureTransformation,
@ -128,8 +129,10 @@ on framebuffers with integer attachments.
If you have a batch of meshes with different object IDs, enable
@ref Flag::InstancedObjectId and supply per-vertex IDs to the @ref ObjectId
attribute. The output will contain a sum of the per-vertex ID and ID coming
from @ref setObjectId().
attribute. The object ID can be also supplied from an integer texture bound via
@ref bindObjectIdTexture() if @ref Flag::ObjectIdTexture is enabled. The output
will contain a sum of the per-vertex ID, texture ID and ID coming from
@ref setObjectId().
@requires_gl30 Extension @gl_extension{EXT,texture_integer}
@requires_gles30 Object ID output requires integer support in shaders, which
@ -315,8 +318,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* Object ID shader output. @ref shaders-generic "Generic output",
* present only if @ref Flag::ObjectId is set. Expects a
* single-component unsigned integral attachment. Writes the value
* set in @ref setObjectId() there, see
* @ref Shaders-FlatGL-object-id for more information.
* set in @ref setObjectId() and possibly also a per-vertex ID and
* an ID fetched from a texture, see @ref Shaders-FlatGL-object-id
* for more information.
* @requires_gl30 Extension @gl_extension{EXT,texture_integer}
* @requires_gles30 Object ID output requires integer support in
* shaders, which is not available in OpenGL ES 2.0.
@ -397,6 +401,23 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* @m_since{2020,06}
*/
InstancedObjectId = (1 << 5)|ObjectId,
/**
* Object ID texture. Retrieves object IDs from a texture bound
* with @ref bindObjectIdTexture(), outputting a sum of the object
* ID texture, the ID coming from @ref setObjectId() or
* @ref FlatDrawUniform::objectId and possibly also the per-vertex
* ID, if @ref Flag::InstancedObjectId is enabled as well.
* Implicitly enables @ref Flag::ObjectId. See
* @ref Shaders-FlatGL-object-id for more information.
* @requires_gl30 Extension @gl_extension{EXT,gpu_shader4}
* @requires_gles30 Object ID output requires integer support in
* shaders, which is not available in OpenGL ES 2.0.
* @requires_webgl20 Object ID output requires integer support in
* shaders, which is not available in WebGL 1.0.
* @m_since_latest
*/
ObjectIdTexture = (1 << 11)|ObjectId,
#endif
/**
@ -728,8 +749,10 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* Expects that the shader was created with @ref Flag::ObjectId
* enabled. Value set here is written to the @ref ObjectIdOutput, see
* @ref Shaders-FlatGL-object-id for more information. Default is
* @cpp 0 @ce. If @ref Flag::InstancedObjectId is enabled as well, this
* value is added to the ID coming from the @ref ObjectId attribute.
* @cpp 0 @ce. If @ref Flag::InstancedObjectId and/or
* @ref Flag::ObjectIdTexture is enabled as well, this value is added
* to the ID coming from the @ref ObjectId attribute and/or the
* texture.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref FlatDrawUniform::objectId and call @ref bindDrawBuffer()
@ -903,6 +926,51 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
FlatGL<dimensions>& bindTexture(GL::Texture2DArray& texture);
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind an object ID texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with @ref Flag::ObjectIdTexture
* enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindObjectIdTexture(GL::Texture2DArray&) instead. The texture
* needs to have an unsigned integer format.
* @see @ref setObjectId(), @ref Flag::TextureTransformation,
* @ref setTextureMatrix()
* @requires_gl30 Extension @gl_extension{EXT,gpu_shader4}
* @requires_gles30 Object ID output requires integer support in
* shaders, which is not available in OpenGL ES 2.0.
* @requires_webgl20 Object ID output requires integer support in
* shaders, which is not available in WebGL 1.0.
*/
FlatGL<dimensions>& bindObjectIdTexture(GL::Texture2D& texture);
/**
* @brief Bind an object ID array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both
* @ref Flag::ObjectIdTexture and @ref Flag::TextureArrays enabled. If
* @ref Flag::UniformBuffers is not enabled, the layer is set via
* @ref setTextureLayer(); if @ref Flag::UniformBuffers is enabled,
* @ref Flag::TextureTransformation has to be enabled as well and the
* layer is set via @ref TextureTransformationUniform::layer.
* @see @ref setObjectId(), @ref Flag::TextureTransformation,
* @ref setTextureLayer()
* @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} and
* @gl_extension{EXT,texture_array}
* @requires_gles30 Object ID output requires integer support in
* shaders, which is not available in OpenGL ES 2.0. Texture
* arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Object ID output requires integer support in
* shaders, which is not available in WebGL 1.0. Texture arrays
* are not available in WebGL 1.0.
*/
FlatGL<dimensions>& bindObjectIdTexture(GL::Texture2DArray& texture);
#endif
/**
* @}
*/

486
src/Magnum/Shaders/Test/FlatGLTest.cpp

@ -94,9 +94,9 @@ struct FlatGLTest: GL::OpenGLTester {
template<UnsignedInt dimensions> void setUniformUniformBuffersEnabled();
template<UnsignedInt dimensions> void bindBufferUniformBuffersNotEnabled();
#endif
template<UnsignedInt dimensions> void bindTextureInvalid();
template<UnsignedInt dimensions> void bindTexturesInvalid();
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void bindTextureArrayInvalid();
template<UnsignedInt dimensions> void bindTextureArraysInvalid();
#endif
template<UnsignedInt dimensions> void setAlphaMaskNotEnabled();
template<UnsignedInt dimensions> void setTextureMatrixNotEnabled();
@ -211,6 +211,9 @@ constexpr struct {
{"object ID", FlatGL2D::Flag::ObjectId},
{"instanced object ID", FlatGL2D::Flag::InstancedObjectId},
{"object ID + alpha mask + textured", FlatGL2D::Flag::ObjectId|FlatGL2D::Flag::AlphaMask|FlatGL2D::Flag::Textured},
{"object ID texture", FlatGL2D::Flag::ObjectIdTexture},
{"instanced object ID texture array + texture transformation", FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::InstancedObjectId|FlatGL2D::Flag::TextureArrays|FlatGL2D::Flag::TextureTransformation},
{"object ID texture + textured", FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::Textured},
#endif
{"instanced transformation", FlatGL2D::Flag::InstancedTransformation},
{"instanced texture offset", FlatGL2D::Flag::Textured|FlatGL2D::Flag::InstancedTextureOffset},
@ -235,6 +238,9 @@ constexpr struct {
{"texture arrays + texture transformation", FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation, 1, 1},
{"alpha mask", FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::AlphaMask, 1, 1},
{"object ID", FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::ObjectId, 1, 1},
{"object ID texture", FlatGL2D::Flag::ObjectIdTexture, 1, 1},
{"instanced object ID texture array + texture transformation", FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::InstancedObjectId|FlatGL2D::Flag::TextureArrays|FlatGL2D::Flag::TextureTransformation, 1, 1},
{"object ID texture + textured", FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::Textured, 1, 1},
{"instanced texture array offset + layer", FlatGL2D::Flag::UniformBuffers|FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureArrays|FlatGL2D::Flag::InstancedTextureOffset, 1, 1},
{"multidraw with all the things", FlatGL2D::Flag::MultiDraw|FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureArrays|FlatGL2D::Flag::AlphaMask|FlatGL2D::Flag::ObjectId|FlatGL2D::Flag::InstancedTextureOffset|FlatGL2D::Flag::InstancedTransformation|FlatGL2D::Flag::InstancedObjectId, 8, 48}
};
@ -245,10 +251,20 @@ constexpr struct {
FlatGL2D::Flags flags;
const char* message;
} ConstructInvalidData[]{
{"texture transformation but not textured", FlatGL2D::Flag::TextureTransformation,
{"texture transformation but not textured",
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
FlatGL2D::Flag::TextureTransformation
#ifndef MAGNUM_TARGET_GLES2
|FlatGL2D::Flag::ObjectId
#endif
,
"texture transformation enabled but the shader is not textured"},
#ifndef MAGNUM_TARGET_GLES2
{"texture arrays but not textured", FlatGL2D::Flag::TextureArrays,
{"texture arrays but not textured",
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
FlatGL2D::Flag::TextureArrays|FlatGL2D::Flag::ObjectId,
"texture arrays enabled but the shader is not textured"}
#endif
};
@ -273,12 +289,25 @@ constexpr struct {
const char* name;
FlatGL2D::Flags flags;
const char* message;
} BindTextureInvalidData[]{
{"not textured", {},
"the shader was not created with texturing enabled"},
} BindTexturesInvalidData[]{
{"not textured",
FlatGL2D::Flags{}
#ifndef MAGNUM_TARGET_GLES2
/* ObjectId shares bits with ObjectIdTexture but should still
trigger the assert */
|FlatGL2D::Flag::ObjectId
#endif
,
"Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled\n"
#ifndef MAGNUM_TARGET_GLES2
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled\n"
#endif
},
#ifndef MAGNUM_TARGET_GLES2
{"array", FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureArrays,
"the shader was created with texture arrays enabled, use a Texture2DArray instead"}
{"array",
FlatGL2D::Flag::Textured|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
"Shaders::FlatGL::bindTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::FlatGL::bindObjectIdTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"}
#endif
};
@ -287,11 +316,17 @@ constexpr struct {
const char* name;
FlatGL2D::Flags flags;
const char* message;
} BindTextureArrayInvalidData[]{
{"not textured", {},
"the shader was not created with texturing enabled"},
{"not array", FlatGL2D::Flag::Textured,
"the shader was not created with texture arrays enabled, use a Texture2D instead"}
} BindTextureArraysInvalidData[]{
{"not textured",
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
FlatGL2D::Flag::ObjectId,
"Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled\n"
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled\n"},
{"not array",
FlatGL2D::Flag::Textured|FlatGL2D::Flag::ObjectIdTexture,
"Shaders::FlatGL::bindTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"
"Shaders::FlatGL::bindObjectIdTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"}
};
#endif
@ -358,6 +393,39 @@ const struct {
/* texture arrays are orthogonal to this, no need to be tested here */
};
#ifndef MAGNUM_TARGET_GLES2
const struct {
const char* name;
UnsignedInt expected[4];
FlatGL2D::Flags flags;
Matrix3 textureTransformation;
Int layer;
} RenderObjectIdData[]{
{"",
{40006, 40006, 40006, 40006},
{}, {}, 0},
{"textured",
{40106, 40206, 40306, 40406},
FlatGL2D::Flag::ObjectIdTexture, {}, 0},
{"textured, texture transformation",
{40406, 40306, 40206, 40106},
FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureTransformation,
Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 0},
{"texture array, first layer",
{40106, 40206, 40306, 40406},
FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
{}, 0},
{"texture array, arbitrary layer",
{40106, 40206, 40306, 40406},
FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
{}, 6},
{"texture array, texture transformation, arbitrary layer",
{40406, 40306, 40206, 40106},
FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::TextureArrays,
Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 6},
};
#endif
constexpr struct {
const char* name;
const char* expected2D;
@ -382,6 +450,21 @@ constexpr struct {
FlatGL2D::Flag::InstancedObjectId,
/* Minor differences on SwiftShader */
164.4f, 0.094f},
{"colored + textured object ID",
"instanced2D.tga", "instanced3D.tga", {3000, 4000, 5000},
FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::InstancedTextureOffset,
/* Minor differences on SwiftShader */
164.4f, 0.094f},
{"colored + instanced textured object ID",
"instanced2D.tga", "instanced3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::InstancedObjectId|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::InstancedTextureOffset,
/* Minor differences on SwiftShader */
164.4f, 0.094f},
{"colored + instanced textured array object ID",
"instanced2D.tga", "instanced3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::InstancedObjectId|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::InstancedTextureOffset|FlatGL2D::Flag::TextureArrays,
/* Minor differences on SwiftShader */
164.4f, 0.094f},
#endif
{"textured",
"instanced-textured2D.tga", "instanced-textured3D.tga", {},
@ -417,6 +500,14 @@ constexpr struct {
"multidraw2D.tga", "multidraw3D.tga", {1211, 5627, 36363},
FlatGL2D::Flag::ObjectId,
1, 1, 16, 0.0f, 0.0f},
{"bind with offset, colored + textured object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture,
1, 1, 16, 0.0f, 0.0f},
{"bind with offset, colored + textured array object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
1, 1, 16, 0.0f, 0.0f},
{"bind with offset, textured",
"multidraw-textured2D.tga", "multidraw-textured3D.tga", {},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::Textured,
@ -438,6 +529,14 @@ constexpr struct {
"multidraw2D.tga", "multidraw3D.tga", {1211, 5627, 36363},
FlatGL2D::Flag::ObjectId,
2, 3, 1, 0.0f, 0.0f},
{"draw offset, colored + textured object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture,
2, 3, 1, 0.0f, 0.0f},
{"draw offset, colored + textured array object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
2, 3, 1, 0.0f, 0.0f},
{"draw offset, textured",
"multidraw-textured2D.tga", "multidraw-textured3D.tga", {},
FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::Textured,
@ -458,6 +557,14 @@ constexpr struct {
"multidraw2D.tga", "multidraw3D.tga", {1211, 5627, 36363},
FlatGL2D::Flag::MultiDraw|FlatGL2D::Flag::ObjectId,
2, 3, 1, 0.0f, 0.0f},
{"multidraw, colored + textured object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::MultiDraw|FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture,
2, 3, 1, 0.0f, 0.0f},
{"multidraw, colored + textured array object ID",
"multidraw2D.tga", "multidraw3D.tga", {3211, 8627, 40363},
FlatGL2D::Flag::MultiDraw|FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::ObjectIdTexture|FlatGL2D::Flag::TextureArrays,
2, 3, 1, 0.0f, 0.0f},
{"multidraw, textured",
"multidraw-textured2D.tga", "multidraw-textured3D.tga", {},
FlatGL2D::Flag::MultiDraw|FlatGL2D::Flag::TextureTransformation|FlatGL2D::Flag::Textured,
@ -519,15 +626,15 @@ FlatGLTest::FlatGLTest() {
});
addInstancedTests<FlatGLTest>({
&FlatGLTest::bindTextureInvalid<2>,
&FlatGLTest::bindTextureInvalid<3>},
Containers::arraySize(BindTextureInvalidData));
&FlatGLTest::bindTexturesInvalid<2>,
&FlatGLTest::bindTexturesInvalid<3>},
Containers::arraySize(BindTexturesInvalidData));
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests<FlatGLTest>({
&FlatGLTest::bindTextureArrayInvalid<2>,
&FlatGLTest::bindTextureArrayInvalid<3>},
Containers::arraySize(BindTextureArrayInvalidData));
&FlatGLTest::bindTextureArraysInvalid<2>,
&FlatGLTest::bindTextureArraysInvalid<3>},
Containers::arraySize(BindTextureArraysInvalidData));
#endif
addTests<FlatGLTest>({
@ -644,11 +751,12 @@ FlatGLTest::FlatGLTest() {
#ifndef MAGNUM_TARGET_GLES2
/* MSVC needs explicit type due to default template args */
addTests<FlatGLTest>({
addInstancedTests<FlatGLTest>({
&FlatGLTest::renderObjectId2D,
&FlatGLTest::renderObjectId2D<FlatGL2D::Flag::UniformBuffers>,
&FlatGLTest::renderObjectId3D,
&FlatGLTest::renderObjectId3D<FlatGL3D::Flag::UniformBuffers>},
Containers::arraySize(RenderObjectIdData),
&FlatGLTest::renderObjectIdSetup,
&FlatGLTest::renderObjectIdTeardown);
#endif
@ -935,8 +1043,8 @@ template<UnsignedInt dimensions> void FlatGLTest::bindBufferUniformBuffersNotEna
}
#endif
template<UnsignedInt dimensions> void FlatGLTest::bindTextureInvalid() {
auto&& data = BindTextureInvalidData[testCaseInstanceId()];
template<UnsignedInt dimensions> void FlatGLTest::bindTexturesInvalid() {
auto&& data = BindTexturesInvalidData[testCaseInstanceId()];
setTestCaseTemplateName(std::to_string(dimensions));
setTestCaseDescription(data.name);
@ -955,13 +1063,15 @@ template<UnsignedInt dimensions> void FlatGLTest::bindTextureInvalid() {
FlatGL<dimensions> shader{data.flags};
GL::Texture2D texture;
shader.bindTexture(texture);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Shaders::FlatGL::bindTexture(): {}\n", data.message));
#ifndef MAGNUM_TARGET_GLES2
shader.bindObjectIdTexture(texture);
#endif
CORRADE_COMPARE(out.str(), data.message);
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> void FlatGLTest::bindTextureArrayInvalid() {
auto&& data = BindTextureArrayInvalidData[testCaseInstanceId()];
template<UnsignedInt dimensions> void FlatGLTest::bindTextureArraysInvalid() {
auto&& data = BindTextureArraysInvalidData[testCaseInstanceId()];
setTestCaseTemplateName(std::to_string(dimensions));
setTestCaseDescription(data.name);
@ -980,8 +1090,8 @@ template<UnsignedInt dimensions> void FlatGLTest::bindTextureArrayInvalid() {
FlatGL<dimensions> shader{data.flags};
GL::Texture2DArray textureArray;
shader.bindTexture(textureArray);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Shaders::FlatGL::bindTexture(): {}\n", data.message));
shader.bindObjectIdTexture(textureArray);
CORRADE_COMPARE(out.str(), data.message);
}
#endif
@ -2318,6 +2428,9 @@ void FlatGLTest::renderObjectIdTeardown() {
}
template<FlatGL2D::Flag flag> void FlatGLTest::renderObjectId2D() {
auto&& data = RenderObjectIdData[testCaseInstanceId()];
setTestCaseDescription(data.name);
if(flag == FlatGL2D::Flag::UniformBuffers) {
setTestCaseTemplateName("Flag::UniformBuffers");
@ -2332,16 +2445,60 @@ template<FlatGL2D::Flag flag> void FlatGLTest::renderObjectId2D() {
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
#endif
#ifndef MAGNUM_TARGET_GLES
if((data.flags & FlatGL2D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())
CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported.");
#endif
CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete);
GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32));
Primitives::Circle2DFlags circleFlags;
if(data.flags & FlatGL2D::Flag::ObjectIdTexture)
circleFlags |= Primitives::Circle2DFlag::TextureCoordinates;
GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32, circleFlags));
FlatGL2D shader{FlatGL2D::Flag::ObjectId|flag};
FlatGL2D::Flags flags = data.flags|flag;
if(flag == FlatGL2D::Flag::UniformBuffers && (data.flags & FlatGL2D::Flag::TextureArrays) && !(data.flags & FlatGL2D::Flag::TextureTransformation)) {
CORRADE_INFO("Texture arrays currently require texture transformation if UBOs are used, enabling implicitly.");
flags |= FlatGL2D::Flag::TextureTransformation;
}
FlatGL2D shader{FlatGL2D::Flag::ObjectId|flags};
GL::Texture2D texture{NoCreate};
GL::Texture2DArray textureArray{NoCreate};
if(data.flags >= FlatGL2D::Flag::ObjectIdTexture) {
const UnsignedShort imageData[]{
100, 200, 300, 400
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
if(data.flags & FlatGL2D::Flag::TextureArrays) {
textureArray = GL::Texture2DArray{};
textureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, {image.size(), data.layer + 1})
.setSubImage(0, {0, 0, data.layer}, image);
shader.bindObjectIdTexture(textureArray);
if(flag != FlatGL2D::Flag::UniformBuffers && data.layer != 0)
shader.setTextureLayer(data.layer); /* to verify the default */
} else {
texture = GL::Texture2D{};
texture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(texture);
}
}
if(flag == FlatGL2D::Flag{}) {
if(data.textureTransformation != Matrix3{})
shader.setTextureMatrix(data.textureTransformation);
shader.setColor(0x9999ff_rgbf)
.setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f}))
.setObjectId(48526)
.setObjectId(40006)
.draw(circle);
} else if(flag == FlatGL2D::Flag::UniformBuffers) {
GL::Buffer transformationProjectionUniform{GL::Buffer::TargetHint::Uniform, {
@ -2350,12 +2507,21 @@ template<FlatGL2D::Flag flag> void FlatGLTest::renderObjectId2D() {
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
FlatDrawUniform{}
.setObjectId(48526)
.setObjectId(40006)
}};
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}
.setTextureMatrix(data.textureTransformation)
.setLayer(data.layer)
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
FlatMaterialUniform{}
.setColor(0x9999ff_rgbf)
}};
/* Also take into account the case when texture transform needs to be
enabled for texture arrays, so not data.flags but flags */
if(flags & FlatGL2D::Flag::TextureTransformation)
shader.bindTextureTransformationBuffer(textureTransformationUniform);
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
@ -2387,10 +2553,16 @@ template<FlatGL2D::Flag flag> void FlatGLTest::renderObjectId2D() {
/* Outside of the object, cleared to 27 */
CORRADE_COMPARE(image.pixels<UnsignedInt>()[10][10], 27);
/* Inside of the object */
CORRADE_COMPARE(image.pixels<UnsignedInt>()[40][46], 48526);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[30][30], data.expected[0]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[30][50], data.expected[1]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[50][30], data.expected[2]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[50][50], data.expected[3]);
}
template<FlatGL3D::Flag flag> void FlatGLTest::renderObjectId3D() {
auto&& data = RenderObjectIdData[testCaseInstanceId()];
setTestCaseDescription(data.name);
if(flag == FlatGL3D::Flag::UniformBuffers) {
setTestCaseTemplateName("Flag::UniformBuffers");
@ -2405,20 +2577,64 @@ template<FlatGL3D::Flag flag> void FlatGLTest::renderObjectId3D() {
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
#endif
#ifndef MAGNUM_TARGET_GLES
if((data.flags & FlatGL3D::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())
CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported.");
#endif
CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete);
GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32));
Primitives::UVSphereFlags sphereFlags;
if(data.flags & FlatGL3D::Flag::ObjectIdTexture)
sphereFlags |= Primitives::UVSphereFlag::TextureCoordinates;
GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, sphereFlags));
FlatGL3D shader{FlatGL3D::Flag::ObjectId|flag};
FlatGL3D::Flags flags = data.flags|flag;
if(flag == FlatGL3D::Flag::UniformBuffers && (data.flags & FlatGL3D::Flag::TextureArrays) && !(data.flags & FlatGL3D::Flag::TextureTransformation)) {
CORRADE_INFO("Texture arrays currently require texture transformation if UBOs are used, enabling implicitly.");
flags |= FlatGL3D::Flag::TextureTransformation;
}
FlatGL3D shader{FlatGL3D::Flag::ObjectId|flags};
GL::Texture2D texture{NoCreate};
GL::Texture2DArray textureArray{NoCreate};
if(data.flags & FlatGL3D::Flag::ObjectIdTexture) {
const UnsignedShort imageData[]{
100, 200, 300, 400
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
if(data.flags & FlatGL2D::Flag::TextureArrays) {
textureArray = GL::Texture2DArray{};
textureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, {image.size(), data.layer + 1})
.setSubImage(0, {0, 0, data.layer}, image);
shader.bindObjectIdTexture(textureArray);
if(flag != FlatGL2D::Flag::UniformBuffers && data.layer != 0)
shader.setTextureLayer(data.layer); /* to verify the default */
} else {
texture = GL::Texture2D{};
texture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(texture);
}
}
if(flag == FlatGL3D::Flag{}) {
if(data.textureTransformation != Matrix3{})
shader.setTextureMatrix(data.textureTransformation);
shader.setColor(0x9999ff_rgbf)
.setTransformationProjectionMatrix(
Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)*
Matrix4::translation(Vector3::zAxis(-2.15f))*
Matrix4::rotationY(-15.0_degf)*
Matrix4::rotationX(15.0_degf))
.setObjectId(48526)
.setObjectId(40006)
.draw(sphere);
} else if(flag == FlatGL3D::Flag::UniformBuffers) {
GL::Buffer transformationProjectionUniform{GL::Buffer::TargetHint::Uniform, {
@ -2432,12 +2648,21 @@ template<FlatGL3D::Flag flag> void FlatGLTest::renderObjectId3D() {
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
FlatDrawUniform{}
.setObjectId(48526)
.setObjectId(40006)
}};
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}
.setTextureMatrix(data.textureTransformation)
.setLayer(data.layer)
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
FlatMaterialUniform{}
.setColor(0x9999ff_rgbf)
}};
/* Also take into account the case when texture transform needs to be
enabled for texture arrays, so not data.flags but flags */
if(flags & FlatGL2D::Flag::TextureTransformation)
shader.bindTextureTransformationBuffer(textureTransformationUniform);
shader.bindTransformationProjectionBuffer(transformationProjectionUniform)
.bindDrawBuffer(drawUniform)
.bindMaterialBuffer(materialUniform)
@ -2476,8 +2701,13 @@ template<FlatGL3D::Flag flag> void FlatGLTest::renderObjectId3D() {
MAGNUM_VERIFY_NO_GL_ERROR();
/* Outside of the object, cleared to 27 */
CORRADE_COMPARE(image.pixels<UnsignedInt>()[10][10], 27);
/* Inside of the object */
CORRADE_COMPARE(image.pixels<UnsignedInt>()[40][46], 48526);
/* Inside of the object. It's a sphere and the seam is at the front,
rotated to bottom left, meaning left is actually the right part of the
texture and right is the left part of the texture. */
CORRADE_COMPARE(image.pixels<UnsignedInt>()[20][50], data.expected[0]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[20][20], data.expected[1]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[50][50], data.expected[2]);
CORRADE_COMPARE(image.pixels<UnsignedInt>()[50][20], data.expected[3]);
}
#endif
@ -2629,6 +2859,52 @@ template<FlatGL2D::Flag flag> void FlatGLTest::renderInstanced2D() {
}
}
#ifndef MAGNUM_TARGET_GLES2
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= FlatGL2D::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & FlatGL2D::Flag::TextureArrays) {
/* 2 extra slices as a base offset, each slice has half height,
second slice has the data in the right half */
const UnsignedShort imageData[]{
0, 0,
0, 0,
2000, 0,
0, 3000,
4000, 0
};
ImageView3D image{PixelFormat::R16UI, {2, 1, 5}, imageData};
objectIdTextureArray = GL::Texture2DArray{};
objectIdTextureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTextureArray);
} else {
/* First is taken from bottom left, second from bottom right, third
from top center (there I just duplicate the pixel on both
sides) */
const UnsignedShort imageData[]{
2000, 3000,
4000, 4000
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
objectIdTexture = GL::Texture2D{};
objectIdTexture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTexture);
}
}
#endif
if(flag == FlatGL2D::Flag{}) {
shader
.setColor(data.flags & FlatGL2D::Flag::Textured ? 0xffffff_rgbf : 0xffff00_rgbf)
@ -2896,6 +3172,52 @@ template<FlatGL3D::Flag flag> void FlatGLTest::renderInstanced3D() {
}
}
#ifndef MAGNUM_TARGET_GLES2
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= FlatGL3D::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & FlatGL3D::Flag::TextureArrays) {
/* 2 extra slices as a base offset, each slice has half height,
second slice has the data in the right half */
const UnsignedShort imageData[]{
0, 0,
0, 0,
2000, 0,
0, 3000,
4000, 0
};
ImageView3D image{PixelFormat::R16UI, {2, 1, 5}, imageData};
objectIdTextureArray = GL::Texture2DArray{};
objectIdTextureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTextureArray);
} else {
/* First is taken from bottom left, second from bottom right, third
from top center (there I just duplicate the pixel on both
sides) */
const UnsignedShort imageData[]{
2000, 3000,
4000, 4000
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
objectIdTexture = GL::Texture2D{};
objectIdTexture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTexture);
}
}
#endif
if(flag == FlatGL3D::Flag{}) {
shader
.setColor(data.flags & FlatGL2D::Flag::Textured ? 0xffffff_rgbf : 0xffff00_rgbf)
@ -3106,6 +3428,48 @@ void FlatGLTest::renderMulti2D() {
}
}
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= FlatGL2D::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & FlatGL2D::Flag::TextureArrays) {
/* Each slice has half height, second slice has the data in the
right half */
const UnsignedShort imageData[]{
2000, 0,
0, 3000,
4000, 0
};
ImageView3D image{PixelFormat::R16UI, {2, 1, 3}, imageData};
objectIdTextureArray = GL::Texture2DArray{};
objectIdTextureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTextureArray);
} else {
/* First is taken from bottom left, second from bottom right, third
from top center (there I just duplicate the pixel on both
sides) */
const UnsignedShort imageData[]{
2000, 3000,
4000, 4000
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
objectIdTexture = GL::Texture2D{};
objectIdTexture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTexture);
}
}
/* Circle is a fan, plane is a strip, make it indexed first */
Trade::MeshData circleData = MeshTools::generateIndices(Primitives::circle2DSolid(32,
Primitives::Circle2DFlag::TextureCoordinates));
@ -3400,6 +3764,48 @@ void FlatGLTest::renderMulti3D() {
}
}
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= FlatGL3D::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & FlatGL3D::Flag::TextureArrays) {
/* Each slice has half height, second slice has the data in the
right half */
const UnsignedShort imageData[]{
2000, 0,
0, 3000,
4000, 0
};
ImageView3D image{PixelFormat::R16UI, {2, 1, 3}, imageData};
objectIdTextureArray = GL::Texture2DArray{};
objectIdTextureArray.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTextureArray);
} else {
/* First is taken from bottom left, second from bottom right, third
from top center (there I just duplicate the pixel on both
sides) */
const UnsignedShort imageData[]{
2000, 3000,
4000, 4000
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
objectIdTexture = GL::Texture2D{};
objectIdTexture.setMinificationFilter(GL::SamplerFilter::Nearest)
.setMagnificationFilter(GL::SamplerFilter::Nearest)
.setWrapping(GL::SamplerWrapping::ClampToEdge)
.setStorage(1, GL::TextureFormat::R16UI, image.size())
.setSubImage(0, {}, image);
shader.bindObjectIdTexture(objectIdTexture);
}
}
Trade::MeshData sphereData = Primitives::uvSphereSolid(16, 32,
Primitives::UVSphereFlag::TextureCoordinates);
/* Plane is a strip, make it indexed first */

12
src/Magnum/Shaders/Test/FlatGL_Test.cpp

@ -91,12 +91,20 @@ void FlatGL_Test::debugFlags() {
void FlatGL_Test::debugFlagsSupersets() {
#ifndef MAGNUM_TARGET_GLES2
/* InstancedObjectId is a superset of ObjectId so only one should be
printed */
/* InstancedObjectId and ObjectIdTexture are a superset of ObjectId so only
one should be printed, but if there are both then both should be */
{
std::ostringstream out;
Debug{&out} << (FlatGL3D::Flag::ObjectId|FlatGL3D::Flag::InstancedObjectId);
CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::InstancedObjectId\n");
} {
std::ostringstream out;
Debug{&out} << (FlatGL3D::Flag::ObjectId|FlatGL3D::Flag::ObjectIdTexture);
CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::ObjectIdTexture\n");
} {
std::ostringstream out;
Debug{&out} << (FlatGL3D::Flag::ObjectId|FlatGL3D::Flag::InstancedObjectId|FlatGL3D::Flag::ObjectIdTexture);
CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::InstancedObjectId|Shaders::FlatGL::Flag::ObjectIdTexture\n");
}
#endif

Loading…
Cancel
Save