Hard Light was a short project I made after reading Unity 5.x Shaders and Effects Cookbook by Alan Zucconi and Kenneth Lammers. The effect is an attempt to recreate Halo 5's Hard Light bridges on one of their levels. After roughly three days of reading the book and writing HLSL, I ended up with this product.
For this effect I had 3 single-channel textures which together comprised the full shader. I decided to compress the three textures into one to reduce memory usage. While this kind of optimization wasn't really needed for this scale of a project, I attempted it as a trial run in case I ever did need some more space.
The red channel was the displacement texture used to get the wavey/distorted surface of the material. To do this I applied a simple displacement to the UV map in both the X and Y axis so when sampling the grid texture, it would change the UV coordinates.
This channel was initially going to be sampled to change the speed in which the red channel was scrolling but ended up unused as the distortions looked better with a constant slow movement.
The grid texture was the main visual part of the compressed texture and was actually sampled twice in the final material. The first time, it is sampled with the displaced UVs but then for the second time, it is displaced more and its color muted to provide for a backing grid for the primary one to lay on.
Shader "Custom/Hardlight" {
Properties { // Unity uses these to generate UI to customize the shader with
_Color ("Color", Color) = (1,1,1,1)
_HexTex ("Hex Texture", 2D) = "white" {}
_DisplaceSpeedX ("X Hex Displacement Speed", Range(0,10)) = 0.0
_DisplaceSpeedY ("Y Hex Displacement Speed", Range(0,10)) = 0.0
_SecDisplaceX ("Secondary X Displacement", Range(0,1)) = 1.0
_SecDisplaceY ("Secondary Y Displacement", Range(0,1)) = 1.0
_SecondaryMultiplier ("Secondary Hex Multiplier", Range(0,1)) = 1.0
_BorderSize ("Border Glow Size", Range(0, 10)) = 8.0
_BorderColor ("Border Glow Color", Color) = (1,1,1,1)
}
SubShader {
// Transparent tags so the sphere in back can render through
Tags { "RenderType"="Transparent" "Queue"="Transparent" "IgnoreProjector"="True" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows alpha:fade
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _HexTex;
struct Input {
float2 uv_HexTex;
};
// Import variable from Unity custom material
fixed4 _Color;
fixed4 _BorderColor;
fixed _DisplaceSpeedX;
fixed _DisplaceSpeedY;
fixed _SecDisplaceX;
fixed _SecDisplaceY;
fixed _SecondaryMultiplier;
fixed _BorderSize;
void surf (Input IN, inout SurfaceOutputStandard o) {
const float PI = 3.14159;
// First displacement of UV coordinated for scrolling UVs
fixed scrollX = _Time * _DisplaceSpeedX + IN.uv_HexTex.x;
fixed scrollY = _Time * _DisplaceSpeedY + IN.uv_HexTex.y;
float2 newUV = float2(scrollX, scrollY);
// Separate hex into channels
float4 hex = tex2D(_HexTex, newUV);
float r = hex.r;
float g = hex.g;
float b = hex.b;
// Apply wavey distortion from the red channel to the UV coordinates
float2 displaceUV = float2(r,r) * 0.1 + IN.uv_HexTex;
// Store the primary grid result into a color
fixed4 firstHex = tex2D(_HexTex, displaceUV).b * _Color;
firstHex.a = r;
// Calculate border fade from cosine of the UV coordinates
// Simply put, it gets a 1 for the edges of the UV space and a 0 for the middle
// NOTE: this will only work on objects that span the entire UV space, the proper way
// to fix this would be to add the border based on either another texture or angle of the camera on the object
float xBorder = pow(cos(PI*displaceUV.x), _BorderSize);
float yBorder = pow(cos(PI*displaceUV.y), _BorderSize);
// Second grid displacement
float dx = _SecDisplaceX + _SinTime * 0.1;
float dy = _SecDisplaceY + _SinTime * 0.1;
displaceUV += float2(dx, dy);
// Second grid fragment
fixed4 secondHex = tex2D(_HexTex, displaceUV).b * _Color * _SecondaryMultiplier;
fixed4 c = firstHex + secondHex + r * _Color * 1.5;
fixed4 border = _BorderColor;
border *= (xBorder + yBorder);
c += border;
// Give resulting combination to the standard Unity lighting function
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}