Only this pageAll pages
Powered by GitBook
1 of 10

Particle Water Shader Pro - URP

Loading...

Getting Started

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Introduction

Different from prior version , the principle of this plugin is based on the paper A Narrow-Range Filter for Screen-Space Fluid Rendering.

Fluid simulation is generally based on grids or particles. In consideration of real-time performance, the SPH-based method (a particle-based method) is still used.

Unity does not have a very suitable fluid rendering plugin, which is the main reason for this plugin. I also noticed that there is indeed an very old implementation "Screen Space Fluids Pro"on the Asset Store (last update at year 2016).

In the process of using, I feel that I can do better, no matter from the efficiency or visual effects or ease of use and scalability, thus this plugin was born.

Extend particle input

Currently, there are two subclasses in the project that inherit from SSF_ParticleSource, namely SSF_LoadParticlesFromParticleSystem and SSF_LoadParticlesFromFile. SSF_ParticleSource represents the source of particle data required for rendering and is also the starting point for extension.

Considering that users may have their own source of particle data, such as a particle solution system running in parallel with the GPU, or imported pre-made particle data, here we will explain how to extend the input of particle data.

Particle Data Struct

The structure of particle data in SSF is as follows:

If you modify the particle’s data structure, you need to pay attention to replacing 32 in particleBuffer = new ComputeBuffer (getParticleNum (), 32); in SSF_ParticleSource.cs with the number of bytes of particle data. At the same time, corresponding changes should be made in DepthColorThickness.shader.

Explain SSF_ParticleSource

The input and update of extended data is to create a new class inheriting from SSF_ParticleSource and implement the corresponding virtual function.

The following two member variables exist in SSF_ParticleSource:

Where particleBuffer is used to provide data to generate related textures for rendering.

You can notice that the following member function modifiers in SSF_ParticleSource are public virtual:

  • SetupParticleBufferData ()

  • UpdateParticleBufferData ()

In SetupParticleBufferData , ParticlesData needs to be created and assigned, and updated in UpdateParticleBufferData () , neither of these operations need to involve particleBuffer.

You should also implement UpdateBounds() , the bounds is used for culling out of view particles, which saves a lot performance.

Example

You can also refer to SSF_LoadParticlesFromParticleSystem, this is a bit complicated and tedious.

public struct SSF_particle
{
    public Vector3 position;
    public Color color;
    public float radius;
}
protected ComputeBuffer particleBuffer;// Buffer sent to GPU
protected SSF_particle[] particlesData;// Particle Data for above buffer

Step By Step Usage

  1. Create an empty Scene named SSF_Test

  2. Create a ParticleSystem

    1. deactivate its Renderer function

    2. set its StartColor to red

    3. Emission -> Rate over time to 1000

The Inspector should looks like

  1. Add SSF_LoadParticlesFromParticleSystem onto the GameObject Particle System

Note that you shall assign the Particle Systems field.

  1. Enter playmode and you shall see

Check other demos to see how it works with particle systems.

Mouse over the fields of the script to see tooltips say how the parameters work.

Welcome

This is a Unity shader plugin, not a fluid physics simulation plugin. It is used to render particle data into a smooth liquid surface. Ideal for rendering simulation systems that use particles as simulation units.

Magic happens when the pure unity particle system gains power through this particle shader plugin.

This version is specially made based On Unity6's Rendergraph system.

It has huge changes compared to the previous version.

  • The newly adopted algorithm brings huge performance, performance, and user experience gains:

    • The number of iterations required for smoothing has been reduced from 150 to 3

    • The time required to run the algorithm Reduced (from 5.8ms to 0.5ms) nearly 10x times

    • Higher resolution and finer surface, with clear layers of water droplets and water surface

    • No param tuning anymore! Plane fitting parameters Reduced from 5 to 0

  • New Rendering process brings performance improvements in the following aspects

    • Required Smoothing + rendering Reduced from Per Fluid Surface Per Frame to Once Per Frame

    • Required RenderTextures Reduced from One Set for all RenderSurfaces to One Set Globally

    • The RenderTexture used is managed by the Rendergraph, further increasing potential bandwidth savings

  • Introduce new DebugVisualize functionality helps locate data problems or debug parameter effects

  • Added down sample option to further reduce bandwidth pressure

  • A unified rendering shader while supporting custom visual parameters for each ParticleSource.

