Pārlūkot izejas kodu

Area light sources (WIP)
Fixed light intensity units

BearishSun 8 gadi atpakaļ
vecāks
revīzija
49a338f456

+ 15 - 9
Source/BansheeCore/Include/BsCLight.h

@@ -20,7 +20,7 @@ namespace bs
     class BS_CORE_EXPORT CLight : public Component
     {
     public:
-		CLight(const HSceneObject& parent, LightType type = LightType::Point, Color color = Color::White, 
+		CLight(const HSceneObject& parent, LightType type = LightType::Radial, Color color = Color::White, 
 			float intensity = 100.0f, float range = 1.0f, bool castsShadows = false, Degree spotAngle = Degree(45), 
 			Degree spotFalloffAngle = Degree(40));
 
@@ -44,11 +44,17 @@ namespace bs
 	    /** @copydoc Light::setColor */
 		void setColor(const Color& color) { mInternal->setColor(color); }
 
-	    /** @copydoc Light::getRange */
-		float getRange() const { return mInternal->getRange(); }
+	    /** @copydoc Light::getAttenuationRadius */
+		float getAttenuationRadius() const { return mInternal->getAttenuationRadius(); }
 
-	    /** @copydoc Light::setRange */
-		void setRange(float range) { mInternal->setRange(range);; }
+	    /** @copydoc Light::setAttenuationRadius */
+		void setAttenuationRadius(float radius) { mInternal->setAttenuationRadius(radius); }
+
+		/** @copydoc Light::getSourceRadius */
+		float getSourceRadius() const { return mInternal->getSourceRadius(); }
+
+		/** @copydoc Light::setSourceRadius */
+		void setSourceRadius(float radius) { mInternal->setSourceRadius(radius); }
 
 	    /** @copydoc Light::getIntensity */
 		float getIntensity() const { return mInternal->getIntensity(); }
@@ -68,11 +74,11 @@ namespace bs
 		/** @copydoc Light::setSpotFalloffAngle */
 		void setSpotFalloffAngle(const Degree& spotAngle) { mInternal->setSpotFalloffAngle(spotAngle); }
 
-		/** @copydoc Light::getPhysicallyBasedAttenuation  */
-		bool getPhysicallyBasedAttenuation() const { return mInternal->getPhysicallyBasedAttenuation(); }
+		/** @copydoc Light::getUseAutoAttenuation  */
+		bool getUseAutoAttenuation() const { return mInternal->getUseAutoAttenuation(); }
 
-		/**  @copydoc Light::setPhysicallyBasedAttenuation  */
-		void setPhysicallyBasedAttenuation(bool enabled) { mInternal->setPhysicallyBasedAttenuation(enabled); }
+		/**  @copydoc Light::setUseAutoAttenuation  */
+		void setUseAutoAttenuation(bool enabled) { mInternal->setUseAutoAttenuation(enabled); }
 
 	    /** @copydoc Light::getBounds  */
 		Sphere getBounds() const;

+ 49 - 39
Source/BansheeCore/Include/BsLight.h

@@ -20,7 +20,7 @@ namespace bs
 	enum class LightType
 	{
 		Directional, 
-		Point, 
+		Radial, 
 		Spot
 	};
 
@@ -42,7 +42,7 @@ namespace bs
 	{
 	public:
 		LightBase();
-		LightBase(LightType type, Color color, float intensity, float range, 
+		LightBase(LightType type, Color color, float intensity, float attRadius, float srcRadius,
 			bool castsShadows, Degree spotAngle, Degree spotFalloffAngle);
 
 		virtual ~LightBase() { }
@@ -79,40 +79,48 @@ namespace bs
 		/**	Sets the color emitted from the light. */
 		void setColor(const Color& color) { mColor = color; _markCoreDirty(); }
 
-		/**	Returns the maximum range of the light. Light will not affect any geometry past that point. */
-		float getRange() const { return mRange; }
+		/**	@see setAttenuationRadius */
+		float getAttenuationRadius() const { return mAttRadius; }
 
 		/**
-		 * Sets the maximum range of the light. Light will not affect any geometry past that point. Value is ignored if
-		 * physically based attenuation is active.
-		 *
-		 * @note	Normally you want to set this at a point where light intensity is too low due to attenuation.
+		 * Range at which the light contribution fades out to zero. Use setUseAutoAttenuation to provide a radius
+		 * automatically dependant on light intensity. The radius will cut-off light contribution and therefore manually set
+		 * very small radius can end up being very physically incorrect.
 		 */
-		void setRange(float range);
+		void setAttenuationRadius(float radius);
 
-		/** 
-		 * Checks is physically based attenuation active. If true the range and attenuation of the light are controlled
-		 * by inverse square of distance. If false then the user is allowed to set the range and attenuation is adjusted
-		 * accordingly. 
+		/**	@see setSourceRadius */
+		float getSourceRadius() const { return mSourceRadius; }
+
+		/**
+		 * Radius of the light source. If non-zero then this light represents an area light, otherwise it is a punctual
+		 * light. Area lights have different attenuation then punctual lights, and their appearance in specular reflections
+		 * is realistic. Shape of the area light depends on light type:
+		 *  - For directional light the shape is a disc projected on the hemisphere on the horizon. This parameter
+		 *    represents angular radius (in degrees) of the disk and should be very small (think of how much space the Sun
+		 *    takes on the sky - roughly 0.5 degrees).
+		 *  - For radial light the shape is a sphere and the radius is the radius of the sphere.
+		 *  - For spot lights the shape is a disc oriented in the direction of the spot light and the radius is the radius
+		 *    of the disc.
 		 */
-		bool getPhysicallyBasedAttenuation() const { return mPhysCorrectAtten; }
+		void setSourceRadius(float radius);
+
+		/** @see setUseAutoAttenuation */
+		bool getUseAutoAttenuation() const { return mAutoAttenuation; }
 
 		/** 
-		 * Activates or deactivates physically based attenuation. If true the range and attenuation of the light are 
-		 * controlled by inverse square of distance. If false then the user is allowed to set the range and attenuation is 
-		 * adjusted accordingly. 
+		 * If enabled the attenuation radius will automatically be controlled in order to provide reasonable light radius, 
+		 * depending on its intensity.
 		 */
-		void setPhysicallyBasedAttenuation(bool enabled);
+		void setUseAutoAttenuation(bool enabled);
 
-		/**
-		 * Gets the power of the light source. This is luminous flux for point & spot lights, and luminance for directional 
-		 * lights.
-		 */
+		/** @see setIntensity */
 		float getIntensity() const { return mIntensity; }
 
 		/**
-		 * Sets the power of the light source. This will be luminous flux for point & spot lights, and radiance for 
-		 * directional lights.
+		 * Determines the power of the light source. This will be luminous flux for radial & spot lights, 
+		 * luminance for directional lights with no area, and illuminance for directional lights with area (non-zero source
+		 * radius).
 		 */
 		void setIntensity(float intensity);
 
@@ -141,9 +149,9 @@ namespace bs
 		/**
 		 * Returns the luminance of the light source. This is the value that should be used in lighting equations.
 		 *
-		 * @note	
-		 * Ignores the light direction, therefore caller must ensure to properly handle non-uniform emitters like spot 
-		 * lights.
+		 * @note
+		 * For point light sources this method returns luminous intensity and not luminance. We use the same method for both
+		 * as a convenience since in either case its used as a measure of intensity in lighting equations.
 		 */
 		float getLuminance() const;
 
@@ -164,7 +172,7 @@ namespace bs
 		void updateBounds();
 
 		/** Calculates maximum light range based on light intensity. */
-		void updatePhysicallyCorrectRange();
+		void updateAttenuationRange();
 
 		Vector3 mPosition; /**< World space position. */
 		Quaternion mRotation; /**< World space rotation. */
@@ -172,13 +180,14 @@ namespace bs
 		LightType mType; /**< Type of light that determines how are the rest of the parameters interpreted. */
 		bool mCastsShadows; /**< Determines whether the light casts shadows. */
 		Color mColor; /**< Color of the light. */
-		float mRange; /**< Cut off range for the light when rendering. */
-		float mIntensity; /**< Power of the light source. This will be luminous flux for point & spot lights, and radiance for directional lights. */
+		float mAttRadius; /**< Radius at which light intensity falls off to zero. */
+		float mSourceRadius; /**< Radius of the light source. If > 0 the light is an area light. */
+		float mIntensity; /**< Power of the light source. @see setIntensity. */
 		Degree mSpotAngle; /**< Total angle covered by a spot light. */
 		Degree mSpotFalloffAngle; /**< Spot light angle at which falloff starts. Must be smaller than total angle. */
 		bool mIsActive; /**< Whether the light should be rendered or not. */
 		Sphere mBounds; /**< Sphere that bounds the light area of influence. */
-		bool mPhysCorrectAtten; /**< Determines is physically based attentuation active. */
+		bool mAutoAttenuation; /**< Determines is attenuation radius is automatically determined. */
 	};
 
 	/** @} */
@@ -214,19 +223,20 @@ namespace bs
 		 *
 		 * @param[in]	type				Type of light that determines how are the rest of the parameters interpreted.
 		 * @param[in]	color				Color of the light.
-		 * @param[in]	intensity			Power of the light source. This will be luminous flux for point & spot lights, 
-		 *									and radiance for directional lights.
-		 * @param[in]	range				Cut off range for the light when rendering.
+		 * @param[in]	intensity			Power of the light source. This will be luminous flux for radial & spot lights, 
+		 *									luminance for directional lights with no area, and illuminance for directional 
+		 *									lights with area (non-zero source radius).
+		 * @param[in]	attRadius			Radius at which light's influence fades out to zero.
 		 * @param[in]	castsShadows		Determines whether the light casts shadows.
 		 * @param[in]	spotAngle			Total angle covered by a spot light.
 		 * @param[in]	spotFalloffAngle	Spot light angle at which falloff starts. Must be smaller than total angle.
 		 */
-		static SPtr<Light> create(LightType type = LightType::Point, Color color = Color::White,
-			float intensity = 100.0f, float range = 10.0f, bool castsShadows = false,
+		static SPtr<Light> create(LightType type = LightType::Radial, Color color = Color::White,
+			float intensity = 100.0f, float attRadius = 10.0f, bool castsShadows = false,
 			Degree spotAngle = Degree(45), Degree spotFalloffAngle = Degree(40));
 
 	protected:
-		Light(LightType type, Color color, float intensity, float range, 
+		Light(LightType type, Color color, float intensity, float attRadius, float srcRadius, 
 			bool castsShadows, Degree spotAngle, Degree spotFalloffAngle);
 
 		/** @copydoc CoreObject::createCore */
@@ -274,8 +284,8 @@ namespace bs
 	protected:
 		friend class bs::Light;
 
-		Light(LightType type, Color color, float intensity, 
-			float range, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle);
+		Light(LightType type, Color color, float intensity, float attRadius, float srcRadius, bool castsShadows, 
+			  Degree spotAngle, Degree spotFalloffAngle);
 
 		/** @copydoc CoreObject::initialize */
 		void initialize() override;

+ 3 - 2
Source/BansheeCore/Include/BsLightRTTI.h

@@ -22,11 +22,12 @@ namespace bs
 			BS_RTTI_MEMBER_PLAIN(mType, 2)
 			BS_RTTI_MEMBER_PLAIN(mCastsShadows, 3)
 			BS_RTTI_MEMBER_PLAIN(mColor, 4)
-			BS_RTTI_MEMBER_PLAIN(mRange, 5)
+			BS_RTTI_MEMBER_PLAIN(mAttRadius, 5)
 			BS_RTTI_MEMBER_PLAIN(mIntensity, 6)
 			BS_RTTI_MEMBER_PLAIN(mSpotAngle, 7)
 			BS_RTTI_MEMBER_PLAIN(mSpotFalloffAngle, 8)
-			BS_RTTI_MEMBER_PLAIN(mPhysCorrectAtten, 9)
+			BS_RTTI_MEMBER_PLAIN(mAutoAttenuation, 9)
+			BS_RTTI_MEMBER_PLAIN(mSourceRadius, 10)
 		BS_END_RTTI_MEMBERS
 	public:
 		LightRTTI()

+ 75 - 43
Source/BansheeCore/Source/BsLight.cpp

@@ -10,76 +10,105 @@
 namespace bs
 {
 	LightBase::LightBase()
-		: mPosition(BsZero), mRotation(BsIdentity), mType(LightType::Point), mCastsShadows(false), mColor(Color::White)
-		, mRange(10.0f), mIntensity(5.0f), mSpotAngle(45), mSpotFalloffAngle(35.0f), mIsActive(true), mPhysCorrectAtten(true)
+		: mPosition(BsZero), mRotation(BsIdentity), mType(LightType::Radial), mCastsShadows(false), mColor(Color::White)
+		, mAttRadius(10.0f), mSourceRadius(0.0f), mIntensity(5.0f), mSpotAngle(45), mSpotFalloffAngle(35.0f)
+		, mIsActive(true), mAutoAttenuation(true)
 	{
-		updatePhysicallyCorrectRange();
+		updateAttenuationRange();
 	}
 
-	LightBase::LightBase(LightType type, Color color,
-		float intensity, float range, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
-		: mPosition(BsZero), mRotation(BsIdentity), mType(type), mCastsShadows(castsShadows), mColor(color), mRange(range)
-		, mIntensity(intensity), mSpotAngle(spotAngle), mSpotFalloffAngle(spotFalloffAngle), mIsActive(true)
-		, mPhysCorrectAtten(true)
+	LightBase::LightBase(LightType type, Color color, float intensity, float attRadius, float srcRadius, bool castsShadows, 
+		Degree spotAngle, Degree spotFalloffAngle)
+		: mPosition(BsZero), mRotation(BsIdentity), mType(type), mCastsShadows(castsShadows), mColor(color)
+		, mAttRadius(attRadius), mSourceRadius(srcRadius), mIntensity(intensity), mSpotAngle(spotAngle)
+		, mSpotFalloffAngle(spotFalloffAngle), mIsActive(true), mAutoAttenuation(true)
 	{
-		updatePhysicallyCorrectRange();
+		updateAttenuationRange();
 	}
 
-	void LightBase::setPhysicallyBasedAttenuation(bool enabled)
+	void LightBase::setUseAutoAttenuation(bool enabled)
 	{
-		mPhysCorrectAtten = enabled; 
+		mAutoAttenuation = enabled; 
 
 		if(enabled)
-			updatePhysicallyCorrectRange();
+			updateAttenuationRange();
 
 		_markCoreDirty();
 	}
 
-	void LightBase::setRange(float range)
+	void LightBase::setAttenuationRadius(float radius)
 	{
-		if (mPhysCorrectAtten)
+		if (mAutoAttenuation)
 			return;
 
-		mRange = range; 
+		mAttRadius = radius;
 		_markCoreDirty(); 
 		updateBounds();
 	}
 
+	void LightBase::setSourceRadius(float radius)
+	{
+		mSourceRadius = radius;
+		_markCoreDirty();
+	}
+
 	void LightBase::setIntensity(float intensity)
 	{
 		mIntensity = intensity; 
 
-		if (mPhysCorrectAtten)
-			updatePhysicallyCorrectRange();
+		if (mAutoAttenuation)
+			updateAttenuationRange();
 
 		_markCoreDirty(); 
 	}
 
 	float LightBase::getLuminance() const
 	{
+		float radius2 = mSourceRadius * mSourceRadius;
+		float pi2 = Math::PI * Math::PI;
+
 		switch (mType)
 		{
-		case LightType::Point:
-			return mIntensity / (4 * Math::PI);
+		case LightType::Radial:
+			if (mSourceRadius > 0.0f)
+				return mIntensity / (4 * radius2 * pi2); // Luminous flux -> luminance
+			else
+				return mIntensity / (4 * Math::PI); // Luminous flux -> luminous intensity
 		case LightType::Spot:
 		{
-			float cosTotalAngle = Math::cos(mSpotAngle);
-			float cosFalloffAngle = Math::cos(mSpotFalloffAngle);
+			if (mSourceRadius > 0.0f) 
+				return mIntensity / (radius2 * pi2); // Luminous flux -> luminance
+			else 
+			{
+				// Note: Consider using the simpler conversion I / PI to match with the area-light conversion
+				float cosTotalAngle = Math::cos(mSpotAngle);
+				float cosFalloffAngle = Math::cos(mSpotFalloffAngle);
 
-			return mIntensity / (Math::TWO_PI * (1.0f - (cosFalloffAngle + cosTotalAngle) * 0.5f));
+				// Luminous flux -> luminous intensity
+				return mIntensity / (Math::TWO_PI * (1.0f - (cosFalloffAngle + cosTotalAngle) * 0.5f));
+			}
 		}
 		case LightType::Directional:
-			return mIntensity;
+			if (mSourceRadius > 0.0f)
+			{
+				float angularDiameter = mSourceRadius * 2; // Assumed in degrees
+
+				// Use cone solid angle formulae to calculate disc solid angle
+				float solidAngle = Math::TWO_PI * (1 - cos(0.5f * angularDiameter * Math::DEG2RAD));
+				return mIntensity / solidAngle; // Illuminance -> luminance
+			}
+			else
+				return mIntensity; // In luminance units by default
 		default:
 			return 0.0f;
 		}
 	}
 
-	void LightBase::updatePhysicallyCorrectRange()
+	void LightBase::updateAttenuationRange()
 	{
 		// When lower than this attenuation light influence is assumed to be zero
 		const float minAttenuation = 0.2f;
-		mRange = sqrt(std::max(0.0f, getLuminance() / minAttenuation));
+		mAttRadius = sqrt(std::max(0.0f, getLuminance() / minAttenuation));
 
 		updateBounds();
 	}
@@ -91,19 +120,19 @@ namespace bs
 		case LightType::Directional:
 			mBounds = Sphere(mPosition, std::numeric_limits<float>::infinity());
 			break;
-		case LightType::Point:
-			mBounds = Sphere(mPosition, mRange);
+		case LightType::Radial:
+			mBounds = Sphere(mPosition, mAttRadius);
 			break;
 		case LightType::Spot:
 		{
 			// Note: We could use the formula for calculating the circumcircle of a triangle (after projecting the cone),
 			// but the radius of the sphere is the same as in the formula we use here, yet it is much simpler with no need
 			// to calculate multiple determinants. Neither are good approximations when cone angle is wide.
-			Vector3 offset(0, 0, mRange * 0.5f);
+			Vector3 offset(0, 0, mAttRadius * 0.5f);
 
 			// Direction along the edge of the cone, on the YZ plane (doesn't matter if we used XZ instead)
 			Degree angle = Math::clamp(mSpotAngle, Degree(-89), Degree(89));
-			Vector3 coneDir(0, Math::tan(angle)*mRange, mRange);
+			Vector3 coneDir(0, Math::tan(angle)*mAttRadius, mAttRadius);
 
 			// Distance between the "corner" of the cone and our center, must be the radius (provided the center is at
 			// the middle of the range)
@@ -122,9 +151,9 @@ namespace bs
 		
 	}
 
-	Light::Light(LightType type, Color color,
-		float intensity, float range, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
-		: LightBase(type, color, intensity, range, castsShadows, spotAngle, spotFalloffAngle),
+	Light::Light(LightType type, Color color, float intensity, float attRadius, float srcRadius, bool castsShadows, 
+		Degree spotAngle, Degree spotFalloffAngle)
+		: LightBase(type, color, intensity, attRadius, srcRadius, castsShadows, spotAngle, spotFalloffAngle),
 		mLastUpdateHash(0)
 	{
 		// Calling virtual method is okay here because this is the most derived type
@@ -137,10 +166,10 @@ namespace bs
 	}
 
 	SPtr<Light> Light::create(LightType type, Color color,
-		float intensity, float range, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
+		float intensity, float attRadius, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
 	{
 		Light* handler = new (bs_alloc<Light>()) 
-			Light(type, color, intensity, range, castsShadows, spotAngle, spotFalloffAngle);
+			Light(type, color, intensity, attRadius, 0.0f, castsShadows, spotAngle, spotFalloffAngle);
 		SPtr<Light> handlerPtr = bs_core_ptr<Light>(handler);
 		handlerPtr->_setThisPtr(handlerPtr);
 		handlerPtr->initialize();
@@ -160,7 +189,7 @@ namespace bs
 	SPtr<ct::CoreObject> Light::createCore() const
 	{
 		ct::Light* handler = new (bs_alloc<ct::Light>())
-			ct::Light(mType, mColor, mIntensity, mRange, mCastsShadows, mSpotAngle, mSpotFalloffAngle);
+			ct::Light(mType, mColor, mIntensity, mAttRadius, mSourceRadius, mCastsShadows, mSpotAngle, mSpotFalloffAngle);
 		SPtr<ct::Light> handlerPtr = bs_shared_ptr<ct::Light>(handler);
 		handlerPtr->_setThisPtr(handlerPtr);
 
@@ -175,11 +204,12 @@ namespace bs
 		size += rttiGetElemSize(mType);
 		size += rttiGetElemSize(mCastsShadows);
 		size += rttiGetElemSize(mColor);
-		size += rttiGetElemSize(mRange);
+		size += rttiGetElemSize(mAttRadius);
+		size += rttiGetElemSize(mSourceRadius);
 		size += rttiGetElemSize(mIntensity);
 		size += rttiGetElemSize(mSpotAngle);
 		size += rttiGetElemSize(mSpotFalloffAngle);
-		size += rttiGetElemSize(mPhysCorrectAtten);
+		size += rttiGetElemSize(mAutoAttenuation);
 		size += rttiGetElemSize(mIsActive);
 		size += rttiGetElemSize(getCoreDirtyFlags());
 		size += rttiGetElemSize(mBounds);
@@ -192,11 +222,12 @@ namespace bs
 		dataPtr = rttiWriteElem(mType, dataPtr);
 		dataPtr = rttiWriteElem(mCastsShadows, dataPtr);
 		dataPtr = rttiWriteElem(mColor, dataPtr);
-		dataPtr = rttiWriteElem(mRange, dataPtr);
+		dataPtr = rttiWriteElem(mAttRadius, dataPtr);
+		dataPtr = rttiWriteElem(mSourceRadius, dataPtr);
 		dataPtr = rttiWriteElem(mIntensity, dataPtr);
 		dataPtr = rttiWriteElem(mSpotAngle, dataPtr);
 		dataPtr = rttiWriteElem(mSpotFalloffAngle, dataPtr);
-		dataPtr = rttiWriteElem(mPhysCorrectAtten, dataPtr);
+		dataPtr = rttiWriteElem(mAutoAttenuation, dataPtr);
 		dataPtr = rttiWriteElem(mIsActive, dataPtr);
 		dataPtr = rttiWriteElem(getCoreDirtyFlags(), dataPtr);
 		dataPtr = rttiWriteElem(mBounds, dataPtr);
@@ -236,8 +267,8 @@ namespace bs
 	const UINT32 Light::LIGHT_CONE_NUM_SLICES = 10;
 
 	Light::Light(LightType type, Color color,
-		float intensity, float range, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
-		:LightBase(type, color, intensity, range, castsShadows, spotAngle, spotFalloffAngle), mRendererId(0)
+		float intensity, float attRadius, float srcRadius, bool castsShadows, Degree spotAngle, Degree spotFalloffAngle)
+		:LightBase(type, color, intensity, attRadius, srcRadius, castsShadows, spotAngle, spotFalloffAngle), mRendererId(0)
 	{
 
 	}
@@ -268,11 +299,12 @@ namespace bs
 		dataPtr = rttiReadElem(mType, dataPtr);
 		dataPtr = rttiReadElem(mCastsShadows, dataPtr);
 		dataPtr = rttiReadElem(mColor, dataPtr);
-		dataPtr = rttiReadElem(mRange, dataPtr);
+		dataPtr = rttiReadElem(mAttRadius, dataPtr);
+		dataPtr = rttiReadElem(mSourceRadius, dataPtr);
 		dataPtr = rttiReadElem(mIntensity, dataPtr);
 		dataPtr = rttiReadElem(mSpotAngle, dataPtr);
 		dataPtr = rttiReadElem(mSpotFalloffAngle, dataPtr);
-		dataPtr = rttiReadElem(mPhysCorrectAtten, dataPtr);
+		dataPtr = rttiReadElem(mAutoAttenuation, dataPtr);
 		dataPtr = rttiReadElem(mIsActive, dataPtr);
 		dataPtr = rttiReadElem(dirtyFlags, dataPtr);
 		dataPtr = rttiReadElem(mBounds, dataPtr);

+ 1 - 6
Source/ExamplePhysicallyBasedShading/Source/Main.cpp

@@ -291,12 +291,7 @@ namespace bs
         lightSO->setPosition(Vector3(0.1f, 0.0f, 0.0f));
 
         HLight light = lightSO->addComponent<CLight>();
-
-        // Disable physically based attentuation because we want to set our own range
-        light->setPhysicallyBasedAttenuation(false);
-
-	    light->setRange(10.0f);
-        light->setIntensity(10.0f);
+        light->setIntensity(2.0f);
 
         /************************************************************************/
         /* 									SKYBOX                       		*/

+ 29 - 22
Source/MBansheeEditor/Inspectors/LightInspector.cs

@@ -17,11 +17,12 @@ namespace BansheeEditor
     {
         private GUIEnumField lightTypeField = new GUIEnumField(typeof(LightType), new LocEdString("Light type"));
         private GUIColorField colorField = new GUIColorField(new LocEdString("Color"));
-        private GUIFloatField rangeField = new GUIFloatField(new LocEdString("Range"));
+        private GUIFloatField attRadiusField = new GUIFloatField(new LocEdString("Attenuation radius"));
+        private GUIFloatField sourceRadiusField = new GUIFloatField(new LocEdString("Source radius"));
         private GUIFloatField intensityField = new GUIFloatField(new LocEdString("Intensity"));
         private GUISliderField spotAngleField = new GUISliderField(1, 180, new LocEdString("Spot angle"));
         private GUISliderField spotFalloffAngleField = new GUISliderField(1, 180, new LocEdString("Spot falloff angle"));
-        private GUIToggleField physBasedAttenField = new GUIToggleField(new LocEdString("Physically based attenuation"));
+        private GUIToggleField autoAttenuationField = new GUIToggleField(new LocEdString("Use auto. attenuation"));
         private GUIToggleField castShadowField = new GUIToggleField(new LocEdString("Cast shadow"));
 
         private InspectableState modifyState;
@@ -37,7 +38,7 @@ namespace BansheeEditor
                 {
                     light.Type = (LightType)x;
 
-                    ToggleTypeSpecificFields((LightType) x, light.PhysicallyBasedAttenuation);
+                    ToggleTypeSpecificFields((LightType) x, light.UseAutoAttenuation);
                 };
 
                 colorField.OnChanged += x =>
@@ -47,9 +48,13 @@ namespace BansheeEditor
                     ConfirmModify();
                 };
 
-                rangeField.OnChanged += x => { light.Range = x; MarkAsModified(); };
-                rangeField.OnConfirmed += ConfirmModify;
-                rangeField.OnFocusLost += ConfirmModify;
+                attRadiusField.OnChanged += x => { light.AttenuationRadius = x; MarkAsModified(); };
+                attRadiusField.OnConfirmed += ConfirmModify;
+                attRadiusField.OnFocusLost += ConfirmModify;
+
+                sourceRadiusField.OnChanged += x => { light.SourceRadius = x; MarkAsModified(); };
+                sourceRadiusField.OnConfirmed += ConfirmModify;
+                sourceRadiusField.OnFocusLost += ConfirmModify;
 
                 intensityField.OnChanged += x => { light.Intensity = x; MarkAsModified(); };
                 intensityField.OnConfirmed += ConfirmModify;
@@ -68,9 +73,9 @@ namespace BansheeEditor
                     ConfirmModify();
                 };
 
-                physBasedAttenField.OnChanged += x =>
+                autoAttenuationField.OnChanged += x =>
                 {
-                    light.PhysicallyBasedAttenuation = x;
+                    light.UseAutoAttenuation = x;
                     ToggleTypeSpecificFields(light.Type, x);
                     MarkAsModified();
                     ConfirmModify();
@@ -79,13 +84,14 @@ namespace BansheeEditor
                 Layout.AddElement(lightTypeField);
                 Layout.AddElement(colorField);
                 Layout.AddElement(intensityField);
-                Layout.AddElement(rangeField);
+                Layout.AddElement(attRadiusField);
+                Layout.AddElement(sourceRadiusField);
                 Layout.AddElement(spotAngleField);
                 Layout.AddElement(spotFalloffAngleField);
-                Layout.AddElement(physBasedAttenField);
+                Layout.AddElement(autoAttenuationField);
                 Layout.AddElement(castShadowField);
 
-                ToggleTypeSpecificFields(light.Type, light.PhysicallyBasedAttenuation);
+                ToggleTypeSpecificFields(light.Type, light.UseAutoAttenuation);
             }
         }
 
@@ -97,16 +103,17 @@ namespace BansheeEditor
                 return InspectableState.NotModified;
 
             LightType lightType = light.Type;
-            if (lightTypeField.Value != (ulong)lightType || physBasedAttenField.Value != light.PhysicallyBasedAttenuation)
-                ToggleTypeSpecificFields(lightType, light.PhysicallyBasedAttenuation);
+            if (lightTypeField.Value != (ulong)lightType || autoAttenuationField.Value != light.UseAutoAttenuation)
+                ToggleTypeSpecificFields(lightType, light.UseAutoAttenuation);
 
             lightTypeField.Value = (ulong)lightType;
             colorField.Value = light.Color;
             intensityField.Value = light.Intensity;
-            rangeField.Value = light.Range;
+            attRadiusField.Value = light.AttenuationRadius;
+            sourceRadiusField.Value = light.SourceRadius;
             spotAngleField.Value = light.SpotAngle.Degrees;
             spotFalloffAngleField.Value = light.SpotFalloffAngle.Degrees;
-            physBasedAttenField.Value = light.PhysicallyBasedAttenuation;
+            autoAttenuationField.Value = light.UseAutoAttenuation;
             castShadowField.Value = light.CastsShadow;
 
             InspectableState oldState = modifyState;
@@ -125,24 +132,24 @@ namespace BansheeEditor
         {
             if (type == LightType.Directional)
             {
-                rangeField.Active = false;
+                attRadiusField.Active = false;
                 spotAngleField.Active = false;
                 spotFalloffAngleField.Active = false;
-                physBasedAttenField.Active = false;
+                autoAttenuationField.Active = false;
             }
-            else if (type == LightType.Point)
+            else if (type == LightType.Radial)
             {
-                rangeField.Active = !physBasedAttenuation;
+                attRadiusField.Active = !physBasedAttenuation;
                 spotAngleField.Active = false;
                 spotFalloffAngleField.Active = false;
-                physBasedAttenField.Active = true;
+                autoAttenuationField.Active = true;
             }
             else
             {
-                rangeField.Active = !physBasedAttenuation;
+                attRadiusField.Active = !physBasedAttenuation;
                 spotAngleField.Active = true;
                 spotFalloffAngleField.Active = true;
-                physBasedAttenField.Active = true;
+                autoAttenuationField.Active = true;
             }
         }
 

+ 6 - 6
Source/MBansheeEditor/Window/MenuItems.cs

@@ -49,7 +49,7 @@ namespace BansheeEditor
         /// <summary>
         /// Adds a point light component to the currently selected scene object.
         /// </summary>
-        [MenuItem("Components/Point light", 7048)]
+        [MenuItem("Components/Radial light", 7048)]
         private static void AddPointLight()
         {
             SceneObject so = Selection.SceneObject;
@@ -58,7 +58,7 @@ namespace BansheeEditor
 
             UndoRedo.RecordSO(so, false, "Added a Light component");
             Light light = so.AddComponent<Light>();
-            light.Type = LightType.Point;
+            light.Type = LightType.Radial;
             EditorApplication.SetSceneDirty();
         }
 
@@ -489,13 +489,13 @@ namespace BansheeEditor
         /// <summary>
         /// Creates a new scene object with a point light component.
         /// </summary>
-        [MenuItem("Scene Objects/Point light", 8048)]
-        [ToolbarItem("Point light", ToolbarIcon.NewPointLight, "New point light", 1598)]
+        [MenuItem("Scene Objects/Radial light", 8048)]
+        [ToolbarItem("Point light", ToolbarIcon.NewPointLight, "New radial light", 1598)]
         private static void AddPointLightSO()
         {
-            SceneObject so = UndoRedo.CreateSO("Point light", "Created a Light");
+            SceneObject so = UndoRedo.CreateSO("Radial light", "Created a Light");
             Light light = so.AddComponent<Light>();
-            light.Type = LightType.Point;
+            light.Type = LightType.Radial;
 
             Selection.SceneObject = so;
             FocusOnHierarchyOrScene();

+ 10 - 10
Source/MBansheeEditor/Windows/Scene/Gizmos/LightGizmos.cs

@@ -47,8 +47,8 @@ namespace BansheeEditor
                     Gizmos.DrawLine(botLeft, botLeft + forward*5.0f);
                 }
                     break;
-                case LightType.Point:
-                    Gizmos.DrawWireSphere(position, light.Range);
+                case LightType.Radial:
+                    Gizmos.DrawWireSphere(position, light.AttenuationRadius);
 
                     break;
                 case LightType.Spot:
@@ -57,17 +57,17 @@ namespace BansheeEditor
                     Vector3 up = light.SceneObject.Rotation.Rotate(Vector3.YAxis);
                     Vector3 forward = light.SceneObject.Forward;
 
-                    float discRadius = light.Range*MathEx.Tan(light.SpotAngle*0.5f);
+                    float discRadius = light.AttenuationRadius * MathEx.Tan(light.SpotAngle*0.5f);
 
-                    Gizmos.DrawLine(position, position + forward * light.Range + up * discRadius);
-                    Gizmos.DrawLine(position, position + forward * light.Range - up * discRadius);
-                    Gizmos.DrawLine(position, position + forward * light.Range + right * discRadius);
-                    Gizmos.DrawLine(position, position + forward * light.Range - right * discRadius);
+                    Gizmos.DrawLine(position, position + forward * light.AttenuationRadius + up * discRadius);
+                    Gizmos.DrawLine(position, position + forward * light.AttenuationRadius - up * discRadius);
+                    Gizmos.DrawLine(position, position + forward * light.AttenuationRadius + right * discRadius);
+                    Gizmos.DrawLine(position, position + forward * light.AttenuationRadius - right * discRadius);
 
-                    float falloffDiscRadius = light.Range * MathEx.Tan(light.SpotFalloffAngle * 0.5f);
+                    float falloffDiscRadius = light.AttenuationRadius * MathEx.Tan(light.SpotFalloffAngle * 0.5f);
 
-                    Gizmos.DrawWireDisc(position + forward * light.Range, forward, discRadius);
-                    Gizmos.DrawWireDisc(position + forward * light.Range, forward, falloffDiscRadius);
+                    Gizmos.DrawWireDisc(position + forward * light.AttenuationRadius, forward, discRadius);
+                    Gizmos.DrawWireDisc(position + forward * light.AttenuationRadius, forward, falloffDiscRadius);
                 }
                     break;
             }

+ 21 - 11
Source/MBansheeEngine/Interop/NativeLight.cs

@@ -12,7 +12,7 @@ namespace BansheeEngine
     /// </summary>
     public enum LightType // Note: Must match C++ enum LightType
     {
-        Directional, Point, Spot
+        Directional, Radial, Spot
     }
 
     /// <summary>
@@ -38,10 +38,16 @@ namespace BansheeEngine
             set { Internal_SetColor(mCachedPtr, value); }
         }
 
-        internal float Range
+        internal float AttenuationRadius
         {
-            get { return Internal_GetRange(mCachedPtr); }
-            set { Internal_SetRange(mCachedPtr, value); }
+            get { return Internal_GetAttenuationRadius(mCachedPtr); }
+            set { Internal_SetAttenuationRadius(mCachedPtr, value); }
+        }
+
+        internal float SourceRadius
+        {
+            get { return Internal_GetSourceRadius(mCachedPtr); }
+            set { Internal_SetSourceRadius(mCachedPtr, value); }
         }
 
         internal float Intensity
@@ -68,10 +74,10 @@ namespace BansheeEngine
             set { Internal_SetCastsShadow(mCachedPtr, value); }
         }
 
-        internal bool PhysicallyBasedAttenuation
+        internal bool UseAutoAttenuation
         {
-            get { return Internal_GetPhysicallyBasedAttenuation(mCachedPtr); }
-            set { Internal_SetPhysicallyBasedAttenuation(mCachedPtr, value); }
+            get { return Internal_GetUseAutoAttenuation(mCachedPtr); }
+            set { Internal_SetUseAutoAttenuation(mCachedPtr, value); }
         }
 
         internal Sphere Bounds
@@ -112,9 +118,13 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetType(IntPtr instance, LightType value);
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern float Internal_GetRange(IntPtr instance);
+        private static extern float Internal_GetAttenuationRadius(IntPtr instance);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_SetAttenuationRadius(IntPtr instance, float value);
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern float Internal_GetSourceRadius(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetRange(IntPtr instance, float value);
+        private static extern void Internal_SetSourceRadius(IntPtr instance, float value);
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern float Internal_GetIntensity(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -128,9 +138,9 @@ namespace BansheeEngine
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetCastsShadow(IntPtr instance, bool value);
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern bool Internal_GetPhysicallyBasedAttenuation(IntPtr instance);
+        private static extern bool Internal_GetUseAutoAttenuation(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_SetPhysicallyBasedAttenuation(IntPtr instance, bool value);
+        private static extern void Internal_SetUseAutoAttenuation(IntPtr instance, bool value);
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern float Internal_GetSpotAngle(IntPtr instance);
         [MethodImpl(MethodImplOptions.InternalCall)]

+ 37 - 17
Source/MBansheeEngine/Rendering/Light.cs

@@ -44,17 +44,36 @@ namespace BansheeEngine
         }
 
         /// <summary>
-        /// Maximum range of the light. Light will not affect any geometry past that point. Range is automatically 
-        /// calculated from intensity if <see cref="PhysicallyBasedAttenuation"/> is turned on.
+        /// Range at which the light contribution fades out to zero. Use <see cref="UseAutoAttenuation"/> to provide
+        /// a radius automatically dependant on light intensity. The radius will cut-off light contribution and therefore
+        /// manually set very small radius can end up being very physically incorrect.
         /// </summary>
-        public float Range
+        public float AttenuationRadius
         {
-            get { return _nativeLight.Range; }
-            set { _nativeLight.Range = value; serializableData.range = value; }
+            get { return _nativeLight.AttenuationRadius; }
+            set { _nativeLight.AttenuationRadius = value; serializableData.attenuationRadius = value; }
         }
 
         /// <summary>
-        /// Power of the light source. This is luminous flux for point & spot lights, and radiance for directional lights.
+        /// Radius of the light source. If non-zero then this light represents an area light, otherwise it is a punctual
+        /// light. Area lights have different attenuation then punctual lights, and their appearance in specular reflections
+        /// is realistic. Shape of the area light depends on light type:
+        ///  - For directional light the shape is a disc projected on the hemisphere on the horizon. This parameter
+        ///    represents angular radius (in degrees) of the disk and should be very small (think of how much space the Sun
+        ///    takes on the sky - roughly 0.5 degrees).
+        ///  - For radial light the shape is a sphere and the radius is the radius of the sphere.
+        ///  - For spot lights the shape is a disc oriented in the direction of the spot light and the radius is the radius
+        ///    of the disc.
+        /// </summary>
+        public float SourceRadius
+        {
+            get { return _nativeLight.SourceRadius; }
+            set { _nativeLight.SourceRadius = value; serializableData.sourceRadius = value; }
+        }
+
+        /// <summary>
+        /// Determines the power of the light source.This will be luminous flux for radial & spot lights, luminance for
+        /// directional lights with no area, and illuminance for directional lights with area(non-zero source radius).
         /// </summary>
         public float Intensity
         {
@@ -82,14 +101,13 @@ namespace BansheeEngine
         }
 
         /// <summary>
-        /// Determines is the light attenuation handled in a physically correct way, or should the user have more artistic
-        /// control over it. If true the range and attenuation of the light are controlled by inverse square of distance. 
-        /// If false then the user is allowed to set the range and attenuation is adjusted accordingly. 
+        /// If enabled the <see cref="AttenuationRadius"/> property will automatically be controlled in order to provide
+        /// reasonable light radius, depending on its intensity.
         /// </summary>
-        public bool PhysicallyBasedAttenuation
+        public bool UseAutoAttenuation
         {
-            get { return _nativeLight.PhysicallyBasedAttenuation; }
-            set { _nativeLight.PhysicallyBasedAttenuation = value; serializableData.physicallyBasedAttenuation = value; }
+            get { return _nativeLight.UseAutoAttenuation; }
+            set { _nativeLight.UseAutoAttenuation = value; serializableData.useAutoAttenuation = value; }
         }
 
         /// <summary>
@@ -120,11 +138,12 @@ namespace BansheeEngine
             _nativeLight.Color = serializableData.color;
             _nativeLight.SpotAngle = serializableData.spotAngle;
             _nativeLight.SpotFalloffAngle = serializableData.spotFalloffAngle;
-            _nativeLight.Range = serializableData.range;
+            _nativeLight.AttenuationRadius = serializableData.attenuationRadius;
+            _nativeLight.SourceRadius = serializableData.sourceRadius;
             _nativeLight.Intensity = serializableData.intensity;
             _nativeLight.Type = serializableData.type;
             _nativeLight.CastsShadow = serializableData.castShadows;
-            _nativeLight.PhysicallyBasedAttenuation = serializableData.physicallyBasedAttenuation;
+            _nativeLight.UseAutoAttenuation = serializableData.useAutoAttenuation;
         }
 
         private void OnUpdate()
@@ -157,11 +176,12 @@ namespace BansheeEngine
             public Color color = Color.White;
             public Degree spotAngle = new Degree(45);
             public Degree spotFalloffAngle = new Degree(40);
-            public float range = 10.0f;
+            public float attenuationRadius = 10.0f;
+            public float sourceRadius = 0.0f;
             public float intensity = 5.0f;
-            public LightType type = LightType.Point;
+            public LightType type = LightType.Radial;
             public bool castShadows = false;
-            public bool physicallyBasedAttenuation = true;
+            public bool useAutoAttenuation = true;
         }
     }
 

+ 2 - 4
Source/RenderBeast/Source/BsLightRendering.cpp

@@ -346,10 +346,8 @@ namespace bs { namespace ct
 					float G = calcMicrofacetShadowingSmithGGX(m2, NoV, NoL);
 
 					// When we factor out G and F, then divide D by PDF, this is what's left
-					//float pdfFactor = 1.0f / NoH;
-
-					// Note: This is based on PDF: D * NoH / (4 * VoH), but I'm not sure where does the (4 * VoH) factor
-					// come from. I'm keeping it since it seems to look better.
+					// Note: This is based on PDF: D * NoH / (4 * VoH). (4 * VoH) factor comes from the Jacobian of the
+					// transformation from half vector to light vector
 					float pdfFactor = 4.0f * VoH / NoH;
 
 					if (NoL > 0.0f)

+ 3 - 3
Source/RenderBeast/Source/BsRenderBeast.cpp

@@ -337,7 +337,7 @@ namespace bs { namespace ct
 		}
 		else
 		{
-			if (light->getType() == LightType::Point)
+			if (light->getType() == LightType::Radial)
 			{
 				UINT32 lightId = (UINT32)mRadialLights.size();
 				light->setRendererId(lightId);
@@ -360,7 +360,7 @@ namespace bs { namespace ct
 	{
 		UINT32 lightId = light->getRendererId();
 
-		if (light->getType() == LightType::Point)
+		if (light->getType() == LightType::Radial)
 			mPointLightWorldBounds[lightId] = light->getBounds();
 		else if(light->getType() == LightType::Spot)
 			mSpotLightWorldBounds[lightId] = light->getBounds();
@@ -386,7 +386,7 @@ namespace bs { namespace ct
 		}
 		else
 		{
-			if (light->getType() == LightType::Point)
+			if (light->getType() == LightType::Radial)
 			{
 				Light* lastLight = mRadialLights.back().getInternal();
 				UINT32 lastLightId = lastLight->getRendererId();

+ 7 - 4
Source/SBansheeEngine/Include/BsScriptLight.h

@@ -47,14 +47,17 @@ namespace bs
 		static bool internal_getCastsShadow(ScriptLight* thisPtr);
 		static void internal_setCastsShadow(ScriptLight* thisPtr, bool castsShadow);
 
-		static bool internal_getPhysicallyBasedAttenuation(ScriptLight* thisPtr);
-		static void internal_setPhysicallyBasedAttenuation(ScriptLight* thisPtr, bool value);
+		static bool internal_getUseAutoAttenuation(ScriptLight* thisPtr);
+		static void internal_setUseAutoAttenuation(ScriptLight* thisPtr, bool value);
 
 		static void internal_getColor(ScriptLight* thisPtr, Color* color);
 		static void internal_setColor(ScriptLight* thisPtr, Color color);
 
-		static float internal_getRange(ScriptLight* thisPtr);
-		static void internal_setRange(ScriptLight* thisPtr, float range);
+		static float internal_getAttenuationRadius(ScriptLight* thisPtr);
+		static void internal_setAttenuationRadius(ScriptLight* thisPtr, float radius);
+
+		static float internal_getSourceRadius(ScriptLight* thisPtr);
+		static void internal_setSourceRadius(ScriptLight* thisPtr, float radius);
 
 		static float internal_getIntensity(ScriptLight* thisPtr);
 		static void internal_setIntensity(ScriptLight* thisPtr, float intensity);

+ 26 - 14
Source/SBansheeEngine/Source/BsScriptLight.cpp

@@ -25,14 +25,16 @@ namespace bs
 		metaData.scriptClass->addInternalCall("Internal_SetType", &ScriptLight::internal_setType);
 		metaData.scriptClass->addInternalCall("Internal_GetCastsShadow", &ScriptLight::internal_getCastsShadow);
 		metaData.scriptClass->addInternalCall("Internal_SetCastsShadow", &ScriptLight::internal_setCastsShadow);
-		metaData.scriptClass->addInternalCall("Internal_GetPhysicallyBasedAttenuation", 
-			&ScriptLight::internal_getPhysicallyBasedAttenuation);
-		metaData.scriptClass->addInternalCall("Internal_SetPhysicallyBasedAttenuation", 
-			&ScriptLight::internal_setPhysicallyBasedAttenuation);
+		metaData.scriptClass->addInternalCall("Internal_GetUseAutoAttenuation", 
+			&ScriptLight::internal_getUseAutoAttenuation);
+		metaData.scriptClass->addInternalCall("Internal_SetUseAutoAttenuation", 
+			&ScriptLight::internal_setUseAutoAttenuation);
 		metaData.scriptClass->addInternalCall("Internal_GetColor", &ScriptLight::internal_getColor);
 		metaData.scriptClass->addInternalCall("Internal_SetColor", &ScriptLight::internal_setColor);
-		metaData.scriptClass->addInternalCall("Internal_GetRange", &ScriptLight::internal_getRange);
-		metaData.scriptClass->addInternalCall("Internal_SetRange", &ScriptLight::internal_setRange);
+		metaData.scriptClass->addInternalCall("Internal_GetAttenuationRadius", &ScriptLight::internal_getAttenuationRadius);
+		metaData.scriptClass->addInternalCall("Internal_SetAttenuationRadius", &ScriptLight::internal_setAttenuationRadius);
+		metaData.scriptClass->addInternalCall("Internal_GetSourceRadius", &ScriptLight::internal_getSourceRadius);
+		metaData.scriptClass->addInternalCall("Internal_SetSourceRadius", &ScriptLight::internal_setSourceRadius);
 		metaData.scriptClass->addInternalCall("Internal_GetIntensity", &ScriptLight::internal_getIntensity);
 		metaData.scriptClass->addInternalCall("Internal_SetIntensity", &ScriptLight::internal_setIntensity);
 		metaData.scriptClass->addInternalCall("Internal_GetSpotAngle", &ScriptLight::internal_getSpotAngle);
@@ -73,14 +75,14 @@ namespace bs
 		thisPtr->getInternal()->setCastsShadow(castsShadow);
 	}
 
-	bool ScriptLight::internal_getPhysicallyBasedAttenuation(ScriptLight* thisPtr)
+	bool ScriptLight::internal_getUseAutoAttenuation(ScriptLight* thisPtr)
 	{
-		return thisPtr->getInternal()->getPhysicallyBasedAttenuation();
+		return thisPtr->getInternal()->getUseAutoAttenuation();
 	}
 
-	void ScriptLight::internal_setPhysicallyBasedAttenuation(ScriptLight* thisPtr, bool value)
+	void ScriptLight::internal_setUseAutoAttenuation(ScriptLight* thisPtr, bool value)
 	{
-		thisPtr->getInternal()->setPhysicallyBasedAttenuation(value);
+		thisPtr->getInternal()->setUseAutoAttenuation(value);
 	}
 
 	void ScriptLight::internal_getColor(ScriptLight* thisPtr, Color* color)
@@ -93,14 +95,24 @@ namespace bs
 		thisPtr->getInternal()->setColor(color);
 	}
 
-	float ScriptLight::internal_getRange(ScriptLight* thisPtr)
+	float ScriptLight::internal_getAttenuationRadius(ScriptLight* thisPtr)
 	{
-		return thisPtr->getInternal()->getRange();
+		return thisPtr->getInternal()->getAttenuationRadius();
 	}
 
-	void ScriptLight::internal_setRange(ScriptLight* thisPtr, float range)
+	void ScriptLight::internal_setAttenuationRadius(ScriptLight* thisPtr, float radius)
 	{
-		thisPtr->getInternal()->setRange(range);
+		thisPtr->getInternal()->setAttenuationRadius(radius);
+	}
+
+	float ScriptLight::internal_getSourceRadius(ScriptLight* thisPtr)
+	{
+		return thisPtr->getInternal()->getSourceRadius();
+	}
+
+	void ScriptLight::internal_setSourceRadius(ScriptLight* thisPtr, float radius)
+	{
+		thisPtr->getInternal()->setSourceRadius(radius);
 	}
 
 	float ScriptLight::internal_getIntensity(ScriptLight* thisPtr)