Updated HLSL shaders for unified patch drawing

This commit is contained in:
David G. Yu 2015-04-18 14:00:23 -07:00
parent 963d952c7b
commit 9f1da077e8
4 changed files with 265 additions and 813 deletions

View File

@ -89,13 +89,16 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig(
case Far::PatchDescriptor::CORNER:
sconfig->commonShader.AddDefine("OSD_PATCH_BSPLINE");
sconfig->commonShader.AddDefine("OSD_PATCH_ENABLE_SINGLE_CREASE");
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;

View File

@ -22,12 +22,6 @@
// language governing permissions and limitations under the Apache License.
//
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH
#define HS_DOMAIN "tri"
#else
#define HS_DOMAIN "quad"
#endif
#if defined OSD_FRACTIONAL_ODD_SPACING
#define HS_PARTITION "fractional_odd"
#elif defined OSD_FRACTIONAL_EVEN_SPACING
@ -67,13 +61,34 @@ static float4x4 Mi = {
0.f, 0.f, 1.f, 0.f
};
// Boundary / Corner
static float4x3 B = {
1.f, 0.f, 0.f,
4.f/6.f, 2.f/6.f, 0.f,
2.f/6.f, 4.f/6.f, 0.f,
1.f/6.f, 4.f/6.f, 1.f/6.f
};
void
reflectBoundaryEdges(inout float3 cpt[24], int patchParam)
{
if (((patchParam >> 4) & 1) != 0) {
cpt[0] = 2*cpt[4] - cpt[8];
cpt[1] = 2*cpt[5] - cpt[9];
cpt[2] = 2*cpt[6] - cpt[10];
cpt[3] = 2*cpt[7] - cpt[11];
}
if (((patchParam >> 4) & 2) != 0) {
cpt[3] = 2*cpt[2] - cpt[1];
cpt[7] = 2*cpt[6] - cpt[5];
cpt[11] = 2*cpt[10] - cpt[9];
cpt[15] = 2*cpt[14] - cpt[13];
}
if (((patchParam >> 4) & 4) != 0) {
cpt[12] = 2*cpt[8] - cpt[4];
cpt[13] = 2*cpt[9] - cpt[5];
cpt[14] = 2*cpt[10] - cpt[6];
cpt[15] = 2*cpt[11] - cpt[7];
}
if (((patchParam >> 4) & 8) != 0) {
cpt[0] = 2*cpt[1] - cpt[2];
cpt[4] = 2*cpt[5] - cpt[6];
cpt[8] = 2*cpt[9] - cpt[10];
cpt[12] = 2*cpt[13] - cpt[14];
}
}
// compute single-crease patch matrix
float4x4
@ -96,62 +111,47 @@ ComputeMatrixSimplified(float sharpness)
}
#ifdef OSD_PATCH_TRANSITION
HS_CONSTANT_TRANSITION_FUNC_OUT
#else
HS_CONSTANT_FUNC_OUT
#endif
HS_CONSTANT_FUNC_OUT
HSConstFunc(
InputPatch<HullVertex, OSD_PATCH_INPUT_SIZE> patch,
uint primitiveID : SV_PrimitiveID)
{
#ifdef OSD_PATCH_TRANSITION
HS_CONSTANT_TRANSITION_FUNC_OUT output;
#else
HS_CONSTANT_FUNC_OUT output;
#endif
int patchParam = GetPatchParam(primitiveID);
int patchLevel = GetPatchLevel(primitiveID);
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH
OSD_PATCH_CULL_TRIANGLE(OSD_PATCH_INPUT_SIZE);
#else
float3 position[24];
for (int p=0; p<16; ++p) {
position[p] = patch[p].position.xyz;
}
reflectBoundaryEdges(position, patchParam);
OSD_PATCH_CULL(OSD_PATCH_INPUT_SIZE);
#endif
#ifdef OSD_PATCH_TRANSITION
float3 cp[OSD_PATCH_INPUT_SIZE];
for(int k = 0; k < OSD_PATCH_INPUT_SIZE; ++k) cp[k] = patch[k].position.xyz;
SetTransitionTessLevels(output, cp, patchLevel, primitiveID);
#else
#if defined OSD_PATCH_BOUNDARY
const int p[4] = { 1, 2, 5, 6 };
#elif defined OSD_PATCH_CORNER
const int p[4] = { 1, 2, 4, 5 };
#else
const int p[4] = { 5, 6, 9, 10 };
#endif
float4 outerLevel = float4(0,0,0,0);
float4 innerLevel = float4(0,0,0,0);
float4 tessOuterLo = float4(0,0,0,0);
float4 tessOuterHi = float4(0,0,0,0);
GetTransitionTessLevels(position, patchParam, patchLevel,
outerLevel, innerLevel,
tessOuterLo, tessOuterHi);
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION
output.tessLevelOuter[0] = TessAdaptive(patch[p[0]].position.xyz, patch[p[2]].position.xyz);
output.tessLevelOuter[1] = TessAdaptive(patch[p[0]].position.xyz, patch[p[1]].position.xyz);
output.tessLevelOuter[2] = TessAdaptive(patch[p[1]].position.xyz, patch[p[3]].position.xyz);
output.tessLevelOuter[3] = TessAdaptive(patch[p[2]].position.xyz, patch[p[3]].position.xyz);
output.tessLevelInner[0] = max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] = max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#else
output.tessLevelInner[0] = GetTessLevel(patchLevel);
output.tessLevelInner[1] = GetTessLevel(patchLevel);
output.tessLevelOuter[0] = GetTessLevel(patchLevel);
output.tessLevelOuter[1] = GetTessLevel(patchLevel);
output.tessLevelOuter[2] = GetTessLevel(patchLevel);
output.tessLevelOuter[3] = GetTessLevel(patchLevel);
#endif
#endif
output.tessLevelOuter[0] = outerLevel[0];
output.tessLevelOuter[1] = outerLevel[1];
output.tessLevelOuter[2] = outerLevel[2];
output.tessLevelOuter[3] = outerLevel[3];
output.tessLevelInner[0] = innerLevel[0];
output.tessLevelInner[1] = innerLevel[0];
output.tessOuterLo = tessOuterLo;
output.tessOuterHi = tessOuterHi;
return output;
}
[domain(HS_DOMAIN)]
[domain("quad")]
[partitioning(HS_PARTITION)]
[outputtopology("triangle_cw")]
[outputcontrolpoints(16)]
@ -164,76 +164,61 @@ HullVertex hs_main_patches(
int i = ID%4;
int j = ID/4;
#if defined OSD_PATCH_BOUNDARY
float3 H[3];
for (int l=0; l<3; ++l) {
H[l] = float3(0,0,0);
for (int k=0; k<4; ++k) {
H[l] += Q[i][k] * patch[l*4 + k].position.xyz;
}
float3 position[24];
for (int p=0; p<16; ++p) {
position[p] = patch[p].position.xyz;
}
float3 pos = float3(0,0,0);
for (int k=0; k<3; ++k) {
pos += B[j][k]*H[k];
}
int patchParam = GetPatchParam(primitiveID);
#elif defined OSD_PATCH_CORNER
float3 H[3];
for (int l=0; l<3; ++l) {
H[l] = float3(0,0,0);
for (int k=0; k<3; ++k) {
H[l] += B[3-i][2-k] * patch[l*3 + k].position.xyz;
}
}
reflectBoundaryEdges(position, patchParam);
float3 pos = float3(0,0,0);
for (int k=0; k<3; ++k) {
pos += B[j][k]*H[k];
}
#else // not OSD_PATCH_BOUNDARY, not OSD_PATCH_CORNER
float3 H[4];
for (int l=0; l<4; ++l) {
H[l] = float3(0,0,0);
for(int k=0; k<4; ++k) {
H[l] += Q[i][k] * patch[l*4 + k].position.xyz;
H[l] += Q[i][k] * position[l*4 + k];
}
}
#if defined OSD_PATCH_SINGLE_CREASE
HullVertex output;
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness = GetSharpness(primitiveID);
float Sf = floor(sharpness);
float Sc = ceil(sharpness);
float Sr = frac(sharpness);
float4x4 Mf = ComputeMatrixSimplified(Sf);
float4x4 Mc = ComputeMatrixSimplified(Sc);
float4x4 Mj = (1-Sr) * Mf + Sr * Mi;
float4x4 Ms = (1-Sr) * Mf + Sr * Mc;
if (sharpness > 0) {
float Sf = floor(sharpness);
float Sc = ceil(sharpness);
float Sr = frac(sharpness);
float4x4 Mf = ComputeMatrixSimplified(Sf);
float4x4 Mc = ComputeMatrixSimplified(Sc);
float4x4 Mj = (1-Sr) * Mf + Sr * Mi;
float4x4 Ms = (1-Sr) * Mf + Sr * Mc;
float3 pos = float3(0,0,0);
float3 P1 = float3(0,0,0);
float3 P2 = float3(0,0,0);
for (int k=0; k<4; ++k) {
pos += Mi[j][k]*H[k]; // 0 to 1-2^(-Sf)
P1 += Mj[j][k]*H[k]; // 1-2^(-Sf) to 1-2^(-Sc)
P2 += Ms[j][k]*H[k]; // 1-2^(-Sc) to 1
float3 pos = float3(0,0,0);
float3 P1 = float3(0,0,0);
float3 P2 = float3(0,0,0);
for (int k=0; k<4; ++k) {
pos += Mi[j][k]*H[k]; // 0 to 1-2^(-Sf)
P1 += Mj[j][k]*H[k]; // 1-2^(-Sf) to 1-2^(-Sc)
P2 += Ms[j][k]*H[k]; // 1-2^(-Sc) to 1
}
output.position = float4(pos, 1.0);
output.P1 = float4(P1, 1.0);
output.P2 = float4(P2, 1.0);
output.sharpness = sharpness;
} else {
float3 pos = float3(0,0,0);
for (int k=0; k<4; ++k){
pos += Q[j][k]*H[k];
}
output.position = float4(pos, 1.0);
output.sharpness = 0;
}
#else
float3 pos = float3(0,0,0);
for (int k=0; k<4; ++k){
pos += Q[j][k]*H[k];
}
#endif
#endif
HullVertex output;
output.position = float4(pos, 1.0);
#if defined OSD_PATCH_SINGLE_CREASE
output.P1 = float4(P1, 1.0);
output.P2 = float4(P2, 1.0);
output.sharpness = sharpness;
#endif
int patchLevel = GetPatchLevel(primitiveID);
@ -252,26 +237,14 @@ HullVertex hs_main_patches(
// Patches.DomainBSpline
//----------------------------------------------------------
[domain(HS_DOMAIN)]
[domain("quad")]
void ds_main_patches(
#ifdef OSD_PATCH_TRANSITION
in HS_CONSTANT_TRANSITION_FUNC_OUT input,
#else
in HS_CONSTANT_FUNC_OUT input,
#endif
in OutputPatch<HullVertex, 16> patch,
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH
in float3 domainCoord : SV_DomainLocation,
#else
in float2 domainCoord : SV_DomainLocation,
#endif
out OutputVertex output )
{
#ifdef OSD_PATCH_TRANSITION
float2 UV = GetTransitionSubpatchUV(domainCoord);
#else
float2 UV = domainCoord;
#endif
float2 UV = GetTransitionParameterization(input, domainCoord);
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
float B[4], D[4], C[4];
@ -286,52 +259,60 @@ void ds_main_patches(
Univar4x4(UV.x, B, D);
#endif
#if defined OSD_PATCH_SINGLE_CREASE
// ----------------------------------------------------------------
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
// sharpness
float sharpness = patch[0].sharpness;
float s0 = 1.0 - pow(2.0f, -floor(sharpness));
float s1 = 1.0 - pow(2.0f, -ceil(sharpness));
#endif
if (sharpness != 0) {
float s0 = 1.0 - pow(2.0f, -floor(sharpness));
float s1 = 1.0 - pow(2.0f, -ceil(sharpness));
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
#if defined OSD_PATCH_SINGLE_CREASE
#if OSD_TRANSITION_ROTATE == 1
int k = 4*(3-j) + i;
float s = 1-UV.x;
#elif OSD_TRANSITION_ROTATE == 2
int k = 4*(3-i) + (3-j);
float s = 1-UV.y;
#elif OSD_TRANSITION_ROTATE == 3
int k = 4*j + (3-i);
float s = UV.x;
#else // ROTATE=0 or non-transition
int k = 4*i + j;
float s = UV.y;
#endif
float3 A = (s < s0) ?
patch[k].position.xyz :
((s < s1) ?
patch[k].P1.xyz :
patch[k].P2.xyz);
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
int k = 4*i + j;
float s = UV.y;
#else // !SINGLE_CREASE
#if OSD_TRANSITION_ROTATE == 1
float3 A = patch[4*(3-j) + i].position.xyz;
#elif OSD_TRANSITION_ROTATE == 2
float3 A = patch[4*(3-i) + (3-j)].position.xyz;
#elif OSD_TRANSITION_ROTATE == 3
float3 A = patch[4*j + (3-i)].position.xyz;
#else // OSD_TRANSITION_ROTATE == 0, or non-transition patch
float3 A = patch[4*i + j].position.xyz;
#endif
#endif
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
float3 A = (s < s0) ?
patch[k].position.xyz :
((s < s1) ?
patch[k].P1.xyz :
patch[k].P2.xyz);
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
CUCP[i] += A * C[j];
CUCP[i] += A * C[j];
#endif
}
}
output.sharpness = sharpness;
} else {
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
float3 A = patch[4*i + j].position.xyz;
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
CUCP[i] += A * C[j];
#endif
}
}
output.sharpness = 0;
}
#else
// ----------------------------------------------------------------
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
float3 A = patch[4*i + j].position.xyz;
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
CUCP[i] += A * C[j];
#endif
}
}
#endif
// ----------------------------------------------------------------
float3 WorldPos = float3(0,0,0);
float3 Tangent = float3(0,0,0);
@ -378,7 +359,10 @@ void ds_main_patches(
Nu = Nu/length(n) - n * (dot(Nu,n)/pow(dot(n,n), 1.5));
Nv = Nv/length(n) - n * (dot(Nv,n)/pow(dot(n,n), 1.5));
OSD_COMPUTE_PTEX_COMPATIBLE_DERIVATIVES(OSD_TRANSITION_ROTATE);
output.tangent = Tangent;
output.bitangent = BiTangent;
output.Nu = Nu;
output.Nv = Nv;
#else
Univar4x4(UV.y, B, D);
@ -393,7 +377,8 @@ void ds_main_patches(
float3 normal = normalize(cross(Tangent, BiTangent));
OSD_COMPUTE_PTEX_COMPATIBLE_TANGENT(OSD_TRANSITION_ROTATE);
output.tangent = Tangent;
output.bitangent = BiTangent;
#endif
output.position = float4(WorldPos, 1.0f);
@ -401,20 +386,13 @@ void ds_main_patches(
output.patchCoord = patch[0].patchCoord;
#if OSD_TRANSITION_ROTATE == 1
output.patchCoord.xy = float2(UV.y, 1.0-UV.x);
#elif OSD_TRANSITION_ROTATE == 2
output.patchCoord.xy = float2(1.0-UV.x, 1.0-UV.y);
#elif OSD_TRANSITION_ROTATE == 3
output.patchCoord.xy = float2(1.0-UV.y, UV.x);
#else // OSD_TRANNSITION_ROTATE == 0, or non-transition patch
output.patchCoord.xy = float2(UV.x, UV.y);
#endif
OSD_COMPUTE_PTEX_COORD_DOMAIN_SHADER;
OSD_DISPLACEMENT_CALLBACK;
output.edgeDistance = 0;
output.positionOut = mul(OsdProjectionMatrix(),
float4(output.position.xyz, 1.0f));
output.edgeDistance = 0;
}

View File

@ -26,17 +26,11 @@
// Patches.Common
//----------------------------------------------------------
#ifndef OSD_TRANSITION_ROTATE
#define OSD_TRANSITION_ROTATE 0
#endif
// XXXdyu-patch-drawing support for fractional spacing
#undef OSD_FRACTIONAL_ODD_SPACING
#undef OSD_FRACTIONAL_EVEN_SPACING
#if defined OSD_PATCH_BOUNDARY
#define OSD_PATCH_INPUT_SIZE 12
#elif defined OSD_PATCH_CORNER
#define OSD_PATCH_INPUT_SIZE 9
#else
#define OSD_PATCH_INPUT_SIZE 16
#endif
#define OSD_PATCH_INPUT_SIZE 16
#define M_PI 3.14159265359f
@ -50,7 +44,7 @@ struct HullVertex {
float4 patchCoord : PATCHCOORD; // u, v, level, faceID
int4 ptexInfo : PTEXINFO; // u offset, v offset, 2^ptexlevel, rotation
int3 clipFlag : CLIPFLAG;
#if defined OSD_PATCH_SINGLE_CREASE
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
float4 P1 : POSITION1;
float4 P2 : POSITION2;
float sharpness : BLENDWEIGHT0;
@ -69,6 +63,9 @@ struct OutputVertex {
float3 Nu : TANGENT2;
float3 Nv : TANGENT3;
#endif
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
float sharpness : BLENDWEIGHT0;
#endif
};
struct GregHullVertex {
@ -98,6 +95,8 @@ struct GregDomainVertex {
struct HS_CONSTANT_FUNC_OUT {
float tessLevelInner[2] : SV_InsideTessFactor;
float tessLevelOuter[4] : SV_TessFactor;
float4 tessOuterLo : TRANSITIONLO;
float4 tessOuterHi : TRANSITIONHI;
};
// osd shaders need following functions defined
@ -141,12 +140,15 @@ float TessAdaptive(float3 p0, float3 p1)
#define OSD_DISPLACEMENT_CALLBACK
#endif
#if defined OSD_PATCH_SINGLE_CREASE
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
Buffer<uint3> OsdPatchParamBuffer : register( t3 );
#else
Buffer<uint2> OsdPatchParamBuffer : register( t3 );
#endif
#define GetPatchParam(primitiveID) \
(OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].y)
#define GetPatchLevel(primitiveID) \
(OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].y & 0xf)
@ -157,12 +159,11 @@ float TessAdaptive(float3 p0, float3 p1)
{ \
int2 ptexIndex = OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].xy; \
int faceID = ptexIndex.x; \
int lv = 1 << ((ptexIndex.y & 0xf) - ((ptexIndex.y >> 4) & 1)); \
int u = (ptexIndex.y >> 17) & 0x3ff; \
int v = (ptexIndex.y >> 7) & 0x3ff; \
int rotation = (ptexIndex.y >> 5) & 0x3; \
int lv = 1 << ((ptexIndex.y & 0x7) - ((ptexIndex.y >> 3) & 1)); \
int u = (ptexIndex.y >> 22) & 0x3ff; \
int v = (ptexIndex.y >> 12) & 0x3ff; \
output.patchCoord.w = faceID+0.5; \
output.ptexInfo = int4(u, v, lv, rotation); \
output.ptexInfo = int4(u, v, lv, 0); \
}
#define OSD_COMPUTE_PTEX_COORD_DOMAIN_SHADER \
@ -171,57 +172,9 @@ float TessAdaptive(float3 p0, float3 p1)
int2 p = patch[0].ptexInfo.xy; \
int lv = patch[0].ptexInfo.z; \
int rot = patch[0].ptexInfo.w; \
uv.xy = float(rot==0)*uv.xy \
+ float(rot==1)*float2(1.0-uv.y, uv.x) \
+ float(rot==2)*float2(1.0-uv.x, 1.0-uv.y) \
+ float(rot==3)*float2(uv.y, 1.0-uv.x); \
output.patchCoord.xy = (uv * float2(1.0,1.0)/lv) + float2(p.x, p.y)/lv; \
}
#define OSD_COMPUTE_PTEX_COMPATIBLE_TANGENT(ROTATE) \
{ \
int rot = (patch[0].ptexInfo.w + 4 - ROTATE)%4; \
if (rot == 1) { \
output.tangent = -BiTangent; \
output.bitangent = Tangent; \
} else if (rot == 2) { \
output.tangent = -Tangent; \
output.bitangent = -BiTangent; \
} else if (rot == 3) { \
output.tangent = BiTangent; \
output.bitangent = -Tangent; \
} else { \
output.tangent = Tangent; \
output.bitangent = BiTangent; \
} \
}
#define OSD_COMPUTE_PTEX_COMPATIBLE_DERIVATIVES(ROTATE) \
{ \
int rot = (patch[0].ptexInfo.w + 4 - ROTATE)%4; \
if (rot == 1) { \
output.tangent = -BiTangent; \
output.bitangent = Tangent; \
output.Nu = -Nv; \
output.Nv = Nv; \
} else if (rot == 2) { \
output.tangent = -Tangent; \
output.bitangent = -BiTangent; \
output.Nu = -Nu; \
output.Nv = -Nv; \
} else if (rot == 3) { \
output.tangent = BiTangent; \
output.bitangent = -Tangent; \
output.Nu = Nv; \
output.Nv = -Nu; \
} else { \
output.tangent = Tangent; \
output.bitangent = BiTangent; \
output.Nu = Nu; \
output.Nv = Nv; \
} \
}
#ifdef OSD_ENABLE_PATCH_CULL

View File

@ -22,600 +22,118 @@
// language governing permissions and limitations under the Apache License.
//
#if defined(OSD_TRANSITION_PATTERN00) || defined(OSD_TRANSITION_PATTERN01) || defined(OSD_TRANSITION_PATTERN02) || defined(OSD_TRANSITION_PATTERN10) || defined(OSD_TRANSITION_PATTERN11) || defined(OSD_TRANSITION_PATTERN12) || defined(OSD_TRANSITION_PATTERN13) || defined(OSD_TRANSITION_PATTERN21) || defined(OSD_TRANSITION_PATTERN22) || defined(OSD_TRANSITION_PATTERN23)
#define OSD_TRANSITION_TRIANGLE_SUBPATCH
#else
#undef OSD_TRANSITION_TRIANGLE_SUBPATCH
#endif
struct HS_CONSTANT_TRANSITION_FUNC_OUT {
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH
float tessLevelInner : SV_InsideTessFactor;
float tessLevelOuter[3] : SV_TessFactor;
#else
float tessLevelInner[2] : SV_InsideTessFactor;
float tessLevelOuter[4] : SV_TessFactor;
#endif
};
//----------------------------------------------------------
// Patches.HullTransition
//----------------------------------------------------------
float
TessAdaptiveRound(float3 p0, float3 p1)
{
return round(TessAdaptive(p0, p1));
}
void
SetTransitionTessLevels(inout HS_CONSTANT_TRANSITION_FUNC_OUT output, float3 cp[OSD_PATCH_INPUT_SIZE], int patchLevel, uint primitiveID) {
GetTransitionTessLevels(
float3 cp[24], int patchParam, int patchLevel,
inout float4 outer, inout float4 inner,
inout float4 tessOuterLo, inout float4 tessOuterHi)
{
// Each edge of a transition patch is adjacent to one or two patches
// at the next refined level of subdivision. We COmpute the corresponding
// vertex-vertex and edge-vertex refined points along the edges of the
// patch using Catmull-Clark subdivision stencil weights.
// For simplicity, we let the optimizer discard unused computation.
cp[16] = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
(cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
cp[17] = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 + (cp[5] + cp[6]) * 0.375;
cp[18] = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
(cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
cp[19] = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 + (cp[6] + cp[10]) * 0.375;
cp[20] = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
(cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
cp[21] = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 + (cp[9] + cp[10]) * 0.375;
cp[22] = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
(cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
cp[23] = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 + (cp[5] + cp[9]) * 0.375;
tessOuterLo = float4(1,1,1,1);
tessOuterHi = float4(0,0,0,0);
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION
// These tables map the 9, 12, or 16 input control points onto the
// canonical 16 control points for a regular patch.
#if defined OSD_PATCH_BOUNDARY
const int p[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
#elif defined OSD_PATCH_CORNER
const int p[16] = { 0, 1, 2, 2, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8 };
if (((patchParam >> 11) & 1) != 0) {
tessOuterLo[0] = TessAdaptiveRound(cp[23], cp[16]);
tessOuterHi[0] = TessAdaptiveRound(cp[22], cp[23]);
} else {
tessOuterLo[0] = TessAdaptiveRound(cp[5], cp[9]);
}
if (((patchParam >> 8) & 1) != 0) {
tessOuterLo[1] = TessAdaptiveRound(cp[16], cp[17]);
tessOuterHi[1] = TessAdaptiveRound(cp[17], cp[18]);
} else {
tessOuterLo[1] = TessAdaptiveRound(cp[5], cp[6]);
}
if (((patchParam >> 9) & 1) != 0) {
tessOuterLo[2] = TessAdaptiveRound(cp[18], cp[19]);
tessOuterHi[2] = TessAdaptiveRound(cp[19], cp[20]);
} else {
tessOuterLo[2] = TessAdaptiveRound(cp[6], cp[10]);
}
if (((patchParam >> 10) & 1) != 0) {
tessOuterLo[3] = TessAdaptiveRound(cp[21], cp[22]);
tessOuterHi[3] = TessAdaptiveRound(cp[20], cp[21]);
} else {
tessOuterLo[3] = TessAdaptiveRound(cp[9], cp[10]);
}
#else
const int p[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
float tessAmount = GetTessLevel(patchLevel);
tessOuterLo[0] = tessAmount;
tessOuterLo[1] = tessAmount;
tessOuterLo[2] = tessAmount;
tessOuterLo[3] = tessAmount;
#endif
#if OSD_TRANSITION_ROTATE == 0
const int r[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
#elif OSD_TRANSITION_ROTATE == 1
const int r[16] = { 12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3 };
#elif OSD_TRANSITION_ROTATE == 2
const int r[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
#elif OSD_TRANSITION_ROTATE == 3
const int r[16] = { 3, 7, 11, 15, 2, 6, 10, 14, 1, 5, 9, 13, 0, 4, 8, 12 };
#endif
// Expand and rotate control points using remapping tables above
float3 pv0 = cp[p[r[0]]];
float3 pv1 = cp[p[r[1]]];
float3 pv2 = cp[p[r[2]]];
float3 pv3 = cp[p[r[3]]];
float3 pv4 = cp[p[r[4]]];
float3 pv5 = cp[p[r[5]]];
float3 pv6 = cp[p[r[6]]];
float3 pv7 = cp[p[r[7]]];
float3 pv8 = cp[p[r[8]]];
float3 pv9 = cp[p[r[9]]];
float3 pv10 = cp[p[r[10]]];
float3 pv11 = cp[p[r[11]]];
float3 pv12 = cp[p[r[12]]];
float3 pv13 = cp[p[r[13]]];
float3 pv14 = cp[p[r[14]]];
float3 pv15 = cp[p[r[15]]];
// Each edge of a transition patch is adjacent to one or two
// patches at the next refined level of subdivision.
// Compute the corresponding vertex-vertex and edge-vertex refined
// points along the edges of the patch using Catmull-Clark subdivision
// stencil weights.
// For simplicity, we let the optimizer discard unused computation.
float3 vv0 = (pv0 + pv2 + pv8 + pv10) * 0.015625 +
(pv1 + pv4 + pv6 + pv9) * 0.09375 + pv5 * 0.5625;
float3 ev01 = (pv1 + pv2 + pv9 + pv10) * 0.0625 + (pv5 + pv6) * 0.375;
float3 vv1 = (pv1 + pv3 + pv9 + pv11) * 0.015625 +
(pv2 + pv5 + pv7 + pv10) * 0.09375 + pv6 * 0.5625;
float3 ev12 = (pv5 + pv7 + pv9 + pv11) * 0.0625 + (pv6 + pv10) * 0.375;
float3 vv2 = (pv5 + pv7 + pv13 + pv15) * 0.015625 +
(pv6 + pv9 + pv11 + pv14) * 0.09375 + pv10 * 0.5625;
float3 ev23 = (pv5 + pv6 + pv13 + pv14) * 0.0625 + (pv9 + pv10) * 0.375;
float3 vv3 = (pv4 + pv6 + pv12 + pv14) * 0.015625 +
(pv5 + pv8 + pv10 + pv13) * 0.09375 + pv9 * 0.5625;
float3 ev30 = (pv4 + pv6 + pv8 + pv10) * 0.0625 + (pv5 + pv9) * 0.375;
// The vertices along boundaries and at corners are refined specially.
#if defined OSD_PATCH_BOUNDARY
#if OSD_TRANSITION_ROTATE == 0
vv0 = (pv4 + pv6) * 0.125 + pv5 * 0.75;
vv1 = (pv5 + pv7) * 0.125 + pv6 * 0.75;
#elif OSD_TRANSITION_ROTATE == 1
vv1 = (pv2 + pv10) * 0.125 + pv6 * 0.75;
vv2 = (pv6 + pv14) * 0.125 + pv10 * 0.75;
#elif OSD_TRANSITION_ROTATE == 2
vv2 = (pv9 + pv11) * 0.125 + pv10 * 0.75;
vv3 = (pv8 + pv10) * 0.125 + pv9 * 0.75;
#elif OSD_TRANSITION_ROTATE == 3
vv3 = (pv5 + pv13) * 0.125 + pv9 * 0.75;
vv0 = (pv1 + pv9) * 0.125 + pv5 * 0.75;
#endif
#elif defined OSD_PATCH_CORNER
#if OSD_TRANSITION_ROTATE == 0
vv0 = (pv4 + pv6) * 0.125 + pv5 * 0.75;
vv1 = pv6;
vv2 = (pv6 + pv14) * 0.125 + pv10 * 0.75;
#elif OSD_TRANSITION_ROTATE == 1
vv1 = (pv2 + pv10) * 0.125 + pv6 * 0.75;
vv2 = pv10;
vv3 = (pv8 + pv10) * 0.125 + pv9 * 0.75;
#elif OSD_TRANSITION_ROTATE == 2
vv2 = (pv9 + pv11) * 0.125 + pv10 * 0.75;
vv3 = pv9;
vv0 = (pv1 + pv9) * 0.125 + pv5 * 0.75;
#elif OSD_TRANSITION_ROTATE == 3
vv3 = (pv5 + pv13) * 0.125 + pv9 * 0.75;
vv0 = pv5;
vv1 = (pv5 + pv7) * 0.125 + pv6 * 0.75;
#endif
#elif defined OSD_PATCH_SINGLE_CREASE
// apply smooth, sharp or fractional-semisharp (linear interpolate) rules
float weight = min(1, GetSharpness(primitiveID));
// XXX: current rotation of single-crease patch is inconsistent
// to boundary patch. should be fixed.
#if OSD_TRANSITION_ROTATE == 2
vv0 = lerp(vv0, (pv4 + pv6) * 0.125 + pv5 * 0.75, weight);
vv1 = lerp(vv1, (pv5 + pv7) * 0.125 + pv6 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 3
vv1 = lerp(vv1, (pv2 + pv10) * 0.125 + pv6 * 0.75, weight);
vv2 = lerp(vv2, (pv6 + pv14) * 0.125 + pv10 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 0
vv2 = lerp(vv2, (pv9 + pv11) * 0.125 + pv10 * 0.75, weight);
vv3 = lerp(vv3, (pv8 + pv10) * 0.125 + pv9 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 1
vv3 = lerp(vv3, (pv5 + pv13) * 0.125 + pv9 * 0.75, weight);
vv0 = lerp(vv0, (pv1 + pv9) * 0.125 + pv5 * 0.75, weight);
#endif
#endif
#ifdef OSD_TRANSITION_PATTERN00
output.tessLevelOuter[0] = TessAdaptive(ev01, pv9) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev01, pv10) * 0.5;
output.tessLevelOuter[2] = TessAdaptive(pv9, pv10);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN01
output.tessLevelOuter[0] = TessAdaptive(ev01, vv1);
output.tessLevelOuter[1] = TessAdaptive(pv6, pv10);
output.tessLevelOuter[2] = TessAdaptive(ev01, pv10) * 0.5;
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN02
output.tessLevelOuter[0] = TessAdaptive(ev01, vv0);
output.tessLevelOuter[1] = TessAdaptive(ev01, pv9) * 0.5;
output.tessLevelOuter[2] = TessAdaptive(pv5, pv9);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN10
output.tessLevelOuter[0] = TessAdaptive(pv6, pv10);
output.tessLevelOuter[1] = TessAdaptive(ev01, pv10);
output.tessLevelOuter[2] = TessAdaptive(ev01, vv1);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN11
output.tessLevelOuter[0] = TessAdaptive(pv9, pv10);
output.tessLevelOuter[1] = TessAdaptive(ev30, vv3);
output.tessLevelOuter[2] = TessAdaptive(ev30, pv10);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN12
output.tessLevelOuter[0] = TessAdaptive(ev30, vv0);
output.tessLevelOuter[1] = TessAdaptive(ev01, vv0);
output.tessLevelOuter[2] = TessAdaptive(ev01, ev30);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN13
output.tessLevelOuter[0] = TessAdaptive(ev01, pv10);
output.tessLevelOuter[1] = TessAdaptive(ev30, pv10);
output.tessLevelOuter[2] = TessAdaptive(ev01, ev30);
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN20
output.tessLevelOuter[0] = TessAdaptive(pv5, pv6);
output.tessLevelOuter[1] = TessAdaptive(ev12, vv1);
output.tessLevelOuter[2] = TessAdaptive(ev12, ev30);
output.tessLevelOuter[3] = TessAdaptive(ev30, vv0);
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN21
output.tessLevelOuter[0] = TessAdaptive(ev23, ev30) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev23, vv3);
output.tessLevelOuter[2] = TessAdaptive(ev30, vv3);
output.tessLevelInner =
(output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN22
output.tessLevelOuter[0] = TessAdaptive(ev12, vv2);
output.tessLevelOuter[1] = TessAdaptive(ev23, vv2);
output.tessLevelOuter[2] = TessAdaptive(ev12, ev23) * 0.5;
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN23
output.tessLevelOuter[0] = TessAdaptive(ev12, ev30);
output.tessLevelOuter[1] = TessAdaptive(ev12, ev23) * 0.5;
output.tessLevelOuter[2] = TessAdaptive(ev23, ev30) * 0.5;
output.tessLevelInner =
(output.tessLevelOuter[0] + output.tessLevelOuter[1] + output.tessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN30
output.tessLevelOuter[0] = TessAdaptive(ev30, ev12) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev30, vv0);
output.tessLevelOuter[2] = TessAdaptive(ev01, vv0);
output.tessLevelOuter[3] = TessAdaptive(ev01, ev23) * 0.5;
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN31
output.tessLevelOuter[0] = TessAdaptive(ev01, ev23) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev23, vv3);
output.tessLevelOuter[2] = TessAdaptive(ev30, vv3);
output.tessLevelOuter[3] = TessAdaptive(ev30, ev12) * 0.5;
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN32
output.tessLevelOuter[0] = TessAdaptive(ev23, ev01) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev01, vv1);
output.tessLevelOuter[2] = TessAdaptive(ev12, vv1);
output.tessLevelOuter[3] = TessAdaptive(ev12, ev30) * 0.5;
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN33
output.tessLevelOuter[0] = TessAdaptive(ev12, ev30) * 0.5;
output.tessLevelOuter[1] = TessAdaptive(ev12, vv2);
output.tessLevelOuter[2] = TessAdaptive(ev23, vv2);
output.tessLevelOuter[3] = TessAdaptive(ev01, ev23) * 0.5;
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN40
output.tessLevelOuter[0] = TessAdaptive(ev01, vv0);
output.tessLevelOuter[1] = TessAdaptive(ev01, ev23);
output.tessLevelOuter[2] = TessAdaptive(ev23, vv3);
output.tessLevelOuter[3] = TessAdaptive(pv5, pv9);
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN41
output.tessLevelOuter[0] = TessAdaptive(ev01, vv1);
output.tessLevelOuter[1] = TessAdaptive(pv6, pv10);
output.tessLevelOuter[2] = TessAdaptive(ev23, vv2);
output.tessLevelOuter[3] = TessAdaptive(ev01, ev23);
output.tessLevelInner[0] =
max(output.tessLevelOuter[1], output.tessLevelOuter[3]);
output.tessLevelInner[1] =
max(output.tessLevelOuter[0], output.tessLevelOuter[2]);
#endif
#else // OSD_ENABLE_SCREENSPACE_TESSELLATION
// XXX: HLSL compiler crashes with an internal compiler error occasionaly
// if this shader accesses a shader resource buffer or a constant buffer
// from this hull constant function.
//float TessAmount = GetTessLevel(patchLevel);
//float TessAmount = GetTessLevel(0);
float TessAmount = 2.0;
#ifdef OSD_TRANSITION_PATTERN00
float side = sqrt(1.25)*TessAmount;
output.tessLevelOuter[0] = side;
output.tessLevelOuter[1] = side;
output.tessLevelOuter[2] = TessAmount;
output.tessLevelInner = TessAmount;
#endif
#ifdef OSD_TRANSITION_PATTERN01
float side = sqrt(1.25)*TessAmount;
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = TessAmount;
output.tessLevelOuter[2] = side;
output.tessLevelInner = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN02
float side = sqrt(1.25)*TessAmount;
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = side;
output.tessLevelOuter[2] = TessAmount;
output.tessLevelInner = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN10
float side = sqrt(1.25) * TessAmount;
output.tessLevelOuter[0] = TessAmount;
output.tessLevelOuter[1] = side;
output.tessLevelOuter[2] = TessAmount/2.0;
output.tessLevelInner = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN11
float side = sqrt(1.25) * TessAmount;
output.tessLevelOuter[0] = TessAmount;
output.tessLevelOuter[1] = TessAmount/2.0;
output.tessLevelOuter[2] = side;
output.tessLevelInner = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN12
float side = sqrt(0.125) * TessAmount;
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = TessAmount/2.0;
output.tessLevelOuter[2] = side;
output.tessLevelInner = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN13
float side1 = sqrt(1.25) * TessAmount;
float side2 = sqrt(0.125) * TessAmount;
output.tessLevelOuter[0] = side1;
output.tessLevelOuter[1] = side1;
output.tessLevelOuter[2] = side2;
output.tessLevelInner = TessAmount/2.0*1.414;
#endif
#ifdef OSD_TRANSITION_PATTERN20
output.tessLevelOuter[0] = TessAmount;
output.tessLevelOuter[1] = TessAmount/2.0;
output.tessLevelOuter[2] = TessAmount;
output.tessLevelOuter[3] = TessAmount/2.0;
output.tessLevelInner[0] = TessAmount/2.0;
output.tessLevelInner[1] = TessAmount;
#endif
#ifdef OSD_TRANSITION_PATTERN21
float side = sqrt(0.125) * TessAmount;
output.tessLevelOuter[0] = side;
output.tessLevelOuter[1] = TessAmount/2.0;
output.tessLevelOuter[2] = TessAmount/2.0;
output.tessLevelInner = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN22
float side = sqrt(0.125) * TessAmount;
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = TessAmount/2.0;
output.tessLevelOuter[2] = side;
output.tessLevelInner = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN23
float side = sqrt(0.125) * TessAmount;
output.tessLevelOuter[0] = TessAmount;
output.tessLevelOuter[1] = side;
output.tessLevelOuter[2] = side;
output.tessLevelInner = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN30
output.tessLevelOuter[0] = output.tessLevelOuter[1] =
output.tessLevelOuter[2] = output.tessLevelOuter[3] = TessAmount/2.0;
output.tessLevelInner[0] = output.tessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN31
output.tessLevelOuter[0] = output.tessLevelOuter[1] =
output.tessLevelOuter[2] = output.tessLevelOuter[3] = TessAmount/2.0;
output.tessLevelInner[0] = output.tessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN32
output.tessLevelOuter[0] = output.tessLevelOuter[1] =
output.tessLevelOuter[2] = output.tessLevelOuter[3] = TessAmount/2.0;
output.tessLevelInner[0] = output.tessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN33
output.tessLevelOuter[0] = output.tessLevelOuter[1] =
output.tessLevelOuter[2] = output.tessLevelOuter[3] = TessAmount/2.0;
output.tessLevelInner[0] = output.tessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN40
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = TessAmount;
output.tessLevelOuter[2] = TessAmount/2.0;
output.tessLevelOuter[3] = TessAmount;
output.tessLevelInner[0] = TessAmount;
output.tessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN41
output.tessLevelOuter[0] = TessAmount/2.0;
output.tessLevelOuter[1] = TessAmount;
output.tessLevelOuter[2] = TessAmount/2.0;
output.tessLevelOuter[3] = TessAmount;
output.tessLevelInner[0] = TessAmount;
output.tessLevelInner[1] = TessAmount/2.0;
#endif
#endif // OSD_ENABLE_SCREENSPACE_TESSELLATION
outer = tessOuterLo + tessOuterHi;
inner[0] = (outer[0] + outer[2]) * 0.5;
inner[1] = (outer[1] + outer[3]) * 0.5;
}
//----------------------------------------------------------
// Patches.DomainTransition
//----------------------------------------------------------
float2
GetTransitionSubpatchUV(
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH
in float3 uvw
#else
in float2 uv
#endif
)
float
GetTransitionSplit(float t, float n0, float n1)
{
float2 UV = float2(0.0, 0.0);
float n = round(n0 + n1);
float ti = round(t * n);
// OSD_TRANSITION_PATTERN0*
// +-------------+
// | /\\ |
// | 1 / \\ 2 |
// | / \\ |
// | / \\ |
// | / 0 \\ |
// |/ \\|
// +-------------+
#ifdef OSD_TRANSITION_PATTERN00
UV.x = 1.0-uvw.y-uvw.z/2;
UV.y = 1.0-uvw.z;
#endif
#ifdef OSD_TRANSITION_PATTERN01
UV.x = 1.0-uvw.y/2;
UV.y = uvw.x;
#endif
#ifdef OSD_TRANSITION_PATTERN02
UV.x = uvw.z/2;
UV.y = uvw.x;
#endif
// OSD_TRANSITION_PATTERN1*
// +-------------+
// | 0 /\\ 2 |
// | / \\ |
// | / 3 \\ |
// | / / |
// | / / 1 |
// |/ / |
// +-------------+
#ifdef OSD_TRANSITION_PATTERN10
UV.x = 1.0-uvw.x/2.0;
UV.y = uvw.z;
#endif
#ifdef OSD_TRANSITION_PATTERN11
UV.x = uvw.y;
UV.y = 1.0-uvw.x/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN12
UV.x = uvw.x/2.0;
UV.y = uvw.y/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN13
UV.x = 1.0-uvw.x-uvw.y/2.0;
UV.y = 1.0-uvw.y-uvw.x/2.0;
#endif
// OSD_TRANSITION_PATTERN2*
// +-------------+
// | |
// | 0 |
// | |
// |-------------|
// |\\ 3 / |
// | \\ / |
// | 1 \\ / 2 |
// +-------------+
#ifdef OSD_TRANSITION_PATTERN20
UV.x = 1.0-uv.y;
UV.y = uv.x/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN21
UV.x = uvw.z/2.0;
UV.y = 1.0-uvw.y/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN22
UV.x = 1.0-uvw.x/2.0;
UV.y = 1.0-uvw.y/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN23
UV.x = 1.0-uvw.y-uvw.x/2;
UV.y = 0.5+uvw.x/2.0;
#endif
// OSD_TRANSITION_PATTERN3*
// +-------------+
// | | |
// | 1 | 0 |
// | | |
// |------|------|
// | | |
// | 3 | 2 |
// | | |
// +-------------+
#ifdef OSD_TRANSITION_PATTERN30
UV.x = uv.y/2.0;
UV.y = 0.5 - uv.x/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN31
UV.x = 0.5 - uv.x/2.0;
UV.y = 1.0 - uv.y/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN32
UV.x = 0.5 + uv.x/2.0;
UV.y = uv.y/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN33
UV.x = 1.0 - uv.y/2.0;
UV.y = 0.5 + uv.x/2.0;
#endif
// OSD_TRANSITION_PATTERN4*
// +-------------+
// | | |
// | | |
// | | |
// | 1 | 0 |
// | | |
// | | |
// | | |
// +-------------+
#ifdef OSD_TRANSITION_PATTERN40
UV.x = 0.5 - uv.y/2.0;
UV.y = uv.x;
#endif
#ifdef OSD_TRANSITION_PATTERN41
UV.x = 1.0 - uv.y/2.0;
UV.y = uv.x;
#endif
if (ti <= n0) {
return 0.5 * (ti / n0);
} else {
return 0.5 * ((ti - n0) / n1) + 0.5;
}
}
float2
GetTransitionParameterization(
in HS_CONSTANT_FUNC_OUT input,
in float2 uv)
{
float2 UV = uv.xy;
if (UV.x == 0 && input.tessOuterHi[0] > 0) {
UV.y = GetTransitionSplit(UV.y, input.tessOuterLo[0], input.tessOuterHi[0]);
} else
if (UV.y == 0 && input.tessOuterHi[1] > 0) {
UV.x = GetTransitionSplit(UV.x, input.tessOuterLo[1], input.tessOuterHi[1]);
} else
if (UV.x == 1 && input.tessOuterHi[2] > 0) {
UV.y = GetTransitionSplit(UV.y, input.tessOuterLo[2], input.tessOuterHi[2]);
} else
if (UV.y == 1 && input.tessOuterHi[3] > 0) {
UV.x = GetTransitionSplit(UV.x, input.tessOuterLo[3], input.tessOuterHi[3]);
}
return UV;
}