dark maps, light tweaks, onemesh fixes
This commit is contained in:
4858
Assets/Maps/aerowalk_dark.map
Normal file
4858
Assets/Maps/aerowalk_dark.map
Normal file
File diff suppressed because it is too large
Load Diff
4703
Assets/Maps/aerowalk_dark_onelight.map
Normal file
4703
Assets/Maps/aerowalk_dark_onelight.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Assertions;
|
||||
using Console = Game.Console;
|
||||
@@ -40,10 +43,48 @@ namespace Game
|
||||
//private string mapPath = @"C:\dev\GoakeFlax\Assets\Maps\problematic.map";
|
||||
|
||||
public bool importLights = false;
|
||||
private bool generateSdf = true;
|
||||
|
||||
private Model model;
|
||||
private MaterialBase missingMaterial;
|
||||
|
||||
private bool dirtyLights = false;
|
||||
|
||||
private float brightnessMultiplier_ = 0.82f;
|
||||
private float lightRadiusMultiplier_ = 9.45f;
|
||||
private float fallOffExponent_ = 2.0f;
|
||||
private float saturationMultiplier_ = 1.0f;
|
||||
private List<MapEntity> lightEnts = new List<MapEntity>();
|
||||
|
||||
[Range(0.1f, 4f)]
|
||||
public float BrightnessMultiplier
|
||||
{
|
||||
get => brightnessMultiplier_;
|
||||
set { brightnessMultiplier_ = value; dirtyLights = true; }
|
||||
}
|
||||
|
||||
[Range(0.1f, 40f)]
|
||||
public float LightRadiusMultiplier
|
||||
{
|
||||
get => lightRadiusMultiplier_;
|
||||
set { lightRadiusMultiplier_ = value; dirtyLights = true; }
|
||||
}
|
||||
|
||||
[Range(2f, 8f)]
|
||||
public float FallOffExponent
|
||||
{
|
||||
get => fallOffExponent_;
|
||||
set { fallOffExponent_ = value; dirtyLights = true; }
|
||||
}
|
||||
|
||||
[Range(0.01f, 1f)]
|
||||
public float SaturationMultiplier
|
||||
{
|
||||
get => saturationMultiplier_;
|
||||
set { saturationMultiplier_ = value; dirtyLights = true; }
|
||||
}
|
||||
|
||||
|
||||
private static void QuickHull(Vector3[] points, out Vector3[] outVertices)
|
||||
{
|
||||
var verts = new List<Vector3>();
|
||||
@@ -211,6 +252,8 @@ namespace Game
|
||||
Debug.Log("OnDeserialized: " + Editor.IsPlayMode);
|
||||
}
|
||||
#endif
|
||||
private ConcurrentBag<Model> sdfModels = new ConcurrentBag<Model>();
|
||||
private Task task;
|
||||
public override void OnStart()
|
||||
{
|
||||
#if false
|
||||
@@ -245,6 +288,50 @@ namespace Game
|
||||
|
||||
//Debug.Log("LoadMap");
|
||||
LoadMap(false);
|
||||
|
||||
if (generateSdf && Graphics.EnableGlobalSDF && sdfModels.Count > 1)
|
||||
{
|
||||
task = Task.Run(() =>
|
||||
{
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
Console.Print($"Generating level SDF ({sdfModels.Count} models)...");
|
||||
|
||||
Parallel.ForEach(sdfModels, new ParallelOptions() { MaxDegreeOfParallelism = 1 }, model =>
|
||||
{
|
||||
if (model.WaitForLoaded())
|
||||
throw new Exception("model was not loaded");
|
||||
model.GenerateSDF();
|
||||
});
|
||||
|
||||
Console.Print($"Generated level SDF in {sw.Elapsed.TotalMilliseconds}ms");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
if (dirtyLights)
|
||||
{
|
||||
Actor worldSpawnActor = Actor.GetChild("WorldSpawn");
|
||||
|
||||
foreach (var light in worldSpawnActor.GetChildren<Light>())
|
||||
Destroy(light);
|
||||
|
||||
int lightIndex = 0;
|
||||
foreach (MapEntity entity in root.entities.Where(x => x.properties.ContainsKey("classname")))
|
||||
switch (entity.properties["classname"])
|
||||
{
|
||||
case "light":
|
||||
if (importLights)
|
||||
ParseLight(entity, worldSpawnActor, ref lightIndex);
|
||||
break;
|
||||
//case "info_player_deathmatch":
|
||||
// ParsePlayerSpawn(entity, worldSpawnActor, ref playerSpawnIndex);
|
||||
// break;
|
||||
}
|
||||
|
||||
dirtyLights = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadMap(bool forceLoad)
|
||||
@@ -280,6 +367,14 @@ namespace Game
|
||||
bool oneMesh = false;
|
||||
bool convexMesh = true;
|
||||
|
||||
if (worldSpawnActor == null)
|
||||
{
|
||||
worldSpawnActor = Actor.AddChild<Actor>();
|
||||
worldSpawnActor.Name = "WorldSpawn";
|
||||
worldSpawnActor.HideFlags |= HideFlags.DontSave;
|
||||
//worldSpawnActor.HideFlags |= HideFlags.DontSelect;
|
||||
}
|
||||
|
||||
if (!oneMesh)
|
||||
{
|
||||
var materials = new Dictionary<string, MaterialBase>();
|
||||
@@ -291,14 +386,6 @@ namespace Game
|
||||
materials.Add(m.name, m.asset);
|
||||
}
|
||||
|
||||
if (worldSpawnActor == null)
|
||||
{
|
||||
worldSpawnActor = Actor.AddChild<Actor>();
|
||||
worldSpawnActor.Name = "WorldSpawn";
|
||||
worldSpawnActor.HideFlags |= HideFlags.DontSave;
|
||||
//worldSpawnActor.HideFlags |= HideFlags.DontSelect;
|
||||
}
|
||||
|
||||
var brushGeometries = new List<BrushGeometry>(root.entities[0].brushes.Count);
|
||||
|
||||
// pass 1: triangulation
|
||||
@@ -492,13 +579,16 @@ namespace Game
|
||||
geom.model.MaterialSlots[i].Material = geom.meshes[i].material;
|
||||
}
|
||||
|
||||
//Not supported yet, should be done here
|
||||
//geom.model.GenerateSDF();
|
||||
|
||||
brushIndex++;
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
//Console.Print("Pass 2: texturing: " + sw.Elapsed.TotalMilliseconds + "ms");
|
||||
|
||||
// pass 3: collision
|
||||
// pass 3: static models & collision
|
||||
sw.Restart();
|
||||
brushIndex = 0;
|
||||
foreach (BrushGeometry geom in brushGeometries)
|
||||
@@ -515,6 +605,8 @@ namespace Game
|
||||
for (uint i = 0; i < indices.Length; i++)
|
||||
indices[i] = i;
|
||||
|
||||
bool isClipMaterial = false;
|
||||
bool isMissingMaterial = false;
|
||||
if (geom.meshes.Length == 1)
|
||||
{
|
||||
MaterialParameter info = geom.meshes[0].material.GetParameter("IsClipMaterial");
|
||||
@@ -522,10 +614,26 @@ namespace Game
|
||||
{
|
||||
var entries = childModel.Entries;
|
||||
entries[0].Visible = false;
|
||||
entries[0].ShadowsMode = ShadowsCastingMode.None;
|
||||
entries[0].ReceiveDecals = false;
|
||||
childModel.Entries = entries;
|
||||
isClipMaterial = true;
|
||||
}
|
||||
|
||||
if (geom.meshes[0].material == missingMaterial)
|
||||
isMissingMaterial = true;
|
||||
}
|
||||
|
||||
/*{
|
||||
var entries = childModel.Entries;
|
||||
for (int i=0; i < entries.Length; i++)
|
||||
entries[i].Visible = false;
|
||||
childModel.Entries = entries;
|
||||
}*/
|
||||
|
||||
if (!isClipMaterial && !isMissingMaterial)
|
||||
sdfModels.Add(geom.model);
|
||||
|
||||
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
|
||||
if (collisionData.CookCollision(
|
||||
convexMesh ? CollisionDataType.ConvexMesh : CollisionDataType.TriangleMesh, geom.vertices,
|
||||
@@ -680,10 +788,21 @@ namespace Game
|
||||
model.LODs[0].Meshes[0].UpdateMesh(vertices.ToArray(), (int[])(object)triangles, normals.ToArray(),
|
||||
null, uvs.ToArray());
|
||||
|
||||
StaticModel childModel = Actor.AddChild<StaticModel>();
|
||||
sdfModels.Add(model);
|
||||
|
||||
StaticModel childModel = worldSpawnActor.AddChild<StaticModel>();
|
||||
childModel.Name = "MapModel";
|
||||
childModel.Model = model;
|
||||
childModel.SetMaterial(0, missingMaterial);
|
||||
//childModel.SetMaterial(0, missingMaterial);
|
||||
|
||||
string workDir = Directory.GetCurrentDirectory();
|
||||
string matBasePath = Path.Combine(workDir, "Content", "Materials");
|
||||
string assetPath = Path.Combine(matBasePath, "dev/dev_128_gray" + ".flax");
|
||||
var brushMaterial = Content.Load<MaterialBase>(assetPath);
|
||||
if (brushMaterial != null)
|
||||
childModel.SetMaterial(0, brushMaterial);
|
||||
else
|
||||
childModel.SetMaterial(0, missingMaterial);
|
||||
|
||||
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
|
||||
if (collisionData.CookCollision(CollisionDataType.TriangleMesh, vertices.ToArray(),
|
||||
@@ -710,6 +829,7 @@ namespace Game
|
||||
case "light":
|
||||
if (importLights)
|
||||
ParseLight(entity, worldSpawnActor, ref lightIndex);
|
||||
lightEnts.Add(entity);
|
||||
break;
|
||||
case "info_player_deathmatch":
|
||||
ParsePlayerSpawn(entity, worldSpawnActor, ref playerSpawnIndex);
|
||||
@@ -722,58 +842,77 @@ namespace Game
|
||||
|
||||
private void ParseLight(MapEntity entity, Actor worldSpawnActor, ref int lightIndex)
|
||||
{
|
||||
const bool lightsUseInverseSquaredFalloff = true;
|
||||
int preset = 3;
|
||||
|
||||
//Console.Print("light");
|
||||
PointLight light = worldSpawnActor.AddChild<PointLight>();
|
||||
light.Name = "Light_" + lightIndex;
|
||||
light.LocalPosition = ParseOrigin(entity.properties["origin"]);
|
||||
|
||||
//"_color" "0.752941 0.752941 0"
|
||||
//"light" "200"
|
||||
|
||||
if (entity.properties.TryGetValue("_color", out string colorStr))
|
||||
light.Color = ParseColor(colorStr);
|
||||
|
||||
float lightamm = 200f;
|
||||
float lightamm = 300f;
|
||||
if (entity.properties.TryGetValue("light", out string lightStr))
|
||||
lightamm = float.Parse(lightStr);
|
||||
|
||||
float radamm = 64f;
|
||||
if (entity.properties.TryGetValue("radius", out string radStr))
|
||||
radamm = float.Parse(radStr);
|
||||
|
||||
|
||||
|
||||
light.Brightness = lightamm / 128f;
|
||||
light.Layer = 1;
|
||||
light.Radius = 1000f * 0.5f;
|
||||
light.UseInverseSquaredFalloff = false;
|
||||
light.FallOffExponent = 8;
|
||||
light.ShadowsDistance = 2000f * 1f;
|
||||
light.ShadowsDistance = 500f;
|
||||
light.ShadowsDepthBias = 0.027f;//0.005f;
|
||||
|
||||
|
||||
if (lightsUseInverseSquaredFalloff)
|
||||
if (preset == 0) // most accurate?, huge radius and low performance
|
||||
{
|
||||
light.Brightness = lightamm / 93f;
|
||||
light.Radius = radamm * 12.5f;
|
||||
light.FallOffExponent = 3.33f;
|
||||
light.ShadowsDepthBias = 0.0565f;
|
||||
|
||||
light.Brightness *= 0.7837f;
|
||||
light.Radius *= 0.83375f;
|
||||
|
||||
var hsv = light.Color.ToHSV();
|
||||
hsv.Y *= 0.8f;
|
||||
light.Color = Color.FromHSV(hsv);
|
||||
}
|
||||
else if (preset == 1) //
|
||||
{
|
||||
light.Radius = 250f;
|
||||
light.FallOffExponent = 2f;
|
||||
light.Brightness = (lightamm / 128f) * 1.25f;
|
||||
}
|
||||
else if (preset == 2)
|
||||
{
|
||||
light.Radius = 200f;
|
||||
light.FallOffExponent = 2f;
|
||||
light.Brightness = (lightamm / 128f) * 1.6f;
|
||||
}
|
||||
else //if (preset == 3)
|
||||
{
|
||||
light.Radius = radamm * LightRadiusMultiplier;
|
||||
light.FallOffExponent = FallOffExponent;
|
||||
light.Brightness = (lightamm / 128f) * BrightnessMultiplier;
|
||||
|
||||
light.ShadowsNormalOffsetScale = 10f;
|
||||
|
||||
light.ShadowsFadeDistance = 100f; // for debugging
|
||||
light.ShadowsDistance = 500f;
|
||||
light.ShadowsDepthBias = 0.027f;//0.005f;
|
||||
if (true)
|
||||
{
|
||||
light.Radius *= 0.5f;
|
||||
light.FallOffExponent = 2f;
|
||||
light.Brightness *= 1.25f;
|
||||
}
|
||||
else
|
||||
{
|
||||
light.Radius *= 0.4f;
|
||||
light.FallOffExponent = 2f;
|
||||
light.Brightness *= 1.6f;
|
||||
}
|
||||
//light.Brightness *= 2500f;
|
||||
//light.UseInverseSquaredFalloff = true;
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
// match FTEQW dynamic only light values
|
||||
}
|
||||
var hsv = light.Color.ToHSV();
|
||||
hsv.Y *= SaturationMultiplier;
|
||||
light.Color = Color.FromHSV(hsv);
|
||||
|
||||
//Console.Print("light pos: " + light.Position);
|
||||
light.ShadowsDepthBias = 0.0565f;
|
||||
// if low quality shadows
|
||||
light.ShadowsDepthBias = 0.2492f;
|
||||
}
|
||||
|
||||
lightIndex++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user