feature request - procedural texture module

Kevin D.
2013-11-12
2014-02-22
  • Kevin D.
    Kevin D.
    2013-11-12

    I was messing around with the procedural texture editor (as I am always doing) when I conceived of a feature that I would use endlessly if it existed. I was trying to make a ground surface texture to apply to a large land scape. I wanted it to be mostly grass with patches of dirt, gravel, etc... The plan was to use the image module to bring in grass, dirt, and gravel images, while using various other modules to determine their distribution. This is when it donned on me, it would be awesome if I could bring in other procedural textures instead of images. The outputs of the module would be all the properties of the texture: color, transparency, shininess, etc...

    I'm sure there are implications of this that I have not thought of, such as what happens if someone tries to bring in the texture they are currently working on (recursive textures?!).

    Thoughts?

     
  • Luke S
    Luke S
    2013-11-13

    There has been a little bit of discussion about some similar ideas. Basically, a procedural module that contains a network of procedural modules. My own interest in such a feature grew out of my experiments on this thread:

    http://www.friendlyskies.net/aoiforum/viewtopic.php?id=2724

    I would be very leery of allowing recursion in any form. Currently, the procedural editor does not allow recursion in any of its elements, and for good reason. You could create an infinite loop, or at least one that takes a very long time to stabilize on a value. (In fact, currently I don't think such a loop would stabilize. It would just go on calculating forever and never give an answer.)

    Another, slightly different feature is a generic procedural 'driver' module. Imagine a procedure that outputs arbitrary numbers, colors, etc. Each output has a (procedure specific) label. Any of the labeled outputs can be accessed by anything that can accept a parameter (As in, parameter track.) The same value could be used by a:

    • procedural texture
    • procedural animation track
    • layered texture blending percentage

    One of the (potential) downsides to these ideas is that they would encourage you to make even more complicated procedural stuff. This has the potential to slow stuff down. By a lot. Try out the file I posted at the end of that FS thread. Render it. Then multiply by a significant factor.

     
    Last edit: Luke S 2013-11-13
  • Peter Eastman
    Peter Eastman
    2013-11-13

    I think something along these lines would be a good idea. I agree with Luke that recursion should not be allowed. But some sort of modularity in defining procedures would be very useful. So the question is just how to define it. Using a texture as a module in another procedure would be one way to do it. Or we could have special "subprocedures" that are defined in their own space. They're not textures or materials or anything else, but they can be used in any other procedure.

    Peter

     
  • Kevin D.
    Kevin D.
    2013-11-16

    For me, the idea is mostly one of organization. I use the procedural editor constantly and the textures I make are often quite complex. It's hard to manage 40+ modules in one window. Bringing in other procedural textures would let me compartmentalize each major element of the texture, much like methods or functions in programming. Considering all the potential outputs, the interface would need to be designed right. Here is a mockup of what I would like to see:

    Each check box would add an output to the module. The edit button would open up a second procedural editor window for the grass texture, allowing you too easily modify the texture within a texture.

    "They're not textures or materials or anything else, but they can be used in any other procedure."
    Peter, I'm not sure what you mean when you say they are not textures or materials. What else would they be?

    A thought on recursion:
    What would stop someone from performing mutual recursion: A contains B which contains A?

     
  • Peter Eastman
    Peter Eastman
    2013-11-17

    Peter, I'm not sure what you mean when you say they are not textures or materials. What else would they be?

    Subprocedures. Each one would have an arbitrary set of inputs and an arbitrary set of outputs. They don't do anything on their own. They exist only to be used within other procedures.

    What would stop someone from performing mutual recursion: A contains B which contains A?

    If you tried to do that it would give you an error message. Exactly as it currently gives you an error message if you try to connect modules in a way that would create a loop.

    Peter

     
  • John_S
    John_S
    2013-11-17

    Thoughts?

    If this is to reduce regular recurring patterns to prevent a tile look, there are easier ways with the existing textures.

    Layer two textures. Or the same texture, set larger and rotated. Reduce opacity. You introduce variability with the overlay that disguises the repeating pattern underneath. It can work really well.

     
  • Luke S
    Luke S
    2013-11-18

    @John: Nothing to do with tiling. Imagine a very complex procedure. It may have dozens, or hundreds of modules. It is very likely that the procedure breaks apart into several large-ish chunks. The proposal would allow you to abstract one of those chunks away into a box, with only its inputs and outputs visible. Its a method of organization. But it gives you more. Once you have defined a sub-procedure, it could in theory be used in many procedures. Textures. Materials. Even distortion tracks.

    Take a look at the thread I linked above to see an example of a fairly simple task that has started to devolve into the sort of spaghetti mess Kevin is trying to avoid.

     
  • Luke S
    Luke S
    2013-11-18

    @Kevin: and there would be nothing to prevent you from creating a sub-procedure that has most or all of the outputs of a full-fledged texture if you prefer.

     
  • Luke S
    Luke S
    2013-11-18

    @Peter: I could see a use case for allowing to insert a 'real' texture, in addition to using sub-procedures. Kevin's example case assumes the existence of several fully finished textures, such as for grass, dirt, etc. He wishes to use the procedural system to combine them. What if he wants to combine them in different ways for different purposes? What if he wants to save the grass texture to his library so that he can use it on its own in another project?

    I'd think that adding an area to the library for sub-procedures would also be a good idea.

    I've also had an idea for another module that makes a lot more sense if sub-modules exist. I'd call it an 'array' module, or 'group' module. Its a little hard to explain, so maybe I'll try to build it myself, or put together an image of how it would work.

     
  • Luke S
    Luke S
    2014-02-21

    @Peter: I've been spending a little time trying to implement this, and I have run in to what seems to be a blocking point. See what you think of this logic train:

    1. A "Sub-procedure" as we have been discussing can have arbitrary outputs. So:
    2. It needs to be able to store what outputModules have been set up. But:
    3. Procedure itself does not store this data. It requires that the outputs have been set up before a procedure can be de-serialized. That setup falls to the procedureOwner. And:
    4. All existing procedureOwners have the outputModule setup hard-coded. There is no way to extract all the data one needs from an existing set of outputModules.

    Possible solutions:

    • Modify Procedure class to keep these modules in serialized form. Probably file-format breaker. Would prefer to avoid.
    • Give output module it's own ser/de-ser methods.
    • Create access methods so that another class can handle the serialization.

    Which would you prefer?

    I believe that I can get a proof of concept up and running without finding a solution for this, (With some strict limits) and once I have working code to share, there may be more to discuss.

     
  • Peter Eastman
    Peter Eastman
    2014-02-21

    Hi Luke,

    I don't see the problem. A "sub-procedure" will be a new class. It can serialize itself however it wants, including writing a record of what its outputs are. It will, of course, contain a Procedure. Or possibly it could subclass Procedure, in which case it would override writeToStream() and readFromStream(), but I'm not sure if that's the best design. And of course you'll want it to be editable, so you'll need to have some class that implements ProcedureOwner. But that's just an interface describing interactions with the editor. It has nothing to do with saving to files.

    What exactly is the problem you're trying to solve?

    Peter

     
  • Hi Peter,

    I think the problem that Luke is trying to solve is that of ensuring the procedures that a subprocedure points to are deserialised before the subprocedure is deserialised so that the subprocedure can reference them - and possibly a mechanism for finding those deserialised procedures.

    Cheers!
    Nik

     
  • Luke S
    Luke S
    2014-02-22

    Thank you, Peter and Nick for taking a moment to think about this.

    A "sub-procedure" will be a new class.

    Yes, it will. It will, itself, be a ProcedureOwner. Most of the serialization is, in fact, fairly straightforward. The one thing that I cannot access is the defaultValue/defaultColor of the OutputModules. These can be set programmatically, but all current uses hard-code them. (See Texture3d, Transparent vs. Emissive) It is not possible to read that data from an existing module.

    After some further thought, this may not be as much of a challenge as I thought. I could see creating a very simple piece of UI to choose a default for each new Output, but I don't know if that is necessary. A texture needs sensible defaults for occasions when a channel is not in use. A "Sub-procedure" is only going to have an output if you intend to use it.

    For the time being, (up to a working alpha, at least) I'm just going to assume that all color outputs default to BLACK and all number outputs default to 0.0

    @Nik, not quite where I was going, but thanks for bringing it up. I will need to be sure that what I create deals gracefully with missing parts, etc. and that, e.g. a Texture3d that contains one of these remembers to bring it along when copied to the library, etc.

     
  • Peter Eastman
    Peter Eastman
    2014-02-22

    You'll clearly need some sort of UI for selecting what the sub-procedure's outputs are. I could see that working in two ways. One is that you choose the names and types of the outputs. When you edit the sub-procedure, those would then appear at the right side of the window and you could connect things to them. The other option is that when editing the sub-procedure, it doesn't have any outputs at all. You just select a subset of the outputs of the modules it contains to act as the outputs from the sub-procedure. I could even imagine combining those: drag a link from any output into the bar at the right of the procedure editor, and an "output" box appears there automatically. But that might be more work, especially since it would require customizing the procedure editor.

    Peter