Advertisement
remo9211

URP Geo Grass With Interactor

May 20th, 2024 (edited)
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.33 KB | None | 0 0
  1. Shader "L04_URP/Grass_With_Interactor"{
  2. Properties{
  3.  
  4. _TopColor("Top Color", Color) = (1,1,1,1)
  5. _BottomColor("Bottom Color", Color) = (1,1,1,1)
  6. _TranslucentGain("Translucent Gain", Range(0,1)) = 0.5
  7.  
  8. _BendRotationRandom("Bend Rotation Random", Range(0, 1)) = 0.2
  9.  
  10. _BladeWidth("Blade Width", Float) = 0.05
  11. _BladeWidthRandom("Blade Width Random", Float) = 0.02
  12. _BladeHeight("Blade Height", Float) = 0.5
  13. _BladeHeightRandom("Blade Height Random", Float) = 0.3
  14.  
  15. [KeywordEnum(INTEGER, FRAC_EVEN, FRAC_ODD, POW2)] _PARTITIONING("Partition algoritm", Int) = 0
  16. [KeywordEnum(FIXED, SCREEN_BASE, WORLD_BASE)] _DYNAMIC("Dynamic Partition Mode", Int) = 0
  17. _TessellationFactor_FIXED("Tessellation FIXED", Range(1, 8)) = 1
  18. _TessellationFactor_SCREEN_BASE("Tessellation SCREEN_BASE", Range(0.01, 8)) = 0.05
  19. _TessellationFactor_WORLD_BASE("Tessellation WORLD_BASE", Range(0.01, 8)) = 0.08
  20.  
  21. _WindDistortionMap("Wind Distortion Map", 2D) = "white" {}
  22. _WindFrequency("Wind Frequency", Vector) = (0.05, 0.05, 0, 0)
  23.  
  24. _WindStrength("Wind Strength", Float) = 1
  25.  
  26. _BladeForward("Blade Forward Amount", Float) = 0.38
  27. _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
  28.  
  29. _Radius("Interactor Radius", Float) = 2.4
  30. _Strength("Interactor Strength", Float) = 1.7
  31.  
  32. [KeywordEnum(TRUE, FALSE)] _CUTTESS("Cut Tess", Int) = 0
  33.  
  34. }
  35. SubShader{
  36. Tags{
  37. "RenderType" = "Opaque"
  38. "Queue" = "Geometry"
  39. "RenderPipeline" = "UniversalPipeline"
  40. }
  41. LOD 100
  42. Cull Off
  43.  
  44. HLSLINCLUDE
  45. #pragma require geometry
  46. #pragma require tessellation tessHW
  47. #pragma vertex vert
  48. #pragma fragment frag
  49. #pragma hull hull
  50. #pragma domain domain
  51. #pragma geometry geo
  52. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  53. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  54. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
  55.  
  56. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
  57. #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
  58. #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
  59. #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
  60. #pragma multi_compile _ _SHADOWS_SOFT
  61.  
  62. #pragma shader_feature_local _PARTITIONING_INTEGER _PARTITIONING_FRAC_EVEN _PARTITIONING_FRAC_ODD _PARTITIONING_POW2
  63. #pragma shader_feature_local _CUTTESS_TRUE _CUTTESS_FALSE
  64. #pragma shader_feature_local _DYNAMIC_FIXED _DYNAMIC_SCREEN_BASE _DYNAMIC_WORLD_BASE
  65.  
  66. #define UNITY_PI 3.14159265359f
  67. #define UNITY_TWO_PI 6.28318530718f
  68. #define BLADE_SEGMENTS 3
  69.  
  70.  
  71.  
  72. CBUFFER_START(UnityPerMaterial)
  73. float4 _BaseColor;
  74. float4 _BaseMap_ST;
  75. float _BendRotationRandom;
  76.  
  77. float _BladeHeight;
  78. float _BladeHeightRandom;
  79. float _BladeWidth;
  80. float _BladeWidthRandom;
  81.  
  82. sampler2D _WindDistortionMap;
  83. float4 _WindDistortionMap_ST;
  84.  
  85. float2 _WindFrequency;
  86. float _WindStrength;
  87.  
  88. float _BladeForward;
  89. float _BladeCurve;
  90.  
  91. float4 _TopColor;
  92. float4 _BottomColor;
  93.  
  94. float _TessellationFactor_FIXED;
  95. float _TessellationFactor_SCREEN_BASE;
  96. float _TessellationFactor_WORLD_BASE;
  97.  
  98. float _TranslucentGain;
  99.  
  100.  
  101. uniform float3 _PositionMoving;
  102.  
  103. // float3 _PositionMoving; // 物体的位置
  104. float _Radius; // 物体的交互半径
  105. float _Strength; // 交互强度
  106.  
  107.  
  108. CBUFFER_END
  109. TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
  110.  
  111.  
  112. struct Attributes
  113. {
  114. float4 posOS : POSITION;
  115. float3 normalOS : NORMAL;
  116. float4 tangentOS : TANGENT;
  117. };
  118. struct TessellationControlPoint
  119. {
  120. float4 posOS : INTERNALTESSPOS;
  121. float3 normalOS : NORMAL;
  122. float4 tangentOS : TANGENT;
  123. float4 positionCS : TEXCOORD0;
  124. };
  125. struct Interpolators
  126. {
  127. float4 posOS : POSITION;
  128. float3 normalOS : NORMAL;
  129. float4 tangentOS : TANGENT;
  130. };
  131. struct TessellationFactors
  132. {
  133. float edge[3] : SV_TessFactor;
  134. float inside : SV_InsideTessFactor;
  135. };
  136. struct geometryOutput{
  137. float4 pos : SV_POSITION;
  138. float2 uv : TEXCOORD0;
  139. float4 shadowCoord : TEXCOORD1;
  140. float3 norWS : TEXCOORD2;
  141. // float3 normal : NORMAL;
  142. };
  143.  
  144. /*
  145. Tools Function
  146. */
  147. // float rand(float3 co){
  148. // return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
  149. // }
  150. float rand(float3 p){
  151. float3 p3 = frac(float3(p.xyz) * .1031);
  152. p3 += dot(p3, p3.yzx + 33.33);
  153. return frac((p3.x + p3.y) * p3.z);
  154. }
  155.  
  156.  
  157. float3x3 AngleAxis3x3(float angle, float3 axis){
  158. float c, s;
  159. sincos(angle, s, c);
  160.  
  161. float t = 1 - c;
  162. float x = axis.x;
  163. float y = axis.y;
  164. float z = axis.z;
  165.  
  166. return float3x3(
  167. t * x * x + c, t * x * y - s * z, t * x * z + s * y,
  168. t * x * y + s * z, t * y * y + c, t * y * z - s * x,
  169. t * x * z - s * y, t * y * z + s * x, t * z * z + c
  170. );
  171. }
  172. bool IsOutOfBounds(float3 p, float3 lower, float3 higher) { //给定矩形判断
  173. return p.x < lower.x || p.x > higher.x || p.y < lower.y || p.y > higher.y || p.z < lower.z || p.z > higher.z;
  174. }
  175. bool IsPointOutOfFrustum(float4 positionCS) { //视锥体判断
  176. float3 culling = positionCS.xyz;
  177. float w = positionCS.w;
  178. float3 lowerBounds = float3(-w, -w, -w * _ProjectionParams.z);
  179. float3 higherBounds = float3(w, w, w);
  180. return IsOutOfBounds(culling, lowerBounds, higherBounds);
  181. }
  182. bool ShouldClipPatch(float4 p0PositionCS, float4 p1PositionCS, float4 p2PositionCS) {
  183. bool allOutside = IsPointOutOfFrustum(p0PositionCS) &&
  184. IsPointOutOfFrustum(p1PositionCS) &&
  185. IsPointOutOfFrustum(p2PositionCS);
  186. return allOutside;
  187. }
  188. // 生成草的具體座標, 草的寬度, 草的高度, 草的朝向, uv傳遞, 變換矩陣
  189. geometryOutput GenerateGrassVertex(float3 vertexPosition, float width, float height, float forward, float2 uv, float3x3 transformMatrix) {
  190. float3 tangentPoint = float3(width, forward, height);
  191. float3 localPosition = vertexPosition + mul(transformMatrix, tangentPoint);
  192. float3 tangentNormal = normalize(float3(0, -1, forward));
  193. float3 localNormal = mul(transformMatrix, tangentNormal);
  194. float3 posWS = TransformObjectToWorld(localPosition.xyz);
  195. float3 norWS = TransformObjectToWorldNormal(localNormal);
  196. geometryOutput o;
  197. o.pos = TransformObjectToHClip(localPosition);
  198. o.uv = uv;
  199. o.norWS = norWS;
  200. o.shadowCoord = TransformWorldToShadowCoord(posWS);
  201. #if UNITY_PASS_SHADOWCASTER
  202. // o.pos = UnityApplyLinearShadowBias(o.pos);
  203. o.shadowCoord = TransformWorldToShadowCoord(ApplyShadowBias(posWS, norWS, 0));
  204. #endif
  205. return o;
  206. }
  207. float EdgeTessellationFactor_ScreenBase(float scale, float4 p0PositionCS, float4 p1PositionCS) {
  208. float factor = distance(p0PositionCS.xyz / p0PositionCS.w, p1PositionCS.xyz / p1PositionCS.w);
  209. return max(1, factor / scale);
  210. }
  211. float EdgeTessellationFactor_WorldBase(float scale, float3 p0PositionWS, float3 p1PositionWS) {
  212. float length = distance(p0PositionWS, p1PositionWS);
  213. float distanceToCamera = distance(_WorldSpaceCameraPos, (p0PositionWS + p1PositionWS) * 0.5);
  214. // 使用平方根函数调整距离的影响,使中距离的镶嵌因子变化更平滑
  215. float adjustedDistance = sqrt(distanceToCamera);
  216. float factor = length / (scale * adjustedDistance);
  217. return max(1, factor);
  218. }
  219.  
  220.  
  221. /*
  222. Vertex Shader
  223. */
  224. TessellationControlPoint vert(Attributes v){
  225. TessellationControlPoint o;
  226. o.posOS = v.posOS;
  227. o.normalOS = v.normalOS;
  228. o.tangentOS = v.tangentOS;
  229. o.positionCS = TransformObjectToHClip(v.posOS.xyz);
  230. return o;
  231. }
  232. /*
  233. Tesselation Shader
  234. */
  235. TessellationFactors patchConstantFunction (InputPatch<TessellationControlPoint, 3> patch){
  236. TessellationFactors f;
  237. #if defined(_DYNAMIC_FIXED)
  238. f.edge[0] = _TessellationFactor_FIXED;
  239. f.edge[1] = _TessellationFactor_FIXED;
  240. f.edge[2] = _TessellationFactor_FIXED;
  241. f.inside = _TessellationFactor_FIXED;
  242. #elif defined(_DYNAMIC_SCREEN_BASE)
  243. f.edge[0] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
  244. patch[1].positionCS, patch[2].positionCS);
  245. f.edge[1] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
  246. patch[2].positionCS, patch[0].positionCS);
  247. f.edge[2] = EdgeTessellationFactor_ScreenBase(_TessellationFactor_SCREEN_BASE,
  248. patch[0].positionCS, patch[1].positionCS);
  249. f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3.0;
  250. #elif defined(_DYNAMIC_WORLD_BASE)
  251. f.edge[0] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
  252. patch[1].posOS, patch[2].posOS);
  253. f.edge[1] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
  254. patch[2].posOS, patch[0].posOS);
  255. f.edge[2] = EdgeTessellationFactor_WorldBase(_TessellationFactor_WORLD_BASE,
  256. patch[0].posOS, patch[1].posOS);
  257. f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) / 3.0;
  258. #else
  259. f.edge[0] = _TessellationFactor_FIXED;
  260. f.edge[1] = _TessellationFactor_FIXED;
  261. f.edge[2] = _TessellationFactor_FIXED;
  262. f.inside = _TessellationFactor_FIXED;
  263. #endif
  264.  
  265. #if defined(_CUTTESS_TRUE)
  266. if(ShouldClipPatch(patch[0].positionCS, patch[1].positionCS, patch[2].positionCS))
  267. f.edge[0] = f.edge[1] = f.edge[2] = f.inside = 0;
  268. #endif
  269.  
  270. return f;
  271. }
  272. [patchconstantfunc("patchConstantFunction")]
  273. [domain("tri")][outputcontrolpoints(3)]
  274. [outputtopology("triangle_cw")]
  275. #if defined(_PARTITIONING_INTEGER)
  276. [partitioning("integer")]
  277. #elif defined(_PARTITIONING_FRAC_EVEN)
  278. [partitioning("fractional_even")]
  279. #elif defined(_PARTITIONING_FRAC_ODD)
  280. [partitioning("fractional_odd")]
  281. #elif defined(_PARTITIONING_POW2)
  282. [partitioning("pow2")]
  283. #else
  284. [partitioning("integer")]
  285. #endif
  286. TessellationControlPoint hull (InputPatch<TessellationControlPoint, 3> patch, uint id : SV_OutputControlPointID){
  287. return patch[id];
  288. }
  289.  
  290. [domain("tri")]
  291. Interpolators domain(TessellationFactors factors, OutputPatch<TessellationControlPoint, 3> patch,
  292. float3 barycentricCoordinates : SV_DomainLocation)
  293. {
  294. Interpolators v;
  295. #define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) v.fieldName = \
  296. patch[0].fieldName * barycentricCoordinates.x + \
  297. patch[1].fieldName * barycentricCoordinates.y + \
  298. patch[2].fieldName * barycentricCoordinates.z;
  299. MY_DOMAIN_PROGRAM_INTERPOLATE(posOS)
  300. MY_DOMAIN_PROGRAM_INTERPOLATE(normalOS)
  301. MY_DOMAIN_PROGRAM_INTERPOLATE(tangentOS)
  302. return v;
  303. }
  304. [maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
  305. void geo(triangle Interpolators IN[3], inout TriangleStream<geometryOutput> triStream){
  306. float3 vNormal = IN[0].normalOS;
  307. float4 vTangent = IN[0].tangentOS;
  308. float3 vBinormal = cross(vNormal, vTangent.xyz) * vTangent.w;
  309.  
  310. float3x3 tangentToLocal = float3x3(
  311. vTangent.x, vBinormal.x, vNormal.x,
  312. vTangent.y, vBinormal.y, vNormal.y,
  313. vTangent.z, vBinormal.z, vNormal.z
  314. );
  315. float3 pos = IN[0].posOS.xyz;
  316. float3 worldPos = TransformObjectToWorld(IN[0].posOS.xyz);
  317.  
  318.  
  319. float3x3 facingRotationMatrix = AngleAxis3x3(rand(pos) * UNITY_TWO_PI, float3(0, 0, 1));
  320. float3x3 bendRotationMatrix = AngleAxis3x3(rand(pos.zzx) * _BendRotationRandom * UNITY_PI * 0.2, float3(-1, 0, 0));
  321.  
  322. float2 uv = pos.xz * _WindDistortionMap_ST.xy + _WindDistortionMap_ST.zw + _WindFrequency * _Time.y;
  323.  
  324. float2 windSample = (tex2Dlod(_WindDistortionMap, float4(uv, 0, 0)).xy * 2 - 1) * _WindStrength;
  325.  
  326. float3 wind = normalize(float3(windSample.x, windSample.y, 0));
  327.  
  328. float3x3 windRotation = AngleAxis3x3(UNITY_PI * windSample.x * 0.2, wind);
  329.  
  330. float3x3 transformationMatrix = mul(mul(mul(tangentToLocal, windRotation), facingRotationMatrix), bendRotationMatrix);
  331.  
  332. float height = (rand(pos.zyx) * 2 - 1) * _BladeHeightRandom + _BladeHeight;
  333. float width = (rand(pos.xzy) * 2 - 1) * _BladeWidthRandom + _BladeWidth;
  334.  
  335. float forward = rand(pos.yyz) * _BladeForward;
  336.  
  337. float3x3 transformationMatrixFacing = mul(tangentToLocal, facingRotationMatrix);
  338.  
  339. // 计算交互效果
  340. float dis = distance(_PositionMoving, worldPos);
  341. float radiusEffect = 1 - saturate(dis / _Radius);
  342. float3 sphereDisp = pos - _PositionMoving;
  343. sphereDisp *= radiusEffect * _Strength;
  344. sphereDisp = clamp(sphereDisp, -0.8, 0.8);
  345.  
  346. for (int i = 0; i < BLADE_SEGMENTS; i++){
  347. float t = i / (float)BLADE_SEGMENTS;
  348. float segmentHeight = height * t;
  349. float segmentWidth = width * (1 - t);
  350. float segmentForward = pow(t, _BladeCurve) * forward;
  351. float3x3 transformMatrix = i == 0 ? transformationMatrixFacing : transformationMatrix;
  352.  
  353. // 应用交互效果
  354. float3 newPos = i == 0 ? pos : pos + (sphereDisp * t);
  355.  
  356. triStream.Append(GenerateGrassVertex(newPos, segmentWidth, segmentHeight, segmentForward, float2(0, t), transformMatrix));
  357. triStream.Append(GenerateGrassVertex(newPos, -segmentWidth, segmentHeight, segmentForward, float2(1, t), transformMatrix));
  358. }
  359.  
  360. // 最后的草片段
  361. float3 newPosTop = pos + sphereDisp;
  362. triStream.Append(GenerateGrassVertex(newPosTop, 0, height, forward, float2(0.5, 1), transformationMatrix));
  363. triStream.RestartStrip();
  364. }
  365.  
  366. ENDHLSL
  367.  
  368. Pass{
  369. Name "GrassPass"
  370. Tags{ "LightMode" = "UniversalForward" }
  371.  
  372. HLSLPROGRAM
  373.  
  374. float4 frag (geometryOutput IN, float facing : VFACE) : SV_Target {
  375. Light mainLight = GetMainLight(IN.shadowCoord);
  376.  
  377. float3 normal = facing > 0 ? IN.norWS : -IN.norWS;
  378.  
  379. float shadow = lerp(0.0, 1.0, mainLight.shadowAttenuation + 0.25f);
  380. float NdotL = saturate(saturate(dot(normal, mainLight.direction)) + _TranslucentGain) * shadow;
  381.  
  382. float3 ambient = SampleSH(normal);
  383. float4 lightIntensity = float4(ambient + NdotL * _MainLightColor.rgb, 1.0);
  384. float4 col = lerp(_BottomColor, _TopColor * lightIntensity, IN.uv.y);
  385.  
  386. return col;
  387. }
  388. ENDHLSL
  389. }
  390.  
  391.  
  392. Pass{
  393. Name "ShadowCaster"
  394. Tags{ "RenderType" = "Opaque" "LightMode" = "ShadowCaster" }
  395.  
  396. ZWrite On
  397. ZTest LEqual
  398.  
  399. HLSLPROGRAM
  400. half4 frag(geometryOutput input) : SV_TARGET{
  401. return 1;
  402. }
  403.  
  404. ENDHLSL
  405. }
  406. }
  407. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement