protected string GetScaledNormalTextureName(Texture bump, float bumpScale, UrhoPBRMaterial material)
        {
            var normalTexture = Engine.EvaluateTextrueName(bump);

            if (bumpScale < 0.999f)
            {
                normalTexture = ExportUtils.ReplaceExtension(normalTexture, string.Format(CultureInfo.InvariantCulture, "{0:0.000}.dds", bumpScale));
            }

            return(normalTexture);
        }
Beispiel #2
0
        private void WriteTerrainMaterial(TerrainData terrain, PrefabContext prefabContext)
        {
            using (var writer =
                       _engine.TryCreateXml(terrain.GetKey(), EvaluateMaterial(terrain),
                                            ExportUtils.GetLastWriteTimeUtc(terrain)))
            {
                if (writer == null)
                {
                    return;
                }

                var layers       = terrain.terrainLayers;
                var layerIndices = GetTerrainLayersByPopularity(terrain).Take(_maxLayers).ToArray();

                var material = new UrhoPBRMaterial();
                material.Technique = "Techniques/PBR/PBRTerrainBlend.xml";
                material.TextureUnits.Add(EvaluateWeightsMap(terrain));
                Vector2 detailTiling = new Vector2(1, 1);
                for (var layerIndex = 0; layerIndex < layerIndices.Length; ++layerIndex)
                {
                    var layer = layers[layerIndices[layerIndex]];
                    detailTiling = new Vector2(terrain.size.x / layer.tileSize.x, terrain.size.z / layer.tileSize.y);
                    if (layer.diffuseTexture != null)
                    {
                        _engine.ScheduleTexture(layer.diffuseTexture);
                        var urhoAssetName = _engine.EvaluateTextrueName(layer.diffuseTexture);
                        material.TextureUnits.Add(urhoAssetName);
                    }
                    else
                    {
                        material.TextureUnits.Add(null);
                    }
                }
                material.MatSpecColor = new Color(0.0f, 0.0f, 0.0f, 1.0f);
                material.Roughness    = 1;
                material.Metallic     = 0;
                material.ExtraParameters.Add("DetailTiling", detailTiling);
                material.PixelShaderDefines.Add("TERRAINLAYERS" + layerIndices.Length.ToString(CultureInfo.InvariantCulture));

                StandardMaterialExporter.WriteMaterial(writer, material, prefabContext);
            }
        }
Beispiel #3
0
        public void ExportPBRTextures(MetallicGlossinessShaderArguments arguments, UrhoPBRMaterial urhoMaterial)
        {
            if (!_engine.Options.ExportTextures)
            {
                return;
            }

            if (!string.IsNullOrWhiteSpace(urhoMaterial.MetallicRoughnessTexture))
            {
                TransformMetallicGlossiness(arguments, urhoMaterial.MetallicRoughnessTexture);
            }
            if (!string.IsNullOrWhiteSpace(urhoMaterial.AOTexture))
            {
                TransformAOTexture(arguments, urhoMaterial.AOTexture);
            }
            if (!string.IsNullOrWhiteSpace(urhoMaterial.NormalTexture))
            {
                TransformNormal(arguments.Bump, arguments.BumpScale, urhoMaterial.NormalTexture);
            }
        }
Beispiel #4
0
 public void SchedulePBRTextures(SpecularGlossinessShaderArguments arguments, UrhoPBRMaterial urhoMaterial)
 {
     EditorTaskScheduler.Default.ScheduleForegroundTask(
         () => _textureExporter.ExportPBRTextures(arguments, urhoMaterial),
         urhoMaterial.MetallicRoughnessTexture);
 }
