-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Update English Version * Update Concepts * Update Overview.md * Update CustomShader.md * Update Docs * Update DebugTools.md * Update README.md * Update README.md * Update CustomTrigger.md * Update Trigger.md * Update Collider.md * Update README.md * Update Body.md --------- Co-authored-by: Zilize <zhenbomy@foxmail.com>
- Loading branch information
1 parent
157a9ee
commit 962ab24
Showing
32 changed files
with
871 additions
and
308 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Custom Shader | ||
|
||
> In addition to using the shaders provided by the plugin, users can create their own shader and use it in the scene. We will introduce custom shader from three perspectives: parameter settting, vertex shader and script setting. | ||
## Parameter Setting | ||
|
||
Since Soft2D only supports Vulkan and Metal, we can optimize the performance by compiling shader code tailored to them: | ||
``` shaderlab | ||
#pragma exclude_renderers d3d11 | ||
``` | ||
At the same time, we need to enable GPU instancing and set the target version to 4.5 or higher: | ||
```shaderlab | ||
#pragma multi_compile_instancing | ||
#pragma UNITY_INSTANCING_ENABLE | ||
#pragma target 4.5 | ||
``` | ||
Soft2DManager will automatically retrieve the buffer of particle properties and pass them to the shader. We only need to declare them, and **cannot change their names or variable types**: | ||
```shaderlab | ||
#if SHADER_TARGET >= 45 | ||
StructuredBuffer<float2> positionBuffer; | ||
StructuredBuffer<int> tagBuffer; | ||
StructuredBuffer<float2> velocityBuffer; | ||
StructuredBuffer<int> IDBuffer; | ||
#endif | ||
``` | ||
|
||
- The variables are as follows: | ||
- positionBuffer: a buffer that stores the positions of the particles. | ||
- tagBuffer: a buffer that stores the tags of the particles, including logical tags and RGB values. | ||
- velocityBuffer: a buffer that stores the velocities of the particles. | ||
- IDBuffer: a buffer that stores the IDs of the particles within Soft2D. As particles are added or destroyed, their IDs remain unchanged. | ||
|
||
Lastly, we need to add `UNITY_VERTEX_INPUT_INSTANCE_ID` to the struct of the input vertex shader. | ||
|
||
## Vertex Shader | ||
|
||
First, we need to obtain the instance_id of the current particle, since the buffers provided by Soft2D are indexed based on instance_id: | ||
```shaderlab | ||
UNITY_SETUP_INSTANCE_ID(IN); | ||
UNITY_TRANSFER_INSTANCE_ID(IN, OUT); | ||
int instance_id = UNITY_GET_INSTANCE_ID(IN); | ||
``` | ||
|
||
Since Soft2D provides the position of the particle, we need to manually apply a model transformation to the particle: | ||
```shaderlab | ||
int instance_id = UNITY_GET_INSTANCE_ID(IN); | ||
float2 center = positionBuffer[instance_id]; | ||
float4 data = float4(center, -0.2f, 1.0f); | ||
float3 localPosition = IN.positionOS.xyz * _InstanceSize * data.w; | ||
float3 worldPosition = data.xyz + localPosition; | ||
``` | ||
Next, apply the VP transformation and obtained the correct position of the particle in homogeneous coordinates. | ||
```shaderlab | ||
OUT.positionCS=mul(UNITY_MATRIX_VP, float4(worldPosition, 1.0f)); | ||
``` | ||
|
||
In addition to the position of the particle, we can also obtain its current velocity and label: | ||
```shaderlab | ||
OUT.velocity = velocityBuffer[instance_id]; | ||
uint buffer = tagBuffer[instance_id]; | ||
``` | ||
|
||
The higher 8 bits of the tagBuffer represent the logical label of the particle, while the lower 24 bits represent the RGB value of the particle. We need to separate them: | ||
```shaderlab | ||
uint tag=(buffer >> 24)&0x7; | ||
float3 baseColor; | ||
uint rbits=(buffer >> 16)&0xFF; | ||
baseColor.r=rbits/255.0; | ||
uint gbits=(buffer >> 8)&0xFF; | ||
baseColor.g=gbits/255.0; | ||
uint bbits=buffer & 0xFF; | ||
baseColor.b=bbits/255.0; | ||
``` | ||
The obtained RGB values range from 0 to 255, and we need to convert them to floating-point numbers ranging from 0.0 to 1.0. | ||
|
||
> Now, we have obtained all the parameters required to write a regular material shader. | ||
## Script Setting | ||
|
||
Change the particle rendering mode to Custom in the inspector window of Soft2DManager, and drag the custom material into the Instance Material slot. | ||
|
||
 | ||
