Merge pull request #422 from davidgyu/patch-drawing

Unified adaptive patch drawing
This commit is contained in:
Takahito Tejima 2015-04-17 15:39:37 -07:00
commit aec1f61fb0
20 changed files with 595 additions and 1471 deletions

View File

@ -24,57 +24,25 @@
#include "patchColors.h" #include "patchColors.h"
static float _colors[5][7][4] = {{{1.0f, 1.0f, 1.0f, 1.0f}, // regular static float _colors[7][4] = {{1.0f, 1.0f, 1.0f, 1.0f}, // regular
{1.0f, 0.5f, 0.5f, 1.0f}, // single crease {1.0f, 0.5f, 0.5f, 1.0f}, // single crease
{0.8f, 0.0f, 0.0f, 1.0f}, // boundary {0.8f, 0.0f, 0.0f, 1.0f}, // boundary
{0.0f, 1.0f, 0.0f, 1.0f}, // corner {0.0f, 1.0f, 0.0f, 1.0f}, // corner
{1.0f, 1.0f, 0.0f, 1.0f}, // gregory {1.0f, 1.0f, 0.0f, 1.0f}, // gregory
{1.0f, 0.5f, 0.0f, 1.0f}, // gregory boundary {1.0f, 0.5f, 0.0f, 1.0f}, // gregory boundary
{1.0f, 0.7f, 0.3f, 1.0f}}, // gregory basis {1.0f, 0.7f, 0.3f, 1.0f}}; // gregory basis
{{0.0f, 1.0f, 1.0f, 1.0f}, // regular pattern 0
{0.0f, 0.5f, 1.0f, 1.0f}, // regular pattern 1
{0.0f, 0.5f, 0.5f, 1.0f}, // regular pattern 2
{0.5f, 0.0f, 1.0f, 1.0f}, // regular pattern 3
{1.0f, 0.5f, 1.0f, 1.0f}}, // regular pattern 4
{{1.0f, 0.70f, 0.6f, 1.0f}, // single crease pattern 0
{1.0f, 0.65f, 0.6f, 1.0f}, // single crease pattern 1
{1.0f, 0.60f, 0.6f, 1.0f}, // single crease pattern 2
{1.0f, 0.55f, 0.6f, 1.0f}, // single crease pattern 3
{1.0f, 0.50f, 0.6f, 1.0f}}, // single crease pattern 4
{{0.0f, 0.0f, 0.75f, 1.0f}, // boundary pattern 0
{0.0f, 0.2f, 0.75f, 1.0f}, // boundary pattern 1
{0.0f, 0.4f, 0.75f, 1.0f}, // boundary pattern 2
{0.0f, 0.6f, 0.75f, 1.0f}, // boundary pattern 3
{0.0f, 0.8f, 0.75f, 1.0f}}, // boundary pattern 4
{{0.25f, 0.25f, 0.25f, 1.0f}, // corner pattern 0
{0.25f, 0.25f, 0.25f, 1.0f}, // corner pattern 1
{0.25f, 0.25f, 0.25f, 1.0f}, // corner pattern 2
{0.25f, 0.25f, 0.25f, 1.0f}, // corner pattern 3
{0.25f, 0.25f, 0.25f, 1.0f}}}; // corner pattern 4
typedef OpenSubdiv::Far::PatchDescriptor Descriptor; typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
float const * float const *
getAdaptivePatchColor(Descriptor const & desc) { getAdaptivePatchColor(Descriptor const & desc) {
if (desc.GetPattern()==Descriptor::NON_TRANSITION) { return _colors[(int)(desc.GetType()-Descriptor::REGULAR)];
return _colors[0][(int)(desc.GetType()-Descriptor::REGULAR)];
} else {
return _colors[(int)(desc.GetType()-Descriptor::REGULAR)+1][(int)desc.GetPattern()-1];
}
} }
float const * float const *
getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc) { getAdaptivePatchColor(OpenSubdiv::Osd::DrawContext::PatchDescriptor const & desc) {
if (desc.GetPattern()==Descriptor::NON_TRANSITION) { return _colors[(int)(desc.GetType()-Descriptor::REGULAR)];
return _colors[0][(int)(desc.GetType()-Descriptor::REGULAR)];
} else {
return _colors[(int)(desc.GetType()-Descriptor::REGULAR)+1][(int)desc.GetPattern()-1];
}
} }

View File

@ -1755,7 +1755,7 @@ drawCageEdges() {
typedef OpenSubdiv::Far::PatchDescriptor FDesc; typedef OpenSubdiv::Far::PatchDescriptor FDesc;
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc( OpenSubdiv::Osd::DrawContext::PatchDescriptor desc(
FDesc(FDesc::LINES, FDesc::NON_TRANSITION, 0), 0, 0, 0); FDesc(FDesc::LINES), 0, 0);
EffectDrawRegistry::ConfigType *config = getInstance(effect, desc); EffectDrawRegistry::ConfigType *config = getInstance(effect, desc);
glUseProgram(config->program); glUseProgram(config->program);

View File

@ -423,7 +423,85 @@ layout(std140) uniform Lighting {
}; };
#if defined COLOR_PATCHTYPE #if defined COLOR_PATCHTYPE
uniform vec4 overrideColor; uniform vec4 overrideColor;
vec4
GetOverrideColor(int patchParam)
{
const vec4 patchColors[7*6] = vec4[7*6](
vec4(1.0f, 1.0f, 1.0f, 1.0f), // regular
vec4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
vec4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
vec4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
vec4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
vec4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
vec4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
vec4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
vec4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
vec4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
vec4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
vec4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
vec4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
vec4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
vec4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
vec4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
vec4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
vec4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
vec4(0.0f, 1.0f, 0.0f, 1.0f), // corner
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f) // gregory basis
);
int patchType = 0;
#if defined OSD_PATCH_SINGLE_CREASE
patchType = 1;
#elif defined OSD_PATCH_GREGORY
patchType = 4;
#elif defined OSD_PATCH_GREGORY_BOUNDARY
patchType = 5;
#elif defined OSD_PATCH_GREGORY_BASIS
patchType = 6;
#endif
int edgeCount = bitCount((patchParam >> 4) & 0xf);
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
if (edgeCount == 2) {
patchType = 3; // CORNER
}
int pattern = bitCount((patchParam >> 8) & 0xf);
int offset = 7*patchType + pattern;
return patchColors[offset];
}
#endif #endif
#if defined(NORMAL_HW_SCREENSPACE) || defined(NORMAL_SCREENSPACE) #if defined(NORMAL_HW_SCREENSPACE) || defined(NORMAL_SCREENSPACE)
@ -597,7 +675,7 @@ main()
textureImage_Data, textureImage_Data,
textureImage_Packing); textureImage_Packing);
#elif defined COLOR_PATCHTYPE #elif defined COLOR_PATCHTYPE
vec4 texColor = edgeColor(lighting(overrideColor, inpt.v.position.xyz, normal, 1, 0)); vec4 texColor = edgeColor(lighting(GetOverrideColor(GetPatchParam()), inpt.v.position.xyz, normal, 1, 0));
outColor = texColor; outColor = texColor;
return; return;
#elif defined COLOR_PATCHCOORD #elif defined COLOR_PATCHCOORD

View File

@ -1158,7 +1158,7 @@ display() {
g_mesh->GetDrawContext()->GetPatchArrays(); g_mesh->GetDrawContext()->GetPatchArrays();
// patch drawing // patch drawing
int patchCount[13][6][4]; // [Type][Pattern][Rotation] (see far/patchTables.h) int patchCount[13]; // [Type] (see far/patchTables.h)
int numTotalPatches = 0; int numTotalPatches = 0;
int numDrawCalls = 0; int numDrawCalls = 0;
memset(patchCount, 0, sizeof(patchCount)); memset(patchCount, 0, sizeof(patchCount));
@ -1174,13 +1174,8 @@ display() {
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor(); OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType(); OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
int patchPattern = desc.GetPattern();
int patchRotation = desc.GetRotation();
int subPatch = desc.GetSubPatch();
if (subPatch == 0) { patchCount[patchType] += patch.GetNumPatches();
patchCount[patchType][patchPattern][patchRotation] += patch.GetNumPatches();
}
numTotalPatches += patch.GetNumPatches(); numTotalPatches += patch.GetNumPatches();
GLenum primType; GLenum primType;
@ -1192,6 +1187,9 @@ display() {
case OpenSubdiv::Far::PatchDescriptor::TRIANGLES: case OpenSubdiv::Far::PatchDescriptor::TRIANGLES:
primType = GL_TRIANGLES; primType = GL_TRIANGLES;
break; break;
case OpenSubdiv::Far::PatchDescriptor::SINGLE_CREASE: // XXXdyu-patch-drawing
continue;
break;
default: default:
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0) #if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
primType = GL_PATCHES; primType = GL_PATCHES;
@ -1288,48 +1286,21 @@ display() {
int x = -280; int x = -280;
int y = -480; int y = -480;
g_hud.DrawString(x, y, "NonPatch : %d", g_hud.DrawString(x, y, "NonPatch : %d",
patchCount[Descriptor::QUADS][0][0]); y += 20; patchCount[Descriptor::QUADS]); y += 20;
g_hud.DrawString(x, y, "Regular : %d", g_hud.DrawString(x, y, "Regular : %d",
patchCount[Descriptor::REGULAR][0][0]); y+= 20; patchCount[Descriptor::REGULAR]); y+= 20;
g_hud.DrawString(x, y, "Boundary : %d", g_hud.DrawString(x, y, "Boundary : %d",
patchCount[Descriptor::BOUNDARY][0][0]); y+= 20; patchCount[Descriptor::BOUNDARY]); y+= 20;
g_hud.DrawString(x, y, "Corner : %d", g_hud.DrawString(x, y, "Corner : %d",
patchCount[Descriptor::CORNER][0][0]); y+= 20; patchCount[Descriptor::CORNER]); y+= 20;
g_hud.DrawString(x, y, "Single Crease : %d", g_hud.DrawString(x, y, "Single Crease : %d",
patchCount[Descriptor::SINGLE_CREASE][0][0]); y+= 20; patchCount[Descriptor::SINGLE_CREASE]); y+= 20;
g_hud.DrawString(x, y, "Gregory : %d", g_hud.DrawString(x, y, "Gregory : %d",
patchCount[Descriptor::GREGORY][0][0]); y+= 20; patchCount[Descriptor::GREGORY]); y+= 20;
g_hud.DrawString(x, y, "Boundary Gregory : %d", g_hud.DrawString(x, y, "Boundary Gregory : %d",
patchCount[Descriptor::GREGORY_BOUNDARY][0][0]); y+= 20; patchCount[Descriptor::GREGORY_BOUNDARY]); y+= 20;
g_hud.DrawString(x, y, "Gregory Basis : %d", g_hud.DrawString(x, y, "Gregory Basis : %d",
patchCount[Descriptor::GREGORY_BASIS][0][0]); y+= 20; patchCount[Descriptor::GREGORY_BASIS]); y+= 20;
g_hud.DrawString(x, y, "Trans. Regular : %d %d %d %d %d",
patchCount[Descriptor::REGULAR][Descriptor::PATTERN0][0],
patchCount[Descriptor::REGULAR][Descriptor::PATTERN1][0],
patchCount[Descriptor::REGULAR][Descriptor::PATTERN2][0],
patchCount[Descriptor::REGULAR][Descriptor::PATTERN3][0],
patchCount[Descriptor::REGULAR][Descriptor::PATTERN4][0]); y+= 20;
for (int i=0; i < 5; i++) {
g_hud.DrawString(x, y, "Trans. Boundary%d : %d %d %d %d", i,
patchCount[Descriptor::BOUNDARY][i+1][0],
patchCount[Descriptor::BOUNDARY][i+1][1],
patchCount[Descriptor::BOUNDARY][i+1][2],
patchCount[Descriptor::BOUNDARY][i+1][3]); y+= 20;
}
for (int i=0; i < 5; i++) {
g_hud.DrawString(x, y, "Trans. Corner%d : %d %d %d %d", i,
patchCount[Descriptor::CORNER][i+1][0],
patchCount[Descriptor::CORNER][i+1][1],
patchCount[Descriptor::CORNER][i+1][2],
patchCount[Descriptor::CORNER][i+1][3]); y+= 20;
}
for (int i=0; i < 5; i++) {
g_hud.DrawString(x, y, "Trans. Single Crease%d : %d %d %d %d", i,
patchCount[Descriptor::SINGLE_CREASE][i+1][0],
patchCount[Descriptor::SINGLE_CREASE][i+1][1],
patchCount[Descriptor::SINGLE_CREASE][i+1][2],
patchCount[Descriptor::SINGLE_CREASE][i+1][3]); y+= 20;
}
} }
int y = -220; int y = -220;

View File

@ -374,6 +374,84 @@ edgeColor(vec4 Cfill, vec4 edgeDistance)
return Cfill; return Cfill;
} }
vec4
getAdaptivePatchColor(int patchParam)
{
const vec4 patchColors[7*6] = vec4[7*6](
vec4(1.0f, 1.0f, 1.0f, 1.0f), // regular
vec4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0
vec4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1
vec4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2
vec4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3
vec4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4
vec4(1.0f, 0.5f, 0.5f, 1.0f), // single crease
vec4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0
vec4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1
vec4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2
vec4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3
vec4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4
vec4(0.8f, 0.0f, 0.0f, 1.0f), // boundary
vec4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0
vec4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1
vec4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2
vec4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3
vec4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4
vec4(0.0f, 1.0f, 0.0f, 1.0f), // corner
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 0
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 1
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 2
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 3
vec4(0.25f, 0.25f, 0.25f, 1.0f), // corner pattern 4
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 1.0f, 0.0f, 1.0f), // gregory
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis
vec4(1.0f, 0.7f, 0.3f, 1.0f) // gregory basis
);
int patchType = 0;
#if defined OSD_PATCH_SINGLE_CREASE
patchType = 1;
#elif defined OSD_PATCH_GREGORY
patchType = 4;
#elif defined OSD_PATCH_GREGORY_BOUNDARY
patchType = 5;
#elif defined OSD_PATCH_GREGORY_BASIS
patchType = 6;
#endif
int edgeCount = bitCount((patchParam >> 4) & 0xf);
if (edgeCount == 1) {
patchType = 2; // BOUNDARY
}
if (edgeCount == 2) {
patchType = 3; // CORNER
}
int pattern = bitCount((patchParam >> 8) & 0xf);
return patchColors[7*patchType + pattern];
}
#if defined(PRIM_QUAD) || defined(PRIM_TRI) #if defined(PRIM_QUAD) || defined(PRIM_TRI)
void void
main() main()
@ -387,7 +465,8 @@ main()
vec4 color = vec4(inpt.color.rg, vec4 color = vec4(inpt.color.rg,
int(floor(20*inpt.color.r)+floor(20*inpt.color.g))&1, 1); int(floor(20*inpt.color.r)+floor(20*inpt.color.g))&1, 1);
#else #else
vec4 color = diffuseColor; //vec4 color = diffuseColor;
vec4 color = getAdaptivePatchColor(GetPatchParam());
#endif #endif
vec4 Cf = lighting(color, inpt.v.position.xyz, N); vec4 Cf = lighting(color, inpt.v.position.xyz, N);

