Browse Source

Shaders: support array textures in Flat and Phong.

pull/518/head
Vladimír Vondruš 5 years ago
parent
commit
95379ace8e
  1. 2
      doc/changelog.dox
  2. 22
      src/Magnum/Shaders/Flat.frag
  3. 48
      src/Magnum/Shaders/Flat.vert
  4. 53
      src/Magnum/Shaders/FlatGL.cpp
  5. 109
      src/Magnum/Shaders/FlatGL.h
  6. 8
      src/Magnum/Shaders/Generic.h
  7. 60
      src/Magnum/Shaders/Phong.frag
  8. 50
      src/Magnum/Shaders/Phong.vert
  9. 102
      src/Magnum/Shaders/PhongGL.cpp
  10. 202
      src/Magnum/Shaders/PhongGL.h
  11. 842
      src/Magnum/Shaders/Test/FlatGLTest.cpp
  12. 807
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  13. 2
      src/Magnum/Shaders/generic.glsl

2
doc/changelog.dox

@ -150,6 +150,8 @@ See also:
- All builtin shaders now have opt-in support for uniform buffers on desktop,
OpenGL ES 3.0+ and WebGL 2.0, including multi-draw functionality for
massive driver overhead reduction
- @ref Shaders::FlatGL and @ref Shaders::PhongGL now support texture arrays,
available also in multi-draw and instanced scenarios
- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
recently added @ref Trade::MaterialAttribute::NormalTextureScale material
attribute

22
src/Magnum/Shaders/Flat.frag

