浏览代码

Fix convertion when in editor + fix color temperature with GI static

/main
sebastienlagarde 6 年前
当前提交
432deee6
共有 5 个文件被更改,包括 123 次插入65 次删除
  1. 39
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs
  2. 2
      com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Lit/LitShaderPreprocessor.cs
  3. 11
      com.unity.render-pipelines.high-definition/HDRP/Lighting/GlobalIlluminationUtils.cs
  4. 93
      com.unity.render-pipelines.high-definition/HDRP/Lighting/Light/HDAdditionalLightData.cs
  5. 43
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightUtils.cs

39
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs


showFeatures = o.Find(x => x.featuresFoldout),
showAdditionalSettings = o.Find(x => x.showAdditionalSettings)
};
// TODO: Review this once AdditionalShadowData is refactored
using (var o = new PropertyFetcher<AdditionalShadowData>(m_SerializedAdditionalShadowData))
m_AdditionalShadowData = new SerializedShadowData

// For punctual lights
if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Candela)
intensity = LightUtils.ConvertPointLightLumenToCandela(intensity);
{
if (m_LightShape == LightShape.Spot && m_AdditionalLightData.enableSpotReflector.boolValue)
{
// We have already calculate the correct value, just assign it
intensity = ((Light)target).intensity;
}
else
intensity = LightUtils.ConvertPointLightLumenToCandela(intensity);
}
intensity = LightUtils.ConvertPointLightCandelaToLumen(intensity);
{
if (m_LightShape == LightShape.Spot && m_AdditionalLightData.enableSpotReflector.boolValue)
{
// We just need to multiply candela by solid angle in this case
if ((SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex == SpotLightShape.Cone)
intensity = LightUtils.ConvertSpotLightCandelaToLumen(intensity, ((Light)target).spotAngle * Mathf.Deg2Rad, true);
else if ((SpotLightShape)m_AdditionalLightData.spotLightShape.enumValueIndex == SpotLightShape.Pyramid)
{
float angleA, angleB;
LightUtils.CalculateAnglesForPyramid(m_AdditionalLightData.aspectRatio.floatValue, ((Light)target).spotAngle * Mathf.Deg2Rad, out angleA, out angleB);
intensity = LightUtils.ConvertFrustrumLightCandelaToLumen(intensity, angleA, angleB);
}
else // Box
intensity = LightUtils.ConvertPointLightCandelaToLumen(intensity);
}
else
intensity = LightUtils.ConvertPointLightCandelaToLumen(intensity);
}
// For area lights
if (oldLightUnit == LightUnit.Lumen && newLightUnit == LightUnit.Luminance)
{

EditorGUILayout.PropertyField(m_AdditionalLightData.intensity, s_Styles.lightIntensity);
m_AdditionalLightData.lightUnit.enumValueIndex = (int)LightIntensityUnitPopup(m_LightShape);
EditorGUILayout.EndHorizontal();
if (spotLightShape == SpotLightShape.Cone || spotLightShape == SpotLightShape.Pyramid)
if ((spotLightShape == SpotLightShape.Cone || spotLightShape == SpotLightShape.Pyramid)
&& m_AdditionalLightData.lightUnit.enumValueIndex == (int)PunctualLightUnit.Lumen)
EditorGUILayout.PropertyField(m_AdditionalLightData.enableSpotReflector, s_Styles.enableSpotReflector);
}

2
com.unity.render-pipelines.high-definition/HDRP/Editor/Material/Lit/LitShaderPreprocessor.cs


return true;
bool isGBufferPass = snippet.passName == "GBuffer";
bool isForwardPass = snippet.passName == "Forward";
//bool isForwardPass = snippet.passName == "Forward";
bool isDepthOnlyPass = snippet.passName == "DepthOnly";
bool isTransparentForwardPass = snippet.passName == "TransparentDepthPostpass" || snippet.passName == "TransparentBackface" || snippet.passName == "TransparentDepthPrepass";

11
com.unity.render-pipelines.high-definition/HDRP/Lighting/GlobalIlluminationUtils.cs


add = HDUtils.s_DefaultHDAdditionalLightData;
}
// TODO: Only take into account the light dimmer when we have real time GI.
// TODO: Currently color temperature is not handled at runtime, need to expose useColorTemperature publicly
Color cct = new Color(1.0f, 1.0f, 1.0f);
#if UNITY_EDITOR
if (add.useColorTemperature)
cct = LightUtils.CorrelatedColorTemperatureToRGB(l.colorTemperature);
#endif
// TODO: Only take into account the light dimmer when we have real time GI.
ld.color.red *= cct.r;
ld.color.green *= cct.g;
ld.color.blue *= cct.b;
ld.indirectColor = add.affectDiffuse ? LightmapperUtils.ExtractIndirect(l) : LinearColor.Black();
// Note that the HDRI is correctly integrated in the GlobalIllumination system, we don't need to do anything regarding it.

