ici_recycle_vr/Assets/LiquidVolumePro/Resources/Shaders/LVLiquidPassBase.cginc
Diaconescu Andrei-Alexandru 19674bfe5d Am adaugat ICI Recycle
2025-05-26 12:54:36 +03:00

440 lines
13 KiB
HLSL

// Set by the asset automatically
#define FORCE_GLES_COMPATIBILITY 0
#define LIQUID_VOLUME_SCATTERING
#define LIQUID_VOLUME_SMOKE
#define LIQUID_VOLUME_BUBBLES
#define LIQUID_VOLUME_FP_RENDER_TEXTURES
//#define LIQUID_VOLUME_ORTHO
#define LIQUID_VOLUME_USE_NOISE3D
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"
struct appdata_base {
float4 vertex : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Input {
float4 positionCS : SV_POSITION;
float3 realPos : TEXCOORD0;
float4 vertex : TEXCOORD1;
float3 camPos : TEXCOORD2;
float4 screenPos : TEXCOORD3;
float3 normalWS : TEXCOORD5;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
struct SurfaceOutput {
half3 Albedo; // diffuse color
half3 Normal; // tangent space normal, if written
half3 Emission;
half Specular; // specular power in 0..1 range
half Gloss; // specular intensity
half Alpha; // alpha for transparencies
};
sampler2D _NoiseTex2D;
float _DepthAwareOffset;
#if LIQUID_VOLUME_DEPTH_AWARE_PASS
TEXTURE2D_X_FLOAT(_VLFrontBufferTexture);
#endif
#if LIQUID_VOLUME_IRREGULAR
TEXTURE2D_X_FLOAT(_VLBackBufferTexture);
#endif
float3 _VertexOffset;
half4 _Color1;
half4 _Color2;
half4 _FoamColor;
float _FoamMaxPos;
int _FoamRaySteps;
float _FoamDensity;
float _FoamBottom;
float _FoamTurbulence;
float _LevelPos;
float3 _FlaskThickness;
float4 _Size;
float3 _Center;
float _Muddy;
float4 _Turbulence;
float _DeepAtten;
half4 _SmokeColor;
float _SmokeAtten;
int _SmokeRaySteps;
float _SmokeSpeed;
float _SmokeHeightAtten;
int _LiquidRaySteps;
half4 _GlossinessInt;
float _FoamWeight;
float4 _Scale;
float _UpperLimit;
float _LowerLimit;
float3 wsCameraPos;
half3 _EmissionColor;
float _DoubleSidedBias;
float _BackDepthBias;
float4x4 _Rot;
float _TurbulenceSpeed;
float _FlaskBlurIntensity;
half _Glossiness;
half4 _FlaskTint;
half4 _FlaskColor;
half3 _LightColor;
#if defined(LIQUID_VOLUME_SCATTERING)
float4 _PointLightPosition[6];
half4 _PointLightColor[6];
float _PointLightInsideAtten;
#endif
int _LVForcedInvisible;
// Open GL 2.0 / WebGL support
#if SHADER_API_GLES || FORCE_GLES_COMPATIBILITY
#define WEBGL_OR_LEGACY
#endif
#if defined(WEBGL_OR_LEGACY)
sampler2D _Noise2Tex;
inline float noise3D(float3 x) {
x *= 100.0;
float3 f = frac(x);
float3 p = x - f;
f = f*f*(3.0-2.0*f);
float4 xy = float4(p.xy + float2(37.0,17.0)*p.z + f.xy, 0, 0);
xy.xy = (xy.xy + 0.5) / 256.0;
float2 zz = tex2Dlod(_Noise2Tex, xy).yx;
return lerp( zz.x, zz.y, f.z );
}
#define SAMPLE_NOISE_3D(tex,pos) noise3D( (pos).xyz)
#define BEGIN_LOOP(k,iterations,defaultIterations) for(int k=0;k<defaultIterations;k++) if (k<iterations) {
#define END_LOOP }
#else
sampler3D _NoiseTex;
#define SAMPLE_NOISE_3D(tex,pos) tex3Dlod(tex,pos)
#define BEGIN_LOOP(k,iterations,defaultIterations) for(int k=0;k<iterations;k++) {
#define END_LOOP }
#endif
#if !defined(LIQUID_VOLUME_USE_NOISE3D)
#undef SAMPLE_NOISE_3D
#define SAMPLE_NOISE_3D(x,y) 0.5
#endif
#if LIQUID_VOLUME_USE_REFRACTION
half4 LightingWrappedSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
half diff = saturate(lightDir.y * 2.0);
half3 h = normalize (lightDir + viewDir);
half nh = saturate (dot (s.Normal, h));
half spec = pow (nh, _GlossinessInt.x);
half4 c;
// apply light scattering
#if defined(LIQUID_VOLUME_SCATTERING)
half sunDiffIntensity = pow( max( dot( viewDir, -lightDir), 0.0 ), _GlossinessInt.y) * _GlossinessInt.z;
diff += sunDiffIntensity;
#endif
half fresnelTerm = Pow4(1.0 - saturate(dot(s.Normal, viewDir)));
spec += fresnelTerm * _GlossinessInt.w;
half3 ambient = SampleSH(s.Normal);
c.rgb = (s.Albedo * _LightColor * diff + _LightColor * spec * diff + ambient * fresnelTerm) * atten + s.Emission;
c.a = s.Alpha;
return c;
}
#else
half4 LightingWrappedSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
half diff = saturate(lightDir.y * 2.0);
half4 c;
// apply light scattering
#if defined(LIQUID_VOLUME_SCATTERING)
half sunDiffIntensity = pow( max( dot( viewDir, -lightDir), 0.0 ), _GlossinessInt.y) * _GlossinessInt.z;
diff += sunDiffIntensity;
#endif
half fresnelTerm = Pow4(1.0 - saturate(dot(s.Normal, viewDir)));
half3 ambient = SampleSH(s.Normal);
c.rgb = (s.Albedo * _LightColor * diff + ambient * fresnelTerm) * atten + s.Emission;
c.a = s.Alpha;
return c;
}
#endif
half4 LightingSimple (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
half4 c;
c.rgb = s.Albedo * _LightColor * atten + s.Emission;
c.a = s.Alpha;
return c;
}
void intSphere(float3 rd, out float t0, out float t1) {
float3 d = wsCameraPos - _Center;
float b = dot(rd, d);
float c = dot(d,d) - _Size.w * _Size.w;
float t = sqrt(b*b - c);
t0 = -b-t;
t1 = -b+t;
}
void intCylinder(float3 rd, out float t0, out float t1) {
#if LIQUID_VOLUME_NON_AABB
rd = mul((float3x3)_Rot, rd);
#endif
float3 d = wsCameraPos - _Center;
#if LIQUID_VOLUME_NON_AABB
d = mul((float3x3)_Rot, d);
#endif
float a = dot(rd.xz, rd.xz);
float b = dot(rd.xz, d.xz);
float c = dot(d.xz,d.xz) - _Size.w * _Size.w;
float t = sqrt(max(b*b-a*c,0)); // max prevents artifacts with MSAA
t0 = (-b-t)/a;
t1 = (-b+t)/a;
// cylinder cap
float sy = _Size.y * 0.5 * _FlaskThickness.y;
float h = abs(d.y) - sy;
if (h>0) {
float rdl = dot(rd.xz / rd.y, rd.xz / rd.y);
float tc = h * sqrt (1.0 + rdl);
t0 = max(t0, tc);
}
h = sign(rd.y) * -d.y + sy;
if (h>0) {
float rdl = dot(rd.xz / rd.y, rd.xz / rd.y);
float tc = h * sqrt (1.0 + rdl);
t1 = min(t1, tc);
}
}
void intBox(float3 rd, out float t0, out float t1) {
#if LIQUID_VOLUME_NON_AABB
rd = mul((float3x3)_Rot, rd);
#endif
float3 ro = wsCameraPos - _Center;
#if LIQUID_VOLUME_NON_AABB
ro = mul((float3x3)_Rot, ro);
#endif
float3 invR = 1.0 / rd;
float3 boxmin = - _Size.w;
float3 boxmax = + _Size.w;
float3 tbot = invR * (boxmin - ro);
float3 ttop = invR * (boxmax - ro);
float3 tmin = min (ttop, tbot);
float3 tmax = max (ttop, tbot);
float2 tt0 = max (tmin.xx, tmin.yz);
t0 = max(tt0.x, tt0.y);
tt0 = min (tmax.xx, tmax.yz);
t1 = min(tt0.x, tt0.y);
}
void vert(appdata_base v, out Input o) {
o = (Input)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.vertex = v.vertex;
o.vertex.w = dot(o.vertex.xz, _Turbulence.zw) + _TurbulenceSpeed;
o.vertex.xz *= 0.1.xx * _Turbulence.xx; // extracted from frag
o.vertex.xz += _Time.xx;
v.vertex.xyz *= _FlaskThickness;
VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
VertexNormalInputs normalInput = GetVertexNormalInputs(v.normalOS, v.tangentOS);
o.normalWS = normalInput.normalWS;
o.realPos = vertexInput.positionWS;
#if LIQUID_VOLUME_IGNORE_GRAVITY
o.realPos = mul((float3x3)_Rot, o.realPos - _Center) + _Center;
o.camPos = mul((float3x3)_Rot, _WorldSpaceCameraPos - _Center) + _Center;
#else
o.camPos = _WorldSpaceCameraPos;
#endif
o.positionCS = vertexInput.positionCS;
#if LIQUID_VOLUME_IRREGULAR
if (_LVForcedInvisible == 1) {
o.positionCS.xy = -10000;
}
#endif
o.screenPos = ComputeScreenPos(o.positionCS);
}
half4 raymarch(float4 vertex, float3 rd, float t0, float t1); // forward declaration
SAMPLER(sampler_point_clamp);
#if defined(LIQUID_VOLUME_FP_RENDER_TEXTURES)
#define texDistance(tex, uv) SAMPLE_TEXTURE2D_X(tex, sampler_point_clamp, uv).r
#else
inline float DecodeFloatRGBA( float4 enc ) {
float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/16581375.0);
return dot( enc, kDecodeDot );
}
#define texDistance(tex, uv) ( (1.0 / DecodeFloatRGBA(SAMPLE_TEXTURE2D_X(tex, sampler_point_clamp, uv))) - 1.0 )
#endif
float minimum_distance_sqr(float rayLengthSqr, float3 w, float3 p) {
// Return minimum distance between line segment vw and point p
float t = saturate(dot(p, w) / rayLengthSqr);
float3 projection = t * w;
return dot(p - projection, p - projection);
}
inline float3 ProjectOnPlane(float3 v, float3 planeNormal) {
float sqrMag = dot(planeNormal, planeNormal);
float dt = dot(v, planeNormal);
return v - planeNormal * dt / sqrMag;
}
float GetLightAttenuation(float3 wpos) {
float4 shadowCoord = TransformWorldToShadowCoord(wpos);
float atten = MainLightRealtimeShadow(shadowCoord);
return atten;
}
half3 boxBlur(float2 uv) {
const int BOXRADIUS = 5;
int kernel_window_size = BOXRADIUS*2+1;
half3 color = 0.0.xxx;
UNITY_UNROLL
for (int ry = -BOXRADIUS; ry <= BOXRADIUS; ++ry) {
UNITY_UNROLL
for (int rx = -BOXRADIUS; rx <= BOXRADIUS; ++rx) {
color += SampleSceneColor(uv + float2(rx,ry)/_ScreenParams.xy);
}
}
half w = (BOXRADIUS * 2 + 1) * (BOXRADIUS * 2 + 1);
return (color/w);
}
half4 frag (Input IN) : SV_Target {
UNITY_SETUP_INSTANCE_ID(IN);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN);
if (IN.vertex.y > _UpperLimit || IN.vertex.y < _LowerLimit) return 0.0.xxxx;
wsCameraPos = IN.camPos;
#if defined(LIQUID_VOLUME_ORTHO)
float3 cameraForward = UNITY_MATRIX_V[2].xyz;
float3 orthoCameraPos = ProjectOnPlane(IN.realPos - wsCameraPos, cameraForward) + wsCameraPos;
wsCameraPos = lerp(wsCameraPos, orthoCameraPos, unity_OrthoParams.w);
#endif
float t0, t1;
float3 rd = IN.realPos - wsCameraPos;
float dist = length(rd);
rd /= dist;
#if LIQUID_VOLUME_SPHERE
intSphere(rd, t0, t1);
#elif LIQUID_VOLUME_CUBE
intBox(rd, t0, t1);
#elif LIQUID_VOLUME_CYLINDER
intCylinder(rd, t0, t1);
#else
t0 = dist;
t1 = dist + _Size.x + _BackDepthBias;
#endif
t0 = max(0,t0); // needed if camera is inside container
#if LIQUID_VOLUME_DEPTH_AWARE || LIQUID_VOLUME_DEPTH_AWARE_PASS || LIQUID_VOLUME_IRREGULAR
float2 uv = IN.screenPos.xy / IN.screenPos.w;
#endif
#if LIQUID_VOLUME_DEPTH_AWARE
#if defined(LIQUID_VOLUME_ORTHO)
float vz = SampleSceneDepth(uv);
#if UNITY_REVERSED_Z
vz = 1.0 - vz;
#endif
float z = vz * _ProjectionParams.z;
#else
float depth = SampleSceneDepth(uv);
float4 raw = mul(UNITY_MATRIX_I_VP, float4(uv * 2.0 - 1.0, depth, 1.0));
float3 wpos = raw.xyz / raw.w;
float z = distance(wsCameraPos, wpos.xyz) + _DepthAwareOffset;
#endif
t1 = min(t1, z);
#endif
#if LIQUID_VOLUME_DEPTH_AWARE_PASS
float frontDist = texDistance(_VLFrontBufferTexture, UnityStereoTransformScreenSpaceTex(uv));
t1 = min(t1, frontDist);
#endif
#if LIQUID_VOLUME_IRREGULAR
float backDist = texDistance(_VLBackBufferTexture, UnityStereoTransformScreenSpaceTex(uv));
t1 = min(t1, backDist);
clip(t1-t0-_DoubleSidedBias);
#endif
half4 co = raymarch(IN.vertex,rd,t0,t1);
#if defined(LIQUID_VOLUME_SCATTERING)
float3 rayStart = wsCameraPos + rd * t0;
float rayLength = t1 - t0;
rayStart += rd * _PointLightInsideAtten;
rayLength -= _PointLightInsideAtten;
float3 ray = rd * rayLength;
float rayLengthSqr = rayLength * rayLength;
for (int k=0;k<6;k++) {
half pointLightInfluence = minimum_distance_sqr(rayLengthSqr, ray, _PointLightPosition[k].xyz - rayStart) / _PointLightColor[k].w;
co.rgb += _PointLightColor[k].rgb * (co.a / (1.0 + pointLightInfluence));
}
#endif
SurfaceOutput s = (SurfaceOutput)0;
s.Albedo = co.rgb;
s.Emission = co.rgb * _EmissionColor;
s.Alpha = co.a;
s.Normal = IN.normalWS;
half atten = 1.0; //GetLightAttenuation(IN.realPos); // uncomment if shadow support is required
co = LIGHTING(s, _MainLightPosition.xyz, -rd, atten);
#if !UNITY_COLORSPACE_GAMMA
co.rgb = SRGBToLinear(co.rgb);
#endif
#if LIQUID_VOLUME_USE_REFRACTION
float4 uvgrab = IN.screenPos;
half4 bgColor = half4(boxBlur(uvgrab.xy/uvgrab.w), _FlaskBlurIntensity);
co = lerp(bgColor, co, co.a);
#endif
return co;
}