diff --git a/shaders/GameShader.frag b/shaders/GameShader.frag index feb7727..2f2963b 100644 --- a/shaders/GameShader.frag +++ b/shaders/GameShader.frag @@ -12,8 +12,11 @@ in mediump vec3 transformedNormal; in highp vec3 cameraDirection; in mediump vec2 interpolatedTextureCoords; + +#ifdef ENABLE_SHADOWMAP_LEVELS in highp vec3 shadowCoord[ENABLE_SHADOWMAP_LEVELS]; uniform float shadowDepthSplits[ENABLE_SHADOWMAP_LEVELS]; +#endif out lowp vec4 color; @@ -21,11 +24,9 @@ in vec3 worldPos; uniform mat4 modelMatrix; -in highp vec3 normalRaw; - - -float computeShadow(vec3 levelShadowCoord, int shadowLevel, vec3 normal, vec3 lightDir) { +#ifdef ENABLE_SHADOWMAP_LEVELS +float computeShadowAtLevel(vec3 levelShadowCoord, int shadowLevel, vec3 normal, vec3 lightDir) { float baseBias = 0.0010 + shadowLevel * 0.001; float slopeScaledBias = baseBias * max(1.0 - dot(normal, lightDir), 0.0); // Slope-scaled bias float dZdx = dFdx(levelShadowCoord.z); @@ -35,51 +36,42 @@ float computeShadow(vec3 levelShadowCoord, int shadowLevel, vec3 normal, vec3 li float bias = depthOffset + slopeScaledBias; #ifdef SHADOWMAP_PCF - { - vec2 texelSize = vec2(1.0) / textureSize(shadowmapTexture, 0).xy; - float shadow = 0.0; - for (int x = -1; x <= 1; ++x) { - for (int y = -1; y <= 1; ++y) { - vec2 offset = vec2(x, y) * texelSize; - shadow += texture(shadowmapTexture, vec4(levelShadowCoord.xy + offset, shadowLevel, clamp(levelShadowCoord.z - bias, 0.0, 1.0))); - } + vec2 texelSize = vec2(1.0) / textureSize(shadowmapTexture, 0).xy; + float shadow = 0.0; + for (int x = -1; x <= 1; ++x) { + for (int y = -1; y <= 1; ++y) { + vec2 offset = vec2(x, y) * texelSize; + shadow += texture(shadowmapTexture, vec4(levelShadowCoord.xy + offset, shadowLevel, clamp(levelShadowCoord.z - bias, 0.0, 1.0))); } - return shadow / 9.0; // Average PCF samples } + return shadow / 9.0; // Average PCF samples #else // return texture(shadowmapTexture, vec4(levelShadowCoord.xy, shadowLevel, clamp(levelShadowCoord.z - bias, 0.0, 1.0))); return texture(shadowmapTexture, vec4(levelShadowCoord.xy, shadowLevel, levelShadowCoord.z - bias)); #endif } +float computeShadow(vec3 normalizedTransformedNormal) { + lowp float intensity = dot(normalizedTransformedNormal, light); + if (intensity > 0) { + for (int shadowLevel = 0; shadowLevel < ENABLE_SHADOWMAP_LEVELS; shadowLevel++) { + vec3 levelShadowCoord = shadowCoord[shadowLevel]; + bool inRange = levelShadowCoord.x > 0 && levelShadowCoord.y > 0 && levelShadowCoord.x < 1 && levelShadowCoord.y < 1 && levelShadowCoord.z > 0 && levelShadowCoord.z < 1; + if (inRange) { + return computeShadowAtLevel(levelShadowCoord, shadowLevel, normalizedTransformedNormal, light); + } + } + } + return 0.0; +} +#endif void main() { lowp vec3 diffuseColor = texture(diffuseTexture, interpolatedTextureCoords).xyz; -/* Ambient color */ vec3 ambient = ambientColor; mediump vec3 normalizedTransformedNormal = normalize(transformedNormal); - float shadow = 0.0; - lowp float intensity = dot(normalizedTransformedNormal, light); - int shadowLevel = 0; - if (intensity <= 0) { - shadow = 0.0f; - intensity = 0.0f; - } - else { - for (; shadowLevel < ENABLE_SHADOWMAP_LEVELS; shadowLevel++) { - vec3 levelShadowCoord = shadowCoord[shadowLevel]; - bool inRange = levelShadowCoord.x > 0 && levelShadowCoord.y > 0 && levelShadowCoord.x < 1 && levelShadowCoord.y < 1 && levelShadowCoord.z > 0 && levelShadowCoord.z < 1; - if (inRange) { - float bias = 0.0015; - // float bias = 0.0015 * max(1.0 - dot(normalizedTransformedNormal, light), 0.0); - shadow = computeShadow(levelShadowCoord, shadowLevel, normalizedTransformedNormal, light); - // shadow = texture(shadowmapTexture, vec4(levelShadowCoord.xy, shadowLevel, levelShadowCoord.z-bias)); - break; - } - } - } // color.rgb = ambient * diffuseColor * lightColor * intensity; ambient *= diffuseColor.rgb; @@ -87,20 +79,20 @@ void main() { vec3 viewDir = normalize(cameraDirection); // Direction to the camera vec3 reflectDir = reflect(-light, normalizedTransformedNormal); // Reflect light around the normal - // vec3 specular = pow(max(dot(viewDir, reflectDir), 0.0), shininess) * 0.5 * lightColor; - vec3 specular = vec3(0); - vec3 shadowFactor = mix(vec3(0.5), vec3(1.0), shadow); // Adjust shadow darkness as needed + vec3 specular = pow(max(dot(viewDir, reflectDir), 0.0), shininess) * 0.5 * lightColor; + + vec3 finalColor = ambient + diffuse + specular; - vec3 finalColor = shadowFactor * (ambient + diffuse + specular); -// finalColor = vec3(shadowFactor.x, 0.5, 0.5); + #ifdef ENABLE_SHADOWMAP_LEVELS + // Adjust shadow darkness as needed + finalColor *= mix(0.5, 1.0, computeShadow(normalizedTransformedNormal)); + #endif color = vec4(finalColor, 1.0); // Output final color with alpha // color.rgb = vec3(0.5) + normalRaw * 0.5; // color.rgb = diffuseColor; - // color.rgb = vec3(intensity); - // color.rgb = vec3(interpolatedTextureCoords, 0.0); // color.rgb = ((0.1 + vec3(intensity * shadow)) * diffuseColor); // color.rgb = diffuseColor * (inRange ? clamp(shadowCoord[shadowLevel],0,1) : vec3(0.1,0.1,0.1)); diff --git a/shaders/GameShader.vert b/shaders/GameShader.vert index 2327168..f783b5e 100644 --- a/shaders/GameShader.vert +++ b/shaders/GameShader.vert @@ -6,13 +6,15 @@ uniform mat4 modelMatrix; layout(location = 0) in highp vec3 position; layout(location = 1) in mediump vec2 textureCoordinates; -layout(location = 2) in highp vec3 normal; +layout(location = 5) in highp vec3 normal; out mediump vec2 interpolatedTextureCoords; out mediump vec3 transformedNormal; out highp vec3 lightDirection; out highp vec3 cameraDirection; +//out highp vec3 normalRaw; + #ifdef ENABLE_SHADOWMAP_LEVELS uniform highp mat4 shadowmapMatrix[ENABLE_SHADOWMAP_LEVELS]; out highp vec3 shadowCoord[ENABLE_SHADOWMAP_LEVELS]; @@ -54,13 +56,14 @@ void main() { cameraDirection = -transformedPosition; + #ifdef ENABLE_SHADOWMAP_LEVELS for (int i = 0; i < shadowmapMatrix.length(); i++) { - // float castReceiveOffsetBias = 0.10 + i * 0.001; - // shadowCoord[i] = (shadowmapMatrix[i] * (worldPos4 + vec4(transformedNormal * castReceiveOffsetBias,0))).xyz; shadowCoord[i] = (shadowmapMatrix[i] * worldPos4).xyz; } + #endif gl_Position = projectionMatrix*transformedPosition4; interpolatedTextureCoords = textureCoordinates; +// normalRaw = normal; } diff --git a/src/CameraController.cpp b/src/CameraController.cpp index b22495b..fcb2e61 100644 --- a/src/CameraController.cpp +++ b/src/CameraController.cpp @@ -7,7 +7,7 @@ #include namespace MagnumGame { - CameraController::CameraController(Scene3D &scene, float near, float far) + CameraController::CameraController(Scene3D &scene, Range1D zPlanes) : _cameraObject(scene.addChild(nullptr)) , _camera(_cameraObject.addFeature()) , _targetObject{} @@ -17,7 +17,7 @@ namespace MagnumGame { .translate(Vector3::zAxis(30.0f)) .rotateX(-90.0_degf); _camera.setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend) - .setProjectionMatrix(Matrix4::perspectiveProjection(30.0_degf, 1.0f, near, far)) + .setProjectionMatrix(Matrix4::perspectiveProjection(30.0_degf, 1.0f, zPlanes.min(), zPlanes.max())) .setViewport(GL::defaultFramebuffer.viewport().size()); } diff --git a/src/CameraController.h b/src/CameraController.h index e607bde..a5f937e 100644 --- a/src/CameraController.h +++ b/src/CameraController.h @@ -9,7 +9,7 @@ namespace MagnumGame { class CameraController { public: - explicit CameraController(Scene3D &camera, float near, float far); + explicit CameraController(Scene3D &camera, Range1D zPlanes); void setupTargetFromCurrent(Object3D &target); diff --git a/src/GameAssets.cpp b/src/GameAssets.cpp index 8fe067f..3c44b51 100644 --- a/src/GameAssets.cpp +++ b/src/GameAssets.cpp @@ -51,29 +51,22 @@ namespace MagnumGame { _fontsDir = *findDirectory("font"); _shadersDir = *findDirectory("shaders"); - const int maxAnimationBones = 16; - _shadowCasterShader.emplace( Utility::Path::join(_shadersDir, "ShadowCaster.vert"), Utility::Path::join(_shadersDir, "ShadowCaster.frag"), 0); _animatedShadowCasterShader.emplace( Utility::Path::join(_shadersDir, "ShadowCaster.vert"), - Utility::Path::join(_shadersDir, "ShadowCaster.frag"), maxAnimationBones); + Utility::Path::join(_shadersDir, "ShadowCaster.frag"), MaxAnimationBones); _texturedShader.emplace( Utility::Path::join(_shadersDir, "GameShader.vert"), - Utility::Path::join(_shadersDir, "GameShader.frag"), 0); + Utility::Path::join(_shadersDir, "GameShader.frag"), 0, ShadowMapLevels, ShadowPercentageCloserFiltering); _animatedTexturedShader.emplace( Utility::Path::join(_shadersDir, "GameShader.vert"), - Utility::Path::join(_shadersDir, "GameShader.frag"), maxAnimationBones); - // _animatedTexturedShader.emplace(Shaders::PhongGL::Configuration{} - // .setJointCount(16, 4) - // .setFlags(Shaders::PhongGL::Flag::DiffuseTexture | Shaders::PhongGL::Flag::ObjectId | Shaders::PhongGL::Flag::DynamicPerVertexJointCount)); + Utility::Path::join(_shadersDir, "GameShader.frag"), MaxAnimationBones, ShadowMapLevels, ShadowPercentageCloserFiltering); _animatedTexturedShader->setAmbientColor(0x111111_rgbf); - // .setSpecularColor(0x33000000_rgbaf) - // .setLightPositions({{10.0f, 15.0f, 5.0f, 0.0f}}); _vertexColorShader.emplace(); diff --git a/src/GameAssets.h b/src/GameAssets.h index 8366d3d..2fc81ad 100644 --- a/src/GameAssets.h +++ b/src/GameAssets.h @@ -16,6 +16,11 @@ namespace MagnumGame { class GameAssets { public: + static constexpr int ShadowMapLevels = 2; + static constexpr bool ShadowPercentageCloserFiltering = true; + static constexpr int MaxAnimationBones = 16; + static constexpr Vector2i ShadowMapResolution = {1024, 1024}; + explicit GameAssets(Trade::AbstractImporter& ); ~GameAssets(); @@ -56,8 +61,8 @@ namespace MagnumGame { void loadModel(Trade::AbstractImporter &gltfImporter, Trade::SceneData &sceneData, - Containers::StringView objectName, GL::Mesh *outMesh, Matrix4x4 *outTransform, - std::shared_ptr *outTexture, btConvexHullShape *outConvexHullShape); + Containers::StringView objectName, GL::Mesh *outMesh, Matrix4x4 *outTransform, + std::shared_ptr *outTexture, btConvexHullShape *outConvexHullShape); }; } diff --git a/src/GameShader.cpp b/src/GameShader.cpp index cd26fc4..0219e68 100644 --- a/src/GameShader.cpp +++ b/src/GameShader.cpp @@ -18,13 +18,18 @@ namespace MagnumGame { using namespace Magnum::GL; -GameShader::GameShader(const std::string& vertFilename, const std::string& fragFilename, int maxAnimationBones) +GameShader::GameShader(const std::string& vertFilename, const std::string& fragFilename, int maxAnimationBones, int shadowMapLevels, bool shadowPcf) { CHECK_GL_ERROR(); - addDefine("ENABLE_SHADOWMAP_LEVELS","4"); + if (shadowMapLevels > 0) { + addDefine("ENABLE_SHADOWMAP_LEVELS",std::to_string(shadowMapLevels)); + } if (maxAnimationBones > 0) { addDefine("ENABLE_MAX_ANIMATION_BONES",std::to_string(maxAnimationBones)); } + if (shadowPcf) { + addDefine("SHADOWMAP_PCF", "1"); + } CHECK_GL_ERROR(); using namespace Magnum; @@ -102,6 +107,7 @@ GameShader::GameShader(const std::string& vertFilename, const std::string& fragF debug << "\n\tbound: shadowmapTexture = " << uniformLocation("shadowmapTexture") ; debug << "\n\tbound: diffuseTexture = " << uniformLocation("diffuseTexture") ; debug << "\n\tbound: lightmapTexture = " << uniformLocation("lightmapTexture") ; + debug << "\n\tshininess = " << shininessUniform ; } void GameShader::addDefine(const std::string &name, const std::string &value) { diff --git a/src/GameShader.h b/src/GameShader.h index 2cfeacb..ba65aec 100644 --- a/src/GameShader.h +++ b/src/GameShader.h @@ -24,12 +24,13 @@ class GameShader : public GL::AbstractShaderProgram typedef Shaders::GenericGL3D::JointIds JointIds; typedef Shaders::GenericGL3D::Weights Weights; - explicit GameShader(const std::string& vertFilename, const std::string& fragFilename, int maxAnimationBones); + explicit GameShader(const std::string& vertFilename, const std::string& fragFilename, int maxAnimationBones, int shadowMapLevels, bool shadowPcf); ~GameShader() override = default; void addDefine(const std::string& name, const std::string& value); + enum: Int { DiffuseTextureLayer = 0, ShadowmapTextureLayer = 1 @@ -77,6 +78,7 @@ class GameShader : public GL::AbstractShaderProgram setUniform(lightVectorUniform, f); return *this; } + auto& setShininess(float shininess) { setUniform(shininessUniform, shininess); return *this; } GameShader& setLightColor(const Vector3& f) { setUniform(lightColorUniform, f); diff --git a/src/GameState.cpp b/src/GameState.cpp index d68d0ee..19e85f6 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -33,12 +33,12 @@ namespace MagnumGame { _debugDraw.setMode(BulletIntegration::DebugDraw::Mode::DrawWireframe); _bWorld.setDebugDrawer(&_debugDraw); - Float near = 0.1f, far = 128.0f; - _cameraController.emplace(_scene, near, far); + Range1D zPlanes{0.1f, 128.0f}; + _cameraController.emplace(_scene, zPlanes); _debugResourceManager.set(DebugRendererGroup, DebugTools::ObjectRendererOptions{}.setSize(1.f)); - _shadowLight.emplace(_scene, 4, near, far); + _shadowLight.emplace(_scene, zPlanes, GameAssets::ShadowMapLevels, GameAssets::ShadowMapResolution); } @@ -234,10 +234,9 @@ namespace MagnumGame { &_animatorDrawables, &_opaqueDrawables); for (auto& meshDrawable : animator->meshDrawables()) { - auto& skinMeshObject3D = dynamic_cast(meshDrawable.get().object()); - skinMeshObject3D.addFeature(_assets.getAnimatedShadowCasterShader(), _shadowCasterDrawables) - .setMesh(&meshDrawable.get().getMesh()) - .setSkinMeshDrawable(meshDrawable.get().getSkinMeshDrawable()); + meshDrawable->getObject3D().addFeature(_assets.getAnimatedShadowCasterShader(), _shadowCasterDrawables) + .setMesh(&meshDrawable.get().getMesh()) + .setSkinMeshDrawable(meshDrawable.get().getSkinMeshDrawable()); } animationOffset.setTransformation(Matrix4::translation({0, -0.4f, 0})); diff --git a/src/ShadowLight.cpp b/src/ShadowLight.cpp index eee298e..5c955d0 100644 --- a/src/ShadowLight.cpp +++ b/src/ShadowLight.cpp @@ -23,12 +23,12 @@ namespace MagnumGame { using namespace Magnum::GL; -ShadowLight::ShadowLight(Object3D& parent, int numShadowLevels, Float zNear, Float zFar) +ShadowLight::ShadowLight(Object3D& parent, Range1D zPlanes, int numShadowLevels, Vector2i shadowMapSize) : Object3D(&parent) , _numLayers(numShadowLevels) , _camera(addFeature()) { - Range2Di viewport = {{0, 0}, {1024, 1024}}; + Range2Di viewport = {{0, 0}, shadowMapSize}; _shadowTexture.emplace(); _shadowTexture->setLabel("Shadow texture"); // shadowTexture.setStorage(1, Magnum::TextureFormat::DepthComponent, shadowFramebuffer.viewport().size()); @@ -52,6 +52,8 @@ ShadowLight::ShadowLight(Object3D& parent, int numShadowLevels, Float zNear, Flo Debug() << "Framebuffer status: read=" << shadowFramebuffer.checkStatus(FramebufferTarget::Read) << " draw=" << shadowFramebuffer.checkStatus(FramebufferTarget::Draw); } + auto zNear = zPlanes.min(); + auto zFar = zPlanes.max(); _cutPlanes = {}; arrayReserve(_cutPlanes, _numLayers); //props http://stackoverflow.com/a/33465663 diff --git a/src/ShadowLight.h b/src/ShadowLight.h index 9714416..55d4372 100644 --- a/src/ShadowLight.h +++ b/src/ShadowLight.h @@ -13,7 +13,7 @@ namespace MagnumGame { class ShadowLight : public Object3D { public: - ShadowLight(Object3D& parent, int numShadowLevels, Float near, Float far); + ShadowLight(Object3D& parent, Range1D zPlanes, int numShadowLevels, Vector2i shadowMapSize); ~ShadowLight() override; void setTarget(Vector3 lightDirection, Vector3 screenDirection, const Matrix4& inverseModelViewProjection); diff --git a/src/TexturedDrawable.cpp b/src/TexturedDrawable.cpp index fcefef1..ecf15d5 100644 --- a/src/TexturedDrawable.cpp +++ b/src/TexturedDrawable.cpp @@ -17,13 +17,14 @@ namespace MagnumGame { - TexturedDrawable::TexturedDrawable(SceneGraph::AbstractObject3D &object, + TexturedDrawable::TexturedDrawable(Object3D &object, const Trade::ImageData2D &image, Shaders::PhongGL &shader, GL::Mesh &mesh, SceneGraph::DrawableGroup3D &drawables, UnsignedInt objectId) : SceneGraph::Drawable3D(object, &drawables), + _object(object), _color{0xffffffff_rgbaf}, _ownTexture{makeTexture(image)}, _texture(&*_ownTexture), @@ -33,13 +34,14 @@ namespace MagnumGame { _objectId{objectId} { } - TexturedDrawable::TexturedDrawable(SceneGraph::AbstractObject3D &object, + TexturedDrawable::TexturedDrawable(Object3D &object, GL::Texture2D *texture, Shaders::PhongGL &shader, GL::Mesh &mesh, SceneGraph::DrawableGroup3D &drawables, UnsignedInt objectId) : SceneGraph::Drawable3D{object, &drawables}, + _object(object), _color{0xffffffff_rgbaf}, _ownTexture{Containers::NullOpt}, _texture(texture), @@ -52,13 +54,14 @@ namespace MagnumGame { } } - TexturedDrawable::TexturedDrawable(SceneGraph::AbstractObject3D &object, + TexturedDrawable::TexturedDrawable(Object3D &object, GL::Texture2D *texture, GameShader &shader, GL::Mesh &mesh, SceneGraph::DrawableGroup3D &drawables, UnsignedInt objectId) : SceneGraph::Drawable3D{object, &drawables}, + _object(object), _color{0xffffffff_rgbaf}, _ownTexture{Containers::NullOpt}, _texture(texture), @@ -126,6 +129,7 @@ namespace MagnumGame { _shader.setSpecularColor(_color.rgb()); _shader.setModelMatrix(object().absoluteTransformationMatrix()); _shader.setLightVector(lightDirection); + _shader.setShininess(shininess); _shader.setLightColor({lightColor, lightColor, lightColor}); _shader.setAmbientColor({ambientColor, ambientColor, ambientColor}); if (_texture) { diff --git a/src/TexturedDrawable.h b/src/TexturedDrawable.h index 6739b2f..42d102d 100644 --- a/src/TexturedDrawable.h +++ b/src/TexturedDrawable.h @@ -26,19 +26,19 @@ namespace MagnumGame { class TexturedDrawable : public SceneGraph::Drawable3D, public IEnableDrawable { public: - explicit TexturedDrawable(SceneGraph::AbstractObject3D &object, + explicit TexturedDrawable(Object3D &object, const Trade::ImageData2D &image, Shaders::PhongGL &shader, GL::Mesh& mesh, SceneGraph::DrawableGroup3D &drawables, UnsignedInt objectId = 0); - explicit TexturedDrawable(SceneGraph::AbstractObject3D &object, + explicit TexturedDrawable(Object3D &object, GL::Texture2D* texture, Shaders::PhongGL &shader, GL::Mesh& mesh, SceneGraph::DrawableGroup3D &drawables, UnsignedInt objectId = 0); - explicit TexturedDrawable(SceneGraph::AbstractObject3D &object, + explicit TexturedDrawable(Object3D &object, GL::Texture2D* texture, GameShader &shader, GL::Mesh& mesh, @@ -51,6 +51,8 @@ namespace MagnumGame { btVector3 getPosition() const override; + Object3D& getObject3D() const { return _object; } + void setSkin(Skin& skin, UnsignedInt perVertexJointCount, UnsignedInt secondaryPerVertexJointCount); GL::Mesh& getMesh() const { return _mesh;} @@ -59,14 +61,15 @@ namespace MagnumGame { static inline float ambientColor = 0.5f; static inline float lightColor = 0.5f; - static inline float shininess = 20.0f; - static inline float specular = 0.3f; - static inline Vector3 lightDirection = {0.4f, 0.5f, 0.3f}; + static inline float shininess = 10.0f; + static inline float specular = 1.0f; + static inline Vector3 lightDirection = {0.2f, 0.7f, 0.3f}; private: void draw(const Matrix4 &transformation, SceneGraph::Camera3D &) override; static GL::Texture2D makeTexture(const Trade::ImageData2D &); + Object3D& _object; Color4 _color; Containers::Optional _ownTexture; GL::Texture2D* _texture{};