Browse Source

PhongGL & tests

pull/576/head
Vladislav Oleshko 4 years ago
parent
commit
cf9b90ff9b
  1. 162
      src/Magnum/Shaders/PhongGL.cpp
  2. 30
      src/Magnum/Shaders/PhongGL.h
  3. 105
      src/Magnum/Shaders/Test/PhongGLTest.cpp

162
src/Magnum/Shaders/PhongGL.cpp

@ -37,7 +37,6 @@
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
#include "Magnum/GL/Extensions.h" #include "Magnum/GL/Extensions.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Texture.h" #include "Magnum/GL/Texture.h"
#include "Magnum/Math/Color.h" #include "Magnum/Math/Color.h"
#include "Magnum/Math/Matrix3.h" #include "Magnum/Math/Matrix3.h"
@ -74,21 +73,11 @@ namespace {
#endif #endif
} }
PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount , const UnsignedInt materialCount, const UnsignedInt drawCount
#endif #endif
): ) {
_flags{flags},
_lightCount{lightCount},
#ifndef MAGNUM_TARGET_GLES2
_materialCount{materialCount},
_drawCount{drawCount},
#endif
_lightColorsUniform{_lightPositionsUniform + Int(lightCount)},
_lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)},
_lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)}
{
{ {
const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture))
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -96,32 +85,32 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#endif #endif
; ;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
"Shaders::PhongGL: texture transformation enabled but the shader is not textured", ); "Shaders::PhongGL: texture transformation enabled but the shader is not textured", CompileState{NoCreate});
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent), CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent),
"Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", ); "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::PhongGL: material count can't be zero", ); "Shaders::PhongGL: material count can't be zero", CompileState{NoCreate});
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::PhongGL: draw count can't be zero", ); "Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture, 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", ); "Shaders::PhongGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), 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", ); "Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate});
CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers), CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers),
"Shaders::PhongGL: light culling requires uniform buffers to be enabled", ); "Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate});
#endif #endif
CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)), CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)),
"Shaders::PhongGL: specular texture requires the shader to not have specular disabled", ); "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", CompileState{NoCreate});
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(flags >= Flag::UniformBuffers)
@ -154,7 +143,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(), CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(),
"Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), ); "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -163,6 +152,17 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200});
#endif #endif
PhongGL out{NoInit};
out._flags = flags;
out._lightCount = lightCount;
out._lightColorsUniform = out._lightPositionsUniform + Int(lightCount);
out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(lightCount);
out._lightRangesUniform = out._lightPositionsUniform + 3*Int(lightCount);
#ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount;
out._drawCount = drawCount;
#endif
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
@ -283,9 +283,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
"#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n"
"#define LIGHT_RANGES_LOCATION {}\n", "#define LIGHT_RANGES_LOCATION {}\n",
lightCount, lightCount,
_lightPositionsUniform + lightCount, out._lightPositionsUniform + lightCount,
_lightPositionsUniform + 2*lightCount, out._lightPositionsUniform + 2*lightCount,
_lightPositionsUniform + 3*lightCount)); out._lightPositionsUniform + 3*lightCount));
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!(flags >= Flag::UniformBuffers) && lightCount) if(!(flags >= Flag::UniformBuffers) && lightCount)
@ -294,9 +294,10 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Phong.frag")); .addSource(rs.getString("Phong.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); vert.submitCompile();
frag.submitCompile();
attachShaders({vert, frag}); out.attachShaders({vert, frag});
/* ES3 has this done in the shader directly and doesn't even provide /* ES3 has this done in the shader directly and doesn't even provide
bindFragmentDataLocation() */ bindFragmentDataLocation() */
@ -305,103 +306,115 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_attrib_location>(version))
#endif #endif
{ {
bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
if(lightCount) if(lightCount)
bindAttributeLocation(Normal::Location, "normal"); out.bindAttributeLocation(Normal::Location, "normal");
if((flags & Flag::NormalTexture) && lightCount) { if((flags & Flag::NormalTexture) && lightCount) {
bindAttributeLocation(Tangent::Location, "tangent"); out.bindAttributeLocation(Tangent::Location, "tangent");
if(flags & Flag::Bitangent) if(flags & Flag::Bitangent)
bindAttributeLocation(Bitangent::Location, "bitangent"); out.bindAttributeLocation(Bitangent::Location, "bitangent");
} }
if(flags & Flag::VertexColor) if(flags & Flag::VertexColor)
bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ out.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 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || flags >= Flag::ObjectIdTexture
#endif #endif
) )
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) { if(flags & Flag::ObjectId) {
bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ColorOutput, "color");
bindFragmentDataLocation(ObjectIdOutput, "objectId"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
} }
if(flags >= Flag::InstancedObjectId) if(flags >= Flag::InstancedObjectId)
bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) { if(flags & Flag::InstancedTransformation) {
bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(lightCount) if(lightCount)
bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
} }
if(flags >= Flag::InstancedTextureOffset) if(flags >= Flag::InstancedTextureOffset)
bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
} }
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); out.submitLink();
return CompileState{std::move(out), std::move(vert), std::move(frag), version};
}
PhongGL::PhongGL(CompileState&& cs)
: PhongGL{static_cast<PhongGL&&>(std::move(cs))} {
if (id() == 0) return;
CORRADE_INTERNAL_ASSERT_OUTPUT(checkLink());
const GL::Context& context = GL::Context::current();
const GL::Version version = cs._version;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version)) if(!context.isExtensionSupported<GL::Extensions::ARB::explicit_uniform_location>(version))
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset"); if(_drawCount > 1) _drawOffsetUniform = uniformLocation("drawOffset");
} else } else
#endif #endif
{ {
_transformationMatrixUniform = uniformLocation("transformationMatrix"); _transformationMatrixUniform = uniformLocation("transformationMatrix");
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
_textureMatrixUniform = uniformLocation("textureMatrix"); _textureMatrixUniform = uniformLocation("textureMatrix");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::TextureArrays) if(_flags & Flag::TextureArrays)
_textureLayerUniform = uniformLocation("textureLayer"); _textureLayerUniform = uniformLocation("textureLayer");
#endif #endif
_projectionMatrixUniform = uniformLocation("projectionMatrix"); _projectionMatrixUniform = uniformLocation("projectionMatrix");
_ambientColorUniform = uniformLocation("ambientColor"); _ambientColorUniform = uniformLocation("ambientColor");
if(lightCount) { if(_lightCount) {
_normalMatrixUniform = uniformLocation("normalMatrix"); _normalMatrixUniform = uniformLocation("normalMatrix");
_diffuseColorUniform = uniformLocation("diffuseColor"); _diffuseColorUniform = uniformLocation("diffuseColor");
if(!(flags & Flag::NoSpecular)) { if(!(_flags & Flag::NoSpecular)) {
_specularColorUniform = uniformLocation("specularColor"); _specularColorUniform = uniformLocation("specularColor");
_shininessUniform = uniformLocation("shininess"); _shininessUniform = uniformLocation("shininess");
} }
if(flags & Flag::NormalTexture) if(_flags & Flag::NormalTexture)
_normalTextureScaleUniform = uniformLocation("normalTextureScale"); _normalTextureScaleUniform = uniformLocation("normalTextureScale");
_lightPositionsUniform = uniformLocation("lightPositions"); _lightPositionsUniform = uniformLocation("lightPositions");
_lightColorsUniform = uniformLocation("lightColors"); _lightColorsUniform = uniformLocation("lightColors");
if(!(flags & Flag::NoSpecular)) if(!(_flags & Flag::NoSpecular))
_lightSpecularColorsUniform = uniformLocation("lightSpecularColors"); _lightSpecularColorsUniform = uniformLocation("lightSpecularColors");
_lightRangesUniform = uniformLocation("lightRanges"); _lightRangesUniform = uniformLocation("lightRanges");
} }
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); if(_flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId"); if(_flags & Flag::ObjectId) _objectIdUniform = uniformLocation("objectId");
#endif #endif
} }
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags && !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version)) if(_flags && !context.isExtensionSupported<GL::Extensions::ARB::shading_language_420pack>(version))
#endif #endif
{ {
if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit); if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit);
if(lightCount) { if(_lightCount) {
if(flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit); if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"), DiffuseTextureUnit);
if(flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit); if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"), SpecularTextureUnit);
if(flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit); if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"), NormalTextureUnit);
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit); if(_flags >= Flag::ObjectIdTexture) setUniform(uniformLocation("objectIdTextureData"), ObjectIdTextureUnit);
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding); setUniformBlockBinding(uniformBlockIndex("Projection"), ProjectionBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("Transformation"), TransformationBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding); setUniformBlockBinding(uniformBlockIndex("Draw"), DrawBufferBinding);
setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding); setUniformBlockBinding(uniformBlockIndex("Material"), MaterialBufferBinding);
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding); setUniformBlockBinding(uniformBlockIndex("TextureTransformation"), TextureTransformationBufferBinding);
if(lightCount) if(_lightCount)
setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding); setUniformBlockBinding(uniformBlockIndex("Light"), LightBufferBinding);
} }
#endif #endif
@ -410,44 +423,51 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
/* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(_flags >= Flag::UniformBuffers) {
/* Draw offset is zero by default */ /* Draw offset is zero by default */
} else } else
#endif #endif
{ {
/* Default to fully opaque white so we can see the textures */ /* Default to fully opaque white so we can see the textures */
if(flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f}); if(_flags & Flag::AmbientTexture) setAmbientColor(Magnum::Color4{1.0f});
else setAmbientColor(Magnum::Color4{0.0f}); else setAmbientColor(Magnum::Color4{0.0f});
setTransformationMatrix(Matrix4{Math::IdentityInit}); setTransformationMatrix(Matrix4{Math::IdentityInit});
setProjectionMatrix(Matrix4{Math::IdentityInit}); setProjectionMatrix(Matrix4{Math::IdentityInit});
if(lightCount) { if(_lightCount) {
setDiffuseColor(Magnum::Color4{1.0f}); setDiffuseColor(Magnum::Color4{1.0f});
if(!(flags & Flag::NoSpecular)) { if(!(_flags & Flag::NoSpecular)) {
setSpecularColor(Magnum::Color4{1.0f, 0.0f}); setSpecularColor(Magnum::Color4{1.0f, 0.0f});
setShininess(80.0f); setShininess(80.0f);
} }
if(flags & Flag::NormalTexture) if(_flags & Flag::NormalTexture)
setNormalTextureScale(1.0f); setNormalTextureScale(1.0f);
setLightPositions(Containers::Array<Vector4>{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); setLightPositions(Containers::Array<Vector4>{DirectInit, _lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}});
Containers::Array<Magnum::Color3> colors{DirectInit, lightCount, Magnum::Color3{1.0f}}; Containers::Array<Magnum::Color3> colors{DirectInit, _lightCount, Magnum::Color3{1.0f}};
setLightColors(colors); setLightColors(colors);
if(!(flags & Flag::NoSpecular)) if(!(_flags & Flag::NoSpecular))
setLightSpecularColors(colors); setLightSpecularColors(colors);
setLightRanges(Containers::Array<Float>{DirectInit, lightCount, Constants::inf()}); setLightRanges(Containers::Array<Float>{DirectInit, _lightCount, Constants::inf()});
/* Light position is zero by default */ /* Light position is zero by default */
setNormalMatrix(Matrix3x3{Math::IdentityInit}); setNormalMatrix(Matrix3x3{Math::IdentityInit});
} }
if(flags & Flag::TextureTransformation) if(_flags & Flag::TextureTransformation)
setTextureMatrix(Matrix3{Math::IdentityInit}); setTextureMatrix(Matrix3{Math::IdentityInit});
/* Texture layer is zero by default */ /* Texture layer is zero by default */
if(flags & Flag::AlphaMask) setAlphaMask(0.5f); if(_flags & Flag::AlphaMask) setAlphaMask(0.5f);
/* Object ID is zero by default */ /* Object ID is zero by default */
} }
#endif #endif
} }
PhongGL::PhongGL(Flags flags, UnsignedInt lightCount) : PhongGL{compile(flags, lightCount)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{flags, lightCount, 1, 1} {} PhongGL::CompileState PhongGL::compile(Flags flags, UnsignedInt lightCount) {
return compile(flags, lightCount, 1, 1);
}
PhongGL::PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount)
: PhongGL{compile(flags, lightCount, materialCount, drawCount)} {}
#endif #endif
PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) {

30
src/Magnum/Shaders/PhongGL.h

@ -31,6 +31,7 @@
*/ */
#include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/AbstractShaderProgram.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/Shaders/GenericGL.h" #include "Magnum/Shaders/GenericGL.h"
#include "Magnum/Shaders/visibility.h" #include "Magnum/Shaders/visibility.h"
@ -821,6 +822,20 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
*/ */
explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {}
class CompileState;
explicit PhongGL(CompileState&& cs);
static CompileState compile(Flags flags, UnsignedInt lightCount
#ifndef MAGNUM_TARGET_GLES2
, UnsignedInt materialCount, UnsignedInt drawCount
#endif
);
#ifndef MAGNUM_TARGET_GLES2
static CompileState compile(Flags flags, UnsignedInt lightCount);
#endif
/** @brief Copying is not allowed */ /** @brief Copying is not allowed */
PhongGL(const PhongGL&) = delete; PhongGL(const PhongGL&) = delete;
@ -1744,6 +1759,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif #endif
private: private:
explicit PhongGL(NoInitT) {}
/* Prevent accidentally calling irrelevant functions */ /* Prevent accidentally calling irrelevant functions */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
using GL::AbstractShaderProgram::drawTransformFeedback; using GL::AbstractShaderProgram::drawTransformFeedback;
@ -1784,6 +1801,19 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif #endif
}; };
class PhongGL::CompileState : public PhongGL {
private:
friend class PhongGL;
explicit CompileState(NoCreateT) : PhongGL{NoCreate}, _vert{NoCreate}, _frag{NoCreate} {}
CompileState(PhongGL&& shader, GL::Shader&& vert, GL::Shader&& frag, GL::Version version) :
PhongGL{std::move(shader)}, _vert{std::move(vert)}, _frag{std::move(frag)}, _version{version} {}
GL::Shader _vert, _frag;
GL::Version _version;
};
/** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */ /** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */
MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value); MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value);

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

