// Exports all non-experimental brushes along with their material parameters
        // into a directory structure suitable for submission to
        // google3/googledata/html/external_content/tiltbrush.com/shaders/brushes
        //
        // Input:
        //   Non-experimental brushes (from Assets/Manifest.asset)
        //   Their materials and shaders
        //
        // Output:
        //   An ExportManifest, writen to manifestPath
        //   An ExportRequests instance
        //
        // The manifest is consumed by Tilt Brush at export time, and should not
        // be uploaded to Poly or be served by it.
        //
        // The ExportRequests is processed by a texture downsampler; see DownsampleTextures()
        //
        // Shaders are not generated here; see GenerateShaders()
        //
        private static ExportRequests WriteManifest(
            string manifestPath, string exportRoot)
        {
            ExportRequests exportRequests = new ExportRequests();

            Debug.LogFormat("Exporting to: {0}", manifestPath);

            ExportGlTF.ExportManifest          manifest = new ExportGlTF.ExportManifest();
            Dictionary <Guid, BrushDescriptor> brushes;

            using (var unused = new BuildTiltBrush.TempHookUpSingletons())
            {
                manifest.tiltBrushVersion    = App.Config.m_VersionNumber;
                manifest.tiltBrushBuildStamp = App.Config.m_BuildStamp;
                brushes = GetBrushes();
            }

            foreach (KeyValuePair <Guid, BrushDescriptor> kvp in brushes)
            {
                try
                {
                    BrushDescriptor descriptor = kvp.Value;
                    var             exp        = ExportBrush(exportRequests, descriptor, exportRoot);
                    manifest.brushes.Add(exp.guid, exp);

                    // While we're at it, maybe a sanity check of the descriptor is in order
                    if (descriptor.m_RenderBackfaces && !exp.enableCull)
                    {
                        Debug.LogWarning(
                            $"{descriptor.m_DurableName}: generates backface geometry, but disables culling",
                            descriptor);
                    }
                }
                catch (ExportException e)
                {
                    Debug.LogException(e);
                } // foreach Brush + try
            }
            var serializer = new JsonSerializer();

            serializer.ContractResolver = new CustomJsonContractResolver();
            using (var writer = new CustomJsonWriter(new StreamWriter(manifestPath)))
            {
                writer.Formatting = Formatting.Indented;
                serializer.Serialize(writer, manifest);
            }

            return(exportRequests);
        }
Beispiel #2
0
        // Input: the exportRequests
        // Output: downsampled textures, to subdirectories of exportRoot
        private static void ExportTextures(ExportRequests exportRequests)
        {
            string projectPath  = Path.GetDirectoryName(Application.dataPath);
            string requestsJson = Path.Combine(projectPath, "Temp/ExportRequests.json");
            var    serializer   = new JsonSerializer();

            serializer.ContractResolver = new CustomJsonContractResolver();
            using (var writer = new CustomJsonWriter(new StreamWriter(requestsJson))) {
                writer.Formatting = Formatting.Indented;
                serializer.Serialize(writer, exportRequests);
            }

            string scriptPath = Path.Combine(projectPath, "Support/bin/gltf_export_textures.py");

            RunCommand("python", scriptPath, requestsJson);
        }
        /// Add an export request to exportRequests.
        /// A follow-up process will actually do the export, which involves
        /// copying, downsampling, and/or filtering.
        static void AddExportTextureRequest(
            ExportGlTF.ExportedBrush exp,
            ExportRequests exportRequests,
            Texture tex, string texName, string exportRoot)
        {
            // Even if it weren't for b/37499109, we'd still want to do a downsample
            // for robustness; tex.width/height is not necessarily the size of the
            // source png.
            int desiredWidth  = tex.width;
            int desiredHeight = tex.height;

            if (desiredWidth >= kLargeTextureThreshold ||
                desiredHeight >= kLargeTextureThreshold)
            {
                desiredWidth  = Mathf.Max(desiredWidth >> 1, 1);
                desiredHeight = Mathf.Max(desiredHeight >> 1, 1);
            }

            string projectRoot = Path.GetDirectoryName(Application.dataPath);
            string src         = Path.Combine(projectRoot, UnityEditor.AssetDatabase.GetAssetPath(tex));
            string dstName     = String.Format(
                "{0}-v{1}-{2}{3}",
                exp.folderName, exp.shaderVersion, texName, Path.GetExtension(src));

            exp.textures.Add(texName, dstName);
            exp.textureSizes.Add(texName, new Vector2(desiredWidth, desiredHeight));

            string dstDir = Path.Combine(exportRoot, exp.folderName);

            bool isBump;

            {
                string          assetPath = AssetDatabase.GetAssetPath(tex);
                TextureImporter importer  = AssetImporter.GetAtPath(assetPath) as TextureImporter;
                isBump = importer.convertToNormalmap;
            }
            exportRequests.exports.Add(
                new ExportRequest
            {
                source        = src,
                destination   = Path.Combine(dstDir, dstName),
                desiredWidth  = desiredWidth,
                desiredHeight = desiredHeight,
                isBump        = isBump
            });
        }
