From cba7e1ab0bfa89b228955e18b47cf7aca2a84c9f Mon Sep 17 00:00:00 2001 From: yum Date: Wed, 19 Feb 2025 23:42:46 -0800 Subject: Add vertex domain warping gimmick --- 2ner.cginc | 18 ++++ 2ner.shader | 10 +++ Textures/Fabric066_2K-PNG_NormalGL.png | Bin 0 -> 23966502 bytes features.cginc | 4 + globals.cginc | 8 ++ math.cginc | 151 +++++++++++++++++++++++++++++++++ pema99.cginc | 30 +++++++ vertex_domain_warping.cginc | 16 ++++ 8 files changed, 237 insertions(+) create mode 100644 Textures/Fabric066_2K-PNG_NormalGL.png create mode 100644 pema99.cginc create mode 100644 vertex_domain_warping.cginc diff --git a/2ner.cginc b/2ner.cginc index bc5f7f3..5cb5d71 100644 --- a/2ner.cginc +++ b/2ner.cginc @@ -38,6 +38,24 @@ v2f vert(appdata v) { v.tangent *= -1; #endif // OUTLINE_PASS +#if defined(_VERTEX_DOMAIN_WARPING) + float3 basePos = v.vertex.xyz; + float offset = sin(_Time[0] * _Vertex_Domain_Warping_Speed) * + _Vertex_Domain_Warping_Temporal_Strength; + v.vertex.xyz = domainWarp3(v.vertex, + _Vertex_Domain_Warping_Spatial_Octaves, + _Vertex_Domain_Warping_Spatial_Strength, + _Vertex_Domain_Warping_Spatial_Scale, + offset); + float3 tangent_tmp = v.tangent.xyz; + domainWarp3Normals(v.normal, tangent_tmp, basePos, + _Vertex_Domain_Warping_Spatial_Octaves, + _Vertex_Domain_Warping_Spatial_Strength, + _Vertex_Domain_Warping_Spatial_Scale, + offset); + v.tangent.xyz = tangent_tmp; +#endif + o.pos = UnityObjectToClipPos(v.vertex); o.uv01 = v.uv01; o.worldPos = mul(unity_ObjectToWorld, v.vertex); diff --git a/2ner.shader b/2ner.shader index bbb8fa3..6f4d0fd 100644 --- a/2ner.shader +++ b/2ner.shader @@ -107,6 +107,16 @@ Shader "yum_food/2ner" [HideInInspector] m_end_Rim_Lighting1("Rim lighting", Float) = 0 [HideInInspector] m_end_Rim_Lighting("Rim lighting", Float) = 0 //endex + //ifex _Vertex_Domain_Warping_Enabled==0 + [HideInInspector] m_start_Vertex_Domain_Warping("Vertex domain warping", Float) = 0 + [ThryToggle(_VERTEX_DOMAIN_WARPING)]_Vertex_Domain_Warping_Enabled("Enable", Float) = 0 + _Vertex_Domain_Warping_Spatial_Strength("Spatial warping strength", Float) = 0.10 + _Vertex_Domain_Warping_Spatial_Scale("Spatial warping scale", Float) = 1.0 + _Vertex_Domain_Warping_Spatial_Octaves("Spatial warping octaves", Float) = 1.0 + _Vertex_Domain_Warping_Speed("Speed", Float) = 1.0 + _Vertex_Domain_Warping_Temporal_Strength("Temporal warping strength", Float) = 0.10 + [HideInInspector] m_end_Vertex_Domain_Warping("Vertex domain warping", Float) = 0 + //endex [HideInInspector] m_lightingOptions("Lighting Options", Float) = 0 //ifex _Receive_Shadows_Enabled==0 diff --git a/Textures/Fabric066_2K-PNG_NormalGL.png b/Textures/Fabric066_2K-PNG_NormalGL.png new file mode 100644 index 0000000..d7159ae Binary files /dev/null and b/Textures/Fabric066_2K-PNG_NormalGL.png differ diff --git a/features.cginc b/features.cginc index 53f8c38..9976d45 100644 --- a/features.cginc +++ b/features.cginc @@ -34,5 +34,9 @@ #pragma shader_feature_local _RIM_LIGHTING1_MASK //endex +//ifex _Vertex_Domain_Warping_Enabled==0 +#pragma shader_feature_local _VERTEX_DOMAIN_WARPING +//endex + #endif // __FEATURES_INC diff --git a/globals.cginc b/globals.cginc index 948b69a..4d357db 100644 --- a/globals.cginc +++ b/globals.cginc @@ -86,4 +86,12 @@ texture2D _Rim_Lighting1_Mask; #endif #endif +#if defined(_VERTEX_DOMAIN_WARPING) +float _Vertex_Domain_Warping_Spatial_Strength; +float _Vertex_Domain_Warping_Spatial_Scale; +float _Vertex_Domain_Warping_Spatial_Octaves; +float _Vertex_Domain_Warping_Speed; +float _Vertex_Domain_Warping_Temporal_Strength; +#endif // _VERTEX_DOMAIN_WARPING + #endif // __GLOBALS_INC diff --git a/math.cginc b/math.cginc index 17ce86f..414f618 100644 --- a/math.cginc +++ b/math.cginc @@ -1,6 +1,8 @@ #ifndef __MATH_INC #define __MATH_INC +#include "pema99.cginc" + #define PI 3.14159265358979323846264 #define TAU (2 * PI) @@ -15,6 +17,155 @@ float wrapNoL(float NoL, float factor) { return pow(max(1E-4, (NoL + factor) / (1 + factor)), 1 + factor); } +float rand1(float p) +{ + return frac(sin(p) * 43758.5453123); +} + +float rand2(float2 p) +{ + return frac(sin(dot(p, float2(12.9898, 78.233))) * 43758.5453123); +} + +inline float rand3_dot(float3 p) +{ + return dot(p, float3(151.0, 157.0, 163.0)); +} + +float3 rand3_hash(float3 p) +{ + // Improved Murmurhash3 by Squirrel Eiserloh (GDC 2017) + p = float3(dot(p, float3(127.1, 311.7, 74.7)), + dot(p, float3(269.5, 183.3, 246.1)), + dot(p, float3(113.5, 271.9, 124.6))); + return -1.0 + 2.0 * frac(sin(p) * 43758.5453123); +} + +float rand3(float3 p) +{ + return frac(rand3_hash(p).x); +} + +float2 domainWarp1(float x, uint octaves, float strength, float scale) +{ + [loop] + for (uint i = 0; i < octaves; i++) { + x += strength * frac(sin(float2( + dot(x * scale, float2(12.9898, 78.233)), + dot(x * scale + 1, float2(12.9898, 78.233))) * 43758.5453123)); + } + return x; +} + +float2 domainWarp2(float2 uv, uint octaves, float strength, float scale) +{ + [loop] + for (uint i = 0; i < octaves; i++) { + uv += strength * frac(sin(float2( + dot(uv * scale, float2(12.9898, 78.233)), + dot(uv * scale + 1, float2(12.9898, 78.233))) * 43758.5453123)); + } + return uv; +} + +float determinant(float3x3 m) +{ + return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); +} + +float3x3 inverse(float3x3 m) +{ + float det = determinant(m); + + float3x3 adj; + adj[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]); + adj[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); + adj[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]); + + adj[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); + adj[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]); + adj[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); + + adj[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + adj[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); + adj[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]); + + return adj * (1.0 / det); +} + +float3 domainWarp3(float3 pos, uint octaves, float strength, float scale, float offset) +{ + [loop] + for (uint i = 0; i < octaves; i++) { + pos += strength * frac(sin(float3( + rand3_dot(pos * scale + offset), + rand3_dot(pos * scale + offset + 1), + rand3_dot(pos * scale + offset + 2)) * 43758.5453123)); + } + return pos; +} + +void domainWarp3Normals(inout float3 normal, inout float3 tangent, float3 basePos, uint octaves, float strength, float scale, float offset) +{ + // Use the actual vertex position for correct derivative evaluation. + float3 p = basePos; + + // Start with the identity matrix for the total Jacobian. + float3x3 J = float3x3( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 + ); + + const float k = 43758.5453123; + // Updated constant vector to match that of rand3_dot (used in domainWarp3) + const float3 c = float3(151.0, 157.0, 163.0); + + for (uint i = 0; i < octaves; i++) + { + // Compute the vector v using the same offsetting as in domainWarp3. + float3 v = float3( + dot(p * scale + float3(offset, offset, offset), c), + dot(p * scale + float3(offset + 1.0, offset + 1.0, offset + 1.0), c), + dot(p * scale + float3(offset + 2.0, offset + 2.0, offset + 2.0), c) + ); + + // Compute the warp offset with frac. + float3 f_val = frac(sin(v) * k); + float3 warpOffset = strength * f_val; + + // Compute the derivative (Jacobian) of the offset. + float3 cos_v = cos(v); + float3x3 D = float3x3( + strength * k * scale * cos_v.x * c.x, strength * k * scale * cos_v.x * c.y, strength * k * scale * cos_v.x * c.z, + strength * k * scale * cos_v.y * c.x, strength * k * scale * cos_v.y * c.y, strength * k * scale * cos_v.y * c.z, + strength * k * scale * cos_v.z * c.x, strength * k * scale * cos_v.z * c.y, strength * k * scale * cos_v.z * c.z + ); + + // The per–octave Jacobian is I + D. + float3x3 iterJacobian = float3x3( + 1.0 + D[0][0], D[0][1], D[0][2], + D[1][0], 1.0 + D[1][1], D[1][2], + D[2][0], D[2][1], 1.0 + D[2][2] + ); + + // Chain this iteration's Jacobian. + J = mul(iterJacobian, J); + + // Update p for the next iteration. + p += warpOffset; + } + + // Transform the normal via the inverse-transpose of the total Jacobian. + float3x3 invTransJ = transpose(inverse(J)); + normal = normalize(mul(invTransJ, normal)); + + // Transform the tangent via the forward total Jacobian. + tangent = normalize(mul(J, tangent)); +} + #endif // __MATH_INC diff --git a/pema99.cginc b/pema99.cginc new file mode 100644 index 0000000..030772b --- /dev/null +++ b/pema99.cginc @@ -0,0 +1,30 @@ +#ifndef __PEMA_99_INC +#define __PEMA_99_INC + +/* +MIT License + +Copyright (c) 2022 Pema Malling + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#define glsl_mod(x,y) (((x)-(y)*floor((x)/(y)))) + +#endif // __PEMA_99_INC diff --git a/vertex_domain_warping.cginc b/vertex_domain_warping.cginc new file mode 100644 index 0000000..0eea172 --- /dev/null +++ b/vertex_domain_warping.cginc @@ -0,0 +1,16 @@ +#ifndef __VERTEX_DOMAIN_WARPING_INC +#define __VERTEX_DOMAIN_WARPING_INC + +#include "math.cginc" + +float3 domainWarpVertexPosition(float3 vertex, float3 normal, float3 tangent, + float3 binormal, float3 worldPos, float3 centerCamPos) { + float3 worldNormal = UnityObjectToWorldNormal(normal); + float3 worldTangent = UnityObjectToWorldDir(tangent); + float3 worldBinormal = cross(worldNormal, worldTangent) * tangent.w * unity_WorldTransformParams.w; + + float3 worldPos = mul(unity_ObjectToWorld, vertex); +} + +#endif // __VERTEX_DOMAIN_WARPING_INC + -- cgit v1.2.3