/// <summary> /// Creates a new material from the specified descriptor. /// </summary> /// <param name="device"></param> /// <param name="descriptor">The material descriptor.</param> /// <returns>An instance of a <see cref="Material"/>.</returns> /// <exception cref="System.ArgumentNullException">descriptor</exception> /// <exception cref="System.InvalidOperationException">If an error occurs with the material description</exception> public static Material New(GraphicsDevice device, MaterialDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException("descriptor"); } var context = new MaterialGeneratorContext(new Material()); var result = MaterialGenerator.Generate(descriptor, context, string.Format("{0}:RuntimeMaterial", descriptor.MaterialId)); if (result.HasErrors) { throw new InvalidOperationException(string.Format("Error when creating the material [{0}]", result.ToText())); } var material = result.Material; // TODO GRAPHICS REFACTOR //var blendState = material.Parameters.GetResourceSlow(Graphics.Effect.BlendStateKey); //if (blendState != null && blendState.GraphicsDevice == null) //{ // var newState = BlendState.New(device, blendState.Description); // material.Parameters.SetResourceSlow(Effect.BlendStateKey, newState); //} // TODO: Add other states? return(material); }
private void CreateChain <TShape, TShapeDescriptor>(MaterialDescriptor materialDescriptor, TShapeDescriptor shapeDescriptor, DistanceRangeJointDescriptor constraintDescriptor, int count, float space, int staticBall, float xOffset, float yOffset, float zOffset) where TShapeDescriptor : struct, IDescriptor where TShape : IShape, IDescriptible <TShapeDescriptor> { var bodies = new IRigidBody[count]; var rigidBodyDescriptor = new RigidBodyDescriptor(MotionType.Static, Matrices.I, true); for (int i = 0; i < count; i++) { rigidBodyDescriptor.Pose = Matrices.Translate(xOffset + (space + i * space - ((count - 1) * space / 2)), yOffset, zOffset); bodies[i] = _simulator.ActorsFactory.Create <IRigidBody, RigidBodyDescriptor>(rigidBodyDescriptor); bodies[i].UserData = String.Format("chain {0}", i); var fixture = bodies[i].FixtureFactory.Create <ISimpleFixture, FixtureDescriptor>(new FixtureDescriptor(Matrices.I)); fixture.ShapeFactory.Create <TShape, TShapeDescriptor>(shapeDescriptor); fixture.MaterialFactory.Create <IMaterial, MaterialDescriptor>(materialDescriptor); if (i > 0) { constraintDescriptor.RigidBodyA = bodies[i - 1]; constraintDescriptor.RigidBodyB = bodies[i]; _simulator.ConstraintsFactory.Create <IDistanceRangeJoint, DistanceRangeJointDescriptor>( constraintDescriptor); } else { rigidBodyDescriptor.MotionType = MotionType.Static; } } }
protected override void OnEntityComponentAdding(Entity entity, [NotNull] DecalComponent component, [NotNull] AssociatedData data) { var model = new Model(); // We create the cube via the *ProceduralModel class rather than GeometricPrimitive.*.New // because there are additional vertext data that gets created through this which are required by the Material var procCube = new CubeProceduralModel(); // Set up a new material with our decal shader. var shader = new ComputeShaderClassColor { MixinReference = "DecalShader" // This is referring to our shader at Effects\DecalShader.xksl }; var materialDescription = new MaterialDescriptor { Attributes = { DiffuseModel = new MaterialDiffuseLambertModelFeature(), Diffuse = new MaterialDiffuseMapFeature(shader), Transparency = new MaterialTransparencyBlendFeature(), CullMode = CullMode.Back, } }; procCube.MaterialInstance.IsShadowCaster = false; procCube.Generate(Services, model); var material = Material.New(_graphicsDevice, materialDescription); UpdateMaterialParameters(component, data.TransformComponent, material); data.Material = material; data.Model = model; }
public static void SetSimpleScene(ISimulator simulator) { #region Create a box //create a rigidBody var boxRigidBodyDescriptor = new RigidBodyDescriptor(MotionType.Dynamic, Matrices.Translate(0, 10, 0)); var boxRigidBody = simulator.ActorsFactory.CreateRigidBody(boxRigidBodyDescriptor); //create a simple fixture for the rigidBody var fixtureDescriptor = new FixtureDescriptor(Matrices.I); var simpleFixture = boxRigidBody.FixtureFactory.CreateSimpleFixture(fixtureDescriptor); //define the shape for the simple fixture var boxShapeDescriptor = new BoxShapeDescriptor(3, 3, 3, _motionColor); simpleFixture.ShapeFactory.CreateBox(boxShapeDescriptor); //define the material for the simple fixture var materialDescriptor = new MaterialDescriptor(friction: 0.5f, restitution: 0.6f); simpleFixture.MaterialFactory.CreateMaterial(materialDescriptor); boxRigidBody.MassFrame.UpdateFromShape(); #endregion #region Create a plane for the ground var groundRigidBody = simulator.ActorsFactory.CreateRigidBody(new RigidBodyDescriptor(MotionType.Static, Matrices.I)); var groundSimpleFixture = groundRigidBody.FixtureFactory.CreateSimpleFixture(new FixtureDescriptor(Matrices.I)); groundSimpleFixture.ShapeFactory.CreatePlane(new PlaneShapeDescriptor(Vectors.YAxis, 0, _groundColor)); groundSimpleFixture.MaterialFactory.CreateMaterial(materialDescriptor); #endregion }
/// <summary> /// VMRC_materials_mtoon の場合にマテリアル生成情報を作成する /// </summary> public static bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc) { var m = data.GLTF.materials[i]; if (!UniGLTF.Extensions.VRMC_materials_mtoon.GltfDeserializer.TryGet(m.extensions, out UniGLTF.Extensions.VRMC_materials_mtoon.VRMC_materials_mtoon mtoon)) { // Fallback to glTF, when MToon extension does not exist. matDesc = default; return(false); } // use material.name, because material name may renamed in GltfParser. matDesc = new MaterialDescriptor( m.name, MToon10Meta.UnityShaderName, null, Vrm10MToonTextureImporter.EnumerateAllTextures(data, m, mtoon).ToDictionary(tuple => tuple.key, tuple => tuple.Item2.Item2), TryGetAllFloats(m, mtoon).ToDictionary(tuple => tuple.key, tuple => tuple.value), TryGetAllColors(m, mtoon).ToDictionary(tuple => tuple.key, tuple => tuple.value), TryGetAllFloatArrays(m, mtoon).ToDictionary(tuple => tuple.key, tuple => tuple.value), new Action <Material>[] { material => { // Set hidden properties, keywords from float properties. new MToonValidator(material).Validate(); } }); return(true); }
public static Material Create(GraphicsDevice device, Color color, bool emissive = true) { var desc = new MaterialDescriptor(); if (emissive) { desc.Attributes.Emissive = new MaterialEmissiveMapFeature(new ComputeColor() { Key = GizmoColorKey }); } else { desc.Attributes.Diffuse = new MaterialDiffuseMapFeature(new ComputeColor() { Key = GizmoColorKey }); desc.Attributes.DiffuseModel = new MaterialDiffuseLambertModelFeature(); } var material = Material.New(device, desc); // set the color to the material UpdateColor(device, material, color); // set the transparency property to the material if necessary if (color.A < Byte.MaxValue) { material.Passes[0].HasTransparency = true; // TODO GRAPHICS REFACTOR //material.Parameters.SetResourceSlow(Graphics.Effect.BlendStateKey, device.BlendStates.NonPremultiplied); } return(material); }
IMaterial IFactoryOf <IMaterial, MaterialDescriptor> .Create(MaterialDescriptor descriptor) { var material = new Material(descriptor); SetMaterial(material); return(material); }
public void TestSimpleNoLayer() { // - LayerRoot: SM0 (Shading Model 0) var context = new MaterialGeneratorContextExtended(); var materialDesc = new MaterialDescriptor { Attributes = { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.Red)), DiffuseModel = new MaterialDiffuseLambertModelFeature() } }; var result = MaterialGenerator.Generate(materialDesc, context, "simple_diffuse"); Assert.False(result.HasErrors); var materialPass = result.Material.Passes[0]; Assert.Null(materialPass.Parameters.Get(MaterialKeys.VertexStageSurfaceShaders)); Assert.Null(materialPass.Parameters.Get(MaterialKeys.DomainStageSurfaceShaders)); // Check that the color is correctly store in the shader parameters Assert.Equal(new Color4(Color.Red), materialPass.Parameters.Get(MaterialKeys.DiffuseValue)); var pixelShaders = materialPass.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders); var expected = @"!ShaderMixinSource Mixins: - !ShaderClassSource ClassName: MaterialSurfaceArray Compositions: layers: !ShaderArraySource Values:" // This is part coming from MaterialDiffuseMapFeature + @" - !ShaderMixinSource Mixins: - !ShaderClassSource ClassName: MaterialSurfaceDiffuse Compositions: diffuseMap: !ShaderClassSource ClassName: ComputeColorConstantColorLink GenericArguments: [Material.DiffuseValue]" // This is part coming from the shading model (MaterialDiffuseLambertModelFeature) + @" - !ShaderMixinSource Mixins: - !ShaderClassSource ClassName: MaterialSurfaceLightingAndShading Compositions: surfaces: !ShaderArraySource Values: - !ShaderClassSource ClassName: MaterialSurfaceShadingDiffuseLambert GenericArguments: [false]"; AssertShaderSourceEqual(expected, pixelShaders); }
public static List <Material> LoadMaterials(SharpGLTF.Schema2.ModelRoot root, GraphicsDevice device) { var result = new List <Material>(); foreach (var mat in root.LogicalMaterials) { var material = new MaterialDescriptor { Attributes = new MaterialAttributes() }; foreach (var chan in mat.Channels) { if (chan.Texture != null) { var imgBuf = chan.Texture.PrimaryImage.Content.Content.ToArray(); var imgPtr = new DataPointer(GCHandle.Alloc(imgBuf, GCHandleType.Pinned).AddrOfPinnedObject(), imgBuf.Length); var image = Stride.Graphics.Image.Load(imgPtr); var texture = Texture.New(device, image, TextureFlags.None); switch (chan.Key) { case "BaseColor": var vt = new ComputeTextureColor(texture) { AddressModeU = TextureAddressMode.Wrap, AddressModeV = TextureAddressMode.Wrap, TexcoordIndex = TextureCoordinate.Texcoord0 }; material.Attributes.Diffuse = new MaterialDiffuseMapFeature(vt); material.Attributes.DiffuseModel = new MaterialDiffuseLambertModelFeature(); break; case "MetallicRoughness": material.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeTextureScalar(texture, TextureCoordinate.Texcoord0, Vector2.One, Vector2.Zero)); break; case "Normal": material.Attributes.Surface = new MaterialNormalMapFeature(new ComputeTextureColor(texture)); break; case "Occlusion": material.Attributes.Occlusion = new MaterialOcclusionMapFeature(); break; case "Emissive": material.Attributes.Emissive = new MaterialEmissiveMapFeature(new ComputeTextureColor(texture)); break; } } } material.Attributes.CullMode = CullMode.Back; result.Add(Material.New(device, material)); } return(result); }
public Material(RigidBody rigidBody, PX.Material wrappedMaterial, MaterialDescriptor descriptor) { wrappedMaterial.DynamicFriction = descriptor.Friction; wrappedMaterial.StaticFriction = descriptor.Friction; wrappedMaterial.Restitution = descriptor.Restitution; _wrappedMaterial = wrappedMaterial; Configurator = new BaseConfigurator <IMaterial>(); }
private void CreateGroud(MaterialDescriptor materialDescriptor) { var groundRigidBodyDescriptor = new RigidBodyDescriptor(MotionType.Static, Matrices.I, true); var ground = _simulator.ActorsFactory.CreateRigidBody(groundRigidBodyDescriptor); var groundFixture = ground.FixtureFactory.CreateSimpleFixture(new FixtureDescriptor(Matrices.I)); groundFixture.ShapeFactory.CreatePlane(new PlaneShapeDescriptor(new Vector3(0, 1, 0), 0)); groundFixture.MaterialFactory.CreateMaterial(materialDescriptor); }
public TrailModel(Vector3 trailPosOffset, float width, int length, MaterialDescriptor material, float whitestep, string trailOrigin = "") { TrailPosOffset = trailPosOffset; Width = width; Length = length; Material = material; Whitestep = whitestep; TrailOrigin = trailOrigin; }
public SimpleFixtureMaterialFactory(SimpleFixture simpleFixture) { _simpleFixture = simpleFixture; var defatulMaterialDescriptor = new MaterialDescriptor(); defatulMaterialDescriptor.ToDefault(); WrappedMaterial = simpleFixture._rigidBody.WrappedActor.Scene.CreateMaterial(new MaterialDescription()); Element = new Material(simpleFixture._rigidBody, WrappedMaterial, defatulMaterialDescriptor); }
public static Task <Material> CreateAsync(GraphicsDevice device, MaterialDescriptor descriptor, IContentManager contentManager) { Material material = new Material { Descriptor = descriptor }; MaterialGeneratorContext context = new MaterialGeneratorContext(device, material, contentManager); return(MaterialGenerator.GenerateAsync(descriptor, context)); }
SimpleFixtureMaterialFactory(SimpleFixture simpleFixture) { _simpleFixture = simpleFixture; //create a default material var descriptor = new MaterialDescriptor(); descriptor.ToDefault(); this.CreateMaterial(descriptor); }
public MaterialDescriptor GetMaterial(int primitiveID) { var material = new MaterialDescriptor { Attributes = new MaterialAttributes() }; foreach (var chan in CurrentMesh.Primitives[primitiveID].Material.Channels) { if (chan.Texture != null) { using var fs = new FileStream(chan.Texture.PrimaryImage.Content.SourcePath, FileMode.Open); var image = Stride.Graphics.Image.Load(fs, true); var texture = Texture.New(Device, image, TextureFlags.None); switch (chan.Key) { case "BaseColor": var vt = new ComputeTextureColor(texture) { AddressModeU = TextureAddressMode.Wrap, AddressModeV = TextureAddressMode.Wrap, TexcoordIndex = TextureCoordinate.Texcoord0 }; material.Attributes.Diffuse = new MaterialDiffuseMapFeature(vt); material.Attributes.DiffuseModel = new MaterialDiffuseLambertModelFeature(); //material.Attributes.DiffuseModel = new MaterialDiffuseCelShadingModelFeature(); //Logger.Info("Added diffuse material"); break; case "MetallicRoughness": material.Attributes.MicroSurface = new MaterialGlossinessMapFeature(new ComputeTextureScalar(texture, TextureCoordinate.Texcoord0, Vector2.One, Vector2.Zero)); break; case "Normal": material.Attributes.Surface = new MaterialNormalMapFeature(new ComputeTextureColor(texture)); break; case "Occlusion": material.Attributes.Occlusion = new MaterialOcclusionMapFeature(); break; case "Emissive": material.Attributes.Emissive = new MaterialEmissiveMapFeature(new ComputeTextureColor(texture)); break; } } } material.Attributes.CullMode = CullMode.Back; return(material); }
private static Material CreateMaterial(MaterialDescriptor materialDesc, MaterialGeneratorContextExtended context) { var result = MaterialGenerator.Generate(materialDesc, context, "test_material"); if (result.HasErrors) { throw new InvalidOperationException($"Error compiling material:\n{result.ToText()}"); } return(result.Material); }
public async void Show(MaterialDescriptor materialDescriptor) { _ = Create(true); _cachedTransform.localScale = Vector3.zero; _materialDropDown.transform.parent.gameObject.SetActive(false); SetMaterial(materialDescriptor.Material); await Task.Delay(100); await AnimateIn(); }
public async override Task CreateAssetAsync(Material material, IServiceProvider services) { IContentManager contentManager = services.GetRequiredService <IContentManager>(); ShaderContentManager shaderContentManager = services.GetRequiredService <ShaderContentManager>(); GraphicsDevice device = services.GetRequiredService <GraphicsDevice>(); if (device is null) { throw new InvalidOperationException(); } MaterialDescriptor descriptor; if (string.IsNullOrEmpty(Source)) { descriptor = new MaterialDescriptor { Id = Id, Attributes = Attributes }; } else { string path = Source; int index = GetIndex(ref path); string extension = Path.GetExtension(path); if (extension == ".glb") { using Stream stream = await contentManager.RootFolder.OpenStreamForReadAsync(path); GltfModelLoader modelLoader = await GltfModelLoader.CreateAsync(device, stream); MaterialAttributes materialAttributes = await modelLoader.GetMaterialAttributesAsync(index); // TODO: Combine material attributes. descriptor = new MaterialDescriptor { Id = Id, Attributes = materialAttributes }; } else { throw new NotSupportedException("This file type is not supported."); } } material.Passes.Clear(); material.Descriptor = descriptor; MaterialGeneratorContext context = new MaterialGeneratorContext(device, material, shaderContentManager); await MaterialGenerator.GenerateAsync(descriptor, context); }
public static Material RedMaterial(GraphicsDevice device) { var descriptor = new MaterialDescriptor { Attributes = new MaterialAttributes { Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(Color.Red)), DiffuseModel = new MaterialDiffuseLambertModelFeature(), CullMode = CullMode.Back } }; return(Material.New(device, descriptor)); }
private static void SetGround(ISimulator simulator, MaterialDescriptor materialDescriptor) { var groundRigidBody = simulator.ActorsFactory.CreateRigidBody(new RigidBodyDescriptor(MotionType.Static, Matrices.I)); var groundSimpleFixture = groundRigidBody.FixtureFactory.CreateSimpleFixture(new FixtureDescriptor(Matrices.I)); groundSimpleFixture.ShapeFactory.CreatePlane(new PlaneShapeDescriptor(new Vector3(0, 1, 0), 0)); groundSimpleFixture.MaterialFactory.CreateMaterial(materialDescriptor); if (groundRigidBody.UserData == null) { groundRigidBody.UserData = _groundColor; } }
private Material CreateSolidMaterial(Color color) { var descriptor = new MaterialDescriptor(); var computeColor = new ComputeColor(color); var transparency = new MaterialTransparencyBlendFeature(); transparency.Tint = new ComputeColor(Color.White); transparency.Alpha = new ComputeFloat(0.25f); descriptor.Attributes.Emissive = new MaterialEmissiveMapFeature(computeColor); descriptor.Attributes.Transparency = transparency; return(Material.New(graphicsDevice, descriptor)); }
/// <summary> /// Creates a new material from the specified descriptor. /// </summary> /// <param name="descriptor">The material descriptor.</param> /// <returns>An instance of a <see cref="Material"/>.</returns> /// <exception cref="System.ArgumentNullException">descriptor</exception> /// <exception cref="System.InvalidOperationException">If an error occurs with the material description</exception> public static Material New(MaterialDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException("descriptor"); } var context = new MaterialGeneratorContext(new Material()); var result = MaterialGenerator.Generate(descriptor, context); if (result.HasErrors) { throw new InvalidOperationException(string.Format("Error when creating the material [{0}]", result.ToText())); } return(result.Material); }
public CustomMaterial(string fileName) { FileName = fileName; if (fileName != "DefaultMaterials") { try { AssetBundle = AssetBundle.LoadFromFile(Path.Combine(Plugin.PluginAssetPath, fileName)); GameObject = AssetBundle.LoadAsset <GameObject>("Assets/_CustomMaterial.prefab"); Descriptor = GameObject.GetComponent <MaterialDescriptor>(); MaterialRenderer = MaterialUtils.GetGameObjectRenderer(GameObject, "pixie"); MaterialMeshFilter = MeshUtils.GetGameObjectMeshFilter(GameObject, "pixie"); } catch (Exception ex) { Logger.log.Warn($"Something went wrong getting the AssetBundle for '{fileName}'!"); Logger.log.Warn(ex); Descriptor = new MaterialDescriptor() { MaterialName = "Invalid Wall (Delete it!)", AuthorName = fileName, Icon = Utils.GetErrorIcon() }; ErrorMessage = $"File: '{fileName}'" + "\n\nThis file failed to load." + "\n\nThis may have been caused by having duplicated files," + " another wall with the same name already exists or that the custom wall is simply just broken." + "\n\nThe best thing is probably just to delete it!"; FileName = "DefaultMaterials"; } } else { Descriptor = new MaterialDescriptor { MaterialName = "Default", AuthorName = "Beat Saber", Description = "This is the default walls. (No preview available)", Icon = Utils.GetDefaultIcon() }; } }
public async override Task <object> CreateAssetAsync(IServiceProvider services) { IContentManager contentManager = services.GetRequiredService <IContentManager>(); GraphicsDevice device = services.GetRequiredService <GraphicsDevice>(); if (device is null) { throw new InvalidOperationException(); } MaterialDescriptor descriptor; if (string.IsNullOrEmpty(Source)) { descriptor = new MaterialDescriptor { Id = Id, Attributes = Attributes }; } else { string path = Source; int index = GetIndex(ref path); string extension = Path.GetExtension(path); if (extension == ".glb") { using Stream stream = await contentManager.FileProvider.OpenStreamAsync(path, FileMode.Open, FileAccess.Read); GltfModelLoader modelLoader = await GltfModelLoader.CreateAsync(device, stream); MaterialAttributes materialAttributes = await modelLoader.GetMaterialAttributesAsync(index); // TODO: Combine material attributes. descriptor = new MaterialDescriptor { Id = Id, Attributes = materialAttributes }; } else { throw new NotSupportedException("This file type is not supported."); } } return(await Material.CreateAsync(device, descriptor, contentManager)); }
public static Material CreateDebugMaterial(Color color, bool emissive, GraphicsDevice device) { var descriptor = new MaterialDescriptor(); var computeColor = new ComputeColor(color); if (emissive) { descriptor.Attributes.Emissive = new MaterialEmissiveMapFeature(computeColor); } else { descriptor.Attributes.Diffuse = new MaterialDiffuseMapFeature(computeColor); descriptor.Attributes.DiffuseModel = new MaterialDiffuseLambertModelFeature(); } return(Material.New(device, descriptor)); }
private void renderedControl1_InitializeRender(object sender, RenderEventArgs e) { _render = e.Render; #region Creating the physics scene //creating the simulation _simulator = new DigitalRuneSimulator(); //definig a material var materialDescriptor = new MaterialDescriptor(0.5f, 0.7f); //creating the ground CreateGroud(materialDescriptor); //creating a Tower for (int i = 0; i < 3; i++) { CreateTower <IBoxShape, BoxShapeDescriptor>(materialDescriptor, new BoxShapeDescriptor(1, 3, 1), xCount: 1, yCount: 3, zCount: 1, xSpace: 1, ySpace: 3, zSpace: 1, xOffset: 3 * i, yOffset: 10 + 9 / 2f, zOffset: 0); } ////creating a chain //var constraintDescriptor = new DistanceRangeJointDescriptor(new Vector3(0),new Vector3(0),1f,1.1f,false); //CreateChain<ISphereShape, SphereShapeDescriptor>(materialDescriptor, new SphereShapeDescriptor(0.5f), constraintDescriptor, // count: 8, space: 1.1f, staticBall: 7, // xOffset:-10, yOffset: 9,zOffset: 0); //creating a composite CreateComposite(); //playing with the mass // CreateMassTesting(-5,1, 1); //CreateMassTesting(0,1, 10); //CreateMassTesting(5,2, 100000); #endregion //initializing the timer _previousTickCount = Environment.TickCount; _startTickCount = _previousTickCount; }
public TrailModel( Vector3 trailPosOffset, float width, int length, MaterialDescriptor material, float whitestep, TextureWrapMode?originalTextureWrapMode, string trailOrigin = "") { TrailPosOffset = trailPosOffset; Width = width; Length = length; OriginalLength = length; Material = material; Whitestep = whitestep; OriginalTextureWrapMode = originalTextureWrapMode; TrailOrigin = trailOrigin; }
public async void Show(MaterialDescriptor materialDescriptor) { if (materialDescriptor == null || materialDescriptor.Material == null) { Debug.LogError("Material was null in MaterialEditor"); return; } _ = Create(false); _cachedTransform.localScale = Vector3.zero; _materialDropDown.transform.parent.gameObject.SetActive(false); SetMaterial(materialDescriptor.Material); await Task.Delay(100); await AnimateIn(); }
public async Task FromJson(JObject obj, Serializer serializer) { obj.Populate(this); if (!string.IsNullOrEmpty(TrailOrigin)) { await LoadFromTrailOrigin(serializer, TrailOrigin); } if (obj.SelectToken("Material") is { } materialToken) { if (Material is null) { Material = new MaterialDescriptor(null); } await serializer.LoadMaterial((JObject)materialToken, Material.Material); } }