|
||
You can also set the rendering layer and the mesh for the particle here. For more details, please refer to [Soft2DManager.md](). | ||
|
||
Once you have set the parameters for the custom material, you can run the simulation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# Custom Trigger | ||
|
||
> Users can customize the events triggered by Triggers to manipulate Soft2D particles. We will introduce two methods: using built-in functions and custom delegates. | ||
> The term "Trigger" used in this article refers to the triggers within Soft2D. | ||
## Built-in Functions | ||
|
||
We can use the [built-in functions]() of Triggers to manipulate particles. | ||
|
||
## Custom Delegates | ||
|
||
> Video: [Tutorial](../../GIFs/TriggerCallback.mp4) | ||
### Basic Structure | ||
|
||
Users can write their own method and pass it to Soft2D for invocation. The basic structure of this method is as follows: | ||
```csharp | ||
[AOT.MonoPInvokeCallback(typeof(S2ParticleManipulationCallback))] | ||
public static void ManipulateParticlesInTrigger(IntPtr particles, int size) | ||
{ | ||
|
||
} | ||
``` | ||
In this function: | ||
- `particles` is a pointer to an array that contains information about all particles that entered the Trigger's range. | ||
- `size` is the total number of particles that entered the Trigger's range. | ||
|
||
The particle information is encapsulated in a structure called **S2Particle**: | ||
```csharp | ||
public struct S2Particle { | ||
public uint id; | ||
public S2Vec2 position; | ||
public S2Vec2 velocity; | ||
public uint tag; | ||
public uint is_removed; | ||
} | ||
``` | ||
- `id` represents the particle's ID within Soft2D. The particle's ID remains unchanged even if particles are added or removed. | ||
- `position` represents the current position of the particle. | ||
- `velocity` represents the current velocity of the particle. | ||
- `tag` represents the tag buffer of the particle. | ||
- `is_removed` indicates whether the particle has been removed. A value greater than 0 indicates that the particle has been removed. | ||
|
||
### Function Implementation | ||
|
||
To manipulate individual particles, we need to first retrieve the memory information of the current particle and convert it into the `S2Particle` structure: | ||
```csharp | ||
IntPtr particlePtr = IntPtr.Add(particles, i * particleSize); | ||
S2Particle particle = Marshal.PtrToStructure<S2Particle>(particlePtr); | ||
``` | ||
After the manipulations are completed, we need to pack the structure and return it to the original memory: | ||
```csharp | ||
Marshal.StructureToPtr(particle, particlePtr, false); | ||
``` | ||
In this way, we have completed the function structure for per-particle manipulations: | ||
```csharp | ||
[AOT.MonoPInvokeCallback(typeof(S2ParticleManipulationCallback))] | ||
public static void ManipulateParticles(IntPtr particles, int size) | ||
{ | ||
int particleSize = Marshal.SizeOf<S2Particle>(); | ||
for (int i = 0; i < size; i++) | ||
{ | ||
IntPtr particlePtr = IntPtr.Add(particles, i * particleSize); | ||
S2Particle particle = Marshal.PtrToStructure<S2Particle>(particlePtr); | ||
// Manipulation on particles... | ||
Marshal.StructureToPtr(particle, particlePtr, false); | ||
} | ||
} | ||
``` | ||
In the commented section of the code above, we can modify the content of the `S2Particle` structure to manipulate particles, such as removing particles that entered the Trigger: | ||
```csharp | ||
[AOT.MonoPInvokeCallback(typeof(S2ParticleManipulationCallback))] | ||
public static void ManipulateParticles(IntPtr particles, int size) | ||
{ | ||
int particleSize = Marshal.SizeOf<S2Particle>(); | ||
for (int i = 0; i < size; i++) | ||
{ | ||
IntPtr particlePtr = IntPtr.Add(particles, i * particleSize); | ||
S2Particle particle = Marshal.PtrToStructure<S2Particle>(particlePtr); | ||
particle.is_removed = 1; | ||
Marshal.StructureToPtr(particle, particlePtr, false); | ||
} | ||
} | ||
``` | ||
If you want to modify external variables within this function, make sure those variables are static. | ||
|
||
### Function Invocation | ||
|
||
You can call `void InvokeCallbackAsync(S2ParticleManipulationCallback callback)` in order to let Soft2D execute the code within the callback. | ||
|
||
For example, to have a Trigger delete all particles that enter its range: | ||
```csharp | ||
private ETrigger trigger; | ||
... | ||
private void Update(){ | ||
trigger.InvokeCallbackAsync(ManipulateParticles); | ||
... | ||
} | ||
``` | ||
- **Do not** use multicast delegates (loading multiple functions) as the callback when calling `void InvokeCallbackAsync(S2ParticleManipulationCallback callback)`, as it can cause the Soft2D program to crash. | ||
- After invoking the function, the callback runs **synchronously** with the subsequent code. To ensure asynchronous execution, you can add a signal flag within the callback: | ||
```csharp | ||
private ETrigger trigger; | ||
private static bool locked = true; | ||
... | ||
private void Update(){ | ||
trigger.InvokeCallbackAsync(ManipulateParticles); | ||
if (!locked){ | ||
... | ||
} | ||
} | ||
|
||
[AOT.MonoPInvokeCallback(typeof(S2ParticleManipulationCallback))] | ||
public static void ManipulateParticles(IntPtr particles, int size) | ||
{ | ||
... | ||
locked = false; | ||
} | ||
``` | ||
- Calling this function only executes the callback once. Make sure to call this function every frame within the Trigger's working cycle to ensure its execution. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Debug Tools | ||
|
||
> The terms "Collider" and "Trigger" used in this article refer to the collision bodies and triggers within Soft2D. Unity's collision bodies and triggers will be indicated specifically. | ||
> Debug tools provide a way for users to visualize the positions and motion states of Colliders and Triggers within Soft2D during runtime. | ||
## Video | ||
|
||
[Video](../../GIFs/DebugTools.mp4) | ||
|
||
## Parameter Panel | ||
|
||
- Enable Debug Tools: open the Debug Tools window. | ||
- Collider Color: represents the color of colliders in the Debug Tools. | ||
- Trigger Color: represents the color of triggers in the Debug Tools. | ||
|
||
Effect without Debug Tools: | ||
 | ||
