From 3b430fd1e9257ba66876fea4daccb9f4400a5b48 Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Thu, 24 Nov 2022 00:02:48 -0500 Subject: [PATCH 1/7] Update VfxConverter.cs change TEXCOORD4 to Color0, turns out Hammer fucks around with model TEXCOORDs on compiles, fixes(?) vertex color getting removed --- Field/Textures/VfxConverter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Field/Textures/VfxConverter.cs b/Field/Textures/VfxConverter.cs index 846480b0..34a0f8e5 100644 --- a/Field/Textures/VfxConverter.cs +++ b/Field/Textures/VfxConverter.cs @@ -56,7 +56,7 @@ public class VfxConverter struct VertexInput { - float4 vColorBlendValues : TEXCOORD4 < Semantic( color ); >; + float4 vColorBlendValues : Color0 < Semantic( Color ); >; #include ""common/vertexinput.hlsl"" }; From a11b68f7adb6322bbe6068724dfc0d3c7042ea63 Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Fri, 2 Dec 2022 16:37:15 -0500 Subject: [PATCH 2/7] Change .vfx to new .shader --- Field/General/InfoConfigHandler.cs | 18 +++++++++--------- Field/Textures/Material.cs | 6 +++--- Field/Textures/VfxConverter.cs | 29 +++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/Field/General/InfoConfigHandler.cs b/Field/General/InfoConfigHandler.cs index f9e6775f..465ec9cc 100644 --- a/Field/General/InfoConfigHandler.cs +++ b/Field/General/InfoConfigHandler.cs @@ -106,7 +106,7 @@ public void AddInstance(string modelHash, float scale, Vector4 quatRotation, Vec Scale = scale }); } - + public void AddStaticInstances(List instances, string staticMesh) { foreach (var instance in instances) @@ -128,15 +128,15 @@ public void AddCustomTexture(string material, int index, TextureHeader texture) public void WriteToFile(string path) { - List s2 = new List(); - foreach (var material in _config["Materials"]) - { - s2.Add($"ps_{material.Key}.vfx"); - } - if(!Directory.Exists($"{path}/Shaders/Source2/")) - Directory.CreateDirectory($"{path}/Shaders/Source2/"); + //List s2 = new List(); + //foreach (var material in _config["Materials"]) + //{ + // s2.Add($"ps_{material.Key}.shader"); + //} + //if(!Directory.Exists($"{path}/Shaders/Source2/")) + // Directory.CreateDirectory($"{path}/Shaders/Source2/"); - File.WriteAllLines($"{path}/Shaders/Source2/_S2BuildList.txt", s2); + //File.WriteAllLines($"{path}/Shaders/Source2/_S2BuildList.txt", s2); // If theres only 1 part, we need to rename it + the instance to the name of the mesh (unreal imports to fbx name if only 1 mesh inside) if (_config["Parts"].Count == 1) diff --git a/Field/Textures/Material.cs b/Field/Textures/Material.cs index d27865af..65e76da1 100644 --- a/Field/Textures/Material.cs +++ b/Field/Textures/Material.cs @@ -153,9 +153,9 @@ public void SavePixelShader(string saveDirectory, bool isTerrain = false) { File.WriteAllText($"{saveDirectory}/PS_{Hash}.usf", usf); } - if (!File.Exists($"{saveDirectory}/Source2/PS_{Hash}.vfx")) + if (!File.Exists($"{saveDirectory}/Source2/PS_{Hash}.shader")) { - File.WriteAllText($"{saveDirectory}/Source2/PS_{Hash}.vfx", vfx); + File.WriteAllText($"{saveDirectory}/Source2/PS_{Hash}.shader", vfx); } Console.WriteLine($"Saved pixel shader {Hash}"); @@ -166,7 +166,7 @@ public void SavePixelShader(string saveDirectory, bool isTerrain = false) } vmat.AppendLine("Layer0 \n{"); - vmat.AppendLine($" shader \"ps_{Hash}.vfx\""); + vmat.AppendLine($" shader \"ps_{Hash}.shader\""); vmat.AppendLine(" F_ALPHA_TEST 1"); foreach (var e in Header.PSTextures) { diff --git a/Field/Textures/VfxConverter.cs b/Field/Textures/VfxConverter.cs index 34a0f8e5..0630f481 100644 --- a/Field/Textures/VfxConverter.cs +++ b/Field/Textures/VfxConverter.cs @@ -32,25 +32,35 @@ public class VfxConverter Description = ""Charm Auto-Generated Source 2 Shader""; } +MODES +{ + VrForward(); + + Depth( ""vr_depth_only.vfx"" ); + + ToolsVis( S_MODE_TOOLS_VIS ); + ToolsWireframe( ""vr_tools_wireframe.vfx"" ); + ToolsShadingComplexity( ""vr_tools_shading_complexity.vfx"" ); + + Reflection( ""high_quality_reflections.vfx"" ); +} + FEATURES { #include ""common/features.hlsl"" //Feature( F_ALPHA_TEST, 0..1, ""Rendering"" ); //Feature( F_PREPASS_ALPHA_TEST, 0..1, ""Rendering"" ); -} -MODES -{ - VrForward(); - Depth( ""vr_depth_only.vfx"" ); - ToolsVis( S_MODE_TOOLS_VIS ); - ToolsWireframe( ""vr_tools_wireframe.vfx"" ); - ToolsShadingComplexity( ""vr_tools_shading_complexity.vfx"" ); + Feature( F_HIGH_QUALITY_REFLECTIONS, 0..1, ""Rendering"" ); } COMMON { #include ""common/shared.hlsl"" + #define USES_HIGH_QUALITY_REFLECTIONS + //#define S_GGX_SHADING 1 + //#define S_SPECULAR_CUBE_MAP 1 + #define D_NO_MODEL_TINT 1 //translucent } @@ -69,6 +79,9 @@ struct PixelInput VS { #include ""common/vertex.hlsl"" + + BoolAttribute( UsesHighQualityReflections, ( F_HIGH_QUALITY_REFLECTIONS > 0 ) ); + PixelInput MainVs( INSTANCED_SHADER_PARAMS( VS_INPUT i ) ) { PixelInput o = ProcessVertex( i ); From 539c1b45466355f2bad749d796c68ae143228f0f Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Mon, 5 Dec 2022 23:21:25 -0500 Subject: [PATCH 3/7] Once again, some more S2 stuff mostly --- Field/General/InfoConfigHandler.cs | 38 ++++++++++++++++++++++-------- Field/Textures/Material.cs | 23 +++++++++++++++--- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/Field/General/InfoConfigHandler.cs b/Field/General/InfoConfigHandler.cs index 465ec9cc..5aa19bc2 100644 --- a/Field/General/InfoConfigHandler.cs +++ b/Field/General/InfoConfigHandler.cs @@ -3,6 +3,7 @@ using Field.Models; using Field.Statics; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace Field.General; @@ -106,7 +107,7 @@ public void AddInstance(string modelHash, float scale, Vector4 quatRotation, Vec Scale = scale }); } - + public void AddStaticInstances(List instances, string staticMesh) { foreach (var instance in instances) @@ -128,15 +129,6 @@ public void AddCustomTexture(string material, int index, TextureHeader texture) public void WriteToFile(string path) { - //List s2 = new List(); - //foreach (var material in _config["Materials"]) - //{ - // s2.Add($"ps_{material.Key}.shader"); - //} - //if(!Directory.Exists($"{path}/Shaders/Source2/")) - // Directory.CreateDirectory($"{path}/Shaders/Source2/"); - - //File.WriteAllLines($"{path}/Shaders/Source2/_S2BuildList.txt", s2); // If theres only 1 part, we need to rename it + the instance to the name of the mesh (unreal imports to fbx name if only 1 mesh inside) if (_config["Parts"].Count == 1) @@ -152,6 +144,32 @@ public void WriteToFile(string path) _config["Parts"] = new ConcurrentDictionary(); _config["Parts"][_config["MeshName"]] = part; } + + + //im not smart enough to have done this, so i made an ai do it lol + //this just sorts the "instances" part of the cfg so its ordered by scale + //makes it easier for instancing models in Hammer/S&Box + + var sortedDict = new ConcurrentDictionary>(); + + // Use LINQ's OrderBy method to sort the values in each array + // based on the "Scale" key. The lambda expression specifies that + // the "Scale" property should be used as the key for the order. + foreach (var keyValuePair in (ConcurrentDictionary>)_config["Instances"]) + { + var array = keyValuePair.Value; + var sortedArray = array.OrderBy(x => x.Scale); + + // Convert the sorted array to a ConcurrentBag + var sortedBag = new ConcurrentBag(sortedArray); + + // Add the sorted bag to the dictionary + sortedDict.TryAdd(keyValuePair.Key, sortedBag); + } + + // Finally, update the _config["Instances"] object with the sorted values + _config["Instances"] = sortedDict; + string s = JsonConvert.SerializeObject(_config, Formatting.Indented); if (_config.ContainsKey("MeshName")) diff --git a/Field/Textures/Material.cs b/Field/Textures/Material.cs index 65e76da1..482531f5 100644 --- a/Field/Textures/Material.cs +++ b/Field/Textures/Material.cs @@ -166,17 +166,34 @@ public void SavePixelShader(string saveDirectory, bool isTerrain = false) } vmat.AppendLine("Layer0 \n{"); - vmat.AppendLine($" shader \"ps_{Hash}.shader\""); - vmat.AppendLine(" F_ALPHA_TEST 1"); + + //If the shader doesnt exist, just use the default complex.shader + if (!File.Exists($"{saveDirectory}/Source2/PS_{Hash}.shader")) + { + vmat.AppendLine($" shader \"complex.shader\""); + + //Use just the first texture for the diffuse + if (Header.PSTextures.Count > 0) + { + vmat.AppendLine($" TextureColor \"materials/Textures/{Header.PSTextures[0].Texture.Hash}.png\""); + } + } + else + { + vmat.AppendLine($" shader \"ps_{Hash}.shader\""); + vmat.AppendLine(" F_ALPHA_TEST 1"); + } + foreach (var e in Header.PSTextures) { if (e.Texture == null) { continue; } - //Console.WriteLine("Saving texture " + e.Texture.Hash + " " + e.TextureIndex + " " + e.Texture.IsSrgb().ToString()); + vmat.AppendLine($" TextureT{e.TextureIndex} \"materials/Textures/{e.Texture.Hash}.png\""); } + // if(isTerrain) // { // vmat.AppendLine($" TextureT14 \"materials/Textures/{partEntry.Dyemap.Hash}.png\""); From 1b4e46e4145d93b6e93425d776818317bb7e6d03 Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Thu, 8 Dec 2022 18:40:59 -0500 Subject: [PATCH 4/7] Make Source 2 models use custom normals May increase compiled model size slightly but slightly improves the look --- Field/Textures/VfxConverter.cs | 12 ++++-------- Field/template.vmdl | 12 ++++++++++++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Field/Textures/VfxConverter.cs b/Field/Textures/VfxConverter.cs index 0630f481..9d7c8a54 100644 --- a/Field/Textures/VfxConverter.cs +++ b/Field/Textures/VfxConverter.cs @@ -393,12 +393,12 @@ private void WriteFunctionDefinition(Material material, bool bIsVertexShader) vfx.AppendLine(" float alpha = 1;"); vfx.AppendLine(" float4 tx = float4(i.vTextureCoords, 1, 1);"); - vfx.AppendLine(" float4 v0 = {1,1,1,1};"); //Seems to only be used for normals. + vfx.AppendLine(" float4 v0 = {1,1,1,1};"); //Seems to only be used for normals. No idea what it is. vfx.AppendLine(" float4 v1 = {i.vNormalWs, 1};"); //Pretty sure this is mesh normals vfx.AppendLine(" float4 v2 = {i.vTangentUWs, 1};"); //Tangent? Seems to only be used for normals. - vfx.AppendLine(" float4 v3 = {i.vTextureCoords, 1,1};"); //seems only used as texture coords - vfx.AppendLine(" float4 v4 = i.vBlendValues;"); //Not sure if this is VC or not - vfx.AppendLine(" float4 v5 = i.vBlendValues;"); //seems like this is always the same as v4/only used if shader uses VC alpha + vfx.AppendLine(" float4 v3 = {i.vTextureCoords, 1,1};"); //99.9% sure this is always UVs + vfx.AppendLine(" float4 v4 = i.vBlendValues;"); //Mostly seen on materials with parallax. Some kind of view vector or matrix? + vfx.AppendLine(" float4 v5 = i.vBlendValues;"); //seems to always be vertex color/vertex color alpha //vfx.AppendLine(" uint v6 = 1;"); //no idea foreach (var i in inputs) @@ -408,10 +408,6 @@ private void WriteFunctionDefinition(Material material, bool bIsVertexShader) vfx.AppendLine($" {i.Variable}.x = {i.Variable}.x * tx.x;"); } } - // vfx.Replace("v0.xyzw = v0.xyzw * tx.xyzw;", "v0.xyzw = v0.xyzw;"); - // vfx.Replace("v1.xyzw = v1.xyzw * tx.xyzw;", "v1.xyzw = v1.xyzw;"); - // vfx.Replace("v2.xyzw = v2.xyzw * tx.xyzw;", "v2.xyzw = v2.xyzw;"); - // vfx.Replace("v5.xyzw = v5.xyzw * tx.xyzw;", "v5.xyzw = v5.xyzw;"); } } diff --git a/Field/template.vmdl b/Field/template.vmdl index 1b1f53d7..1a3e22b3 100644 --- a/Field/template.vmdl +++ b/Field/template.vmdl @@ -26,6 +26,18 @@ [ { _class = "RenderMeshFile" + children = + [ + { + _class = "RenderMeshMarkup" + material_search_path = "" + use_expensive_tangents = true + high_high_precision_texcoords = false + calc_per_vertex_curvature = false + prefer_high_density_tris_in_uv_density_calc = false + cpu_access = false + }, + ] name = "%MESHNAME%" filename = "%FILENAME%" import_translation = [ 0.0, 0.0, 0.0 ] From c6c10e30000bfb8dd591b4078ecf152bd38643cb Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Fri, 9 Dec 2022 21:03:42 -0500 Subject: [PATCH 5/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d6a28c1..8d85f015 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Not yet implemented: - Generates .vfx shader files for semi-accurate game shaders (similar to UE5 shaders) - Generates .vmat (material) and .vmdl (model) files for statics and maps - (CS:GO Source 2 support is planned once that is released and if it supports custom content similar to S&Box) + ~~(CS:GO Source 2 support is planned once that is released and if it supports custom content similar to S&Box)~~ (Unlikely) Copy files from shaders/source2 to your addons "Shaders" folder, and the .vmat, textures, and .vmdl files to "materials", "materials/textures", and "models" respectively. From 589a04f90ab8ab2cdf308d0d48df155c09d625cc Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Fri, 9 Dec 2022 21:04:31 -0500 Subject: [PATCH 6/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d85f015..9df55dcc 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,8 @@ Not yet implemented: Copy files from shaders/source2 to your addons "Shaders" folder, and the .vmat, textures, and .vmdl files to "materials", "materials/textures", and "models" respectively. **To compile shaders:** - Drag and drop all the .vfx files into your addons shaders folder while you have S&Box open, this should automatically trigger the compile process. (Not Recommended though). - The better option is to locate all your .vfx files and drag/drop them onto vfxcompile.exe in your "Steam\steamapps\common\sbox\bin\win64" folder, this should compile the shaders without having the game open, saving system resources. **THIS WILL TAKE A LONG TIME TO DO, DUE TO COMPILE SPEEDS** + Drag and drop all the .shader files into your addons shaders folder while you have S&Box open, this should automatically trigger the compile process. (Not Recommended though). + The better option is to locate all your .shader files and drag/drop them onto vfxcompile.exe in your "Steam\steamapps\common\sbox\bin\win64" folder, this should compile the shaders without having the game open, saving system resources. **THIS WILL TAKE A LONG TIME TO DO, DUE TO COMPILE SPEEDS** From 80589fb9ccb27959214cf28b27798950a0de6447 Mon Sep 17 00:00:00 2001 From: DeltaDesigns <50308149+DeltaDesigns@users.noreply.github.com> Date: Sun, 11 Dec 2022 18:42:02 -0500 Subject: [PATCH 7/7] Basic string exporting --- Charm/TagListView.xaml.cs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/Charm/TagListView.xaml.cs b/Charm/TagListView.xaml.cs index e16bf467..e6d5486b 100644 --- a/Charm/TagListView.xaml.cs +++ b/Charm/TagListView.xaml.cs @@ -21,6 +21,7 @@ using Field; using Microsoft.Toolkit.Mvvm.Input; using Serilog; +using System.Text; namespace Charm; @@ -1313,6 +1314,7 @@ private void LoadStringContainer(TagHash tagHash) // Would be nice to do something with colour formatting. private void LoadStrings(TagHash tagHash) { + var viewer = GetViewer(); _allTagItems = new ConcurrentBag(); StringContainer stringContainer = PackageHandler.GetTag(typeof(StringContainer), tagHash); Parallel.ForEach(stringContainer.Header.StringHashTable, hash => @@ -1325,12 +1327,32 @@ private void LoadStrings(TagHash tagHash) }); }); RefreshItemList(); + SetExportFunction(ExportString, (int)EExportTypeFlag.Full); + viewer.ExportControl.SetExportInfo(tagHash); + } + + private void ExportString(ExportInfo info) + { + + StringContainer stringContainer = PackageHandler.GetTag(typeof(StringContainer), new TagHash(info.Hash)); + StringBuilder text = new StringBuilder(); + + Parallel.ForEach(stringContainer.Header.StringHashTable, hash => + { + text.Append($"{hash} : {stringContainer.GetStringFromHash(ELanguage.English, hash)} \n"); + }); + + string saveDirectory = ConfigHandler.GetExportSavePath() + $"/Strings/{info.Hash}_{info.Name}/"; + Directory.CreateDirectory(saveDirectory); + + File.WriteAllText(saveDirectory + "strings.txt", text.ToString()); + } #endregion - + #region Sound - + private async Task LoadSoundsPackagesList() { // If there are packages, we don't want to reload the view as very poor for performance.