dark maps, light tweaks, onemesh fixes

This commit is contained in:
2022-06-09 20:42:03 +03:00
parent 5d12548cbc
commit 17296d3749
3 changed files with 9742 additions and 42 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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++;
}