void Start() { float inten = 2f; if (GetComponent <SpriteRenderer>() != null) { Material material = GetComponent <SpriteRenderer>().material; material.SetColor("Color_F71EC87A", new Color(color.r * inten, color.g * inten, color.b * inten)); } if (GetComponent <UnityEngine.Rendering.Universal.Light2D>() != null) { UnityEngine.Rendering.Universal.Light2D light = GetComponent <UnityEngine.Rendering.Universal.Light2D>(); light.color = color; } }
public static void ErrorIfDuplicateGlobalLight(Light2D light) { if (light.lightType != Light2D.LightType.Global) { return; } foreach (var sortingLayer in light.affectedSortingLayers) { // should this really trigger at runtime? if (ContainsDuplicateGlobalLight(sortingLayer, light.blendStyleIndex)) { Debug.LogError("More than one global light on layer " + SortingLayer.IDToName(sortingLayer) + " for light blend style index " + light.blendStyleIndex); } } }
private static Material CreateLightMaterial(Renderer2DData rendererData, Light2D light, bool isVolume) { var isPoint = light.isPointLight; Material material; if (isVolume) { material = CoreUtils.CreateEngineMaterial(isPoint ? rendererData.pointLightVolumeShader : rendererData.shapeLightVolumeShader); } else { material = CoreUtils.CreateEngineMaterial(isPoint ? rendererData.pointLightShader : rendererData.shapeLightShader); if (light.overlapOperation == Light2D.OverlapOperation.Additive) { SetBlendModes(material, BlendMode.One, BlendMode.One); material.EnableKeyword(k_UseAdditiveBlendingKeyword); } else { SetBlendModes(material, BlendMode.SrcAlpha, BlendMode.OneMinusSrcAlpha); } } if (light.lightType == Light2D.LightType.Sprite) { material.EnableKeyword(k_SpriteLightKeyword); } if (isPoint && light.lightCookieSprite != null && light.lightCookieSprite.texture != null) { material.EnableKeyword(k_UsePointLightCookiesKeyword); } if (isPoint && light.normalMapQuality == Light2D.NormalMapQuality.Fast) { material.EnableKeyword(k_LightQualityFastKeyword); } if (light.normalMapQuality != Light2D.NormalMapQuality.Disabled) { material.EnableKeyword(k_UseNormalMap); } return(material); }
internal bool IsLit(Light2D light) { // Oddly adding and subtracting vectors is expensive here because of the new structures created... Vector3 deltaPos; deltaPos.x = m_ProjectedBoundingSphere.position.x + m_CachedPosition.x; deltaPos.y = m_ProjectedBoundingSphere.position.y + m_CachedPosition.y; deltaPos.z = m_ProjectedBoundingSphere.position.z + m_CachedPosition.z; deltaPos.x = light.m_CachedPosition.x - deltaPos.x; deltaPos.y = light.m_CachedPosition.y - deltaPos.y; deltaPos.z = light.m_CachedPosition.z - deltaPos.z; float distanceSq = Vector3.SqrMagnitude(deltaPos); float radiiLength = light.boundingSphere.radius + m_ProjectedBoundingSphere.radius; return(distanceSq <= (radiiLength * radiiLength)); }
public static Bounds GenerateSpriteMesh(Light2D light, Sprite sprite) { var mesh = light.lightMesh; if (sprite == null) { mesh.Clear(); return(new Bounds(Vector3.zero, Vector3.zero)); } // this needs to be called before getting UV at the line below. // Venky fixed it, enroute to trunk var uvs = sprite.uv; var srcVertices = sprite.GetVertexAttribute <Vector3>(VertexAttribute.Position); var srcUVs = sprite.GetVertexAttribute <Vector2>(VertexAttribute.TexCoord0); var srcIndices = sprite.GetIndices(); var center = 0.5f * (sprite.bounds.min + sprite.bounds.max); var vertices = new NativeArray <LightMeshVertex>(srcIndices.Length, Allocator.Temp); var color = new Color(0, 0, 0, 1); for (var i = 0; i < srcVertices.Length; i++) { vertices[i] = new LightMeshVertex { position = new Vector3(srcVertices[i].x, srcVertices[i].y, 0) - center, color = color, uv = srcUVs[i] }; } mesh.SetVertexBufferParams(vertices.Length, LightMeshVertex.VertexLayout); mesh.SetVertexBufferData(vertices, 0, 0, vertices.Length); mesh.SetIndices(srcIndices, MeshTopology.Triangles, 0, true); light.vertices = new LightMeshVertex[vertices.Length]; NativeArray <LightMeshVertex> .Copy(vertices, light.vertices, vertices.Length); light.indices = new ushort[srcIndices.Length]; NativeArray <ushort> .Copy(srcIndices, light.indices, srcIndices.Length); return(mesh.GetSubMesh(0).bounds); }
public static void RenderShadows(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int layerToRender, Light2D light, float shadowIntensity, RenderTargetIdentifier renderTexture, int colorBit) { using (new ProfilingScope(cmdBuffer, m_ProfilingSamplerShadows)) { bool hasShadow = false; var shadowCasterGroups = ShadowCasterGroup2DManager.shadowCasterGroups; if (shadowCasterGroups != null && shadowCasterGroups.Count > 0) { // Before doing anything check to see if any of the shadow casters are visible to this light for (var group = 0; group < shadowCasterGroups.Count; group++) { var shadowCasterGroup = shadowCasterGroups[group]; var shadowCasters = shadowCasterGroup.GetShadowCasters(); if (shadowCasters != null) { // Draw the projected shadows for the shadow caster group. Writing into the group stencil buffer bit for (var i = 0; i < shadowCasters.Count; i++) { var shadowCaster = shadowCasters[i]; if (shadowCaster.IsLit(light)) { hasShadow = true; break; } } } } if (hasShadow) { cmdBuffer.SetRenderTarget(renderTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare); if (colorBit == 0) { cmdBuffer.ClearRenderTarget(true, true, Color.clear); // clear stencil } using (new ProfilingScope(cmdBuffer, m_ProfilingSamplerShadowColorsLookup[colorBit])) { var shadowRadius = light.boundingSphere.radius; cmdBuffer.SetGlobalVector(k_LightPosID, light.transform.position); cmdBuffer.SetGlobalFloat(k_ShadowRadiusID, shadowRadius); cmdBuffer.SetGlobalColor(k_ShadowColorMaskID, k_ColorLookup[colorBit]); var projectedShadowsMaterial = pass.rendererData.GetProjectedShadowMaterial(colorBit); var selfShadowMaterial = pass.rendererData.GetSpriteSelfShadowMaterial(colorBit); var unshadowMaterial = pass.rendererData.GetSpriteUnshadowMaterial(colorBit); var setGlobalStencilMaterial = pass.rendererData.GetStencilOnlyShadowMaterial(colorBit); for (var group = 0; group < shadowCasterGroups.Count; group++) { var shadowCasterGroup = shadowCasterGroups[group]; var shadowCasters = shadowCasterGroup.GetShadowCasters(); if (shadowCasters != null) { // Draw the projected shadows for the shadow caster group. Writing into the group stencil buffer bit for (var i = 0; i < shadowCasters.Count; i++) { var shadowCaster = shadowCasters[i]; if (shadowCaster.IsLit(light)) { if (shadowCaster != null && projectedShadowsMaterial != null && shadowCaster.IsShadowedLayer(layerToRender)) { if (shadowCaster.castsShadows) { SetShadowProjectionGlobals(cmdBuffer, shadowCaster); cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedShadowsMaterial, 0, 0); } } } } // Draw the sprites, either as self shadowing or unshadowing for (var i = 0; i < shadowCasters.Count; i++) { var shadowCaster = shadowCasters[i]; if (shadowCaster.IsLit(light)) { if (shadowCaster != null && shadowCaster.IsShadowedLayer(layerToRender)) { if (shadowCaster.useRendererSilhouette) { // Draw using the sprite renderer var renderer = (Renderer)null; shadowCaster.TryGetComponent <Renderer>(out renderer); if (renderer != null) { var material = shadowCaster.selfShadows ? selfShadowMaterial : unshadowMaterial; if (material != null) { cmdBuffer.DrawRenderer(renderer, material); } } } else { var meshMat = shadowCaster.transform.localToWorldMatrix; var material = shadowCaster.selfShadows ? selfShadowMaterial : unshadowMaterial; // Draw using the shadow mesh if (material != null) { cmdBuffer.DrawMesh(shadowCaster.mesh, meshMat, material); } } } } } // Draw the projected shadows for the shadow caster group. Writing clearing the group stencil bit, and setting the global bit for (var i = 0; i < shadowCasters.Count; i++) { var shadowCaster = shadowCasters[i]; if (shadowCaster.IsLit(light)) { if (shadowCaster != null && projectedShadowsMaterial != null && shadowCaster.IsShadowedLayer(layerToRender)) { if (shadowCaster.castsShadows) { SetShadowProjectionGlobals(cmdBuffer, shadowCaster); cmdBuffer.DrawMesh(shadowCaster.mesh, shadowCaster.transform.localToWorldMatrix, projectedShadowsMaterial, 0, 1); } } } } } } } } } } }
public static void PrerenderShadows(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int layerToRender, Light2D light, int shadowIndex, float shadowIntensity) { var colorChannel = shadowIndex % 4; var textureIndex = shadowIndex / 4; if (colorChannel == 0) { ShadowRendering.CreateShadowRenderTexture(pass, renderingData, cmdBuffer, textureIndex); } // Render the shadows for this light RenderShadows(pass, renderingData, cmdBuffer, layerToRender, light, shadowIntensity, m_RenderTargets[textureIndex].Identifier(), colorChannel); }
public static Bounds GenerateParametricMesh(Light2D light, float radius, float falloffDistance, float angle, int sides) { var angleOffset = Mathf.PI / 2.0f + Mathf.Deg2Rad * angle; if (sides < 3) { radius = 0.70710678118654752440084436210485f * radius; sides = 4; } if (sides == 4) { angleOffset = Mathf.PI / 4.0f + Mathf.Deg2Rad * angle; } var vertexCount = 1 + 2 * sides; var indexCount = 3 * 3 * sides; var vertices = new NativeArray <LightMeshVertex>(vertexCount, Allocator.Temp); var triangles = new NativeArray <ushort>(indexCount, Allocator.Temp); var centerIndex = (ushort)(2 * sides); var mesh = light.lightMesh; // Only Alpha value in Color channel is ever used. May remove it or keep it for batching params in the future. var color = new Color(0, 0, 0, 1); vertices[centerIndex] = new LightMeshVertex { position = float3.zero, color = color }; var radiansPerSide = 2 * Mathf.PI / sides; var min = new float3(float.MaxValue, float.MaxValue, 0); var max = new float3(float.MinValue, float.MinValue, 0); for (var i = 0; i < sides; i++) { var endAngle = (i + 1) * radiansPerSide; var extrudeDir = new float3(math.cos(endAngle + angleOffset), math.sin(endAngle + angleOffset), 0); var endPoint = radius * extrudeDir; var vertexIndex = (2 * i + 2) % (2 * sides); vertices[vertexIndex] = new LightMeshVertex { position = endPoint, color = new Color(extrudeDir.x, extrudeDir.y, 0, 0) }; vertices[vertexIndex + 1] = new LightMeshVertex { position = endPoint, color = color }; // Triangle 1 (Tip) var triangleIndex = 9 * i; triangles[triangleIndex] = (ushort)(vertexIndex + 1); triangles[triangleIndex + 1] = (ushort)(2 * i + 1); triangles[triangleIndex + 2] = centerIndex; // Triangle 2 (Upper Top Left) triangles[triangleIndex + 3] = (ushort)(vertexIndex); triangles[triangleIndex + 4] = (ushort)(2 * i); triangles[triangleIndex + 5] = (ushort)(2 * i + 1); // Triangle 2 (Bottom Top Left) triangles[triangleIndex + 6] = (ushort)(vertexIndex + 1); triangles[triangleIndex + 7] = (ushort)(vertexIndex); triangles[triangleIndex + 8] = (ushort)(2 * i + 1); min = math.min(min, endPoint + extrudeDir * falloffDistance); max = math.max(max, endPoint + extrudeDir * falloffDistance); } mesh.SetVertexBufferParams(vertexCount, LightMeshVertex.VertexLayout); mesh.SetVertexBufferData(vertices, 0, 0, vertexCount); mesh.SetIndices(triangles, MeshTopology.Triangles, 0, false); light.vertices = new LightMeshVertex[vertexCount]; NativeArray <LightMeshVertex> .Copy(vertices, light.vertices, vertexCount); light.indices = new ushort[indexCount]; NativeArray <ushort> .Copy(triangles, light.indices, indexCount); return(new Bounds { min = min, max = max }); }
// Called during OnEnable public static void DeregisterLight(Light2D light) { Debug.Assert(lights.Contains(light)); lights.Remove(light); }
public static Bounds GenerateShapeMesh(Light2D light, Vector3[] shapePath, float falloffDistance) { var ix = 0; var vcount = 0; var icount = 0; const float kClipperScale = 10000.0f; var mesh = light.lightMesh; // todo Revisit this while we do Batching. var meshInteriorColor = new Color(0.0f, 0, 0, 1.0f); var meshExteriorColor = new Color(0.0f, 0, 0, 0.0f); var vertices = new NativeArray <LightMeshVertex>(shapePath.Length * 256, Allocator.Temp); var indices = new NativeArray <ushort>(shapePath.Length * 256, Allocator.Temp); // Create shape geometry var inputPointCount = shapePath.Length; var inner = new ContourVertex[inputPointCount + 1]; for (var i = 0; i < inputPointCount; ++i) { inner[ix++] = new ContourVertex() { Position = new Vec3() { X = shapePath[i].x, Y = shapePath[i].y, Z = 0 } } } ; inner[ix++] = inner[0]; var tess = new Tess(); tess.AddContour(inner, ContourOrientation.CounterClockwise); Tessellate(tess, ElementType.Polygons, indices, vertices, meshInteriorColor, ref vcount, ref icount); // Create falloff geometry List <IntPoint> path = new List <IntPoint>(); for (var i = 0; i < inputPointCount; ++i) { var newPoint = new Vector2(inner[i].Position.X, inner[i].Position.Y) * kClipperScale; var addPoint = new IntPoint((System.Int64)(newPoint.x), (System.Int64)(newPoint.y)); addPoint.N = i; addPoint.D = -1; path.Add(addPoint); } var lastPointIndex = inputPointCount - 1; // Generate Bevels. List <List <IntPoint> > solution = new List <List <IntPoint> >(); ClipperOffset clipOffset = new ClipperOffset(24.0f); clipOffset.AddPath(path, JoinType.jtRound, EndType.etClosedPolygon); clipOffset.Execute(ref solution, kClipperScale * falloffDistance, path.Count); if (solution.Count > 0) { // Fix path for Pivots. var outPath = solution[0]; var minPath = (long)inputPointCount; for (int i = 0; i < outPath.Count; ++i) { minPath = (outPath[i].N != -1) ? Math.Min(minPath, outPath[i].N) : minPath; } var containsStart = minPath == 0; outPath = FixPivots(outPath, path); // Tessellate. var bIndices = new NativeArray <ushort>(icount + (outPath.Count * 6) + 6, Allocator.Temp); for (int i = 0; i < icount; ++i) { bIndices[i] = indices[i]; } var bVertices = new NativeArray <LightMeshVertex>(vcount + outPath.Count + inputPointCount, Allocator.Temp); for (int i = 0; i < vcount; ++i) { bVertices[i] = vertices[i]; } var innerIndices = new ushort[inputPointCount]; // Inner Vertices. (These may or may not be part of the created path. Beware!!) for (int i = 0; i < inputPointCount; ++i) { bVertices[vcount++] = new LightMeshVertex() { position = new float3(inner[i].Position.X, inner[i].Position.Y, 0), color = meshInteriorColor }; innerIndices[i] = (ushort)(vcount - 1); } var saveIndex = (ushort)vcount; var pathStart = saveIndex; var prevIndex = outPath[0].N == -1 ? 0 : outPath[0].N; for (int i = 0; i < outPath.Count; ++i) { var curr = outPath[i]; var currPoint = new float2(curr.X / kClipperScale, curr.Y / kClipperScale); var currIndex = curr.N == -1 ? 0 : curr.N; bVertices[vcount++] = new LightMeshVertex() { position = new float3(currPoint.x, currPoint.y, 0), color = meshExteriorColor }; if (prevIndex != currIndex) { bIndices[icount++] = innerIndices[prevIndex]; bIndices[icount++] = innerIndices[currIndex]; bIndices[icount++] = (ushort)(vcount - 1); } bIndices[icount++] = innerIndices[prevIndex]; bIndices[icount++] = saveIndex; bIndices[icount++] = saveIndex = (ushort)(vcount - 1); prevIndex = currIndex; } // Close the Loop. { bIndices[icount++] = pathStart; bIndices[icount++] = innerIndices[minPath]; bIndices[icount++] = containsStart ? innerIndices[lastPointIndex] : saveIndex; bIndices[icount++] = containsStart ? pathStart : saveIndex; bIndices[icount++] = containsStart ? saveIndex : innerIndices[minPath]; bIndices[icount++] = containsStart ? innerIndices[lastPointIndex] : innerIndices[minPath - 1]; } TransferToMesh(bVertices, vcount, bIndices, icount, light); } else { TransferToMesh(vertices, vcount, indices, icount, light); } return(mesh.GetSubMesh(0).bounds); }
public static bool PrerenderShadows(IRenderPass2D pass, RenderingData renderingData, CommandBuffer cmdBuffer, int layerToRender, Light2D light, int shadowIndex, float shadowIntensity) { var colorChannel = shadowIndex % 4; var textureIndex = shadowIndex / 4; if (colorChannel == 0) { ShadowRendering.CreateShadowRenderTexture(pass, renderingData, cmdBuffer, textureIndex); } bool hadShadowsToRender = RenderShadows(pass, renderingData, cmdBuffer, layerToRender, light, shadowIntensity, m_RenderTargets[textureIndex].nameID, colorChannel); m_LightInputTextures[textureIndex] = m_RenderTargets[textureIndex].nameID; return(hadShadowsToRender); }
// Called during OnEnable public static void RegisterLight(Light2D light) { Debug.Assert(!lights.Contains(light)); lights.Add(light); ErrorIfDuplicateGlobalLight(light); }
private static void SetPointLightShaderGlobals(IRenderPass2D pass, CommandBuffer cmd, Light2D light) { // This is used for the lookup texture GetScaledLightInvMatrix(light, out var lightInverseMatrix); var innerRadius = GetNormalizedInnerRadius(light); var innerAngle = GetNormalizedAngle(light.pointLightInnerAngle); var outerAngle = GetNormalizedAngle(light.pointLightOuterAngle); var innerRadiusMult = 1 / (1 - innerRadius); cmd.SetGlobalVector(k_LightPositionID, light.transform.position); cmd.SetGlobalMatrix(k_LightInvMatrixID, lightInverseMatrix); cmd.SetGlobalFloat(k_InnerRadiusMultID, innerRadiusMult); cmd.SetGlobalFloat(k_OuterAngleID, outerAngle); cmd.SetGlobalFloat(k_InnerAngleMultID, 1 / (outerAngle - innerAngle)); cmd.SetGlobalTexture(k_LightLookupID, Light2DLookupTexture.GetLightLookupTexture()); cmd.SetGlobalTexture(k_FalloffLookupID, pass.rendererData.fallOffLookup); cmd.SetGlobalFloat(k_FalloffIntensityID, light.falloffIntensity); cmd.SetGlobalFloat(k_IsFullSpotlightID, innerAngle == 1 ? 1.0f : 0.0f); cmd.SetGlobalFloat(k_LightZDistanceID, light.normalMapDistance); if (light.lightCookieSprite != null && light.lightCookieSprite.texture != null) { cmd.SetGlobalTexture(k_PointLightCookieTexID, light.lightCookieSprite.texture); } }
private static void SetGeneralLightShaderGlobals(IRenderPass2D pass, CommandBuffer cmd, Light2D light) { float intensity = light.intensity * light.color.a; Color color = intensity * light.color; color.a = 1.0f; float volumeIntensity = light.volumeIntensity; cmd.SetGlobalFloat(k_FalloffIntensityID, light.falloffIntensity); cmd.SetGlobalFloat(k_FalloffDistanceID, light.shapeLightFalloffSize); cmd.SetGlobalColor(k_LightColorID, color); cmd.SetGlobalFloat(k_VolumeOpacityID, volumeIntensity); }
private static float GetNormalizedInnerRadius(Light2D light) { return(light.pointLightInnerRadius / light.pointLightOuterRadius); }
private static bool CanCastVolumetricShadows(Light2D light, int endLayerValue) { var topMostLayerValue = light.GetTopMostLitLayer(); return(light.volumetricShadowsEnabled && light.shadowVolumeIntensity > 0 && topMostLayerValue == endLayerValue); }
private static bool CanCastShadows(Light2D light, int layerToRender) { return(light.shadowsEnabled && light.shadowIntensity > 0 && light.IsLitLayer(layerToRender)); }