Skip to content

Commit

Permalink
Commented code
Browse files Browse the repository at this point in the history
  • Loading branch information
leonjovanovic committed Sep 23, 2021
1 parent 1b146c8 commit 6cbfad3
Show file tree
Hide file tree
Showing 681 changed files with 1,194 additions and 1,959 deletions.
Binary file modified .vs/Water Shader/v16/.suo
Binary file not shown.
Binary file modified .vs/Water Shader/v16/Browse.VC.db
Binary file not shown.
2 changes: 1 addition & 1 deletion Assets/Materials/Pool/PoolWaterDistortional.mat
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Material:
- _GlossMapScale: 1
- _Glossiness: 0.9
- _GlossyReflections: 1
- _HeightScale: 0
- _HeightScale: 0.1
- _HeightScaleModulated: 6.16
- _Metallic: 0
- _Mode: 0
Expand Down
2 changes: 1 addition & 1 deletion Assets/Scenes/SampleScene.unity
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,7 @@ Transform:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 490070371}
m_LocalRotation: {x: -0, y: -0.17337641, z: -0, w: 0.98485565}
m_LocalPosition: {x: 2.8, y: -1.8, z: -7.6}
m_LocalPosition: {x: 2.8, y: -2.4, z: -7.6}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1984522254}
Expand Down
29 changes: 15 additions & 14 deletions Assets/Shaders/Caustics.shader
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@

// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0

//_MainTex is for object texture, _CausticsTex is for caustics texture
sampler2D _MainTex, _CausticsTex;
// We will sample twice same texture for more realistic caustics movement
float4 _Caustics_ST1, _Caustics_ST2;
float2 _Speed1, _Speed2;
// Different wavelengths of light diffract differently when passing through a medium.
// We will split RGB components to get that effect.
// _MaxHeight is there to limit caustics not to go above water and _Intensity provides strength of the output color
float _SplitRGB, _MaxHeight, _Intensity;

struct Input
Expand All @@ -45,44 +49,41 @@
half _Metallic;
fixed4 _Color;

// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)

float3 caustics(float2 uvTex) {
// Caustics sampling
// ------------ First caustics sampling ----------------
fixed2 uv = uvTex * _Caustics_ST1.xy + _Caustics_ST1.zw;
// To animate caustics we need to apply _Time for it to increase UV each time
uv += _Speed1 * _Time.y;
// RGB split
// RGB split of resampled pixel (we need to move UV with s offset and resample)
fixed s = _SplitRGB / 10;
fixed r = tex2D(_CausticsTex, uv + fixed2(+s, +s)).r;
fixed g = tex2D(_CausticsTex, uv + fixed2(+s, -s)).g;
fixed b = tex2D(_CausticsTex, uv + fixed2(-s, -s)).b;
fixed3 caustics1 = fixed3(r, g, b);
//2
// ------------ Second caustics sampling ----------------
uv = uvTex * _Caustics_ST2.xy + _Caustics_ST2.zw;
uv += _Speed2 * _Time.y;
// RGB split of resampled pixel
r = tex2D(_CausticsTex, uv + fixed2(+s, +s)).r;
g = tex2D(_CausticsTex, uv + fixed2(+s, -s)).g;
b = tex2D(_CausticsTex, uv + fixed2(-s, -s)).b;
fixed3 caustics2 = fixed3(r, g, b);
// Blend
// Blending the two patterns using the min operator
return min(caustics1, caustics2) * _Intensity;
}

void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
float2 uv = float2(IN.uv_MainTex.x, IN.uv_MainTex.y/1.5);
// Sample Main texture and multiply it with Color
fixed4 c = tex2D (_MainTex, uv) * _Color;
o.Albedo = c.rgb;
// If fragment Y position is not above _MaxHeight (water) apply caustics
if (IN.worldPos.y < _MaxHeight)
// Caustics will end on clear line at _MaxHeight which we dont want
// So we add second multiplicator to fade caustics as it is closer to _MaxHeight
o.Albedo.rgb += caustics(IN.uv_MainTex) * abs(min(1, ((_MaxHeight - IN.worldPos.y) / _MaxHeight))) * 2;

// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
Expand Down
22 changes: 20 additions & 2 deletions Assets/Shaders/Flow.cginc
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
#if !defined(FLOW_INCLUDED)
#if !defined(FLOW_INCLUDED)
#define FLOW_INCLUDED


// Distortional water. Take UV and flow parameters and returns the new flowed UV coordinates for distortional flow.
float3 FlowUVW(float2 uv, float2 flowVector, float2 jump, float flowOffset, float tiling, float time, bool flowB) {
// FlowA needs to be 0 when FlowB is 1 and vice versa for transition to disappear. That is achieved with 0.5 offset for second flow
float phaseOffset = flowB ? 0.5 : 0;
// Frac takes only decimal part of number to get 0-1 pattern (0 to 1 , then resets to 0)
float progress = frac(time + phaseOffset);
float3 uvw;
// Subtract flow multiplied by progress from UV. We subtract so the flow goes in the direction of the vector
// FlowOffset is variable that will control where the animation starts (default at 0)
uvw.xy = uv - flowVector * (progress + flowOffset);
// We need separate tiling property because we dont want to affect flowing. Thats why we cant use tiling and offset
// of the surface shader and thats why we need to apply it after adding flow and before adding phaseOffset.
uvw.xy *= tiling;
// Adding phase offset for flowB
uvw.xy += phaseOffset;
// Apply UV jump for longer single lopp. We need to multiply it with integer portion of the time.
uvw.xy += (time - progress) * jump;
// Calculate weight which will make each flow fade based on their position. We will use Seesaw pattern,
// where weight is minimum (0) in 0, 1, 2 ... and maximum (1) in 1/2, 3/2, ... (∧∧∧)
// When we overlap two distortion where one has offset of 0.5 (XXXXXX) and we fade flows as it comes
// near minimum, we get smooth transitions between animations
uvw.z = 1 - abs(1 - 2 * progress);
return uvw;
}

// Directional water. Take UV and flow parameters and returns the new flowed UV coordinates for directional flow.
float2 DirectionalFlowUV(float2 uv, float3 flowVectorAndSpeed, float tiling, float time, out float2x2 rotation) {
// Flow map doesn't contain vectors of unit length, we have to normalize them first.
float2 dir = normalize(flowVectorAndSpeed.xy);
// Calculate rotation by creating Rotation matrix where sinA = dir.x and cosA = dir.y
rotation = float2x2(dir.y, -dir.x, dir.x, dir.y);
// Rotate UV with rotation matrix
uv = mul(rotation, uv);
// Since UV are normalized we need to apply speed that we stored in _FlowMap B channel
uv.y -= time * flowVectorAndSpeed.z;
// Apply tiling
return uv * tiling;
}
#endif
54 changes: 33 additions & 21 deletions Assets/Shaders/LookingThroughWater.cginc
Original file line number Diff line number Diff line change
@@ -1,59 +1,71 @@
#if !defined(LOOKING_THROUGH_WATER_INCLUDED)
#define LOOKING_THROUGH_WATER_INCLUDED

// Unity makes the depth buffer globally available via the _CameraDepthTexture variable
// GrabPass will retreive texture that was rendered before water
sampler2D _CameraDepthTexture, _WaterBackground;
float4 _CameraDepthTexture_TexelSize;

float3 _WaterFogColor;
float _WaterFogDensity, _RefractionStrength, _RefractionStrength2;

// fix blending when sampling the grabbed texture
// Fix blending when sampling the grabbed texture
// (to remove thin line of artifacts around the edge of the refraction)
float2 AlignWithGrabTexel(float2 uv) {
#if UNITY_UV_STARTS_AT_TOP

#if UNITY_UV_STARTS_AT_TOP
if (_CameraDepthTexture_TexelSize.y < 0) {
uv.y = 1 - uv.y;
}
#endif
#endif
return (floor(uv * _CameraDepthTexture_TexelSize.zw) + 0.5) * abs(_CameraDepthTexture_TexelSize.xy);
}


//Returns rgb of fragments under the water
// Returns rgb of fragments under the water on which refraction and underwater fog has been applied to.
float3 ColorBelowWater(float4 screenPos, float3 tangentSpaceNormal) {
//---------------------REFRACTION----------------------------
//To make the offset wiggle, we'll use the XY coordinates of the tangent-space normal vector as the offset
// To make the offset wiggle, we'll use the XY coordinates of the tangent-space normal vector as the offset
// It will be synced with the apparent motion of surface
float2 uvOffset = tangentSpaceNormal.xy * _RefractionStrength;
// If water is still, we need to move background a bit to simulate refraction
if (uvOffset.x == 0 && uvOffset.y == 0) {
uvOffset = _RefractionStrength2;
}
// not symmetrical. The vertical offset is less than the horizontal.
// to equalize the offsets, we have to multiply the V offset by the image width divided by its height
// Diagonal offset is not symmetrical. The vertical offset is less than the horizontal.
// To equalize the offsets, we have to multiply the V offset by the image width divided by its height
// Z & W component of _CameraDepthTexture_TexelSize contain width & height in pixels
// Y is reciprocal of the height so we can multiply with Y instead of dividing with W (Y can be negative hence abs)
uvOffset.y *= _CameraDepthTexture_TexelSize.z * abs(_CameraDepthTexture_TexelSize.y);
float2 uv;
// We have to convert to screen-space coordinates, by dividing X and Y by W.
if(screenPos.w != 0)
uv = AlignWithGrabTexel((screenPos.xy + uvOffset) / screenPos.w);

float2 uv = AlignWithGrabTexel((screenPos.xy + uvOffset) / screenPos.w);



// depth relative to the screen
// Sample the background depth (behind water relative to the screen) via the SAMPLE_DEPTH_TEXTURE macro,
// and then convert the raw value to the linear depth via the LinearEyeDepth function.
float backgroundDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
// surface depth
// We need to know the distance between the water and the screen
// Solution is to take screenPos.z, which is interpolated clip space depth and converting it to linear depth
float surfaceDepth = UNITY_Z_0_FAR_FROM_CLIPSPACE(screenPos.z);
// depth - water surface = depth from surface to object
// The underwater depth is found by subtracting the surface depth from the background depth.
float depthDifference = backgroundDepth - surfaceDepth;

// Calculate new offset scaled by depth difference
// Scale offset with depth difference. Depth is saturated (<0 = 0, >1 = 1) to range between 0 and 1.
// We do this to eliminate possible incorrect refractions near surface. With saturation and scaling,
// we eliminate near surface refractionsa
uvOffset *= saturate(depthDifference);
// recalculate UV
uv = AlignWithGrabTexel((screenPos.xy + uvOffset) / screenPos.w);
// again sample depth difference with correct UV
// Recalculate UV with new offset
if (screenPos.w != 0)
uv = AlignWithGrabTexel((screenPos.xy + uvOffset) / screenPos.w);
// Recalculate depth difference with correct UV
backgroundDepth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv));
depthDifference = backgroundDepth - surfaceDepth;

// Get color from behind color
// Sample color from _WaterBackground which represents color of fragment behind water
float3 backgroundColor = tex2D(_WaterBackground, uv).rgb;
// Calculate how much we want to apply fog
// Calculate how much we want to apply fog based on _WaterFogDensity and how much away is the fragment from water
float fogFactor = exp2(-_WaterFogDensity/10 * depthDifference);
// Linear interpolation of fog color and background color based on fogFactor as weight
return lerp(_WaterFogColor, backgroundColor, fogFactor);
}

Expand Down
Loading

0 comments on commit 6cbfad3

Please sign in to comment.