您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

173 行
7.0 KiB

// Note: positionWS can be either in camera relative space or not
float3 GetVertexDisplacement(float3 positionRWS, float3 normalWS, float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3, float4 vertexColor)
{
// This call will work for both LayeredLit and Lit shader
LayerTexCoord layerTexCoord;
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
GetLayerTexCoord(texCoord0, texCoord1, texCoord2, texCoord3, positionRWS, normalWS, layerTexCoord);
// TODO: do this algorithm for lod fetching as lod not available in vertex/domain shader
// http://www.sebastiansylvan.com/post/the-problem-with-tessellation-in-directx-11/
float lod = 0.0;
return ComputePerVertexDisplacement(layerTexCoord, vertexColor, lod) * normalWS;
}
// Note: positionWS can be either in camera relative space or not
void ApplyVertexModification(AttributesMesh input, float3 normalWS, inout float3 positionRWS, float4 time)
{
#if defined(_VERTEX_DISPLACEMENT)
positionRWS += GetVertexDisplacement(positionRWS, normalWS,
#ifdef ATTRIBUTES_NEED_TEXCOORD0
input.uv0,
#else
float2(0.0, 0.0),
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD1
input.uv1,
#else
float2(0.0, 0.0),
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD2
input.uv2,
#else
float2(0.0, 0.0),
#endif
#ifdef ATTRIBUTES_NEED_TEXCOORD3
input.uv3,
#else
float2(0.0, 0.0),
#endif
#ifdef ATTRIBUTES_NEED_COLOR
input.color
#else
float4(0.0, 0.0, 0.0, 0.0)
#endif
);
#endif
#ifdef _VERTEX_WIND
// current wind implementation is in absolute world space
float3 rootWP = GetObjectAbsolutePositionWS();
float3 absolutePositionWS = GetAbsolutePositionWS(positionRWS);
ApplyWindDisplacement(absolutePositionWS, normalWS, rootWP, _Stiffness, _Drag, _ShiverDrag, _ShiverDirectionality, _InitialBend, input.color.a, time);
positionRWS = GetCameraRelativePositionWS(absolutePositionWS);
#endif
}
#ifdef TESSELLATION_ON
float4 GetTessellationFactors(float3 p0, float3 p1, float3 p2, float3 n0, float3 n1, float3 n2)
{
float maxDisplacement = GetMaxDisplacement();
// For tessellation we want to process tessellation factor always from the point of view of the camera (to be consistent and avoid Z-fight).
// For the culling part however we want to use the current view (shadow view).
// Thus the following code play with both.
float frustumEps = -maxDisplacement; // "-" Expected parameter for CullTriangleEdgesFrustum
// TODO: the only reason I test the near plane here is that I am not sure that the product of other tessellation factors
// (such as screen-space/distance-based) results in the tessellation factor of 1 for the geometry behind the near plane.
// If that is the case (and, IMHO, it should be), we shouldn't have to test the near plane here.
bool3 frustumCullEdgesMainView = CullTriangleEdgesFrustum(p0, p1, p2, frustumEps, _FrustumPlanes, 5); // Do not test the far plane
#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS)
bool frustumCullCurrView = all(frustumCullEdgesMainView);
#else
// 'unity_CameraWorldClipPlanes' are camera-relative rendering aware.
bool frustumCullCurrView = CullTriangleFrustum(p0, p1, p2, frustumEps, unity_CameraWorldClipPlanes, 4); // Do not test near/far planes
#endif
bool faceCull = false;
#ifndef _DOUBLESIDED_ON
if (_TessellationBackFaceCullEpsilon > -1.0) // Is back-face culling enabled ?
{
// Handle transform mirroring (like negative scaling)
// Note: We don't need to handle handness of view matrix here as the backface is perform in worldspace
// note2: When we have an orthogonal matrix (cascade shadow map), we need to use the direction of the light.
// Otherwise we use only p0 instead of the mean of P0, p1,p2 to save ALU as with tessellated geomerty it is rarely needed and user can still control _TessellationBackFaceCullEpsilon.
float winding = unity_WorldTransformParams.w;
faceCull = CullTriangleBackFaceView(p0, p1, p2, _TessellationBackFaceCullEpsilon, GetWorldSpaceNormalizeViewDir(p0), winding); // Use shadow view
}
#endif
if (frustumCullCurrView || faceCull)
{
// Settings factor to 0 will kill the triangle
return 0;
}
// For performance reasons, we choose not to tessellate outside of the main camera view
// (we perform this test both during the regular scene rendering and the shadow pass).
// For edges not visible from the main view, our goal is to set the tessellation factor to 1.
// In this case, we set the tessellation factor to 0 here.
// That way, all scaling of this tessellation factor will still result in 0.
// Before we call CalcTriTessFactorsFromEdgeTessFactors(), all factors are clamped by max(f, 1),
// which achieves the desired effect.
float3 edgeTessFactors = float3(frustumCullEdgesMainView.x ? 0 : 1, frustumCullEdgesMainView.y ? 0 : 1, frustumCullEdgesMainView.z ? 0 : 1);
// Adaptive screen space tessellation
if (_TessellationFactorTriangleSize > 0.0)
{
// return a value between 0 and 1
// Warning: '_ViewProjMatrix' is not the same as UNITY_MATRIX_VP for shadow views!
edgeTessFactors *= GetScreenSpaceTessFactor( p0, p1, p2, _ViewProjMatrix, _ScreenSize, _TessellationFactorTriangleSize); // Use primary camera view
}
// Distance based tessellation
if (_TessellationFactorMaxDistance > 0.0)
{
float3 distFactor = GetDistanceBasedTessFactor(p0, p1, p2, GetPrimaryCameraPosition(), _TessellationFactorMinDistance, _TessellationFactorMaxDistance); // Use primary camera view
// We square the disance factor as it allow a better percptual descrease of vertex density.
edgeTessFactors *= distFactor * distFactor;
}
edgeTessFactors *= _TessellationFactor;
// TessFactor below 1.0 have no effect. At 0 it kill the triangle, so clamp it to 1.0
edgeTessFactors = max(edgeTessFactors, float3(1.0, 1.0, 1.0));
return CalcTriTessFactorsFromEdgeTessFactors(edgeTessFactors);
}
// tessellationFactors
// x - 1->2 edge
// y - 2->0 edge
// z - 0->1 edge
// w - inside tessellation factor
void ApplyTessellationModification(VaryingsMeshToDS input, float3 normalWS, inout float3 positionRWS)
{
#if defined(_TESSELLATION_DISPLACEMENT)
positionRWS += GetVertexDisplacement(positionRWS, normalWS,
#ifdef VARYINGS_DS_NEED_TEXCOORD0
input.texCoord0,
#else
float2(0.0, 0.0),
#endif
#ifdef VARYINGS_DS_NEED_TEXCOORD1
input.texCoord1,
#else
float2(0.0, 0.0),
#endif
#ifdef VARYINGS_DS_NEED_TEXCOORD2
input.texCoord2,
#else
float2(0.0, 0.0),
#endif
#ifdef VARYINGS_DS_NEED_TEXCOORD3
input.texCoord3,
#else
float2(0.0, 0.0),
#endif
#ifdef VARYINGS_DS_NEED_COLOR
input.color
#else
float4(0.0, 0.0, 0.0, 0.0)
#endif
);
#endif // _TESSELLATION_DISPLACEMENT
}
#endif // #ifdef TESSELLATION_ON