93
com.unity.render-pipelines.high-definition/HDRP/Lighting/Light/HDAdditionalLightData.cs


};
public enum SpotLightShape { Cone, Pyramid, Box };
public enum LightUnit
{
Lumen,

public const float currentVersion = 1.1f;
[HideInInspector]
[FormerlySerializedAs("m_Version")]
public float version = currentVersion;
// To be able to have correct default values for our lights and to also control the conversion of intensity from the light editor (so it is compatible with GI)

public const float k_DefaultDirectionalLightIntensity = Mathf.PI; // In lux
public const float k_DefaultPunctualLightIntensity = 600.0f; // In lumens
public const float k_DefaultAreaLightIntensity = 200.0f; // In lumens
public float intensity
{
get { return displayLightIntensity; }

public bool featuresFoldout = true;
public bool showAdditionalSettings = false;
public float displayLightIntensity;
// Duplication of HDLightEditor.k_MinAreaWidth, maybe do something about that
const float k_MinAreaWidth = 0.01f; // Provide a small size of 1cm for line light

return _light;
}
}
void SetLightIntensity(float intensity)
{
displayLightIntensity = intensity;

}
else
m_Light.intensity = intensity;
m_Light.SetLightDirty(); // Should be apply only to parameter that's affect GI, but make the code cleaner
}

{
case LightType.Directional:
m_Light.intensity = intensity; // Alwas in lux
m_Light.intensity = intensity; // Always in lux
break;
case LightType.Point:
if (lightUnit == LightUnit.Candela)

break;
case LightType.Spot:
if (lightUnit == LightUnit.Candela)
{
// When using candela, reflector don't have any effect. Our intensity is candela = lumens/steradian and the user
// provide desired value for an angle of 1 steradian.
else if (enableSpotReflector)
}
else // lumen
if (spotLightShape == SpotLightShape.Cone)
if (enableSpotReflector)
m_Light.intensity = LightUtils.ConvertSpotLightLumenToCandela(intensity, m_Light.spotAngle * Mathf.Deg2Rad, true);
}
else if (spotLightShape == SpotLightShape.Pyramid)
{
float angleA, angleB;
LightUtils.CalculateAnglesForPyramid(aspectRatio, m_Light.spotAngle,
out angleA, out angleB);
// If reflector is enabled all the lighting from the sphere is focus inside the solid angle of current shape
if (spotLightShape == SpotLightShape.Cone)
{
m_Light.intensity = LightUtils.ConvertSpotLightLumenToCandela(intensity, m_Light.spotAngle * Mathf.Deg2Rad, true);
}
else if (spotLightShape == SpotLightShape.Pyramid)
{
float angleA, angleB;
LightUtils.CalculateAnglesForPyramid(aspectRatio, m_Light.spotAngle * Mathf.Deg2Rad, out angleA, out angleB);
m_Light.intensity = LightUtils.ConvertFrustrumLightLumenToCandela(intensity, angleA, angleB);
m_Light.intensity = LightUtils.ConvertFrustrumLightLumenToCandela(intensity, angleA, angleB);
}
else // Box shape, fallback to punctual light.
{
m_Light.intensity = LightUtils.ConvertPointLightLumenToCandela(intensity);
}
else // Box shape, fallback to punctual light.
else
// No reflector, angle act as occlusion of point light.
else // Reflector disabled, fallback to punctual light.
{
m_Light.intensity = LightUtils.ConvertPointLightLumenToCandela(intensity);
}
break;
}
}