Beispiel #5
0
        protected virtual UrhoPBRMaterial FromMetallicGlossiness(Material mat, MetallicGlossinessShaderArguments arguments)
        {
            var material = new UrhoPBRMaterial();

            material.NormalTexture    = GetScaledNormalTextureName(arguments.Bump, arguments.BumpScale, material);
            material.EmissiveTexture  = Engine.EvaluateTextrueName(arguments.Emission);
            material.AOTexture        = BuildAOTextureName(arguments.Occlusion, arguments.OcclusionStrength);
            material.BaseColorTexture = Engine.EvaluateTextrueName(arguments.BaseColor);
            var metalicGlossinesTexture = Engine.EvaluateTextrueName(arguments.MetallicGloss);
            var smoothnessTexture       = Engine.EvaluateTextrueName(arguments.Smoothness);
            var linearMetallic          = new Color(arguments.Metallic, 0, 0, 1).linear.r;

            if (string.IsNullOrWhiteSpace(metalicGlossinesTexture) && string.IsNullOrWhiteSpace(smoothnessTexture))
            {
                material.Metallic  = linearMetallic;
                material.Roughness = 1.0f - arguments.Glossiness;
            }
            else
            {
                var texNameBuilder = new StringBuilder();
                if (!string.IsNullOrWhiteSpace(metalicGlossinesTexture))
                {
                    texNameBuilder.Append(Path.GetDirectoryName(metalicGlossinesTexture).FixAssetSeparator());
                }
                else
                {
                    texNameBuilder.Append(Path.GetDirectoryName(smoothnessTexture).FixAssetSeparator());
                }
                if (texNameBuilder.Length > 0)
                {
                    texNameBuilder.Append('/');
                }

                if (!string.IsNullOrWhiteSpace(metalicGlossinesTexture))
                {
                    texNameBuilder.Append(Path.GetFileNameWithoutExtension(metalicGlossinesTexture));
                }
                else
                {
                    texNameBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0:0.00}", linearMetallic);
                }

                if (smoothnessTexture != metalicGlossinesTexture)
                {
                    texNameBuilder.Append('.');
                    texNameBuilder.Append(Path.GetFileNameWithoutExtension(smoothnessTexture));
                }

                if (arguments.SmoothnessRemapMax < 0.999f)
                {
                    texNameBuilder.Append('.');
                    texNameBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0:0.000}",
                                                arguments.SmoothnessRemapMax);
                }

                texNameBuilder.Append(".MetallicRoughness.png");
                material.MetallicRoughnessTexture = texNameBuilder.ToString();
            }

            material.BaseColor  = arguments.BaseColorColor.linear;
            material.AlphaBlend = arguments.Transparent;
            material.Cull       = Urho3DCulling.ccw;
            material.ShadowCull = Urho3DCulling.ccw;
            if (arguments.AlphaTest)
            {
                material.PixelShaderDefines.Add("ALPHAMASK");
            }
            material.EmissiveColor = arguments.EmissiveColor.linear;
            material.MatSpecColor  = new Color(1, 1, 1, 0);
            material.UOffset       = new Vector4(arguments.MainTextureScale.x, 0, 0, arguments.MainTextureOffset.x);
            material.VOffset       = new Vector4(0, arguments.MainTextureScale.y, 0, arguments.MainTextureOffset.y);
            material.EvaluateTechnique();
            return(material);
        }
        public static void WriteMaterial(XmlWriter writer, UrhoPBRMaterial urhoMaterial, PrefabContext prefabContext)
        {
            writer.WriteStartElement("material");
            writer.WriteWhitespace(Environment.NewLine);

            WriteTechnique(writer, urhoMaterial.Technique);

            WriteTexture(urhoMaterial.BaseColorTexture, writer, "diffuse", prefabContext);
            WriteTexture(urhoMaterial.NormalTexture, writer, "normal", prefabContext);
            WriteTexture(urhoMaterial.MetallicRoughnessTexture, writer, "specular", prefabContext);
            if (!string.IsNullOrWhiteSpace(urhoMaterial.EmissiveTexture))
            {
                WriteTexture(urhoMaterial.EmissiveTexture, writer, "emissive", prefabContext);
            }
            else
            {
                WriteTexture(urhoMaterial.AOTexture, writer, "emissive", prefabContext);
            }

            for (var index = 0; index < urhoMaterial.TextureUnits.Count; index++)
            {
                if (!string.IsNullOrWhiteSpace(urhoMaterial.TextureUnits[index]))
                {
                    WriteTexture(urhoMaterial.TextureUnits[index], writer, index, prefabContext);
                }
            }

            writer.WriteParameter("MatEmissiveColor", urhoMaterial.EmissiveColor);
            writer.WriteParameter("MatDiffColor", urhoMaterial.BaseColor);
            writer.WriteParameter("MatEnvMapColor", urhoMaterial.MatEnvMapColor);
            writer.WriteParameter("MatSpecColor", urhoMaterial.MatSpecColor);
            writer.WriteParameter("Roughness", urhoMaterial.Roughness);
            writer.WriteParameter("Metallic", urhoMaterial.Metallic);
            writer.WriteParameter("UOffset", urhoMaterial.UOffset);
            writer.WriteParameter("VOffset", urhoMaterial.VOffset);
            writer.WriteElementParameter("cull", "value", urhoMaterial.Cull.ToString());
            writer.WriteElementParameter("shadowcull", "value", urhoMaterial.ShadowCull.ToString());

            foreach (var extraParameter in urhoMaterial.ExtraParameters)
            {
                var val = extraParameter.Value;
                if (val is float floatValue)
                {
                    writer.WriteParameter(extraParameter.Key, floatValue);
                }
                else if (val is Vector2 vec2Value)
                {
                    writer.WriteParameter(extraParameter.Key, vec2Value);
                }
                else if (val is Vector3 vec3Value)
                {
                    writer.WriteParameter(extraParameter.Key, vec3Value);
                }
                else if (val is Vector4 vec4Value)
                {
                    writer.WriteParameter(extraParameter.Key, vec4Value);
                }
                else if (val is Quaternion quatValue)
                {
                    writer.WriteParameter(extraParameter.Key, quatValue);
                }
                else if (val is Color colorValue)
                {
                    writer.WriteParameter(extraParameter.Key, colorValue);
                }
                else if (val is Color32 color32Value)
                {
                    writer.WriteParameter(extraParameter.Key, color32Value);
                }
                else if (val is string strValue)
                {
                    writer.WriteParameter(extraParameter.Key, strValue);
                }
            }

            if (urhoMaterial.PixelShaderDefines.Count != 0 || urhoMaterial.VertexShaderDefines.Count != 0)
            {
                writer.WriteWhitespace("\t");
                writer.WriteStartElement("shader");
                writer.WriteAttributeString("psdefines", string.Join(" ", urhoMaterial.PixelShaderDefines));
                writer.WriteAttributeString("vsdefines", string.Join(" ", urhoMaterial.VertexShaderDefines));
                writer.WriteEndElement();
                writer.WriteWhitespace(Environment.NewLine);
            }

            writer.WriteEndElement();
        }
        public UrhoPBRMaterial FromSpecularGlossiness(SpecularGlossinessShaderArguments arguments)
        {
            var material = new UrhoPBRMaterial();

            material.NormalTexture   = GetScaledNormalTextureName(arguments.Bump, arguments.BumpScale);
            material.EmissiveTexture = Engine.EvaluateTextrueName(arguments.Emission);
            material.AOTexture       = BuildAOTextureName(arguments.Occlusion, arguments.OcclusionStrength);
            var    diffuseTextrueName = Engine.EvaluateTextrueName(arguments.Diffuse);
            var    specularTexture    = Engine.EvaluateTextrueName(arguments.PBRSpecular.Texture);
            string smoothnessTexture;

            if (arguments.Smoothness.Texture == arguments.Diffuse)
            {
                smoothnessTexture = diffuseTextrueName;
            }
            else
            {
                smoothnessTexture = specularTexture;
            }

            if (string.IsNullOrWhiteSpace(specularTexture) && string.IsNullOrWhiteSpace(diffuseTextrueName))
            {
                var pbrValues = PBRUtils.ConvertToMetallicRoughnessSRGB(new PBRUtils.SpecularGlossiness
                {
                    diffuse    = arguments.DiffuseColor,
                    specular   = arguments.PBRSpecular.Color,
                    opacity    = arguments.DiffuseColor.a,
                    glossiness = arguments.Glossiness
                }).linear();
                material.BaseColor = pbrValues.baseColor;
                material.Metallic  = pbrValues.metallic;
                material.Roughness = pbrValues.roughness;
            }
            else
            {
                {
                    var baseColorTextureNameBuilder = new StringBuilder();
                    if (!string.IsNullOrWhiteSpace(diffuseTextrueName))
                    {
                        baseColorTextureNameBuilder.Append(
                            Path.GetDirectoryName(diffuseTextrueName).FixAssetSeparator());
                    }
                    else
                    {
                        baseColorTextureNameBuilder.Append(Path.GetDirectoryName(specularTexture).FixAssetSeparator());
                    }
                    if (baseColorTextureNameBuilder.Length > 0)
                    {
                        baseColorTextureNameBuilder.Append('/');
                    }
                    if (!string.IsNullOrWhiteSpace(diffuseTextrueName))
                    {
                        baseColorTextureNameBuilder.Append(Path.GetFileNameWithoutExtension(diffuseTextrueName));
                    }
                    else
                    {
                        baseColorTextureNameBuilder.Append(FormatRGB(arguments.DiffuseColor.linear));
                    }
                    baseColorTextureNameBuilder.Append('.');
                    if (!string.IsNullOrWhiteSpace(specularTexture))
                    {
                        baseColorTextureNameBuilder.Append(Path.GetFileNameWithoutExtension(specularTexture));
                    }
                    else
                    {
                        baseColorTextureNameBuilder.Append(FormatRGB(arguments.PBRSpecular.Color.linear));
                    }

                    baseColorTextureNameBuilder.Append(".BaseColor.dds");
                    material.BaseColorTexture = baseColorTextureNameBuilder.ToString();
                }
                {
                    var metallicTextureNameBuilder = new StringBuilder();
                    if (!string.IsNullOrWhiteSpace(specularTexture))
                    {
                        metallicTextureNameBuilder.Append(Path.GetDirectoryName(specularTexture).FixAssetSeparator());
                    }
                    else
                    {
                        metallicTextureNameBuilder.Append(Path.GetDirectoryName(diffuseTextrueName)
                                                          .FixAssetSeparator());
                    }
                    if (metallicTextureNameBuilder.Length > 0)
                    {
                        metallicTextureNameBuilder.Append('/');
                    }
                    if (!string.IsNullOrWhiteSpace(specularTexture))
                    {
                        metallicTextureNameBuilder.Append(Path.GetFileNameWithoutExtension(specularTexture));
                    }
                    else
                    {
                        metallicTextureNameBuilder.Append(FormatRGB(arguments.PBRSpecular.Color.linear));
                    }

                    metallicTextureNameBuilder.Append('.');
                    if (!string.IsNullOrWhiteSpace(diffuseTextrueName))
                    {
                        metallicTextureNameBuilder.Append(Path.GetFileNameWithoutExtension(diffuseTextrueName));
                    }
                    else
                    {
                        metallicTextureNameBuilder.Append(FormatRGB(arguments.DiffuseColor.linear));
                    }

                    if (!string.IsNullOrWhiteSpace(smoothnessTexture))
                    {
                        if (arguments.GlossinessTextureScale < 0.999f)
                        {
                            metallicTextureNameBuilder.Append('.');
                            metallicTextureNameBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0:0.000}",
                                                                    arguments.GlossinessTextureScale);
                        }
                    }
                    else
                    {
                        if (arguments.Glossiness > 0)
                        {
                            metallicTextureNameBuilder.Append('.');
                            metallicTextureNameBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0:0.000}",
                                                                    arguments.Glossiness);
                        }
                    }

                    metallicTextureNameBuilder.Append(".MetallicRoughness.dds");
                    material.MetallicRoughnessTexture = metallicTextureNameBuilder.ToString();
                }

                if (arguments.Diffuse != null)
                {
                    material.BaseColor = arguments.DiffuseColor.linear;
                }
                else
                {
                    material.BaseColor = Color.white;
                }
            }

            material.AlphaBlend = arguments.Transparent;
            if (arguments.AlphaTest)
            {
                material.PixelShaderDefines.Add("ALPHAMASK");
            }
            if (arguments.Emission != null)
            {
                material.EmissiveColor = Color.white;
            }
            else
            {
                material.EmissiveColor = arguments.EmissiveColor.linear;
            }
            material.MatSpecColor = new Color(1, 1, 1, 0);
            material.UOffset      = new Vector4(arguments.MainTextureScale.x, 0, 0, arguments.MainTextureOffset.x);
            material.VOffset      = new Vector4(0, arguments.MainTextureScale.y, 0, arguments.MainTextureOffset.y);
            material.EvaluateTechnique();
            return(material);
        }