|
||
Effect with Debug Tools: | ||
 | ||
|
||
## Important Notes | ||
|
||
- The Debug Tools can only be enabled in Unity Editor mode. | ||
- Enabling the Debug Tools will generate a Quad in the scene with the same position and size as the simulation area. Its z-axis is set to -0.2, and users can freely drag and view it in the scene. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Body | ||
|
||
> Body is a simulated continuum composed of a group of particles. A body has attributes such as shape, center and material. Body corresponds to the EBody class in the code. | ||
## How to Use Body GameObject | ||
|
||
 | ||
|
||
## Parameter Panel | ||
|
||
The parameter panel for Body consists of three sections: Body Settings, Material Settings, and Color Settings. | ||
|
||
### Body Settings | ||
|
||
- Shape | ||
- The initial shape of the Body. Depending on the specific shape, Soft2D will automatically sample and generate particles inside it. Currently, it supports several types: box, circle, ellipse, capsule, and polygon. | ||
- For detailed documentation on shapes, see: [Shape.md](../Concepts/Shape.md) | ||
- Linear Velocity | ||
- The initial linear velocity of the Body, measured in m/s. | ||
- Angular Velocity | ||
- The initial angular velocity of the Body, measured in s^-1. | ||
- Life Cycle | ||
- The duration from the generation to the automatical destruction of the Body. Measured in seconds. A value less than or equal to 0 means it will never be automatically destroyed. | ||
|
||
### Material Settings | ||
|
||
[Detailed Content](../Concepts/Material.md) | ||
|
||
### Color Settings | ||
|
||
- Base Color | ||
- The color given to the particles inside the Body. | ||
- Randomize Color | ||
- Randomly generated color for the particles inside the Body. | ||
|
||
## Built-in Functions | ||
|
||
[Detailed Content]() | ||
|
||
# Other Types of Body | ||
|
||
## CustomBody | ||
|
||
CustomBody is a Body where the user specifies the sampling points. It corresponds to the ECustomBody class in the code. | ||
|
||
### How to Use CustomBody GameObject | ||
|
||
 | ||
