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 Answer 1

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .