gi stuff, static batching toggle

This commit is contained in:
2022-07-03 22:07:36 +03:00
parent 9cc8e81b33
commit 5805529ba8
8 changed files with 220 additions and 33 deletions

View File

@@ -107,6 +107,7 @@
"ID": "56eddcef4698702bd3cb0b8a1fb3396f",
"TypeName": "FlaxEngine.EmptyActor",
"ParentID": "a50f3639419a8306036ecfab7115e772",
"IsActive": false,
"Name": "ViewModelHolder",
"Transform": {
"Translation": {
@@ -215,6 +216,7 @@
"ID": "12cd95b64f5145dcae7b28b7404ef512",
"TypeName": "FlaxEngine.StaticModel",
"ParentID": "a50f3639419a8306036ecfab7115e772",
"IsActive": false,
"Name": "PlayerModel",
"Transform": {
"Scale": {
@@ -225,6 +227,7 @@
},
"StaticFlags": 0,
"Model": "b43f0f8f4aaba3f3156896a5a22ba493",
"DrawModes": 31,
"Buffer": {
"Entries": [
{

View File

@@ -6,7 +6,7 @@
"UseVSync": false,
"AAQuality": 3,
"SSRQuality": 3,
"SSAOQuality": 3,
"SSAOQuality": 0,
"VolumetricFogQuality": 3,
"ShadowsQuality": 3,
"ShadowMapsQuality": 3,
@@ -15,6 +15,7 @@
"GlobalSDFQuality": 2,
"GenerateSDFOnModelImport": true,
"GIQuality": 2,
"GIProbesSpacing": 300.0,
"GlobalSurfaceAtlasResolution": 2048,
"PostProcessSettings": {
"AO": {
@@ -27,11 +28,12 @@
"FadeDistance": 500.0
},
"GI": {
"OverrideFlags": 27,
"OverrideFlags": 63,
"Mode": 1,
"Intensity": 1.0,
"TemporalResponse": 0.9,
"Distance": 7000.0,
"BounceIntensity": 2.0,
"TemporalResponse": 1.0,
"Distance": 20000.0,
"FallbackIrradiance": {
"R": 1.0,
"G": 0.0,

View File

@@ -282,6 +282,96 @@ namespace Game
}
}
[ConsoleVariable("r_gi_bounce")]
public static string GlobalIlluminationBounce
{
get
{
return Graphics.PostProcessSettings.GlobalIllumination.BounceIntensity.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 999.0f);
PostProcessSettings postProcessSettings = Graphics.PostProcessSettings;
GlobalIlluminationSettings giSettings = postProcessSettings.GlobalIllumination;
giSettings.BounceIntensity = valueFloat;
postProcessSettings.GlobalIllumination = giSettings;
Graphics.PostProcessSettings = postProcessSettings;
}
}
}
[ConsoleVariable("r_gi_spacing")]
public static string GlobalIlluminationProbeSpacing
{
get
{
return Graphics.GIProbesSpacing.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 999.0f);
Graphics.GIProbesSpacing = valueFloat;
}
}
}
[ConsoleVariable("r_gi_time")]
public static string GlobalIlluminationTime
{
get
{
return Graphics.PostProcessSettings.GlobalIllumination.TemporalResponse.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 10.0f);
PostProcessSettings postProcessSettings = Graphics.PostProcessSettings;
GlobalIlluminationSettings giSettings = postProcessSettings.GlobalIllumination;
giSettings.TemporalResponse = valueFloat;
postProcessSettings.GlobalIllumination = giSettings;
Graphics.PostProcessSettings = postProcessSettings;
}
}
}
[ConsoleVariable("r_gi_distance")]
public static string GlobalIlluminationDistance
{
get
{
return Graphics.PostProcessSettings.GlobalIllumination.Distance.ToString();
}
set
{
if (float.TryParse(value, out float valueFloat))
{
valueFloat = Mathf.Clamp(valueFloat, 0.0f, 10000000.0f);
PostProcessSettings postProcessSettings = Graphics.PostProcessSettings;
GlobalIlluminationSettings giSettings = postProcessSettings.GlobalIllumination;
giSettings.Distance = valueFloat;
postProcessSettings.GlobalIllumination = giSettings;
Graphics.PostProcessSettings = postProcessSettings;
}
}
}
[ConsoleVariable("r_shadows")]
public static string SceneShadows
{

View File

@@ -7,6 +7,13 @@ namespace Game
[ExecuteInEditMode]
public class LevelScript : Script
{
public string MapName;
public DateTime MapTimestamp;
}
public class LevelScript2 : Script
{
public string MapName;
public DateTime MapTimestamp;
}
}

View File

@@ -4,6 +4,9 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using FlaxEditor;
@@ -61,6 +64,7 @@ namespace Game
private float indirectLightMultiplier_ = 1.0f;
private List<MapEntity> lightEnts = new List<MapEntity>();
private Actor worldSpawnActor = null;
private bool staticBatching_ = false;
[Range(0.1f, 4f)]
public float BrightnessMultiplier
@@ -97,6 +101,20 @@ namespace Game
set { indirectLightMultiplier_ = value; resetLights = true; }
}
public bool StaticBatching
{
get => staticBatching_;
set
{
if (staticBatching_ == value)
return;
staticBatching_ = value;
FlaxEngine.Debug.Log("StaticBatching changed, reloading map");
LoadMap(true);
}
}
private static void QuickHull(Float3[] points, out Float3[] outVertices)
{
@@ -345,6 +363,21 @@ namespace Game
}
}
private static bool IsMapDirty(Actor worldSpawnActor, string mapPath)
{
#if FLAX_EDITOR
LevelScript levelScript = worldSpawnActor.GetScript<LevelScript>();
if (levelScript.MapName != mapPath)
return true;
DateTime timestamp = File.GetLastWriteTime(mapPath);
if (timestamp != levelScript.MapTimestamp)
return true;
#endif
return false;
}
private void LoadMap(bool forceLoad)
{
Stopwatch sw = Stopwatch.StartNew();
@@ -354,26 +387,14 @@ namespace Game
//Console.Print("Map parsing time: " + sw.Elapsed.TotalMilliseconds + "ms");
worldSpawnActor = Actor.FindActor("WorldSpawn");
LevelScript levelScript = worldSpawnActor?.GetScript<LevelScript>();
if (worldSpawnActor != null)
{
#if FLAX_EDITOR
DateTime timestamp = File.GetLastWriteTime(mapPath);
if (timestamp != levelScript.MapTimestamp)
{
FlaxEngine.Debug.Log($"Map dirty, reloading. {timestamp.ToString()} != {levelScript.MapTimestamp.ToString()}");
forceLoad = true;
levelScript.MapTimestamp = timestamp;
}
#endif
if (forceLoad)
worldSpawnActor.DestroyChildren();
else
{
//FlaxEngine.Debug.Log("Map already loaded in the scene");
resetLights = false;
if (!forceLoad && !IsMapDirty(worldSpawnActor, mapPath))
return;
}
FlaxEngine.Debug.Log($"Map dirty, reloading.");
worldSpawnActor.DestroyChildren();
resetLights = false;
}
//else
// FlaxEngine.Debug.Log("No WorldSpawn, loading map");
@@ -388,24 +409,25 @@ namespace Game
ConcurrentBag<Model> sdfModels = new ConcurrentBag<Model>();
bool oneMesh = false;
bool useStaticBatching = false;
bool useStaticBatching = StaticBatching;
bool convexMesh = true;
if (worldSpawnActor == null)
{
worldSpawnActor = Actor.AddChild<Actor>();
worldSpawnActor.Name = "WorldSpawn";
levelScript = worldSpawnActor.AddScript<LevelScript>();
#if FLAX_EDITOR
levelScript.MapTimestamp = File.GetLastWriteTime(mapPath);
#endif
worldSpawnActor.HideFlags &= ~HideFlags.DontSave;
//worldSpawnActor.HideFlags |= HideFlags.DontSave;
//worldSpawnActor.HideFlags |= HideFlags.DontSelect;
}
else
levelScript = worldSpawnActor.GetScript<LevelScript>();
LevelScript levelScript =
worldSpawnActor.GetScript<LevelScript>() ?? worldSpawnActor.AddScript<LevelScript>();
#if FLAX_EDITOR
levelScript.MapTimestamp = File.GetLastWriteTime(mapPath);
levelScript.MapName = mapPath;
#endif
if (!oneMesh)
{
@@ -1041,6 +1063,45 @@ namespace Game
//Debug.Log($"generate:{generateSdf}, GI:{Graphics.PostProcessSettings.GlobalIllumination.Mode != GlobalIlluminationMode.None}, {sdfModels.Count}");
if (generateSdf /*&& Graphics.PostProcessSettings.GlobalIllumination.Mode != GlobalIlluminationMode.None*/ && sdfModels.Count > 1)
{
int modelIndex = 0;
// TODO: read sdf data from texture and dump it to file, and reuse it when generating sdf data
using var sha1 = new SHA1Managed();
string mapHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(levelScript.MapName + levelScript.MapTimestamp.Ticks.ToString())).ToString();
foreach (var model in sdfModels.ToList())
{
string sdfDataPath = Path.Combine(AssetManager.CachePath, "MapSdfData",
$"{mapHash}_brush{modelIndex+1}");
/*if (File.Exists(sdfDataPath))
{
sdfModels.TryTake(out var model_);
T RawDeserialize<T>(byte[] rawData, int position)
{
int rawsize = Marshal.SizeOf(typeof(T));
if (rawsize > rawData.Length - position)
throw new ArgumentException("Not enough data to fill struct. Array length from position: " +
(rawData.Length - position) + ", Struct length: " + rawsize);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
Marshal.FreeHGlobal(buffer);
return retobj;
}
ModelBase.SDFData sdfData = new ModelBase.SDFData();
sdfData.Texture
model.SetSDF(sdfData);
}*/
modelIndex++;
}
var task = Task.Run(() =>
{
Stopwatch sw = Stopwatch.StartNew();
@@ -1048,14 +1109,34 @@ namespace Game
ParallelOptions opts = new ParallelOptions();
FlaxEngine.Debug.Log("processorcount: " + Environment.ProcessorCount);
float backfacesThreshold = 0.15f;
if (useStaticBatching)
opts.MaxDegreeOfParallelism = 2;//Environment.ProcessorCount / 2;
Parallel.ForEach(sdfModels, opts, model =>
{
opts.MaxDegreeOfParallelism = 2; //Environment.ProcessorCount / 2;
//backfacesThreshold = 1f;
}
Parallel.ForEach(sdfModels, opts, (model, _, index) =>
{
if (model.WaitForLoaded())
throw new Exception("model was not loaded");
model.GenerateSDF(0.9f, 6, true, 0.15f);
model.GenerateSDF(0.9f, 6, true, backfacesThreshold);
/*byte[] RawSerialize(object anything)
{
int rawSize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawDatas = new byte[rawSize];
Marshal.Copy(buffer, rawDatas, 0, rawSize);
Marshal.FreeHGlobal(buffer);
return rawDatas;
}
string sdfDataPath = Path.Combine(AssetManager.CachePath, "MapSdfData",
$"{mapHash}_brush{modelIndex+1}");*/
});
FlaxEngine.Debug.Log($"Generated level SDF in {sw.Elapsed.TotalMilliseconds}ms");

View File

@@ -63,7 +63,8 @@ namespace Game
if (playerId == NetworkManager.LocalPlayerClientId)
{
FindActor("CameraHolder").IsActive = true;
FindActor("ViewModelHolder").IsActive = true;
//FindActor("ViewModelHolder").IsActive = true;
FindActor("PlayerModel").IsActive = false;
}
}

View File

@@ -11,6 +11,9 @@ namespace Game
public static string DemoPath { get; private set; } =
Path.Combine(Directory.GetCurrentDirectory(), "Demos");
public static string CachePath { get; private set; } =
Path.Combine(Directory.GetCurrentDirectory(), "Cache");
public static GameplayGlobals Globals { get; private set; }
public static Config Config { get; private set; }