//Unity Toon Shader/HDRP //nobuyuki@unity3d.com //toshiyuki@unity3d.com (Universal RP/HDRP) #define APPROXIMATE_POLY_LIGHT_AS_SPHERE_LIGHT #if SHADERPASS != SHADERPASS_FORWARD #error SHADERPASS_is_not_correctly_define #endif #ifndef SCALARIZE_LIGHT_LOOP // We perform scalarization only for forward rendering as for deferred loads will already be scalar since tiles will match waves and therefore all threads will read from the same tile. // More info on scalarization: https://flashypixels.wordpress.com/2018/11/10/intro-to-gpu-scalarization-part-2-scalarize-all-the-lights/ . // Note that it is currently disabled on gamecore platforms for issues with wave intrinsics and the new compiler, it will be soon investigated, but we disable it in the meantime. #define SCALARIZE_LIGHT_LOOP (defined(PLATFORM_SUPPORTS_WAVE_INTRINSICS) && !defined(LIGHTLOOP_DISABLE_TILE_AND_CLUSTER) && !defined(SHADER_API_GAMECORE) && SHADERPASS == SHADERPASS_FORWARD) #endif #ifdef _WRITE_TRANSPARENT_MOTION_VECTOR #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/MotionVectorVertexShaderCommon.hlsl" PackedVaryingsType Vert(AttributesMesh inputMesh, AttributesPass inputPass) { VaryingsType varyingsType; varyingsType.vmesh = VertMesh(inputMesh); return MotionVectorVS(varyingsType, inputMesh, inputPass); } #else // _WRITE_TRANSPARENT_MOTION_VECTOR #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl" PackedVaryingsType Vert(AttributesMesh inputMesh) { VaryingsType varyingsType; varyingsType.vmesh = VertMesh(inputMesh); return PackVaryingsType(varyingsType); } #endif // _WRITE_TRANSPARENT_MOTION_VECTOR float ApplyChannelAlpha( float alpha) { return lerp(1.0, alpha, _ComposerMaskMode); } #ifdef UNITY_VIRTUAL_TEXTURING #define VT_BUFFER_TARGET SV_Target1 #define EXTRA_BUFFER_TARGET SV_Target2 #else #define EXTRA_BUFFER_TARGET SV_Target1 #endif void Frag(PackedVaryingsToPS packedInput, #ifdef OUTPUT_SPLIT_LIGHTING out float4 outColor : SV_Target0, // outSpecularLighting #ifdef UNITY_VIRTUAL_TEXTURING out float4 outVTFeedback : VT_BUFFER_TARGET, #endif out float4 outDiffuseLighting : EXTRA_BUFFER_TARGET, OUTPUT_SSSBUFFER(outSSSBuffer) #else out float4 outColor : SV_Target0 #ifdef UNITY_VIRTUAL_TEXTURING ,out float4 outVTFeedback : VT_BUFFER_TARGET #endif #ifdef _WRITE_TRANSPARENT_MOTION_VECTOR , out float4 outMotionVec : EXTRA_BUFFER_TARGET #endif // _WRITE_TRANSPARENT_MOTION_VECTOR #endif // OUTPUT_SPLIT_LIGHTING #ifdef _DEPTHOFFSET_ON , out float outputDepth : SV_Depth #endif ) { #ifdef _WRITE_TRANSPARENT_MOTION_VECTOR // Init outMotionVector here to solve compiler warning (potentially unitialized variable) // It is init to the value of forceNoMotion (with 2.0) outMotionVec = float4(2.0, 0.0, 0.0, 0.0); #endif UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(packedInput); FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh); #if defined(PLATFORM_SUPPORTS_PRIMITIVE_ID_IN_PIXEL_SHADER) && SHADER_STAGE_FRAGMENT #if (defined(VARYINGS_NEED_PRIMITIVEID) || (SHADERPASS == SHADERPASS_FULL_SCREEN_DEBUG)) input.primitiveID = packedInput.primitiveID; #endif #endif #if defined(VARYINGS_NEED_CULLFACE) && SHADER_STAGE_FRAGMENT input.isFrontFace = IS_FRONT_VFACE(packedInput.cullFace, true, false); #endif // We need to readapt the SS position as our screen space positions are for a low res buffer, but we try to access a full res buffer. input.positionSS.xy = _OffScreenRendering > 0 ? (input.positionSS.xy * _OffScreenDownsampleFactor) : input.positionSS.xy; uint2 tileIndex = uint2(input.positionSS.xy) / GetTileSize(); PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw, input.positionSS.z, input.positionSS.w, input.positionRWS.xyz, tileIndex); #ifdef VARYINGS_NEED_POSITION_WS float3 V = GetWorldSpaceNormalizeViewDir(input.positionRWS); #ifdef MATERIAL_TYPE_EYE // Must have view Dir to work float2 viewT = TransformObjectToTangent(V, input.tangentToWorld); float2 parallaxOffset = viewT; parallaxOffset.y = -parallaxOffset.y; input.texCoord0.xy = clamp(input.texCoord0.xy -_EyeParallaxAmount * parallaxOffset, 0, 1); #endif #else // Unused float3 V = float3(1.0, 1.0, 1.0); // Avoid the division by 0 #endif #ifdef _SURFACE_TYPE_TRANSPARENT uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT; #else uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_OPAQUE; #endif SurfaceData tempSurfaceData; BuiltinData builtinData; GetSurfaceAndBuiltinData(input, V, posInput, tempSurfaceData, builtinData); UTSSurfaceData surfaceData = GetUTSSurfaceData(input, V); UtsBSDFData bsdfData = ConvertUTSSurfaceDataToUTSBSDFData(surfaceData); #define UNITY_PROJ_COORD(a) a #define UNITY_SAMPLE_SCREEN_SHADOW(tex, uv) tex2Dproj( tex, UNITY_PROJ_COORD(uv) ).r float inverseClipping = 0.0; LightLoopContext context; context.shadowContext = InitShadowContext(); context.shadowValue = 1; context.sampleReflection = 0.0; #if UNITY_VERSION >= 202120 && UNITY_VERSION < 202320 context.splineVisibility = -1; #endif #ifdef APPLY_FOG_ON_SKY_REFLECTIONS context.positionWS = posInput.positionWS; #endif // With XR single-pass and camera-relative: offset position to do lighting computations from the combined center view (original camera matrix). // This is required because there is only one list of lights generated on the CPU. Shadows are also generated once and shared between the instanced views. ApplyCameraRelativeXR(posInput.positionWS); // Initialize the contactShadow and contactShadowFade fields InitContactShadow(posInput, context); LightLoopOutput lightLoopOutput; ZERO_INITIALIZE(LightLoopOutput, lightLoopOutput); UtsLightLoop(input, posInput, bsdfData, builtinData, V, featureFlags, lightLoopOutput); float3 finalColor = lightLoopOutput.diffuseLighting + lightLoopOutput.specularLighting; // #if _SURFACE_TYPE_TRANSPARENT // float alpha = channelAlpha; // outColor = EvaluateAtmosphericScattering(posInput, V, float4(finalColor, 1)); // #else // float alpha = lerp(1.0, channelAlpha, _AlphaCutoffEnable); // #endif // // alpha = lerp(alpha, step(_AlphaCutoff, alpha), _AlphaCutoffEnable); outColor = float4(finalColor, 1.0); #if _MATERIAL_TYPE_FRONTHAIR && ENABLE_UTS_HAIR_BLENDING float2 screenUV = posInput.positionNDC * _HairBlendingRTHandleScale.xy; float4 hairBlendingMap = LOAD_TEXTURE2D_X(_HairBlendingTex, screenUV); outColor.rgb = lerp(outColor.rgb, hairBlendingMap.rgb, hairBlendingMap.a * _HairBlendingFactor); #endif #if UTS_DEBUG_SHADOWMAP || UTS_DEBUG_SELFSHADOW outColor.rgb = 1; #ifdef UTS_DEBUG_SELFSHADOW outColor.rgb = min(finalColor, outColor.rgb); #endif #ifdef UTS_DEBUG_SHADOWMAP #ifdef UTS_DEBUG_SHADOWMAP_BINALIZATION outColor.rgb = min(context.shadowValue < 0.9f ? clamp(context.shadowValue - 0.2, 0.0, 0.9) : 1.0f, outColor.rgb); #else outColor.rgb = min(context.shadowValue, outColor.rgb); #endif #endif // ifdef UTS_DEBUG_SHADOWMAP #endif // defined(UTS_DEBUG_SHADOWMAP) || defined(UTS_DEBUG_SELFSHADOW) #ifdef _DEPTHOFFSET_ON outputDepth = posInput.deviceDepth; #endif #ifdef UNITY_VIRTUAL_TEXTURING outVTFeedback = builtinData.vtPackedFeedback; #endif }