|
||
### Parameter Panel | ||
|
||
- Particle Local Space Position | ||
- The position of particles inside the CustomBody in local space. | ||
|
||
## MeshBody | ||
|
||
MeshBody is a Body with a topological relationship. Each vertex position in the input mesh generates a Soft2D particle, and they follow the topological relationship of the triangles inside the mesh. It corresponds to the EMeshBody class in the code. | ||
|
||
### How to Use MeshBody GameObject | ||
|
||
 | ||
|
||
### Parameter Panel | ||
|
||
- Mesh | ||
- The mesh corresponding to the MeshBody. | ||
- Mesh Scale | ||
- The scaling factor for generating the MeshBody from the mesh. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Collider | ||
|
||
> A Collider is an obstacle that obstructs the movement of a body. It corresponds to the `ECollider` type in the code. | ||
> In this article, Collider refers to the collider component within Soft2D. | ||
## How to Use Collider GameObject | ||
|
||
 | ||
|
||
## Parameter Panel | ||
|
||
- Unity 2D Collider | ||
- The Unity 2D Collider component of the Collider, currently supporting Box / Circle / Capsule / Polygon / Composite types. | ||
- The type and size of the Collider are controlled by its Collider2D component. | ||
- Motion State | ||
- Whether the Collider is static or dynamic. When true, the object is dynamic. | ||
- Linear Velocity | ||
- The linear velocity of the Collider. Measured in m/s. | ||
- Angular Velocity | ||
- The angular velocity of the Collider. Measured in s^-1. | ||
- Update Position and Rotation Automatically | ||
- Whether to automatically update the position and rotation of the collider. When true, the plugin synchronizes the collider's state with Soft2D every frame. | ||
- > Due to the time interval difference between Soft2D and Unity, the Collider's motion state may not be consistent on both sides. Enabling this feature for too many colliders may cause simulation lag. | ||
- Collision Type | ||
- The collision type between Soft2D particles and the Collider. There are three types: | ||
- **Separate**: Particles separate from the Collider immediately after collision. | ||
- **Slip**: Particles slide on the Collider for a while after collision. | ||
- **Sticky**: Particles stick to the Collider after collision. | ||
- Friction Coefficient: The friction coefficient between Soft2D particles and the Collider. | ||
- Restitution Coefficient: The restitution coefficient (bounciness) of Soft2D particles on the Collider. | ||
|
||
## Built-in Functions | ||
|
||
[Detailed Content]() |
Oops, something went wrong.