Jump right in

Getting Started

Step by step

Parameters Tuning

Quickstart

First you need to download this plugin from the Unity Asset Store or Fab.

Please buy it legally, i am a solo developer who has to earn something to support coding.

Import

  • First , please make sure you are at a Unity version greater or equal to Unity 6000.

  • Then, please make sure your project is using universal render pipeline.

  • Check google if you do not know how to create a URP unity project , please ~

  • Import the package and you will get the folder view like below:

Add renderer feauture (SSF Renderer Feature) to your renderer

Also fill in the fields if any one is empty , though they were expected to be auto loaded.

All is set! Party Time~

Open the Scene at Assets/SSF_Particle2Fluid_ShaderUtil/Scenes/Demo_File.unity and enter play mode. You shall see:

Also, you can check other scene file under the folder Assets/SSF_Particle2Fluid_ShaderUtil/Scenes/

Paramters Tuning

This page will tell you all need to know on the parameters to ajust the visual outlook.

You will notice that there are a set of parameters on the SSF_LoadParticlesFromParticleSystem inspector:

The meaning of these parameters are as follows:

Name
Description

ParticleBufferUpdateInterval

The interval for updating particle data to GPU, <0 means update every frame. Adjust this value to your preferred visual frame rate

Thickness

The thickness of the liquid. The higher the value, the more precipitated and solid the color will be visually.

Noise

The detail turbulence of the surface. The higher the value, the more turbulence the surface will show. It is implemented by adding perturbation to the surface normal.

Render Params

Fluid surface rendering related parameters are listed separately below and may change with version iterations

Render Params

Name
Description

IsTransparent

0 for traditional blinn-phong rendering, 1 for fluid rendering, value in-between means blending

Ior

Refractive Index of Fluid (1.33 for water...)

Smoothness

higher value for more smoothness

Fresnel Power

higher value gives more refraction

Min/Max Reflection Ratio

this constraints the amount of reflection, if no reflection is needed, just set them to 0, vice versa, 1 for no refraction

Ambient/Diffuse/Specular Color

Very traditional Blinn-phong model

Here's some comparisions on differnt paramters.

Non trasparent
transparent
high thickness
low thickness
no reflection(pure refraction)
reflection and refraction
no reflection, high fresnel power
no reflection, normal fresnel power

DebugVisualize

Toggle on the "Debug visualize" on the Renderer Feature to check the output.

Switch the DebugTexture type to see different debug informations.

Normal
Thickness
Color

Fluid Shader File

For anyone who wants to modify the shader to tweak the shading functionality, I will explain how the shading process works, though i personally not recommend.

The files used for fluid shading are in Assets/SSF_Particle2Fluid_ShaderUtil/Shaders/FluidRender.shader

The whole process can be divided into the following steps:

  • Read the surface parameters through the map:

TEXTURE2D(_ColorTex);
TEXTURE2D_FLOAT(_EyeDepthTex);
TEXTURE2D(_EyeNormalTex);
TEXTURE2D_FLOAT(_ParticleDataTex);
TEXTURE2D_FLOAT(_ThicknessTex);
StructuredBuffer<SSF_RenderParams> _RenderParams;

