public static void AddLight(VolumetricLight light) { if (!allLights.Contains(light)) { allLights.Add(light); } }
static void SetupSpotLight(VolumetricLight light, CommandBuffer cb, Vector3 lightPos, bool drawShadows) { float angleScale = Mathf.Tan((light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad) * light.range; Quaternion rotation = light.transform.rotation; Matrix4x4 world = Matrix4x4.TRS(lightPos, rotation, new Vector3(angleScale, angleScale, light.range)); Matrix4x4 view = Matrix4x4.TRS(lightPos, rotation, Vector3.one).inverse; Vector3 fwd = light.transform.forward; // cosAngle, planeD, Vector2 extraParams = new Vector2(Mathf.Cos((light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad), -Vector3.Dot((lightPos + fwd * light.lightC.range), fwd)); cb.SetGlobalVector(_ConeAxis, fwd); SetNonDirectionalParams(light, cb, lightPos, ref world, drawShadows, extraParams); if (light.cookie != null) { Matrix4x4 proj = Matrix4x4.Perspective(light.spotAngle, 1, 0, 1); cb.SetGlobalMatrix(_MyLightMatrix0, spotClipNeg * proj * view); } if (drawShadows) { Matrix4x4 proj = Matrix4x4.Perspective(light.spotAngle, 1, SystemInfo.usesReversedZBuffer ? light.range : light.lightC.shadowNearPlane, SystemInfo.usesReversedZBuffer ? light.lightC.shadowNearPlane : light.range); Matrix4x4 m = spotClip * proj; m[0, 2] *= -1; m[1, 2] *= -1; m[2, 2] *= -1; m[3, 2] *= -1; cb.SetGlobalMatrix(_MyWorld2Shadow, m * view); } cb.DrawMesh(VolumetricLightUtils.spotlightMesh, world, VolumetricLightUtils.GetMaterial(LightType.Spot), 0, IsCameraInSpotLightBounds(light, fwd) ? 0 : 1); }
static void DrawLight(VolumetricLight light, CommandBuffer cb) { bool forceShadowsOff = light.type != LightType.Directional && light.cam2LightDist >= QualitySettings.shadowDistance; bool drawShadows = light.lightC.shadows != LightShadows.None && light.lightC.shadowStrength > 0 && !forceShadowsOff; cb.EnableKeyword("USE_SHADOWS", drawShadows); light.UpdateShadowCommandBuffers(drawShadows); if (drawShadows) { cb.SetGlobalTexture(_CachedShadowMap, light.shadowmapCache.shadowMap); } cb.SetGlobalVector(_LightColor, new Vector4(light.lightC.color.r, light.lightC.color.g, light.lightC.color.b, light.finalIntensity)); if (light.type == LightType.Point) { SetupPointLight(light, cb, light.transform.position, drawShadows); } else if (light.type == LightType.Spot) { SetupSpotLight(light, cb, light.transform.position, drawShadows); } else if (light.type == LightType.Directional) { SetupDirectionalLight(light, cb, drawShadows); } }
static void SetupDirectionalLight(VolumetricLight light, CommandBuffer cb, bool drawShadows) { if (drawShadows) { cb.SetGlobalTexture(_World2ShadowTex, light.world2ShadowCache.world2ShadowTex); } cb.Blit(null as Texture, _RenderTarget, VolumetricLightUtils.GetMaterial(LightType.Directional), 0); }
static void SetupPointLight(VolumetricLight light, CommandBuffer cb, Vector3 lightPos, bool drawShadows) { Matrix4x4 world = Matrix4x4.TRS(lightPos, Quaternion.identity, Vector3.one * light.range * 2.0f); SetNonDirectionalParams(light, cb, lightPos, ref world, drawShadows, Vector2.zero); //view if (light.cookie != null) { cb.SetGlobalMatrix(_MyLightMatrix0, Matrix4x4.TRS(lightPos, light.transform.rotation, Vector3.one).inverse); } cb.DrawMesh(RenderUtils.GetMesh(PrimitiveType.Sphere), world, VolumetricLightUtils.GetMaterial(LightType.Point), 0, IsCameraInPointLightBounds(light) ? 0 : 1); }
static bool IsCameraInSpotLightBounds(VolumetricLight light, Vector3 fwd) { if (!IsCameraInPointLightBounds(light)) { return(false); } Vector3 cam2LightNorm = light.cam2Light / light.cam2LightDist; if ((Mathf.Acos(Vector3.Dot(fwd, cam2LightNorm)) * Mathf.Rad2Deg) > (light.spotAngle + 3) * 0.5f) { return(false); } return(true); }
static void SetNonDirectionalParams(VolumetricLight light, CommandBuffer cb, Vector3 lightPos, ref Matrix4x4 world, bool drawShadows, Vector2 extraParams) { float innerLimit = light.range * light.attenuationStart; cb.SetGlobalVector(_AttenuationParams, new Vector4(innerLimit, light.range - innerLimit, extraParams.x, extraParams.y)); cb.SetGlobalVector(_VolumetricLight, new Vector4(1 - (light.mieG * light.mieG), 1 + (light.mieG * light.mieG), 2 * light.mieG, light.range)); cb.SetGlobalVector(_LightPos, lightPos); cb.EnableKeyword("USE_COOKIE", light.cookie != null); if (light.cookie != null) { cb.SetGlobalTexture(_LightTexture0, light.cookie); } if (drawShadows) { light.shadowmapForcer.ForceShadows(ref world); } }
public static bool PrepareLightsForRender(Camera cam, float maxDistance, float fadeRange) { bool anyRendering = false; Vector3 camPos = cam.transform.position; float inner = maxDistance - fadeRange; int c = allLights.Count; for (int i = 0; i < c; i++) { VolumetricLight light = allLights[i]; if (light.lightC.intensity <= 0) { light.finalIntensity = 0; continue; } if (light.type == LightType.Directional) { light.finalIntensity = light.maxIntensity; } else { light.cam2Light = camPos - light.transform.position; light.cam2LightSq = light.cam2Light.sqrMagnitude; light.cam2LightDist = Mathf.Sqrt(light.cam2LightSq); float t = 1.0f - Mathf.Clamp01((light.cam2LightDist - inner) / fadeRange); light.finalIntensity = light.maxIntensity * t; } if (light.finalIntensity > 0) { anyRendering = true; } } return(anyRendering); }
public static void RemoveLight(VolumetricLight light) { allLights.Remove(light); }
static bool IsCameraInPointLightBounds(VolumetricLight light) { return(light.cam2LightDist < light.range + 1); }