Browse Source

Shaders: support object ID textures in the PhongGL shader.

pull/547/head
Vladimír Vondruš 4 years ago
parent
commit
229641d2ac
  1. 4
      doc/changelog.dox
  2. 2
      src/Magnum/Shaders/FlatGL.cpp
  3. 18
      src/Magnum/Shaders/Phong.frag
  4. 6
      src/Magnum/Shaders/Phong.h
  5. 69
      src/Magnum/Shaders/PhongGL.cpp
  6. 79
      src/Magnum/Shaders/PhongGL.h
  7. 302
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  8. 12
      src/Magnum/Shaders/Test/PhongGL_Test.cpp

4
doc/changelog.dox

@ -205,8 +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
- @ref Shaders::FlatGL and @ref Shaders::PhongGL now support 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

2
src/Magnum/Shaders/FlatGL.cpp

@ -52,7 +52,7 @@ namespace {
enum: Int {
TextureUnit = 0,
/* 1/2/3 taken by Phong (D/S/N), 4 by MeshVisualizer colormap */
ObjectIdTextureUnit = 5
ObjectIdTextureUnit = 5 /* shared with Phong */
};
#ifndef MAGNUM_TARGET_GLES2

18
src/Magnum/Shaders/Phong.frag

@ -293,6 +293,19 @@ uniform lowp
#endif
#endif
#ifdef OBJECT_ID_TEXTURE
#ifdef EXPLICIT_BINDING
layout(binding = 5)
#endif
uniform lowp
#ifndef TEXTURE_ARRAYS
usampler2D
#else
usampler2DArray
#endif
objectIdTextureData;
#endif
/* Inputs */
#if LIGHT_COUNT
@ -308,7 +321,7 @@ in mediump vec3 transformedBitangent;
in highp vec3 transformedPosition;
#endif
#if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE) || defined(NORMAL_TEXTURE)
#if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE) || defined(NORMAL_TEXTURE) || defined(OBJECT_ID_TEXTURE)
in mediump
#ifndef TEXTURE_ARRAYS
vec2
@ -524,6 +537,9 @@ void main() {
#ifdef INSTANCED_OBJECT_ID
interpolatedInstanceObjectId +
#endif
#ifdef OBJECT_ID_TEXTURE
texture(objectIdTextureData, interpolatedTextureCoordinates).r +
#endif
objectId;
#endif
}

6
src/Magnum/Shaders/Phong.h

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

69
src/Magnum/Shaders/PhongGL.cpp

@ -57,7 +57,9 @@ namespace {
AmbientTextureUnit = 0,
DiffuseTextureUnit = 1,
SpecularTextureUnit = 2,
NormalTextureUnit = 3
NormalTextureUnit = 3,
/* 4 taken by MeshVisualizer colormap */
ObjectIdTextureUnit = 5 /* shared with Flat */
};
#ifndef MAGNUM_TARGET_GLES2
@ -87,8 +89,15 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
_lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)},
_lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)}
{
CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)),
"Shaders::PhongGL: texture transformation enabled but the shader is not textured", );
{
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture))
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
"Shaders::PhongGL: texture transformation enabled but the shader is not textured", );
}
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent),
@ -103,7 +112,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#endif
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)),
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture,
"Shaders::PhongGL: texture arrays enabled but the shader is not textured", );
CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation),
"Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", );
@ -206,7 +215,11 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
}
#endif
vert.addSource(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture) ? "#define TEXTURED\n" : "")
vert.addSource((flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
) ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
@ -245,6 +258,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#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
.addSource(flags & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "")
;
@ -301,7 +315,11 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
}
if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture))
if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture)
#ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture
#endif
)
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) {
@ -372,6 +390,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
if(flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit);
}
#ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding);
@ -901,6 +920,28 @@ PhongGL& PhongGL::bindNormalTexture(GL::Texture2DArray& texture) {
}
#endif
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::bindObjectIdTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags >= Flag::ObjectIdTexture,
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindObjectIdTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
texture.bind(ObjectIdTextureUnit);
return *this;
}
PhongGL& PhongGL::bindObjectIdTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags >= Flag::ObjectIdTexture,
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
texture.bind(ObjectIdTextureUnit);
return *this;
}
#endif
PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal) {
CORRADE_ASSERT(_flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture),
"Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled", *this);
@ -913,6 +954,14 @@ PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, G
}
Debug& operator<<(Debug& debug, const PhongGL::Flag value) {
#ifndef MAGNUM_TARGET_GLES2
/* Special case coming from the Flags printer. As both flags are a superset
of ObjectId, printing just one would result in
`Flag::InstancedObjectId|Flag(0x20000)` in the output. */
if(value == PhongGL::Flag(UnsignedInt(PhongGL::Flag::InstancedObjectId|PhongGL::Flag::ObjectIdTexture)))
return debug << PhongGL::Flag::InstancedObjectId << Debug::nospace << "|" << Debug::nospace << PhongGL::Flag::ObjectIdTexture;
#endif
debug << "Shaders::PhongGL::Flag" << Debug::nospace;
switch(value) {
@ -927,8 +976,9 @@ Debug& operator<<(Debug& debug, const PhongGL::Flag value) {
_c(VertexColor)
_c(TextureTransformation)
#ifndef MAGNUM_TARGET_GLES2
_c(InstancedObjectId)
_c(ObjectId)
_c(InstancedObjectId)
_c(ObjectIdTexture)
#endif
_c(InstancedTransformation)
_c(InstancedTextureOffset)
@ -958,7 +1008,12 @@ Debug& operator<<(Debug& debug, const PhongGL::Flags value) {
PhongGL::Flag::InstancedTextureOffset, /* Superset of TextureTransformation */
PhongGL::Flag::TextureTransformation,
#ifndef MAGNUM_TARGET_GLES2
/* Both are a superset of ObjectId, meaning printing just one would
result in `Flag::InstancedObjectId|Flag(0x20000)` in the output. So
we pass both and let the Flag printer deal with that. */
PhongGL::Flag(UnsignedInt(PhongGL::Flag::InstancedObjectId|PhongGL::Flag::ObjectIdTexture)),
PhongGL::Flag::InstancedObjectId, /* Superset of ObjectId */
PhongGL::Flag::ObjectIdTexture, /* Superset of ObjectId */
PhongGL::Flag::ObjectId,
#endif
PhongGL::Flag::InstancedTransformation,

79
src/Magnum/Shaders/PhongGL.h

@ -214,8 +214,10 @@ The shader supports writing object ID to the framebuffer for object picking or
other annotation purposes. Enable it using @ref Flag::ObjectId and set up an
integer buffer attached to the @ref ObjectIdOutput attachment. 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().
and supply per-vertex IDs to the @ref ObjectId 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().
The functionality is practically the same as in the @ref FlatGL shader, see
@ref Shaders-FlatGL-object-id "its documentation" for more information and usage
@ -472,8 +474,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* 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-PhongGL-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-PhongGL-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.
@ -585,6 +588,23 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @m_since{2020,06}
*/
InstancedObjectId = (1 << 8)|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 PhongDrawUniform::objectId and possibly also the per-vertex
* ID, if @ref Flag::InstancedObjectId is enabled as well.
* Implicitly enables @ref Flag::ObjectId. See
* @ref Shaders-PhongGL-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 << 17)|ObjectId,
#endif
/**
@ -976,8 +996,10 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* Expects that the shader was created with @ref Flag::ObjectId
* enabled. Value set here is written to the @ref ObjectIdOutput, see
* @ref Shaders-PhongGL-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 PhongDrawUniform::objectId and call @ref bindDrawBuffer()
@ -1617,6 +1639,51 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
PhongGL& bindNormalTexture(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.
*/
PhongGL& 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.
*/
PhongGL& bindObjectIdTexture(GL::Texture2DArray& texture);
#endif
/**
* @brief Bind textures
* @return Reference to self (for method chaining)

302
src/Magnum/Shaders/Test/PhongGLTest.cpp

@ -235,6 +235,10 @@ constexpr struct {
{"object ID + separate bitangent", PhongGL::Flag::ObjectId|PhongGL::Flag::Bitangent, 1},
{"instanced object ID", PhongGL::Flag::InstancedObjectId, 1},
{"object ID + alpha mask + specular texture", PhongGL::Flag::ObjectId|PhongGL::Flag::AlphaMask|PhongGL::Flag::SpecularTexture, 1},
{"object ID texture", PhongGL::Flag::ObjectIdTexture, 1},
{"instanced object ID texture array + texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1},
{"object ID texture + diffuse texture", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture, 1},
{"object ID texture, zero lights", PhongGL::Flag::ObjectIdTexture, 0},
#endif
{"no specular", PhongGL::Flag::NoSpecular, 1},
{"five lights", {}, 5},
@ -269,6 +273,9 @@ constexpr struct {
{"normal texture + separate bitangents", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1, 1, 1},
{"alpha mask", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AlphaMask, 1, 1, 1},
{"object ID", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectId, 1, 1, 1},
{"object ID texture", PhongGL::Flag::ObjectIdTexture, 1, 1, 1},
{"instanced object ID texture array + texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1, 1, 1},
{"object ID texture + diffuse texture", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture, 1, 1, 1},
{"no specular", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NoSpecular, 1, 1, 1},
{"multidraw with all the things", PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::AlphaMask|PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedTextureOffset|PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::LightCulling, 8, 16, 24}
};
@ -280,10 +287,19 @@ constexpr struct {
const char* message;
} ConstructInvalidData[] {
{"texture transformation but not textured",
PhongGL::Flag::TextureTransformation,
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
PhongGL::Flag::TextureTransformation
#ifndef MAGNUM_TARGET_GLES2
|PhongGL::Flag::ObjectId
#endif
,
"texture transformation enabled but the shader is not textured"},
#ifndef MAGNUM_TARGET_GLES2
{"texture arrays but not textured", PhongGL::Flag::TextureArrays,
{"texture arrays but not textured",
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
PhongGL::Flag::TextureArrays|PhongGL::Flag::ObjectId,
"texture arrays enabled but the shader is not textured"},
{"conflicting bitangent and instanced object id attribute",
PhongGL::Flag::Bitangent|PhongGL::Flag::InstancedObjectId,
@ -317,18 +333,29 @@ constexpr struct {
PhongGL::Flags flags;
const char* message;
} BindTexturesInvalidData[]{
{"not textured", {},
{"not textured",
PhongGL::Flags{}
#ifndef MAGNUM_TARGET_GLES2
/* ObjectId shares bits with ObjectIdTexture but should still
trigger the assert */
|PhongGL::Flag::ObjectId
#endif
,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled\n"
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled\n"
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled\n"
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled\n"
#ifndef MAGNUM_TARGET_GLES2
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled\n"
#endif
"Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled\n"},
#ifndef MAGNUM_TARGET_GLES2
{"array", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays,
{"array", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
"Shaders::PhongGL::bindAmbientTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::PhongGL::bindDiffuseTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::PhongGL::bindSpecularTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::PhongGL::bindNormalTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::PhongGL::bindObjectIdTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"
"Shaders::PhongGL::bindTextures(): the shader was created with texture arrays enabled, use a Texture2DArray instead\n"}
#endif
};
@ -339,16 +366,22 @@ constexpr struct {
PhongGL::Flags flags;
const char* message;
} BindTextureArraysInvalidData[]{
{"not textured", {},
{"not textured",
/* ObjectId shares bits with ObjectIdTexture but should still trigger
the assert */
PhongGL::Flag::ObjectId,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled\n"
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled\n"
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled\n"
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled\n"},
{"not array", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture,
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled\n"
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with object ID texture enabled\n"},
{"not array",
PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::ObjectIdTexture,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"}
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"
"Shaders::PhongGL::bindObjectIdTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead\n"}
};
#endif
@ -662,6 +695,39 @@ const struct {
1.0f, 0.0f, {}}
};
#ifndef MAGNUM_TARGET_GLES2
const struct {
const char* name;
UnsignedInt expected[4];
PhongGL::Flags flags;
Matrix3 textureTransformation;
Int layer;
} RenderObjectIdData[]{
{"",
{40006, 40006, 40006, 40006},
{}, {}, 0},
{"textured",
{40106, 40206, 40306, 40406},
PhongGL::Flag::ObjectIdTexture, {}, 0},
{"textured, texture transformation",
{40406, 40306, 40206, 40106},
PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureTransformation,
Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 0},
{"texture array, first layer",
{40106, 40206, 40306, 40406},
PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
{}, 0},
{"texture array, arbitrary layer",
{40106, 40206, 40306, 40406},
PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
{}, 6},
{"texture array, texture transformation, arbitrary layer",
{40406, 40306, 40206, 40106},
PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureTransformation|PhongGL::Flag::TextureArrays,
Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 6},
};
#endif
constexpr struct {
const char* name;
const char* expected;
@ -685,6 +751,21 @@ constexpr struct {
PhongGL::Flag::InstancedObjectId,
/* Minor differences on SwiftShader */
81.0f, 0.06f},
{"diffuse color + textured object ID",
"instanced.tga", {3000, 4000, 5000},
PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset,
/* Minor differences on SwiftShader */
81.0f, 0.06f},
{"diffuse color + instanced textured object ID",
"instanced.tga", {3211, 8627, 40363},
PhongGL::Flag::InstancedObjectId|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset,
/* Minor differences on SwiftShader */
81.0f, 0.06f},
{"diffuse color + instanced texture array object ID",
"instanced.tga", {3211, 8627, 40363},
PhongGL::Flag::InstancedObjectId|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset|PhongGL::Flag::TextureArrays,
/* Minor differences on SwiftShader */
81.0f, 0.06f},
#endif
{"diffuse texture",
"instanced-textured.tga", {},
@ -725,6 +806,18 @@ constexpr struct {
2, 1, 1, 16,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"bind with offset, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
2, 1, 1, 16,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"bind with offset, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
2, 1, 1, 16,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"bind with offset, textured",
"multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
@ -750,6 +843,18 @@ constexpr struct {
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"draw offset, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"draw offset, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"draw offset, textured",
"multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
@ -775,6 +880,18 @@ constexpr struct {
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"multidraw, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"multidraw, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"multidraw, textured",
"multidraw-textured.tga", {},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
@ -943,9 +1060,10 @@ PhongGLTest::PhongGLTest() {
#ifndef MAGNUM_TARGET_GLES2
/* MSVC needs explicit type due to default template args */
addTests<PhongGLTest>({
addInstancedTests<PhongGLTest>({
&PhongGLTest::renderObjectId,
&PhongGLTest::renderObjectId<PhongGL::Flag::UniformBuffers>},
Containers::arraySize(RenderObjectIdData),
&PhongGLTest::renderObjectIdSetup,
&PhongGLTest::renderObjectIdTeardown);
#endif
@ -1314,6 +1432,9 @@ void PhongGLTest::bindTexturesInvalid() {
.bindDiffuseTexture(texture)
.bindSpecularTexture(texture)
.bindNormalTexture(texture)
#ifndef MAGNUM_TARGET_GLES2
.bindObjectIdTexture(texture)
#endif
.bindTextures(&texture, &texture, &texture, &texture);
CORRADE_COMPARE(out.str(), data.message);
@ -1341,7 +1462,11 @@ void PhongGLTest::bindTextureArraysInvalid() {
shader.bindAmbientTexture(textureArray)
.bindDiffuseTexture(textureArray)
.bindSpecularTexture(textureArray)
.bindNormalTexture(textureArray);
.bindNormalTexture(textureArray)
#ifndef MAGNUM_TARGET_GLES2
.bindObjectIdTexture(textureArray)
#endif
;
CORRADE_COMPARE(out.str(), data.message);
}
@ -2824,6 +2949,9 @@ void PhongGLTest::renderObjectIdTeardown() {
}
template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
auto&& data = RenderObjectIdData[testCaseInstanceId()];
setTestCaseDescription(data.name);
if(flag == PhongGL::Flag::UniformBuffers) {
setTestCaseTemplateName("Flag::UniformBuffers");
@ -2845,11 +2973,50 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
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 & PhongGL::Flag::ObjectIdTexture)
sphereFlags |= Primitives::UVSphereFlag::TextureCoordinates;
GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, sphereFlags));
PhongGL::Flags flags = data.flags|flag;
if(flag == PhongGL::Flag::UniformBuffers && (data.flags & PhongGL::Flag::TextureArrays) && !(data.flags & PhongGL::Flag::TextureTransformation)) {
CORRADE_INFO("Texture arrays currently require texture transformation if UBOs are used, enabling implicitly.");
flags |= PhongGL::Flag::TextureTransformation;
}
PhongGL shader{PhongGL::Flag::ObjectId|flags, 2};
PhongGL shader{PhongGL::Flag::ObjectId|flag, 2};
GL::Texture2D texture{NoCreate};
GL::Texture2DArray textureArray{NoCreate};
if(data.flags >= PhongGL::Flag::ObjectIdTexture) {
const UnsignedShort imageData[]{
100, 200, 300, 400
};
ImageView2D image{PixelFormat::R16UI, {2, 2}, imageData};
if(data.flags & PhongGL::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 != PhongGL::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 == PhongGL::Flag{}) {
if(data.textureTransformation != Matrix3{})
shader.setTextureMatrix(data.textureTransformation);
shader
.setLightColors({0x993366_rgbf, 0x669933_rgbf})
.setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f},
@ -2859,7 +3026,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
.setSpecularColor(0x6666ff_rgbf)
.setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f)))
.setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f))
.setObjectId(48526)
.setObjectId(40006)
.draw(sphere);
} else if(flag == PhongGL::Flag::UniformBuffers) {
GL::Buffer projectionUniform{GL::Buffer::TargetHint::Uniform, {
@ -2874,7 +3041,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
}};
GL::Buffer drawUniform{GL::Buffer::TargetHint::Uniform, {
PhongDrawUniform{}
.setObjectId(48526)
.setObjectId(40006)
}};
GL::Buffer lightUniform{GL::Buffer::TargetHint::Uniform, {
PhongLightUniform{}
@ -2884,12 +3051,21 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
.setPosition({3.0f, -3.0f, 2.0f, 0.0f})
.setColor(0x669933_rgbf)
}};
GL::Buffer textureTransformationUniform{GL::Buffer::TargetHint::Uniform, {
TextureTransformationUniform{}
.setTextureMatrix(data.textureTransformation)
.setLayer(data.layer)
}};
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
PhongMaterialUniform{}
.setAmbientColor(0x330033_rgbf)
.setDiffuseColor(0xccffcc_rgbf)
.setSpecularColor(0x6666ff_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 & PhongGL::Flag::TextureTransformation)
shader.bindTextureTransformationBuffer(textureTransformationUniform);
shader.bindProjectionBuffer(projectionUniform)
.bindTransformationBuffer(transformationUniform)
.bindDrawBuffer(drawUniform)
@ -2924,8 +3100,13 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
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
@ -3589,6 +3770,53 @@ template<PhongGL::Flag flag> void PhongGLTest::renderInstanced() {
shader.bindNormalTexture(normal);
}
}
#ifndef MAGNUM_TARGET_GLES2
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= PhongGL::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & PhongGL::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 == PhongGL::Flag{}) {
shader
.setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f},
@ -3823,6 +4051,48 @@ void PhongGLTest::renderMulti() {
}
}
GL::Texture2D objectIdTexture{NoCreate};
GL::Texture2DArray objectIdTextureArray{NoCreate};
if(data.flags >= PhongGL::Flag::ObjectIdTexture) {
/* This should match transformation done for the diffuse/normal
texture */
if(data.flags & PhongGL::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|
Primitives::UVSphereFlag::Tangents);

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

@ -85,12 +85,20 @@ void PhongGL_Test::debugFlags() {
void PhongGL_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} << (PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedObjectId);
CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::InstancedObjectId\n");
} {
std::ostringstream out;
Debug{&out} << (PhongGL::Flag::ObjectId|PhongGL::Flag::ObjectIdTexture);
CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::ObjectIdTexture\n");
} {
std::ostringstream out;
Debug{&out} << (PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::ObjectIdTexture);
CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::InstancedObjectId|Shaders::PhongGL::Flag::ObjectIdTexture\n");
}
#endif

Loading…
Cancel
Save