View File

@ -43,94 +43,19 @@ PatchDescriptor::GetAdaptivePatchDescriptors(Sdc::SchemeType type) {
static PatchDescriptor _loopDescriptors[] = { static PatchDescriptor _loopDescriptors[] = {
// XXXX work in progress ! // XXXX work in progress !
PatchDescriptor(LOOP, NON_TRANSITION, 0) PatchDescriptor(LOOP),
}; };
static PatchDescriptor _catmarkDescriptors[] = { static PatchDescriptor _catmarkDescriptors[] = {
// non-transition patches : 7 // XXXdyu-patch-drawing
PatchDescriptor(REGULAR, NON_TRANSITION, 0), PatchDescriptor(REGULAR),
PatchDescriptor(SINGLE_CREASE, NON_TRANSITION, 0), PatchDescriptor(SINGLE_CREASE),
PatchDescriptor(BOUNDARY, NON_TRANSITION, 0), PatchDescriptor(BOUNDARY),
PatchDescriptor(CORNER, NON_TRANSITION, 0), PatchDescriptor(CORNER),
PatchDescriptor(GREGORY, NON_TRANSITION, 0), PatchDescriptor(GREGORY),
PatchDescriptor(GREGORY_BOUNDARY, NON_TRANSITION, 0), PatchDescriptor(GREGORY_BOUNDARY),
PatchDescriptor(GREGORY_BASIS, NON_TRANSITION, 0), PatchDescriptor(GREGORY_BASIS),
// transition pattern 0
PatchDescriptor(REGULAR, PATTERN0, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN0, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN0, 1),
PatchDescriptor(SINGLE_CREASE, PATTERN0, 2),
PatchDescriptor(SINGLE_CREASE, PATTERN0, 3),
PatchDescriptor(BOUNDARY, PATTERN0, 0),
PatchDescriptor(BOUNDARY, PATTERN0, 1),
PatchDescriptor(BOUNDARY, PATTERN0, 2),
PatchDescriptor(BOUNDARY, PATTERN0, 3),
PatchDescriptor(CORNER, PATTERN0, 0),
PatchDescriptor(CORNER, PATTERN0, 1),
PatchDescriptor(CORNER, PATTERN0, 2),
PatchDescriptor(CORNER, PATTERN0, 3),
// transition pattern 1
PatchDescriptor(REGULAR, PATTERN1, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN1, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN1, 1),
PatchDescriptor(SINGLE_CREASE, PATTERN1, 2),
PatchDescriptor(SINGLE_CREASE, PATTERN1, 3),
PatchDescriptor(BOUNDARY, PATTERN1, 0),
PatchDescriptor(BOUNDARY, PATTERN1, 1),
PatchDescriptor(BOUNDARY, PATTERN1, 2),
PatchDescriptor(BOUNDARY, PATTERN1, 3),
PatchDescriptor(CORNER, PATTERN1, 0),
PatchDescriptor(CORNER, PATTERN1, 1),
PatchDescriptor(CORNER, PATTERN1, 2),
PatchDescriptor(CORNER, PATTERN1, 3),
// transition pattern 2
PatchDescriptor(REGULAR, PATTERN2, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN2, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN2, 1),
PatchDescriptor(SINGLE_CREASE, PATTERN2, 2),
PatchDescriptor(SINGLE_CREASE, PATTERN2, 3),
PatchDescriptor(BOUNDARY, PATTERN2, 0),
PatchDescriptor(BOUNDARY, PATTERN2, 1),
PatchDescriptor(BOUNDARY, PATTERN2, 2),
PatchDescriptor(BOUNDARY, PATTERN2, 3),
PatchDescriptor(CORNER, PATTERN2, 0),
PatchDescriptor(CORNER, PATTERN2, 1),
PatchDescriptor(CORNER, PATTERN2, 2),
PatchDescriptor(CORNER, PATTERN2, 3),
// transition pattern 3
PatchDescriptor(REGULAR, PATTERN3, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN3, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN3, 1),
PatchDescriptor(SINGLE_CREASE, PATTERN3, 2),
PatchDescriptor(SINGLE_CREASE, PATTERN3, 3),
PatchDescriptor(BOUNDARY, PATTERN3, 0),
PatchDescriptor(BOUNDARY, PATTERN3, 1),
PatchDescriptor(BOUNDARY, PATTERN3, 2),
PatchDescriptor(BOUNDARY, PATTERN3, 3),
PatchDescriptor(CORNER, PATTERN3, 0),
PatchDescriptor(CORNER, PATTERN3, 1),
PatchDescriptor(CORNER, PATTERN3, 2),
PatchDescriptor(CORNER, PATTERN3, 3),
// transition pattern 4
PatchDescriptor(REGULAR, PATTERN4, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN4, 0),
PatchDescriptor(SINGLE_CREASE, PATTERN4, 1),
PatchDescriptor(SINGLE_CREASE, PATTERN4, 2),
PatchDescriptor(SINGLE_CREASE, PATTERN4, 3),
PatchDescriptor(BOUNDARY, PATTERN4, 0),
PatchDescriptor(BOUNDARY, PATTERN4, 1),
PatchDescriptor(BOUNDARY, PATTERN4, 2),
PatchDescriptor(BOUNDARY, PATTERN4, 3),
PatchDescriptor(CORNER, PATTERN4, 0),
PatchDescriptor(CORNER, PATTERN4, 1),
PatchDescriptor(CORNER, PATTERN4, 2),
PatchDescriptor(CORNER, PATTERN4, 3),
}; };
switch (type) { switch (type) {
@ -155,8 +80,8 @@ PatchDescriptor::print() const {
"SINGLE_CREASE", "BOUNDARY", "CORNER", "GREGORY", "SINGLE_CREASE", "BOUNDARY", "CORNER", "GREGORY",
"GREGORY_BOUNDARY", "GREGORY_BASIS" }; "GREGORY_BOUNDARY", "GREGORY_BASIS" };
printf(" type %s trans %d rot %d\n", printf(" type %s\n",
types[_type], _pattern, _rotation); types[_type]);
} }

View File

