Browse Source

Added shadow intensity and shadow fade distance parameters for Light.
Fixed light XML load not loading all shadow parameters.

Lasse Öörni 15 years ago
parent
commit
ea9cc96e52

+ 4 - 0
Engine/Engine/RegisterRenderer.cpp

@@ -565,6 +565,8 @@ static void registerLight(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Light", "void setShadowBias(const BiasParameters& in)", asMETHOD(Light, setShadowBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void setShadowCascade(const CascadeParameters& in)", asMETHOD(Light, setShadowCascade), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void setShadowFocus(const FocusParameters& in)", asMETHOD(Light, setShadowFocus), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "void setShadowFadeDistance(float)", asMETHOD(Light, setShadowFadeDistance), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "void setShadowIntensity(float)", asMETHOD(Light, setShadowIntensity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void setShadowResolution(float)", asMETHOD(Light, setShadowResolution), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void setShadowNearFarRatio(float)", asMETHOD(Light, setShadowNearFarRatio), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void setRampTexture(Texture@+)", asMETHOD(Light, setRampTexture), asCALL_THISCALL);
@@ -583,6 +585,8 @@ static void registerLight(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Light", "const BiasParameters& getShadowBias() const", asMETHOD(Light, getShadowBias), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "const CascadeParameters& getShadowCascade() const", asMETHOD(Light, getShadowCascade), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "const FocusParameters& getShadowFocus() const", asMETHOD(Light, getShadowFocus), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "float getShadowFadeDistance() const", asMETHOD(Light, getShadowFadeDistance), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "float getShadowIntensity() const", asMETHOD(Light, getShadowIntensity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "float getShadowResolution() const", asMETHOD(Light, getShadowResolution), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "float getShadowNearFarRatio() const", asMETHOD(Light, getShadowNearFarRatio), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Texture@+ getRampTexture() const", asMETHOD(Light, getRampTexture), asCALL_THISCALL);

+ 11 - 0
Engine/Renderer/Batch.cpp

@@ -335,6 +335,17 @@ void Batch::draw(Renderer* renderer) const
                 Vector4(0.5f * invWidth, -0.5f * invWidth, 0.0f, 0.0f));
         }
         
