Browse Source

Shaders: properly use bitangents in Phong normal map calculation.

pull/470/head
Vladimír Vondruš 6 years ago
parent
commit
903e2c213c
  1. 10
      doc/changelog.dox
  2. 9
      src/Magnum/Shaders/Phong.cpp
  3. 16
      src/Magnum/Shaders/Phong.frag
  4. 71
      src/Magnum/Shaders/Phong.h
  5. 33
      src/Magnum/Shaders/Phong.vert
  6. 1
      src/Magnum/Shaders/Test/CMakeLists.txt
  7. 78
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  8. BIN
      src/Magnum/Shaders/Test/PhongTestFiles/textured-normal-left.tga

10
doc/changelog.dox

@ -114,6 +114,16 @@ See also:
- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also materials - @ref magnum-sceneconverter "magnum-sceneconverter" now lists also materials
and textures in `--info` and textures in `--info`
@subsubsection changelog-latest-changes-shaders Shaders library
- In the original implementation of normal mapping in @ref Shaders::Phong,
there shader didn't provide a way to supply bitangent direction, forcing
users to patch normal maps. This is now possible using newly added
@ref Shaders::Phong::Tangent4, @ref Shaders::Phong::Bitangent attributes
and a @ref Shaders::Phong::Flag::Bitangent flag, implementing support for
both four-component tangents (used by glTF, for example) and separate
tangent and bitangent direction (used by Assimp).
@subsubsection changelog-latest-changes-trade Trade library @subsubsection changelog-latest-changes-trade Trade library
- Recognizing TIFF file header magic in @ref Trade::AnyImageImporter "AnyImageImporter" - Recognizing TIFF file header magic in @ref Trade::AnyImageImporter "AnyImageImporter"

9
src/Magnum/Shaders/Phong.cpp

