#if SHADERPASS != SHADERPASS_VELOCITY #error SHADERPASS_is_not_correctly_define #endif // Available semantic start from TEXCOORD4 struct AttributesPass { float3 previousPositionOS : NORMAL; // Contain previous transform position (in case of skinning for example) // TODO: Caution - For now the tesselation doesn't displace along the normal with Velocity shader as the previous previous position // conflict with the normal in the semantic. This need to be fix! }; struct VaryingsPassToPS { // Note: Z component is not use currently // This is the clip space position. Warning, do not confuse with the value of positionCS in PackedVarying which is SV_POSITION and store in positionSS float4 positionCS; float4 previousPositionCS; }; // Available interpolator start from TEXCOORD8 struct PackedVaryingsPassToPS { // Note: Z component is not use float3 interpolators0 : TEXCOORD8; float3 interpolators1 : TEXCOORD9; }; PackedVaryingsPassToPS PackVaryingsPassToPS(VaryingsPassToPS input) { PackedVaryingsPassToPS output; output.interpolators0 = float3(input.positionCS.xyw); output.interpolators1 = float3(input.previousPositionCS.xyw); return output; } VaryingsPassToPS UnpackVaryingsPassToPS(PackedVaryingsPassToPS input) { VaryingsPassToPS output; output.positionCS = float4(input.interpolators0.xy, 0.0, input.interpolators0.z); output.previousPositionCS = float4(input.interpolators1.xy, 0.0, input.interpolators1.z); return output; } #ifdef TESSELLATION_ON // Available interpolator start from TEXCOORD4 // Same as ToPS here #define VaryingsPassToDS VaryingsPassToPS #define PackedVaryingsPassToDS PackedVaryingsPassToPS #define PackVaryingsPassToDS PackVaryingsPassToPS #define UnpackVaryingsPassToDS UnpackVaryingsPassToPS VaryingsPassToDS InterpolateWithBaryCoordsPassToDS(VaryingsPassToDS input0, VaryingsPassToDS input1, VaryingsPassToDS input2, float3 baryCoords) { VaryingsPassToDS ouput; TESSELLATION_INTERPOLATE_BARY(positionCS, baryCoords); TESSELLATION_INTERPOLATE_BARY(previousPositionCS, baryCoords); return ouput; } #endif // TESSELLATION_ON #ifdef TESSELLATION_ON #define VaryingsPassType VaryingsPassToDS #else #define VaryingsPassType VaryingsPassToPS #endif // We will use custom attributes for this pass #define VARYINGS_NEED_PASS #include "VertMesh.hlsl" PackedVaryingsType Vert(AttributesMesh inputMesh, AttributesPass inputPass) { VaryingsType varyingsType; varyingsType.vmesh = VertMesh(inputMesh); // It is not possible to correctly generate the motion vector for tesselated geometry as tessellation parameters can change // from one frame to another (adaptative, lod) + in Unity we only receive information for one non tesselated vertex. // So motion vetor will be based on interpolate previous position at vertex level instead. varyingsType.vpass.positionCS = mul(_NonJitteredViewProjMatrix, mul(unity_ObjectToWorld, float4(inputMesh.positionOS, 1.0))); varyingsType.vpass.previousPositionCS = mul(_PrevViewProjMatrix, mul(unity_MatrixPreviousM, unity_MotionVectorsParams.x ? float4(inputPass.previousPositionOS, 1.0) : float4(inputMesh.positionOS, 1.0))); return PackVaryingsType(varyingsType); } #ifdef TESSELLATION_ON PackedVaryingsToPS VertTesselation(VaryingsToDS input) { VaryingsToPS output; output.vmesh = VertMeshTesselation(input.vmesh); output.vpass.positionCS = input.vpass.positionCS; output.vpass.previousPositionCS = input.vpass.previousPositionCS; return PackVaryingsToPS(output); } #include "TessellationShare.hlsl" #endif // TESSELLATION_ON float4 Frag(PackedVaryingsToPS packedInput) : SV_Target { FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh); // input.positionSS is SV_Position PositionInputs posInput = GetPositionInput(input.positionSS.xy, _ScreenSize.zw); UpdatePositionInput(input.positionSS.z, input.positionSS.w, input.positionWS, posInput); float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS); // Perform alpha testing + get velocity SurfaceData surfaceData; BuiltinData builtinData; GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData); VaryingsPassToPS inputPass = UnpackVaryingsPassToPS(packedInput.vpass); #ifdef _DEPTHOFFSET_ON inputPass.positionCS.w += builtinData.depthOffset; inputPass.previousPositionCS.w += builtinData.depthOffset; #endif // TODO: How to allow overriden velocity vector from GetSurfaceAndBuiltinData ? float2 velocity = CalculateVelocity(inputPass.positionCS, inputPass.previousPositionCS); float4 outBuffer; EncodeVelocity(velocity, outBuffer); return outBuffer; }