private ImageTexture[] loadMaterialTextures(ai.Material material, ai.TextureType type, TextureType textureType) { ImageTexture[] textures = new ImageTexture[material.GetMaterialTextureCount(type)]; for (int i = 0; i < textures.Length; i++) { ai.TextureSlot slot; material.GetMaterialTexture(type, i, out slot); string path = directory + slot.FilePath; ImageTexture texture; ImageTexture loaded = loadedTextures.Find(x => x.path == path); if (loaded != null) { texture = loaded; } else { texture = new ImageTexture(gl, path, textureType); loadedTextures.Add(texture); Console.WriteLine($"Texture file path: {path}"); } textures[i] = texture; } return(textures); }
List <Texture> loadMaterialTextures(Assimp.Material mat, Assimp.TextureType type, string typeName) { List <Texture> textures = new List <Texture>(); for (int i = 0; i < mat.GetMaterialTextureCount(type); i++) { bool skip = false; TextureSlot textureSlot; mat.GetMaterialTexture(type, i, out textureSlot); for (int j = 0; j < texturesLoaded.Count; j++) { if (texturesLoaded[j].path.CompareTo(textureSlot.FilePath) == 0) { skip = true; textures.Add(texturesLoaded[j]); break; } } if (!skip) { Texture texture = new Texture(); texture.id = TextureFromFile(textureSlot.FilePath, directory); texture.type = typeName; texture.path = textureSlot.FilePath; textures.Add(texture); texturesLoaded.Add(texture); } } return(textures); }
private static Material ConvertMaterialFromAiMaterial(Ai.Material aiMaterial, string texturesDirectory, TextureSet textureSet) { Material material = new Material(); material.Shader = "BLINN"; material.Field02 = 2688; material.Name = aiMaterial.Name; material.Field25 = 1; if (aiMaterial.HasColorDiffuse) { material.DiffuseColor = aiMaterial.ColorDiffuse.ToMML(); } else { material.DiffuseColor = new Color(1, 1, 1, 1); } if (aiMaterial.HasColorAmbient) { material.AmbientColor = aiMaterial.ColorAmbient.ToMML(); } else { material.AmbientColor = new Color(1, 1, 1, 1); } if (aiMaterial.HasColorSpecular) { material.SpecularColor = aiMaterial.ColorSpecular.ToMML(); } else { material.SpecularColor = new Color(0.5f, 0.5f, 0.5f, 1); } if (aiMaterial.HasColorEmissive) { material.EmissionColor = aiMaterial.ColorEmissive.ToMML(); } else { material.EmissionColor = new Color(0, 0, 0, 1); } if (aiMaterial.HasShininess && aiMaterial.ShadingMode == Ai.ShadingMode.Phong) { material.Shininess = aiMaterial.Shininess; } else { material.Shininess = 50f; } Texture texture; if (aiMaterial.HasTextureDiffuse && (texture = ConvertTexture(aiMaterial.TextureDiffuse.FilePath, texturesDirectory, textureSet)) != null) { material.Field00 |= 1; material.Diffuse.TextureId = texture.Id; material.Diffuse.Field02 = 241; } if (aiMaterial.HasTextureAmbient && (texture = ConvertTexture(aiMaterial.TextureAmbient.FilePath, texturesDirectory, textureSet)) != null) { material.Ambient.TextureId = texture.Id; material.Ambient.Field02 = 241; } if (aiMaterial.HasTextureNormal && (texture = ConvertTexture(aiMaterial.TextureNormal.FilePath, texturesDirectory, textureSet)) != null) { material.Field00 |= 256; material.Normal.TextureId = texture.Id; material.Normal.Field02 = 242; } if (aiMaterial.HasTextureSpecular && (texture = ConvertTexture(aiMaterial.TextureSpecular.FilePath, texturesDirectory, textureSet)) != null) { material.Field00 |= 128; material.Specular.TextureId = texture.Id; material.Specular.Field02 = 243; } if (aiMaterial.HasTextureReflection && (texture = ConvertTexture(aiMaterial.TextureReflection.FilePath, texturesDirectory, textureSet)) != null) { material.Field00 |= 33832; material.Reflection.TextureId = texture.Id; material.Reflection.Field02 = 1017; } if (aiMaterial.GetMaterialTexture(Ai.TextureType.Shininess, 0, out Ai.TextureSlot shininess) && (texture = ConvertTexture(shininess.FilePath, texturesDirectory, textureSet)) != null) { material.Field00 |= 8192; material.Tangent.TextureId = texture.Id; material.Tangent.Field02 = 246; } foreach (var materialTexture in material.MaterialTextures) { if (materialTexture == material.Diffuse) { materialTexture.Field00 = materialTexture.IsActive ? 82288 : 48; } materialTexture.Field05 = 1; if (materialTexture.IsActive) { materialTexture.Field01 = 0x2418C3; materialTexture.Field06 = 1; materialTexture.Field11 = 1; materialTexture.Field16 = 1; materialTexture.Field21 = 1; } } return(material); }
/// <summary> /// Helper method, used to transfer information from Material to ClientMaterial /// </summary> /// <param name="mat"> the source Material </param> /// <param name="myMat"> the destination ClientMaterial </param> protected void ApplyMaterial(Material mat, ClientMaterial myMat) { if (mat.GetMaterialTextureCount(TextureType.Diffuse) > 0) { TextureSlot tex; if (mat.GetMaterialTexture(TextureType.Diffuse, 0, out tex)) { ShaderResourceView temp; myMat.setDiffuseTexture(temp = CreateTexture(Path.Combine(Path.GetDirectoryName(sourceFileName), Path.GetFileName(tex.FilePath)))); myMat.setTexCount(temp == null ? 0 : 1); } else { myMat.setDiffuseTexture(null); myMat.setTexCount(1); } } // copies over all the material properties to the struct // sets the diffuse color Color4 color = new Color4(.4f, .4f, .4f, 1.0f); // default is light grey if (mat.HasColorDiffuse) { myMat.setDiffuse(mat.ColorDiffuse.R, mat.ColorDiffuse.G, mat.ColorDiffuse.B, mat.ColorDiffuse.A); } else { myMat.setDiffuse(color.Red, color.Green, color.Blue, color.Alpha); } // sets the specular color color = new Color4(0.1f, 0.1f, 0.1f, 1.0f); // default is non-specular if (mat.HasColorSpecular) { myMat.setSpecular(mat.ColorDiffuse.R, mat.ColorDiffuse.G, mat.ColorDiffuse.B, mat.ColorDiffuse.A); } else { myMat.setSpecular(color.Red, color.Green, color.Blue, color.Alpha); } // sets the ambient color color = new Color4(.3f, .3f, .3f, 1.0f); // default is dark grey if (mat.HasColorAmbient) { myMat.setAmbient(mat.ColorDiffuse.R, mat.ColorDiffuse.G, mat.ColorDiffuse.B, mat.ColorDiffuse.A); } else { myMat.setAmbient(color.Red, color.Green, color.Blue, color.Alpha); } // sets the emissive color color = new Color4(0, 0, 0, 1.0f); // default is black if (mat.HasColorEmissive) { myMat.setEmissive(mat.ColorDiffuse.R, mat.ColorDiffuse.G, mat.ColorDiffuse.B, mat.ColorDiffuse.A); } else { myMat.setEmissive(color.Red, color.Green, color.Blue, color.Alpha); } // sets the shininess float shininess = 1; // default is 1 if (mat.HasShininess) { myMat.setShininess(mat.Shininess); } else { myMat.setShininess(shininess); } // sets the opacity float opacity = 1; // default is 1 if (mat.HasOpacity) { myMat.setOpacity(mat.Opacity); } else { myMat.setOpacity(mat.Opacity); } }
void ProcessMaterials(Scene scene, string directoryName, VertexMode mode) { for (int i = 0; i < scene.MaterialCount; i++) { Material mat = new Material(); Assimp.Material material = scene.Materials[i]; var diffuse = material.ColorDiffuse; mat.diffuse = new Vec3(diffuse.R, diffuse.G, diffuse.B); var specular = material.ColorSpecular; mat.specular = new Vec3(specular.R, specular.G, specular.B); var emissive = material.ColorEmissive; mat.emissive = new Vec3(emissive.R, emissive.G, emissive.B); float shininess = material.Shininess; mat.shininess = shininess; float shininessStrength = material.ShininessStrength; mat.specular.x *= shininessStrength; mat.specular.y *= shininessStrength; mat.specular.z *= shininessStrength; int numDiffuseMaps = material.GetMaterialTextureCount(TextureType.Diffuse); int numNormalMaps = material.GetMaterialTextureCount(TextureType.Normals); if (numDiffuseMaps > 0) { material.GetMaterialTexture(TextureType.Diffuse, 0, out var diffuseMapName); Console.WriteLine(diffuseMapName.FilePath); if (!File.Exists(diffuseMapName.FilePath) && (mode == VertexMode.TextureAndNormal || mode == VertexMode.TextureOnly)) { var a = new ModelWorkerEventArgs() { Args = diffuseMapName.FilePath, EventType = ModelWorkerEventArgs.EventArgsType.TextureNotExists, Context = directoryName }; this.OnActionCallback?.Invoke(this, a); diffuseMapName.FilePath = a.Args.Replace(directoryName, ""); } mat.diffuseMapName = diffuseMapName.FilePath; } if (numNormalMaps > 0) { material.GetMaterialTexture(TextureType.Normals, 0, out var normalMapName); Console.WriteLine(normalMapName.FilePath); if (!File.Exists(normalMapName.FilePath) && mode == VertexMode.TextureAndNormal) { var a = new ModelWorkerEventArgs() { Args = normalMapName.FilePath, EventType = ModelWorkerEventArgs.EventArgsType.TextureNotExists, Context = directoryName }; this.OnActionCallback?.Invoke(this, a); normalMapName.FilePath = a.Args.Replace(directoryName, ""); ; } mat.normalMapName = normalMapName.FilePath; } this._materials.Add(mat); } }
private void ApplyFixedFunctionMaterial(Mesh mesh, Material mat, bool textured, bool shaded) { shaded = shaded && (mesh == null || mesh.HasNormals); if (shaded) { GL.Enable(EnableCap.Lighting); } else { GL.Disable(EnableCap.Lighting); } var hasColors = mesh != null && mesh.HasVertexColors(0); if (hasColors) { GL.Enable(EnableCap.ColorMaterial); GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse); } else { GL.Disable(EnableCap.ColorMaterial); } // note: keep semantics of hasAlpha consistent with IsAlphaMaterial() var hasAlpha = false; var hasTexture = false; // note: keep this up-to-date with the code in UploadTextures() if (textured && mat.GetMaterialTextureCount(TextureType.Diffuse) > 0) { hasTexture = true; TextureSlot tex; mat.GetMaterialTexture(TextureType.Diffuse, 0, out tex); var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath); hasAlpha = hasAlpha || gtex.HasAlpha == Texture.AlphaState.HasAlpha; if(gtex.State == Texture.TextureState.GlTextureCreated) { GL.ActiveTexture(TextureUnit.Texture0); gtex.BindGlTexture(); GL.Enable(EnableCap.Texture2D); } else { GL.Disable(EnableCap.Texture2D); } } else { GL.Disable(EnableCap.Texture2D); } GL.Enable(EnableCap.Normalize); var alpha = 1.0f; if (mat.HasOpacity) { alpha = mat.Opacity; if (alpha < AlphaSuppressionThreshold) // suppress zero opacity, this is likely wrong input data { alpha = 1.0f; } } var color = new Color4(.8f, .8f, .8f, 1.0f); if (mat.HasColorDiffuse) { color = AssimpToOpenTk.FromColor(mat.ColorDiffuse); if (color.A < AlphaSuppressionThreshold) // s.a. { color.A = 1.0f; } } color.A *= alpha; hasAlpha = hasAlpha || color.A < 1.0f; if (shaded) { // if the material has a texture but the diffuse color texture is all black, // then heuristically assume that this is an import/export flaw and substitute // white. if (hasTexture && color.R < 1e-3f && color.G < 1e-3f && color.B < 1e-3f) { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, Color4.White); } else { GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, color); } color = new Color4(0, 0, 0, 1.0f); if (mat.HasColorSpecular) { color = AssimpToOpenTk.FromColor(mat.ColorSpecular); } GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, color); color = new Color4(.2f, .2f, .2f, 1.0f); if (mat.HasColorAmbient) { color = AssimpToOpenTk.FromColor(mat.ColorAmbient); } GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, color); color = new Color4(0, 0, 0, 1.0f); if (mat.HasColorEmissive) { color = AssimpToOpenTk.FromColor(mat.ColorEmissive); } GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, color); float shininess = 1; float strength = 1; if (mat.HasShininess) { shininess = mat.Shininess; } // todo: I don't even remember how shininess strength was supposed to be handled in assimp if (mat.HasShininessStrength) { strength = mat.ShininessStrength; } var exp = shininess*strength; if (exp >= 128.0f) // 128 is the maximum exponent as per the Gl spec { exp = 128.0f; } GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, exp); } else if (!hasColors) { GL.Color3(color.R, color.G, color.B); } if (hasAlpha) { GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.DepthMask(false); } else { GL.Disable(EnableCap.Blend); GL.DepthMask(true); } }
/// <summary> /// Check if a given assimp material requires alpha-blending for rendering /// </summary> /// <param name="material"></param> /// <returns></returns> public bool IsAlphaMaterial(Material material) { if (material.HasOpacity && IsTransparent(material.Opacity)) { return true; } // Also treat material as (potentially) semi-transparent if the alpha // components of any of the diffuse, specular, ambient and emissive // colors are non-1. It is not very well-defined how assimp handles // these values so better count them into transparency as well. // // Ignore color values with alpha=0, however. These are most likely // not intended to be fully transparent. if (material.HasColorDiffuse && IsTransparent(material.ColorDiffuse.A)) { return true; } if (material.HasColorSpecular && IsTransparent(material.ColorSpecular.A)) { return true; } if (material.HasColorAmbient && IsTransparent(material.ColorAmbient.A)) { return true; } if (material.HasColorEmissive && IsTransparent(material.ColorEmissive.A)) { return true; } if (material.GetMaterialTextureCount(TextureType.Diffuse) > 0) { TextureSlot tex; material.GetMaterialTexture(TextureType.Diffuse, 0, out tex); var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath); if(gtex.HasAlpha == Texture.AlphaState.HasAlpha) { return true; } } return false; }
/// <summary> /// Uploads all the textures required for a given material to VRAM (i.e. /// create the corresponding Gl objects). Textures that have been /// uploaded before are not attempted again. /// </summary> /// <param name="material"></param> /// <returns>Whether there were any new texture uploads</returns> public bool UploadTextures(Material material) { Debug.Assert(material != null); var any = false; // note: keep this up to date with the code in ApplyFixedFunctionMaterial if (material.GetMaterialTextureCount(TextureType.Diffuse) > 0) { TextureSlot tex; material.GetMaterialTexture(TextureType.Diffuse, 0, out tex); var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath); if (gtex.State == Texture.TextureState.WinFormsImageCreated) { gtex.Upload(); any = true; } else if (gtex.ReconfigureUploadedTextureRequested) { gtex.ReconfigureUploadedTexture(); } } return any; }
void WriteTextureStack (Material mat, TextureType type, BinaryWriter writer, Dictionary<string,string> textures) { var count = mat.GetMaterialTextureCount(type); writer.Write(count); for (var i = 0; i < count; i++) { TextureSlot slot; mat.GetMaterialTexture(type, i, out slot); if (slot.Mapping != TextureMapping.FromUV) throw new ContentException("Unsupported texture mapping type, textures must be UV-mapped."); if (!textures.ContainsKey(slot.FilePath)) { textures.Add(slot.FilePath, Path.GetFileNameWithoutExtension(slot.FilePath)); } writer.Write(textures[slot.FilePath]); writer.Write(slot.UVIndex); writer.Write(slot.BlendFactor); writer.Write((int)slot.Operation); writer.Write(slot.WrapModeU == TextureWrapMode.Wrap); writer.Write(slot.WrapModeV == TextureWrapMode.Wrap); } }