2
\$\begingroup\$

I have a substance (sbsar) that I'm using to generate a procedural material . I have applied this texture to reversi pieces. It works well, but all the pieces look identical. I addressed this by using a script to change the $randomseed property and then call the RebuildTextures method for each piece. The effect is exactly what I want: each piece has a slightly distinct marble pattern.

The problem is that the process of rebuilding the textures for 64 pieces takes about 20 seconds. For a simple Android game, this is not acceptable performance.

The designer has the option to "bake" the material under Load Behavior, but this only works for one variation. Is there a way I can bake many different random seeds? I'd be OK with pre-generating a batch of non-procedural materials from the substance and picking randomly from that batch at runtime, but I'm not sure how that can be done.

\$\endgroup\$
1
\$\begingroup\$

I wrote the following script to generate a batch of pre-rendered textures from a ProceduralMaterial. Just add it to an empty object in the scene, set the parameters, and run.

Note that you must set the format of the material to RAW first.

using System.IO;
using System.Linq;

using UnityEngine;

public class ExportTexture: MonoBehaviour {

    public ProceduralMaterial Material;

    public string[] TextureNames = {};

    public int Iterations = 1;

    public int RandomSeed = -1;

    public string Folder = "Export";

    public void Start() {
        if( RandomSeed >= 0 ) Random.InitState( RandomSeed );
        for( var i = 0; i < Iterations; ++i ) {
            var mat = Material;
            mat.SetProceduralFloat( "$randomseed", Random.Range( 0f, 1000f ) );
            mat.isReadable = true;
            mat.RebuildTexturesImmediately();

            var textures = ( TextureNames.Any() ? TextureNames.Select( mat.GetGeneratedTexture ).ToArray() : mat.GetGeneratedTextures() ).Cast<ProceduralTexture>();
            foreach( var tex in textures ) {
                var tex2d = new Texture2D( tex.width, tex.height );
                tex2d.SetPixels32( tex.GetPixels32( 0, 0, tex.width, tex.height ) );
                tex2d.Apply();
                var bytes = tex2d.EncodeToPNG();
                var outFile = new FileInfo( Path.Combine( Folder, string.Format( "{0}_{1}.png", tex.name, i ) ) );
                outFile.Directory.Create();
                File.WriteAllBytes( outFile.FullName, bytes );
            }
        }
    }   
}

I release this code under the WTFPL.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.