Brush Engine Refactor #91473
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
26 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#91473
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Sculpt mode is in dire need of a new brush system. A great deal of user confusion has been caused by the sheer mess that is the sculpt brush code. Bad API design has create strange workflow limitations and subpar user interfaces.
Our goal is to produce brush editor where users can compose different types of brushes together. Since this is a very ambitious goal it will be done in a series of stages. The immediate priority is to have a system that can be extended in the future without breaking backwards compatibility. Users will be using this system to create thousands of new brushes. We've hidden an awful lot of brushes from the users with bad UX, so if we must break backwards compatibility we should do it now--not after we've fixed the UX and users have gone on a brush creating spree.
Current Status
The system has been implemented in sculpt-dev through Stage 2. The API was initially implemented in C, but is currently in the process of being moved to C++.
Current core data structures:
BKE_brush_engine.hh
Stage 1: Brush Channels & Command Lists
Most Sculpt brushes execute up to four separate commands:
Each of these require their own strength, radius and spacing parameters.
Yeesh.
Command Lists
We can simply the code and the user experience by explicitly building brushes out of
multiple logical operations, a command list. A brush command list is a set
of instructions for a very simple command processor. In the future these lists
will be generated from node graphs, but for now they'll be hardcoded.
The goal is to have a system that can survive the introduction of a composable
brush editor (either a node editor or a modifier-like stack) without breaking everyone's files.
Note that command lists will not be user-definable at this stage.
Brush Channels
A brush channel is a float, int, enum, bitmask, etc. It can be driven by input mappings (e.g. pen pressure) with
custom input curves.
Importantly, brush channels can be strung together in inheritance chains. Each channel can be flagged
to inherit from whatever it's logical "parent" is; in the node graph that would be group parents, but for
now it's brushes and the scene tool settings.
For example, each command in a command list has it's own list of brush channels. Each of these can be flagged to inherit from the "parent", which is a list of channels stored in Brush. These in turn can be flagged to inherit from a list of channels stored in the Scene toolsettings (in Sculpt).
This will serve as a replacement for the UnifiedPaintSettings and DynTopoSettings structures.
Value Semantics
Brush channels are meant to be copied by value. This avoids violating the architectural design rule in Blender that, in general, data owned by one datablock should not store pointers to another. It also simplifies the code. Instead of each brush channel set storing a pointer to it's original owner (so it can resolve inheritance), inheritance is applied in stages:
ss->cache->channels_final
.ss->cache->channels_final
andBrushCommand->params
are combined intoBrushCommand->params_final
.BrushCommand->params_final
is copied toBrushCommand->params_mapped
and input mapping is applied (e.g. pressure).And yes, there are API functions to lookup the final value of a brush channel given parent and child brush channel sets.
Compile-time Name Checking
Brush settings identifiers are just simple strings. The C API is designed to catch typos at compiler time. It does this by generating a bunch of global string variables like so:
Important API functions are then wrapped in a series of
BRUSHSET_XXX
macros. So tolookup a channel you might do:
The C++ API works a bit differently;
BrushChannelSetIF
has one accessor method per brush channel.I tried to get compile-time string validation of channel names to work but failed (at least in C++17),
so I ended up using macros to create accessor methods instead.
Note the sculpt code has it own API. This is due to the
StrokeCache
structure (ss->cache), which is allowed toNULL
. The Sculpt channel API thus requires backup pointers (toBrush
andSculpt
structures) as a fallback to derive channel values.Example:
No ID pointers
Aside from textures (the implementation of which incomplete), no ID pointers are allowed in BrushChannels. This is so we can link in brushes from an asset file as library overrides without weird edge cases or performance degradations on file IO.
This decision may be revisited later.
Use id properties?
In the current implementation brush channels have four value members:
Floats go in
fvalue
, vectors invector
, while ints, booleans, enums and bitmasks useivalue
. BrushCurveis just a struct that stores a Brush curve preset and a pointer to a CurveMapping.
We could replace the first three with a single ID Property; for the second we would need to implement
CurveMapping ID properties, which might be a good idea anyway?
C++
The current API implementation in sculpt-dev is mostly implemented in C, which has led to some code messiness. The process of switching the implementation to C++ has begun; the existing C API will be (mostly) kept, but it will wrap a C++ one.
The C++ API works by wrapping the C DNA structs, so e.g.
BrushChannel
has aBrushChannelIF
C++ wrapper class ("IF" just stances for "Interface"; suggestions for better names are welcome). The C++ API is quite a bit cleaner (and clearer), and uses templates:Commands
Exactly how many commands to implement at this stage in an open question. The node editor will probably require a small VM similar to Cycle's SM nodes (if much simpler).
For now, the commands mirror the
SCULPT_TOOL_XXX
enumeration. There are several commands that are not available as brushtypes:
SCULPT_TOOL_DYNTOPO
SCULPT_TOOL_TOPOLOGY_RAKE
SCULPT_TOOL_ENHANCE_DETAILS
(currently exposed as a brush in sculpt-dev, but will probably be moved back inside the Smooth brush).Textures
There will be no changes to brush textures at this stage. The Tool command will support textures in much the same way the existing codebase does. Fixing Blender's texture node mess is not the sculpt team's job.
Stage 2: Port Existing Brushes and UI
All current brushes will have to be ported to the new system, this shouldn't be hard. The existing brush UI
will be split into two pieces; 25-33% will remain in the workspace buttons, while the rest will be moved
someplace else (either a dedicated space type or another tab in the properties editor).
The settings themselves will be ported to brush channels, but the underlying functionality will remain
unchanged.
This is mostly finished in sculpt-dev, but needs more work on the UX design level.
Stage 3: Python Node Editor
Option A: Node Editor
Expose the command lists in RNA and start writing a proof of concept node editor in Python. Code to convert command lists to nodes will be written (probably in python to begin with), so we can convert old files.
Design Issues
There are 50+ brush parameters. Having nodes with 50 sockets is not going to work.
Instead we should let users add the brush channels they want to command nodes.
Option B: Command Stack
Node editors aren't always the right thing to do if the underlying system is fundamentally linear.
Brush commands are simple and sequential; they do not have outputs. A node editor would be useful
for configuring input mappings (e.g. using pen pressure to switch between commands), however this
should be possible with a stack metaphor as well.
Stage 4: Presets
At this stage brushes will be converted to command presets. There are a number of ways we can do this, mostly having to do with how we update builtin brushes on installation of new versions of blender:
Added subscriber: @JosephEagar
Added subscriber: @TheRedWaxPolice
Added subscriber: @TonatiuhdeSanJulian
Added subscriber: @lowpolysaac
Added subscriber: @AlexeyAdamitsky
Added subscriber: @thinsoldier
Added subscriber: @ErickNyanduKabongo
Added subscriber: @tux21b
Added subscriber: @GeorgiaPacific
Added subscriber: @JulianPerez
Added subscriber: @pawel.palenica
Added subscriber: @Zunio
Added subscriber: @ostry
Hi Joe,
After reading all this, I m wondering if you will consider old design and discussion about sculpt mode brushes we had in the past? People has been posting really good UI and user-friendly ways to use sculpt brushes.
Feel free to post links or mockup images.
Added subscriber: @Francis_J
Added subscriber: @lichtwerk
Added subscriber: @RC12
Here is a good thread, in there you can find many UI suggestions. The thread was started by Pablo, the sculptor. -> https://developer.blender.org/T80384
Added subscriber: @NelsonNAS
what we really need is this {https://developer.blender.org/D7616}
Added subscriber: @Debuk
Added subscriber: @AndyCuccaro
Added subscriber: @wevon-2
If you really want to work with brush assets and have a global palette, I think it is convenient that most of them derive from the same parent and their individual attributes are the ones that define their function. The clothes brush already works like this.
Although it seems to me that it is not the most suitable place, some time ago I made a proposal and mockups in "Brushes Storage" in reference to this.
https://developer.blender.org/T70412
Image:
https://dev-files.blender.org/file/data/ksbbwvuyerwu4im6gg2k/PHID-FILE-e655fe2gkbnf5hqdzhev/Tools.png
In it I show in a basic way the unification of brushes and how to quickly access the assets, both from the upper toolbar and from the attributes panel.
Now that Asset Manager is more developed, maybe it's time to do some rethinking.
There are many proposals on the table, but none official on the table, although there is XD. Couldn't it be made public yet?
Added subscriber: @ckohl_art
Added subscriber: @shinyuu
Added subscriber: @Garek
Added subscriber: @zNight
Added subscriber: @hzuika
Added subscriber: @Fran11o11D