@ -98,6 +98,7 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
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) ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
.addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount)) .addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount))
@ -112,6 +113,7 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -141,8 +143,11 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l
bindAttributeLocation(Position::Location, "position"); bindAttributeLocation(Position::Location, "position");
if(lightCount) if(lightCount)
bindAttributeLocation(Normal::Location, "normal"); bindAttributeLocation(Normal::Location, "normal");
if((flags & Flag::NormalTexture) && lightCount) if((flags & Flag::NormalTexture) && lightCount) {
bindAttributeLocation(Tangent::Location, "tangent"); bindAttributeLocation(Tangent::Location, "tangent");
if(flags & Flag::Bitangent)
bindAttributeLocation(Bitangent::Location, "bitangent");
}
if(flags & Flag::VertexColor) if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture)) if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture))
@ -374,6 +379,7 @@ Debug& operator<<(Debug& debug, const Phong::Flag value) {
_c(DiffuseTexture) _c(DiffuseTexture)
_c(SpecularTexture) _c(SpecularTexture)
_c(NormalTexture) _c(NormalTexture)
_c(Bitangent)
_c(AlphaMask) _c(AlphaMask)
_c(VertexColor) _c(VertexColor)
_c(TextureTransformation) _c(TextureTransformation)
@ -396,6 +402,7 @@ Debug& operator<<(Debug& debug, const Phong::Flags value) {
Phong::Flag::DiffuseTexture, Phong::Flag::DiffuseTexture,
Phong::Flag::SpecularTexture, Phong::Flag::SpecularTexture,
Phong::Flag::NormalTexture, Phong::Flag::NormalTexture,
Phong::Flag::Bitangent,
Phong::Flag::AlphaMask, Phong::Flag::AlphaMask,
Phong::Flag::VertexColor, Phong::Flag::VertexColor,
Phong::Flag::InstancedTextureOffset, /* Superset of TextureTransformation */ Phong::Flag::InstancedTextureOffset, /* Superset of TextureTransformation */

16
src/Magnum/Shaders/Phong.frag

@ -154,7 +154,12 @@ uniform lowp vec4 lightColors[LIGHT_COUNT]
#if LIGHT_COUNT #if LIGHT_COUNT
in mediump vec3 transformedNormal; in mediump vec3 transformedNormal;
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifndef BITANGENT
in mediump vec4 transformedTangent;
#else
in mediump vec3 transformedTangent; in mediump vec3 transformedTangent;
in mediump vec3 transformedBitangent;
#endif
#endif #endif
in highp vec3 lightDirections[LIGHT_COUNT]; in highp vec3 lightDirections[LIGHT_COUNT];
in highp vec3 cameraDirection; in highp vec3 cameraDirection;
@ -218,11 +223,20 @@ void main() {
/* Normal */ /* Normal */
mediump vec3 normalizedTransformedNormal = normalize(transformedNormal); mediump vec3 normalizedTransformedNormal = normalize(transformedNormal);
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifndef BITANGENT
mediump vec3 normalizedTransformedTangent = normalize(transformedTangent.xyz);
#else
mediump vec3 normalizedTransformedTangent = normalize(transformedTangent); mediump vec3 normalizedTransformedTangent = normalize(transformedTangent);
mediump vec3 normalizedTransformedBitangent = normalize(transformedBitangent);
#endif
mediump mat3 tbn = mat3( mediump mat3 tbn = mat3(
normalizedTransformedTangent, normalizedTransformedTangent,
#ifndef BITANGENT
normalize(cross(normalizedTransformedNormal, normalize(cross(normalizedTransformedNormal,
normalizedTransformedTangent)), normalizedTransformedTangent)*transformedTangent.w),
#else
normalizedTransformedBitangent,
#endif
normalizedTransformedNormal normalizedTransformedNormal
); );
normalizedTransformedNormal = tbn*(normalize((texture(normalTexture, interpolatedTextureCoordinates).rgb*2.0 - vec3(1.0))*vec3(normalTextureScale, normalTextureScale, 1.0))); normalizedTransformedNormal = tbn*(normalize((texture(normalTexture, interpolatedTextureCoordinates).rgb*2.0 - vec3(1.0))*vec3(normalTextureScale, normalTextureScale, 1.0)));

71
src/Magnum/Shaders/Phong.h

@ -100,6 +100,35 @@ diffuse part and then separate the alpha like this:
@snippet MagnumShaders.cpp Phong-usage-alpha @snippet MagnumShaders.cpp Phong-usage-alpha
@section Shaders-Phong-normal-mapping Normal mapping
If you want to use normal textures, enable @ref Flag::NormalTexture and call
@ref bindNormalTexture(). In addition you need to supply per-vertex tangent and
bitangent direction:
- either using a four-component @ref Tangent4 attribute, where the sign of
the fourth component defines handedness of tangent basis, as described in
@ref Trade::MeshAttribute::Tangent;
- or a using pair of three-component @ref Tangent and @ref Bitangent
attributes together with enabling @ref Flag::Bitangent
If you supply just a three-component @ref Tangent attribute and no bitangents,
the shader will implicitly assume the fourth component to be @cpp 1.0f @ce,
forming a right-handed tangent space. This is a valid optimization when you
have full control over the bitangent orientation, but won't work with general
meshes.
@m_class{m-note m-success}
@par
You can also use the @ref MeshVisualizer3D shader to visualize and debug
per-vertex normal, tangent and binormal direction, among other things.
The strength of the effect can be controlled by
@ref setNormalTextureScale(). See
@ref Trade::MaterialAttribute::NormalTextureScale for a description of the
factor is used.
@section Shaders-Phong-object-id Object ID output @section Shaders-Phong-object-id Object ID output
The shader supports writing object ID to the framebuffer for object picking or The shader supports writing object ID to the framebuffer for object picking or
@ -177,11 +206,40 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
* @m_since{2019,10} * @m_since{2019,10}
* *
* @ref shaders-generic "Generic attribute", * @ref shaders-generic "Generic attribute",
* @ref Magnum::Vector3 "Vector3", used only if * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4
* @ref Flag::NormalTexture is set. * attribute. If only a three-component attribute is used and
* @ref Flag::Bitangent is not enabled, it's the same as if
* @ref Tangent4 was specified with the fourth component always being
* @cpp 1.0f @ce. Used only if @ref Flag::NormalTexture is set.
* @see @ref Shaders-Phong-normal-mapping
*/ */
typedef Generic3D::Tangent Tangent; typedef Generic3D::Tangent Tangent;
/**
* @brief Tangent direction with a bitangent sign
* @m_since_latest
*
* @ref shaders-generic "Generic attribute",
* @ref Magnum::Vector4 "Vector4". Use either this or the @ref Tangent
* attribute. If @ref Flag::Bitangent is set, the fourth component is
* ignored and bitangents are taken from the @ref Bitangent attribute
* instead. Used only if @ref Flag::NormalTexture is set.
* @see @ref Shaders-Phong-normal-mapping
*/
typedef typename Generic3D::Tangent4 Tangent4;
/**
* @brief Bitangent direction
* @m_since_latest
*
* @ref shaders-generic "Generic attribute",
* @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4
* attribute. Used only if both @ref Flag::NormalTexture and
* @ref Flag::Bitangent are set.
* @see @ref Shaders-Phong-normal-mapping
*/
typedef typename Generic3D::Bitangent Bitangent;
/** /**
* @brief 2D texture coordinates * @brief 2D texture coordinates
* *
@ -348,6 +406,15 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
*/ */
VertexColor = 1 << 5, VertexColor = 1 << 5,
/**
* Use the separate @ref Bitangent attribute for retrieving vertex
* bitangents. If this flag is not present, the last component of
* @ref Tangent4 is used to calculate bitangent direction. See
* @ref Shaders-Phong-normal-mapping for more information.
* @m_since_latest
*/
Bitangent = 1 << 11,
/** /**
* Enable texture coordinate transformation. If this flag is set, * Enable texture coordinate transformation. If this flag is set,
* the shader expects that at least one of * the shader expects that at least one of

33
src/Magnum/Shaders/Phong.vert

@ -95,7 +95,20 @@ in mediump vec3 normal;
#ifdef EXPLICIT_ATTRIB_LOCATION #ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = TANGENT_ATTRIBUTE_LOCATION) layout(location = TANGENT_ATTRIBUTE_LOCATION)
#endif #endif
in mediump vec3 tangent; in mediump
#ifndef BITANGENT
vec4
#else
vec3
#endif
tangent;
#endif
#ifdef BITANGENT
#ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = BITANGENT_ATTRIBUTE_LOCATION)
#endif
in mediump vec3 bitangent;
#endif #endif
#endif #endif
@ -148,7 +161,12 @@ in mediump vec2 instancedTextureOffset;
#if LIGHT_COUNT #if LIGHT_COUNT
out mediump vec3 transformedNormal; out mediump vec3 transformedNormal;
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifndef BITANGENT
out mediump vec4 transformedTangent;
#else
out mediump vec3 transformedTangent; out mediump vec3 transformedTangent;
out mediump vec3 transformedBitangent;
#endif
#endif #endif
out highp vec3 lightDirections[LIGHT_COUNT]; out highp vec3 lightDirections[LIGHT_COUNT];
out highp vec3 cameraDirection; out highp vec3 cameraDirection;
@ -171,11 +189,24 @@ void main() {
#endif #endif
normal; normal;
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifndef BITANGENT
transformedTangent = vec4(normalMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedNormalMatrix*
#endif
tangent.xyz, tangent.w);
#else
transformedTangent = normalMatrix* transformedTangent = normalMatrix*
#ifdef INSTANCED_TRANSFORMATION #ifdef INSTANCED_TRANSFORMATION
instancedNormalMatrix* instancedNormalMatrix*
#endif #endif
tangent; tangent;
transformedBitangent = normalMatrix*
#ifdef INSTANCED_TRANSFORMATION
instancedNormalMatrix*
#endif
bitangent;
#endif
#endif #endif
/* Direction to the light */ /* Direction to the light */

1
src/Magnum/Shaders/Test/CMakeLists.txt

@ -234,6 +234,7 @@ if(BUILD_GL_TESTS)
PhongTestFiles/textured-diffuse.tga PhongTestFiles/textured-diffuse.tga
PhongTestFiles/textured-diffuse-transformed.tga PhongTestFiles/textured-diffuse-transformed.tga
PhongTestFiles/textured-normal.tga PhongTestFiles/textured-normal.tga
PhongTestFiles/textured-normal-left.tga
PhongTestFiles/textured-normal0.0.tga PhongTestFiles/textured-normal0.0.tga
PhongTestFiles/textured-normal0.5.tga PhongTestFiles/textured-normal0.5.tga
PhongTestFiles/textured-specular.tga PhongTestFiles/textured-specular.tga

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

@ -145,6 +145,8 @@ constexpr struct {
{"diffuse texture + texture transform", Phong::Flag::DiffuseTexture|Phong::Flag::TextureTransformation, 1}, {"diffuse texture + texture transform", Phong::Flag::DiffuseTexture|Phong::Flag::TextureTransformation, 1},
{"specular texture", Phong::Flag::SpecularTexture, 1}, {"specular texture", Phong::Flag::SpecularTexture, 1},
{"normal texture", Phong::Flag::NormalTexture, 1}, {"normal texture", Phong::Flag::NormalTexture, 1},
{"normal texture + separate bitangents", Phong::Flag::NormalTexture|Phong::Flag::Bitangent, 1},
{"separate bitangents alone", Phong::Flag::Bitangent, 1},
{"ambient + diffuse texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 1}, {"ambient + diffuse texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 1},
{"ambient + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::SpecularTexture, 1}, {"ambient + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::SpecularTexture, 1},
{"diffuse + specular texture", Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1}, {"diffuse + specular texture", Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1},
@ -210,13 +212,52 @@ const struct {
bool multiBind; bool multiBind;
Deg rotation; Deg rotation;
Float scale; Float scale;
Vector4 tangent;
Vector3 bitangent;
Shaders::Phong::Tangent4::Components tangentComponents;
bool flipNormalY;
Shaders::Phong::Flags flags;
} RenderTexturedNormalData[]{ } RenderTexturedNormalData[]{
{"", "textured-normal.tga", false, {}, 1.0f}, {"", "textured-normal.tga", false, {}, 1.0f,
{"multi bind", "textured-normal.tga", true, {}, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {},
{"rotated 90°", "textured-normal.tga", false, 90.0_degf, 1.0f}, Shaders::Phong::Tangent4::Components::Four, false, {}},
{"rotated -90°", "textured-normal.tga", false, -90.0_degf, 1.0f}, {"multi bind", "textured-normal.tga", true, {}, 1.0f,
{"0.5 scale", "textured-normal0.5.tga", false, {}, 0.5f}, {1.0f, 0.0f, 0.0f, 1.0f}, {},
{"0.0 scale", "textured-normal0.0.tga", false, {}, 0.0f} Shaders::Phong::Tangent4::Components::Four, false, {}},
{"rotated 90°", "textured-normal.tga", false, 90.0_degf, 1.0f,
{1.0f, 0.0f, 0.0f, 1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, false, {}},
{"rotated -90°", "textured-normal.tga", false, -90.0_degf, 1.0f,
{1.0f, 0.0f, 0.0f, 1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, false, {}},
{"0.5 scale", "textured-normal0.5.tga", false, {}, 0.5f,
{1.0f, 0.0f, 0.0f, 1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, false, {}},
{"0.0 scale", "textured-normal0.0.tga", false, {}, 0.0f,
{1.0f, 0.0f, 0.0f, 1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, false, {}},
/* The fourth component, if missing, gets automatically filled up to 1,
so this should work */
{"implicit bitangent direction", "textured-normal.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, 0.0f}, {},
Shaders::Phong::Tangent4::Components::Three, false, {}},
{"separate bitangents", "textured-normal.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f},
Shaders::Phong::Tangent4::Components::Three, false,
Shaders::Phong::Flag::Bitangent},
{"right-handed, flipped Y", "textured-normal-left.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, 1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, true, {}},
{"left-handed", "textured-normal-left.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, -1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, false, {}},
{"left-handed, separate bitangents", "textured-normal-left.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f},
Shaders::Phong::Tangent4::Components::Three, false,
Shaders::Phong::Flag::Bitangent},
{"left-handed, flipped Y", "textured-normal.tga", false, {}, 1.0f,
{1.0f, 0.0f, 0.0f, -1.0f}, {},
Shaders::Phong::Tangent4::Components::Four, true, {}}
}; };
const struct { const struct {
@ -903,9 +944,14 @@ void PhongGLTest::renderTexturedNormal() {
Containers::Pointer<Trade::AbstractImporter> importer = _manager.loadAndInstantiate("AnyImageImporter"); Containers::Pointer<Trade::AbstractImporter> importer = _manager.loadAndInstantiate("AnyImageImporter");
CORRADE_VERIFY(importer); CORRADE_VERIFY(importer);
GL::Texture2D normal; /* Normal texture. Flip normal Y, if requested */
Containers::Optional<Trade::ImageData2D> image; Containers::Optional<Trade::ImageData2D> image;
CORRADE_VERIFY(importer->openFile(Utility::Directory::join(_testDir, "TestFiles/normal-texture.tga")) && (image = importer->image2D(0))); CORRADE_VERIFY(importer->openFile(Utility::Directory::join(_testDir, "TestFiles/normal-texture.tga")) && (image = importer->image2D(0)));
if(data.flipNormalY) for(auto row: image->mutablePixels<Color3ub>())
for(Color3ub& pixel: row)
pixel.y() = 255 - pixel.y();
GL::Texture2D normal;
normal.setMinificationFilter(GL::SamplerFilter::Linear) normal.setMinificationFilter(GL::SamplerFilter::Linear)
.setMagnificationFilter(GL::SamplerFilter::Linear) .setMagnificationFilter(GL::SamplerFilter::Linear)
.setWrapping(GL::SamplerWrapping::ClampToEdge) .setWrapping(GL::SamplerWrapping::ClampToEdge)
@ -914,16 +960,24 @@ void PhongGLTest::renderTexturedNormal() {
GL::Mesh plane = MeshTools::compile(Primitives::planeSolid( Primitives::PlaneFlag::TextureCoordinates)); GL::Mesh plane = MeshTools::compile(Primitives::planeSolid( Primitives::PlaneFlag::TextureCoordinates));
/* Add hardcoded tangents */ /* Add tangents / bitangents of desired component count. Unused components
/** @todo remove once MeshData is sane */ are set to zero to ensure the shader doesn't use them. */
const struct TangentBitangent {
Vector4 tangent;
Vector3 bitangent;
} tangentBitangent{data.tangent, data.bitangent};
GL::Buffer tangents; GL::Buffer tangents;
tangents.setData(Containers::Array<Vector3>{Containers::DirectInit, 4, Vector3::xAxis()}); tangents.setData(Containers::Array<TangentBitangent>{Containers::DirectInit, 4, tangentBitangent});
plane.addVertexBuffer(std::move(tangents), 0, Shaders::Phong::Tangent{}); plane.addVertexBuffer(tangents, 0, sizeof(TangentBitangent),
GL::DynamicAttribute{Shaders::Phong::Tangent4{data.tangentComponents}});
plane.addVertexBuffer(std::move(tangents), sizeof(Vector4),
sizeof(TangentBitangent),
GL::DynamicAttribute{Shaders::Phong::Bitangent{}});
/* Rotating the view a few times (together with light positions). If the /* Rotating the view a few times (together with light positions). If the
tangent transformation in the shader is correct, it should result in tangent transformation in the shader is correct, it should result in
exactly the same images. */ exactly the same images. */
Phong shader{Phong::Flag::NormalTexture, 2}; Phong shader{Phong::Flag::NormalTexture|data.flags, 2};
shader.setLightPositions({ shader.setLightPositions({
Matrix4::rotationZ(data.rotation).transformPoint({-3.0f, -3.0f, 0.0f}), Matrix4::rotationZ(data.rotation).transformPoint({-3.0f, -3.0f, 0.0f}),
Matrix4::rotationZ(data.rotation).transformPoint({ 3.0f, -3.0f, 0.0f})}) Matrix4::rotationZ(data.rotation).transformPoint({ 3.0f, -3.0f, 0.0f})})

BIN
src/Magnum/Shaders/Test/PhongTestFiles/textured-normal-left.tga

Binary file not shown.
Loading…
Cancel
Save