@ -41,7 +41,7 @@
#ifndef UNIFORM_BUFFERS
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 2)
layout(location = 3)
#endif
uniform lowp vec4 color
#ifndef GL_ES
@ -51,7 +51,7 @@ uniform lowp vec4 color
#ifdef ALPHA_MASK
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 3)
layout(location = 4)
#endif
uniform lowp float alphaMask
#ifndef GL_ES
@ -62,7 +62,7 @@ uniform lowp float alphaMask
#ifdef OBJECT_ID
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 4)
layout(location = 5)
#endif
/* mediump is just 2^10, which might not be enough, this is 2^16 */
uniform highp uint objectId; /* defaults to zero */
@ -118,13 +118,25 @@ layout(std140
#ifdef EXPLICIT_BINDING
layout(binding = 0)
#endif
uniform lowp sampler2D textureData;
uniform lowp
#ifndef TEXTURE_ARRAYS
sampler2D
#else
sampler2DArray
#endif
textureData;
#endif
/* Inputs */
#ifdef TEXTURED
in mediump vec2 interpolatedTextureCoordinates;
in mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
interpolatedTextureCoordinates;
#endif
#ifdef VERTEX_COLOR

48
src/Magnum/Shaders/Flat.vert

@ -27,6 +27,10 @@
#extension GL_EXT_gpu_shader4: require
#endif
#if defined(UNIFORM_BUFFERS) && defined(TEXTURE_ARRAYS) && !defined(GL_ES)
#extension GL_ARB_shader_bit_encoding: require
#endif
#ifdef MULTI_DRAW
#ifndef GL_ES
#extension GL_ARB_shader_draw_parameters: require
@ -77,6 +81,14 @@ uniform mediump mat3 textureMatrix
;
#endif
#ifdef TEXTURE_ARRAYS
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 2)
#endif
/* mediump is just 2^10, which might not be enough, this is 2^16 */
uniform highp uint textureLayer; /* defaults to zero */
#endif
/* Uniform buffers */
#else
@ -108,8 +120,9 @@ layout(std140
#ifdef TEXTURE_TRANSFORMATION
struct TextureTransformationUniform {
highp vec4 rotationScaling;
highp vec4 offsetReservedReserved;
#define textureTransformation_offset offsetReservedReserved.xy
highp vec4 offsetLayerReserved;
#define textureTransformation_offset offsetLayerReserved.xy
#define textureTransformation_layer offsetLayerReserved.z
};
layout(std140
@ -173,13 +186,25 @@ in highp mat4 instancedTransformationMatrix;
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TEXTURE_OFFSET_ATTRIBUTE_LOCATION)
#endif
in mediump vec2 instancedTextureOffset;
in mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
instancedTextureOffset;
#endif
/* Outputs */
#ifdef TEXTURED
out mediump vec2 interpolatedTextureCoordinates;
out mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
interpolatedTextureCoordinates;
#endif
#ifdef VERTEX_COLOR
@ -219,6 +244,9 @@ void main() {
transformationProjectionMatrix = transformationProjectionMatrices[drawId];
#ifdef TEXTURE_TRANSFORMATION
mediump const mat3 textureMatrix = mat3(textureTransformations[drawId].rotationScaling.xy, 0.0, textureTransformations[drawId].rotationScaling.zw, 0.0, textureTransformations[drawId].textureTransformation_offset, 1.0);
#ifdef TEXTURE_ARRAYS
highp const uint textureLayer = floatBitsToUint(textureTransformations[drawId].textureTransformation_layer);
#endif
#endif
#endif
@ -240,17 +268,25 @@ void main() {
#ifdef TEXTURED
/* Texture coordinates, if needed */
interpolatedTextureCoordinates =
interpolatedTextureCoordinates.xy =
#ifdef TEXTURE_TRANSFORMATION
(textureMatrix*vec3(
#ifdef INSTANCED_TEXTURE_OFFSET
instancedTextureOffset +
instancedTextureOffset.xy +
#endif
textureCoordinates, 1.0)).xy
#else
textureCoordinates
#endif
;
#ifdef TEXTURE_ARRAYS
interpolatedTextureCoordinates.z = float(
#ifdef INSTANCED_TEXTURE_OFFSET
uint(instancedTextureOffset.z) +
#endif
textureLayer
);
#endif
#endif
#ifdef VERTEX_COLOR

53
src/Magnum/Shaders/FlatGL.cpp

@ -43,6 +43,7 @@
#include <Corrade/Utility/FormatStl.h>
#include "Magnum/GL/Buffer.h"
#include "Magnum/GL/TextureArray.h"
#endif
namespace Magnum { namespace Shaders {
@ -83,6 +84,13 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
"Shaders::FlatGL: draw count can't be zero", );
#endif
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & Flag::Textured),
"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", );
#endif
#ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
@ -98,6 +106,10 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::TextureArrays)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array);
#endif
#ifdef MAGNUM_BUILD_STATIC
/* Import resources on static build, if not already */
@ -120,6 +132,9 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif
.addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n")
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
@ -138,6 +153,9 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
vert.addSource(rs.get("generic.glsl"))
.addSource(rs.get("Flat.vert"));
frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
#ifndef MAGNUM_TARGET_GLES2
@ -205,6 +223,10 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
_transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix");
if(flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer");
#endif
_colorUniform = uniformLocation("color");
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2
@ -240,6 +262,7 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags
setTransformationProjectionMatrix(MatrixTypeFor<dimensions, Float>{Math::IdentityInit});
if(flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */
setColor(Magnum::Color4{1.0f});
if(flags & Flag::AlphaMask) setAlphaMask(0.5f);
/* Object ID is zero by default */
@ -271,6 +294,17 @@ template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setText
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setTextureLayer(UnsignedInt id) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::FlatGL::setTextureLayer(): the shader was created with uniform buffers enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::FlatGL::setTextureLayer(): the shader was not created with texture arrays enabled", *this);
setUniform(_textureLayerUniform, id);
return *this;
}
#endif
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::setColor(const Magnum::Color4& color) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
@ -376,10 +410,25 @@ template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindMat
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags & Flag::Textured,
"Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::FlatGL::bindTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
texture.bind(TextureUnit);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> FlatGL<dimensions>& FlatGL<dimensions>::bindTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags & Flag::Textured,
"Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::FlatGL::bindTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
texture.bind(TextureUnit);
return *this;
}
#endif
template class MAGNUM_SHADERS_EXPORT FlatGL<2>;
template class MAGNUM_SHADERS_EXPORT FlatGL<3>;
@ -404,6 +453,7 @@ Debug& operator<<(Debug& debug, const FlatGLFlag value) {
#ifndef MAGNUM_TARGET_GLES2
_c(UniformBuffers)
_c(MultiDraw)
_c(TextureArrays)
#endif
#undef _c
/* LCOV_EXCL_STOP */
@ -426,7 +476,8 @@ Debug& operator<<(Debug& debug, const FlatGLFlags value) {
FlatGLFlag::InstancedTransformation,
#ifndef MAGNUM_TARGET_GLES2
FlatGLFlag::MultiDraw, /* Superset of UniformBuffers */
FlatGLFlag::UniformBuffers
FlatGLFlag::UniformBuffers,
FlatGLFlag::TextureArrays
#endif
});
}

