void DrawListSize(Rect rect) { int previousCount = m_List.count; int newCount = EditorGUI.DelayedIntField(rect, previousCount); if (newCount < 0) { newCount = 0; } if (newCount != previousCount) { m_Elements.arraySize = newCount; serializedObject.ApplyModifiedProperties(); // Set Default values if (newCount > previousCount) { LensFlareDataSRP lensFlareData = target as LensFlareDataSRP; for (int i = previousCount; i < newCount; ++i) { lensFlareData.elements[i] = new LensFlareDataElementSRP(); } m_Elements.serializedObject.Update(); } } }
public override void Action(int instanceId, string pathName, string resourceFile) { LensFlareDataSRP asset = ScriptableObject.CreateInstance <LensFlareDataSRP>(); UnityEngine.Assertions.Assert.IsNotNull(asset, $"failed to create instance of {nameof(LensFlareDataSRP)}"); pathName = AssetDatabase.GenerateUniqueAssetPath(pathName); asset.name = Path.GetFileName(pathName); AssetDatabase.CreateAsset(asset, pathName); ProjectWindowUtil.ShowCreatedAsset(asset); }
/// <summary> /// Implement this function to make a custom inspector /// </summary> public override void OnInspectorGUI() { m_Elements.serializedObject.Update(); EditorGUI.BeginChangeCheck(); LensFlareDataSRP lensFlareData = m_Elements.serializedObject.targetObject as LensFlareDataSRP; int countBefore = lensFlareData != null && lensFlareData.elements != null ? lensFlareData.elements.Length : 0; EditorGUILayout.PropertyField(m_Elements, Styles.elements); if (EditorGUI.EndChangeCheck()) { m_Elements.serializedObject.ApplyModifiedProperties(); int countAfter = lensFlareData != null && lensFlareData.elements != null ? lensFlareData.elements.Length : 0; if (countAfter > countBefore) { for (int i = countBefore; i < countAfter; ++i) { lensFlareData.elements[i] = new LensFlareDataElementSRP(); // Set Default values } m_Elements.serializedObject.Update(); } } }
/// <summary> /// Effective Job of drawing the set of Lens Flare registered /// </summary> /// <param name="lensFlareShader">Lens Flare material (HDRP or URP shader)</param> /// <param name="lensFlares">Set of Lens Flare</param> /// <param name="cam">Camera</param> /// <param name="actualWidth">Width actually used for rendering after dynamic resolution and XR is applied.</param> /// <param name="actualHeight">Height actually used for rendering after dynamic resolution and XR is applied.</param> /// <param name="usePanini">Set if use Panani Projection</param> /// <param name="paniniDistance">Distance used for Panini projection</param> /// <param name="paniniCropToFit">CropToFit parameter used for Panini projection</param> /// <param name="cmd">Command Buffer</param> /// <param name="colorBuffer">Source Render Target which contains the Color Buffer</param> /// <param name="GetLensFlareLightAttenuation">Delegate to which return return the Attenuation of the light based on their shape which uses the functions ShapeAttenuation...(...), must reimplemented per SRP</param> /// <param name="_FlareTex">ShaderID for the FlareTex</param> /// <param name="_FlareColorValue">ShaderID for the FlareColor</param> /// <param name="_FlareData0">ShaderID for the FlareData0</param> /// <param name="_FlareData1">ShaderID for the FlareData1</param> /// <param name="_FlareData2">ShaderID for the FlareData2</param> /// <param name="_FlareData3">ShaderID for the FlareData3</param> /// <param name="_FlareData4">ShaderID for the FlareData4</param> /// <param name="_FlareData5">ShaderID for the FlareData5</param> /// <param name="debugView">Debug View which setup black background to see only Lens Flare</param> static public void DoLensFlareDataDrivenCommon(Material lensFlareShader, LensFlareCommonSRP lensFlares, Camera cam, float actualWidth, float actualHeight, bool usePanini, float paniniDistance, float paniniCropToFit, Rendering.CommandBuffer cmd, Rendering.RenderTargetIdentifier colorBuffer, System.Func <Light, Camera, Vector3, float> GetLensFlareLightAttenuation, int _FlareTex, int _FlareColorValue, int _FlareData0, int _FlareData1, int _FlareData2, int _FlareData3, int _FlareData4, int _FlareData5, bool debugView) { Vector2 vScreenRatio; if (lensFlares.IsEmpty()) { return; } Vector2 screenSize = new Vector2(actualWidth, actualHeight); float screenRatio = screenSize.x / screenSize.y; vScreenRatio = new Vector2(screenRatio, 1.0f); Rendering.CoreUtils.SetRenderTarget(cmd, colorBuffer); if (debugView) { // Background pitch black to see only the Flares cmd.ClearRenderTarget(false, true, Color.black); } foreach (LensFlareComponentSRP comp in lensFlares.GetData()) { if (comp == null) { continue; } LensFlareDataSRP data = comp.lensFlareData; if (!comp.enabled || !comp.gameObject.activeSelf || !comp.gameObject.activeInHierarchy || data == null || data.elements == null || data.elements.Length == 0) { continue; } Light light = comp.GetComponent <Light>(); Vector3 positionWS; Vector3 viewportPos; bool isDirLight = false; if (light != null && light.type == LightType.Directional) { positionWS = -light.transform.forward * cam.farClipPlane; isDirLight = true; } else { positionWS = comp.transform.position; } viewportPos = cam.WorldToViewportPoint(positionWS); if (usePanini && cam == Camera.main) { viewportPos = DoPaniniProjection(viewportPos, actualWidth, actualHeight, cam.fieldOfView, paniniCropToFit, paniniDistance); } if (viewportPos.z < 0.0f) { continue; } if (!comp.allowOffScreen) { if (viewportPos.x < 0.0f || viewportPos.x > 1.0f || viewportPos.y < 0.0f || viewportPos.y > 1.0f) { continue; } } Vector4 modulationByColor = Vector4.one; Vector4 modulationAttenuation = Vector4.one; Vector3 diffToObject = positionWS - cam.transform.position; float distToObject = diffToObject.magnitude; float coefDistSample = distToObject / comp.maxAttenuationDistance; float coefScaleSample = distToObject / comp.maxAttenuationScale; float distanceAttenuation = !isDirLight && comp.distanceAttenuationCurve.length > 0 ? comp.distanceAttenuationCurve.Evaluate(coefDistSample) : 1.0f; float scaleByDistance = !isDirLight && comp.scaleByDistanceCurve.length >= 1 ? comp.scaleByDistanceCurve.Evaluate(coefScaleSample) : 1.0f; Color globalColorModulation = Color.white; if (light != null) { if (comp.attenuationByLightShape) { globalColorModulation *= GetLensFlareLightAttenuation(light, cam, -diffToObject.normalized); } } globalColorModulation *= distanceAttenuation; Vector3 dir = (cam.transform.position - comp.transform.position).normalized; Vector3 screenPosZ = cam.WorldToViewportPoint(positionWS + dir * comp.occlusionOffset); Vector2 occlusionRadiusEdgeScreenPos0 = (Vector2)cam.WorldToViewportPoint(positionWS); Vector2 occlusionRadiusEdgeScreenPos1 = (Vector2)cam.WorldToViewportPoint(positionWS + cam.transform.up * comp.occlusionRadius); float occlusionRadius = (occlusionRadiusEdgeScreenPos1 - occlusionRadiusEdgeScreenPos0).magnitude; cmd.SetGlobalVector(_FlareData1, new Vector4(occlusionRadius, comp.sampleCount, screenPosZ.z, actualHeight / actualWidth)); if (comp.useOcclusion) { cmd.EnableShaderKeyword("FLARE_OCCLUSION"); } else { cmd.DisableShaderKeyword("FLARE_OCCLUSION"); } foreach (LensFlareDataElementSRP element in data.elements) { if (element == null || (element.lensFlareTexture == null && element.flareType == SRPLensFlareType.Image) || element.localIntensity <= 0.0f || element.count <= 0) { continue; } Color colorModulation = globalColorModulation; if (light != null && element.modulateByLightColor) { if (light.useColorTemperature) { colorModulation *= light.color * Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature); } else { colorModulation *= light.color; } } Color curColor = colorModulation; Vector2 screenPos = new Vector2(2.0f * viewportPos.x - 1.0f, 1.0f - 2.0f * viewportPos.y); Vector2 translationScale = new Vector2(element.translationScale.x, element.translationScale.y); Texture texture = element.lensFlareTexture; float elemAspectRatio = element.sizeXY.x / element.sizeXY.y; float usedAspectRatio; if (element.flareType == SRPLensFlareType.Image) { usedAspectRatio = element.preserveAspectRatio ? ((((float)texture.height) / (float)texture.width)) : 1.0f; } else { usedAspectRatio = 1.0f; } float rotation = element.rotation; Vector4 tint = Vector4.Scale(element.tint, curColor); Vector2 radPos = new Vector2(Mathf.Abs(screenPos.x), Mathf.Abs(screenPos.y)); float radius = Mathf.Max(radPos.x, radPos.y); // l1 norm (instead of l2 norm) float radialsScaleRadius = comp.radialScreenAttenuationCurve.length > 0 ? comp.radialScreenAttenuationCurve.Evaluate(radius) : 1.0f; Vector2 elemSizeXY; if (element.preserveAspectRatio) { if (usedAspectRatio >= 1.0f) { elemSizeXY = new Vector2(element.sizeXY.x / usedAspectRatio, element.sizeXY.y); } else { elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y * usedAspectRatio); } } else { elemSizeXY = new Vector2(element.sizeXY.x, element.sizeXY.y); } float scaleSize = 0.1f; // Arbitrary value Vector2 size = new Vector2(elemSizeXY.x, elemSizeXY.y); float combinedScale = scaleByDistance * scaleSize * element.uniformScale * comp.scale; size *= combinedScale; Vector4 gradientModulation = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); float currentIntensity = comp.intensity * element.localIntensity * radialsScaleRadius * distanceAttenuation; if (currentIntensity <= 0.0f) { continue; } curColor *= element.tint; curColor *= currentIntensity; float globalCos0 = Mathf.Cos(-element.angularOffset * Mathf.Deg2Rad); float globalSin0 = Mathf.Sin(-element.angularOffset * Mathf.Deg2Rad); float position = 2.0f * element.position; SRPLensFlareBlendMode blendMode = element.blendMode; int materialPass; if (blendMode == SRPLensFlareBlendMode.Additive) { materialPass = 0; } else if (blendMode == SRPLensFlareBlendMode.Screen) { materialPass = 1; } else if (blendMode == SRPLensFlareBlendMode.Premultiply) { materialPass = 2; } else if (blendMode == SRPLensFlareBlendMode.Lerp) { materialPass = 3; } else { materialPass = 0; } if (element.flareType == SRPLensFlareType.Image) { cmd.DisableShaderKeyword("FLARE_CIRCLE"); cmd.DisableShaderKeyword("FLARE_POLYGON"); } else if (element.flareType == SRPLensFlareType.Circle) { cmd.EnableShaderKeyword("FLARE_CIRCLE"); cmd.DisableShaderKeyword("FLARE_POLYGON"); } else if (element.flareType == SRPLensFlareType.Polygon) { cmd.DisableShaderKeyword("FLARE_CIRCLE"); cmd.EnableShaderKeyword("FLARE_POLYGON"); } if (element.flareType == SRPLensFlareType.Circle || element.flareType == SRPLensFlareType.Polygon) { if (element.inverseSDF) { cmd.EnableShaderKeyword("FLARE_INVERSE_SDF"); } else { cmd.DisableShaderKeyword("FLARE_INVERSE_SDF"); } } else { cmd.DisableShaderKeyword("FLARE_INVERSE_SDF"); } if (element.lensFlareTexture != null) { cmd.SetGlobalTexture(_FlareTex, element.lensFlareTexture); } float usedGradientPosition = Mathf.Clamp01((1.0f - element.edgeOffset) - 1e-6f); if (element.flareType == SRPLensFlareType.Polygon) { usedGradientPosition = Mathf.Pow(usedGradientPosition + 1.0f, 5); } Vector2 ComputeLocalSize(Vector2 rayOff, Vector2 rayOff0, Vector2 curSize, AnimationCurve distortionCurve) { Vector2 rayOffZ = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0); Vector2 localRadPos; float localRadius; if (!element.distortionRelativeToCenter) { localRadPos = (rayOff - rayOff0) * 0.5f; localRadius = Mathf.Clamp01(Mathf.Max(Mathf.Abs(localRadPos.x), Mathf.Abs(localRadPos.y))); // l1 norm (instead of l2 norm) } else { localRadPos = screenPos + (rayOff + new Vector2(element.positionOffset.x, -element.positionOffset.y)) * element.translationScale; localRadius = Mathf.Clamp01(localRadPos.magnitude); // l2 norm (instead of l1 norm) } float localLerpValue = Mathf.Clamp01(distortionCurve.Evaluate(localRadius)); return(new Vector2(Mathf.Lerp(curSize.x, element.targetSizeDistortion.x * combinedScale / usedAspectRatio, localLerpValue), Mathf.Lerp(curSize.y, element.targetSizeDistortion.y * combinedScale, localLerpValue))); } float usedSDFRoundness = element.sdfRoundness; cmd.SetGlobalVector(_FlareData5, new Vector4(comp.allowOffScreen ? 1.0f : -1.0f, usedGradientPosition, Mathf.Exp(Mathf.Lerp(0.0f, 4.0f, Mathf.Clamp01(1.0f - element.fallOff))), 0.0f)); if (element.flareType == SRPLensFlareType.Polygon) { float invSide = 1.0f / (float)element.sideCount; float rCos = Mathf.Cos(Mathf.PI * invSide); float roundValue = rCos * usedSDFRoundness; float r = rCos - roundValue; float an = 2.0f * Mathf.PI * invSide; float he = r * Mathf.Tan(0.5f * an); cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, r, an, he)); } else { cmd.SetGlobalVector(_FlareData4, new Vector4(usedSDFRoundness, 0.0f, 0.0f, 0.0f)); } if (!element.allowMultipleElement || element.count == 1) { Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, position, element.angularOffset, element.positionOffset, element.autoRotate); Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0); Vector2 localSize = size; if (element.enableRadialDistortion) { Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0); localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); } cmd.SetGlobalVector(_FlareData0, flareData0); cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f)); cmd.SetGlobalVector(_FlareColorValue, curColor); UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); } else { float dLength = 2.0f * element.lengthSpread / ((float)(element.count - 1)); if (element.distribution == SRPLensFlareDistribution.Uniform) { for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) { Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0); Vector2 localSize = size; if (element.enableRadialDistortion) { Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0); localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); } float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f; Color col = element.colorGradient.Evaluate(timeScale); Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, position, element.angularOffset, element.positionOffset, element.autoRotate); cmd.SetGlobalVector(_FlareData0, flareData0); cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f)); cmd.SetGlobalVector(_FlareColorValue, curColor * col); UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); position += dLength; } } else if (element.distribution == SRPLensFlareDistribution.Random) { Random.State backupRandState = UnityEngine.Random.state; Random.InitState(element.seed); Vector2 side = new Vector2(Mathf.Sin(-element.angularOffset * Mathf.Deg2Rad), Mathf.Cos(-element.angularOffset * Mathf.Deg2Rad)); side *= element.positionVariation.y; float RandomRange(float min, float max) { return(Random.Range(min, max)); } for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) { float localIntensity = RandomRange(-1.0f, 1.0f) * element.intensityVariation + 1.0f; Vector2 rayOff = GetLensFlareRayOffset(screenPos, position, globalCos0, globalSin0); Vector2 localSize = size; if (element.enableRadialDistortion) { Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0); localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); } localSize += localSize * (element.scaleVariation * RandomRange(-1.0f, 1.0f)); Color randCol = element.colorGradient.Evaluate(RandomRange(0.0f, 1.0f)); Vector2 localPositionOffset = element.positionOffset + RandomRange(-1.0f, 1.0f) * side; float localRotation = element.rotation + RandomRange(-Mathf.PI, Mathf.PI) * element.rotationVariation; if (localIntensity > 0.0f) { Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, localRotation, position, element.angularOffset, localPositionOffset, element.autoRotate); cmd.SetGlobalVector(_FlareData0, flareData0); cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f)); cmd.SetGlobalVector(_FlareColorValue, curColor * randCol * localIntensity); UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); } position += dLength; position += 0.5f * dLength * RandomRange(-1.0f, 1.0f) * element.positionVariation.x; } Random.state = backupRandState; } else if (element.distribution == SRPLensFlareDistribution.Curve) { for (int elemIdx = 0; elemIdx < element.count; ++elemIdx) { float timeScale = element.count >= 2 ? ((float)elemIdx) / ((float)(element.count - 1)) : 0.5f; Color col = element.colorGradient.Evaluate(timeScale); float positionSpacing = element.positionCurve.length > 0 ? element.positionCurve.Evaluate(timeScale) : 1.0f; float localPos = position + 2.0f * element.lengthSpread * positionSpacing; Vector2 rayOff = GetLensFlareRayOffset(screenPos, localPos, globalCos0, globalSin0); Vector2 localSize = size; if (element.enableRadialDistortion) { Vector2 rayOff0 = GetLensFlareRayOffset(screenPos, 0.0f, globalCos0, globalSin0); localSize = ComputeLocalSize(rayOff, rayOff0, localSize, element.distortionCurve); } float sizeCurveValue = element.scaleCurve.length > 0 ? element.scaleCurve.Evaluate(timeScale) : 1.0f; localSize *= sizeCurveValue; Vector4 flareData0 = GetFlareData0(screenPos, element.translationScale, vScreenRatio, element.rotation, localPos, element.angularOffset, element.positionOffset, element.autoRotate); cmd.SetGlobalVector(_FlareData0, flareData0); cmd.SetGlobalVector(_FlareData2, new Vector4(screenPos.x, screenPos.y, localSize.x, localSize.y)); cmd.SetGlobalVector(_FlareData3, new Vector4(rayOff.x * element.translationScale.x, rayOff.y * element.translationScale.y, 1.0f / (float)element.sideCount, 0.0f)); cmd.SetGlobalVector(_FlareColorValue, curColor * col); UnityEngine.Rendering.Blitter.DrawQuad(cmd, lensFlareShader, materialPass); } } } } } }