暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StencilDeferred.hlsl 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #ifndef UNIVERSAL_STENCIL_DEFERRED
  2. #define UNIVERSAL_STENCIL_DEFERRED
  3. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  4. #include "Packages/com.unity.render-pipelines.universal/Shaders/Utils/Deferred.hlsl"
  5. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  6. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DynamicScaling.hlsl"
  7. #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
  8. struct Attributes
  9. {
  10. float4 positionOS : POSITION;
  11. uint vertexID : SV_VertexID;
  12. UNITY_VERTEX_INPUT_INSTANCE_ID
  13. };
  14. struct Varyings
  15. {
  16. float4 positionCS : SV_POSITION;
  17. float3 screenUV : TEXCOORD1;
  18. UNITY_VERTEX_INPUT_INSTANCE_ID
  19. UNITY_VERTEX_OUTPUT_STEREO
  20. };
  21. #if defined(_SPOT)
  22. float4 _SpotLightScale;
  23. float4 _SpotLightBias;
  24. float4 _SpotLightGuard;
  25. #endif
  26. Varyings Vertex(Attributes input)
  27. {
  28. Varyings output = (Varyings)0;
  29. UNITY_SETUP_INSTANCE_ID(input);
  30. UNITY_TRANSFER_INSTANCE_ID(input, output);
  31. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  32. float3 positionOS = input.positionOS.xyz;
  33. #if defined(_SPOT)
  34. // Spot lights have an outer angle than can be up to 180 degrees, in which case the shape
  35. // becomes a capped hemisphere. There is no affine transforms to handle the particular cone shape,
  36. // so instead we will adjust the vertices positions in the vertex shader to get the tighest fit.
  37. [flatten] if (any(positionOS.xyz))
  38. {
  39. // The hemisphere becomes the rounded cap of the cone.
  40. positionOS.xyz = _SpotLightBias.xyz + _SpotLightScale.xyz * positionOS.xyz;
  41. positionOS.xyz = normalize(positionOS.xyz) * _SpotLightScale.w;
  42. // Slightly inflate the geometry to fit the analytic cone shape.
  43. // We want the outer rim to be expanded along xy axis only, while the rounded cap is extended along all axis.
  44. positionOS.xyz = (positionOS.xyz - float3(0, 0, _SpotLightGuard.w)) * _SpotLightGuard.xyz + float3(0, 0, _SpotLightGuard.w);
  45. }
  46. #endif
  47. #if defined(_DIRECTIONAL) || defined(_FOG) || defined(_CLEAR_STENCIL_PARTIAL) || (defined(_SSAO_ONLY) && defined(_SCREEN_SPACE_OCCLUSION))
  48. // Full screen render using a large triangle.
  49. output.positionCS = float4(positionOS.xy, UNITY_RAW_FAR_CLIP_VALUE, 1.0); // Force triangle to be on zfar
  50. #elif defined(_SSAO_ONLY) && !defined(_SCREEN_SPACE_OCCLUSION)
  51. // Deferred renderer does not know whether there is a SSAO feature or not at the C# scripting level.
  52. // However, this is known at the shader level because of the shader keyword SSAO feature enables.
  53. // If the keyword was not enabled, discard the SSAO_only pass by rendering the geometry outside the screen.
  54. output.positionCS = float4(positionOS.xy, -2, 1.0); // Force triangle to be discarded
  55. #else
  56. // Light shape geometry is projected as normal.
  57. VertexPositionInputs vertexInput = GetVertexPositionInputs(positionOS.xyz);
  58. output.positionCS = vertexInput.positionCS;
  59. #endif
  60. output.screenUV = output.positionCS.xyw;
  61. #if UNITY_UV_STARTS_AT_TOP
  62. output.screenUV.xy = output.screenUV.xy * float2(0.5, -0.5) + 0.5 * output.screenUV.z;
  63. #else
  64. output.screenUV.xy = output.screenUV.xy * 0.5 + 0.5 * output.screenUV.z;
  65. #endif
  66. output.screenUV.xy = DynamicScalingApplyScaleBias(output.screenUV.xy, float4(_RTHandleScale.xy, 0.0f, 0.0f));
  67. return output;
  68. }
  69. TEXTURE2D_X(_CameraDepthTexture);
  70. TEXTURE2D_X_HALF(_GBuffer0);
  71. TEXTURE2D_X_HALF(_GBuffer1);
  72. TEXTURE2D_X_HALF(_GBuffer2);
  73. #if _RENDER_PASS_ENABLED
  74. #define GBUFFER0 0
  75. #define GBUFFER1 1
  76. #define GBUFFER2 2
  77. #define GBUFFER3 3
  78. FRAMEBUFFER_INPUT_X_HALF(GBUFFER0);
  79. FRAMEBUFFER_INPUT_X_HALF(GBUFFER1);
  80. FRAMEBUFFER_INPUT_X_HALF(GBUFFER2);
  81. FRAMEBUFFER_INPUT_X_FLOAT(GBUFFER3);
  82. #if OUTPUT_SHADOWMASK && (defined(_WRITE_RENDERING_LAYERS) || defined(_LIGHT_LAYERS))
  83. #define GBUFFER4 4
  84. #define GBUFFER5 5
  85. TEXTURE2D_X_HALF(_GBuffer4);
  86. TEXTURE2D_X_HALF(_GBuffer5);
  87. FRAMEBUFFER_INPUT_X_HALF(GBUFFER4);
  88. FRAMEBUFFER_INPUT_X_HALF(GBUFFER5);
  89. #elif OUTPUT_SHADOWMASK || defined(_WRITE_RENDERING_LAYERS) || defined(_LIGHT_LAYERS)
  90. #define GBUFFER4 4
  91. TEXTURE2D_X_HALF(_GBuffer4);
  92. FRAMEBUFFER_INPUT_X_HALF(GBUFFER4);
  93. #endif
  94. #else
  95. #ifdef GBUFFER_OPTIONAL_SLOT_1
  96. TEXTURE2D_X_HALF(_GBuffer4);
  97. #endif
  98. #ifdef GBUFFER_OPTIONAL_SLOT_2
  99. TEXTURE2D_X(_GBuffer5);
  100. #endif
  101. #endif
  102. #ifdef GBUFFER_OPTIONAL_SLOT_3
  103. TEXTURE2D_X(_GBuffer6);
  104. #endif
  105. float4x4 _ScreenToWorld[2];
  106. // 2023.3 Deprecated. This is for backwards compatibility. Remove in the future.
  107. #define my_point_clamp_sampler sampler_PointClamp
  108. float3 _LightPosWS;
  109. half3 _LightColor;
  110. half4 _LightAttenuation; // .xy are used by DistanceAttenuation - .zw are used by AngleAttenuation *for SpotLights)
  111. half3 _LightDirection; // directional/spotLights support
  112. half4 _LightOcclusionProbInfo;
  113. int _LightFlags;
  114. int _ShadowLightIndex;
  115. uint _LightLayerMask;
  116. int _CookieLightIndex;
  117. half4 FragWhite(Varyings input) : SV_Target
  118. {
  119. return half4(1.0, 1.0, 1.0, 1.0);
  120. }
  121. half4 SampleAdditionalLightCookieDeferred(int perObjectLightIndex, float3 samplePositionWS)
  122. {
  123. float4 cookieUvRect = GetLightCookieAtlasUVRect(perObjectLightIndex);
  124. float4x4 worldToLight = GetLightCookieWorldToLightMatrix(perObjectLightIndex);
  125. float2 cookieUv = float2(0,0);
  126. #if defined(_SPOT)
  127. cookieUv = ComputeLightCookieUVSpot(worldToLight, samplePositionWS, cookieUvRect);
  128. #endif
  129. #if defined(_POINT)
  130. cookieUv = ComputeLightCookieUVPoint(worldToLight, samplePositionWS, cookieUvRect);
  131. #endif
  132. #if defined(_DIRECTIONAL)
  133. cookieUv = ComputeLightCookieUVDirectional(worldToLight, samplePositionWS, cookieUvRect, URP_TEXTURE_WRAP_MODE_REPEAT);
  134. #endif
  135. half4 cookieColor = SampleAdditionalLightsCookieAtlasTexture(cookieUv);
  136. cookieColor = half4(IsAdditionalLightsCookieAtlasTextureRGBFormat() ? cookieColor.rgb
  137. : IsAdditionalLightsCookieAtlasTextureAlphaFormat() ? cookieColor.aaa
  138. : cookieColor.rrr, 1);
  139. return cookieColor;
  140. }
  141. Light GetStencilLight(float3 posWS, float2 screen_uv, half4 shadowMask, uint materialFlags)
  142. {
  143. Light unityLight;
  144. bool materialReceiveShadowsOff = (materialFlags & kMaterialFlagReceiveShadowsOff) != 0;
  145. uint lightLayerMask =_LightLayerMask;
  146. #if defined(_DIRECTIONAL)
  147. #if defined(_DEFERRED_MAIN_LIGHT)
  148. unityLight = GetMainLight();
  149. // unity_LightData.z is set per mesh for forward renderer, we cannot cull lights in this fashion with deferred renderer.
  150. unityLight.distanceAttenuation = 1.0;
  151. if (!materialReceiveShadowsOff)
  152. {
  153. #if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
  154. float4 shadowCoord = float4(screen_uv, 0.0, 1.0);
  155. #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
  156. float4 shadowCoord = TransformWorldToShadowCoord(posWS.xyz);
  157. #else
  158. float4 shadowCoord = float4(0, 0, 0, 0);
  159. #endif
  160. unityLight.shadowAttenuation = MainLightShadow(shadowCoord, posWS.xyz, shadowMask, _MainLightOcclusionProbes);
  161. }
  162. #if defined(_LIGHT_COOKIES)
  163. real3 cookieColor = SampleMainLightCookie(posWS);
  164. unityLight.color *= half3(cookieColor);
  165. #endif
  166. #else
  167. unityLight.direction = _LightDirection;
  168. unityLight.distanceAttenuation = 1.0;
  169. unityLight.shadowAttenuation = 1.0;
  170. unityLight.color = _LightColor.rgb;
  171. unityLight.layerMask = lightLayerMask;
  172. if (!materialReceiveShadowsOff)
  173. {
  174. #if defined(_ADDITIONAL_LIGHT_SHADOWS)
  175. unityLight.shadowAttenuation = AdditionalLightShadow(_ShadowLightIndex, posWS.xyz, _LightDirection, shadowMask, _LightOcclusionProbInfo);
  176. #endif
  177. }
  178. #ifdef _LIGHT_COOKIES
  179. // Enable/disable is done toggling the keyword _LIGHT_COOKIES, but we could do a "static if" instead if required.
  180. // if(_CookieLightIndex >= 0)
  181. {
  182. half3 cookieColor = SampleAdditionalLightCookieDeferred(_CookieLightIndex, posWS).xyz;
  183. unityLight.color *= cookieColor;
  184. }
  185. #endif
  186. #endif
  187. #else
  188. PunctualLightData light;
  189. light.posWS = _LightPosWS;
  190. light.radius2 = 0.0; // only used by tile-lights.
  191. light.color = float4(_LightColor, 0.0);
  192. light.attenuation = _LightAttenuation;
  193. light.spotDirection = _LightDirection;
  194. light.occlusionProbeInfo = _LightOcclusionProbInfo;
  195. light.flags = _LightFlags;
  196. light.layerMask = lightLayerMask;
  197. unityLight = UnityLightFromPunctualLightDataAndWorldSpacePosition(light, posWS.xyz, shadowMask, _ShadowLightIndex, materialReceiveShadowsOff);
  198. #ifdef _LIGHT_COOKIES
  199. // Enable/disable is done toggling the keyword _LIGHT_COOKIES, but we could do a "static if" instead if required.
  200. // if(_CookieLightIndex >= 0)
  201. {
  202. half3 cookieColor = SampleAdditionalLightCookieDeferred(_CookieLightIndex, posWS).xyz;
  203. unityLight.color *= cookieColor;
  204. }
  205. #endif
  206. #endif
  207. return unityLight;
  208. }
  209. half4 DeferredShading(Varyings input) : SV_Target
  210. {
  211. UNITY_SETUP_INSTANCE_ID(input);
  212. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  213. float2 screen_uv = (input.screenUV.xy / input.screenUV.z);
  214. #if defined(SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  215. float2 undistorted_screen_uv = screen_uv;
  216. UNITY_BRANCH if (_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  217. {
  218. screen_uv = input.positionCS.xy * _ScreenSize.zw;
  219. }
  220. #endif
  221. half4 shadowMask = 1.0;
  222. #if _RENDER_PASS_ENABLED
  223. float d = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER3, input.positionCS.xy).x;
  224. half4 gbuffer0 = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER0, input.positionCS.xy);
  225. half4 gbuffer1 = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER1, input.positionCS.xy);
  226. half4 gbuffer2 = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER2, input.positionCS.xy);
  227. #if defined(_DEFERRED_MIXED_LIGHTING)
  228. shadowMask = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER4, input.positionCS.xy);
  229. #endif
  230. #else
  231. // Using SAMPLE_TEXTURE2D is faster than using LOAD_TEXTURE2D on iOS platforms (5% faster shader).
  232. // Possible reason: HLSLcc upcasts Load() operation to float, which doesn't happen for Sample()?
  233. float d = SAMPLE_TEXTURE2D_X_LOD(_CameraDepthTexture, sampler_PointClamp, screen_uv, 0).x; // raw depth value has UNITY_REVERSED_Z applied on most platforms.
  234. half4 gbuffer0 = SAMPLE_TEXTURE2D_X_LOD(_GBuffer0, sampler_PointClamp, screen_uv, 0);
  235. half4 gbuffer1 = SAMPLE_TEXTURE2D_X_LOD(_GBuffer1, sampler_PointClamp, screen_uv, 0);
  236. half4 gbuffer2 = SAMPLE_TEXTURE2D_X_LOD(_GBuffer2, sampler_PointClamp, screen_uv, 0);
  237. #if defined(_DEFERRED_MIXED_LIGHTING)
  238. shadowMask = SAMPLE_TEXTURE2D_X_LOD(MERGE_NAME(_, GBUFFER_SHADOWMASK), sampler_PointClamp, screen_uv, 0);
  239. #endif
  240. #endif
  241. half surfaceDataOcclusion = gbuffer1.a;
  242. uint materialFlags = UnpackMaterialFlags(gbuffer0.a);
  243. half3 color = 0.0.xxx;
  244. half alpha = 1.0;
  245. #if defined(_DEFERRED_MIXED_LIGHTING)
  246. // If both lights and geometry are static, then no realtime lighting to perform for this combination.
  247. [branch] if ((_LightFlags & materialFlags) == kMaterialFlagSubtractiveMixedLighting)
  248. return half4(color, alpha); // Cannot discard because stencil must be updated.
  249. #endif
  250. #if defined(SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  251. UNITY_BRANCH if (_FOVEATED_RENDERING_NON_UNIFORM_RASTER)
  252. {
  253. input.positionCS.xy = undistorted_screen_uv * _ScreenSize.xy;
  254. }
  255. #endif
  256. #if defined(USING_STEREO_MATRICES)
  257. int eyeIndex = unity_StereoEyeIndex;
  258. #else
  259. int eyeIndex = 0;
  260. #endif
  261. float4 posWS = mul(_ScreenToWorld[eyeIndex], float4(input.positionCS.xy, d, 1.0));
  262. posWS.xyz *= rcp(posWS.w);
  263. Light unityLight = GetStencilLight(posWS.xyz, screen_uv, shadowMask, materialFlags);
  264. #ifdef _LIGHT_LAYERS
  265. #if _RENDER_PASS_ENABLED
  266. float renderingLayers = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER4, input.positionCS.xy).x;
  267. #else
  268. float4 renderingLayers = SAMPLE_TEXTURE2D_X_LOD(MERGE_NAME(_, GBUFFER_LIGHT_LAYERS), sampler_PointClamp, screen_uv, 0);
  269. #endif
  270. uint meshRenderingLayers = DecodeMeshRenderingLayer(renderingLayers);
  271. [branch] if (!IsMatchingLightLayer(unityLight.layerMask, meshRenderingLayers))
  272. return half4(color, alpha); // Cannot discard because stencil must be updated.
  273. #endif
  274. #if defined(_SCREEN_SPACE_OCCLUSION) && !defined(_SURFACE_TYPE_TRANSPARENT)
  275. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(screen_uv);
  276. unityLight.color *= aoFactor.directAmbientOcclusion;
  277. #if defined(_DIRECTIONAL) && defined(_DEFERRED_FIRST_LIGHT)
  278. // What we want is really to apply the mininum occlusion value between the baked occlusion from surfaceDataOcclusion and real-time occlusion from SSAO.
  279. // But we already applied the baked occlusion during gbuffer pass, so we have to cancel it out here.
  280. // We must also avoid divide-by-0 that the reciprocal can generate.
  281. half occlusion = aoFactor.indirectAmbientOcclusion < surfaceDataOcclusion ? aoFactor.indirectAmbientOcclusion * rcp(surfaceDataOcclusion) : 1.0;
  282. alpha = occlusion;
  283. #endif
  284. #endif
  285. InputData inputData = InputDataFromGbufferAndWorldPosition(gbuffer2, posWS.xyz);
  286. #if defined(_LIT)
  287. #if SHADER_API_MOBILE || SHADER_API_SWITCH
  288. // Specular highlights are still silenced by setting specular to 0.0 during gbuffer pass and GPU timing is still reduced.
  289. bool materialSpecularHighlightsOff = false;
  290. #else
  291. bool materialSpecularHighlightsOff = (materialFlags & kMaterialFlagSpecularHighlightsOff);
  292. #endif
  293. BRDFData brdfData = BRDFDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2);
  294. color = LightingPhysicallyBased(brdfData, unityLight, inputData.normalWS, inputData.viewDirectionWS, materialSpecularHighlightsOff);
  295. #elif defined(_SIMPLELIT)
  296. SurfaceData surfaceData = SurfaceDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2, kLightingSimpleLit);
  297. half3 attenuatedLightColor = unityLight.color * (unityLight.distanceAttenuation * unityLight.shadowAttenuation);
  298. half3 diffuseColor = LightingLambert(attenuatedLightColor, unityLight.direction, inputData.normalWS);
  299. half smoothness = exp2(10 * surfaceData.smoothness + 1);
  300. half3 specularColor = LightingSpecular(attenuatedLightColor, unityLight.direction, inputData.normalWS, inputData.viewDirectionWS, half4(surfaceData.specular, 1), smoothness);
  301. // TODO: if !defined(_SPECGLOSSMAP) && !defined(_SPECULAR_COLOR), force specularColor to 0 in gbuffer code
  302. color = diffuseColor * surfaceData.albedo + specularColor;
  303. #endif
  304. return half4(color, alpha);
  305. }
  306. half4 FragFog(Varyings input) : SV_Target
  307. {
  308. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  309. #if _RENDER_PASS_ENABLED
  310. float d = LOAD_FRAMEBUFFER_X_INPUT(GBUFFER3, input.positionCS.xy).x;
  311. #else
  312. float d = LOAD_TEXTURE2D_X(_CameraDepthTexture, input.positionCS.xy).x;
  313. #endif
  314. float eye_z = LinearEyeDepth(d, _ZBufferParams);
  315. float clip_z = UNITY_MATRIX_P[2][2] * -eye_z + UNITY_MATRIX_P[2][3];
  316. half fogFactor = ComputeFogFactor(clip_z);
  317. half fogIntensity = ComputeFogIntensity(fogFactor);
  318. return half4(unity_FogColor.rgb, fogIntensity);
  319. }
  320. half4 FragSSAOOnly(Varyings input) : SV_Target
  321. {
  322. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  323. float2 screen_uv = (input.screenUV.xy / input.screenUV.z);
  324. AmbientOcclusionFactor aoFactor = GetScreenSpaceAmbientOcclusion(screen_uv);
  325. half surfaceDataOcclusion = SAMPLE_TEXTURE2D_X_LOD(_GBuffer1, sampler_PointClamp, screen_uv, 0).a;
  326. // What we want is really to apply the mininum occlusion value between the baked occlusion from surfaceDataOcclusion and real-time occlusion from SSAO.
  327. // But we already applied the baked occlusion during gbuffer pass, so we have to cancel it out here.
  328. // We must also avoid divide-by-0 that the reciprocal can generate.
  329. half occlusion = aoFactor.indirectAmbientOcclusion < surfaceDataOcclusion ? aoFactor.indirectAmbientOcclusion * rcp(surfaceDataOcclusion) : 1.0;
  330. return half4(0.0, 0.0, 0.0, occlusion);
  331. }
  332. #endif //UNIVERSAL_STENCIL_DEFERRED