Snow
A simple snow surface implementation is to calculate dot product of normal and a custom direction.
half snowSurfaceMask = clamp(dot(normalWS, _SnowDirection), 0.0f, 1.0f);
It is similar to NdotL
. We can add some small scale gradient noise or simple noise to this mask, and make it white. When we change the _SnowDirection
, we might add some unwanted artifacts. To solve this problem, multiplying another upward snow mask to the snow surface mask.
Unity Shader
saturate vs. lerp
saturate is compiled to:
// original shader
return saturate(_ColorA);
// compiled
SV_Target0 = _ColorA;
#ifdef UNITY_ADRENO_ES3
SV_Target0 = min(max(SV_Target0, 0.0), 1.0);
#else
SV_Target0 = clamp(SV_Target0, 0.0, 1.0);
#endif
return;
lerp is compiled to:
// original shader
return lerp(_ColorA, _ColorB, _ColorLerp);
// compiled
u_xlat16_0 = (-_ColorA) + _ColorB;
SV_Target0 = vec4(_ColorLerp) * u_xlat16_0 + _ColorA;
return;
The malioc’s profiling result is:
saturate:
Main shader
===========
Work registers: 18
Uniform registers: 4
Stack spilling: false
16-bit arithmetic: N/A
FMA CVT SFU LS V T Bound
Total instruction cycles: 0.00 0.08 0.00 0.00 0.00 0.00 CVT
Shortest path cycles: 0.00 0.05 0.00 0.00 0.00 0.00 CVT
Longest path cycles: 0.00 0.08 0.00 0.00 0.00 0.00 CVT
FMA = Arith FMA, CVT = Arith CVT, SFU = Arith SFU,
LS = Load/Store, V = Varying, T = Texture
lerp:
Main shader
===========
Work registers: 18
Uniform registers: 4
Stack spilling: false
16-bit arithmetic: N/A
FMA CVT SFU LS V T Bound
Total instruction cycles: 0.00 0.08 0.00 0.00 0.00 0.00 CVT
Shortest path cycles: 0.00 0.05 0.00 0.00 0.00 0.00 CVT
Longest path cycles: 0.00 0.08 0.00 0.00 0.00 0.00 CVT
FMA = Arith FMA, CVT = Arith CVT, SFU = Arith SFU,
LS = Load/Store, V = Varying, T = Texture
So they have the same cost performance on profiling.
It worth to notice that the malioc can’t profile the SRP Batcher’s CBuffer, we have to remove the CBuffer when we compile the sahder code. It probably has something to do with hlsl vs. glsl in malioc support. related stackoverflow: https://stackoverflow.com/questions/36115095/hlsl-cbuffer-equivalent-in-glsl
glsl vs. hlsl
OpenGL Shading Language (GLSL) is a high-level shading language and based on C. It is for OpenGL. High-level shading langauge (HLSL) is created by Microsoft.
Lit
The option “Source: Metallic Alpha” and “Source: Albedo Alpha” controls the smoothness’ source. It could be the Metallic Map’s alpha channel or Base Map’s alpha channel.
Lit also uses a function to sample the Metallic Map differently based on workflow and smoothness source.
half4 SampleMetallicSpecGloss(float2 uv, half albedoAlpha)
{
half4 specGloss;
#ifdef _METALLICSPECGLOSSMAP
specGloss = SAMPLE_METALLICSPECULAR(uv);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _Smoothness;
#else
specGloss.a *= _Smoothness;
#endif
#else // _METALLICSPECGLOSSMAP
#if _SPECULAR_SETUP
specGloss.rgb = _SpecColor.rgb;
#else
specGloss.rgb = _Metallic.rrr;
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
specGloss.a = albedoAlpha * _Smoothness;
#else
specGloss.a = _Smoothness;
#endif
#endif
return specGloss;
}
If Metallic Map exists, then the shader will sample the map. Otherwise, the shader will either use _Metallic
or _SpecColor
to set up metallic value or the the specular light. Then it will calculate smoothness based on the source.
Particle System
IJobParticleSystemParallelFor.Execute
This job interface essentially makes what GetParticles
and SetParticles
did more efficiently. The key part of this interface is the event and the job structure.
void OnParticleUpdateJobScheduled() // the job event function
{
// excute job in here
}
struct ParticleJob : IJobParticleSystemParallelFor
{
public void Execute(ParticleSystemJobData particles, inti)
{
// update particles
}
}
Please notice that the job script must stay next to the particle system component, otherwise Unity will not call the job event function.
Custom Vertex Stream
We can set custom data in particles vertex. In such away, we can add more data other than POSITION
, NORMAL
, and UV
. For example, Center gives the center particle’s center in particle’s assigned space. We can use it to calculate a sphere mask to control the particle’s movement. Or we can add a vector to [Custom1.xyz](<http://Custom1.xyz>)
to give a unifrom moving direction to all particles and use a noise texture to offset them to create a wave.
Math
Perpendicular in 2D
half2 v2;
half2 perpendicular_cw = half2(v2.y, -v2.x); // clock wise
hafl2 perpendicular_ccw = half2(-v2.y, v2.x); // counter clock wise