109
src/Magnum/Shaders/FlatGL.h

@ -51,7 +51,8 @@ namespace Implementation {
InstancedTextureOffset = (1 << 7)|TextureTransformation,
#ifndef MAGNUM_TARGET_GLES2
UniformBuffers = 1 << 8,
MultiDraw = UniformBuffers|(1 << 9)
MultiDraw = UniformBuffers|(1 << 9),
TextureArrays = 1 << 10
#endif
};
typedef Containers::EnumSet<FlatGLFlag> FlatGLFlags;
@ -231,8 +232,9 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* @brief (Instanced) texture offset
* @m_since{2020,06}
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used
* only if @ref Flag::InstancedTextureOffset is set.
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Use
* either this or the @ref TextureOffsetLayer attribute. Used only if
* @ref Flag::InstancedTextureOffset is set.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
@ -242,6 +244,24 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
*/
typedef typename GenericGL<dimensions>::TextureOffset TextureOffset;
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief (Instanced) texture offset and layer
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector3, with
* the last component interpreted as an integer. Use either this or the
* @ref TextureOffset attribute. First two components used only if
* @ref Flag::InstancedTextureOffset is set, third component only if
* @ref Flag::TextureArrays is set.
* @requires_gl33 Extension @gl_extension{EXT,texture_array} and
* @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
typedef typename GenericGL<dimensions>::TextureOffsetLayer TextureOffsetLayer;
#endif
enum: UnsignedInt {
/**
* Color shader output. Present always, expects three- or
@ -366,6 +386,13 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* specify that only via the uniform @ref setTextureMatrix().
* Implicitly enables @ref Flag::TextureTransformation. See
* @ref Shaders-FlatGL-instancing for more information.
*
* If @ref Flag::TextureArrays is set as well, a three-component
* @ref TextureOffsetLayer attribute can be used instead of
* @ref TextureOffset to specify per-instance texture layer, which
* gets added to the uniform layer numbers set by
* @ref setTextureLayer() or
* @ref TextureTransformationUniform::layer.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
@ -414,7 +441,25 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* relies on uniform buffers, which require WebGL 2.0.
* @m_since_latest
*/
MultiDraw = UniformBuffers|(1 << 9)
MultiDraw = UniformBuffers|(1 << 9),
/**
* Use 2D texture arrays. Expects that the texture is supplied via
* @ref bindTexture(GL::Texture2DArray&) instead of
* @ref bindTexture(GL::Texture2D&) and the layer is set via
* @ref setTextureLayer() or
* @ref TextureTransformationUniform::layer. If
* @ref Flag::InstancedTextureOffset is set as well and a
* three-component @ref TextureOffsetLayer attribute is used
* instead of @ref TextureOffset, the per-instance and uniform
* layer numbers are added together.
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES
* 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
* @m_since_latest
*/
TextureArrays = 1 << 10
#endif
};
@ -574,6 +619,29 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
*/
FlatGL<dimensions>& setTextureMatrix(const Matrix3& matrix);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Set texture array layer
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with @ref Flag::TextureArrays
* enabled. Initial value is @cpp 0 @ce. If
* @ref Flag::InstancedTextureOffset is set and a three-component
* @ref TextureOffsetLayer attribute is used instead of
* @ref TextureOffset, this value is added to the layer coming from the
* third component.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref TextureTransformationUniform::layer and call
* @ref bindTextureTransformationBuffer() instead.
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
FlatGL<dimensions>& setTextureLayer(UnsignedInt layer);
#endif
/**
* @brief Set color
* @return Reference to self (for method chaining)
@ -760,12 +828,34 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* @return Reference to self (for method chaining)
*
* Expects that the shader was created with @ref Flag::Textured
* enabled.
* enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindTexture(GL::Texture2DArray&) instead.
* @see @ref setColor(), @ref Flag::TextureTransformation,
* @ref setTextureMatrix()
*/
FlatGL<dimensions>& bindTexture(GL::Texture2D& texture);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind a color array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both @ref Flag::Textured
* 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 setColor(), @ref Flag::TextureTransformation,
* @ref setTextureLayer()
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
FlatGL<dimensions>& bindTexture(GL::Texture2DArray& texture);
#endif
/**
* @}
*/
@ -785,10 +875,13 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#endif
Int _transformationProjectionMatrixUniform{0},
_textureMatrixUniform{1},
_colorUniform{2},
_alphaMaskUniform{3};
#ifndef MAGNUM_TARGET_GLES2
_textureLayerUniform{2},
#endif
_colorUniform{3},
_alphaMaskUniform{4};
#ifndef MAGNUM_TARGET_GLES2
Int _objectIdUniform{4};
Int _objectIdUniform{5};
/* Used instead of all other uniforms when Flag::UniformBuffers is set,
so it can alias them */
Int _drawOffsetUniform{0};

