private void FindMaterialAttributes(ValveMaterialFile vmt, List <VertexAttribute> dest) { dest.Add(VertexAttribute.Position); dest.Add(VertexAttribute.Normal); dest.Add(VertexAttribute.Uv); if (vmt == null) { return; } var shader = vmt.Shaders.First(); switch (shader.ToLower()) { case "lightmappedgeneric": case "lightmappedreflective": case "water": dest.Add(VertexAttribute.Uv2); break; case "lightmapped_4wayblend": case "worldvertextransition": dest.Add(VertexAttribute.Alpha); goto case "lightmappedgeneric"; } }
private MeshData GetOrCreateMeshData(ValveBspFile bsp, GeometryPage page, string matPath, bool cacheVertices = true) { MaterialGroup matGroup; var matDictIndex = MaterialDictionary.GetResourceIndex(bsp, matPath); if (!page.MaterialIndices.TryGetValue(matDictIndex, out int matIndex)) { var vmt = ValveMaterialFile.FromProvider(MaterialDictionary.GetResourcePath(bsp, matDictIndex), bsp.PakFile, Program.Resources); matGroup = new MaterialGroup(matIndex = page.Materials.Count, cacheVertices) { Material = matDictIndex }; page.MaterialIndices.Add(matDictIndex, matIndex); page.Materials.Add(matGroup); FindMaterialAttributes(vmt, matGroup.MeshData.Attributes); } else { matGroup = page.Materials[matIndex]; } return(matGroup.MeshData); }
private void LoadMaterial(MeshRenderer mr, string path) { if (!_resourceLoader.ContainsFile(path)) { return; } if (path.ToLower().Contains("tools")) { mr.enabled = false; return; } Material mat = null; var pathLower = path.ToLower(); if (_materialCache.ContainsKey(pathLower)) { mat = _materialCache[pathLower]; } else { using (var fs = _resourceLoader.OpenFile(path)) { var vmt = ValveMaterialFile.FromStream(fs); mat = VmtToMaterial(_resourceLoader, vmt, path); _materialCache.Add(pathLower, mat); } } mr.material = mat; }
private void Parse(ValveMaterialFile vmt) { // idk why this is enumerable var e = vmt.Shaders.GetEnumerator(); while (e.MoveNext()) { VmtShader = e.Current.ToLower(); Lightmapped = VmtShader == "lightmappedgeneric" || VmtShader == "worldvertextransition"; Transition = VmtShader == "worldvertextransition"; AlphaTest = vmt[VmtShader].ContainsKey("$alphatest") ? vmt[VmtShader]["$alphatest"] : false; Translucent = vmt[VmtShader].ContainsKey("$translucent") ? vmt[VmtShader]["$translucent"] : false; NoCull = vmt[VmtShader].ContainsKey("$nocull") ? vmt[VmtShader]["$nocull"] : false; BaseTex = vmt[VmtShader].ContainsKey("$basetexture") ? vmt[VmtShader]["$basetexture"] : string.Empty; BaseTex2 = vmt[VmtShader].ContainsKey("$basetexture2") ? vmt[VmtShader]["$basetexture2"] : string.Empty; BumpMap = vmt[VmtShader].ContainsKey("bumpmap") ? vmt[VmtShader]["bumpmap"] : string.Empty; Color = vmt[VmtShader].ContainsKey("$color") ? vmt[VmtShader]["$color"] : new SourceUtils.Color32(255, 255, 255, 255); RefractTint = vmt[VmtShader].ContainsKey("$refracttint") ? vmt[VmtShader]["$refracttint"] : new SourceUtils.Color32(255, 255, 255, 255); SurfaceProp = vmt[VmtShader].ContainsKey("$surfaceprop") ? vmt[VmtShader]["$surfaceprop"] : "grass"; Include = vmt[VmtShader].ContainsKey("include") ? vmt[VmtShader]["include"] : string.Empty; Alpha = vmt[VmtShader].ContainsKey("$alpha") ? vmt[VmtShader]["$alpha"] : 1.0f; RefractAmount = vmt[VmtShader].ContainsKey("$refractamount") ? vmt[VmtShader]["$refractamount"] : 0.2f; CompileSky = vmt[VmtShader].ContainsKey("%compilesky") ? vmt[VmtShader]["%compilesky"] : 0; break; } }
private VmtInfo GetVmtInfo(string vmtPath) { if (!_resourceLoader.ContainsFile(vmtPath)) { return(null); } using var fs = _resourceLoader.OpenFile(vmtPath); var vmt = ValveMaterialFile.FromStream(fs); var result = new VmtInfo(vmtPath, vmt); return(result); }
public static Material Get(ValveBspFile bsp, string path) { var vmt = bsp == null ? ValveMaterialFile.FromProvider(path, Program.Resources) : ValveMaterialFile.FromProvider(path, bsp.PakFile, Program.Resources); if (vmt == null) { return(null); } var mat = new Material(); AddMaterialProperties(mat, vmt, path, bsp); return(mat); }
private static void AddMaterialProperties(Material mat, ValveMaterialFile vmt, string vmtPath, ValveBspFile bsp) { var shader = vmt.Shaders.First(); var props = vmt[shader]; switch (shader.ToLower()) { case "lightmappedgeneric": case "lightmappedreflective": { mat.Shader = "SourceUtils.Shaders.LightmappedGeneric"; break; } case "lightmapped_4wayblend": // todo: temp case "worldvertextransition": { mat.Shader = "SourceUtils.Shaders.Lightmapped2WayBlend"; break; } case "worldtwotextureblend": // todo: temp { mat.Shader = "SourceUtils.Shaders.WorldTwoTextureBlend"; break; } case "vertexlitgeneric": { mat.Shader = "SourceUtils.Shaders.VertexLitGeneric"; break; } case "unlittwotexture": case "unlitgeneric": case "monitorscreen": case "sprite": { mat.Shader = "SourceUtils.Shaders.UnlitGeneric"; break; } case "water": { mat.Shader = "SourceUtils.Shaders.Water"; break; } case "splinerope": case "cable": { mat.Shader = "SourceUtils.Shaders.SplineRope"; break; } default: { mat.Shader = shader; break; } } foreach (var name in props.Keys) { var value = props[name]; switch (name.ToLower()) { case "$basetexture": mat.SetTextureUrl("basetexture", GetTextureUrl(value, vmtPath, bsp)); break; case "$hdrcompressedtexture": mat.SetTextureUrl("hdrcompressedtexture", GetTextureUrl(value, vmtPath, bsp)); break; case "$texture2": case "$basetexture2": mat.SetTextureUrl("basetexture2", GetTextureUrl(value, vmtPath, bsp)); break; case "$detail": mat.SetTextureUrl("detail", GetTextureUrl(value, vmtPath, bsp)); break; case "$blendmodulatetexture": mat.SetTextureUrl("blendModulateTexture", GetTextureUrl(value, vmtPath, bsp)); break; case "$normalmap": mat.SetTextureUrl("normalMap", GetTextureUrl(value, vmtPath, bsp)); break; case "$simpleoverlay": mat.SetTextureUrl("simpleOverlay", GetTextureUrl(value, vmtPath, bsp)); break; case "$nofog": mat.SetBoolean("fogEnabled", !value); break; case "$alphatest": if (!Program.BaseOptions.Untextured) { mat.SetBoolean("alphaTest", value); } break; case "$translucent": mat.SetBoolean("translucent", value); break; case "$refract": mat.SetBoolean("refract", value); break; case "$alpha": mat.SetNumber("alpha", value); break; case "$detailscale": mat.SetNumber("detailScale", value); break; case "$nocull": mat.SetBoolean("cullFace", !value); break; case "$notint": mat.SetBoolean("tint", !value); break; case "$blendtintbybasealpha": mat.SetBoolean("baseAlphaTint", value); break; case "$fogstart": mat.SetNumber("fogStart", value); break; case "$fogend": mat.SetNumber("fogEnd", value); break; case "$fogcolor": mat.SetColor("fogColor", new MaterialColor(value)); break; case "$lightmapwaterfog": mat.SetBoolean("fogLightmapped", value); break; case "$reflecttint": mat.SetColor("reflectTint", new MaterialColor(value)); break; case "$refracttint": mat.SetColor("refractTint", new MaterialColor(value)); break; case "$refractamount": mat.SetNumber("refractAmount", value); break; case "$selfillum": mat.SetBoolean("emission", value); break; case "$selfillumtint": mat.SetColor("emissionTint", new MaterialColor(value)); break; default: if (Program.BaseOptions.DebugMaterials) { mat.SetString($"{name}", value); } break; } } }
static FoamModel LoadMdl(string FilePath) { FilePath = FilePath.Substring(0, FilePath.Length - Path.GetExtension(FilePath).Length); StudioModelFile Mdl = StudioModelFile.FromProvider(FilePath + ".mdl", VFS); if (Mdl == null) { throw new FileNotFoundException("File not found", FilePath + ".mdl"); } ValveVertexFile Verts = ValveVertexFile.FromProvider(FilePath + ".vvd", VFS); ValveTriangleFile Tris = ValveTriangleFile.FromProvider(FilePath + ".dx90.vtx", Mdl, Verts, VFS); // Foam stuff List <FoamMaterial> FoamMaterials = new List <FoamMaterial>(); string[] TexNames = Mdl.TextureNames.ToArray(); for (int i = 0; i < Mdl.MaterialCount; i++) { string MatName = Mdl.GetMaterialName(i, VFS); string ShortMatName = Path.GetFileNameWithoutExtension(MatName); ValveMaterialFile VMF = ValveMaterialFile.FromProvider(MatName, VFS); FoamMaterials.Add(new FoamMaterial(ShortMatName, new FoamTexture[] { new FoamTexture(TexNames[i], FoamTextureType.Diffuse) })); } List <FoamMesh> FoamMeshes = new List <FoamMesh>(); List <FoamBone> FoamBones = new List <FoamBone>(); StudioModelFile.StudioBone[] Bones = Mdl.GetBones(); for (int i = 0; i < Bones.Length; i++) { string BoneName = Mdl.GetBoneName(i); FoamBones.Add(new FoamBone(BoneName, Bones[i].Parent, Matrix4x4.Identity)); } // BODIES for (int BodyPartIdx = 0; BodyPartIdx < Mdl.BodyPartCount; BodyPartIdx++) { StudioModelFile.StudioModel[] StudioModels = Mdl.GetModels(BodyPartIdx).ToArray(); // MODELS for (int ModelIdx = 0; ModelIdx < StudioModels.Length; ModelIdx++) { ref StudioModelFile.StudioModel StudioModel = ref StudioModels[ModelIdx]; StudioModelFile.StudioMesh[] StudioMeshes = Mdl.GetMeshes(ref StudioModel).ToArray(); // MESHES for (int MeshIdx = 0; MeshIdx < StudioMeshes.Length; MeshIdx++) { ref StudioModelFile.StudioMesh StudioMesh = ref StudioMeshes[MeshIdx]; StudioVertex[] StudioVerts = new StudioVertex[Tris.GetVertexCount(BodyPartIdx, ModelIdx, 0, MeshIdx)]; Tris.GetVertices(BodyPartIdx, ModelIdx, 0, MeshIdx, StudioVerts); int[] Indices = new int[Tris.GetIndexCount(BodyPartIdx, ModelIdx, 0, MeshIdx)]; Tris.GetIndices(BodyPartIdx, ModelIdx, 0, MeshIdx, Indices); // Foam converted List <FoamVertex3> FoamVerts = new List <FoamVertex3>(StudioVerts.Select(V => { // TODO: CCW nVector2 UV = new nVector2(V.TexCoordX, V.TexCoordY); return(new FoamVertex3(Conv(V.Position), UV, nVector2.Zero, Conv(V.Normal), nVector3.Zero, FoamColor.White)); })); List <FoamBoneInfo> FoamInfo = new List <FoamBoneInfo>(StudioVerts.Select(V => { FoamBoneInfo Info = new FoamBoneInfo(); Info.Bone1 = V.BoneWeights.Bone0; Info.Bone2 = V.BoneWeights.Bone1; Info.Bone3 = V.BoneWeights.Bone1; Info.Weight1 = V.BoneWeights.Weight0; Info.Weight2 = V.BoneWeights.Weight1; Info.Weight3 = V.BoneWeights.Weight2; return(Info); })); List <ushort> FoamInds = new List <ushort>(Indices.Select(I => (ushort)I)); if (ConvertToCCW) { FoamInds.Reverse(); } FoamMeshes.Add(new FoamMesh(FoamVerts.ToArray(), FoamInds.ToArray(), FoamInfo.ToArray(), StudioModel.Name + ";" + MeshIdx, StudioMesh.Material)); /*List<FoamVertex3> Vts = new List<FoamVertex3>(); * for (int i = 0; i < Indices.Length; i++) { * ref StudioVertex V = ref StudioVerts[Indices[i]]; * Vts.Add(new Vertex3(new Vector3(V.Position.X, V.Position.Y, V.Position.Z), new Vector2(V.TexCoordX, 1.0f - V.TexCoordY), Color.White)); * }*/ /*string MatName = MaterialNames[StudioMesh.Material]; * Material Mat = Engine.GetMaterial(MatName); * * if (Mat == Engine.GetMaterial("error")) { * Mat = ValveMaterial.CreateMaterial(MatName); * * if (Mat != Engine.GetMaterial("error")) * Engine.RegisterMaterial(Mat); * } * * libTechMesh Msh = new libTechMesh(Vts.ToArray(), Mat); * Msh.Name = StudioModel.Name; * Model.AddMesh(Msh);*/ } }
public VmtInfo(string vmtName, ValveMaterialFile vmt) { VmtName = vmtName; Parse(vmt); }
private Material VmtToMaterial(ResourceLoader resourceLoader, ValveMaterialFile vmt, string vmtPath) { string vmtShader = default; bool lightmapped = default; bool alphaTest = default; bool translucent = default; bool noCull = default; bool transition = default; string baseTex = default; string baseTex2 = default; string bumpMap = default; string surfaceProp = default; string include = default; float alpha = default; float refractAmount = default; int compileSky = default; SourceUtils.Color32 color = default; SourceUtils.Color32 refractTint = default; var e = vmt.Shaders.GetEnumerator(); while (e.MoveNext()) { vmtShader = e.Current.ToLower(); lightmapped = vmtShader == "lightmappedgeneric" || vmtShader == "worldvertextransition"; transition = vmtShader == "worldvertextransition"; alphaTest = vmt[vmtShader].ContainsKey("$alphatest") ? vmt[vmtShader]["$alphatest"] : false; translucent = vmt[vmtShader].ContainsKey("$translucent") ? vmt[vmtShader]["$translucent"] : false; noCull = vmt[vmtShader].ContainsKey("$nocull") ? vmt[vmtShader]["$nocull"] : false; baseTex = vmt[vmtShader].ContainsKey("$basetexture") ? vmt[vmtShader]["$basetexture"] : string.Empty; baseTex2 = vmt[vmtShader].ContainsKey("$basetexture2") ? vmt[vmtShader]["$basetexture2"] : string.Empty; bumpMap = vmt[vmtShader].ContainsKey("bumpmap") ? vmt[vmtShader]["bumpmap"] : string.Empty; color = vmt[vmtShader].ContainsKey("$color") ? vmt[vmtShader]["$color"] : new SourceUtils.Color32(255, 255, 255, 255); refractTint = vmt[vmtShader].ContainsKey("$refracttint") ? vmt[vmtShader]["$refracttint"] : new SourceUtils.Color32(255, 255, 255, 255); surfaceProp = vmt[vmtShader].ContainsKey("$surfaceprop") ? vmt[vmtShader]["$surfaceprop"] : "grass"; include = vmt[vmtShader].ContainsKey("include") ? vmt[vmtShader]["include"] : string.Empty; alpha = vmt[vmtShader].ContainsKey("$alpha") ? vmt[vmtShader]["$alpha"] : 1.0f; refractAmount = vmt[vmtShader].ContainsKey("$refractamount") ? vmt[vmtShader]["$refractamount"] : 0.2f; compileSky = vmt[vmtShader].ContainsKey("%compilesky") ? vmt[vmtShader]["%compilesky"] : 0; break; } if (!string.IsNullOrEmpty(include)) { using (var fs = resourceLoader.OpenFile(include)) { var includedVmt = ValveMaterialFile.FromStream(fs); return(VmtToMaterial(resourceLoader, includedVmt, include)); } } Object materialResource; Material result; materialResource = surfaceProp == "water" ? _options.WaterMaterial : _options.FaceMaterial; if (materialResource == null) { var shader = Shader.Find("BSP/Lightmapped") ?? Shader.Find("HDRP/Lit") ?? Shader.Find("URP/Lit") ?? Shader.Find("Lightweight Render Pipeline/Lit") ?? Shader.Find("Standard"); result = new Material(shader); } else { result = GameObject.Instantiate(materialResource) as Material; } //result.SetTexture("_MainTex", LoadTexture(resourceLoader, baseTex)); result.mainTexture = LoadTexture(resourceLoader, baseTex); result.SetFloat("_Smoothness", 0); result.SetFloat("_Metallic", .8f); result.name = vmtPath; if (!string.IsNullOrEmpty(bumpMap)) { result.SetTexture("_BumpMap", LoadTexture(resourceLoader, bumpMap)); } if (transition) { result.SetTexture("_MainTex2", LoadTexture(resourceLoader, baseTex2)); } if (translucent) { var baseColor = result.GetColor("_BaseColor"); baseColor.a = alpha; result.SetColor("_BaseColor", baseColor); result.SetFloat("_SurfaceType", 1); } return(result); }
public static JToken SerializeVmt(HttpListenerRequest request, ValveBspFile bsp, ValveMaterialFile vmt, string path) { // TODO: Proper patch shader support var firstShader = vmt.Shaders.FirstOrDefault(); var shader = firstShader; if (shader == null) { return(null); } var propArray = new JArray(); var vmtDir = Path.GetDirectoryName(path).Replace('\\', '/'); SerializeShaderProperties(request, bsp, vmt, ref shader, vmtDir, propArray); var variant = "Generic"; if (propArray.Any(x => (string)x["name"] == "translucent" && (bool)x["value"])) { variant = "Translucent"; } var shaderName = $"Lightmapped{variant}"; switch (shader.ToLower()) { case "lightmappedgeneric": shaderName = $"Lightmapped{variant}"; break; case "vertexlitgeneric": shaderName = $"VertexLit{variant}"; break; case "unlittwotexture": // TODO case "unlitgeneric": shaderName = $"Unlit{variant}"; break; case "worldvertextransition": shaderName = "Lightmapped2WayBlend"; break; case "water": shaderName = "Water"; AddBooleanProperty(propArray, "refract", true); break; } return(new JObject { { "shader", shaderName }, { "properties", propArray }, #if DEBUG { "debug", new JObject { { "shader", shader }, { "properties", new JArray(vmt[firstShader].PropertyNames.Select(x => new JArray(x, vmt[firstShader][x]))) } } } #endif }); }
public static JToken SerializeVmt(HttpListenerRequest request, ValveMaterialFile vmt, string path) { return(SerializeVmt(request, null, vmt, path)); }
private static void SerializeShaderProperties(HttpListenerRequest request, ValveBspFile bsp, ValveMaterialFile vmt, ref string shaderName, string vmtDir, JArray destArray) { if (!vmt.ContainsShader(shaderName)) { shaderName = vmt.Shaders.FirstOrDefault(); } var props = vmt[shaderName]; foreach (var name in props.PropertyNames) { switch (name.ToLower()) { case "include": { var includePath = props[name]; var includeDir = Path.GetDirectoryName(includePath); var includeVmt = OpenVmt(bsp, includePath); SerializeShaderProperties(request, bsp, includeVmt, ref shaderName, includeDir, destArray); break; } case "$basetexture": AddTexture2DProperty(destArray, "baseTexture", GetTextureUrl(request, bsp, props[name], vmtDir)); break; case "$texture2": case "$basetexture2": AddTexture2DProperty(destArray, "baseTexture2", GetTextureUrl(request, bsp, props[name], vmtDir)); break; case "$blendmodulatetexture": AddTexture2DProperty(destArray, "blendModulateTexture", GetTextureUrl(request, bsp, props[name], vmtDir)); break; case "$normalmap": AddTexture2DProperty(destArray, "normalMap", GetTextureUrl(request, bsp, props[name], vmtDir)); break; case "$simpleoverlay": AddTexture2DProperty(destArray, "simpleOverlay", GetTextureUrl(request, bsp, props[name], vmtDir)); break; case "$nofog": AddBooleanProperty(destArray, "noFog", props.GetBoolean(name)); break; case "$alphatest": AddBooleanProperty(destArray, "alphaTest", props.GetBoolean(name)); break; case "$translucent": AddBooleanProperty(destArray, "translucent", props.GetBoolean(name)); break; case "$refract": AddBooleanProperty(destArray, "refract", props.GetBoolean(name)); break; case "$alpha": AddNumberProperty(destArray, "alpha", props.GetSingle(name)); break; case "$nocull": AddBooleanProperty(destArray, "noCull", props.GetBoolean(name)); break; case "$notint": AddBooleanProperty(destArray, "noTint", props.GetBoolean(name)); break; case "$blendtintbybasealpha": AddBooleanProperty(destArray, "baseAlphaTint", props.GetBoolean(name)); break; case "$fogstart": AddNumberProperty(destArray, "fogStart", props.GetSingle(name)); break; case "$fogend": AddNumberProperty(destArray, "fogEnd", props.GetSingle(name)); break; case "$fogcolor": AddColorProperty(destArray, "fogColor", props.GetColor(name)); break; case "$reflecttint": AddColorProperty(destArray, "reflectTint", props.GetColor(name)); break; case "$refractamount": AddNumberProperty(destArray, "refractAmount", props.GetSingle(name)); break; } } }