+        if (ps->needParameterUpdate(PSP_SHADOWINTENSITY, light))
+        {
+            float intensity = light->getShadowIntensity();
+            float fadeStart = light->getShadowFadeDistance();
+            float fadeEnd = light->getShadowDistance();
+            if ((fadeStart > 0.0f) && (fadeEnd > 0.0f) && (fadeEnd > fadeStart))
+                intensity = lerp(intensity, 1.0f, clamp((light->getDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
+            float pcfValues = (1.0f - intensity) * 0.25f;
+            renderer->setPixelShaderConstant(getPSRegister(PSP_SHADOWINTENSITY), Vector4(pcfValues, intensity, 0.0f, 0.0f));
+        }
+        
         if (ps->needParameterUpdate(PSP_SHADOWPROJ, light))
         {
             Camera& shadowCamera = light->getShadowCamera();

+ 44 - 8
Engine/Renderer/Light.cpp

@@ -86,6 +86,8 @@ Light::Light(Octant* octant, const std::string& name) :
     mShadowBias(BiasParameters(DEFAULT_CONSTANTBIAS, DEFAULT_SLOPESCALEDBIAS)),
     mShadowCascade(CascadeParameters(1, DEFAULT_LAMBDA, DEFAULT_SHADOWFADERANGE, M_LARGE_VALUE)),
     mShadowFocus(FocusParameters(true, true, true, DEFAULT_SHADOWQUANTIZE, DEFAULT_SHADOWMINVIEW)),
+    mShadowFadeDistance(0.0f),
+    mShadowIntensity(0.0f),
     mShadowResolution(1.0f),
     mShadowNearFarRatio(DEFAULT_SHADOWNEARFARRATIO),
     mNearSplit(0.0f),
@@ -128,6 +130,8 @@ void Light::save(Serializer& dest)
     dest.writeBool(mShadowFocus.mZoomOut);
     dest.writeFloat(mShadowFocus.mQuantize);
     dest.writeFloat(mShadowFocus.mMinView);
+    dest.writeFloat(mShadowFadeDistance);
+    dest.writeFloat(mShadowIntensity);
     dest.writeFloat(mShadowResolution);
     dest.writeFloat(mShadowNearFarRatio);
     
@@ -166,6 +170,8 @@ void Light::load(Deserializer& source, ResourceCache* cache)
     mShadowFocus.mZoomOut = source.readBool();
     mShadowFocus.mQuantize = source.readFloat();
     mShadowFocus.mMinView = source.readFloat();
+    mShadowFadeDistance = source.readFloat();
+    mShadowIntensity = source.readFloat();
     mShadowResolution = source.readFloat();
     mShadowNearFarRatio = source.readFloat();
     
@@ -212,6 +218,8 @@ void Light::saveXML(XMLElement& dest)
     lodElem.setInt("shadowdetail", mShadowDetailLevel);
     
     XMLElement shadowElem = dest.createChildElement("shadows");
+    shadowElem.setFloat("fadedistance", mShadowFadeDistance);
+    shadowElem.setFloat("intensity", mShadowIntensity);
     shadowElem.setFloat("resolution", mShadowResolution);
     shadowElem.setFloat("nearfarratio", mShadowNearFarRatio);
     
@@ -259,6 +267,12 @@ void Light::loadXML(const XMLElement& source, ResourceCache* cache)
     mDetailLevel = lodElem.getInt("detail");
     mShadowDetailLevel = lodElem.getInt("shadowdetail");
     
+    XMLElement shadowElem = source.getChildElement("shadows");
+    mShadowFadeDistance = shadowElem.getFloat("fadedistance");
+    mShadowIntensity = shadowElem.getFloat("intensity");
+    mShadowResolution = shadowElem.getFloat("resolution");
+    mShadowNearFarRatio = shadowElem.getFloat("nearfarratio");
+    
     XMLElement biasElem = source.getChildElement("shadowbias");
     mShadowBias.mConstantBias = biasElem.getFloat("constant");
     mShadowBias.mSlopeScaledBias = biasElem.getFloat("slopescaled");
@@ -326,8 +340,10 @@ bool Light::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deseriali
     checkBool(mShadowFocus.mZoomOut, true, baseRevision, bits2, 4);
     checkFloat(mShadowFocus.mQuantize, DEFAULT_SHADOWQUANTIZE, baseRevision, bits2, 4);
     checkFloat(mShadowFocus.mMinView, DEFAULT_SHADOWMINVIEW, baseRevision, bits2, 4);
-    checkUByte((unsigned char)(mShadowResolution * 100), 100, baseRevision, bits2, 8);
-    checkFloat(mShadowNearFarRatio, DEFAULT_SHADOWNEARFARRATIO, baseRevision, bits2, 16);
+    checkFloat(mShadowFadeDistance, 0.0f, baseRevision, bits2, 8);
+    checkUByte((unsigned char)(mShadowIntensity * 255), 0, baseRevision, bits2, 16);
+    checkUByte((unsigned char)(mShadowResolution * 100), 100, baseRevision, bits2, 32);
+    checkFloat(mShadowNearFarRatio, DEFAULT_SHADOWNEARFARRATIO, baseRevision, bits2, 64);
     
     // Send only information necessary for the light type, and shadow data only for shadowed lights
     if (mLightType == LIGHT_POINT)
@@ -367,8 +383,10 @@ bool Light::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deseriali
     writeBoolDelta(mShadowFocus.mZoomOut, dest, destRevision, bits2 & 4);
     writeFloatDelta(mShadowFocus.mQuantize, dest, destRevision, bits2 & 4);
     writeFloatDelta(mShadowFocus.mMinView, dest, destRevision, bits2 & 4);
-    writeUByteDelta((unsigned char)(mShadowResolution * 100), dest, destRevision, bits2 & 8);
-    writeFloatDelta(mShadowNearFarRatio, dest, destRevision, bits2 & 16);
+    writeFloatDelta(mShadowFadeDistance, dest, destRevision, bits2 & 8);
+    writeUByteDelta((unsigned char)(mShadowIntensity * 255), dest, destRevision, bits2 & 16);
+    writeUByteDelta((unsigned char)(mShadowResolution * 100), dest, destRevision, bits2 & 32);
+    writeFloatDelta(mShadowNearFarRatio, dest, destRevision, bits2 & 64);
     
     return prevBits || (bits != 0) || (bits2 != 0);
 }
@@ -427,12 +445,18 @@ void Light::readNetUpdate(Deserializer& source, ResourceCache* cache, const NetU
     readBoolDelta(mShadowFocus.mZoomOut, source, bits2 & 4);
     readFloatDelta(mShadowFocus.mQuantize, source, bits2 & 4);
     readFloatDelta(mShadowFocus.mMinView, source, bits2 & 4);
-    if (bits2 & 8)
+    readFloatDelta(mShadowFadeDistance, source, bits2 & 8);
+    if (bits2 & 16)
+    {
+        int shadowIntensity = source.readUByte();
+        mShadowIntensity = shadowIntensity / 255.0f;
+    }
+    if (bits2 & 32)
     {
         int shadowResolution = source.readUByte();
         mShadowResolution = shadowResolution / 100.0f;
     }
-    readFloatDelta(mShadowNearFarRatio, source, bits2 & 16);
+    readFloatDelta(mShadowNearFarRatio, source, bits2 & 64);
     
     if (bits)
         markDirty();
@@ -562,9 +586,9 @@ void Light::setShadowNearFarRatio(float nearFarRatio)
     mShadowNearFarRatio = clamp(nearFarRatio, 0.0f, 0.5f);
 }
 
-void Light::setSpecularIntensity(float specularFactor)
+void Light::setSpecularIntensity(float intensity)
 {
-    mSpecularIntensity = specularFactor;
+    mSpecularIntensity = max(intensity, 0.0f);
 }
 
 void Light::setFadeDistance(float distance)
@@ -596,6 +620,16 @@ void Light::setShadowFocus(const FocusParameters& parameters)
     mShadowFocus.validate();
 }
 
+void Light::setShadowFadeDistance(float distance)
+{
+    mShadowFadeDistance = max(distance, 0.0f);
+}
+
+void Light::setShadowIntensity(float intensity)
+{
+    mShadowIntensity = clamp(intensity, 0.0f, 1.0f);
+}
+
 void Light::setShadowResolution(float resolution)
 {
     mShadowResolution = clamp(resolution, 0.25f, 1.0f);
@@ -633,6 +667,8 @@ void Light::copyFrom(Light* original)
     mShadowBias = original->mShadowBias;
     mShadowCascade = original->mShadowCascade;
     mShadowFocus = original->mShadowFocus;
+    mShadowFadeDistance = original->mShadowFadeDistance;
+    mShadowIntensity = original->mShadowIntensity;
     mShadowResolution = original->mShadowResolution;
     mRampTexture = original->mRampTexture;
     mSpotTexture = original->mSpotTexture;

+ 17 - 5
Engine/Renderer/Light.h

@@ -173,7 +173,7 @@ public:
     //! Set color
     void setColor(const Color& color);
     //! Set specular intensity
-    void setSpecularIntensity(float specularFactor);
+    void setSpecularIntensity(float intensity);
     //! Set range
     void setRange(float range);
     //! Set spotlight field of view
@@ -190,6 +190,10 @@ public:
     void setShadowCascade(const CascadeParameters& parameters);
     //! Set shadow map focusing parameters
     void setShadowFocus(const FocusParameters& parameters);
+    //! Set shadow fade out start distance. Only has effect if shadow distance is also non-zero
+    void setShadowFadeDistance(float distance);
+    //! Set shadow intensity between 0.0 - 1.0. 0.0 (the default) gives fully dark shadows.
+    void setShadowIntensity(float intensity);
     //! Set shadow resolution between 0.25 - 1.0. Determines the shadow map to use
     void setShadowResolution(float resolution);
     //! Set shadow camera near/far clip distance ratio
@@ -227,6 +231,10 @@ public:
     const CascadeParameters& getShadowCascade() const { return mShadowCascade; }
     //! Return shadow map focus parameters
     const FocusParameters& getShadowFocus() const { return mShadowFocus; }
+    //! Return shadow fade start distance
+    float getShadowFadeDistance() const { return mShadowFadeDistance; }
+    //! Return shadow intensity
+    float getShadowIntensity() const { return mShadowIntensity; }
     //! Return shadow resolution
     float getShadowResolution() const { return mShadowResolution; }
     //! Return shadow camera near/far clip distance ratio
@@ -237,10 +245,6 @@ public:
     Texture* getSpotTexture() const { return mSpotTexture; }
     //! Return spotlight frustum
     const Frustum& getFrustum();
-    //! Return volume safety extent of spot or point light
-    float getVolumeExtent() const;
-    //! Return directional light near or far quad transform
-    Matrix4x3 getDirLightTransform(Camera& camera, bool getNearQuad) const;
     
     //! Set near split distance for directional light
     void setNearSplit(float near);
@@ -266,6 +270,10 @@ public:
     Camera& getShadowCamera() { return mShadowCamera; }
     //! Return shadow map
     Texture2D* getShadowMap() const { return mShadowMap; }
+    //! Return volume safety extent of spot or point light
+    float getVolumeExtent() const;
+    //! Return directional light near or far quad transform
+    Matrix4x3 getDirLightTransform(Camera& camera, bool getNearQuad) const;
     
 protected:
     //! Transform has changed. Mark spotlight frustum dirty
@@ -300,6 +308,10 @@ private:
     CascadeParameters mShadowCascade;
     //! Shadow map focus parameters
     FocusParameters mShadowFocus;
+    //! Shadow fade start distance
+    float mShadowFadeDistance;
+    //! Shadow intensity
+    float mShadowIntensity;
     //! Shadow resolution
     float mShadowResolution;
     //! Shadow camera near/far clip distance ratio

+ 1 - 0
Engine/Renderer/PixelShader.cpp

@@ -239,6 +239,7 @@ void PixelShader::initializeParameters()
     sParameters["MatEmissiveColor"] = PSP_MATEMISSIVECOLOR;
     sParameters["MatSpecProperties"] = PSP_MATSPECPROPERTIES;
     sParameters["SampleOffsets"] = PSP_SAMPLEOFFSETS;
+    sParameters["ShadowIntensity"] = PSP_SHADOWINTENSITY;
     sParameters["ShadowProjPS"] = PSP_SHADOWPROJ;
     sParameters["SpotProjPS"] = PSP_SPOTPROJ;
     

+ 1 - 0
Engine/Renderer/ShaderDefs.h

@@ -65,6 +65,7 @@ enum PSParameter
     PSP_MATEMISSIVECOLOR,
     PSP_MATSPECPROPERTIES,
     PSP_SAMPLEOFFSETS,
+    PSP_SHADOWINTENSITY,
     PSP_SHADOWPROJ,
     PSP_SPOTPROJ,
     MAX_PS_PARAMETERS

+ 8 - 7
SourceAssets/Shaders/Common.hlsl

@@ -36,8 +36,9 @@ uniform float4 cMatDiffColor : register(C11);
 uniform float3 cMatEmissiveColor : register(C12);
 uniform float2 cMatSpecProperties : register(C13);
 uniform float4 cSampleOffsets : register(C14);
-uniform float4x4 cShadowProjPS : register(C15);
-uniform float4x4 cSpotProjPS : register(C19);
+uniform float2 cShadowIntensity : register(C15);
+uniform float4x4 cShadowProjPS : register(C16);
+uniform float4x4 cSpotProjPS : register(C20);
 
 // Material map samplers
 sampler2D sDiffMap : register(S0);
@@ -310,7 +311,7 @@ float evaluateSpecular(float3 normal, float3 worldPos, float3 lightDir, float sp
 float evaluateShadow(float4 shadowPos)
 {
     // Take four samples and average them
-    float4 pcfValues = 0.25;
+    float4 pcfValues = cShadowIntensity.x;
     #ifdef SM3
         float2 ofs = cSampleOffsets.xy;
         float4 projShadowPos = float4(shadowPos.xyz / shadowPos.w, 0.0);
@@ -321,9 +322,9 @@ float evaluateShadow(float4 shadowPos)
             tex2Dlod(sShadowMap, float4(projShadowPos.xy + float2(ofs.y, ofs.y), projShadowPos.zw)).r
         );
         #ifdef HWSHADOW
-            return dot(inLight, pcfValues);
+            return cShadowIntensity.y + dot(inLight, pcfValues);
         #else
-            return dot(inLight > projShadowPos.z, pcfValues);
+            return cShadowIntensity.y + dot(inLight > projShadowPos.z, pcfValues);
         #endif
     #else
         float2 projOfs = cSampleOffsets.xy * shadowPos.w;
@@ -334,9 +335,9 @@ float evaluateShadow(float4 shadowPos)
             tex2Dproj(sShadowMap, float4(shadowPos.xy + float2(projOfs.y, projOfs.y), shadowPos.zw)).r
         );
         #ifdef HWSHADOW
-            return dot(inLight, pcfValues);
+            return cShadowIntensity.y + dot(inLight, pcfValues);
         #else
-            return dot((inLight * shadowPos.w) > shadowPos.z, pcfValues);
+            return cShadowIntensity.y + dot((inLight * shadowPos.w) > shadowPos.z, pcfValues);
         #endif
     #endif
 }