@ -51,11 +51,9 @@ namespace Far {
/// ///
/// Bitfield layout : /// Bitfield layout :
/// ///
/// Field | Bits | Content /// Field | Bits | Content
/// -----------|:----:|------------------------------------------------------ /// ------------|:----:|------------------------------------------------------
/// _type | 4 | patch type /// _type | 4 | patch type
/// _pattern | 3 | patch transition pattern
/// _rotation | 2 | patch rotation
/// ///
class PatchDescriptor { class PatchDescriptor {
@ -81,44 +79,25 @@ public:
GREGORY_BASIS GREGORY_BASIS
}; };
enum TransitionPattern {
NON_TRANSITION = 0,
PATTERN0,
PATTERN1,
PATTERN2,
PATTERN3,
PATTERN4
};
public: public:
/// \brief Default constructor. /// \brief Default constructor.
PatchDescriptor() : PatchDescriptor() :
_type(NON_PATCH), _pattern(NON_TRANSITION), _rotation(0) {} _type(NON_PATCH) { }
/// \brief Constructor /// \brief Constructor
PatchDescriptor(int type, int pattern, unsigned char rotation) : PatchDescriptor(int type) :
_type(type), _pattern(pattern), _rotation(rotation) { } _type(type) { }
/// \brief Copy Constructor /// \brief Copy Constructor
PatchDescriptor( PatchDescriptor const & d ) : PatchDescriptor( PatchDescriptor const & d ) :
_type(d.GetType()), _pattern(d.GetPattern()), _rotation(d.GetRotation()) { } _type(d.GetType()) { }
/// \brief Returns the type of the patch /// \brief Returns the type of the patch
Type GetType() const { Type GetType() const {
return (Type)_type; return (Type)_type;
} }
/// \brief Returns the transition pattern of the patch if any (5 types)
TransitionPattern GetPattern() const {
return (TransitionPattern)_pattern;
}
/// \brief Returns the rotation of the patch (4 rotations)
unsigned char GetRotation() const {
return (unsigned char)_rotation;
}
/// \brief Returns true if the type is an adaptive patch /// \brief Returns true if the type is an adaptive patch
static inline bool IsAdaptive(Type type) { static inline bool IsAdaptive(Type type) {
return (type>=LOOP and type<=GREGORY_BASIS); return (type>=LOOP and type<=GREGORY_BASIS);
@ -151,10 +130,10 @@ public:
static short GetRegularPatchSize() { return 16; } static short GetRegularPatchSize() { return 16; }
/// \brief Number of control vertices of Boundary Patches in table. /// \brief Number of control vertices of Boundary Patches in table.
static short GetBoundaryPatchSize() { return 12; } static short GetBoundaryPatchSize() { return 16; }
/// \brief Number of control vertices of Boundary Patches in table. /// \brief Number of control vertices of Boundary Patches in table.
static short GetCornerPatchSize() { return 9; } static short GetCornerPatchSize() { return 16; }
/// \brief Number of control vertices of Gregory (and Gregory Boundary) Patches in table. /// \brief Number of control vertices of Gregory (and Gregory Boundary) Patches in table.
static short GetGregoryPatchSize() { return 4; } static short GetGregoryPatchSize() { return 4; }
@ -180,8 +159,6 @@ private:
friend class PatchTablesFactory; friend class PatchTablesFactory;
unsigned int _type:4; unsigned int _type:4;
unsigned int _pattern:3;
unsigned int _rotation:2;
}; };
typedef Vtr::ConstArray<PatchDescriptor> ConstPatchDescriptorArray; typedef Vtr::ConstArray<PatchDescriptor> ConstPatchDescriptorArray;
@ -227,17 +204,13 @@ PatchDescriptor::GetNumFVarControlVertices( Type type ) {
// Allows ordering of patches by type // Allows ordering of patches by type
inline bool inline bool
PatchDescriptor::operator < ( PatchDescriptor const other ) const { PatchDescriptor::operator < ( PatchDescriptor const other ) const {
return _pattern < other._pattern or ((_pattern == other._pattern) and return (_type < other._type);
(_type < other._type or ((_type == other._type) and
(_rotation < other._rotation))));
} }
// True if the descriptors are identical // True if the descriptors are identical
inline bool inline bool
PatchDescriptor::operator == ( PatchDescriptor const other ) const { PatchDescriptor::operator == ( PatchDescriptor const other ) const {
return _pattern == other._pattern and return _type == other._type;
_type == other._type and
_rotation == other._rotation;
} }

View File

@ -48,12 +48,12 @@ namespace Far {
/// ///
/// Field | Bits | Content /// Field | Bits | Content
/// -----------|:----:|------------------------------------------------------ /// -----------|:----:|------------------------------------------------------
/// level | 4 | the subdivision level of the patch /// level | 3 | the subdivision level of the patch
/// nonquad | 1 | whether the patch is the child of a non-quad face /// nonquad | 1 | whether the patch is the child of a non-quad face
/// rotation | 2 | patch rotations necessary to match CCW face-winding /// boundary | 4 | boundary edge mask encoding
/// transition | 4 | transition edge mask encoding
/// v | 10 | log2 value of u parameter at first patch corner /// v | 10 | log2 value of u parameter at first patch corner
/// u | 10 | log2 value of v parameter at first patch corner /// u | 10 | log2 value of v parameter at first patch corner
/// reserved1 | 5 | padding
/// ///
/// Note : the bitfield is not expanded in the struct due to differences in how /// Note : the bitfield is not expanded in the struct due to differences in how
/// GPU & CPU compilers pack bit-fields and endian-ness. /// GPU & CPU compilers pack bit-fields and endian-ness.
@ -73,28 +73,35 @@ struct PatchParam {
/// @param depth subdivision level of the patch /// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad /// @param nonquad true if the root face is not a quad
/// ///
void Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ); void Set( short u, short v, unsigned char depth, bool nonquad,
unsigned short boundary, unsigned short transition );
/// \brief Returns the log2 value of the u parameter at the top left corner of /// \brief Returns the log2 value of the u parameter at the top left corner of
/// the patch /// the patch
unsigned short GetU() const { return (unsigned short)((field >> 17) & 0x3ff); } unsigned short GetU() const { return (unsigned short)((field >> 22) & 0x3ff); }
/// \brief Returns the log2 value of the v parameter at the top left corner of /// \brief Returns the log2 value of the v parameter at the top left corner of
/// the patch /// the patch
unsigned short GetV() const { return (unsigned short)((field >> 7) & 0x3ff); } unsigned short GetV() const { return (unsigned short)((field >> 12) & 0x3ff); }
/// \brief Returns the rotation of the patch (the number of CCW parameter winding) /// \brief Returns the transition edge encoding for the patch.
unsigned char GetRotation() const { return (unsigned char)((field >> 5) & 0x3); } unsigned short GetTransition() const { return (unsigned short)((field >> 8) & 0xf); }
/// \brief Returns the boundary edge encoding for the patch.
unsigned short GetBoundary() const { return (unsigned short)((field >> 4) & 0xf); }
/// \brief Deprecated XXXdyu-patch-drawing (patches rotated when gathered from refiner)
unsigned char GetRotation() const { return 0; }
/// \brief True if the parent coarse face is a non-quad /// \brief True if the parent coarse face is a non-quad
bool NonQuadRoot() const { return (field >> 4) & 0x1; } bool NonQuadRoot() const { return (field >> 3) & 0x1; }
/// \brief Returns the fratcion of normalized parametric space covered by the /// \brief Returns the fratcion of normalized parametric space covered by the
/// sub-patch. /// sub-patch.
float GetParamFraction() const; float GetParamFraction() const;
/// \brief Returns the level of subdivision of the patch /// \brief Returns the level of subdivision of the patch
unsigned char GetDepth() const { return (unsigned char)(field & 0xf); } unsigned char GetDepth() const { return (unsigned char)(field & 0x7); }
/// The (u,v) pair is normalized to this sub-parametric space. /// The (u,v) pair is normalized to this sub-parametric space.
/// ///
@ -103,14 +110,6 @@ struct PatchParam {
/// ///
void Normalize( float & u, float & v ) const; void Normalize( float & u, float & v ) const;
/// \brief Rotate (u,v) pair to compensate for transition pattern and boundary
/// orientations.
///
/// @param u u parameter
/// @param v v parameter
///
void Rotate( float & u, float & v ) const;
/// \brief Resets the values to 0 /// \brief Resets the values to 0
void Clear() { field = 0; } void Clear() { field = 0; }
@ -127,7 +126,8 @@ struct PatchParam {
/// @param depth subdivision level of the patch /// @param depth subdivision level of the patch
/// @param nonquad true if the root face is not a quad /// @param nonquad true if the root face is not a quad
/// ///
void Set( Index faceid, short u, short v, unsigned char rots, unsigned char depth, bool nonquad ); void Set( Index faceid, short u, short v, unsigned char depth, bool nonquad ,
unsigned short boundary, unsigned short transition );
/// \brief Resets everything to 0 /// \brief Resets everything to 0
void Clear(); void Clear();
@ -139,11 +139,13 @@ typedef Vtr::Array<PatchParam> PatchParamArray;
typedef Vtr::ConstArray<PatchParam> ConstPatchParamArray; typedef Vtr::ConstArray<PatchParam> ConstPatchParamArray;
inline void inline void
PatchParam::BitField::Set( short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) { PatchParam::BitField::Set( short u, short v, unsigned char depth, bool nonquad,
field = (u << 17) | unsigned short boundary, unsigned short transition ) {
(v << 7) | field = (u << 22) |
(rots << 5) | (v << 12) |
((nonquad ? 1:0) << 4) | (transition << 8) |
(boundary << 4) |
((nonquad ? 1:0) << 3) |
(nonquad ? depth+1 : depth); (nonquad ? depth+1 : depth);
} }
@ -172,21 +174,10 @@ PatchParam::BitField::Normalize( float & u, float & v ) const {
} }
inline void inline void
PatchParam::BitField::Rotate( float & u, float & v ) const { PatchParam::Set( Index faceid, short u, short v, unsigned char depth, bool nonquad,
switch( GetRotation() ) { unsigned short boundary, unsigned short transition ) {
case 0 : break;
case 1 : { float tmp=v; v=1.0f-u; u=tmp; } break;
case 2 : { u=1.0f-u; v=1.0f-v; } break;
case 3 : { float tmp=u; u=1.0f-v; v=tmp; } break;
default:
assert(0);
}
}
inline void
PatchParam::Set( Index faceid, short u, short v, unsigned char rots, unsigned char depth, bool nonquad ) {
faceIndex = faceid; faceIndex = faceid;
bitField.Set(u,v,rots,depth,nonquad); bitField.Set(u,v,depth,nonquad,boundary,transition);
} }
inline void inline void

View File

@ -461,7 +461,7 @@ PatchTables::Evaluate(PatchHandle const & handle, float s, float t,
float Q[16], Qd1[16], Qd2[16]; float Q[16], Qd1[16], Qd2[16];
if (ptype>=PatchDescriptor::REGULAR and ptype<=PatchDescriptor::CORNER) { if (ptype>=PatchDescriptor::REGULAR and ptype<=PatchDescriptor::SINGLE_CREASE) {
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2); GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
@ -470,17 +470,13 @@ PatchTables::Evaluate(PatchHandle const & handle, float s, float t,
switch (ptype) { switch (ptype) {
case PatchDescriptor::REGULAR: case PatchDescriptor::REGULAR:
InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst); InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
// XXXdyu bits InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break; break;
case PatchDescriptor::SINGLE_CREASE: case PatchDescriptor::SINGLE_CREASE:
// TODO: implement InterpolateSingleCreasePatch(). // TODO: implement InterpolateSingleCreasePatch().
//InterpolateRegularPatch(cvs, Q, Qd1, Qd2, src, dst); //InterpolateRegularPatch(cvs, Q, Qd1, Qd2, src, dst);
break; break;
case PatchDescriptor::BOUNDARY:
InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break;
case PatchDescriptor::CORNER:
InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break;
case PatchDescriptor::GREGORY: case PatchDescriptor::GREGORY:
case PatchDescriptor::GREGORY_BOUNDARY: case PatchDescriptor::GREGORY_BOUNDARY:
assert(0); assert(0);
@ -537,14 +533,8 @@ PatchTables::EvaluateFaceVarying(int channel, PatchHandle const & handle,
case PatchDescriptor::REGULAR: case PatchDescriptor::REGULAR:
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2); GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst); InterpolateRegularPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break; // XXXdyu bits InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
case PatchDescriptor::BOUNDARY: // XXXdyu bits InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
InterpolateBoundaryPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break;
case PatchDescriptor::CORNER:
GetBSplineWeights(bits, s, t, Q, Qd1, Qd2);
InterpolateCornerPatch(cvs.begin(), Q, Qd1, Qd2, src, dst);
break; break;
default: default:
assert(0); assert(0);

View File

@ -42,50 +42,41 @@ namespace {
template <class TYPE> template <class TYPE>
struct PatchTypes { struct PatchTypes {
static const int NUM_TRANSITIONS=6,
NUM_ROTATIONS=4;
TYPE R[NUM_TRANSITIONS], // regular patch TYPE R, // regular patch
S[NUM_TRANSITIONS][NUM_ROTATIONS], // single-crease patch S, // single-crease patch
B[NUM_TRANSITIONS][NUM_ROTATIONS], // boundary patch (4 rotations) B, // boundary patch (4 rotations)
C[NUM_TRANSITIONS][NUM_ROTATIONS], // corner patch (4 rotations) C, // corner patch (4 rotations)
G, // gregory patch G, // gregory patch
GB, // gregory boundary patch GB, // gregory boundary patch
GP; // gregory basis patch GP; // gregory basis patch
PatchTypes() { std::memset(this, 0, sizeof(PatchTypes<TYPE>)); } PatchTypes() { std::memset(this, 0, sizeof(PatchTypes<TYPE>)); }
// Returns the number of patches based on the patch type in the descriptor // Returns the number of patches based on the patch type in the descriptor
TYPE & getValue( Far::PatchDescriptor desc ) { TYPE & getValue( Far::PatchDescriptor desc ) {
switch (desc.GetType()) { switch (desc.GetType()) {
case Far::PatchDescriptor::REGULAR : return R[desc.GetPattern()]; case Far::PatchDescriptor::REGULAR : return R;
case Far::PatchDescriptor::SINGLE_CREASE : return S[desc.GetPattern()][desc.GetRotation()]; case Far::PatchDescriptor::SINGLE_CREASE : return S;
case Far::PatchDescriptor::BOUNDARY : return B[desc.GetPattern()][desc.GetRotation()]; case Far::PatchDescriptor::BOUNDARY : return B;
case Far::PatchDescriptor::CORNER : return C[desc.GetPattern()][desc.GetRotation()]; case Far::PatchDescriptor::CORNER : return C;
case Far::PatchDescriptor::GREGORY : return G; case Far::PatchDescriptor::GREGORY : return G;
case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB; case Far::PatchDescriptor::GREGORY_BOUNDARY : return GB;
case Far::PatchDescriptor::GREGORY_BASIS : return GP; case Far::PatchDescriptor::GREGORY_BASIS : return GP;
default : assert(0); default : assert(0);
} }
// can't be reached (suppress compiler warning) // can't be reached (suppress compiler warning)
return R[0]; return R;
} }
// Counts the number of arrays required to store each type of patch used // Counts the number of arrays required to store each type of patch used
// in the primitive // in the primitive
int getNumPatchArrays() const { int getNumPatchArrays() const {
int result=0; int result=0;
for (int i=0; i<6; ++i) { if (R) ++result;
if (S) ++result;
if (R[i]) ++result; if (B) ++result;
if (C) ++result;
for (int j=0; j<4; ++j) {
if (S[i][j]) ++result;
if (B[i][j]) ++result;
if (C[i][j]) ++result;
}
}
if (G) ++result; if (G) ++result;
if (GB) ++result; if (GB) ++result;
if (GP) ++result; if (GP) ++result;
@ -94,11 +85,7 @@ struct PatchTypes {
// Returns true if there's any single-crease patch // Returns true if there's any single-crease patch
bool hasSingleCreasedPatches() const { bool hasSingleCreasedPatches() const {
for (int i=0; i<6; ++i) { if (S) return true;
for (int j=0; j<4; ++j) {
if (S[i][j]) return true;
}
}
return false; return false;
} }
}; };
@ -127,25 +114,11 @@ typedef PatchTypes<Far::Index **> PatchFVarPointers;
// branching on the edges or vertices. // branching on the edges or vertices.
// //
struct PatchFaceTag { struct PatchFaceTag {
public:
// The HBR_ADAPTIVE TransitionType from <hbr/face.h> -- now named to more clearly
// reflect the number and orientation of transitional edges. Note that the values
// assigned here need to match the intended purpose to remain consistent with Hbr:
enum TransitionType {
NONE = 0,
TRANS_ONE = 1,
TRANS_TWO_ADJ = 2,
TRANS_THREE = 3,
TRANS_ALL = 4,
TRANS_TWO_OPP = 5
};
public: public:
unsigned int _hasPatch : 1; unsigned int _hasPatch : 1;
unsigned int _isRegular : 1; unsigned int _isRegular : 1;
unsigned int _isTransitional : 1; unsigned int _transitionMask : 4;
unsigned int _transitionType : 3; unsigned int _boundaryMask : 4;
unsigned int _transitionRot : 2;
unsigned int _boundaryIndex : 2; unsigned int _boundaryIndex : 2;
unsigned int _boundaryCount : 3; unsigned int _boundaryCount : 3;
unsigned int _hasBoundaryEdge : 3; unsigned int _hasBoundaryEdge : 3;
@ -166,6 +139,7 @@ public:
// it ourselves? // it ourselves?
// //
_hasBoundaryEdge = true; _hasBoundaryEdge = true;
_boundaryMask = boundaryEdgeMask;
switch (boundaryEdgeMask) { switch (boundaryEdgeMask) {
case 0x0: _boundaryCount = 0, _boundaryIndex = 0, _hasBoundaryEdge = false; break; // no boundaries case 0x0: _boundaryCount = 0, _boundaryIndex = 0, _hasBoundaryEdge = false; break; // no boundaries
@ -200,6 +174,7 @@ public:
// and assert for all other cases. // and assert for all other cases.
// //
assert(_hasBoundaryEdge == false); assert(_hasBoundaryEdge == false);
_boundaryMask = boundaryVertexMask;
switch (boundaryVertexMask) { switch (boundaryVertexMask) {
case 0x0: _boundaryCount = 0; break; // no boundaries case 0x0: _boundaryCount = 0; break; // no boundaries
@ -222,140 +197,8 @@ public:
} }
} }
void assignTransitionRotationForCorner(int transitionEdgeMask) {
//
// Corner transition patches have only two interior edges that may be transitional.
//
// Either both are transitional (TRANS_TWO_ADJ) with only a single possible orientation,
// or only one is transitional (TRANS_ONE) with two possibilities. The former case is
// trivial. For the latter, use the known corner index to identify one of the two
// possible transition masks and test to determine between the two cases.
//
if (_transitionType == TRANS_ONE) {
int const edgeMaskPerCorner[] = { 4, 8, 1, 2 };
_transitionRot = 1 + (edgeMaskPerCorner[_boundaryIndex] != transitionEdgeMask);
} else {
_transitionRot = 1;
}
}
void assignTransitionRotationForBoundary(int transitionEdgeMask) {
//
// Boundary transition patches have three interior edges that may be transitional.
//
// The case of all three transitional (TRANS_THREE) has only one orientation, while the
// case of two opposite transitional edges (TRANS_TWO_OPP) also has only one orientation.
// So both of these are trivially handled.
//
// The case of a single transitional edge (TRANS_ONE) or one transitional edge (TRANS_TWO_ADJ)
// both have multiple orientations -- three for TRANS_ONE and two for TRANS_TWO_ADJ. Each is
// handled separately:
//
if (_transitionType == TRANS_ONE) {
if (transitionEdgeMask == (1 << ((_boundaryIndex + 2) % 4))) {
_transitionRot = 2;
} else if (transitionEdgeMask == (1 << ((_boundaryIndex + 1) % 4))) {
_transitionRot = 1;
} else {
_transitionRot = 3;
}
// XXXX manuelk mirror this rotation to match shader idiosyncracies
_transitionRot = (4-_transitionRot)%4;
} else if (_transitionType == TRANS_TWO_ADJ) {
int const edgeMaskPerBoundary[] = { 6, 12, 9, 3 };
_transitionRot = 1 + (edgeMaskPerBoundary[_boundaryIndex] == transitionEdgeMask);
} else if (_transitionType == TRANS_THREE) {
_transitionRot = 0;
} else {
_transitionRot = 1;
}
}
void assignTransitionRotationForSingleCrease(int transitionEdgeMask) {
//
// Single crease transition patches.
//
// rotate edgemask by boundaryIndex to align the creased edge
//
transitionEdgeMask = ((transitionEdgeMask >> _boundaryIndex) |
(transitionEdgeMask << (4-_boundaryIndex))) % 16;
/*
edgemask type : rotation to match to shader
0000 0 : NONE : 0
0001 1 : ONE : 0
0010 2 : ONE : 3
0011 3 : TWO_ADJ : 3
0100 4 : ONE : 2
0101 5 : TWO_OPP : 0
0110 6 : TWO_ADJ : 2
0111 7 : THREE : 1 (needs verify)
1000 8 : ONE : 1
1001 9 : TWO_ADJ : 0
1010 10 : TWO_OPP : 1
1011 11 : THREE : 2 (needs verify)
1100 12 : TWO_ADJ : 1
1101 13 : THREE : 3
1110 14 : THREE : 0 (needs verify)
1111 15 : ALL : 0
*/
static int transitionRots[16] = {0, 0, 3, 3, 2, 0, 2, 1, 1, 0, 1, 2, 1, 3, 0, 0 };
_transitionRot = transitionRots[transitionEdgeMask];
}
void assignTransitionPropertiesFromEdgeMask(int transitionEdgeMask) { void assignTransitionPropertiesFromEdgeMask(int transitionEdgeMask) {
// _transitionMask = transitionEdgeMask;
// Note the transition rotations will be a function of the boundary rotations, and
// so boundary rotations/index should have been previously assigned:
//
// As with the boundary rotation case, consider retrieving values from static 16-
// entry lookup tables if possible (depending on the function involving boundary
// rotations)...
//
_isTransitional = (transitionEdgeMask != 0);
switch (transitionEdgeMask) {
case 0x0: _transitionType = NONE; break; // no transitions
case 0x1: _transitionType = TRANS_ONE; break; // single edge 0
case 0x2: _transitionType = TRANS_ONE; break; // single edge 1
case 0x3: _transitionType = TRANS_TWO_ADJ; break; // two adjacent edges, 0 and 1
case 0x4: _transitionType = TRANS_ONE; break; // single edge 2
case 0x5: _transitionType = TRANS_TWO_OPP; break; // two opposite edges, 0 and 2
case 0x6: _transitionType = TRANS_TWO_ADJ; break; // two adjacent edges, 1 and 2
case 0x7: _transitionType = TRANS_THREE; break; // three edges, all but 3
case 0x8: _transitionType = TRANS_ONE; break; // single edge 3
case 0x9: _transitionType = TRANS_TWO_ADJ; break; // two adjacent edges, 3 and 0
case 0xa: _transitionType = TRANS_TWO_OPP; break; // two opposite edges, 1 and 3
case 0xb: _transitionType = TRANS_THREE; break; // three edges, all but 2
case 0xc: _transitionType = TRANS_TWO_ADJ; break; // two adjacent edges, 2 and 3
case 0xd: _transitionType = TRANS_THREE; break; // three edges, all but 1
case 0xe: _transitionType = TRANS_THREE; break; // three edges, all but 0
case 0xf: _transitionType = TRANS_ALL; break; // all edges
default: assert(false); break;
}
// May need another switch/lookup table here or combine it with the above -- the
// results below are a function of both transition and boundary properties...
if (transitionEdgeMask == 0) {
_transitionRot = 0;
} else if (_boundaryCount == 0 and _isSingleCrease) {
assignTransitionRotationForSingleCrease(transitionEdgeMask);
} else if (_boundaryCount == 0) {
// XXXX manuelk Rotations are mostly a direct map of the transitionEdgeMask
// Except for:
// - TRANS_TWO_ADJ that has rotation { 1, 2, 0, 3 }
// - TRANS_THREE that has rotation { 3, 2, 1, 0 }
// (matching shader idiosyncracies)
static unsigned char transitionRots[16] = {0, 0, 1, 1, 2, 0, 2, 3, 3, 0, 1, 2, 3, 1, 0, 0};
_transitionRot = transitionRots[transitionEdgeMask];
} else if (_boundaryCount == 1) {
assignTransitionRotationForBoundary(transitionEdgeMask);
} else if (_boundaryCount == 2) {
assignTransitionRotationForCorner(transitionEdgeMask);
}
} }
}; };
@ -372,7 +215,11 @@ offsetAndPermuteIndices(Far::Index const indices[], int count,
if (permutation) { if (permutation) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
result[i] = offset + indices[permutation[i]]; if (permutation[i] < 0) { // XXXdyu-patch-drawing
result[i] = offset + indices[0]; // XXXdyu-patch-drawing
} else {
result[i] = offset + indices[permutation[i]];
}
} }
} else if (offset) { } else if (offset) {
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
@ -847,9 +694,9 @@ PatchTablesFactory::gatherFVarData(AdaptiveContext & context, int level,
// a pointer to the next descriptor // a pointer to the next descriptor
// //
PatchParam * PatchParam *
PatchTablesFactory::computePatchParam(TopologyRefiner const & refiner, PatchTablesFactory::computePatchParam(
int depth, Vtr::Index faceIndex, int rotation, TopologyRefiner const & refiner, int depth, Vtr::Index faceIndex,
PatchParam *coord) { int rotation, int boundaryMask, int transitionMask, PatchParam *coord) {
if (coord == NULL) return NULL; if (coord == NULL) return NULL;
@ -899,7 +746,11 @@ PatchTablesFactory::computePatchParam(TopologyRefiner const & refiner,
--depth; --depth;
} }
coord->Set(ptexIndex, (short)u, (short)v, (unsigned char) rotation, (unsigned char) depth, nonquad); boundaryMask = ((((boundaryMask << 4) | boundaryMask) >> rotation)) & 0xf;
transitionMask = ((((transitionMask << 4) | transitionMask) >> rotation)) & 0xf;
coord->Set(ptexIndex, (short)u, (short)v, (unsigned char) depth, nonquad,
(unsigned short) boundaryMask, (unsigned short) transitionMask);
return ++coord; return ++coord;
} }
@ -1102,7 +953,7 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
tables->reservePatchArrays(nlevels); tables->reservePatchArrays(nlevels);
PatchDescriptor desc(ptype, PatchDescriptor::NON_TRANSITION, 0); PatchDescriptor desc(ptype);
// generate patch arrays // generate patch arrays
for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) { for (int level=firstlevel, poffset=0, voffset=0; level<=maxlevel; ++level) {
@ -1170,7 +1021,7 @@ PatchTablesFactory::createUniform(TopologyRefiner const & refiner, Options optio
*iptr++ = levelVertOffset + fverts[vert]; *iptr++ = levelVertOffset + fverts[vert];
} }
pptr = computePatchParam(refiner, level, face, /*rot*/0, pptr); pptr = computePatchParam(refiner, level, face, /*rot*/0, /*boundary*/0, /*transition*/0, pptr);
if (generateFVarPatches) { if (generateFVarPatches) {
for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) { for (fvc=fvc.begin(); fvc!=fvc.end(); ++fvc) {
@ -1508,17 +1359,15 @@ PatchTablesFactory::identifyAdaptivePatches(AdaptiveContext & context) {
patchTag.assignTransitionPropertiesFromEdgeMask(refinedFaceTag._transitional); patchTag.assignTransitionPropertiesFromEdgeMask(refinedFaceTag._transitional);
if (patchTag._isRegular) { if (patchTag._isRegular) {
int transIndex = patchTag._transitionType;
int transRot = patchTag._transitionRot;
if (!patchTag._isSingleCrease and patchTag._boundaryCount == 0) { if (!patchTag._isSingleCrease and patchTag._boundaryCount == 0) {
context.patchInventory.R[transIndex]++; context.patchInventory.R++;
} else if (patchTag._isSingleCrease and patchTag._boundaryCount == 0) { } else if (patchTag._isSingleCrease and patchTag._boundaryCount == 0) {
context.patchInventory.S[transIndex][transRot]++; context.patchInventory.S++;
} else if (patchTag._boundaryCount == 1) { } else if (patchTag._boundaryCount == 1) {
context.patchInventory.B[transIndex][transRot]++; context.patchInventory.R++;
} else { } else {
context.patchInventory.C[transIndex][transRot]++; context.patchInventory.R++;
} }
} else { } else {
// if end-cap patches use a stencils-driven basis, we don't need // if end-cap patches use a stencils-driven basis, we don't need
@ -1679,21 +1528,21 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
if (patchTag._isRegular) { if (patchTag._isRegular) {
Index patchVerts[16]; Index patchVerts[16];
int tIndex = patchTag._transitionType;
int rIndex = patchTag._transitionRot;
int bIndex = patchTag._boundaryIndex; int bIndex = patchTag._boundaryIndex;
int boundaryMask = patchTag._boundaryMask;
int transitionMask = patchTag._transitionMask;
if (!patchTag._isSingleCrease and patchTag._boundaryCount == 0) { if (!patchTag._isSingleCrease and patchTag._boundaryCount == 0) {
int const permuteInterior[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 }; int const permuteInterior[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 };
level->gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, rIndex); level->gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, /*rotation*/0);
offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteInterior, iptrs.R[tIndex]); offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteInterior, iptrs.R);
iptrs.R[tIndex] += 16; iptrs.R += 16;
pptrs.R[tIndex] = computePatchParam(refiner, i, faceIndex, rIndex, pptrs.R[tIndex]); pptrs.R = computePatchParam(refiner, i, faceIndex, /*rotation*/0, /*boundary*/0, transitionMask, pptrs.R);
fofss.R[tIndex] += gatherFVarData(context, fofss.R += gatherFVarData(context,
i, faceIndex, levelFaceOffset, rIndex, levelFVarVertOffsets, fofss.R[tIndex], fptrs.R[tIndex]); i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R);
} else { } else {
// For the boundary and corner cases, the Hbr code makes some adjustments to the // For the boundary and corner cases, the Hbr code makes some adjustments to the
// rotations here from the way they were defined earlier. That raises questions // rotations here from the way they were defined earlier. That raises questions
@ -1717,42 +1566,42 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
if (patchTag._isSingleCrease and patchTag._boundaryCount==0) { if (patchTag._isSingleCrease and patchTag._boundaryCount==0) {
int const permuteInterior[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 }; int const permuteInterior[16] = { 5, 6, 7, 8, 4, 0, 1, 9, 15, 3, 2, 10, 14, 13, 12, 11 };
level->gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, bIndex); level->gatherQuadRegularInteriorPatchPoints(faceIndex, patchVerts, bIndex);
offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteInterior, iptrs.S[tIndex][rIndex]); offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteInterior, iptrs.S);
int creaseEdge = (bIndex+2)%4; int creaseEdge = (bIndex+2)%4;
float sharpness = level->getEdgeSharpness((level->getFaceEdges(faceIndex)[creaseEdge])); float sharpness = level->getEdgeSharpness((level->getFaceEdges(faceIndex)[creaseEdge]));
sharpness = std::min(sharpness, (float)(context.options.maxIsolationLevel-i)); sharpness = std::min(sharpness, (float)(context.options.maxIsolationLevel-i));
iptrs.S[tIndex][rIndex] += 16; iptrs.S += 16;
pptrs.S[tIndex][rIndex] = computePatchParam(refiner, i, faceIndex, bIndex, pptrs.S[tIndex][rIndex]); pptrs.S = computePatchParam(refiner, i, faceIndex, bIndex, /*boundary*/0, transitionMask, pptrs.S);
*sptrs.S[tIndex][rIndex]++ = assignSharpnessIndex(sharpness, tables->_sharpnessValues); *sptrs.S++ = assignSharpnessIndex(sharpness, tables->_sharpnessValues);
fofss.S[tIndex][rIndex] += gatherFVarData(context, fofss.S += gatherFVarData(context,
i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.S[tIndex][rIndex], fptrs.S[tIndex][rIndex]); i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.S, fptrs.S);
} else if (patchTag._boundaryCount == 1) { } else if (patchTag._boundaryCount == 1) {
int const permuteBoundary[12] = { 11, 3, 0, 4, 10, 2, 1, 5, 9, 8, 7, 6 }; int const permuteBoundary[16] = { -1, 4, 5, 6, -1, 0, 1, 7, -1, 3, 2, 8, -1, 11, 10, 9 };
level->gatherQuadRegularBoundaryPatchPoints(faceIndex, patchVerts, bIndex); level->gatherQuadRegularBoundaryPatchPoints(faceIndex, patchVerts, bIndex);
offsetAndPermuteIndices(patchVerts, 12, levelVertOffset, permuteBoundary, iptrs.B[tIndex][rIndex]); offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteBoundary, iptrs.R);
iptrs.B[tIndex][rIndex] += 12; bIndex = 3*((bIndex+1)&1);
pptrs.B[tIndex][rIndex] = computePatchParam(refiner, i, faceIndex, bIndex, pptrs.B[tIndex][rIndex]);
fofss.B[tIndex][rIndex] += gatherFVarData(context, iptrs.R += 16;
i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.B[tIndex][rIndex], fptrs.B[tIndex][rIndex]); pptrs.R = computePatchParam(refiner, i, faceIndex, bIndex, boundaryMask, transitionMask, pptrs.R);
fofss.R += gatherFVarData(context,
i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R);
} else { } else {
int const permuteCorner[9] = { 8, 3, 0, 7, 2, 1, 6, 5, 4 }; int const permuteCorner[16] = { -1, -1, -1, -1, -1, 0, 1, 4, -1, 3, 2, 5, -1, 8, 7, 6 };
level->gatherQuadRegularCornerPatchPoints(faceIndex, patchVerts, bIndex); level->gatherQuadRegularCornerPatchPoints(faceIndex, patchVerts, bIndex);
offsetAndPermuteIndices(patchVerts, 9, levelVertOffset, permuteCorner, iptrs.C[tIndex][rIndex]); offsetAndPermuteIndices(patchVerts, 16, levelVertOffset, permuteCorner, iptrs.R);
bIndex = (bIndex+3)%4; iptrs.R += 16;
pptrs.R = computePatchParam(refiner, i, faceIndex, bIndex, boundaryMask, transitionMask, pptrs.R);
iptrs.C[tIndex][rIndex] += 9; fofss.R += gatherFVarData(context,
pptrs.C[tIndex][rIndex] = computePatchParam(refiner, i, faceIndex, bIndex, pptrs.C[tIndex][rIndex]); i, faceIndex, levelFaceOffset, /*rotation*/0, levelFVarVertOffsets, fofss.R, fptrs.R);
fofss.C[tIndex][rIndex] += gatherFVarData(context,
i, faceIndex, levelFaceOffset, bIndex, levelFVarVertOffsets, fofss.C[tIndex][rIndex], fptrs.C[tIndex][rIndex]);
} }
} }
} else { } else {
@ -1779,7 +1628,7 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
++numGregoryBasisPatches; ++numGregoryBasisPatches;
pptrs.GP = computePatchParam(refiner, i, faceIndex, 0, pptrs.GP); pptrs.GP = computePatchParam(refiner, i, faceIndex, 0, /*boundary*/0, /*transition*/0, pptrs.GP);
fofss.GP += gatherFVarData(context, fofss.GP += gatherFVarData(context,
i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GP, fptrs.GP); i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GP, fptrs.GP);
@ -1796,7 +1645,7 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
getQuadOffsets(*level, faceIndex, quad_G_C0_P); getQuadOffsets(*level, faceIndex, quad_G_C0_P);
quad_G_C0_P += 4; quad_G_C0_P += 4;
pptrs.G = computePatchParam(refiner, i, faceIndex, 0, pptrs.G); pptrs.G = computePatchParam(refiner, i, faceIndex, 0, /*boundary*/0, /*transition*/0, pptrs.G);
fofss.G += gatherFVarData(context, fofss.G += gatherFVarData(context,
i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.G, fptrs.G); i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.G, fptrs.G);
@ -1814,7 +1663,7 @@ PatchTablesFactory::populateAdaptivePatches(AdaptiveContext & context) {
//int bIndex = (patchTag._boundaryIndex+1)%4; //int bIndex = (patchTag._boundaryIndex+1)%4;
pptrs.GB = computePatchParam(refiner, i, faceIndex, 0, pptrs.GB); pptrs.GB = computePatchParam(refiner, i, faceIndex, 0, /*boundary*/0, /*transition*/0, pptrs.GB);
fofss.GB += gatherFVarData(context, fofss.GB += gatherFVarData(context,
i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GB, fptrs.GB); i, faceIndex, levelFaceOffset, 0, levelFVarVertOffsets, fofss.GB, fptrs.GB);

View File

@ -126,7 +126,8 @@ private:
Options options, int npatches, PatchTables * tables); Options options, int npatches, PatchTables * tables);
static PatchParam * computePatchParam(TopologyRefiner const & refiner, static PatchParam * computePatchParam(TopologyRefiner const & refiner,
int level, int face, int rotation, PatchParam * coord); int level, int face, int rotation,
int boundaryMask, int transitionMask, PatchParam * coord);
static int gatherFVarData(AdaptiveContext & state, static int gatherFVarData(AdaptiveContext & state,
int level, Index faceIndex, Index levelFaceOffset, int rotation, Index const * levelOffsets, Index fofss, Index ** fptrs); int level, Index faceIndex, Index levelFaceOffset, int rotation, Index const * levelOffsets, Index fofss, Index ** fptrs);

View File

@ -84,122 +84,67 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig(
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str()); sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
} }
if (desc.GetPattern() == Far::PatchDescriptor::NON_TRANSITION) { switch (desc.GetType()) {
switch (desc.GetType()) { case Far::PatchDescriptor::REGULAR:
case Far::PatchDescriptor::REGULAR: case Far::PatchDescriptor::BOUNDARY:
sconfig->vertexShader.source = bsplineShaderSource; case Far::PatchDescriptor::CORNER:
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;
case Far::PatchDescriptor::SINGLE_CREASE:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->domainShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
break;
case Far::PatchDescriptor::BOUNDARY:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_BOUNDARY");
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;
case Far::PatchDescriptor::CORNER:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_CORNER");
sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;
case Far::PatchDescriptor::GREGORY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = gregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;
case Far::PatchDescriptor::GREGORY_BOUNDARY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->vertexShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->hullShader.source = gregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->domainShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
break;
default: // POINTS, LINES, QUADS, TRIANGLES
// do nothing
break;
}
} else { // pattern != NON_TRANSITION
sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.target = "vs_5_0"; sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches"; sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.source = sconfig->hullShader.source = bsplineShaderSource;
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->hullShader.target = "hs_5_0"; sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches"; sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_TRANSITION"); sconfig->domainShader.source = bsplineShaderSource;
sconfig->domainShader.source =
std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->domainShader.target = "ds_5_0"; sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches"; sconfig->domainShader.entry = "ds_main_patches";
sconfig->domainShader.AddDefine("OSD_PATCH_TRANSITION"); break;
case Far::PatchDescriptor::SINGLE_CREASE:
int pattern = desc.GetPattern() - 1; sconfig->commonShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
int rotation = desc.GetRotation(); sconfig->vertexShader.source = bsplineShaderSource;
int subpatch = desc.GetSubPatch(); sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
std::ostringstream ss; sconfig->hullShader.source = bsplineShaderSource;
ss << "OSD_TRANSITION_PATTERN" << pattern << subpatch; sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.AddDefine(ss.str()); sconfig->hullShader.entry = "hs_main_patches";
sconfig->domainShader.AddDefine(ss.str()); sconfig->hullShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
sconfig->domainShader.source = bsplineShaderSource;
ss.str(""); sconfig->domainShader.target = "ds_5_0";
ss << rotation; sconfig->domainShader.entry = "ds_main_patches";
sconfig->hullShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); sconfig->domainShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
sconfig->domainShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); break;
case Far::PatchDescriptor::GREGORY:
if (desc.GetType() == Far::PatchDescriptor::SINGLE_CREASE) { sconfig->commonShader.AddDefine("OSD_PATCH_GREGORY");
sconfig->hullShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); sconfig->vertexShader.source = gregoryShaderSource;
sconfig->domainShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); sconfig->vertexShader.target = "vs_5_0";
} else if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) { sconfig->vertexShader.entry = "vs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_BOUNDARY"); sconfig->hullShader.source = gregoryShaderSource;
} else if (desc.GetType() == Far::PatchDescriptor::CORNER) { sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.AddDefine("OSD_PATCH_CORNER"); sconfig->hullShader.entry = "hs_main_patches";
} sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
break;
case Far::PatchDescriptor::GREGORY_BOUNDARY:
sconfig->commonShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.target = "vs_5_0";
sconfig->vertexShader.entry = "vs_main_patches";
sconfig->vertexShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->hullShader.source = gregoryShaderSource;
sconfig->hullShader.target = "hs_5_0";
sconfig->hullShader.entry = "hs_main_patches";
sconfig->hullShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->domainShader.source = gregoryShaderSource;
sconfig->domainShader.target = "ds_5_0";
sconfig->domainShader.entry = "ds_main_patches";
sconfig->domainShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
break;
case Far::PatchDescriptor::GREGORY_BOUNDARY_BASIS:
// XXXdyu-patch-drawing gregory basis for d3d11
break;
default: // POINTS, LINES, QUADS, TRIANGLES
// do nothing
break;
} }
return sconfig; return sconfig;

View File

@ -39,37 +39,21 @@ void
DrawContext::ConvertPatchArrays(Far::PatchTables const &patchTables, DrawContext::ConvertPatchArrays(Far::PatchTables const &patchTables,
PatchArrayVector &osdPatchArrays, int maxValence, int numElements) { PatchArrayVector &osdPatchArrays, int maxValence, int numElements) {
// create patch arrays for drawing (while duplicating subpatches for transition patch arrays) int narrays = patchTables.GetNumPatchArrays();
static int subPatchCounts[] = { 1, 3, 4, 4, 4, 2 }; // number of subpatches for patterns
int numTotalPatchArrays = 0;
for (int array=0; array < patchTables.GetNumPatchArrays(); ++array) {
Far::PatchDescriptor::TransitionPattern pattern =
patchTables.GetPatchArrayDescriptor(array).GetPattern();
numTotalPatchArrays += subPatchCounts[(int)pattern];
}
// allocate drawing patch arrays // allocate drawing patch arrays
osdPatchArrays.clear(); osdPatchArrays.clear();
osdPatchArrays.reserve(numTotalPatchArrays); osdPatchArrays.reserve(narrays);
int narrays = patchTables.GetNumPatchArrays();
for (int array=0, pidx=0, vidx=0, qidx=0; array<narrays; ++array) { for (int array=0, pidx=0, vidx=0, qidx=0; array<narrays; ++array) {
Far::PatchDescriptor srcDesc = patchTables.GetPatchArrayDescriptor(array); Far::PatchDescriptor srcDesc = patchTables.GetPatchArrayDescriptor(array);
int npatches = patchTables.GetNumPatches(array), int npatches = patchTables.GetNumPatches(array),
nsubpatches = subPatchCounts[(int)srcDesc.GetPattern()],
nverts = srcDesc.GetNumControlVertices(); nverts = srcDesc.GetNumControlVertices();
for (int i = 0; i < nsubpatches; ++i) { PatchDescriptor desc(srcDesc, maxValence, numElements);
osdPatchArrays.push_back(PatchArray(desc, npatches, vidx, pidx, qidx));
PatchDescriptor desc(srcDesc, maxValence, i, numElements);
osdPatchArrays.push_back(PatchArray(desc, npatches, vidx, pidx, qidx));
}
vidx += npatches * nverts; vidx += npatches * nverts;
pidx += npatches; pidx += npatches;

View File

@ -68,17 +68,11 @@ public:
/// ///
/// @param maxValence Highest vertex valence in the primitive /// @param maxValence Highest vertex valence in the primitive
/// ///
/// @param subPatch Index of the triangulated sub-patch for the given
/// transition pattern. Transition patches need to be
/// split into multiple sub-patches in order to be
/// rendered with hardware tessellation.
///
/// @param numElements The size of the vertex and varying data per-vertex /// @param numElements The size of the vertex and varying data per-vertex
/// (in floats) /// (in floats)
/// ///
PatchDescriptor(Far::PatchDescriptor farDesc, unsigned char maxValence, PatchDescriptor(Far::PatchDescriptor farDesc, unsigned char maxValence, unsigned char numElements) :
unsigned char subPatch, unsigned char numElements) : _farDesc(farDesc), _maxValence(maxValence), _numElements(numElements) { }
_farDesc(farDesc), _maxValence(maxValence), _subPatch(subPatch), _numElements(numElements) { }
/// Returns the type of the patch /// Returns the type of the patch
@ -86,16 +80,6 @@ public:
return _farDesc.GetType(); return _farDesc.GetType();
} }
/// Returns the transition pattern of the patch if any (5 types)
Far::PatchDescriptor::TransitionPattern GetPattern() const {
return _farDesc.GetPattern();
}
/// Returns the rotation of the patch (4 rotations)
unsigned char GetRotation() const {
return _farDesc.GetRotation();
}
/// Returns the number of control vertices expected for a patch of the /// Returns the number of control vertices expected for a patch of the
/// type described /// type described
int GetNumControlVertices() const { int GetNumControlVertices() const {
@ -107,11 +91,6 @@ public:
return _maxValence; return _maxValence;
} }
/// Returns the subpatch id
int GetSubPatch() const {
return _subPatch;
}
/// Returns the number of vertex elements /// Returns the number of vertex elements
int GetNumElements() const { int GetNumElements() const {
return _numElements; return _numElements;
@ -131,7 +110,6 @@ public:
private: private:
Far::PatchDescriptor _farDesc; Far::PatchDescriptor _farDesc;
unsigned char _maxValence; unsigned char _maxValence;
unsigned char _subPatch;
unsigned char _numElements; unsigned char _numElements;
}; };
@ -261,9 +239,8 @@ inline bool
DrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const DrawContext::PatchDescriptor::operator < ( PatchDescriptor const other ) const
{ {
return _farDesc < other._farDesc or (_farDesc == other._farDesc and return _farDesc < other._farDesc or (_farDesc == other._farDesc and
(_subPatch < other._subPatch or ((_subPatch == other._subPatch) and
(_maxValence < other._maxValence or ((_maxValence == other._maxValence) and (_maxValence < other._maxValence or ((_maxValence == other._maxValence) and
(_numElements < other._numElements)))))); (_numElements < other._numElements))));
} }
// True if the descriptors are identical // True if the descriptors are identical
@ -271,7 +248,6 @@ inline bool
DrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const DrawContext::PatchDescriptor::operator == ( PatchDescriptor const other ) const
{ {
return _farDesc == other._farDesc and return _farDesc == other._farDesc and
_subPatch == other._subPatch and
_maxValence == other._maxValence and _maxValence == other._maxValence and
_numElements == other._numElements; _numElements == other._numElements;
} }

View File

@ -84,133 +84,77 @@ GLDrawRegistryBase::_CreateDrawSourceConfig(
sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str()); sconfig->commonShader.AddDefine("OSD_NUM_ELEMENTS", ss.str());
} }
if (desc.GetPattern() == Far::PatchDescriptor::NON_TRANSITION) { switch (desc.GetType()) {
switch (desc.GetType()) { case Far::PatchDescriptor::REGULAR:
case Far::PatchDescriptor::REGULAR: case Far::PatchDescriptor::BOUNDARY:
sconfig->vertexShader.source = bsplineShaderSource; case Far::PatchDescriptor::CORNER:
sconfig->vertexShader.version = "#version 410\n"; sconfig->commonShader.AddDefine("OSD_PATCH_BSPLINE");
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source = bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessEvalShader.source = bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
break;
case Far::PatchDescriptor::SINGLE_CREASE:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source = bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
sconfig->tessEvalShader.source = bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
sconfig->tessEvalShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
break;
case Far::PatchDescriptor::BOUNDARY:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source = bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_BOUNDARY");
sconfig->tessEvalShader.source = bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
break;
case Far::PatchDescriptor::CORNER:
sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source = bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_CORNER");
sconfig->tessEvalShader.source = bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
break;
case Far::PatchDescriptor::GREGORY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER");
sconfig->tessControlShader.source = gregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_SHADER");
sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
break;
case Far::PatchDescriptor::GREGORY_BOUNDARY:
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER");
sconfig->vertexShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->tessControlShader.source = gregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
sconfig->tessEvalShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
break;
case Far::PatchDescriptor::GREGORY_BASIS:
sconfig->vertexShader.source = gregoryBasisShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER");
sconfig->tessControlShader.source = gregoryBasisShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER");
sconfig->tessEvalShader.source = gregoryBasisShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER");
break;
default: // POINTS, LINES, QUADS, TRIANGLES
// do nothing
break;
}
} else { // pattern != NON_TRANSITION
sconfig->vertexShader.source = bsplineShaderSource; sconfig->vertexShader.source = bsplineShaderSource;
sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER"); sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
sconfig->tessControlShader.source = sconfig->tessControlShader.source =
std::string(transitionShaderSource) + bsplineShaderSource; std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->tessControlShader.version = "#version 410\n"; sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER"); sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_TRANSITION");
sconfig->tessEvalShader.source = sconfig->tessEvalShader.source =
std::string(transitionShaderSource) + bsplineShaderSource; std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->tessEvalShader.version = "#version 410\n"; sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER"); sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TRANSITION"); break;
case Far::PatchDescriptor::SINGLE_CREASE:
int pattern = desc.GetPattern() - 1; sconfig->commonShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
int rotation = desc.GetRotation(); sconfig->vertexShader.source = bsplineShaderSource;
int subpatch = desc.GetSubPatch(); sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_BSPLINE_SHADER");
std::ostringstream ss; sconfig->tessControlShader.source =
ss << "OSD_TRANSITION_PATTERN" << pattern << subpatch; std::string(transitionShaderSource) + bsplineShaderSource;
sconfig->tessControlShader.AddDefine(ss.str()); sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine(ss.str()); sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER");
sconfig->tessEvalShader.source =
ss.str(""); std::string(transitionShaderSource) + bsplineShaderSource;
ss << rotation; sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_BSPLINE_SHADER");
sconfig->tessEvalShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str()); sconfig->tessEvalShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
case Far::PatchDescriptor::GREGORY:
if (desc.GetType() == Far::PatchDescriptor::SINGLE_CREASE) { sconfig->commonShader.AddDefine("OSD_PATCH_GREGORY");
sconfig->tessControlShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); sconfig->vertexShader.source = gregoryShaderSource;
sconfig->tessEvalShader.AddDefine("OSD_PATCH_SINGLE_CREASE"); sconfig->vertexShader.version = "#version 410\n";
} else if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) { sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_BOUNDARY"); sconfig->tessControlShader.source = gregoryShaderSource;
} else if (desc.GetType() == Far::PatchDescriptor::CORNER) { sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_CORNER"); sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_SHADER");
} sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
break;
case Far::PatchDescriptor::GREGORY_BOUNDARY:
sconfig->commonShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->vertexShader.source = gregoryShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_SHADER");
sconfig->tessControlShader.source = gregoryShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_SHADER");
sconfig->tessControlShader.AddDefine("OSD_PATCH_GREGORY_BOUNDARY");
sconfig->tessEvalShader.source = gregoryShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_SHADER");
break;
case Far::PatchDescriptor::GREGORY_BASIS:
sconfig->commonShader.AddDefine("OSD_PATCH_GREGORY_BASIS");
sconfig->vertexShader.source = gregoryBasisShaderSource;
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.AddDefine("OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER");
sconfig->tessControlShader.source = gregoryBasisShaderSource;
sconfig->tessControlShader.version = "#version 410\n";
sconfig->tessControlShader.AddDefine("OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER");
sconfig->tessEvalShader.source = gregoryBasisShaderSource;
sconfig->tessEvalShader.version = "#version 410\n";
sconfig->tessEvalShader.AddDefine("OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER");
break;
default: // POINTS, LINES, QUADS, TRIANGLES
// do nothing
break;
} }
return sconfig; return sconfig;