Beispiel #4
0
        /// Returns an ExportedBrush, and appends export requests to exportRequests.
        public static ExportGlTF.ExportedBrush ExportBrush(
            ExportRequests exportRequests,
            BrushDescriptor descriptor, string exportRoot)
        {
            if (string.IsNullOrEmpty(descriptor.m_DurableName))
            {
                throw new ApplicationException(
                          string.Format("Brush {0} has no DurableName", descriptor.name));
            }
            string brushFolderNameFmt = "{0}-{1}";
            string shaderFmt          = "{0}-v{1}-{2}.glsl";

            var exp = new ExportGlTF.ExportedBrush();

            exp.name           = descriptor.m_DurableName;
            exp.guid           = descriptor.m_Guid;
            exp.folderName     = string.Format(brushFolderNameFmt, exp.name, exp.guid.ToString("D"));
            exp.shaderVersion  = descriptor.m_ShaderVersion;
            exp.vertexShader   = string.Format(shaderFmt, exp.folderName, exp.shaderVersion, "vertex");
            exp.fragmentShader = string.Format(shaderFmt, exp.folderName, exp.shaderVersion, "fragment");
            exp.enableCull     = GetEnableCull(descriptor);
            exp.blendMode      = descriptor.m_BlendMode;

            // And the material
            {
                Material material = descriptor.Material;
                Shader   shader   = material.shader;
                for (int i = 0; i < ShaderUtil.GetPropertyCount(shader); i++)
                {
                    string internalName = ShaderUtil.GetPropertyName(shader, i);
                    int    propId       = Shader.PropertyToID(internalName);
                    string propName     = SanitizeName(internalName);

                    switch (ShaderUtil.GetPropertyType(shader, i))
                    {
                    case ShaderUtil.ShaderPropertyType.TexEnv:
                        if (material.HasProperty(internalName) && material.GetTexture(propId) is Texture2D)
                        {
                            AddExportTextureRequest(
                                exp, exportRequests, material.GetTexture(propId), propName, exportRoot);
                        }
                        break;

                    case ShaderUtil.ShaderPropertyType.Color:
                        exp.colorParams.Add(propName, material.GetColor(propId));
                        break;

                    case ShaderUtil.ShaderPropertyType.Range:
                    case ShaderUtil.ShaderPropertyType.Float:
                        float value = material.GetFloat(propId);
                        if (propName == "ScrollJitterIntensity")
                        {
                            value *= App.UNITS_TO_METERS;
                        }
                        exp.floatParams.Add(propName, value);
                        break;

                    case ShaderUtil.ShaderPropertyType.Vector:
                        Vector4 vec = material.GetVector(propId);
                        if (propName == "ScrollDistance")
                        {
                            vec   *= App.UNITS_TO_METERS;
                            vec.z *= -1;
                        }
                        exp.vectorParams.Add(propName, vec);
                        break;

                    default:
                        break;
                    }
                }
            }

            // A bit of sanity-checking.
            bool expectCutoff = (exp.blendMode == ExportableMaterialBlendMode.AlphaMask);
            bool hasCutoff    = exp.floatParams.ContainsKey("Cutoff");

            if (expectCutoff != hasCutoff)
            {
                if (expectCutoff)
                {
                    Debug.LogWarning($"{descriptor.m_DurableName}: missing cutoff (or shouldn't be AlphaMask)",
                                     descriptor);
                }
                else
                {
                    // Some of these warnings are caused by materials which are AdditiveBlend but also have
                    // alpha cutoff; but exp.blendMode can only represent one or the other. Unclear how
                    // we can get this into a gltf material.
                    // Some are caused by materials which don't use blending at all but still use a
                    // shader that has cutoff math in it (eg hull, wire, icing). This is a bit of wasted
                    // work at shading time.
                    // Debug.LogWarning($"{descriptor.m_DurableName}: {exp.blendMode} but has cutoff",
                    //                  descriptor);
                }
            }

            return(exp);
        }