summaryrefslogtreecommitdiffstats
path: root/Shaders/avatar_clone/avatar_clone_lighting.cginc
diff options
context:
space:
mode:
Diffstat (limited to 'Shaders/avatar_clone/avatar_clone_lighting.cginc')
-rw-r--r--Shaders/avatar_clone/avatar_clone_lighting.cginc309
1 files changed, 309 insertions, 0 deletions
diff --git a/Shaders/avatar_clone/avatar_clone_lighting.cginc b/Shaders/avatar_clone/avatar_clone_lighting.cginc
new file mode 100644
index 0000000..7471157
--- /dev/null
+++ b/Shaders/avatar_clone/avatar_clone_lighting.cginc
@@ -0,0 +1,309 @@
+#ifndef AVATAR_CLONE_LIGHTING
+#define AVATAR_CLONE_LIGHTING
+
+#include "AutoLight.cginc"
+#include "iq_sdf.cginc"
+#include "math.cginc"
+#include "motion.cginc"
+#include "pbr.cginc"
+#include "poi.cginc"
+#include "shadertoy.cginc"
+
+sampler2D _BaseColor;
+sampler2D _Emission;
+float _Emission_Strength;
+sampler2D _Normal;
+sampler2D _Metallic;
+sampler2D _Roughness;
+
+bool _Disable_Normal_Texture;
+bool _Disable_Normal_Recalc;
+
+sampler2D _Height;
+float _Height_LOD;
+float _Height_Exponent;
+float _Height_Scale;
+float _Height_Speed_X;
+float _Height_Speed_Y;
+float _Height_AA_Sample_Scale;
+
+sampler2D _Height_Mask;
+float _Height_Mask_Exponent;
+
+float _Center_Out_Speed;
+float _Center_Out_Sharpness;
+float _Center_Out_Min_Radius;
+float _Center_Out_Max_Radius;
+
+float _Num_Clones;
+float _Clone_dx;
+float _Clone_dy;
+float _Clone_dz;
+
+struct appdata
+{
+ float4 position : POSITION;
+ float2 uv : TEXCOORD0;
+ float3 normal : NORMAL;
+};
+
+void getVertexLightColor(inout v2f i)
+{
+ #if defined(VERTEXLIGHT_ON)
+ float3 light_pos = float3(unity_4LightPosX0.x, unity_4LightPosY0.x,
+ unity_4LightPosZ0.x);
+ float3 light_float = light_pos - i.worldPos;
+ float3 light_dir = normalize(light_float);
+ float ndotl = DotClamped(i.normal, light_dir);
+ // Light fills an expanding sphere with surface area 4 * pi * r^2.
+ // By conservation of energy, this means that at distance r, light intensity
+ // is proportional to 1/(r^2).
+ float attenuation = 1 / (1 + dot(light_float, light_float) * unity_4LightAtten0.x);
+ i.vertexLightColor = unity_LightColor[0].rgb * ndotl * attenuation;
+
+ i.vertexLightColor = Shade4PointLights(
+ unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
+ unity_LightColor[0].rgb,
+ unity_LightColor[1].rgb,
+ unity_LightColor[2].rgb,
+ unity_LightColor[3].rgb,
+ unity_4LightAtten0, i.worldPos, i.normal
+ );
+ #endif
+}
+
+v2f vert(appdata v)
+{
+ v2f o;
+
+ o.objPos = v.position;
+ o.clipPos = UnityObjectToClipPos(v.position);
+ o.worldPos = mul(unity_ObjectToWorld, v.position);
+
+ o.normal = UnityObjectToWorldNormal(v.normal);
+ o.uv = v.uv;
+
+ getVertexLightColor(o);
+
+ return o;
+}
+
+float getDisplacement(float2 uv)
+{
+ // Manipulate vertex in world space.
+ float height = 0;
+
+ float2 traveling_uv = uv;
+ traveling_uv.x += _Time[0] * _Height_Speed_X;
+ traveling_uv.y += _Time[0] * _Height_Speed_Y;
+ traveling_uv = glsl_mod(traveling_uv, 1.0);
+
+ const float duv = _Height_AA_Sample_Scale;
+
+ float z0 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y, _Height_LOD, 0));
+ // Trivial optimization. No need to keep going if no displacement is desired.
+ if (z0 == 0) {
+ return 0;
+ }
+ #if HEIGHT_AA_LEVEL >= 1
+ float z1 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y + duv, _Height_LOD, 0));
+ float z2 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y - duv, _Height_LOD, 0));
+ float z3 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y - duv, _Height_LOD, 0));
+ float z4 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y + duv, _Height_LOD, 0));
+ #endif
+ #if HEIGHT_AA_LEVEL >= 2
+ float z5 = tex2Dlod(_Height, float4(traveling_uv.x + duv, traveling_uv.y, _Height_LOD, 0));
+ float z6 = tex2Dlod(_Height, float4(traveling_uv.x - duv, traveling_uv.y, _Height_LOD, 0));
+ float z7 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y + duv, _Height_LOD, 0));
+ float z8 = tex2Dlod(_Height, float4(traveling_uv.x, traveling_uv.y - duv, _Height_LOD, 0));
+ #endif
+
+ #if HEIGHT_AA_LEVEL == 0
+ height += z0;
+ #elif HEIGHT_AA_LEVEL == 1
+ height += (z0 + z1 + z2 + z3 + z4) / 5.0;
+ #elif HEIGHT_AA_LEVEL == 2
+ height += (z0 + z1 + z2 + z3 + z4 + z5 + z6 + z7 + z8) / 9.0;
+ #endif
+
+ height = pow(height, _Height_Exponent);
+ height *= _Height_Scale;
+
+ {
+ float mask = tex2Dlod(_Height_Mask, float4(uv, _Height_LOD, 0));
+ mask = pow(mask, _Height_Mask_Exponent);
+ height *= mask;
+ }
+
+ // 0 at middle, 1 or -1 at edges
+ if (_Center_Out_Speed > 0.0) {
+ float2 middle_out_uv = uv * 2.0 - 1.0;
+
+ float center_dist2 = length2(middle_out_uv);
+ float ring_radius = fmod(_Time[1] * _Center_Out_Speed,
+ _Center_Out_Max_Radius - _Center_Out_Min_Radius)
+ + _Center_Out_Min_Radius;
+
+ // How far am I from the desired ring?
+ float ring_dist = dabs(center_dist2 - ring_radius, _Center_Out_Sharpness);
+ float ring_scale = exp(-1.0 * ring_dist);
+
+ float middle_out_height = ring_scale;
+ height *= middle_out_height;
+ }
+
+ return height;
+}
+
+void displace(inout v2f vert)
+{
+ float height = getDisplacement(vert.uv);
+
+ vert.worldPos += height * vert.normal;
+ vert.objPos = mul(unity_WorldToObject, float4(vert.worldPos, 1.0));
+ vert.clipPos = UnityObjectToClipPos(vert.objPos);
+}
+
+float3 getNormal(
+ v2f v0,
+ v2f v1,
+ v2f v2,
+ float duv_scale) {
+ float2 duv_v0v1 = v1.uv - v0.uv;
+ float2 duv_v0v2 = v2.uv - v0.uv;
+
+ float h0 = getDisplacement(v0.uv);
+ float h1 = getDisplacement(v0.uv + duv_v0v1 * duv_scale);
+ float h2 = getDisplacement(v0.uv + duv_v0v2 * duv_scale);
+
+ float dh_v0v1 = h1 - h0;
+ float dh_v0v2 = h2 - h0;
+
+ float3 dpos_v0v1 = v1.worldPos - v0.worldPos;
+ float3 dpos_v0v2 = v2.worldPos - v0.worldPos;
+
+ float3 p0 = v0.worldPos + h0 * v0.normal;
+ float3 p1 = v0.worldPos + dpos_v0v1 * duv_scale + lerp(h0, h1, duv_scale) * v1.normal;
+ float3 p2 = v0.worldPos + dpos_v0v2 * duv_scale + lerp(h0, h2, duv_scale) * v2.normal;
+
+ float3 tangent = normalize(p1 - p0);
+ float3 bitangent = normalize(p2 - p0);
+ float3 new_normal = normalize(cross(tangent, bitangent));
+ return new_normal;
+}
+
+// maxvertexcount == the number of vertices we create
+[maxvertexcount(15)]
+void geom(triangle v2f tri_in[3],
+ uint pid: SV_PrimitiveID,
+ inout TriangleStream<v2f> tri_out)
+{
+ float dx = 0.5;
+
+ v2f t0 = tri_in[0];
+ v2f t1 = tri_in[1];
+ v2f t2 = tri_in[2];
+
+ displace(t0);
+ displace(t1);
+ displace(t2);
+
+ // Math from here:
+ // http://tonfilm.blogspot.com/2007/01/calculate-normals-in-shader.html
+ for (uint i = 0; i < 3; i++) {
+ v2f v0 = tri_in[(i + 0) % 3];
+ v2f v1 = tri_in[(i + 1) % 3];
+ v2f v2 = tri_in[(i + 2) % 3];
+
+ if (!_Disable_Normal_Recalc) {
+ float3 aa_normal = 0;
+ aa_normal += getNormal(v0, v1, v2, 0.3);
+ aa_normal += getNormal(v0, v1, v2, 0.4);
+ aa_normal += getNormal(v0, v1, v2, 0.5);
+ aa_normal += getNormal(v0, v1, v2, 0.6);
+ aa_normal += getNormal(v0, v1, v2, 0.7);
+ aa_normal = normalize(aa_normal);
+
+ if (i == 0) {
+ t0.normal = aa_normal;
+ } else if (i == 1) {
+ t1.normal = aa_normal;
+ } else if (i == 2) {
+ t2.normal = aa_normal;
+ }
+ }
+ }
+
+ tri_out.Append(t0);
+ tri_out.Append(t1);
+ tri_out.Append(t2);
+ tri_out.RestartStrip();
+
+ const int num_clones = max((int) floor(_Num_Clones), 0);
+ for (int i = 2; i < num_clones + 2; i++) {
+ v2f t0p = t0;
+ v2f t1p = t1;
+ v2f t2p = t2;
+
+ t0p.worldPos.x += _Clone_dx * (i / 2) * (i % 2 == 0 ? 1.0 : -1.0);
+ t0p.worldPos.y += _Clone_dy * (i / 2);
+ t0p.worldPos.z += _Clone_dz * (i / 2);
+
+ t1p.worldPos.x += _Clone_dx * (i / 2) * (i % 2 == 0 ? 1.0 : -1.0);
+ t1p.worldPos.y += _Clone_dy * (i / 2);
+ t1p.worldPos.z += _Clone_dz * (i / 2);
+
+ t2p.worldPos.x += _Clone_dx * (i / 2) * (i % 2 == 0 ? 1.0 : -1.0);
+ t2p.worldPos.y += _Clone_dy * (i / 2);
+ t2p.worldPos.z += _Clone_dz * (i / 2);
+
+ t0p.objPos = mul(unity_WorldToObject, float4(t0p.worldPos, 1.0));
+ t0p.clipPos = UnityObjectToClipPos(t0p.objPos);
+
+ t1p.objPos = mul(unity_WorldToObject, float4(t1p.worldPos, 1.0));
+ t1p.clipPos = UnityObjectToClipPos(t1p.objPos);
+
+ t2p.objPos = mul(unity_WorldToObject, float4(t2p.worldPos, 1.0));
+ t2p.clipPos = UnityObjectToClipPos(t2p.objPos);
+
+ tri_out.Append(t0p);
+ tri_out.Append(t1p);
+ tri_out.Append(t2p);
+ tri_out.RestartStrip();
+ }
+}
+
+float getWorldSpaceDepth(in const float3 worldPos)
+{
+ float4 clip_pos = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
+ return clip_pos.z / clip_pos.w;
+}
+
+float4 effect(inout v2f i, out float depth)
+{
+ depth = -1000.0;
+
+ float4 albedo = tex2D(_BaseColor, i.uv);
+ float3 emission = tex2D(_Emission, i.uv);
+ float3 normal = _Disable_Normal_Texture ? i.normal : tex2D(_Normal, i.uv);
+ float metallic = tex2D(_Metallic, i.uv);
+ float roughness = tex2D(_Roughness, i.uv);
+ if (albedo.a > 0) {
+ depth = getWorldSpaceDepth(i.worldPos);
+ }
+
+ float4 lit_color = getLitColor(i, albedo, i.worldPos, normal, metallic,
+ 1.0 - roughness, /*custom_cubemap=*/true);
+
+ lit_color.rgb += emission * _Emission_Strength;
+
+ return lit_color;
+}
+
+fixed4 frag(v2f i, out float depth : SV_DepthLessEqual) : SV_Target
+{
+ return effect(i, depth);
+}
+
+#endif // AVATAR_CLONE_LIGHTING
+