in d3d/archive/images/d3d11/tessellator.cpp [2179:2412]
void CHLSLTessellator::QuadHLSLProcessTessFactors( float tessFactor_Ueq0, float tessFactor_Veq0, float tessFactor_Ueq1, float tessFactor_Veq1,
float insideTessFactorScaleU, float insideTessFactorScaleV )
{
if( !(tessFactor_Ueq0 > 0) ||// NaN will pass
!(tessFactor_Veq0 > 0) ||
!(tessFactor_Ueq1 > 0) ||
!(tessFactor_Veq1 > 0) )
{
m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0;
m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0;
m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1;
m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1;
m_LastUnRoundedComputedTessFactors[4] = 0;
m_LastUnRoundedComputedTessFactors[5] = 0;
m_LastComputedTessFactors[0] =
m_LastComputedTessFactors[1] =
m_LastComputedTessFactors[2] =
m_LastComputedTessFactors[3] =
m_LastComputedTessFactors[4] =
m_LastComputedTessFactors[5] = 0;
return;
}
CleanupFloatTessFactor(tessFactor_Ueq0);// clamp to [1.0f..INF], NaN->1.0f
CleanupFloatTessFactor(tessFactor_Veq0);
CleanupFloatTessFactor(tessFactor_Ueq1);
CleanupFloatTessFactor(tessFactor_Veq1);
// Save off tessFactors so they can be returned to app
m_LastUnRoundedComputedTessFactors[0] = tessFactor_Ueq0;
m_LastUnRoundedComputedTessFactors[1] = tessFactor_Veq0;
m_LastUnRoundedComputedTessFactors[2] = tessFactor_Ueq1;
m_LastUnRoundedComputedTessFactors[3] = tessFactor_Veq1;
// Process outside tessFactors
float outsideTessFactor[QUAD_EDGES] = {tessFactor_Ueq0, tessFactor_Veq0, tessFactor_Ueq1, tessFactor_Veq1};
int edge, axis;
TESSELLATOR_PARITY insideTessFactorParity[QUAD_AXES], outsideTessFactorParity[QUAD_EDGES];
if( Pow2Partitioning() || IntegerPartitioning() )
{
for( edge = 0; edge < QUAD_EDGES; edge++ )
{
RoundUpTessFactor(outsideTessFactor[edge]);
ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode
int edgeEven = isEven(outsideTessFactor[edge]);
outsideTessFactorParity[edge] = edgeEven ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
}
else
{
SetTessellationParity(m_originalParity); // ClampTessFactor needs it
for( edge = 0; edge < QUAD_EDGES; edge++ )
{
ClampTessFactor(outsideTessFactor[edge]); // clamp unbounded user input based on tessellation mode
outsideTessFactorParity[edge] = m_originalParity;
}
}
// Compute inside TessFactors
float insideTessFactor[QUAD_AXES];
if( m_quadInsideTessFactorReductionAxis == D3D11_TESSELLATOR_QUAD_REDUCTION_1_AXIS )
{
switch( m_insideTessFactorReduction )
{
case D3D11_TESSELLATOR_REDUCTION_MIN:
insideTessFactor[U] = fmin(fmin(tessFactor_Veq0,tessFactor_Veq1),fmin(tessFactor_Ueq0,tessFactor_Ueq1));
break;
case D3D11_TESSELLATOR_REDUCTION_MAX:
insideTessFactor[U] = fmax(fmax(tessFactor_Veq0,tessFactor_Veq1),fmax(tessFactor_Ueq0,tessFactor_Ueq1));
break;
case D3D11_TESSELLATOR_REDUCTION_AVERAGE:
insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4;
break;
}
// Scale inside tessFactor based on user scale factor.
ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0
insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU;
// Compute inside parity
if( Pow2Partitioning() || IntegerPartitioning() )
{
ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
RoundUpTessFactor(insideTessFactor[U]);
insideTessFactorParity[U] =
insideTessFactorParity[V] =
(isEven(insideTessFactor[U]) || (FLOAT_ONE == insideTessFactor[U]) )
? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
else
{
ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
// no parity changes for fractional tessellation - just use what the user requested
insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity;
}
// To prevent snapping on edges, the "picture frame" comes
// in using avg or max (and ignore inside TessFactor scaling) until it is at least 3.
if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) &&
(insideTessFactor[U] < FLOAT_THREE) )
{
if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
{
insideTessFactor[U] = fmin(FLOAT_THREE,fmax(fmax(tessFactor_Veq0,tessFactor_Veq1),fmax(tessFactor_Ueq0,tessFactor_Ueq1)));
}
else
{
insideTessFactor[U] = fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1 + tessFactor_Ueq0 + tessFactor_Ueq1) / 4);
}
ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4] = m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
if( IntegerPartitioning())
{
RoundUpTessFactor(insideTessFactor[U]);
insideTessFactorParity[U] =
insideTessFactorParity[V] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
}
insideTessFactor[V] = insideTessFactor[U];
}
else
{
switch( m_insideTessFactorReduction )
{
case D3D11_TESSELLATOR_REDUCTION_MIN:
insideTessFactor[U] = fmin(tessFactor_Veq0,tessFactor_Veq1);
insideTessFactor[V] = fmin(tessFactor_Ueq0,tessFactor_Ueq1);
break;
case D3D11_TESSELLATOR_REDUCTION_MAX:
insideTessFactor[U] = fmax(tessFactor_Veq0,tessFactor_Veq1);
insideTessFactor[V] = fmax(tessFactor_Ueq0,tessFactor_Ueq1);
break;
case D3D11_TESSELLATOR_REDUCTION_AVERAGE:
insideTessFactor[U] = (tessFactor_Veq0 + tessFactor_Veq1) / 2;
insideTessFactor[V] = (tessFactor_Ueq0 + tessFactor_Ueq1) / 2;
break;
}
// Scale inside tessFactors based on user scale factor.
ClampFloatTessFactorScale(insideTessFactorScaleU); // clamp scale value to [0..1], NaN->0
ClampFloatTessFactorScale(insideTessFactorScaleV);
insideTessFactor[U] = insideTessFactor[U]*insideTessFactorScaleU;
insideTessFactor[V] = insideTessFactor[V]*insideTessFactorScaleV;
// Compute inside parity
if( Pow2Partitioning() || IntegerPartitioning() )
{
for( axis = 0; axis < QUAD_AXES; axis++ )
{
ClampTessFactor(insideTessFactor[axis]); // clamp reduction + scale result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app
RoundUpTessFactor(insideTessFactor[axis]);
insideTessFactorParity[axis] =
(isEven(insideTessFactor[axis]) || (FLOAT_ONE == insideTessFactor[axis]) )
? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
}
else
{
ClampTessFactor(insideTessFactor[U]); // clamp reduction + scale result that is based on unbounded user input
ClampTessFactor(insideTessFactor[V]); // clamp reduction + scale result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app
// no parity changes for fractional tessellation - just use what the user requested
insideTessFactorParity[U] = insideTessFactorParity[V] = m_originalParity;
}
// To prevent snapping on edges, the "picture frame" comes
// in using avg or max (and ignore inside TessFactor scaling) until it is at least 3.
if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[U]) &&
(insideTessFactor[U] < FLOAT_THREE) )
{
if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
{
insideTessFactor[U] = fmin(FLOAT_THREE,fmax(tessFactor_Veq0,tessFactor_Veq1));
}
else
{
insideTessFactor[U] = fmin(FLOAT_THREE,(tessFactor_Veq0 + tessFactor_Veq1) / 2);
}
ClampTessFactor(insideTessFactor[U]); // clamp reduction result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[4] = insideTessFactor[U]; // Save off TessFactors so they can be returned to app
if( IntegerPartitioning())
{
RoundUpTessFactor(insideTessFactor[U]);
insideTessFactorParity[U] = isEven(insideTessFactor[U]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
}
if( (TESSELLATOR_PARITY_ODD == insideTessFactorParity[V]) &&
(insideTessFactor[V] < FLOAT_THREE) )
{
if(D3D11_TESSELLATOR_REDUCTION_MAX == m_insideTessFactorReduction)
{
insideTessFactor[V] = fmin(FLOAT_THREE,fmax(tessFactor_Ueq0,tessFactor_Ueq1));
}
else
{
insideTessFactor[V] = fmin(FLOAT_THREE,(tessFactor_Ueq0 + tessFactor_Ueq1) / 2);
}
ClampTessFactor(insideTessFactor[V]);// clamp reduction result that is based on unbounded user input
m_LastUnRoundedComputedTessFactors[5] = insideTessFactor[V]; // Save off TessFactors so they can be returned to app
if( IntegerPartitioning())
{
RoundUpTessFactor(insideTessFactor[V]);
insideTessFactorParity[V] = isEven(insideTessFactor[V]) ? TESSELLATOR_PARITY_EVEN : TESSELLATOR_PARITY_ODD;
}
}
for( axis = 0; axis < QUAD_AXES; axis++ )
{
if( TESSELLATOR_PARITY_ODD == insideTessFactorParity[axis] )
{
// Ensure the first ring ("picture frame") interpolates in on all sides
// as much as the side with the minimum TessFactor. Prevents snapping to edge.
if( (insideTessFactor[axis] < FLOAT_THREE) && (insideTessFactor[axis] < insideTessFactor[(axis+1)&0x1]))
{
insideTessFactor[axis] = fmin(insideTessFactor[(axis+1)&0x1],FLOAT_THREE);
m_LastUnRoundedComputedTessFactors[4+axis] = insideTessFactor[axis]; // Save off TessFactors so they can be returned to app
}
}
}
}
// Save off TessFactors so they can be returned to app
m_LastComputedTessFactors[0] = outsideTessFactor[Ueq0];
m_LastComputedTessFactors[1] = outsideTessFactor[Veq0];
m_LastComputedTessFactors[2] = outsideTessFactor[Ueq1];
m_LastComputedTessFactors[3] = outsideTessFactor[Veq1];
m_LastComputedTessFactors[4] = insideTessFactor[U];
m_LastComputedTessFactors[5] = insideTessFactor[V];
}