....
float fluidEyeDepth = SAMPLE_TEXTURE2D(_EyeDepthTex, sampler_PointClamp, uv).r;
float3 fluidColor = SAMPLE_TEXTURE2D(_ColorTex, sampler_LinearRepeat, uv).xyz;
float thickness = SAMPLE_TEXTURE2D(_ThicknessTex, sampler_LinearRepeat, uv).r;
float3 fluidEyeNormal = SAMPLE_TEXTURE2D(_EyeNormalTex, sampler_LinearRepeat, uv).xyz;
int paramIndex = SAMPLE_TEXTURE2D(_ParticleDataTex, sampler_PointClamp,uv).x;
float smoothness = _RenderParams[paramIndex].smoothness;
float refractiveIndex = _RenderParams[paramIndex].ior;
float fresnelPower = _RenderParams[paramIndex].fresnelPower;
float minReflectionRatio = _RenderParams[paramIndex].minReflectionRatio;
float maxReflectionRatio = _RenderParams[paramIndex].maxReflectionRatio;
float isTransparent = _RenderParams[paramIndex].isTransparent;
float4 ambientColor = _RenderParams[paramIndex].ambientColor;
float4 diffuseColor = _RenderParams[paramIndex].diffuseColor;
float4 specularColor = _RenderParams[paramIndex].specularColor;
  • We first filter out the pixels that are not blocked by the fluid particles and return them to the previously rendered color.

half4 color = SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearRepeat, uv, _BlitMipLevel);
#if UNITY_REVERSED_Z
real depth = SampleSceneDepth(uv);
#else
// Adjust z to match NDC for OpenGL
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(UV));
#endif
float sceneEyeDepth = LinearEyeDepth(depth, _ZBufferParams);
       	if(fluidEyeDepth <= 0.0f || fluidEyeDepth > 1000.0f ||sceneEyeDepth < fluidEyeDepth) {
	return color;
}

Based on the above parameters, you can play with the shader to create different effects.

  • For example, I first made a blinn-phong rendering

// Calculate non-transparent color, using old model
Light mainLight = GetMainLight();
// the light direction is also expect to be a inverse since we care its relative angle to the normal
// so its world direction should be considered to treate inversely
float3 lightDir = -mul(unity_MatrixV, float4(mainLight.direction, 0.0)).xyz;
float3 specular = LightingSpecular(mainLight.color,lightDir,fluidEyeNormal,viewDir,specularColor,smoothness*32);
float3 diffuse = LightingLambert(mainLight.color,lightDir,fluidEyeNormal)*diffuseColor.rgb;
float3 ambient = ambientColor.rgb;
float3 finalColorNonTransparent = ambient + diffuse + specular;
  • In addition, you can use parameters such as thickness, fluid color, IOR, smoothness, etc. to create water rendering effects that include refraction and reflection:

// Calculate transparent color, with a combination of refraction and reflection
float eta =  1.0 / refractiveIndex;
float F0 = ((1.0 - eta) * (1.0 - eta)) / ((1.0 + eta) * (1.0 + eta));
float fresnelRatio = clamp(F0 + (1.0 - F0) * pow((1.0 - dot(viewDir, fluidEyeNormal)), fresnelPower), 0, 1);

float3 reflectionDir = reflect(-viewDir, fluidEyeNormal);
float3 reflectionDirWS = mul(unity_MatrixInvV, float4(reflectionDir, 0.0)).xyz;

float3 reflectionColor = GlossyEnvironmentReflection(reflectionDirWS, smoothness, half(1.0));

float3 colorAttennuation = computeAttennuation(thickness*5, 1-fluidColor);

half3 refractionDir = refract(-viewDir, fluidEyeNormal, eta);
float3 refractionColor = colorAttennuation * SAMPLE_TEXTURE2D(_BlitTexture,sampler_LinearRepeat, uv + refractionDir.xy * thickness  * 0.1f).xyz;

fresnelRatio = clamp(fresnelRatio, minReflectionRatio, maxReflectionRatio);
float3 finalColorTransparent = lerp(refractionColor, reflectionColor, fresnelRatio) ;

Of course, we can also implement shadow effects, but since Unity's API is not stable and open enough, we will consider updating it later.

Common Q&A

Q: why my surface is sometimes black?

A:

Bake the scene lighting if you do not see reflection! Because the scripts needs the light reflection data. If not baked, the default reflection data is black.

Or else, you may pass in the particle color as black, or there's no lights in the scene.