View File

@ -65,14 +65,6 @@ uniform mat4 Mi = mat4(
0.f, 0.f, 1.f, 0.f 0.f, 0.f, 1.f, 0.f
); );
// Boundary / Corner
uniform mat4x3 B = mat4x3(
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
);
layout(vertices = 16) out; layout(vertices = 16) out;
in block { in block {
@ -92,6 +84,35 @@ out block {
#define ID gl_InvocationID #define ID gl_InvocationID
void
reflectBoundaryEdges(inout vec3 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 // compute single-crease patch matrix
mat4 mat4
ComputeMatrixSimplified(float sharpness) ComputeMatrixSimplified(float sharpness)
@ -117,44 +138,20 @@ void main()
int i = ID%4; int i = ID%4;
int j = ID/4; int j = ID/4;
#if defined OSD_PATCH_BOUNDARY vec3 position[24];
vec3 H[3]; for (int i=0; i<16; ++i) {
for (int l=0; l<3; ++l) { position[i] = inpt[i].v.position.xyz;
H[l] = vec3(0,0,0);
for (int k=0; k<4; ++k) {
H[l] += Q[i][k] * inpt[l*4 + k].v.position.xyz;
}
} }
vec3 pos = vec3(0,0,0); int patchParam = GetPatchParam();
for (int k=0; k<3; ++k) {
pos += B[j][k]*H[k];
}
outpt[ID].v.position = vec4(pos, 1.0); reflectBoundaryEdges(position, patchParam);
#elif defined OSD_PATCH_CORNER
vec3 H[3];
for (int l=0; l<3; ++l) {
H[l] = vec3(0,0,0);
for (int k=0; k<3; ++k) {
H[l] += B[3-i][2-k] * inpt[l*3 + k].v.position.xyz;
}
}
vec3 pos = vec3(0,0,0);
for (int k=0; k<3; ++k) {
pos += B[j][k]*H[k];
}
outpt[ID].v.position = vec4(pos, 1.0);
#else // not OSD_PATCH_BOUNDARY, not OSD_PATCH_CORNER
vec3 H[4]; vec3 H[4];
for (int l=0; l<4; ++l) { for (int l=0; l<4; ++l) {
H[l] = vec3(0,0,0); H[l] = vec3(0,0,0);
for (int k=0; k<4; ++k) { for (int k=0; k<4; ++k) {
H[l] += Q[i][k] * inpt[l*4 + k].v.position.xyz; H[l] += Q[i][k] * position[l*4 + k].xyz;
} }
} }
@ -189,28 +186,7 @@ void main()
outpt[ID].v.position = vec4(pos, 1.0); outpt[ID].v.position = vec4(pos, 1.0);
#endif #endif
#endif OSD_USER_VARYING_PER_CONTROL_POINT(ID, ID);
#if defined OSD_PATCH_BOUNDARY
const int p[16] = int[]( 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] = int[]( 0, 1, 2, 2, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8 );
#else
const int p[16] = int[]( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
#endif
#if OSD_TRANSITION_ROTATE == 0
const int r[16] = int[]( 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] = int[]( 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] = int[]( 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] = int[]( 3, 7, 11, 15, 2, 6, 10, 14, 1, 5, 9, 13, 0, 4, 8, 12 );
#endif
OSD_USER_VARYING_PER_CONTROL_POINT(ID, p[r[ID]]);
int patchLevel = GetPatchLevel(); int patchLevel = GetPatchLevel();
@ -224,35 +200,17 @@ void main()
if (ID == 0) { if (ID == 0) {
OSD_PATCH_CULL(OSD_PATCH_INPUT_SIZE); OSD_PATCH_CULL(OSD_PATCH_INPUT_SIZE);
#ifdef OSD_PATCH_TRANSITION vec4 outerLevel = vec4(0);
vec3 cp[OSD_PATCH_INPUT_SIZE]; vec2 innerLevel = vec2(0);
for(int k = 0; k < OSD_PATCH_INPUT_SIZE; ++k) cp[k] = inpt[k].v.position.xyz; GetTransitionTessLevels(position, patchParam, outerLevel, innerLevel);
SetTransitionTessLevels(cp, patchLevel);
#else
#if defined OSD_PATCH_BOUNDARY
const int p[4] = int[]( 1, 2, 5, 6 );
#elif defined OSD_PATCH_CORNER
const int p[4] = int[]( 1, 2, 4, 5 );
#else
const int p[4] = int[]( 5, 6, 9, 10 );
#endif
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION gl_TessLevelOuter[0] = outerLevel[0];
gl_TessLevelOuter[0] = TessAdaptive(inpt[p[0]].v.position.xyz, inpt[p[2]].v.position.xyz); gl_TessLevelOuter[1] = outerLevel[1];
gl_TessLevelOuter[1] = TessAdaptive(inpt[p[0]].v.position.xyz, inpt[p[1]].v.position.xyz); gl_TessLevelOuter[2] = outerLevel[2];
gl_TessLevelOuter[2] = TessAdaptive(inpt[p[1]].v.position.xyz, inpt[p[3]].v.position.xyz); gl_TessLevelOuter[3] = outerLevel[3];
gl_TessLevelOuter[3] = TessAdaptive(inpt[p[2]].v.position.xyz, inpt[p[3]].v.position.xyz);
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]); gl_TessLevelInner[0] = innerLevel[0];
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]); gl_TessLevelInner[1] = innerLevel[1];
#else
gl_TessLevelInner[0] = GetTessLevel(patchLevel);
gl_TessLevelInner[1] = GetTessLevel(patchLevel);
gl_TessLevelOuter[0] = GetTessLevel(patchLevel);
gl_TessLevelOuter[1] = GetTessLevel(patchLevel);
gl_TessLevelOuter[2] = GetTessLevel(patchLevel);
gl_TessLevelOuter[3] = GetTessLevel(patchLevel);
#endif
#endif
} }
} }
@ -269,11 +227,13 @@ void main()
layout(quads) in; layout(quads) in;
#endif #endif
/* XXXdyu-patch-drawing support for frational spacing
#if defined OSD_FRACTIONAL_ODD_SPACING #if defined OSD_FRACTIONAL_ODD_SPACING
layout(fractional_odd_spacing) in; layout(fractional_odd_spacing) in;
#elif defined OSD_FRACTIONAL_EVEN_SPACING #elif defined OSD_FRACTIONAL_EVEN_SPACING
layout(fractional_even_spacing) in; layout(fractional_even_spacing) in;
#endif #endif
*/
in block { in block {
ControlVertex v; ControlVertex v;
@ -292,11 +252,7 @@ out block {
void main() void main()
{ {
#ifdef OSD_PATCH_TRANSITION vec2 UV = GetTransitionParameterization();
vec2 UV = GetTransitionSubpatchUV();
#else
vec2 UV = gl_TessCoord.xy;
#endif
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES #ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
float B[4], D[4], C[4]; float B[4], D[4], C[4];
@ -340,15 +296,7 @@ void main()
inpt[k].P2.xyz); inpt[k].P2.xyz);
#else // !SINGLE_CREASE #else // !SINGLE_CREASE
#if OSD_TRANSITION_ROTATE == 1
vec3 A = inpt[4*(3-j) + i].v.position.xyz;
#elif OSD_TRANSITION_ROTATE == 2
vec3 A = inpt[4*(3-i) + (3-j)].v.position.xyz;
#elif OSD_TRANSITION_ROTATE == 3
vec3 A = inpt[4*j + (3-i)].v.position.xyz;
#else // OSD_TRANSITION_ROTATE == 0, or non-transition patch
vec3 A = inpt[4*i + j].v.position.xyz; vec3 A = inpt[4*i + j].v.position.xyz;
#endif
#endif #endif
BUCP[i] += A * B[j]; BUCP[i] += A * B[j];
DUCP[i] += A * D[j]; DUCP[i] += A * D[j];
@ -403,7 +351,10 @@ void main()
Nu = Nu/length(n) - n * (dot(Nu,n)/pow(dot(n,n), 1.5)); 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)); Nv = Nv/length(n) - n * (dot(Nv,n)/pow(dot(n,n), 1.5));
OSD_COMPUTE_PTEX_COMPATIBLE_DERIVATIVES(OSD_TRANSITION_ROTATE); outpt.v.tangent = Tangent;
outpt.v.bitangent = BiTangent;
outpt.v.Nu = Nu;
outpt.v.Nv = Nv;
#else #else
Univar4x4(UV.y, B, D); Univar4x4(UV.y, B, D);
@ -418,7 +369,8 @@ void main()
vec3 normal = normalize(cross(Tangent, BiTangent)); vec3 normal = normalize(cross(Tangent, BiTangent));
OSD_COMPUTE_PTEX_COMPATIBLE_TANGENT(OSD_TRANSITION_ROTATE); outpt.v.tangent = Tangent;
outpt.v.bitangent = BiTangent;
#endif #endif
outpt.v.position = vec4(WorldPos, 1.0f); outpt.v.position = vec4(WorldPos, 1.0f);
@ -428,15 +380,7 @@ void main()
outpt.v.patchCoord = inpt[0].v.patchCoord; outpt.v.patchCoord = inpt[0].v.patchCoord;
#if OSD_TRANSITION_ROTATE == 1
outpt.v.patchCoord.xy = vec2(UV.y, 1.0-UV.x);
#elif OSD_TRANSITION_ROTATE == 2
outpt.v.patchCoord.xy = vec2(1.0-UV.x, 1.0-UV.y);
#elif OSD_TRANSITION_ROTATE == 3
outpt.v.patchCoord.xy = vec2(1.0-UV.y, UV.x);
#else // OSD_TRANNSITION_ROTATE == 0, or non-transition patch
outpt.v.patchCoord.xy = vec2(UV.x, UV.y); outpt.v.patchCoord.xy = vec2(UV.x, UV.y);
#endif
OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER; OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER;

View File

@ -183,10 +183,13 @@ float TessAdaptive(vec3 p0, vec3 p1)
uniform isamplerBuffer OsdPatchParamBuffer; uniform isamplerBuffer OsdPatchParamBuffer;
#define GetPatchParam() \
(texelFetch(OsdPatchParamBuffer, GetPrimitiveID()).y)
#define GetPatchLevel() \ #define GetPatchLevel() \
(texelFetch(OsdPatchParamBuffer, GetPrimitiveID()).y & 0xf) (texelFetch(OsdPatchParamBuffer, GetPrimitiveID()).y & 0xf)
#define GetSharpness() \ #define GetSharpness() \
(intBitsToFloat(texelFetch(OsdPatchParamBuffer, GetPrimitiveID()).z)) (intBitsToFloat(texelFetch(OsdPatchParamBuffer, GetPrimitiveID()).z))
#define OSD_COMPUTE_PTEX_COORD_TESSCONTROL_SHADER \ #define OSD_COMPUTE_PTEX_COORD_TESSCONTROL_SHADER \
@ -194,12 +197,11 @@ uniform isamplerBuffer OsdPatchParamBuffer;
ivec2 ptexIndex = texelFetch(OsdPatchParamBuffer, \ ivec2 ptexIndex = texelFetch(OsdPatchParamBuffer, \
GetPrimitiveID()).xy; \ GetPrimitiveID()).xy; \
int faceID = ptexIndex.x; \ int faceID = ptexIndex.x; \
int lv = 1 << ((ptexIndex.y & 0xf) - ((ptexIndex.y >> 4) & 1)); \ int lv = 1 << ((ptexIndex.y & 0x7) - ((ptexIndex.y >> 3) & 1)); \
int u = (ptexIndex.y >> 17) & 0x3ff; \ int u = (ptexIndex.y >> 22) & 0x3ff; \
int v = (ptexIndex.y >> 7) & 0x3ff; \ int v = (ptexIndex.y >> 12) & 0x3ff; \
int rotation = (ptexIndex.y >> 5) & 0x3; \
outpt[ID].v.patchCoord.w = faceID+0.5; \ outpt[ID].v.patchCoord.w = faceID+0.5; \
outpt[ID].v.ptexInfo = ivec4(u, v, lv, rotation); \ outpt[ID].v.ptexInfo = ivec4(u, v, lv, 0); \
} }
#define OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER \ #define OSD_COMPUTE_PTEX_COORD_TESSEVAL_SHADER \
@ -207,57 +209,8 @@ uniform isamplerBuffer OsdPatchParamBuffer;
vec2 uv = outpt.v.patchCoord.xy; \ vec2 uv = outpt.v.patchCoord.xy; \
ivec2 p = inpt[0].v.ptexInfo.xy; \ ivec2 p = inpt[0].v.ptexInfo.xy; \
int lv = inpt[0].v.ptexInfo.z; \ int lv = inpt[0].v.ptexInfo.z; \
int rot = inpt[0].v.ptexInfo.w; \
outpt.v.tessCoord.xy = uv; \ outpt.v.tessCoord.xy = uv; \
uv.xy = float(rot==0)*uv.xy \ outpt.v.patchCoord.xy = (uv * vec2(1.0)/lv) + vec2(p.x, p.y)/lv;\
+ float(rot==1)*vec2(1.0-uv.y, uv.x) \
+ float(rot==2)*vec2(1.0-uv.x, 1.0-uv.y) \
+ float(rot==3)*vec2(uv.y, 1.0-uv.x); \
outpt.v.patchCoord.xy = (uv * vec2(1.0)/lv) + vec2(p.x, p.y)/lv; \
}
#define OSD_COMPUTE_PTEX_COMPATIBLE_TANGENT(ROTATE) \
{ \
int rot = (inpt[0].v.ptexInfo.w + 4 - ROTATE)%4; \
if (rot == 1) { \
outpt.v.tangent = -BiTangent; \
outpt.v.bitangent = Tangent; \
} else if (rot == 2) { \
outpt.v.tangent = -Tangent; \
outpt.v.bitangent = -BiTangent; \
} else if (rot == 3) { \
outpt.v.tangent = BiTangent; \
outpt.v.bitangent = -Tangent; \
} else { \
outpt.v.tangent = Tangent; \
outpt.v.bitangent = BiTangent; \
} \
}
#define OSD_COMPUTE_PTEX_COMPATIBLE_DERIVATIVES(ROTATE) \
{ \
int rot = (inpt[0].v.ptexInfo.w + 4 - ROTATE)%4; \
if (rot == 1) { \
outpt.v.tangent = -BiTangent; \
outpt.v.bitangent = Tangent; \
outpt.v.Nu = -Nv; \
outpt.v.Nv = Nv; \
} else if (rot == 2) { \
outpt.v.tangent = -Tangent; \
outpt.v.bitangent = -BiTangent; \
outpt.v.Nu = -Nu; \
outpt.v.Nv = -Nv; \
} else if (rot == 3) { \
outpt.v.tangent = BiTangent; \
outpt.v.bitangent = -Tangent; \
outpt.v.Nu = Nv; \
outpt.v.Nv = -Nu; \
} else { \
outpt.v.tangent = Tangent; \
outpt.v.bitangent = BiTangent; \
outpt.v.Nu = Nu; \
outpt.v.Nv = Nv; \
} \
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -441,11 +441,13 @@ void main()
layout(quads) in; layout(quads) in;
layout(cw) in; layout(cw) in;
/* XXXdyu-patch-drawing support for frational spacing
#if defined OSD_FRACTIONAL_ODD_SPACING #if defined OSD_FRACTIONAL_ODD_SPACING
layout(fractional_odd_spacing) in; layout(fractional_odd_spacing) in;
#elif defined OSD_FRACTIONAL_EVEN_SPACING #elif defined OSD_FRACTIONAL_EVEN_SPACING
layout(fractional_even_spacing) in; layout(fractional_even_spacing) in;
#endif #endif
*/
in block { in block {
GregEvalVertex v; GregEvalVertex v;

View File

@ -119,11 +119,13 @@ void main()
layout(quads) in; layout(quads) in;
layout(cw) in; layout(cw) in;
/* XXXdyu-patch-drawing support for frational spacing
#if defined OSD_FRACTIONAL_ODD_SPACING #if defined OSD_FRACTIONAL_ODD_SPACING
layout(fractional_odd_spacing) in; layout(fractional_odd_spacing) in;
#elif defined OSD_FRACTIONAL_EVEN_SPACING #elif defined OSD_FRACTIONAL_EVEN_SPACING
layout(fractional_even_spacing) in; layout(fractional_even_spacing) in;
#endif #endif
*/
in block { in block {
ControlVertex v; ControlVertex v;

View File

@ -22,431 +22,85 @@
// language governing permissions and limitations under the Apache License. // 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
//---------------------------------------------------------- //----------------------------------------------------------
// Patches.TessControlTransition // Patches.TessControlTransition
//---------------------------------------------------------- //----------------------------------------------------------
#ifdef OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER #ifdef OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER
void patch out vec4 tessOuterLo, tessOuterHi;
SetTransitionTessLevels(vec3 cp[OSD_PATCH_INPUT_SIZE], int patchLevel)
float
TessAdaptiveRound(vec3 p0, vec3 p1)
{ {
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION return round(TessAdaptive(p0, p1));
// 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] = int[]( 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] = int[]( 0, 1, 2, 2, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8 );
#else
const int p[16] = int[]( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
#endif
#if OSD_TRANSITION_ROTATE == 0 void
const int r[16] = int[]( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); GetTransitionTessLevels(vec3 cp[24], int patchParam, inout vec4 outer, inout vec2 inner)
#elif OSD_TRANSITION_ROTATE == 1 {
const int r[16] = int[]( 12, 8, 4, 0, 13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3 ); // Each edge of a transition patch is adjacent to one or two patches
#elif OSD_TRANSITION_ROTATE == 2 // at the next refined level of subdivision. We compute the corresponding
const int r[16] = int[]( 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ); // vertex-vertex and edge-vertex refined points along the edges of the
#elif OSD_TRANSITION_ROTATE == 3 // patch using Catmull-Clark subdivision stencil weights.
const int r[16] = int[]( 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
vec3 pv0 = cp[p[r[0]]];
vec3 pv1 = cp[p[r[1]]];
vec3 pv2 = cp[p[r[2]]];
vec3 pv3 = cp[p[r[3]]];
vec3 pv4 = cp[p[r[4]]];
vec3 pv5 = cp[p[r[5]]];
vec3 pv6 = cp[p[r[6]]];
vec3 pv7 = cp[p[r[7]]];
vec3 pv8 = cp[p[r[8]]];
vec3 pv9 = cp[p[r[9]]];
vec3 pv10 = cp[p[r[10]]];
vec3 pv11 = cp[p[r[11]]];
vec3 pv12 = cp[p[r[12]]];
vec3 pv13 = cp[p[r[13]]];
vec3 pv14 = cp[p[r[14]]];
vec3 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. // For simplicity, we let the optimizer discard unused computation.
vec3 vv0 = (pv0 + pv2 + pv8 + pv10) * 0.015625 + cp[16] = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
(pv1 + pv4 + pv6 + pv9) * 0.09375 + pv5 * 0.5625; (cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
vec3 ev01 = (pv1 + pv2 + pv9 + pv10) * 0.0625 + (pv5 + pv6) * 0.375; cp[17] = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 + (cp[5] + cp[6]) * 0.375;
vec3 vv1 = (pv1 + pv3 + pv9 + pv11) * 0.015625 + cp[18] = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
(pv2 + pv5 + pv7 + pv10) * 0.09375 + pv6 * 0.5625; (cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
vec3 ev12 = (pv5 + pv7 + pv9 + pv11) * 0.0625 + (pv6 + pv10) * 0.375; cp[19] = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 + (cp[6] + cp[10]) * 0.375;
vec3 vv2 = (pv5 + pv7 + pv13 + pv15) * 0.015625 + cp[20] = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
(pv6 + pv9 + pv11 + pv14) * 0.09375 + pv10 * 0.5625; (cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
vec3 ev23 = (pv5 + pv6 + pv13 + pv14) * 0.0625 + (pv9 + pv10) * 0.375; cp[21] = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 + (cp[9] + cp[10]) * 0.375;
vec3 vv3 = (pv4 + pv6 + pv12 + pv14) * 0.015625 + cp[22] = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
(pv5 + pv8 + pv10 + pv13) * 0.09375 + pv9 * 0.5625; (cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
vec3 ev30 = (pv4 + pv6 + pv8 + pv10) * 0.0625 + (pv5 + pv9) * 0.375; cp[23] = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 + (cp[5] + cp[9]) * 0.375;
// The vertices along boundaries and at corners are refined specially. tessOuterLo = vec4(1);
#if defined OSD_PATCH_BOUNDARY tessOuterHi = vec4(0);
#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());
// XXX: current rotation of single-crease patch is inconsistent #ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION
// to boundary patch. should be fixed. float tessAmount = GetTessLevel(GetPatchLevel());
#if OSD_TRANSITION_ROTATE == 2
vv0 = mix(vv0, (pv4 + pv6) * 0.125 + pv5 * 0.75, weight); if (((patchParam >> 11) & 1) != 0) {
vv1 = mix(vv1, (pv5 + pv7) * 0.125 + pv6 * 0.75, weight); tessOuterLo[0] = TessAdaptiveRound(cp[23], cp[16]);
#elif OSD_TRANSITION_ROTATE == 3 tessOuterHi[0] = TessAdaptiveRound(cp[22], cp[23]);
vv1 = mix(vv1, (pv2 + pv10) * 0.125 + pv6 * 0.75, weight); } else {
vv2 = mix(vv2, (pv6 + pv14) * 0.125 + pv10 * 0.75, weight); tessOuterLo[0] = TessAdaptiveRound(cp[5], cp[9]);
#elif OSD_TRANSITION_ROTATE == 0 }
vv2 = mix(vv2, (pv9 + pv11) * 0.125 + pv10 * 0.75, weight); if (((patchParam >> 8) & 1) != 0) {
vv3 = mix(vv3, (pv8 + pv10) * 0.125 + pv9 * 0.75, weight); tessOuterLo[1] = TessAdaptiveRound(cp[16], cp[17]);
#elif OSD_TRANSITION_ROTATE == 1 tessOuterHi[1] = TessAdaptiveRound(cp[17], cp[18]);
vv3 = mix(vv3, (pv5 + pv13) * 0.125 + pv9 * 0.75, weight); } else {
vv0 = mix(vv0, (pv1 + pv9) * 0.125 + pv5 * 0.75, weight); 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
float tessAmount = GetTessLevel(GetPatchLevel());
tessOuterLo[0] = tessAmount;
tessOuterLo[1] = tessAmount;
tessOuterLo[2] = tessAmount;
tessOuterLo[3] = tessAmount;
#endif #endif
#endif outer = tessOuterLo + tessOuterHi;
inner[0] = (outer[0] + outer[2]) * 0.5;
inner[1] = (outer[1] + outer[3]) * 0.5;
#ifdef OSD_TRANSITION_PATTERN00
gl_TessLevelOuter[0] = TessAdaptive(ev01, pv9) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev01, pv10) * 0.5;
gl_TessLevelOuter[2] = TessAdaptive(pv9, pv10);
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN01
gl_TessLevelOuter[0] = TessAdaptive(ev01, vv1);
gl_TessLevelOuter[1] = TessAdaptive(pv6, pv10);
gl_TessLevelOuter[2] = TessAdaptive(ev01, pv10) * 0.5;
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN02
gl_TessLevelOuter[0] = TessAdaptive(ev01, vv0);
gl_TessLevelOuter[1] = TessAdaptive(ev01, pv9) * 0.5;
gl_TessLevelOuter[2] = TessAdaptive(pv5, pv9);
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN10
gl_TessLevelOuter[0] = TessAdaptive(pv6, pv10);
gl_TessLevelOuter[1] = TessAdaptive(ev01, pv10);
gl_TessLevelOuter[2] = TessAdaptive(ev01, vv1);
gl_TessLevelInner[0] = (gl_TessLevelOuter[0] + gl_TessLevelOuter[1]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN11
gl_TessLevelOuter[0] = TessAdaptive(pv9, pv10);
gl_TessLevelOuter[1] = TessAdaptive(ev30, vv3);
gl_TessLevelOuter[2] = TessAdaptive(ev30, pv10);
gl_TessLevelInner[0] = (gl_TessLevelOuter[0] + gl_TessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN12
gl_TessLevelOuter[0] = TessAdaptive(ev30, vv0);
gl_TessLevelOuter[1] = TessAdaptive(ev01, vv0);
gl_TessLevelOuter[2] = TessAdaptive(ev01, ev30);
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN13
gl_TessLevelOuter[0] = TessAdaptive(ev01, pv10);
gl_TessLevelOuter[1] = TessAdaptive(ev30, pv10);
gl_TessLevelOuter[2] = TessAdaptive(ev01, ev30);
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.25;
#endif
#ifdef OSD_TRANSITION_PATTERN20
gl_TessLevelOuter[0] = TessAdaptive(pv5, pv6);
gl_TessLevelOuter[1] = TessAdaptive(ev12, vv1);
gl_TessLevelOuter[2] = TessAdaptive(ev12, ev30);
gl_TessLevelOuter[3] = TessAdaptive(ev30, vv0);
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN21
gl_TessLevelOuter[0] = TessAdaptive(ev23, ev30) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev23, vv3);
gl_TessLevelOuter[2] = TessAdaptive(ev30, vv3);
gl_TessLevelInner[0] = (gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN22
gl_TessLevelOuter[0] = TessAdaptive(ev12, vv2);
gl_TessLevelOuter[1] = TessAdaptive(ev23, vv2);
gl_TessLevelOuter[2] = TessAdaptive(ev12, ev23) * 0.5;
gl_TessLevelInner[0] = (gl_TessLevelOuter[0] + gl_TessLevelOuter[1]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN23
gl_TessLevelOuter[0] = TessAdaptive(ev12, ev30);
gl_TessLevelOuter[1] = TessAdaptive(ev12, ev23) * 0.5;
gl_TessLevelOuter[2] = TessAdaptive(ev23, ev30) * 0.5;
gl_TessLevelInner[0] =
(gl_TessLevelOuter[0] + gl_TessLevelOuter[1] + gl_TessLevelOuter[2]) * 0.5;
#endif
#ifdef OSD_TRANSITION_PATTERN30
gl_TessLevelOuter[0] = TessAdaptive(ev30, ev12) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev30, vv0);
gl_TessLevelOuter[2] = TessAdaptive(ev01, vv0);
gl_TessLevelOuter[3] = TessAdaptive(ev01, ev23) * 0.5;
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN31
gl_TessLevelOuter[0] = TessAdaptive(ev01, ev23) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev23, vv3);
gl_TessLevelOuter[2] = TessAdaptive(ev30, vv3);
gl_TessLevelOuter[3] = TessAdaptive(ev30, ev12) * 0.5;
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN32
gl_TessLevelOuter[0] = TessAdaptive(ev23, ev01) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev01, vv1);
gl_TessLevelOuter[2] = TessAdaptive(ev12, vv1);
gl_TessLevelOuter[3] = TessAdaptive(ev12, ev30) * 0.5;
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN33
gl_TessLevelOuter[0] = TessAdaptive(ev12, ev30) * 0.5;
gl_TessLevelOuter[1] = TessAdaptive(ev12, vv2);
gl_TessLevelOuter[2] = TessAdaptive(ev23, vv2);
gl_TessLevelOuter[3] = TessAdaptive(ev01, ev23) * 0.5;
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN40
gl_TessLevelOuter[0] = TessAdaptive(ev01, vv0);
gl_TessLevelOuter[1] = TessAdaptive(ev01, ev23);
gl_TessLevelOuter[2] = TessAdaptive(ev23, vv3);
gl_TessLevelOuter[3] = TessAdaptive(pv5, pv9);
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#ifdef OSD_TRANSITION_PATTERN41
gl_TessLevelOuter[0] = TessAdaptive(ev01, vv1);
gl_TessLevelOuter[1] = TessAdaptive(pv6, pv10);
gl_TessLevelOuter[2] = TessAdaptive(ev23, vv2);
gl_TessLevelOuter[3] = TessAdaptive(ev01, ev23);
gl_TessLevelInner[0] = max(gl_TessLevelOuter[1], gl_TessLevelOuter[3]);
gl_TessLevelInner[1] = max(gl_TessLevelOuter[0], gl_TessLevelOuter[2]);
#endif
#else // OSD_ENABLE_SCREENSPACE_TESSELLATION
float TessAmount = GetTessLevel(patchLevel);
#ifdef OSD_TRANSITION_PATTERN00
float side = sqrt(1.25)*TessAmount;
gl_TessLevelOuter[0] = side;
gl_TessLevelOuter[1] = side;
gl_TessLevelOuter[2] = TessAmount;
gl_TessLevelInner[0] = TessAmount;
#endif
#ifdef OSD_TRANSITION_PATTERN01
float side = sqrt(1.25)*TessAmount;
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = TessAmount;
gl_TessLevelOuter[2] = side;
gl_TessLevelInner[0] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN02
float side = sqrt(1.25)*TessAmount;
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = side;
gl_TessLevelOuter[2] = TessAmount;
gl_TessLevelInner[0] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN10
float side = sqrt(1.25) * TessAmount;
gl_TessLevelOuter[0] = TessAmount;
gl_TessLevelOuter[1] = side;
gl_TessLevelOuter[2] = TessAmount/2.0;
gl_TessLevelInner[0] = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN11
float side = sqrt(1.25) * TessAmount;
gl_TessLevelOuter[0] = TessAmount;
gl_TessLevelOuter[1] = TessAmount/2.0;
gl_TessLevelOuter[2] = side;
gl_TessLevelInner[0] = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN12
float side = sqrt(0.125) * TessAmount;
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = TessAmount/2.0;
gl_TessLevelOuter[2] = side;
gl_TessLevelInner[0] = TessAmount/2;
#endif
#ifdef OSD_TRANSITION_PATTERN13
float side1 = sqrt(1.25) * TessAmount;
float side2 = sqrt(0.125) * TessAmount;
gl_TessLevelOuter[0] = side1;
gl_TessLevelOuter[1] = side1;
gl_TessLevelOuter[2] = side2;
gl_TessLevelInner[0] = TessAmount/2.0*1.414;
#endif
#ifdef OSD_TRANSITION_PATTERN20
gl_TessLevelOuter[0] = TessAmount;
gl_TessLevelOuter[1] = TessAmount/2.0;
gl_TessLevelOuter[2] = TessAmount;
gl_TessLevelOuter[3] = TessAmount/2.0;
gl_TessLevelInner[0] = TessAmount/2.0;
gl_TessLevelInner[1] = TessAmount;
#endif
#ifdef OSD_TRANSITION_PATTERN21
float side = sqrt(0.125) * TessAmount;
gl_TessLevelOuter[0] = side;
gl_TessLevelOuter[1] = TessAmount/2.0;
gl_TessLevelOuter[2] = TessAmount/2.0;
gl_TessLevelInner[0] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN22
float side = sqrt(0.125) * TessAmount;
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = TessAmount/2.0;
gl_TessLevelOuter[2] = side;
gl_TessLevelInner[0] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN23
float side = sqrt(0.125) * TessAmount;
gl_TessLevelOuter[0] = TessAmount;
gl_TessLevelOuter[1] = side;
gl_TessLevelOuter[2] = side;
gl_TessLevelInner[0] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN30
gl_TessLevelOuter[0] = gl_TessLevelOuter[1] =
gl_TessLevelOuter[2] = gl_TessLevelOuter[3] = TessAmount/2.0;
gl_TessLevelInner[0] = gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN31
gl_TessLevelOuter[0] = gl_TessLevelOuter[1] =
gl_TessLevelOuter[2] = gl_TessLevelOuter[3] = TessAmount/2.0;
gl_TessLevelInner[0] = gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN32
gl_TessLevelOuter[0] = gl_TessLevelOuter[1] =
gl_TessLevelOuter[2] = gl_TessLevelOuter[3] = TessAmount/2.0;
gl_TessLevelInner[0] = gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN33
gl_TessLevelOuter[0] = gl_TessLevelOuter[1] =
gl_TessLevelOuter[2] = gl_TessLevelOuter[3] = TessAmount/2.0;
gl_TessLevelInner[0] = gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN40
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = TessAmount;
gl_TessLevelOuter[2] = TessAmount/2.0;
gl_TessLevelOuter[3] = TessAmount;
gl_TessLevelInner[0] = TessAmount;
gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#ifdef OSD_TRANSITION_PATTERN41
gl_TessLevelOuter[0] = TessAmount/2.0;
gl_TessLevelOuter[1] = TessAmount;
gl_TessLevelOuter[2] = TessAmount/2.0;
gl_TessLevelOuter[3] = TessAmount;
gl_TessLevelInner[0] = TessAmount;
gl_TessLevelInner[1] = TessAmount/2.0;
#endif
#endif // OSD_ENABLE_SCREENSPACE_TESSELLATION
} }
#endif #endif
@ -456,142 +110,37 @@ SetTransitionTessLevels(vec3 cp[OSD_PATCH_INPUT_SIZE], int patchLevel)
//---------------------------------------------------------- //----------------------------------------------------------
#ifdef OSD_PATCH_TESS_EVAL_BSPLINE_SHADER #ifdef OSD_PATCH_TESS_EVAL_BSPLINE_SHADER
vec2 patch in vec4 tessOuterLo, tessOuterHi;
GetTransitionSubpatchUV()
float
GetTransitionSplit(float t, float n0, float n1)
{ {
#ifdef OSD_TRANSITION_TRIANGLE_SUBPATCH float n = round(n0 + n1);
vec3 uvw = gl_TessCoord.xyz; float ti = round(t * n);
#else
vec2 uv = gl_TessCoord.xy;
#endif
vec2 UV = vec2(0, 0);
// OSD_TRANSITION_PATTERN0* if (ti <= n0) {
// +-------------+ return 0.5 * (ti / n0);
// | /\\ | } else {
// | 1 / \\ 2 | return 0.5 * ((ti - n0) / n1) + 0.5;
// | / \\ | }
// | / \\ | }
// | / 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
vec2
GetTransitionParameterization()
{
vec2 UV = gl_TessCoord.xy;
if (UV.x == 0 && tessOuterHi[0] > 0) {
UV.y = GetTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
} else
if (UV.y == 0 && tessOuterHi[1] > 0) {
UV.x = GetTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
} else
if (UV.x == 1 && tessOuterHi[2] > 0) {
UV.y = GetTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
} else
if (UV.y == 1 && tessOuterHi[3] > 0) {
UV.x = GetTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
}
return UV; return UV;
} }