// Force to retreive color light's m_UseColorTemperature because it's private
// Force to retrieve color light's m_UseColorTemperature because it's private
bool useColorTemperature
public bool useColorTemperature
{
get
{

{
return IsAreaLight((LightTypeExtent)lightType.enumValueIndex);
}
public void UpdateAreaLightEmissiveMesh()
{
MeshRenderer emissiveMeshRenderer = GetComponent<MeshRenderer>();

// We don't have anything to do left if the dislay emissive mesh option is disabled
return ;
}
Vector3 lightSize;
// Update light area size from GameObject transform scale if the transform have changed

else
lightSize = new Vector3(shapeWidth, shapeHeight, 0);
lightSize = Vector3.Max(Vector3.one * k_MinAreaWidth, lightSize);
m_Light.transform.localScale = lightSize;
m_Light.areaSize = lightSize;

case LightTypeExtent.Rectangle:
shapeWidth = lightSize.x;
shapeHeight = lightSize.y;
// If the light unit is in lumen, we need a convertion to get the good intensity value
if (lightUnit == LightUnit.Lumen)
{

if (emissiveMeshRenderer.sharedMaterial == null)
emissiveMeshRenderer.material = new Material(Shader.Find("HDRenderPipeline/Unlit"));
emissiveMeshRenderer.sharedMaterial.SetColor("_EmissiveColor", m_Light.color.linear * areaLightIntensity * CorrelatedColorTemperatureToRGB(m_Light.colorTemperature));
emissiveMeshRenderer.sharedMaterial.SetColor("_EmissiveColor", m_Light.color.linear * areaLightIntensity * LightUtils.CorrelatedColorTemperatureToRGB(m_Light.colorTemperature));
}
// Given a correlated color temperature (in Kelvin), estimate the RGB equivalent. Curve fit error is max 0.008.
Color CorrelatedColorTemperatureToRGB(float temperature)
{
float r, g, b;
// Temperature must fall between 1000 and 40000 degrees
// The fitting require to divide kelvin by 1000 (allow more precision)
float kelvin = Mathf.Clamp(temperature, 1000.0f, 40000.0f) / 1000.0f;
float kelvin2 = kelvin * kelvin;
// Using 6570 as a pivot is an approximation, pivot point for red is around 6580 and for blue and green around 6560.
// Calculate each color in turn (Note, clamp is not really necessary as all value belongs to [0..1] but can help for extremum).
// Red
r = kelvin < 6.570f ? 1.0f : Mathf.Clamp((1.35651f + 0.216422f * kelvin + 0.000633715f * kelvin2) / (-3.24223f + 0.918711f * kelvin), 0.0f, 1.0f);
// Green
g = kelvin < 6.570f ?
Mathf.Clamp((-399.809f + 414.271f * kelvin + 111.543f * kelvin2) / (2779.24f + 164.143f * kelvin + 84.7356f * kelvin2), 0.0f, 1.0f) :
Mathf.Clamp((1370.38f + 734.616f * kelvin + 0.689955f * kelvin2) / (-4625.69f + 1699.87f * kelvin), 0.0f, 1.0f);
//Blue
b = kelvin > 6.570f ? 1.0f : Mathf.Clamp((348.963f - 523.53f * kelvin + 183.62f * kelvin2) / (2848.82f - 214.52f * kelvin + 78.8614f * kelvin2), 0.0f, 1.0f);
return new Color(r, g, b, 1.0f);
}
#endif

43
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightUtils.cs


return exact ? intensity / (2.0f * (1.0f - Mathf.Cos(angle / 2.0f)) * Mathf.PI) : intensity / Mathf.PI;
}
public static float ConvertSpotLightCandelaToLumen(float intensity, float angle, bool exact)
{
return exact ? intensity * (2.0f * (1.0f - Mathf.Cos(angle / 2.0f)) * Mathf.PI) : intensity * Mathf.PI;
}
}
public static float ConvertFrustrumLightCandelaToLumen(float intensity, float angleA, float angleB)
{
return intensity * (4.0f * Mathf.Asin(Mathf.Sin(angleA / 2.0f) * Mathf.Sin(angleB / 2.0f)));
}
// convert intensity (lumen) to nits

{
return intensity / ((discRadius * discRadius * Mathf.PI) * Mathf.PI);
}
// convert intensity (nits) to lumen
public static float ConvertDiscLightLuminanceToLumen(float intensity, float discRadius)
{

//radiance = power / (length * (4 * Pi)).
return intensity / (4.0f * Mathf.PI * lineWidth);
}
// spotAngle in radiant
public static void CalculateAnglesForPyramid(float aspectRatio, float spotAngle, out float angleA, out float angleB)
{
// Since the smallest angles is = to the fov, and we don't care of the angle order, simply make sure the aspect ratio is > 1

angleA = spotAngle * Mathf.Deg2Rad;
angleA = spotAngle;
var halfAngle = angleA * 0.5f; // half of the smallest angle
var length = Mathf.Tan(halfAngle); // half length of the smallest side of the rectangle

angleB = halfAngle * 2.0f;
}
// TODO: Do a cheaper fitting
// Given a correlated color temperature (in Kelvin), estimate the RGB equivalent. Curve fit error is max 0.008.
// return color in linear RGB space
public static Color CorrelatedColorTemperatureToRGB(float temperature)
{
float r, g, b;
// Temperature must fall between 1000 and 40000 degrees
// The fitting require to divide kelvin by 1000 (allow more precision)
float kelvin = Mathf.Clamp(temperature, 1000.0f, 40000.0f) / 1000.0f;
float kelvin2 = kelvin * kelvin;
// Using 6570 as a pivot is an approximation, pivot point for red is around 6580 and for blue and green around 6560.
// Calculate each color in turn (Note, clamp is not really necessary as all value belongs to [0..1] but can help for extremum).
// Red
r = kelvin < 6.570f ? 1.0f : Mathf.Clamp((1.35651f + 0.216422f * kelvin + 0.000633715f * kelvin2) / (-3.24223f + 0.918711f * kelvin), 0.0f, 1.0f);
// Green
g = kelvin < 6.570f ?
Mathf.Clamp((-399.809f + 414.271f * kelvin + 111.543f * kelvin2) / (2779.24f + 164.143f * kelvin + 84.7356f * kelvin2), 0.0f, 1.0f) :
Mathf.Clamp((1370.38f + 734.616f * kelvin + 0.689955f * kelvin2) / (-4625.69f + 1699.87f * kelvin), 0.0f, 1.0f);
//Blue
b = kelvin > 6.570f ? 1.0f : Mathf.Clamp((348.963f - 523.53f * kelvin + 183.62f * kelvin2) / (2848.82f - 214.52f * kelvin + 78.8614f * kelvin2), 0.0f, 1.0f);
return new Color(r, g, b, 1.0f);
}
}
}
正在加载...
取消
保存