diff options
| author | yum <yum.food.vr@gmail.com> | 2024-04-25 15:52:24 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2024-04-25 15:52:24 -0700 |
| commit | 6eed98ff4e57326ebf7a41f0c180635a7bcac626 (patch) | |
| tree | 67f5e269bafb49608cab8a6b22534d83fd09b58b /Third_Party/at.pimaker.ltcgi/Shaders | |
| parent | b9671b47df8b17fa3143d4b0dbdecf9b77cc7607 (diff) | |
Add LTCGI
Also begin trying to fix fallback shaders.
Diffstat (limited to 'Third_Party/at.pimaker.ltcgi/Shaders')
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/.LTCGI.cginc.swp | bin | 0 -> 16384 bytes | |||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/Amplify/AmplifyTest.mat | 87 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Amplify.shader | 223 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Contribution.asset | 46 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc | 408 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Simple.shader | 91 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface.shader | 87 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface_v2.shader | 136 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_config.cginc | 87 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_functions.cginc | 500 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_shadowmap.cginc | 84 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc | 43 | ||||
| -rw-r--r-- | Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_uniform.cginc | 142 |
13 files changed, 1934 insertions, 0 deletions
diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/.LTCGI.cginc.swp b/Third_Party/at.pimaker.ltcgi/Shaders/.LTCGI.cginc.swp Binary files differnew file mode 100644 index 0000000..d7a8805 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/.LTCGI.cginc.swp diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/AmplifyTest.mat b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/AmplifyTest.mat new file mode 100644 index 0000000..6ba2676 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/AmplifyTest.mat @@ -0,0 +1,87 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: AmplifyTest + m_Shader: {fileID: 4800000, guid: dbf90271d2d7a4946a1e653600c88ca3, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 0 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 5f34f31b510450b4b86b7554ea158d12, type: 3} + m_Scale: {x: 0.2, y: 0.2} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 4ac0d09ca8633a642b5c5b4cc91e02d0, type: 3} + m_Scale: {x: 0.2, y: 0.2} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _texcoord: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _texcoord2: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _Smoothness: 0.925 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + - __dirty: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Amplify.shader b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Amplify.shader new file mode 100644 index 0000000..08e2152 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Amplify.shader @@ -0,0 +1,223 @@ +// Made with Amplify Shader Editor +// Available at the Unity Asset Store - http://u3d.as/y3X +Shader "LTCGI_Amplify" +{ + Properties + { + _MainTex("MainTex", 2D) = "white" {} + [Normal]_BumpMap("BumpMap", 2D) = "bump" {} + _Smoothness("Smoothness", Range( 0 , 1)) = 0.5 + [HideInInspector] _texcoord( "", 2D ) = "white" {} + [HideInInspector] _texcoord2( "", 2D ) = "white" {} + [HideInInspector] __dirty( "", Int ) = 1 + } + + SubShader + { + Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+0" "LTCGI"="ALWAYS" } + Cull Back + CGINCLUDE + #include "UnityPBSLighting.cginc" + #include "UnityShaderVariables.cginc" + #include "Lighting.cginc" + #pragma target 3.0 + #include "Assets/_pi_/_LTCGI/Shaders/LTCGI.cginc" + #ifdef UNITY_PASS_SHADOWCASTER + #undef INTERNAL_DATA + #undef WorldReflectionVector + #undef WorldNormalVector + #define INTERNAL_DATA half3 internalSurfaceTtoW0; half3 internalSurfaceTtoW1; half3 internalSurfaceTtoW2; + #define WorldReflectionVector(data,normal) reflect (data.worldRefl, half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal))) + #define WorldNormalVector(data,normal) half3(dot(data.internalSurfaceTtoW0,normal), dot(data.internalSurfaceTtoW1,normal), dot(data.internalSurfaceTtoW2,normal)) + #endif + struct Input + { + float2 uv_texcoord; + float3 worldPos; + float3 worldNormal; + INTERNAL_DATA + float2 uv2_texcoord2; + }; + + struct SurfaceOutputCustomLightingCustom + { + half3 Albedo; + half3 Normal; + half3 Emission; + half Metallic; + half Smoothness; + half Occlusion; + half Alpha; + Input SurfInput; + UnityGIInput GIData; + }; + + uniform sampler2D _MainTex; + uniform float4 _MainTex_ST; + uniform sampler2D _BumpMap; + uniform float4 _BumpMap_ST; + uniform float _Smoothness; + + inline half4 LightingStandardCustomLighting( inout SurfaceOutputCustomLightingCustom s, half3 viewDir, UnityGI gi ) + { + UnityGIInput data = s.GIData; + Input i = s.SurfInput; + half4 c = 0; + float localLTCGI15_g1 = ( 0.0 ); + float3 ase_worldPos = i.worldPos; + float3 worldPos15_g1 = ase_worldPos; + float2 uv_BumpMap = i.uv_texcoord * _BumpMap_ST.xy + _BumpMap_ST.zw; + float3 normalizeResult9_g1 = normalize( (WorldNormalVector( i , UnpackNormal( tex2D( _BumpMap, uv_BumpMap ) ) )) ); + float3 worldNorm15_g1 = normalizeResult9_g1; + float3 normalizeResult12_g1 = normalize( ( _WorldSpaceCameraPos - ase_worldPos ) ); + float3 cameraDir15_g1 = normalizeResult12_g1; + float roughness15_g1 = ( 1.0 - _Smoothness ); + float2 lightmapUV15_g1 = i.uv2_texcoord2; + float3 diffuse15_g1 = float3( 0,0,0 ); + float3 specular15_g1 = float3( 0,0,0 ); + float specularIntensity15_g1 = 0; + { + LTCGI_Contribution(worldPos15_g1, worldNorm15_g1, cameraDir15_g1, roughness15_g1, lightmapUV15_g1, diffuse15_g1, specular15_g1, specularIntensity15_g1); + } + c.rgb = ( ( diffuse15_g1 * 0.05 ) + ( specular15_g1 * 1.0 ) ); + c.a = 1; + return c; + } + + inline void LightingStandardCustomLighting_GI( inout SurfaceOutputCustomLightingCustom s, UnityGIInput data, inout UnityGI gi ) + { + s.GIData = data; + } + + void surf( Input i , inout SurfaceOutputCustomLightingCustom o ) + { + o.SurfInput = i; + o.Normal = float3(0,0,1); + float2 uv_MainTex = i.uv_texcoord * _MainTex_ST.xy + _MainTex_ST.zw; + o.Albedo = tex2D( _MainTex, uv_MainTex ).rgb; + } + + ENDCG + CGPROGRAM + #pragma surface surf StandardCustomLighting keepalpha fullforwardshadows + + ENDCG + Pass + { + Name "ShadowCaster" + Tags{ "LightMode" = "ShadowCaster" } + ZWrite On + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma multi_compile_shadowcaster + #pragma multi_compile UNITY_PASS_SHADOWCASTER + #pragma skip_variants FOG_LINEAR FOG_EXP FOG_EXP2 + #include "HLSLSupport.cginc" + #if ( SHADER_API_D3D11 || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3 || SHADER_API_METAL || SHADER_API_VULKAN ) + #define CAN_SKIP_VPOS + #endif + #include "UnityCG.cginc" + #include "Lighting.cginc" + #include "UnityPBSLighting.cginc" + struct v2f + { + V2F_SHADOW_CASTER; + float4 customPack1 : TEXCOORD1; + float4 tSpace0 : TEXCOORD2; + float4 tSpace1 : TEXCOORD3; + float4 tSpace2 : TEXCOORD4; + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + }; + v2f vert( appdata_full v ) + { + v2f o; + UNITY_SETUP_INSTANCE_ID( v ); + UNITY_INITIALIZE_OUTPUT( v2f, o ); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO( o ); + UNITY_TRANSFER_INSTANCE_ID( v, o ); + Input customInputData; + float3 worldPos = mul( unity_ObjectToWorld, v.vertex ).xyz; + half3 worldNormal = UnityObjectToWorldNormal( v.normal ); + half3 worldTangent = UnityObjectToWorldDir( v.tangent.xyz ); + half tangentSign = v.tangent.w * unity_WorldTransformParams.w; + half3 worldBinormal = cross( worldNormal, worldTangent ) * tangentSign; + o.tSpace0 = float4( worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x ); + o.tSpace1 = float4( worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y ); + o.tSpace2 = float4( worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z ); + o.customPack1.xy = customInputData.uv_texcoord; + o.customPack1.xy = v.texcoord; + o.customPack1.zw = customInputData.uv2_texcoord2; + o.customPack1.zw = v.texcoord1; + TRANSFER_SHADOW_CASTER_NORMALOFFSET( o ) + return o; + } + half4 frag( v2f IN + #if !defined( CAN_SKIP_VPOS ) + , UNITY_VPOS_TYPE vpos : VPOS + #endif + ) : SV_Target + { + UNITY_SETUP_INSTANCE_ID( IN ); + Input surfIN; + UNITY_INITIALIZE_OUTPUT( Input, surfIN ); + surfIN.uv_texcoord = IN.customPack1.xy; + surfIN.uv2_texcoord2 = IN.customPack1.zw; + float3 worldPos = float3( IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w ); + half3 worldViewDir = normalize( UnityWorldSpaceViewDir( worldPos ) ); + surfIN.worldPos = worldPos; + surfIN.worldNormal = float3( IN.tSpace0.z, IN.tSpace1.z, IN.tSpace2.z ); + surfIN.internalSurfaceTtoW0 = IN.tSpace0.xyz; + surfIN.internalSurfaceTtoW1 = IN.tSpace1.xyz; + surfIN.internalSurfaceTtoW2 = IN.tSpace2.xyz; + SurfaceOutputCustomLightingCustom o; + UNITY_INITIALIZE_OUTPUT( SurfaceOutputCustomLightingCustom, o ) + surf( surfIN, o ); + #if defined( CAN_SKIP_VPOS ) + float2 vpos = IN.pos; + #endif + SHADOW_CASTER_FRAGMENT( IN ) + } + ENDCG + } + } + Fallback "Diffuse" + CustomEditor "ASEMaterialInspector" +} +/*ASEBEGIN +Version=18935 +536;73;2067;851;779.8046;162.2598;1;True;True +Node;AmplifyShaderEditor.RangedFloatNode;6;-821.1882,196.0575;Inherit;False;Constant;_Float0;Float 0;3;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.RangedFloatNode;2;-934.938,98.16958;Inherit;False;Property;_Smoothness;Smoothness;2;0;Create;True;0;0;0;False;0;False;0.5;0.925;0;1;0;1;FLOAT;0 +Node;AmplifyShaderEditor.SimpleSubtractOpNode;5;-635.8664,186.1211;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0 +Node;AmplifyShaderEditor.TexturePropertyNode;20;-775.5374,331.3456;Inherit;True;Property;_BumpMap;BumpMap;1;1;[Normal];Create;True;0;0;0;False;0;False;None;5f34f31b510450b4b86b7554ea158d12;True;bump;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1 +Node;AmplifyShaderEditor.RangedFloatNode;24;-255.1472,222.6049;Inherit;False;Constant;_Float1;Float 1;3;0;Create;True;0;0;0;False;0;False;0.05;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.RangedFloatNode;25;-255.1469,448.7357;Inherit;False;Constant;_Float2;Float 2;3;0;Create;True;0;0;0;False;0;False;1;0;0;0;0;1;FLOAT;0 +Node;AmplifyShaderEditor.TexturePropertyNode;15;-478.7493,-90.12699;Inherit;True;Property;_MainTex;MainTex;0;0;Create;True;0;0;0;False;0;False;None;4ac0d09ca8633a642b5c5b4cc91e02d0;False;white;Auto;Texture2D;-1;0;2;SAMPLER2D;0;SAMPLERSTATE;1 +Node;AmplifyShaderEditor.FunctionNode;35;-477.8035,308.7716;Inherit;False;LTCGI_Contribution;-1;;1;d3ea6060590627141a6e856295f0e87c;0;2;18;SAMPLER2D;0;False;21;FLOAT;0;False;3;FLOAT3;16;FLOAT;17;FLOAT3;0 +Node;AmplifyShaderEditor.SimpleMultiplyOpNode;21;-97.38132,256.7875;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0 +Node;AmplifyShaderEditor.SimpleMultiplyOpNode;12;-94.82584,382.3184;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;1;FLOAT3;0 +Node;AmplifyShaderEditor.TextureCoordinatesNode;14;-229.4183,-19.4483;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.SimpleAddOpNode;26;64.32862,318.5789;Inherit;False;2;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0 +Node;AmplifyShaderEditor.SamplerNode;1;4.050852,-87.71029;Inherit;True;Property;_Albedo;Albedo;0;0;Fetch;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;False;Instance;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4 +Node;AmplifyShaderEditor.StandardSurfaceOutputNode;45;387.8991,5.103931;Float;False;True;-1;2;ASEMaterialInspector;0;0;CustomLighting;LTCGI_Amplify;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Opaque;0.5;True;True;0;False;Opaque;;Geometry;All;18;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;False;2;15;10;25;False;0.5;True;0;0;False;-1;0;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;True;Relative;0;;-1;-1;-1;-1;1;LTCGI=ALWAYS;False;0;0;False;-1;-1;0;False;-1;1;Include;Assets/_pi_/_LTCGI/Shaders/LTCGI.cginc;False;;Custom;0;0;False;0.1;False;-1;0;False;-1;False;15;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0 +WireConnection;5;0;6;0 +WireConnection;5;1;2;0 +WireConnection;35;18;20;0 +WireConnection;35;21;5;0 +WireConnection;21;0;35;0 +WireConnection;21;1;24;0 +WireConnection;12;0;35;16 +WireConnection;12;1;25;0 +WireConnection;14;2;15;0 +WireConnection;26;0;21;0 +WireConnection;26;1;12;0 +WireConnection;1;0;15;0 +WireConnection;1;1;14;0 +WireConnection;1;7;15;1 +WireConnection;45;0;1;0 +WireConnection;45;13;26;0 +ASEEND*/ +//CHKSM=2F9669BE0F908372CF1438E7300F30E35C6E2269
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Contribution.asset b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Contribution.asset new file mode 100644 index 0000000..307676a --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/Amplify/LTCGI_Contribution.asset @@ -0,0 +1,46 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 78b2425a2284af743826c689403a4924, type: 3} + m_Name: LTCGI_Contribution + m_EditorClassIdentifier: + m_functionInfo: "// Made with Amplify Shader Editor\n// Available at the Unity + Asset Store - http://u3d.as/y3X \n/*ASEBEGIN\nVersion=18935\n536;73;2067;851;3119.343;614.295;1.681782;True;True\nNode;AmplifyShaderEditor.WorldSpaceCameraPos;3;-1572.588,304.9969;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.FunctionInput;21;-1149.124,1.794816;Inherit;False;Roughness;1;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionInput;18;-2132.389,-209.6327;Inherit;True;Normal + Map;9;0;True;1;0;SAMPLER2D;0;False;1;SAMPLER2D;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;19;-1906.188,-105.2091;Inherit;False;0;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.SamplerNode;20;-1663.786,-180.0446;Inherit;True;Property;_Albedo;Albedo;0;0;Fetch;True;0;0;0;False;0;False;-1;None;None;True;0;False;white;Auto;True;Instance;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.WorldPosInputsNode;11;-1166,-331.4044;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.CustomExpressionNode;15;-801.2723,-77.17082;Inherit;False;LTCGI_Contribution(worldPos, + worldNorm, cameraDir, roughness, lightmapUV, diffuse, specular, specularIntensity)@$;7;Call;8;False;worldPos;FLOAT3;0,0,0;In;;Float;False;False;worldNorm;FLOAT3;0,0,0;In;;Float;False;False;cameraDir;FLOAT3;0,0,0;In;;Float;False;False;roughness;FLOAT;0;In;;Inherit;False;False;lightmapUV;FLOAT2;0,0;In;;Float;False;False;diffuse;FLOAT3;0,0,0;Out;;Half;False;False;specular;FLOAT3;0,0,0;Out;;Half;False;False;specularIntensity;FLOAT;0;Out;;Inherit;False;LTCGI;False;False;0;;False;9;0;FLOAT;0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT3;0,0,0;False;4;FLOAT;0;False;5;FLOAT2;0,0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;4;FLOAT;0;FLOAT3;7;FLOAT3;8;FLOAT;9\nNode;AmplifyShaderEditor.RangedFloatNode;22;-1407.949,27.19302;Inherit;False;Constant;_DefaultRoughness;Default + Roughness;0;0;Create;True;0;0;0;False;0;False;0.5;0;0;0;0;1;FLOAT;0\nNode;AmplifyShaderEditor.TextureCoordinatesNode;10;-1188.472,117.4048;Inherit;True;1;-1;2;3;2;SAMPLER2D;;False;0;FLOAT2;1,1;False;1;FLOAT2;0,0;False;5;FLOAT2;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4\nNode;AmplifyShaderEditor.NormalizeNode;9;-1135.18,-104.5354;Inherit;False;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldNormalVector;7;-1353.008,-175.4043;Inherit;False;False;1;0;FLOAT3;0,0,1;False;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.SimpleSubtractOpNode;6;-1253.479,434.9653;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.WorldPosInputsNode;4;-1570.679,470.0651;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3\nNode;AmplifyShaderEditor.NormalizeNode;12;-1057.422,435.0438;Inherit;False;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;16;-382.1458,1.795166;Inherit;False;False;-1;Specular;0;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nNode;AmplifyShaderEditor.FunctionOutput;17;-381.1458,95.79517;Inherit;False;False;-1;Specular + Intensity;1;False;1;0;FLOAT;0;False;1;FLOAT;0\nNode;AmplifyShaderEditor.FunctionOutput;0;-382,-94;Inherit;False;True;-1;Diffuse;2;False;1;0;FLOAT3;0,0,0;False;1;FLOAT3;0\nWireConnection;21;0;22;0\nWireConnection;19;2;18;0\nWireConnection;20;0;18;0\nWireConnection;20;1;19;0\nWireConnection;15;1;11;0\nWireConnection;15;2;9;0\nWireConnection;15;3;12;0\nWireConnection;15;4;21;0\nWireConnection;15;5;10;0\nWireConnection;9;0;7;0\nWireConnection;7;0;20;0\nWireConnection;6;0;3;0\nWireConnection;6;1;4;0\nWireConnection;12;0;6;0\nWireConnection;16;0;15;8\nWireConnection;17;0;15;9\nWireConnection;0;0;15;7\nASEEND*/\n//CHKSM=7E6B0A6F8854806C46769C1D40451E18FF4A9344" + m_functionName: + m_description: LTCGI custom contribution function. Make sure to add the custom + Include and Tag directives! + m_additionalIncludes: + m_additionalIncludes: [] + m_outsideIncludes: [] + m_additionalPragmas: + m_additionalPragmas: [] + m_outsidePragmas: [] + m_additionalDirectives: + m_validData: 0 + m_isDirty: 1 + m_moduleName: ' Additional Directives' + m_independentModule: 1 + m_customEdited: 0 + m_additionalDirectives: [] + m_shaderFunctionDirectives: [] + m_nativeDirectives: [] + m_nativeDirectivesIndex: -1 + m_nativeDirectivesFoldout: 0 + m_directivesSaveItems: [] + m_nodeCategory: 3 + m_customNodeCategory: + m_previewPosition: 0 + m_hidden: 0 + m_url: https://github.com/PiMaker/ltcgi/wiki#amplify diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc new file mode 100644 index 0000000..ca4cd24 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI.cginc @@ -0,0 +1,408 @@ +#ifndef LTCGI_INCLUDED +#define LTCGI_INCLUDED + +#include "LTCGI_config.cginc" + +#ifdef LTCGI_AVATAR_MODE + #undef LTCGI_STATIC_UNIFORMS + #undef LTCGI_BICUBIC_LIGHTMAP + #define LTCGI_ALWAYS_LTC_DIFFUSE + // for perf and locality don't allow cylinders on avatars for now (it probably would be misdetected anyway) + #undef LTCGI_CYLINDER +#endif + +#ifdef LTCGI_TOGGLEABLE_SPEC_DIFF_OFF + #undef LTCGI_DIFFUSE_OFF + #undef LTCGI_SPECULAR_OFF +#endif + +#if defined(LTCGI_V2_CUSTOM_INPUT) || defined(LTCGI_V2_DIFFUSE_CALLBACK) || defined(LTCGI_V2_SPECULAR_CALLBACK) + #define LTCGI_API_V2 +#endif + +#include "LTCGI_structs.cginc" +#include "LTCGI_uniform.cginc" +#include "LTCGI_functions.cginc" +#include "LTCGI_shadowmap.cginc" + +#ifdef SHADER_TARGET_SURFACE_ANALYSIS +#define const +#endif + +// Main function - this calculates the approximated model for one pixel and one light +void LTCGI_Evaluate(ltcgi_input input, float3 worldNorm, float3 viewDir, float3x3 Minv, float roughness, const bool diffuse, out ltcgi_output output) { + output.input = input; + output.color = input.rawColor; // copy for colormode static + output.intensity = 0; + + // diffuse distance fade + #ifdef LTCGI_DISTANCE_FADE_APPROX + if (diffuse) // static branch, specular does not directly fade with distance + { + if (!input.flags.lmdOnly) { + // very approximate lol + float3 ctr = (input.Lw[0] + input.Lw[1])/2; + float dist = length(ctr); + if (dist > LTCGI_DISTANCE_FADE_APPROX_MULT) + { + return; + } + } + } + #endif + + #define RET1_IF_LMDIFF [branch] if (/*const*/ diffuse && input.flags.diffFromLm) { output.intensity = 1.0f; return; } + + if (input.flags.colormode == LTCGI_COLORMODE_SINGLEUV) { + float2 uv = input.uvStart; + if (uv.x < 0) uv.xy = uv.yx; + // TODO: make more configurable? + #ifdef LTCGI_VISUALIZE_SAMPLE_UV + output.color = float3(uv.xy, 0); + #elif !defined(SHADER_TARGET_SURFACE_ANALYSIS) + // sample video texture directly for accuracy + float3 sampled = _Udon_LTCGI_Texture_LOD0.SampleLevel(LTCGI_SAMPLER, uv.xy, 0).rgb; + output.color *= sampled; + #endif + + RET1_IF_LMDIFF + } + + #ifdef LTCGI_AUDIOLINK + if (input.flags.colormode == LTCGI_COLORMODE_AUDIOLINK) { + float al = AudioLinkData(ALPASS_AUDIOLINK + uint2(0, input.flags.alBand)).r; + output.color *= al; + + RET1_IF_LMDIFF + } + #endif + + // create LTC polygon array + // note the order of source verts (keyword: winding order) + float3 L[5]; + L[0] = mul(Minv, input.Lw[0]); + L[1] = mul(Minv, input.Lw[1]); + L[2] = input.isTri ? L[1] : mul(Minv, input.Lw[3]); + L[3] = mul(Minv, input.Lw[2]); + L[4] = 0; + + // get texture coords (before clipping!) + [branch] + if (input.flags.colormode == LTCGI_COLORMODE_TEXTURE) { + float3 RN; + float2 uv = LTCGI_calculateUV(input.i, input.flags, L, input.isTri, input.uvStart, input.uvEnd, RN); + float planeAreaSquared = dot(RN, RN); + float planeDistxPlaneArea = dot(RN, L[0]); + + float3 sampled; + [branch] + if (diffuse) { // static branch + #ifdef LTCGI_BLENDED_DIFFUSE_SAMPLING + float3 sampled1; + LTCGI_sample(uv, 3, input.flags.texindex, 10, sampled1); + float3 sampled2; + LTCGI_sample(uv, 3, input.flags.texindex, 100, sampled2); + sampled = + sampled1 * 0.75 + + sampled2 * 0.25; + #else + LTCGI_sample(uv, 3, input.flags.texindex, 10, sampled); + #endif + } else { + float d = abs(planeDistxPlaneArea) / planeAreaSquared; + d *= LTCGI_UV_BLUR_DISTANCE; + d = log(d) / log(3.0); + + // a rough material must never show a perfect reflection, + // since our LOD0 texture is not prefiltered (and thus cannot + // depict any blur correctly) - without this there is artifacting + // on the border of LOD0 and LOD1 + d = clamp(d, saturate(roughness * 5.75), 1000); + + LTCGI_trilinear(uv, d, input.flags.texindex, sampled); + } + + // colorize output + output.color *= sampled; + } + + RET1_IF_LMDIFF + #undef RET1_IF_LMDIFF + + int n; + LTCGI_ClipQuadToHorizon(L, n); + + // early out if everything was clipped below horizon + if (n == 0) + return; + + L[0] = normalize(L[0]); + L[1] = normalize(L[1]); + L[2] = normalize(L[2]); + L[3] = normalize(L[3]); + L[4] = normalize(L[4]); + + // integrate (and pray that constant folding works well) + float sum = 0; + [unroll(5)] + for (uint v = 0; v < max(3, (uint)n); v++) { + float3 a = L[v]; + float3 b = L[(v + 1) % 5]; + sum += LTCGI_IntegrateEdge(a, b).z; + } + + // doublesided is accounted for with optimization at the start, so return abs + output.intensity = abs(sum); + return; +} + +// Calculate light contribution for all lights, +// call this from your shader and use the "diffuse" and "specular" outputs +// lmuv is the raw lightmap UV coordinate (e.g. UV1) +void LTCGI_Contribution( +#ifdef LTCGI_API_V2 + inout LTCGI_V2_CUSTOM_INPUT data, +#endif + float3 worldPos, float3 worldNorm, float3 viewDir, float roughness, float2 lmuv +#ifndef LTCGI_API_V2 + , inout half3 diffuse, inout half3 specular, out float totalSpecularIntensity, out float totalDiffuseIntensity +#endif +) { + #ifndef LTCGI_API_V2 + totalSpecularIntensity = 0; + totalDiffuseIntensity = 0; + #endif + if (_Udon_LTCGI_GlobalEnable == 0.0f) { + return; + } + + // sample lookup tables + float theta = LTCGI_acos_fast(dot(worldNorm, viewDir)); + float2 uv = float2(roughness, theta/(0.5*UNITY_PI)); + uv = uv*LUT_SCALE + LUT_BIAS; + + #ifndef UNITY_UV_STARTS_AT_TOP + uv.y = 1 - uv.y; + #endif + + // calculate LTCGI custom lightmap UV and sample + float3 lms = LTCGI_SampleShadowmap(lmuv); + + #ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER + // sample BDRF approximation from lookup texture + float4 t = _Udon_LTCGI_lut1.SampleLevel(LTCGI_SAMPLER, uv, 0); + #endif + float3x3 Minv = float3x3( + float3( 1, 0, t.w), + float3( 0, t.z, 0), + float3(t.y, 0, t.x) + ); + + // construct orthonormal basis around N + float3 T1, T2; + T1 = normalize(viewDir - worldNorm*dot(viewDir, worldNorm)); + T2 = cross(worldNorm, T1); + + // for diffuse lighting we assume the identity matrix as BDRF, so the + // LTC approximation is directly equivalent to the orthonormal rotation matrix + float3x3 identityBrdf = float3x3(float3(T1), float3(T2), float3(worldNorm)); + // rotate area light in (T1, T2, N) basis for actual BRDF matrix as well + Minv = mul(Minv, identityBrdf); + + // specular brightness + #ifndef LTCGI_SPECULAR_OFF + #ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER + float spec_amp = _Udon_LTCGI_lut2.SampleLevel(LTCGI_SAMPLER, uv, 0).x; + #endif + #endif + + bool noLm = false; + #ifdef LTCGI_LTC_DIFFUSE_FALLBACK + #ifndef LTCGI_ALWAYS_LTC_DIFFUSE + #ifndef SHADER_TARGET_SURFACE_ANALYSIS + float2 lmSize; + _Udon_LTCGI_Lightmap.GetDimensions(lmSize.x, lmSize.y); + noLm = lmSize.x == 1; + #endif + #endif + #endif + #ifdef LTCGI_ALWAYS_LTC_DIFFUSE + noLm = true; + #endif + + // loop through all lights and add them to the output + uint count = min(_Udon_LTCGI_ScreenCount, MAX_SOURCES); + [loop] + for (uint i = 0; i < count; i++) { + // skip masked and black lights + if (_Udon_LTCGI_Mask[i]) continue; + float4 extra = _Udon_LTCGI_ExtraData[i]; + float3 color = extra.rgb; + if (!any(color)) continue; + + ltcgi_flags flags = ltcgi_parse_flags(asuint(extra.w), noLm); + + #ifdef LTCGI_ALWAYS_LTC_DIFFUSE + // can't honor a lightmap-only light in this mode + if (flags.lmdOnly) continue; + #endif + + #ifdef LTCGI_TOGGLEABLE_SPEC_DIFF_OFF + // compile branches below away statically + flags.diffuse = flags.specular = true; + #endif + + // calculate (shifted) world space positions + float3 Lw[4]; + float4 uvStart = (float4)0, uvEnd = (float4)0; + bool isTri = false; + if (flags.lmdOnly) { + Lw[0] = Lw[1] = Lw[2] = Lw[3] = (float3)0; + } else { + LTCGI_GetLw(i, flags, worldPos, Lw, uvStart, uvEnd, isTri); + } + + // skip single-sided lights that face the other way + float3 screenNorm = cross(Lw[1] - Lw[0], Lw[2] - Lw[0]); + if (!flags.doublesided) { + if (dot(screenNorm, Lw[0]) < 0) + continue; + } + + float lm = 1; + if (flags.lmch) { + lm = lms[flags.lmch - 1]; + if (lm < 0.001) continue; + } + + ltcgi_input input; + input.i = i; + input.Lw = Lw; + input.isTri = isTri; + input.uvStart = uvStart; + input.uvEnd = uvEnd; + input.rawColor = color; + input.flags = flags; + input.screenNormal = screenNorm; + + // diffuse lighting + #ifndef LTCGI_DIFFUSE_OFF + [branch] + if (flags.diffuse) + { + float lmd = lm; + if (flags.lmch) { + if (flags.diffFromLm) + lmd *= _Udon_LTCGI_LightmapMult[flags.lmch - 1]; + else + lmd = smoothstep(0.0, LTCGI_SPECULAR_LIGHTMAP_STEP, saturate(lm - LTCGI_LIGHTMAP_CUTOFF)); + } + ltcgi_output diff; + LTCGI_Evaluate(input, worldNorm, viewDir, identityBrdf, roughness, true, diff); + diff.intensity *= lmd; + + #ifdef LTCGI_API_V2 + LTCGI_V2_DIFFUSE_CALLBACK(data, diff); + #else + // simply accumulate all lights + diffuse += (diff.intensity * diff.color); + totalDiffuseIntensity += diff.intensity; + #endif + } + #endif + + // specular lighting + #ifndef LTCGI_SPECULAR_OFF + [branch] + if (flags.specular) + { + ltcgi_output spec; + LTCGI_Evaluate(input, worldNorm, viewDir, Minv, roughness, false, spec); + spec.intensity *= spec_amp * smoothstep(0.0, LTCGI_SPECULAR_LIGHTMAP_STEP, saturate(lm - LTCGI_LIGHTMAP_CUTOFF)); + + #ifdef LTCGI_API_V2 + LTCGI_V2_SPECULAR_CALLBACK(data, spec); + #else + // simply accumulate all lights + specular += spec.intensity * spec.color; + totalSpecularIntensity += spec.intensity; + #endif + } + #endif + } +} + +// COMPATIBILITY FALLBACKS + +#ifndef LTCGI_API_V2 + +void LTCGI_Contribution( + float3 worldPos, float3 worldNorm, float3 viewDir, float roughness, float2 lmuv, inout half3 diffuse +) { + half3 _u1; + float _u2, _u3; + LTCGI_Contribution(worldPos, worldNorm, viewDir, roughness, lmuv, diffuse, _u1, _u2, _u3); +} + +void LTCGI_Contribution( + float3 worldPos, float3 worldNorm, float3 viewDir, float roughness, float2 lmuv, inout half3 diffuse, inout half3 specular +) { + float _u1, _u2; + LTCGI_Contribution(worldPos, worldNorm, viewDir, roughness, lmuv, diffuse, specular, _u1, _u2); +} + +void LTCGI_Contribution( + float3 worldPos, float3 worldNorm, float3 viewDir, float roughness, float2 lmuv, inout half3 diffuse, inout half3 specular, out float totalSpecularIntensity +) { + float _u1; + LTCGI_Contribution(worldPos, worldNorm, viewDir, roughness, lmuv, diffuse, specular, totalSpecularIntensity, _u1); +} + +#endif + +/* + +Parts of the code in this file are adapted from the example code found here: + + https://github.com/selfshadow/ltc_code + +Modifications by _pi_ (@pimaker on GitHub), licensed under the terms of the +MIT license as far as applicable. + +Original copyright notice: + +Copyright (c) 2017, Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* If you use (or adapt) the source code in your own work, please include a + reference to the paper: + + Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. + Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. + ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. + Project page: https://eheitzresearch.wordpress.com/415-2/ + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#endif
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Simple.shader b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Simple.shader new file mode 100644 index 0000000..512ca47 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Simple.shader @@ -0,0 +1,91 @@ +Shader "LTCGI/Simple" +{ + Properties + { + _MainTex ("Texture", 2D) = "white" {} + _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0) + + _Roughness ("Roughness", Range(0.0, 1.0)) = 0.5 + + //[ToggleUI] _Debug ("Debug Param, does whatever it wants", float) = 0.0 + } + SubShader + { + // "LTCGI" tag defines that any renderer with this material will + // receive data from the LTCGI editor and Udon scripts. + // Can be either "ALWAYS" or the name of a float ("ToggleUI") + // property on which input will depends. + Tags { "RenderType"="Opaque" "LTCGI"="ALWAYS" } + LOD 100 + + Pass + { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_fog + + //#define LTCGI_SPECULAR_OFF + + #include "UnityCG.cginc" + #include "LTCGI.cginc" + + struct v2f + { + float4 uv : TEXCOORD0; + float3 worldPos : TEXCOORD1; + float3 worldNorm : TEXCOORD2; + float4 vertex : SV_POSITION; + }; + + sampler2D _MainTex; + float4 _MainTex_ST; + + float4 _Color; + float _Roughness; + + v2f vert (appdata_full v) + { + v2f o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.worldPos = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)).xyz; + o.worldNorm = mul(unity_ObjectToWorld, float4(v.normal.xyz, 0.0)).xyz; + o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv.zw = v.texcoord1; + return o; + } + + float3 get_camera_pos() { + float3 worldCam; + worldCam.x = unity_CameraToWorld[0][3]; + worldCam.y = unity_CameraToWorld[1][3]; + worldCam.z = unity_CameraToWorld[2][3]; + return worldCam; + } + static float3 camera_pos = get_camera_pos(); + + half4 frag (v2f i) : SV_Target + { + //return half4(tex2Dlod(_LTCGI_mat, float4(i.uv, 0, 0)).rgb, 1); + + half4 col = tex2D(_MainTex, i.uv) * _Color; + half3 diff = 0; + half3 spec = 0; + + LTCGI_Contribution( + i.worldPos, + normalize(i.worldNorm), + normalize(camera_pos - i.worldPos), + _Roughness, + i.uv.zw, + diff, + spec + ); + col.rgb *= saturate(diff + 0.1); + col.rgb += spec; + return col; + } + ENDCG + } + } +} diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface.shader b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface.shader new file mode 100644 index 0000000..b4ee68e --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface.shader @@ -0,0 +1,87 @@ +Shader "LTCGI/Surface" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _MainTex ("Albedo (RGB)", 2D) = "white" {} + [HideInInspector] _LightMap ("(for surface ST only)", 2D) = "white" {} + _BumpMap ("Normal Map", 2D) = "bump" {} + _Metallic ("Metallic", Range(0,1)) = 0.0 + _Glossiness ("Smoothness", Range(0,1)) = 0.5 + _GlossinessMap ("Smoothness Map", 2D) = "white" {} + [ToggleUI] _MapIsRoughness ("Invert Smoothness Map", Float) = 0.0 + [ToggleUI] _LTCGI ("LTCGI enabled", Float) = 1.0 + } + SubShader + { + // The LTCGI tag can either be "ALWAYS" or specify a "Toggle"/"ToggleUI" property. + // It is required so that renderers using this material will be updated by the controller. + Tags { "RenderType"="Opaque" "LTCGI"="_LTCGI" } + LOD 200 + + CGPROGRAM + #pragma surface surf Standard fullforwardshadows + #pragma target 3.0 + + #include "LTCGI.cginc" + + sampler2D _MainTex; + sampler2D _BumpMap; + sampler2D _GlossinessMap; + + struct Input + { + float2 uv_MainTex; + float2 uv_BumpMap; + float2 uv2_LightMap; + float3 worldPos; + float3 worldNormal; INTERNAL_DATA + }; + + half _Glossiness; + float _MapIsRoughness; + half _Metallic; + fixed4 _Color; + float _LTCGI; + + float3 get_camera_pos() { + float3 worldCam; + worldCam.x = unity_CameraToWorld[0][3]; + worldCam.y = unity_CameraToWorld[1][3]; + worldCam.z = unity_CameraToWorld[2][3]; + return worldCam; + } + + void surf (Input IN, inout SurfaceOutputStandard o) + { + fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; + o.Albedo = c.rgb; + o.Metallic = _Metallic; + o.Smoothness = tex2D (_GlossinessMap, IN.uv_MainTex); + if (_MapIsRoughness) + o.Smoothness = 1 - o.Smoothness; + o.Smoothness *= _Glossiness; + o.Alpha = c.a; + + o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); + + if (_LTCGI) { + float3 normal = WorldNormalVector(IN, o.Normal); + float3 spec = 0, diff = 0; + LTCGI_Contribution( + IN.worldPos, + normalize(normal), + normalize(get_camera_pos() - IN.worldPos), + 1 - o.Smoothness, + IN.uv2_LightMap, + diff, + spec + ); + o.Emission += spec; + o.Emission += diff * c; + } + } + ENDCG + } + FallBack "Diffuse" +} diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface_v2.shader b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface_v2.shader new file mode 100644 index 0000000..2cba27b --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_Surface_v2.shader @@ -0,0 +1,136 @@ +Shader "LTCGI/Surface (APIv2)" +{ + Properties + { + _Color ("Color", Color) = (1,1,1,1) + _MainTex ("Albedo (RGB)", 2D) = "white" {} + [HideInInspector] _LightMap ("(for surface ST only)", 2D) = "white" {} + _BumpMap ("Normal Map", 2D) = "bump" {} + _Metallic ("Metallic", Range(0,1)) = 0.0 + _Glossiness ("Smoothness", Range(0,1)) = 0.5 + _GlossinessMap ("Smoothness Map", 2D) = "white" {} + [ToggleUI] _MapIsRoughness ("Invert Smoothness Map", Float) = 0.0 + + [ToggleUI] _LTCGI ("LTCGI enabled", Float) = 1.0 + _LTCGI_DiffuseColor ("LTCGI Diffuse Color", Color) = (1,1,1,1) + _LTCGI_SpecularColor ("LTCGI Specular Color", Color) = (1,1,1,1) + } + SubShader + { + // The LTCGI tag can either be "ALWAYS" or specify a "Toggle"/"ToggleUI" property. + // It is required so that renderers using this material will be updated by the controller. + Tags { "RenderType"="Opaque" "LTCGI"="_LTCGI" } + LOD 200 + + CGPROGRAM + #pragma surface surf Standard fullforwardshadows + #pragma target 3.0 + + // This shader demonstrates how to use the APIv2 LTCGI functionality, which has access to per-light callbacks + + // preamble: include this first to get access to required types + #include "Packages/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc" + + // then define the accumulator type and callback functions (can forward-declare functions to keep things tidy) + // note the function signatures, especially that the accumulator is "inout" so it will keep modifications between calls + struct accumulator_struct { + // let your imagination run wild on what to accumulate here... + float3 diffuse; + float3 specular; + }; + void callback_diffuse(inout accumulator_struct acc, in ltcgi_output output); + void callback_specular(inout accumulator_struct acc, in ltcgi_output output); + + // tell LTCGI that we want the V2 API, and which constructs to use + #define LTCGI_V2_CUSTOM_INPUT accumulator_struct + #define LTCGI_V2_DIFFUSE_CALLBACK callback_diffuse + #define LTCGI_V2_SPECULAR_CALLBACK callback_specular + + // then include this to finish the deal + #include "Packages/at.pimaker.ltcgi/Shaders/LTCGI.cginc" + + // standard shader stuff follows... + sampler2D _MainTex; + sampler2D _BumpMap; + sampler2D _GlossinessMap; + + struct Input + { + float2 uv_MainTex; + float2 uv_BumpMap; + float2 uv2_LightMap; + float3 worldPos; + float3 worldNormal; INTERNAL_DATA + }; + + half _Glossiness; + float _MapIsRoughness; + half _Metallic; + half4 _Color; + float _LTCGI; + half4 _LTCGI_DiffuseColor; + half4 _LTCGI_SpecularColor; + + float3 get_camera_pos() { + float3 worldCam; + worldCam.x = unity_CameraToWorld[0][3]; + worldCam.y = unity_CameraToWorld[1][3]; + worldCam.z = unity_CameraToWorld[2][3]; + return worldCam; + } + + // now we declare LTCGI APIv2 functions for real + void callback_diffuse(inout accumulator_struct acc, in ltcgi_output output) { + // you can do whatever here! check out the ltcgi_output struct in + // "LTCGI_structs.cginc" to see what data you have available + acc.diffuse += output.intensity * output.color * _LTCGI_DiffuseColor; + } + void callback_specular(inout accumulator_struct acc, in ltcgi_output output) { + // same here, this example one is pretty boring though. + // you could accumulate intensity separately for example, + // to emulate total{Specular,Diffuse}Intensity from APIv1 + acc.specular += output.intensity * output.color * _LTCGI_SpecularColor; + } + + void surf (Input IN, inout SurfaceOutputStandard o) + { + // standard surface shader stuff again... + fixed4 mainColor = tex2D (_MainTex, IN.uv_MainTex) * _Color; + o.Albedo = mainColor.rgb; + o.Metallic = _Metallic; + o.Smoothness = tex2D (_GlossinessMap, IN.uv_MainTex); + if (_MapIsRoughness) + o.Smoothness = 1.0f - o.Smoothness; + o.Smoothness *= _Glossiness; + o.Alpha = mainColor.a; + + o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); + float3 worldSpaceNormal = normalize(WorldNormalVector(IN, o.Normal)); + + if (_LTCGI) { + // and lastly, here's how we call the APIv2 version of LTCGI: + + // first, we create the struct that'll be passed through + accumulator_struct acc = (accumulator_struct)0; + + // then we make the LTCGI_Contribution call as usual, but with slightly different params + LTCGI_Contribution( + acc, // our accumulator + IN.worldPos, // world position of the shaded point + worldSpaceNormal, // world space normal + normalize(get_camera_pos() - IN.worldPos), // view vector to shaded point, normalized + 1.0f - o.Smoothness, // roughness + IN.uv2_LightMap // shadowmap coordinates (the normal Unity ones, they should be in sync with LTCGI maps) + ); + + // after the call, our accumulator struct will have been modified by our callbacks + // we can now use it to set the output color + o.Emission += acc.specular; + o.Emission += acc.diffuse * mainColor.rgb; + } + } + ENDCG + } + + FallBack "Diffuse" +}
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_config.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_config.cginc new file mode 100644 index 0000000..561fe93 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_config.cginc @@ -0,0 +1,87 @@ +#ifndef LTCGI_CONFIG_INCLUDED +#define LTCGI_CONFIG_INCLUDED + +// Feel free to enable or disable (//) the options here. +// They will apply to all LTCGI materials in the project. +// Most of these can be changed in the LTCGI_Controller editor as well. + +/// No specular at all. +//#define LTCGI_SPECULAR_OFF +/// No diffuse at all. +//#define LTCGI_DIFFUSE_OFF +/// Disable the ability to toggle specular/diffuse on or off per screen. +//#define LTCGI_TOGGLEABLE_SPEC_DIFF_OFF + +/// Only use LTC diffuse mode, never lightmapped diffuse. +/// This disables lightmaps entirely. +//#define LTCGI_ALWAYS_LTC_DIFFUSE + +/// Double-sample screen texture for diffuse lighting to smooth resulting lighting +/// a bit more with global screen color data. Slight performance cost. +//#define LTCGI_BLENDED_DIFFUSE_SAMPLING + +/// Slightly simplified and thus faster sampling for reflections at the cost of quality. +/// Consider using this if your scene looks about the same with this enabled. +//#define LTCGI_FAST_SAMPLING + +/// Use bicubic filtering for LTCGI lightmap. Recommended on. +#define LTCGI_BICUBIC_LIGHTMAP + +/// Lightmap values below this will be treated as black for specular/LTC diffuse. +#define LTCGI_LIGHTMAP_CUTOFF 0.1 +/// Lightmap values above this (plus cutoff) will be treated as white. +#define LTCGI_SPECULAR_LIGHTMAP_STEP 0.3 + +/// Distance multiplier for calculating blur amount. +/// Increase to make reflections blurrier faster as distance increases. +#define LTCGI_UV_BLUR_DISTANCE 333 + +/// Fall back to LTC diffuse (from LM diffuse) on objects that are not marked static. +#define LTCGI_LTC_DIFFUSE_FALLBACK + +/// Approximation to ignore diffuse light for far away +/// lights, increase MULT or disable if you notice artifacting +#define LTCGI_DISTANCE_FADE_APPROX +/// Distance at which diffuse from screens will be ignored. +#define LTCGI_DISTANCE_FADE_APPROX_MULT 50 + + +// disabled editor from here on out +/// + + +// Allow statically textured lights. +// (deprecated: doesn't really cause any improvement when disabled...) +#define LTCGI_STATIC_TEXTURES + + +// keep in sync with LTCGI_Controller.cs +#define MAX_SOURCES 16 + +// set according to the LUT specified on CONTROLLER +#define LUT_SIZE 256 +static float LUT_SCALE = (LUT_SIZE - 1.0)/LUT_SIZE; +const float LUT_BIAS = 0.5/LUT_SIZE; + +// will be set automatically if audiolink is available +//#define LTCGI_AUDIOLINK + +#ifdef LTCGI_AUDIOLINK +#ifndef AUDIOLINK_WIDTH +#ifndef AUDIOLINK_CGINC_INCLUDED +#include "Packages/com.llealloo.audiolink/Runtime/Shaders/AudioLink.cginc" +#define AUDIOLINK_CGINC_INCLUDED +#endif +#endif +#endif + +// Bake screen data into texture for better performance. Disables moveable screens. +#define LTCGI_STATIC_UNIFORMS + +// Enable support for cylindrical screens. +#define LTCGI_CYLINDER + +// Activate avatar mode, which overrides certain configs from above. +//#define LTCGI_AVATAR_MODE + +#endif diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_functions.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_functions.cginc new file mode 100644 index 0000000..ff33c87 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_functions.cginc @@ -0,0 +1,500 @@ +#ifndef LTCGI_FUNCTIONS_INCLUDED +#define LTCGI_FUNCTIONS_INCLUDED + +/* + LTC HELPERS +*/ + +float3 LTCGI_IntegrateEdge(float3 v1, float3 v2) +{ + float x = dot(v1, v2); + float y = abs(x); + + float a = 0.8543985 + (0.4965155 + 0.0145206*y)*y; + float b = 3.4175940 + (4.1616724 + y)*y; + float v = a / b; + float theta_sintheta = (x > 0.0) ? v : 0.5*rsqrt(max(1.0 - x*x, 1e-7)) - v; + + return cross(v1, v2) * theta_sintheta; +} + +void LTCGI_ClipQuadToHorizon(inout float3 L[5], out int n) +{ + // detect clipping config + uint config = 0; + if (L[0].z > 0.0) config += 1; + if (L[1].z > 0.0) config += 2; + if (L[2].z > 0.0) config += 4; + if (L[3].z > 0.0) config += 8; + + n = 0; + + // This [forcecase] only works when the cases are ordered in a specific manner. + // It gives like 10%-20% performance boost, so *make sure to leave it on*! + // If it breaks however, see if [branch] fixes it, and if it does, start + // reordering cases at random until it works again. + // It seems the compiler somehow optimizes away anything but setting 'n' in + // some orderings, including the ascending and descending ones. + // I wish I was joking. + [forcecase] + switch (config) { + case 13: // V1 V3 V4 clip V2 <- tl;dr: this fecker has to be first or shader go boom + n = 5; + L[4] = L[3]; + L[3] = L[2]; + L[2] = -L[1].z * L[2] + L[2].z * L[1]; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + break; + case 15: // V1 V2 V3 V4 - most common + n = 4; + break; + case 9: // V1 V4 clip V2 V3 + n = 4; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[2].z * L[3] + L[3].z * L[2]; + break; + case 0: // clip all + break; + case 1: // V1 clip V2 V3 V4 + n = 3; + L[1] = -L[1].z * L[0] + L[0].z * L[1]; + L[2] = -L[3].z * L[0] + L[0].z * L[3]; + L[3] = L[0]; + break; + case 2: // V2 clip V1 V3 V4 + n = 3; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + L[3] = L[0]; + break; + case 3: // V1 V2 clip V3 V4 + n = 4; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + L[3] = -L[3].z * L[0] + L[0].z * L[3]; + break; + case 4: // V3 clip V1 V2 V4 + n = 3; + L[0] = -L[3].z * L[2] + L[2].z * L[3]; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + L[3] = L[0]; + break; + case 5: // V1 V3 clip V2 V4) impossible + break; + case 6: // V2 V3 clip V1 V4 + n = 4; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + break; + case 7: // V1 V2 V3 clip V4 + n = 5; + L[4] = -L[3].z * L[0] + L[0].z * L[3]; + L[3] = -L[3].z * L[2] + L[2].z * L[3]; + break; + case 8: // V4 clip V1 V2 V3 + n = 3; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + L[1] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = L[3]; + break; + case 10: // V2 V4 clip V1 V3) impossible + break; + case 11: // V1 V2 V4 clip V3 + n = 5; + L[4] = L[3]; + L[3] = -L[2].z * L[3] + L[3].z * L[2]; + L[2] = -L[2].z * L[1] + L[1].z * L[2]; + break; + case 12: // V3 V4 clip V1 V2 + n = 4; + L[1] = -L[1].z * L[2] + L[2].z * L[1]; + L[0] = -L[0].z * L[3] + L[3].z * L[0]; + break; + case 14: // V2 V3 V4 clip V1 + n = 5; + L[4] = -L[0].z * L[3] + L[3].z * L[0]; + L[0] = -L[0].z * L[1] + L[1].z * L[0]; + break; + } + + // inlining these branches *unconditionally* breaks the [forcecase] above + // ...yeah I know + if (n == 3) + L[3] = L[0]; + if (n == 4) + L[4] = L[0]; +} + +/* + TEXTURE SAMPLING +*/ + +float2 LTCGI_inset_uv(float2 uv) +{ + return uv * 0.75 + float2(0.125, 0.125); +} + +half3 premul_alpha(half4 i) +{ + return i.rgb * i.a; +} + +void LTCGI_sample(float2 uv, uint lod, uint idx, float blend, out float3 result) +{ +#ifdef LTCGI_FAST_SAMPLING + #ifndef SHADER_TARGET_SURFACE_ANALYSIS + blend *= 2.5f; + [branch] + if (idx == 0) + { + result = premul_alpha(_Udon_LTCGI_Texture_LOD0.SampleLevel(LTCGI_SAMPLER, uv, blend)); + } + else + { + result = UNITY_SAMPLE_TEX2DARRAY_SAMPLER_LOD( + _Udon_LTCGI_Texture_LOD0_arr, + LTCGI_SAMPLER_RAW, + float3(uv, idx - 1), + blend + ).rgb; + } + #else + result = 0; + #endif +#else + result = 0; + #ifndef LTCGI_STATIC_TEXTURES + idx = 0; // optimize away the branches below + #endif + + [branch] + if (lod == 0) + { + // if we're outside of the 0-1 UV space we must sample a prefiltered texture + [branch] + if(any(saturate(abs(uv - 0.5) - 0.5))) + { + lod = 1; + } + else + { + // LOD0 is the original texture itself, so not prefiltered, but we can + // approximate it a bit with trilinear lod + float lod = (1 - blend) * 1.5; + [branch] + if (idx == 0) + { + #ifndef SHADER_TARGET_SURFACE_ANALYSIS + result = premul_alpha(_Udon_LTCGI_Texture_LOD0.SampleLevel(LTCGI_SAMPLER, uv, lod)); + return; + #else + result = 0; + return; + #endif + } + else + { + result = premul_alpha(UNITY_SAMPLE_TEX2DARRAY_SAMPLER_LOD( + _Udon_LTCGI_Texture_LOD0_arr, + LTCGI_SAMPLER_RAW, + float3(uv, idx - 1), + lod + )); + return; + } + } + } + + float2 ruv = LTCGI_inset_uv(uv); + + [branch] + if (idx == 0) + { + #ifndef SHADER_TARGET_SURFACE_ANALYSIS + switch (lod) + { + case 1: + result = _Udon_LTCGI_Texture_LOD1.SampleLevel(LTCGI_SAMPLER, ruv, 0).rgb; + return; + case 2: + result = _Udon_LTCGI_Texture_LOD2.SampleLevel(LTCGI_SAMPLER, ruv, 0).rgb; + return; + default: + result = _Udon_LTCGI_Texture_LOD3.SampleLevel(LTCGI_SAMPLER, ruv, blend*0.72).rgb; + return; + } + #else + result = 0; + return; + #endif + } + else + { + [forcecase] + switch (lod) + { + case 1: + result = UNITY_SAMPLE_TEX2DARRAY_SAMPLER_LOD( + _Udon_LTCGI_Texture_LOD1_arr, + LTCGI_SAMPLER_RAW, + float3(ruv, idx - 1), + 0 + ).rgb; + return; + case 2: + result = UNITY_SAMPLE_TEX2DARRAY_SAMPLER_LOD( + _Udon_LTCGI_Texture_LOD2_arr, + LTCGI_SAMPLER_RAW, + float3(ruv, idx - 1), + 0 + ).rgb; + return; + default: + result = UNITY_SAMPLE_TEX2DARRAY_SAMPLER_LOD( + _Udon_LTCGI_Texture_LOD3_arr, + LTCGI_SAMPLER_RAW, + float3(ruv, idx - 1), + blend + ).rgb; + return; + } + } +#endif +} + +void LTCGI_trilinear(float2 uv, float d, uint idx, out float3 result) +{ +#ifdef LTCGI_FAST_SAMPLING + LTCGI_sample(uv, 0, idx, d, result); +#else + uint low = (uint)d; + uint high = low + 1; + + // DEBUG: colorize d/lod + //return float3(low == 0, low == 1, low == 2); + + if (low >= 3) + { + LTCGI_sample(uv, 3, idx, d - 3, result); + } + else + { + float amount = saturate(high - d); + float3 low_sample; + LTCGI_sample(uv, low, idx, amount, low_sample); + float3 high_sample; + LTCGI_sample(uv, high, idx, 0, high_sample); + + result = lerp(high_sample, low_sample, amount); + } +#endif +} + +/* + GENERIC HELPERS +*/ + +// from: https://seblagarde.wordpress.com/2014/12/01/inverse-trigonometric-functions-gpu-optimization-for-amd-gcn-architecture/ +// max absolute error 9.0x10^-3 +// Eberly's polynomial degree 1 - respect bounds +// 4 VGPR, 12 FR (8 FR, 1 QR), 1 scalar +// input [-1, 1] and output [0, PI] +float LTCGI_acos_fast(float inX) +{ + float x = abs(inX); + float res = -0.156583f * x + UNITY_HALF_PI; + res *= sqrt(1.0f - x); + return (inX >= 0) ? res : UNITY_PI - res; +} + +bool LTCGI_tri_ray(float3 orig, float3 dir, float3 v0, float3 v1, float3 v2, out float2 bary) { + float3 v0v1 = v1 - v0; + float3 v0v2 = v2 - v0; + float3 pvec = cross(dir, v0v2); + float det = dot(v0v1, pvec); + float invDet = 1 / det; + + float3 tvec = orig - v0; + bary.x = dot(tvec, pvec) * invDet; + + float3 qvec = cross(tvec, v0v1); + bary.y = dot(dir, qvec) * invDet; + + // return false when other triangle of quad should be sampled, + // i.e. we went over the diagonal line + return bary.x >= 0; +} + +float2 LTCGI_rotateVector(float2 x, float angle) +{ + float c = cos(angle); + float s = sin(angle); + return mul(float2x2(c,s,-s,c), x); +} + +/*float LTCGI_remap(float3 from, float3 to, float2 targetFrom, float2 targetTo, float3 value) +{ + float rel = (value - from) / (to - from); + return lerp(targetFrom, targetTo, rel); +}*/ + +float2 LTCGI_calculateUV(uint i, ltcgi_flags flags, float3 L[5], bool isTri, float4 uvStart, float4 uvEnd, out float3 ray) +{ + // calculate perpendicular vector to plane defined by area light + float3 E1 = L[1] - L[0]; + float3 E2 = L[3] - L[0]; + ray = cross(E1, E2); + + // raycast it against the two triangles formed by the quad + float2 bary; + bool hit0 = LTCGI_tri_ray(0, ray, L[0], L[2], L[3], bary) || isTri; + if (!hit0) { + LTCGI_tri_ray(0, ray, L[0], L[1], L[2], bary); + } + + float3 bary3 = float3(bary, 1 - bary.x - bary.y); + float2 uv; + if (hit0) + uv = uvEnd.zw * bary3.x + uvEnd.xy * bary3.y; + else + uv = uvStart.zw * bary3.x + uvEnd.zw * bary3.y; + return uv + uvStart.xy * bary3.z; +} + +/* + EXPERIMENTAL: CYLINDER HELPER +*/ + +void LTCGI_GetLw(uint i, ltcgi_flags flags, float3 worldPos, out float3 Lw[4], out float4 uvStart, out float4 uvEnd, out bool isTri) { + bool cylinder = false; + #ifdef LTCGI_CYLINDER + // statically optimize out branch below in case disabled + cylinder = flags.cylinder; + #endif + + float4 v0 = _Udon_LTCGI_Vertices_0_get(i); + float4 v1 = _Udon_LTCGI_Vertices_1_get(i); + float4 v2 = _Udon_LTCGI_Vertices_2_get(i); + float4 v3 = _Udon_LTCGI_Vertices_3_get(i); + + [branch] + if (cylinder) { + // construct data according to worldPos to create aligned + // rectangle tangent to the cylinder + + float3 in_base = v0.xyz; + float in_height = v0.w; + float in_radius = v1.w; + float in_size = v2.w; + float in_angle = v3.w; + + // get angle between 2D unit plane and vector pointing from cylinder to shade point + float2 towardsCylinder = LTCGI_rotateVector((in_base - worldPos).xz, -in_angle); + float angle = atan2(towardsCylinder.x, towardsCylinder.y); + // clamp angle to size parameter, i.e. "width" of lit surface area + float angleClamped = clamp(angle, -in_size, in_size) + in_angle; + // construct vector that *most* faces shade point + float2 facing = float2(sin(angleClamped), cos(angleClamped)); + // tangent of rectangular screen on cylinder surface used for calculating lighting for shade point + float2 tangent = float2(facing.y, -facing.x); + float2 onCylinderFacing = facing * in_radius; + + // clip ends, approximately + float rclip = saturate(lerp(1, 0, (angleClamped - in_angle) - (in_size - UNITY_HALF_PI*0.5f))); + float lclip = saturate(lerp(1, 0, -(angleClamped - in_angle) - (in_size - UNITY_HALF_PI*0.5f))); + + float2 p1 = in_base.xz - onCylinderFacing + tangent * in_radius * lclip; + float2 p2 = in_base.xz - onCylinderFacing - tangent * in_radius * rclip; + + Lw[0] = float3(p1.x, in_base.y, p1.y) - worldPos; + Lw[1] = float3(p1.x, in_base.y + in_height, p1.y) - worldPos; + Lw[2] = float3(p2.x, in_base.y, p2.y) - worldPos; + Lw[3] = float3(p2.x, in_base.y + in_height, p2.y) - worldPos; + + isTri = false; + + // UV depends on "viewing" angle of the shade point towards the cylinder + float2 viewDir = normalize((in_base - worldPos).xz); + // forwardAngle == atan2(cos(in_angle), sin(in_angle)); but only negative + float forwardAngle = -in_angle + UNITY_HALF_PI; + // offset from center of screen forward to the side ends, positive goes left/ccw fpv top, + // sine to account for the fact we're rotating around a cylinder which has depth + float viewAngle = forwardAngle - atan2(viewDir.y, viewDir.x); + // prevent rollover, since we need to clamp we must stay withing [-pi, pi] + if (viewAngle < -UNITY_PI) + viewAngle += UNITY_TWO_PI; + if (viewAngle > UNITY_PI) + viewAngle -= UNITY_TWO_PI; + viewAngle = clamp(viewAngle * 0.5f, -in_size, in_size); + viewAngle = sin(viewAngle); + // full view UVs, but shifted left/right depending on view angle + float2 uvStart2 = float2(1 - saturate(viewAngle), 0); + float2 uvEnd2 = float2(1 - saturate(viewAngle + 1), 1); + uvStart = float4(uvStart2.x, uvStart2.y, uvStart2.x, uvEnd2.y); + uvEnd = float4(uvEnd2.x, uvStart2.y, uvEnd2.x, uvEnd2.y); + + } else { + // use passed in data, offset around worldPos + Lw[0] = v0.xyz - worldPos; + Lw[1] = v1.xyz - worldPos; + Lw[2] = v2.xyz - worldPos; + Lw[3] = v3.xyz - worldPos; + #ifndef SHADER_TARGET_SURFACE_ANALYSIS + uvStart = _Udon_LTCGI_static_uniforms[uint2(4, i)]; + uvEnd = _Udon_LTCGI_static_uniforms[uint2(5, i)]; + #else + uvStart = float4(0, 0, 1, 0); + uvEnd = float4(1, 1, 0, 1); + #endif + + // we only detect triangles for "blender" import configuration, as those are the only + // ones that can actually be triangles (I think?) + isTri = /*distance(Lw[2], Lw[3]) < 0.001 || */distance(Lw[1], Lw[3]) < 0.001; + } +} + +#endif + +/* + +Parts of the code in this file are adapted from the example code found here: + + https://github.com/selfshadow/ltc_code + +Modifications by _pi_ (@pimaker on GitHub), licensed under the terms of the +MIT license as far as applicable. + +Original copyright notice: + +Copyright (c) 2017, Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* If you use (or adapt) the source code in your own work, please include a + reference to the paper: + + Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. + Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. + ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. + Project page: https://eheitzresearch.wordpress.com/415-2/ + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_shadowmap.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_shadowmap.cginc new file mode 100644 index 0000000..922c567 --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_shadowmap.cginc @@ -0,0 +1,84 @@ +#ifndef LTCGI_SHADOWMAP_INCLUDED +#define LTCGI_SHADOWMAP_INCLUDED + +// Adapted from: https://gitlab.com/s-ilent/filamented +// Licensed under the terms of the Apache License 2.0 +// Full text: https://gitlab.com/s-ilent/filamented/-/blob/master/LICENSE +// +// Conforming to the terms of the above license, this file is redistributed +// under the terms of the MIT license as part of the LTCGI shader package, +// provided this notice is kept. + +#ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER + +float4 LTCGI_cubic(float v) +{ + float4 n = float4(1.0, 2.0, 3.0, 4.0) - v; + float4 s = n * n * n; + float x = s.x; + float y = s.y - 4.0 * s.x; + float z = s.z - 4.0 * s.y + 6.0 * s.x; + float w = 6.0 - x - y - z; + return float4(x, y, z, w); +} + +// Unity's SampleTexture2DBicubic doesn't exist in 2018, which is our target here. +// So this is a similar function with tweaks to have similar semantics. + +float4 LTCGI_SampleTexture2DBicubicFilter(Texture2D tex, SamplerState smp, float2 coord, float4 texSize) +{ + coord = coord * texSize.xy - 0.5; + float fx = frac(coord.x); + float fy = frac(coord.y); + coord.x -= fx; + coord.y -= fy; + + float4 xcubic = LTCGI_cubic(fx); + float4 ycubic = LTCGI_cubic(fy); + + float4 c = float4(coord.x - 0.5, coord.x + 1.5, coord.y - 0.5, coord.y + 1.5); + float4 s = float4(xcubic.x + xcubic.y, xcubic.z + xcubic.w, ycubic.x + ycubic.y, ycubic.z + ycubic.w); + float4 offset = c + float4(xcubic.y, xcubic.w, ycubic.y, ycubic.w) / s; + + float4 sample0 = tex.Sample(smp, float2(offset.x, offset.z) * texSize.zw); + float4 sample1 = tex.Sample(smp, float2(offset.y, offset.z) * texSize.zw); + float4 sample2 = tex.Sample(smp, float2(offset.x, offset.w) * texSize.zw); + float4 sample3 = tex.Sample(smp, float2(offset.y, offset.w) * texSize.zw); + + float sx = s.x / (s.x + s.y); + float sy = s.z / (s.z + s.w); + + return lerp( + lerp(sample3, sample2, sx), + lerp(sample1, sample0, sx), sy); +} + +float4 LTCGI_SampleShadowmap(float2 lmuv) +{ + #ifdef LTCGI_ALWAYS_LTC_DIFFUSE + return 1; + #else + lmuv = lmuv * _Udon_LTCGI_LightmapST.xy + _Udon_LTCGI_LightmapST.zw; + + #ifdef LTCGI_BICUBIC_LIGHTMAP + float width, height; + _Udon_LTCGI_Lightmap.GetDimensions(width, height); + + float4 _Udon_LTCGI_Lightmap_TexelSize = float4(width, height, 1.0/width, 1.0/height); + + return LTCGI_SampleTexture2DBicubicFilter( + _Udon_LTCGI_Lightmap, LTCGI_SAMPLER, + lmuv, _Udon_LTCGI_Lightmap_TexelSize + ); + #else + return _Udon_LTCGI_Lightmap.Sample(LTCGI_SAMPLER, lmuv); + #endif + #endif +} + +#else +// surface shader analysis stub +float4 LTCGI_SampleShadowmap(float2 lmuv) { return 1; } +#endif + +#endif
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc new file mode 100644 index 0000000..164887f --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_structs.cginc @@ -0,0 +1,43 @@ +#ifndef LTCGI_STRUCTS_INCLUDED +#define LTCGI_STRUCTS_INCLUDED + +#define LTCGI_COLORMODE_STATIC 0 +#define LTCGI_COLORMODE_TEXTURE 1 +#define LTCGI_COLORMODE_SINGLEUV 2 +#define LTCGI_COLORMODE_AUDIOLINK 3 + +struct ltcgi_flags +{ + bool doublesided; // if the light is doublesided or only illuminates the front face + bool diffFromLm; // diffuse lighting intensity will not be calculated via LTC but taken directly from the lightmap + bool specular; // if the light has a specular component + bool diffuse; // if the light has a diffuse component + uint colormode; // colormode, see above + uint texindex; // index of the texture to shade with, if colormode == LTCGI_COLORMODE_TEXTURE + uint lmch, lmidx; // lightmap channel and index + bool cylinder; // is this light a cylinder + uint alBand; // audiolink band if colormode == LTCGI_COLORMODE_AUDIOLINK + bool lmdOnly; // if this light is lightmap-diffuse _only_, that is, no LTC will be run (Lw will be all 0 in that case) - this will never be true on avatars (with LTCGI_ALWAYS_LTC_DIFFUSE) +}; + +struct ltcgi_input +{ + uint i; // light number + float3 Lw[4]; // world space area light vertices, Lw[1] == Lw[3] for triangle lights, shifted by input worldPos (i.e. world space position as seen from (0, 0, 0)) + bool isTri; // if this is a triangle light, quad if false + float4 uvStart; // defines the UV layout of the area (xy = top-left, zw=top-right) + float4 uvEnd; // defines the UV layout of the area (xy = bottom-left, zw=bottom-right), different use for cylinders + float3 rawColor; // the raw light color, unaffected by any colormode calculations (i.e. exactly what's given as "color" in editor) + float3 screenNormal; // world space normal direction of area light + ltcgi_flags flags; // flags, see above +}; + +struct ltcgi_output +{ + ltcgi_input input; // input data that resulted in this output + + float intensity; // intensity output by LTC calculation + float3 color; // color output by LTCGI colormode calculation +}; + +#endif
\ No newline at end of file diff --git a/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_uniform.cginc b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_uniform.cginc new file mode 100644 index 0000000..116cedd --- /dev/null +++ b/Third_Party/at.pimaker.ltcgi/Shaders/LTCGI_uniform.cginc @@ -0,0 +1,142 @@ +#ifndef LTCGI_UNIFORM_INCLUDED +#define LTCGI_UNIFORM_INCLUDED + +// global sampler (trilinear) +#ifndef LTCGI_SAMPLER +SamplerState sampler_LTCGI_trilinear_clamp_sampler; +#define LTCGI_SAMPLER sampler_LTCGI_trilinear_clamp_sampler +#define LTCGI_SAMPLER_RAW _LTCGI_trilinear_clamp_sampler +#endif + +// LUTs +#ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER +uniform Texture2D<float4> _Udon_LTCGI_lut2; +uniform Texture2D<float4> _Udon_LTCGI_lut1; +#endif + +#ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER +uniform Texture2D<float4> _Udon_LTCGI_static_uniforms; +#endif + +#ifdef LTCGI_STATIC_UNIFORMS + +float4 _Udon_LTCGI_Vertices_0_get(uint i) { + return _Udon_LTCGI_static_uniforms[uint2(0, i)]; +} +float4 _Udon_LTCGI_Vertices_1_get(uint i) { + return _Udon_LTCGI_static_uniforms[uint2(1, i)]; +} +float4 _Udon_LTCGI_Vertices_2_get(uint i) { + return _Udon_LTCGI_static_uniforms[uint2(2, i)]; +} +float4 _Udon_LTCGI_Vertices_3_get(uint i) { + return _Udon_LTCGI_static_uniforms[uint2(3, i)]; +} + +#else + +// vertices in object space; w component is UV (legacy) +uniform float4 _Udon_LTCGI_Vertices_0[MAX_SOURCES]; +uniform float4 _Udon_LTCGI_Vertices_1[MAX_SOURCES]; +uniform float4 _Udon_LTCGI_Vertices_2[MAX_SOURCES]; +uniform float4 _Udon_LTCGI_Vertices_3[MAX_SOURCES]; + +float4 _Udon_LTCGI_Vertices_0_get(uint i) { + return _Udon_LTCGI_Vertices_0[i]; +} +float4 _Udon_LTCGI_Vertices_1_get(uint i) { + return _Udon_LTCGI_Vertices_1[i]; +} +float4 _Udon_LTCGI_Vertices_2_get(uint i) { + return _Udon_LTCGI_Vertices_2[i]; +} +float4 _Udon_LTCGI_Vertices_3_get(uint i) { + return _Udon_LTCGI_Vertices_3[i]; +} + +#endif + +// light source count, maximum is MAX_SOURCES +uniform uint _Udon_LTCGI_ScreenCount; + +// per-renderer mask to select sources, +// for max perf update _Udon_LTCGI_ScreenCount too +uniform bool _Udon_LTCGI_Mask[MAX_SOURCES]; + +// extra data per light source, layout: +// color.r color.g color.b flags* +// * b0=double-sided, b1=diffuse-from-lightmap, b2=specular, b3=diffuse, +// b4-b7=texture index (0=video, (n>0)=n-1) +// b8-b9=color mode +// b10-b11=lightmap channel (0=disabled, 1=r, 2=g, 3=b) +// b12=cylinder +// b13-14=audio link band +// b15=lightmap diffuse only +// (color black = fully disabled) +uniform float4 _Udon_LTCGI_ExtraData[MAX_SOURCES]; + +ltcgi_flags ltcgi_parse_flags(uint val, bool noLmDiff) +{ + ltcgi_flags ret = (ltcgi_flags)0; + ret.doublesided = (val & 1) == 1; + + #ifdef LTCGI_ALWAYS_LTC_DIFFUSE + ret.diffFromLm = false; + #else + ret.diffFromLm = !noLmDiff && (val & 2) == 2; + #endif + + ret.diffuse = (val & 8) == 8; + + ret.specular = (val & 4) == 4; + ret.texindex = (val & 0xf0) >> 4; + ret.colormode = (val & 0x300) >> 8; + + #ifdef LTCGI_ALWAYS_LTC_DIFFUSE + ret.lmch = 0; + #else + ret.lmch = (val & 0xC00) >> 10; + #endif + + ret.cylinder = (val & (1 << 12)) == (1 << 12); + + #ifdef LTCGI_AUDIOLINK + ret.alBand = (val & 0x6000) >> 13; + #endif + + ret.lmdOnly = (val & (1 << 15)) == (1 << 15); + + return ret; +} + +// video input +#ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER +uniform Texture2D<float4> _Udon_LTCGI_Texture_LOD0; +#ifndef LTCGI_FAST_SAMPLING +uniform Texture2D<float4> _Udon_LTCGI_Texture_LOD1; +uniform Texture2D<float4> _Udon_LTCGI_Texture_LOD2; +uniform Texture2D<float4> _Udon_LTCGI_Texture_LOD3; +#endif +#endif + +// static textures +UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(_Udon_LTCGI_Texture_LOD0_arr); +#ifndef LTCGI_FAST_SAMPLING +UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(_Udon_LTCGI_Texture_LOD1_arr); +UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(_Udon_LTCGI_Texture_LOD2_arr); +UNITY_DECLARE_TEX2DARRAY_NOSAMPLER(_Udon_LTCGI_Texture_LOD3_arr); +#endif + +// lightmap +#ifndef SHADER_TARGET_SURFACE_ANALYSIS_MOJOSHADER +#ifndef LTCGI_ALWAYS_LTC_DIFFUSE +uniform Texture2D<float4> _Udon_LTCGI_Lightmap; +#endif +#endif +uniform float3 _Udon_LTCGI_LightmapMult; +uniform float4 _Udon_LTCGI_LightmapST; + +// global toggle +uniform float _Udon_LTCGI_GlobalEnable; + +#endif
\ No newline at end of file |