8
src/Magnum/Shaders/Generic.h

@ -462,6 +462,14 @@ struct TextureTransformationUniform {
*
* Descibes which layer of a texture array to use. Default value is
* @cpp 0.5f @ce.
*
* Used only if @ref FlatGL::Flag::TextureArrays /
* @ref PhongGL::Flag::TextureArrays is enabled, ignored otherwise. If
* @ref FlatGL::Flag::InstancedTextureOffset /
* @ref PhongGL::Flag::InstancedTextureOffset is enabled as well, the
* per-instance layer coming from the @ref FlatGL::TextureOffsetLayer /
* @ref PhongGL::TextureOffsetLayer attribute is added to this value.
* @see @ref FlatGL::setTextureLayer(), @ref PhongGL::setTextureLayer()
*/
UnsignedInt layer;

60
src/Magnum/Shaders/Phong.frag

@ -41,7 +41,7 @@
#ifndef UNIFORM_BUFFERS
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 4)
layout(location = 5)
#endif
uniform lowp vec4 ambientColor
#ifndef GL_ES
@ -55,7 +55,7 @@ uniform lowp vec4 ambientColor
#if LIGHT_COUNT
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 5)
layout(location = 6)
#endif
uniform lowp vec4 diffuseColor
#ifndef GL_ES
@ -64,7 +64,7 @@ uniform lowp vec4 diffuseColor
;
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 6)
layout(location = 7)
#endif
uniform lowp vec4 specularColor
#ifndef GL_ES
@ -73,7 +73,7 @@ uniform lowp vec4 specularColor
;
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 7)
layout(location = 8)
#endif
uniform mediump float shininess
#ifndef GL_ES
@ -84,7 +84,7 @@ uniform mediump float shininess
#ifdef NORMAL_TEXTURE
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 8)
layout(location = 9)
#endif
uniform mediump float normalTextureScale
#ifndef GL_ES
@ -95,7 +95,7 @@ uniform mediump float normalTextureScale
#ifdef ALPHA_MASK
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 9)
layout(location = 10)
#endif
uniform lowp float alphaMask
#ifndef GL_ES
@ -106,16 +106,16 @@ uniform lowp float alphaMask
#ifdef OBJECT_ID
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 10)
layout(location = 11)
#endif
/* mediump is just 2^10, which might not be enough, this is 2^16 */
uniform highp uint objectId; /* defaults to zero */
#endif
#if LIGHT_COUNT
/* Needs to be last because it uses locations 11 + LIGHT_COUNT to
11 + 2*LIGHT_COUNT - 1. Location 11 is lightPositions. Also it can't be
specified as 11 + LIGHT_COUNT because that requires ARB_enhanced_layouts.
/* Needs to be last because it uses locations 12 + LIGHT_COUNT to
12 + 2*LIGHT_COUNT - 1. Location 12 is lightPositions. Also it can't be
specified as 12 + LIGHT_COUNT because that requires ARB_enhanced_layouts.
Same for lightSpecularColors and lightRanges below. */
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = LIGHT_COLORS_LOCATION) /* I fear this will blow up some drivers */
@ -226,7 +226,13 @@ layout(std140
#ifdef EXPLICIT_BINDING
layout(binding = 0)
#endif
uniform lowp sampler2D ambientTexture;
uniform lowp
#ifndef TEXTURE_ARRAYS
sampler2D
#else
sampler2DArray
#endif
ambientTexture;
#endif
#if LIGHT_COUNT
@ -234,21 +240,39 @@ uniform lowp sampler2D ambientTexture;
#ifdef EXPLICIT_BINDING
layout(binding = 1)
#endif
uniform lowp sampler2D diffuseTexture;
uniform lowp
#ifndef TEXTURE_ARRAYS
sampler2D
#else
sampler2DArray
#endif
diffuseTexture;
#endif
#ifdef SPECULAR_TEXTURE
#ifdef EXPLICIT_BINDING
layout(binding = 2)
#endif
uniform lowp sampler2D specularTexture;
uniform lowp
#ifndef TEXTURE_ARRAYS
sampler2D
#else
sampler2DArray
#endif
specularTexture;
#endif
#ifdef NORMAL_TEXTURE
#ifdef EXPLICIT_BINDING
layout(binding = 3)
#endif
uniform lowp sampler2D normalTexture;
uniform lowp
#ifndef TEXTURE_ARRAYS
sampler2D
#else
sampler2DArray
#endif
normalTexture;
#endif
#endif
@ -269,7 +293,13 @@ in highp vec3 cameraDirection;
#endif
#if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE) || defined(NORMAL_TEXTURE)
in mediump vec2 interpolatedTextureCoordinates;
in mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
interpolatedTextureCoordinates;
#endif
#ifdef VERTEX_COLOR

50
src/Magnum/Shaders/Phong.vert

@ -27,6 +27,10 @@
#extension GL_EXT_gpu_shader4: require
#endif
#if defined(UNIFORM_BUFFERS) && defined(TEXTURE_ARRAYS) && !defined(GL_ES)
#extension GL_ARB_shader_bit_encoding: require
#endif
#ifdef MULTI_DRAW
#ifndef GL_ES
#extension GL_ARB_shader_draw_parameters: require
@ -87,10 +91,18 @@ uniform mediump mat3 textureMatrix
;
#endif
#ifdef TEXTURE_ARRAYS
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 4)
#endif
/* mediump is just 2^10, which might not be enough, this is 2^16 */
uniform highp uint textureLayer; /* defaults to zero */
#endif
#if LIGHT_COUNT
/* Needs to be last because it uses locations 11 to 11 + LIGHT_COUNT - 1 */
#ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 11)
layout(location = 12)
#endif
uniform highp vec4 lightPositions[LIGHT_COUNT]
#ifndef GL_ES
@ -149,8 +161,9 @@ layout(std140
#ifdef TEXTURE_TRANSFORMATION
struct TextureTransformationUniform {
highp vec4 rotationScaling;
highp vec4 offsetReservedReserved;
#define textureTransformation_offset offsetReservedReserved.xy
highp vec4 offsetLayerReserved;
#define textureTransformation_offset offsetLayerReserved.xy
#define textureTransformation_layer offsetLayerReserved.z
};
layout(std140
@ -256,13 +269,25 @@ in highp mat3 instancedNormalMatrix;
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TEXTURE_OFFSET_ATTRIBUTE_LOCATION)
#endif
in mediump vec2 instancedTextureOffset;
in mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
instancedTextureOffset;
#endif
/* Outputs */
#ifdef TEXTURED
out mediump vec2 interpolatedTextureCoordinates;
out mediump
#ifndef TEXTURE_ARRAYS
vec2
#else
vec3
#endif
interpolatedTextureCoordinates;
#endif
#ifdef VERTEX_COLOR
@ -311,6 +336,9 @@ void main() {
#endif
#ifdef TEXTURE_TRANSFORMATION
mediump const mat3 textureMatrix = mat3(textureTransformations[drawId].rotationScaling.xy, 0.0, textureTransformations[drawId].rotationScaling.zw, 0.0, textureTransformations[drawId].textureTransformation_offset, 1.0);
#ifdef TEXTURE_ARRAYS
highp const uint textureLayer = floatBitsToUint(textureTransformations[drawId].textureTransformation_layer);
#endif
#endif
#if LIGHT_COUNT
mediump const uint lightOffset = draws[drawId].draw_lightOffset;
@ -380,17 +408,25 @@ void main() {
#ifdef TEXTURED
/* Texture coordinates, if needed */
interpolatedTextureCoordinates =
interpolatedTextureCoordinates.xy =
#ifdef TEXTURE_TRANSFORMATION
(textureMatrix*vec3(
#ifdef INSTANCED_TEXTURE_OFFSET
instancedTextureOffset +
instancedTextureOffset.xy +
#endif
textureCoordinates, 1.0)).xy
#else
textureCoordinates
#endif
;
#ifdef TEXTURE_ARRAYS
interpolatedTextureCoordinates.z = float(
#ifdef INSTANCED_TEXTURE_OFFSET
uint(instancedTextureOffset.z) +
#endif
textureLayer
);
#endif
#endif
#ifdef VERTEX_COLOR

102
src/Magnum/Shaders/PhongGL.cpp

@ -45,6 +45,7 @@
#ifndef MAGNUM_TARGET_GLES2
#include "Magnum/GL/Buffer.h"
#include "Magnum/GL/TextureArray.h"
#endif
#include "Magnum/Shaders/Implementation/CreateCompatibilityShader.h"
@ -101,6 +102,13 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
"Shaders::PhongGL: draw count can't be zero", );
#endif
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)),
"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", );
#endif
#ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
@ -116,6 +124,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::TextureArrays)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array);
#endif
#ifdef MAGNUM_BUILD_STATIC
/* Import resources on static build, if not already */
@ -196,6 +208,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif
.addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount))
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
@ -223,6 +238,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
#ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
@ -315,6 +333,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
_transformationMatrixUniform = uniformLocation("transformationMatrix");
if(flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer");
#endif
_projectionMatrixUniform = uniformLocation("projectionMatrix");
_ambientColorUniform = uniformLocation("ambientColor");
if(lightCount) {
@ -389,6 +411,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
}
if(flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */
if(flags & Flag::AlphaMask) setAlphaMask(0.5f);
/* Object ID is zero by default */
}
@ -506,6 +529,17 @@ PhongGL& PhongGL::setTextureMatrix(const Matrix3& matrix) {
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::setTextureLayer(UnsignedInt id) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::PhongGL::setTextureLayer(): the shader was created with uniform buffers enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::setTextureLayer(): the shader was not created with texture arrays enabled", *this);
setUniform(_textureLayerUniform, id);
return *this;
}
#endif
PhongGL& PhongGL::setLightPositions(const Containers::ArrayView<const Vector4> positions) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
@ -768,34 +802,98 @@ PhongGL& PhongGL::bindLightBuffer(GL::Buffer& buffer, const GLintptr offset, con
PhongGL& PhongGL::bindAmbientTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags & Flag::AmbientTexture,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindAmbientTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
texture.bind(AmbientTextureUnit);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::bindAmbientTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags & Flag::AmbientTexture,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindAmbientTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
texture.bind(AmbientTextureUnit);
return *this;
}
#endif
PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags & Flag::DiffuseTexture,
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindDiffuseTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
if(_lightCount) texture.bind(DiffuseTextureUnit);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags & Flag::DiffuseTexture,
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(DiffuseTextureUnit);
return *this;
}
#endif
PhongGL& PhongGL::bindSpecularTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags & Flag::SpecularTexture,
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindSpecularTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
if(_lightCount) texture.bind(SpecularTextureUnit);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::bindSpecularTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags & Flag::SpecularTexture,
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(SpecularTextureUnit);
return *this;
}
#endif
PhongGL& PhongGL::bindNormalTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(_flags & Flag::NormalTexture,
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindNormalTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
if(_lightCount) texture.bind(NormalTextureUnit);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2
PhongGL& PhongGL::bindNormalTexture(GL::Texture2DArray& texture) {
CORRADE_ASSERT(_flags & Flag::NormalTexture,
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(NormalTextureUnit);
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);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindTextures(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif
GL::AbstractTexture::bind(AmbientTextureUnit, {ambient, diffuse, specular, normal});
return *this;
}
@ -823,6 +921,7 @@ Debug& operator<<(Debug& debug, const PhongGL::Flag value) {
#ifndef MAGNUM_TARGET_GLES2
_c(UniformBuffers)
_c(MultiDraw)
_c(TextureArrays)
#endif
#undef _c
/* LCOV_EXCL_STOP */
@ -849,7 +948,8 @@ Debug& operator<<(Debug& debug, const PhongGL::Flags value) {
PhongGL::Flag::InstancedTransformation,
#ifndef MAGNUM_TARGET_GLES2
PhongGL::Flag::MultiDraw, /* Superset of UniformBuffers */
PhongGL::Flag::UniformBuffers
PhongGL::Flag::UniformBuffers,
PhongGL::Flag::TextureArrays
#endif
});
}

202
src/Magnum/Shaders/PhongGL.h

@ -396,6 +396,24 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*/
typedef typename GenericGL3D::TextureOffset TextureOffset;
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief (Instanced) texture offset and layer
* @m_since_latest
*
* @ref shaders-generic "Generic attribute", @ref Magnum::Vector3, with
* the last component interpreted as an integer. Use either this or the
* @ref TextureOffset attribute. First two components used only if
* @ref Flag::InstancedTextureOffset is set, third component only if
* @ref Flag::TextureArrays is set.
* @requires_gl33 Extension @gl_extension{EXT,texture_array} and
* @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
typedef typename GenericGL3D::TextureOffsetLayer TextureOffsetLayer;
#endif
enum: UnsignedInt {
/**
* Color shader output. @ref shaders-generic "Generic output",
@ -553,6 +571,13 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* specify that only via the uniform @ref setTextureMatrix().
* Implicitly enables @ref Flag::TextureTransformation. See
* @ref Shaders-PhongGL-instancing for more information.
*
* If @ref Flag::TextureArrays is set as well, a three-component
* @ref TextureOffsetLayer attribute can be used instead of
* @ref TextureOffset to specify per-instance texture layer, which
* gets added to the uniform layer numbers set by
* @ref setTextureLayer() or
* @ref TextureTransformationUniform::layer.
* @requires_gl33 Extension @gl_extension{ARB,instanced_arrays}
* @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays},
* @gl_extension{EXT,instanced_arrays} or
@ -602,7 +627,31 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* relies on uniform buffers, which require WebGL 2.0.
* @m_since_latest
*/
MultiDraw = UniformBuffers|(1 << 13)
MultiDraw = UniformBuffers|(1 << 13),
/**
* Use 2D texture arrays. Expects that the texture is supplied via
* @ref bindAmbientTexture(GL::Texture2DArray&) /
* @ref bindDiffuseTexture(GL::Texture2DArray&) /
* @ref bindSpecularTexture(GL::Texture2DArray&) /
* @ref bindNormalTexture(GL::Texture2DArray&) instead of
* @ref bindAmbientTexture(GL::Texture2D&) /
* @ref bindDiffuseTexture(GL::Texture2D&) /
* @ref bindSpecularTexture(GL::Texture2D&) /
* @ref bindNormalTexture(GL::Texture2D&) and the layer shared by
* all textures is set via @ref setTextureLayer() or
* @ref TextureTransformationUniform::layer. If
* @ref Flag::InstancedTextureOffset is set as well and a
* three-component @ref TextureOffsetLayer attribute is used
* instead of @ref TextureOffset, the per-instance and uniform
* layer numbers are added together.
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES
* 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
* @m_since_latest
*/
TextureArrays = 1 << 14
#endif
};
@ -934,6 +983,29 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*/
PhongGL& setTextureMatrix(const Matrix3& matrix);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Set texture array layer
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with @ref Flag::TextureArrays
* enabled. Initial value is @cpp 0 @ce. If
* @ref Flag::InstancedTextureOffset is set and a three-component
* @ref TextureOffsetLayer attribute is used instead of
* @ref TextureOffset, this value is added to the layer coming from the
* third component.
*
* Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref TextureTransformationUniform::layer and call
* @ref bindTextureTransformationBuffer() instead.
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
PhongGL& setTextureLayer(UnsignedInt layer);
#endif
/**
* @brief Set light positions
* @return Reference to self (for method chaining)
@ -1335,34 +1407,103 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @return Reference to self (for method chaining)
*
* Expects that the shader was created with @ref Flag::AmbientTexture
* enabled.
* enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindAmbientTexture(GL::Texture2DArray&) instead.
* @see @ref bindTextures(), @ref setAmbientColor(),
* @ref Shaders-PhongGL-lights-ambient
*/
PhongGL& bindAmbientTexture(GL::Texture2D& texture);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind an ambient array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both
* @ref Flag::AmbientTexture 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 setAmbientColor(), @ref Shaders-PhongGL-lights-ambient
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
PhongGL& bindAmbientTexture(GL::Texture2DArray& texture);
#endif
/**
* @brief Bind a diffuse texture
* @return Reference to self (for method chaining)
*
* Expects that the shader was created with @ref Flag::DiffuseTexture
* enabled. If @ref lightCount() is zero, this function is a no-op, as
* diffuse color doesn't contribute to the output in that case.
* enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindDiffuseTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as diffuse
* color doesn't contribute to the output in that case.
* @see @ref bindTextures(), @ref setDiffuseColor()
*/
PhongGL& bindDiffuseTexture(GL::Texture2D& texture);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind a diffuse array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both
* @ref Flag::DiffuseTexture 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.
* If @ref lightCount() is zero, this function is a no-op, as diffuse
* color doesn't contribute to the output in that case.
* @see @ref setDiffuseColor()
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
PhongGL& bindDiffuseTexture(GL::Texture2DArray& texture);
#endif
/**
* @brief Bind a specular texture
* @return Reference to self (for method chaining)
*
* Expects that the shader was created with @ref Flag::SpecularTexture
* enabled. If @ref lightCount() is zero, this function is a no-op, as
* specular color doesn't contribute to the output in that case.
* enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindSpecularTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as specular
* color doesn't contribute to the output in that case.
* @see @ref bindTextures(), @ref setSpecularColor()
*/
PhongGL& bindSpecularTexture(GL::Texture2D& texture);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind a specular array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both
* @ref Flag::SpecularTexture 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. If
* @ref lightCount() is zero, this function is a no-op, as specular
* color doesn't contribute to the output in that case.
* @see @ref setSpecularColor()
* @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
* @requires_webgl20 Texture arrays are not available in WebGL 1.0.
*/
PhongGL& bindSpecularTexture(GL::Texture2DArray& texture);
#endif
/**
* @brief Bind a normal texture
* @return Reference to self (for method chaining)
@ -1370,6 +1511,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*
* Expects that the shader was created with @ref Flag::NormalTexture
* enabled and the @ref Tangent attribute was supplied. If
* @ref Flag::TextureArrays is enabled as well, use
* @ref bindNormalTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as normals
* don't contribute to the output in that case.
* @see @ref Shaders-PhongGL-normal-mapping,
@ -1377,6 +1520,23 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*/
PhongGL& bindNormalTexture(GL::Texture2D& texture);
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind a normal array texture
* @return Reference to self (for method chaining)
* @m_since_latest
*
* Expects that the shader was created with both
* @ref Flag::NormalTexture and @ref Flag::TextureArrays enabled and
* the @ref Tangent attribute was supplied. If @ref lightCount() is
* zero, this function is a no-op, as normals don't contribute to the
* output in that case.
* @see @ref Shaders-PhongGL-normal-mapping,
* @ref setNormalTextureScale()
*/
PhongGL& bindNormalTexture(GL::Texture2DArray& texture);
#endif
/**
* @brief Bind textures
* @return Reference to self (for method chaining)
@ -1385,8 +1545,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @ref PhongGL::Flag "Flag" is set, you can use @cpp nullptr @ce for
* the rest. Expects that the shader was created with at least one of
* @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture,
* @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled. More
* efficient than setting each texture separately.
* @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled and
* @ref Flag::TextureArrays is not set. More efficient than setting
* each texture separately.
* @see @ref bindAmbientTexture(), @ref bindDiffuseTexture(),
* @ref bindSpecularTexture(), @ref bindNormalTexture()
*/
@ -1418,19 +1579,22 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
_projectionMatrixUniform{1},
_normalMatrixUniform{2},
_textureMatrixUniform{3},
_ambientColorUniform{4},
_diffuseColorUniform{5},
_specularColorUniform{6},
_shininessUniform{7},
_normalTextureScaleUniform{8},
_alphaMaskUniform{9};
#ifndef MAGNUM_TARGET_GLES2
_textureLayerUniform{4},
#endif
_ambientColorUniform{5},
_diffuseColorUniform{6},
_specularColorUniform{7},
_shininessUniform{8},
_normalTextureScaleUniform{9},
_alphaMaskUniform{10};
#ifndef MAGNUM_TARGET_GLES2
Int _objectIdUniform{10};
Int _objectIdUniform{11};
#endif
Int _lightPositionsUniform{11},
_lightColorsUniform, /* 11 + lightCount, set in the constructor */
_lightSpecularColorsUniform, /* 11 + 2*lightCount */
_lightRangesUniform; /* 11 + 3*lightCount */
Int _lightPositionsUniform{12},
_lightColorsUniform, /* 12 + lightCount, set in the constructor */
_lightSpecularColorsUniform, /* 12 + 2*lightCount */
_lightRangesUniform; /* 12 + 3*lightCount */
#ifndef MAGNUM_TARGET_GLES2
/* Used instead of all other uniforms when Flag::UniformBuffers is set,
so it can alias them */

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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

2
src/Magnum/Shaders/generic.glsl

@ -35,7 +35,7 @@
#define TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION 8
#define NORMAL_MATRIX_ATTRIBUTE_LOCATION 12
#define TEXTURE_OFFSET_ATTRIBUTE_LOCATION 15
#define TEXTURE_OFFSET_ATTRIBUTE_LOCATION 15 /* + layer in the 3rd component */
/* Outputs */
#define COLOR_OUTPUT_ATTRIBUTE_LOCATION 0

Loading…
Cancel
Save