public static void GetLightAtWorldPos(Vector3 worldPos, out Vector4 lightColor, float translucency = 0.0f) { DeviceLightInfo info = UpdateLighting(null); lightColor = Vector4.UnitW; foreach (Light light in info.PriorizedLights) { if (light.Disposed) { continue; } if (light.IsDirectional) { float translucencyFactor = Vector3.Dot(light.dir, Vector3.UnitZ); translucencyFactor = translucencyFactor + 0.5f + 1.5f * translucency; translucencyFactor = MathF.Sign(translucencyFactor) * MathF.Pow(MathF.Abs(translucencyFactor), 0.5f); translucencyFactor = MathF.Clamp(translucencyFactor, 0.0f, 1.0f); Vector3 color = new Vector3( (float)light.color.R * light.intensity / 255.0f, (float)light.color.G * light.intensity / 255.0f, (float)light.color.B * light.intensity / 255.0f); Vector3.Multiply(ref color, translucencyFactor, out color); lightColor += new Vector4(color); } else { Vector3 lightPos = light.GameObj.Transform.Pos; Vector3 lightVec = lightPos - worldPos; float dist = lightVec.Length; Vector3 lightVecNorm = lightVec / dist; float spotExp = light.dir == Vector3.Zero ? 0.0f : MathF.Max(light.spotFocus, 1.0f); Vector3 lightDir = light.dir; float uniformScale = light.GameObj.Transform.Scale; MathF.TransformCoord(ref lightDir.X, ref lightDir.Y, light.GameObj.Transform.Angle); float attenFactor = 1.0f - MathF.Min(dist / (light.range * uniformScale), 1.0f); float spotFactor = MathF.Pow(MathF.Max(Vector3.Dot(lightVecNorm, -lightDir), 0.000001f), spotExp); float translucencyFactor = Vector3.Dot(lightVecNorm, -Vector3.UnitZ); translucencyFactor = translucencyFactor + 0.5f + 1.5f * translucency; translucencyFactor = MathF.Sign(translucencyFactor) * MathF.Pow(MathF.Abs(translucencyFactor), 0.5f); translucencyFactor = MathF.Clamp(translucencyFactor, 0.0f, 1.0f); Vector3 color = new Vector3( (float)light.color.R * light.intensity / 255.0f, (float)light.color.G * light.intensity / 255.0f, (float)light.color.B * light.intensity / 255.0f); Vector3.Multiply(ref color, attenFactor * spotFactor * translucencyFactor, out color); lightColor += new Vector4(color); } } }
private static DeviceLightInfo UpdateLighting(IDrawDevice device) { DeviceLightInfo info; if (device == null) { info = nullDeviceInfo; if (info != null && info.FrameId == Time.FrameCount) { return(info); } if (info == null) { info = new DeviceLightInfo(); nullDeviceInfo = info; } info.FrameId = Time.FrameCount; info.PriorizedLights = Scene.Current.FindComponents <Light>().Where(l => l.Active).ToList(); } else { if (deviceInfo.TryGetValue(device, out info) && info != null && info.FrameId == Time.FrameCount) { return(info); } if (info == null) { info = new DeviceLightInfo(); deviceInfo[device] = info; } info.FrameId = Time.FrameCount; info.PriorizedLights = Scene.Current.FindComponents <Light>().Where(l => l.Active).Where(l => l.IsVisibleTo(device)).ToList(); info.PriorizedLights.StableSort((Light a, Light b) => a.CalcPriority(device) - b.CalcPriority(device)); } return(info); }
public static void SetupLighting(IDrawDevice device, BatchInfo material) { DeviceLightInfo info = UpdateLighting(device); // Prepare shader dara float[] _lightPos = new float[4 * MaxVisible]; float[] _lightDir = new float[4 * MaxVisible]; float[] _lightColor = new float[3 * MaxVisible]; int _lightCount = MathF.Min(MaxVisible, info.PriorizedLights.Count); int i = 0; foreach (Light light in info.PriorizedLights) { if (light.Disposed) { continue; } Vector3 dir; Vector3 pos; float uniformScale; bool directional = light.IsDirectional; if (directional) { dir = light.dir; pos = Vector3.Zero; uniformScale = 1.0f; } else { dir = light.dir; pos = light.GameObj.Transform.Pos; uniformScale = light.GameObj.Transform.Scale; MathF.TransformCoord(ref dir.X, ref dir.Y, light.GameObj.Transform.Angle); } if (directional) { _lightPos[i * 4 + 0] = (float)light.ambientColor.R * light.ambientIntensity / 255.0f; _lightPos[i * 4 + 1] = (float)light.ambientColor.G * light.ambientIntensity / 255.0f; _lightPos[i * 4 + 2] = (float)light.ambientColor.B * light.ambientIntensity / 255.0f; _lightPos[i * 4 + 3] = 0.0f; } else { _lightPos[i * 4 + 0] = pos.X; _lightPos[i * 4 + 1] = pos.Y; _lightPos[i * 4 + 2] = pos.Z; _lightPos[i * 4 + 3] = light.range * uniformScale; } _lightDir[i * 4 + 0] = dir.X; _lightDir[i * 4 + 1] = dir.Y; _lightDir[i * 4 + 2] = dir.Z; _lightDir[i * 4 + 3] = dir == Vector3.Zero ? 0.0f : MathF.Max(light.spotFocus, 1.0f); _lightColor[i * 3 + 0] = (float)light.color.R * light.intensity / 255.0f; _lightColor[i * 3 + 1] = (float)light.color.G * light.intensity / 255.0f; _lightColor[i * 3 + 2] = (float)light.color.B * light.intensity / 255.0f; i++; if (i >= _lightCount) { break; } } if (i + 1 < _lightCount) { _lightCount = i + 1; } material.SetUniform("_lightCount", _lightCount); material.SetUniform("_lightPos", _lightPos); material.SetUniform("_lightDir", _lightDir); material.SetUniform("_lightColor", _lightColor); }
private static DeviceLightInfo UpdateLighting(IDrawDevice device) { DeviceLightInfo info; if (device == null) { info = nullDeviceInfo; if (info != null && info.FrameId == Time.FrameCount) return info; if (info == null) { info = new DeviceLightInfo(); nullDeviceInfo = info; } info.FrameId = Time.FrameCount; info.PriorizedLights = Scene.Current.FindComponents<Light>().Where(l => l.Active).ToList(); } else { if (deviceInfo.TryGetValue(device, out info) && info != null && info.FrameId == Time.FrameCount) return info; if (info == null) { info = new DeviceLightInfo(); deviceInfo[device] = info; } info.FrameId = Time.FrameCount; info.PriorizedLights = Scene.Current.FindComponents<Light>().Where(l => l.Active).Where(l => l.IsVisibleTo(device)).ToList(); info.PriorizedLights.StableSort((Light a, Light b) => a.CalcPriority(device) - b.CalcPriority(device)); } return info; }
public static void UpdateLighting(IDrawDevice device) { // Only update lighting info once per frame and device DeviceLightInfo info; if (deviceInfo.TryGetValue(device, out info) && info != null && info.FrameId == Time.FrameCount) { return; } if (info == null) { info = new DeviceLightInfo(); deviceInfo[device] = info; } info.FrameId = Time.FrameCount; info.PriorizedLights = Scene.Current.FindComponents <Light>().Where(l => l.Active).Where(l => l.IsVisibleTo(device)).ToList(); info.PriorizedLights.StableSort((Light a, Light b) => a.CalcPriority(device) - b.CalcPriority(device)); // Prepare shader dara Vector4[] _lightPos = new Vector4[MaxVisible]; Vector4[] _lightDir = new Vector4[MaxVisible]; Vector3[] _lightColor = new Vector3[MaxVisible]; int _lightCount = MathF.Min(MaxVisible, info.PriorizedLights.Count); int i = 0; foreach (Light light in info.PriorizedLights) { if (light.Disposed) { continue; } Vector3 dir; Vector3 pos; float uniformScale; bool directional = light.IsDirectional; if (directional) { dir = light.dir; pos = Vector3.Zero; uniformScale = 1.0f; } else { dir = light.dir; pos = light.GameObj.Transform.Pos; uniformScale = light.GameObj.Transform.Scale; MathF.TransformCoord(ref dir.X, ref dir.Y, light.GameObj.Transform.Angle); } if (directional) { _lightPos[i].X = (float)light.ambientColor.R * light.ambientIntensity / 255.0f; _lightPos[i].Y = (float)light.ambientColor.G * light.ambientIntensity / 255.0f; _lightPos[i].Z = (float)light.ambientColor.B * light.ambientIntensity / 255.0f; _lightPos[i].W = 0.0f; } else { _lightPos[i].X = pos.X; _lightPos[i].Y = pos.Y; _lightPos[i].Z = pos.Z; _lightPos[i].W = light.range * uniformScale; } _lightDir[i].X = dir.X; _lightDir[i].Y = dir.Y; _lightDir[i].Z = dir.Z; _lightDir[i].W = dir == Vector3.Zero ? 0.0f : MathF.Max(light.spotFocus, 1.0f); _lightColor[i].X = (float)light.color.R * light.intensity / 255.0f; _lightColor[i].Y = (float)light.color.G * light.intensity / 255.0f; _lightColor[i].Z = (float)light.color.B * light.intensity / 255.0f; i++; if (i >= _lightCount) { break; } } if (i + 1 < _lightCount) { _lightCount = i + 1; } device.ShaderParameters.Set("_lightCount", _lightCount); device.ShaderParameters.Set("_lightPos", _lightPos); device.ShaderParameters.Set("_lightDir", _lightDir); device.ShaderParameters.Set("_lightColor", _lightColor); }