private PhysicallyBasedMaterial CreatePbrMaterial(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures) { PhysicallyBasedMaterial physicallyBasedMaterial; if (_dxMaterials.TryGetValue(assimpMaterial, out physicallyBasedMaterial)) // Is PhysicallyBasedMaterial already creared { Log($" Material: {assimpMaterial.Name ?? ""} (already defined)"); return(physicallyBasedMaterial); } //if (!assimpMaterial.HasTextureDiffuse) //{ // Log($" Material {assimpMaterial.Name ?? ""} does not define a diffuse texture"); // return null; //} Log($" Material {assimpMaterial.Name ?? ""}:"); physicallyBasedMaterial = new PhysicallyBasedMaterial(); // When materials has diffuse texture defined, then we also try to find other PBR textures if (assimpMaterial.HasTextureDiffuse) { AddPBRTextures(assimpMaterial, filePath, customTexturesFolder, useStrictFileNameMatch, supportDDSTextures, physicallyBasedMaterial); } // Set BaseColor based on the DiffuseColor if (assimpMaterial.HasColorDiffuse) { physicallyBasedMaterial.BaseColor = new Color4(assimpMaterial.ColorDiffuse.R, assimpMaterial.ColorDiffuse.G, assimpMaterial.ColorDiffuse.B, assimpMaterial.ColorDiffuse.A); } // When there is no Metalness texture defined, then set Metalness to zero - use plastic if (!physicallyBasedMaterial.HasTextureMap(TextureMapTypes.Metalness)) { physicallyBasedMaterial.Metalness = 0; } _disposables.Add(physicallyBasedMaterial); _dxMaterials.Add(assimpMaterial, physicallyBasedMaterial); AddTextureMapSelections(assimpMaterial.Name, physicallyBasedMaterial); return(physicallyBasedMaterial); }
public TextureMapSelectionControl(IMultiMapMaterial material, TextureMapTypes textureMapType, string baseFolder = null) { Material = material; _physicallyBasedMaterial = material as PhysicallyBasedMaterial; TextureMapType = textureMapType; if (baseFolder != null && !baseFolder.EndsWith("\\") && !baseFolder.EndsWith("/")) { baseFolder += '\\'; } BaseFolder = baseFolder; _textureMapInfo = Material.TextureMaps.FirstOrDefault(m => m.MapType == TextureMapType); InitializeComponent(); ShowTextureTextBox = true; if (_physicallyBasedMaterial != null) { ShowFilter = textureMapType == TextureMapTypes.Metalness || textureMapType == TextureMapTypes.Glossiness || textureMapType == TextureMapTypes.Roughness || textureMapType == TextureMapTypes.MetalnessRoughness || textureMapType == TextureMapTypes.AmbientOcclusion; ShowMask = textureMapType == TextureMapTypes.Albedo || textureMapType == TextureMapTypes.BaseColor || textureMapType == TextureMapTypes.DiffuseColor; if (textureMapType == TextureMapTypes.Metalness || textureMapType == TextureMapTypes.MetalnessRoughness) { CurrentFilterValue = _physicallyBasedMaterial.Metalness; } if (textureMapType == TextureMapTypes.Roughness || textureMapType == TextureMapTypes.MetalnessRoughness) { CurrentFilterValue = _physicallyBasedMaterial.Roughness; } if (ShowMask) { CurrentMaskColor = _physicallyBasedMaterial.BaseColor.ToWpfColor(); } } else { ShowFilter = false; ShowMask = false; } // To add support for drop into TextBox, we need to use PreviewDrop and PreviewDragOver events in DragAndDropHelper //var dragAndDropHelper = new DragAndDropHelper(FileNameTextBox, ".*"); //dragAndDropHelper.FileDroped += delegate (object sender, FileDropedEventArgs e) //{ // FileNameTextBox.Text = e.FileName; // MasterCheckBox.IsChecked = true; // LoadCurrentTexture(); //}; MapTypeTextBlock.Text = textureMapType.ToString(); if (_textureMapInfo == null) { FileNameTextBox.Text = ""; TextureCheckBox.IsChecked = false; } else { if (BaseFolder != null && _textureMapInfo.TextureResourceName.StartsWith(BaseFolder)) { FileNameTextBox.Text = _textureMapInfo.TextureResourceName.Substring(BaseFolder.Length); } else { FileNameTextBox.Text = _textureMapInfo.TextureResourceName; } TextureCheckBox.IsChecked = true; } UpdateMaskHeadingTextBlock(); }
private PhysicallyBasedMaterial CreatePbrMaterial(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures) { PhysicallyBasedMaterial physicallyBasedMaterial; if (_dxMaterials.TryGetValue(assimpMaterial, out physicallyBasedMaterial)) { Log($" Material: {assimpMaterial.Name ?? ""} (already defined)"); return(physicallyBasedMaterial); } if (!assimpMaterial.HasTextureDiffuse) { Log($" Material {assimpMaterial.Name ?? ""} does not define a diffuse texture"); return(null); } Log($" Material {assimpMaterial.Name ?? ""}:"); //PhysicallyBasedMaterial physicallyBasedMaterial; string diffuseTextureFileName = assimpMaterial.TextureDiffuse.FilePath; if (!string.IsNullOrEmpty(customTexturesFolder)) { diffuseTextureFileName = System.IO.Path.Combine(customTexturesFolder, System.IO.Path.GetFileName(diffuseTextureFileName)); } else if (!System.IO.Path.IsPathRooted(diffuseTextureFileName)) { diffuseTextureFileName = System.IO.Path.Combine(filePath, diffuseTextureFileName); } string folderName = System.IO.Path.GetDirectoryName(diffuseTextureFileName); if (!System.IO.Directory.Exists(folderName)) { Log($" Folder for diffuse texture does not exist: {folderName ?? ""}:"); return(null); } if (_folderImageFiles == null) { _folderImageFiles = new Dictionary <string, string[]>(); } string[] allFilesInFolder; if (!_folderImageFiles.TryGetValue(folderName, out allFilesInFolder)) { allFilesInFolder = System.IO.Directory.GetFiles(folderName, "*.*", SearchOption.TopDirectoryOnly); _folderImageFiles.Add(folderName, allFilesInFolder); } string fileNameWithoutKnownSuffix = KnownTextureFiles.GetFileNameWithoutKnownSuffix(diffuseTextureFileName); // Get material files that start with the diffuse texture file name without a suffix List <string> materialFiles; if (useStrictFileNameMatch) { materialFiles = allFilesInFolder.Where(f => fileNameWithoutKnownSuffix == KnownTextureFiles.GetFileNameWithoutKnownSuffix(f)).ToList(); } else { materialFiles = allFilesInFolder.Where(f => f.IndexOf(fileNameWithoutKnownSuffix, 0, StringComparison.OrdinalIgnoreCase) != -1).ToList(); } _textureFiles.Clear(); if (materialFiles.Count == 0) { Log($" Folder ({folderName}) for {assimpMaterial.Name ?? ""} material does not define any texture files"); return(null); } else { bool hasDiffuseTexture = false; foreach (var materialFile in materialFiles) { if (!TextureLoader.IsSupportedFile(materialFile, supportDDSTextures)) // Skip unsupported files { continue; } var textureMapType = KnownTextureFiles.GetTextureType(materialFile); if (textureMapType == TextureMapTypes.Unknown) { if (!hasDiffuseTexture) { textureMapType = TextureMapTypes.DiffuseColor; // First unknown file type is considered to be diffuse texture file } else { continue; // Unknown file type } } bool isDiffuseTexture = (textureMapType == TextureMapTypes.DiffuseColor || textureMapType == TextureMapTypes.Albedo || textureMapType == TextureMapTypes.BaseColor); string existingTextureFileName; if (_textureFiles.TryGetValue(textureMapType, out existingTextureFileName)) { // Map for this texture type already exist var existingFileExtension = System.IO.Path.GetExtension(existingTextureFileName); if (existingFileExtension != null && existingFileExtension.Equals(".dds", StringComparison.OrdinalIgnoreCase)) { continue; // DDS texture already found for this texture type - we will use existing dds texture } } hasDiffuseTexture |= isDiffuseTexture; _textureFiles.Add(textureMapType, materialFile); Log(" " + textureMapType + ": " + System.IO.Path.GetFileName(materialFile)); } if (_textureFiles.Count > 0) { physicallyBasedMaterial = new PhysicallyBasedMaterial(); foreach (var oneTextureFile in _textureFiles) { var textureType = oneTextureFile.Key; var oneFileName = oneTextureFile.Value; ShaderResourceView shaderResourceView; if (!_texturesCache.TryGetValue(oneFileName, out shaderResourceView)) { var convertTo32bppPRGBA = (textureType == TextureMapTypes.BaseColor || textureType == TextureMapTypes.Albedo || textureType == TextureMapTypes.DiffuseColor); shaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, oneFileName, loadDdsIfPresent: false, convertTo32bppPRGBA: convertTo32bppPRGBA); physicallyBasedMaterial.TextureMaps.Add(new TextureMapInfo((Ab3d.DirectX.Materials.TextureMapTypes)textureType, shaderResourceView, null, oneFileName)); _texturesCache.Add(oneFileName, shaderResourceView); } } _dxMaterials.Add(assimpMaterial, physicallyBasedMaterial); _disposables.Add(physicallyBasedMaterial); } } return(physicallyBasedMaterial); }
private void AddPBRTextures(AssimpMaterial assimpMaterial, string filePath, string customTexturesFolder, bool useStrictFileNameMatch, bool supportDDSTextures, PhysicallyBasedMaterial physicallyBasedMaterial) { //PhysicallyBasedMaterial physicallyBasedMaterial; string diffuseTextureFileName = assimpMaterial.TextureDiffuse.FilePath; if (!string.IsNullOrEmpty(customTexturesFolder)) { diffuseTextureFileName = System.IO.Path.Combine(customTexturesFolder, System.IO.Path.GetFileName(diffuseTextureFileName)); } else if (!System.IO.Path.IsPathRooted(diffuseTextureFileName)) { diffuseTextureFileName = System.IO.Path.Combine(filePath, diffuseTextureFileName); } string folderName = System.IO.Path.GetDirectoryName(diffuseTextureFileName); if (!System.IO.Directory.Exists(folderName)) { Log($" Folder for diffuse texture does not exist: {folderName ?? ""}:"); return; } if (_folderImageFiles == null) { _folderImageFiles = new Dictionary <string, string[]>(); } string[] allFilesInFolder; if (!_folderImageFiles.TryGetValue(folderName, out allFilesInFolder)) { allFilesInFolder = System.IO.Directory.GetFiles(folderName, "*.*", SearchOption.TopDirectoryOnly); _folderImageFiles.Add(folderName, allFilesInFolder); } //TextureMapTypes textureMapType = KnownTextureFiles.GetTextureType(diffuseTextureFileName); string fileNameWithoutKnownSuffix = KnownTextureFiles.GetFileNameWithoutKnownSuffix(diffuseTextureFileName); // Get material files that start with the diffuse texture file name without a suffix List <string> materialFiles; if (useStrictFileNameMatch) { materialFiles = allFilesInFolder.Where(f => fileNameWithoutKnownSuffix == KnownTextureFiles.GetFileNameWithoutKnownSuffix(f)).ToList(); } else { materialFiles = allFilesInFolder.Where(f => f.IndexOf(fileNameWithoutKnownSuffix, 0, StringComparison.OrdinalIgnoreCase) != -1).ToList(); } _textureFiles.Clear(); if (materialFiles.Count == 0) { Log($" Folder ({folderName}) for {assimpMaterial.Name ?? ""} material does not define any texture files"); return; } else { bool hasDiffuseTexture = false; foreach (var materialFile in materialFiles) { if (!TextureLoader.IsSupportedFile(materialFile, supportDDSTextures)) // Skip unsupported files { continue; } var textureMapType = KnownTextureFiles.GetTextureType(materialFile); if (textureMapType == TextureMapTypes.Unknown) { if (!hasDiffuseTexture) { textureMapType = TextureMapTypes.DiffuseColor; // First unknown file type is considered to be diffuse texture file } else { continue; // Unknown file type } } bool isDiffuseTexture = (textureMapType == TextureMapTypes.DiffuseColor || textureMapType == TextureMapTypes.Albedo || textureMapType == TextureMapTypes.BaseColor); string existingTextureFileName; if (_textureFiles.TryGetValue(textureMapType, out existingTextureFileName)) { // Map for this texture type already exist var existingFileExtension = System.IO.Path.GetExtension(existingTextureFileName); if (existingFileExtension != null && existingFileExtension.Equals(".dds", StringComparison.OrdinalIgnoreCase)) { continue; // DDS texture already found for this texture type - we will use existing dds texture } } hasDiffuseTexture |= isDiffuseTexture; _textureFiles.Add(textureMapType, materialFile); Log(" " + textureMapType + ": " + System.IO.Path.GetFileName(materialFile)); } if (_textureFiles.Count > 0) { foreach (var oneTextureFile in _textureFiles) { var textureType = oneTextureFile.Key; var oneFileName = oneTextureFile.Value; ShaderResourceView shaderResourceView; if (!_texturesCache.TryGetValue(oneFileName, out shaderResourceView)) { var isBaseColor = (textureType == TextureMapTypes.BaseColor || textureType == TextureMapTypes.Albedo || textureType == TextureMapTypes.DiffuseColor); // To load a texture from file, you can use the TextureLoader.LoadShaderResourceView (this supports loading standard image files and also loading dds files). // This method returns a ShaderResourceView and it can also set a textureInfo parameter that defines some of the properties of the loaded texture (bitmap size, dpi, format, hasTransparency). TextureInfo textureInfo; shaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.Device, oneFileName, loadDdsIfPresent: true, convertTo32bppPRGBA: isBaseColor, generateMipMaps: true, textureInfo: out textureInfo); physicallyBasedMaterial.TextureMaps.Add(new TextureMapInfo((Ab3d.DirectX.Materials.TextureMapTypes)textureType, shaderResourceView, null, oneFileName)); if (isBaseColor) { // Get recommended BlendState based on HasTransparency and HasPreMultipliedAlpha values. // Possible values are: CommonStates.Opaque, CommonStates.PremultipliedAlphaBlend or CommonStates.NonPremultipliedAlphaBlend. var recommendedBlendState = MainDXViewportView.DXScene.DXDevice.CommonStates.GetRecommendedBlendState(textureInfo.HasTransparency, textureInfo.HasPremultipliedAlpha); physicallyBasedMaterial.BlendState = recommendedBlendState; physicallyBasedMaterial.HasTransparency = textureInfo.HasTransparency; } _texturesCache.Add(oneFileName, shaderResourceView); } } } } }
private void AddTextureMapSelections(string materialName, PhysicallyBasedMaterial physicallyBasedMaterial) { if (physicallyBasedMaterial == null) { return; } var expander = new Expander() { Header = materialName, Margin = new Thickness(0, 0, 0, 3), IsExpanded = true }; TextureMapsPanel.Children.Add(expander); var stackPanel = new StackPanel() { Orientation = Orientation.Vertical }; expander.Content = stackPanel; //if (!string.IsNullOrEmpty(materialName)) //{ // var textBlock = new TextBlock() // { // Text = materialName, // FontWeight = FontWeights.Bold, // Margin = new Thickness(0, 0, 0, 3) // }; // TextureMapsPanel.Children.Add(textBlock); //} bool hasDiffuseColor = physicallyBasedMaterial.HasTextureMap(TextureMapTypes.DiffuseColor); string baseFolder = System.IO.Path.GetDirectoryName(_loadedFileName); foreach (var supportedTextureMapType in KnownTextureFiles.PBRSupportedTextureMapTypes) { // Show only one of DiffuseColor or BaseColor (not both) // Show DiffuseColor only if there is a texture map defined for it if ((supportedTextureMapType == TextureMapTypes.DiffuseColor && !hasDiffuseColor) || (supportedTextureMapType == TextureMapTypes.BaseColor && hasDiffuseColor)) { continue; } var textureMapSelectionControl = new TextureMapSelectionControl(physicallyBasedMaterial, supportedTextureMapType, baseFolder); textureMapSelectionControl.Margin = new Thickness(23, 0, 0, 7); textureMapSelectionControl.MapSettingsChanged += TextureMapSelectionControlOnMapSettingsChanged; textureMapSelectionControl.LayoutTransform = new ScaleTransform(0.75, 0.75); if (MainDXViewportView.DXScene != null) { textureMapSelectionControl.DXDevice = MainDXViewportView.DXScene.DXDevice; } //TextureMapsPanel.Children.Add(textureMapSelectionControl); stackPanel.Children.Add(textureMapSelectionControl); } }
private void CreateSampleScene() { _physicallyBasedMaterial = new PhysicallyBasedMaterial(); // We need to dispose the PhysicallyBasedMaterial when this sample is uloaded _disposables.Add(_physicallyBasedMaterial); UpdateBaseColor(); UpdateMetalness(); UpdateRoughness(); var normalMapShaderResourceView = GetNormalMapShaderResourceView(); if (normalMapShaderResourceView != null) { _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.NormalMap, normalMapShaderResourceView, "bricks_normal.png"); } var ambientOcclusionShaderResourceView = AmbientOcclusionShaderResourceView(); if (ambientOcclusionShaderResourceView != null) { _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.AmbientOcclusion, ambientOcclusionShaderResourceView, "bricks_ao.png"); } var wpfMaterial = new DiffuseMaterial(Brushes.Red); wpfMaterial.SetUsedDXMaterial(_physicallyBasedMaterial); ModelPlaceholder.Content = null; ModelPlaceholder.Children.Clear(); var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D() { CenterPosition = new Point3D(40, 12, 0), Radius = 12, Segments = 50, Material = wpfMaterial, FreezeMeshGeometry3D = false, UseCachedMeshGeometry3D = false }; ModelPlaceholder.Children.Add(sphereVisual3D); var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(-40, 10, 0), Size = new Size3D(20, 20, 20), Material = wpfMaterial, FreezeMeshGeometry3D = false, UseCachedMeshGeometry3D = false }; ModelPlaceholder.Children.Add(boxVisual3D); var readerObj = new Ab3d.ReaderObj(); var readModel3D = (GeometryModel3D)readerObj.ReadModel3D(_modelsFolder + "teapot-hires.obj"); Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(readModel3D, new Point3D(0, 10, 0), new Size3D(40, 40, 40), true); //// This code is called for each GeometryModel3D inside Plane1 //var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)readModel3D.Geometry); ////// Assign tangent array to the MeshGeometry3D //readModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors); readModel3D.Material = wpfMaterial; //ModelPlaceholder.Content = null; ModelPlaceholder.Children.Add(readModel3D.CreateModelVisual3D()); // Rendering normal (bump) maps require tangent vectors. // The following code will generate tangent vectors and assign them to the MeshGeometry3D that form our 3D model. // If tangent vectors are not provided, they will be calculated on-demand in the pixel shader (slightly reducing performance). Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects(ModelPlaceholder, delegate(GeometryModel3D geometryModel3D, Transform3D transform3D) { // This code is called for each GeometryModel3D inside Plane1 var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)geometryModel3D.Geometry); // Assign tangent array to the MeshGeometry3D geometryModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors); }); Camera1.Distance = 150; UpdateLights(); }