@ -31,12 +31,12 @@
#include <Corrade/PluginManager/Manager.h> #include <Corrade/PluginManager/Manager.h>
#include <Corrade/TestSuite/Compare/Numeric.h> #include <Corrade/TestSuite/Compare/Numeric.h>
#include <Corrade/Utility/DebugStl.h> #include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/System.h>
#include <Corrade/Utility/FormatStl.h> #include <Corrade/Utility/FormatStl.h>
#include <Corrade/Utility/Path.h> #include <Corrade/Utility/Path.h>
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
#include <Corrade/Containers/Pair.h> #include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/System.h> /* isSandboxed() */
#endif #endif
#include "Magnum/Image.h" #include "Magnum/Image.h"
@ -83,8 +83,10 @@ struct PhongGLTest: GL::OpenGLTester {
explicit PhongGLTest(); explicit PhongGLTest();
void construct(); void construct();
void constructAsync();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void constructUniformBuffers(); void constructUniformBuffers();
void constructUniformBuffersAsync();
#endif #endif
void constructMove(); void constructMove();
@ -927,9 +929,13 @@ PhongGLTest::PhongGLTest() {
addInstancedTests({&PhongGLTest::construct}, addInstancedTests({&PhongGLTest::construct},
Containers::arraySize(ConstructData)); Containers::arraySize(ConstructData));
addTests({&PhongGLTest::constructAsync});
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&PhongGLTest::constructUniformBuffers}, addInstancedTests({&PhongGLTest::constructUniformBuffers},
Containers::arraySize(ConstructUniformBuffersData)); Containers::arraySize(ConstructUniformBuffersData));
addTests({&PhongGLTest::constructUniformBuffersAsync});
#endif #endif
addTests({ addTests({
@ -1192,6 +1198,45 @@ void PhongGLTest::construct() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void PhongGLTest::constructAsync() {
constexpr struct {
const char* name;
PhongGL::Flags flags;
UnsignedInt lightCount;
} data {
"instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3
};
setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES
if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())
CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported.");
#endif
auto compileState = PhongGL::compile(data.flags, data.lightCount);
CORRADE_COMPARE(compileState.flags(), data.flags);
CORRADE_COMPARE(compileState.lightCount(), data.lightCount);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
PhongGL shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.lightCount(), data.lightCount);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void PhongGLTest::constructUniformBuffers() { void PhongGLTest::constructUniformBuffers() {
auto&& data = ConstructUniformBuffersData[testCaseInstanceId()]; auto&& data = ConstructUniformBuffersData[testCaseInstanceId()];
@ -1234,6 +1279,64 @@ void PhongGLTest::constructUniformBuffers() {
MAGNUM_VERIFY_NO_GL_ERROR(); MAGNUM_VERIFY_NO_GL_ERROR();
} }
void PhongGLTest::constructUniformBuffersAsync() {
constexpr struct {
const char* name;
PhongGL::Flags flags;
UnsignedInt lightCount, materialCount, drawCount;
} data {
"multiple lights, materials, draws + light culling", PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, 8, 8, 24
};
setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES
if((data.flags & PhongGL::Flag::UniformBuffers) && !GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::gpu_shader4>())
CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported.");
if((data.flags & PhongGL::Flag::TextureArrays) && !GL::Context::current().isExtensionSupported<GL::Extensions::EXT::texture_array>())
CORRADE_SKIP(GL::Extensions::EXT::texture_array::string() << "is not supported.");
#endif
if(data.flags >= PhongGL::Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::shader_draw_parameters>())
CORRADE_SKIP(GL::Extensions::ARB::shader_draw_parameters::string() << "is not supported.");
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ANGLE::multi_draw>())
CORRADE_SKIP(GL::Extensions::ANGLE::multi_draw::string() << "is not supported.");
#else
if(!GL::Context::current().isExtensionSupported<GL::Extensions::WEBGL::multi_draw>())
CORRADE_SKIP(GL::Extensions::WEBGL::multi_draw::string() << "is not supported.");
#endif
}
auto compileState = PhongGL::compile(data.flags, data.lightCount, data.materialCount, data.drawCount);
CORRADE_COMPARE(compileState.flags(), data.flags);
CORRADE_COMPARE(compileState.lightCount(), data.lightCount);
CORRADE_COMPARE(compileState.materialCount(), data.materialCount);
CORRADE_COMPARE(compileState.drawCount(), data.drawCount);
while(!compileState.isLinkFinished())
Utility::System::sleep(100);
PhongGL shader{std::move(compileState)};
CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.lightCount(), data.lightCount);
CORRADE_COMPARE(shader.materialCount(), data.materialCount);
CORRADE_COMPARE(shader.drawCount(), data.drawCount);
CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id());
{
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
#endif
CORRADE_VERIFY(shader.validate().first);
}
MAGNUM_VERIFY_NO_GL_ERROR();
}
#endif #endif
void PhongGLTest::constructMove() { void PhongGLTest::constructMove() {

Loading…
Cancel
Save