mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-23 20:20:09 +00:00
Merge pull request #1041 from davidgyu/loop_patches_gl_drawing
Thanks, David!
This commit is contained in:
commit
1c35aa435a
@ -63,7 +63,8 @@ enum DisplayStyle { kWire = 0,
|
||||
kShaded,
|
||||
kWireShaded };
|
||||
|
||||
enum EndCap { kEndCapBSplineBasis,
|
||||
enum EndCap { kEndCapBilinearBasis,
|
||||
kEndCapBSplineBasis,
|
||||
kEndCapGregoryBasis };
|
||||
|
||||
int g_currentShape = 0;
|
||||
@ -109,7 +110,7 @@ std::vector<float> g_orgPositions,
|
||||
|
||||
Scheme g_scheme;
|
||||
|
||||
int g_endCap = kEndCapBSplineBasis;
|
||||
int g_endCap = kEndCapGregoryBasis;
|
||||
int g_level = 2;
|
||||
int g_tessLevel = 1;
|
||||
int g_tessLevelMin = 1;
|
||||
@ -435,13 +436,11 @@ rebuildMesh() {
|
||||
|
||||
g_scheme = scheme;
|
||||
|
||||
// Adaptive refinement currently supported only for catmull-clark scheme
|
||||
bool doAdaptive = (g_adaptive!=0 && g_scheme==kCatmark);
|
||||
|
||||
OpenSubdiv::Osd::MeshBitset bits;
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, g_adaptive != 0);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarAdaptive, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapBilinearBasis, g_endCap == kEndCapBilinearBasis);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
|
||||
@ -580,7 +579,9 @@ public:
|
||||
|
||||
if (type == Far::PatchDescriptor::QUADS) {
|
||||
ss << "#define PRIM_QUAD\n";
|
||||
} else if (type == Far::PatchDescriptor::TRIANGLES) {
|
||||
} else if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define PRIM_TRI\n";
|
||||
ss << "#define LOOP\n";
|
||||
} else {
|
||||
@ -1133,7 +1134,10 @@ initHUD() {
|
||||
|
||||
int endcap_pulldown = g_hud.AddPullDown("End cap (E)", 10, 140, 200,
|
||||
callbackEndCap, 'e');
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "BSpline",
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "Linear",
|
||||
kEndCapBilinearBasis,
|
||||
g_endCap == kEndCapBilinearBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "Regular",
|
||||
kEndCapBSplineBasis,
|
||||
g_endCap == kEndCapBSplineBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
|
||||
@ -1228,7 +1232,9 @@ parseIntArg(const char* argString, int dfltValue = 0) {
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
bool fullscreen = false;
|
||||
Scheme defaultScheme = kCatmark;
|
||||
std::string str;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "-d")) {
|
||||
if (++i < argc) g_level = parseIntArg(argv[i], g_level);
|
||||
@ -1236,6 +1242,12 @@ int main(int argc, char ** argv) {
|
||||
if (++i < argc) g_repeatCount = parseIntArg(argv[i], g_repeatCount);
|
||||
} else if (!strcmp(argv[i], "-f")) {
|
||||
fullscreen = true;
|
||||
} else if (!strcmp(argv[i], "-bilinear")) {
|
||||
defaultScheme = kBilinear;
|
||||
} else if (!strcmp(argv[i], "-catmark")) {
|
||||
defaultScheme = kCatmark;
|
||||
} else if (!strcmp(argv[i], "-loop")) {
|
||||
defaultScheme = kLoop;
|
||||
} else if (argv[i][0] == '-') {
|
||||
printf("Warning: unrecognized option '%s' ignored\n", argv[i]);
|
||||
} else {
|
||||
@ -1245,7 +1257,7 @@ int main(int argc, char ** argv) {
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
str = ss.str();
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[i], str.c_str(), kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[i], str.c_str(), defaultScheme));
|
||||
} else {
|
||||
printf("Warning: cannot open shape file '%s'\n", argv[i]);
|
||||
}
|
||||
|
@ -298,6 +298,8 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
// create Far mesh (topology)
|
||||
OpenSubdiv::Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
OpenSubdiv::Sdc::Split sdcsplit =
|
||||
Sdc::SchemeTypeTraits::GetTopologicalSplitType(sdctype);
|
||||
|
||||
OpenSubdiv::Far::TopologyRefiner * refiner =
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
@ -357,8 +359,15 @@ createMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
larray.t = vPtr;
|
||||
|
||||
for (int j=0; j<g_nsamples; ++j, ++uPtr, ++vPtr) {
|
||||
*uPtr = (float)rand()/(float)RAND_MAX;
|
||||
*vPtr = (float)rand()/(float)RAND_MAX;
|
||||
float u = (float)rand()/(float)RAND_MAX;
|
||||
float v = (float)rand()/(float)RAND_MAX;
|
||||
if (sdcsplit == Sdc::SPLIT_TO_TRIS && (u+v >= 1.0f)) {
|
||||
// Keep locations within the triangular parametric domain
|
||||
u = 1.0f - u;
|
||||
v = 1.0f - v;
|
||||
}
|
||||
*uPtr = u;
|
||||
*vPtr = v;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1052,21 +1061,36 @@ callbackErrorGLFW(int error, const char* description) {
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
bool fullscreen = false;
|
||||
|
||||
Scheme defaultScheme = kCatmark;
|
||||
std::string str;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "-u")) {
|
||||
g_adaptive = false;
|
||||
}
|
||||
if (!strcmp(argv[i], "-d")) {
|
||||
g_isolationLevel = atoi(argv[++i]);
|
||||
} else if (!strcmp(argv[i], "-f")) {
|
||||
}
|
||||
else if (!strcmp(argv[i], "-f")) {
|
||||
fullscreen = true;
|
||||
} else {
|
||||
}
|
||||
else if (!strcmp(argv[i], "-bilinear")) {
|
||||
defaultScheme = kBilinear;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-catmark")) {
|
||||
defaultScheme = kCatmark;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-loop")) {
|
||||
defaultScheme = kLoop;
|
||||
}
|
||||
else {
|
||||
std::ifstream ifs(argv[1]);
|
||||
if (ifs) {
|
||||
std::stringstream ss;
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
str = ss.str();
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[1], str.c_str(), kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[1], str.c_str(), defaultScheme));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,10 +144,11 @@ enum ShadingMode { kShadingMaterial,
|
||||
kShadingInterleavedVaryingColor,
|
||||
kShadingFaceVaryingColor,
|
||||
kShadingPatchType,
|
||||
kShadingPatchDepth,
|
||||
kShadingPatchCoord,
|
||||
kShadingNormal };
|
||||
|
||||
enum EndCap { kEndCapNone = 0,
|
||||
enum EndCap { kEndCapBilinearBasis = 0,
|
||||
kEndCapBSplineBasis,
|
||||
kEndCapGregoryBasis,
|
||||
kEndCapLegacyGregory };
|
||||
@ -189,10 +190,10 @@ int g_fullscreen = 0,
|
||||
g_mbutton[3] = {0, 0, 0},
|
||||
g_running = 1;
|
||||
|
||||
int g_screenSpaceTess = 1,
|
||||
g_fractionalSpacing = 1,
|
||||
int g_screenSpaceTess = 0,
|
||||
g_fractionalSpacing = 0,
|
||||
g_patchCull = 0,
|
||||
g_displayPatchCounts = 1;
|
||||
g_displayPatchCounts = 0;
|
||||
|
||||
float g_rotate[2] = {0, 0},
|
||||
g_dolly = 5,
|
||||
@ -394,7 +395,7 @@ updateGeom() {
|
||||
static const char *
|
||||
getKernelName(int kernel) {
|
||||
|
||||
if (kernel == kCPU)
|
||||
if (kernel == kCPU)
|
||||
return "CPU";
|
||||
else if (kernel == kOPENMP)
|
||||
return "OpenMP";
|
||||
@ -420,7 +421,6 @@ rebuildMesh() {
|
||||
int level = g_level;
|
||||
int kernel = g_kernel;
|
||||
bool doAnim = g_objAnim && g_currentShape==0;
|
||||
Scheme scheme = shapeDesc.scheme;
|
||||
|
||||
Shape const * shape = 0;
|
||||
if (doAnim) {
|
||||
@ -446,27 +446,21 @@ rebuildMesh() {
|
||||
delete g_mesh;
|
||||
g_mesh = NULL;
|
||||
|
||||
// Adaptive refinement currently supported only for catmull-clark scheme
|
||||
bool doAdaptive = (g_adaptive!=0 && scheme==kCatmark);
|
||||
bool interleaveVarying = g_shadingMode == kShadingInterleavedVaryingColor;
|
||||
bool doSmoothCornerPatch = (g_smoothCornerPatch!=0 && scheme==kCatmark);
|
||||
bool doSingleCreasePatch = (g_singleCreasePatch!=0 && scheme==kCatmark);
|
||||
bool doInfSharpPatch = (g_infSharpPatch!=0 && scheme==kCatmark);
|
||||
|
||||
Osd::MeshBitset bits;
|
||||
bits.set(Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(Osd::MeshUseSmoothCornerPatch, doSmoothCornerPatch);
|
||||
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
||||
bits.set(Osd::MeshUseInfSharpPatch, doInfSharpPatch);
|
||||
bits.set(Osd::MeshInterleaveVarying, interleaveVarying);
|
||||
bits.set(Osd::MeshFVarData, g_shadingMode == kShadingFaceVaryingColor);
|
||||
bits.set(Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
bits.set(Osd::MeshEndCapLegacyGregory, g_endCap == kEndCapLegacyGregory);
|
||||
bits.set(Osd::MeshAdaptive, g_adaptive != 0);
|
||||
bits.set(Osd::MeshUseSmoothCornerPatch, g_smoothCornerPatch != 0);
|
||||
bits.set(Osd::MeshUseSingleCreasePatch, g_singleCreasePatch != 0);
|
||||
bits.set(Osd::MeshUseInfSharpPatch, g_infSharpPatch != 0);
|
||||
bits.set(Osd::MeshInterleaveVarying, g_shadingMode == kShadingInterleavedVaryingColor);
|
||||
bits.set(Osd::MeshFVarData, g_shadingMode == kShadingFaceVaryingColor);
|
||||
bits.set(Osd::MeshEndCapBilinearBasis, g_endCap == kEndCapBilinearBasis);
|
||||
bits.set(Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
bits.set(Osd::MeshEndCapLegacyGregory, g_endCap == kEndCapLegacyGregory);
|
||||
|
||||
int numVertexElements = 3;
|
||||
int numVaryingElements =
|
||||
(g_shadingMode == kShadingVaryingColor || interleaveVarying) ? 4 : 0;
|
||||
(g_shadingMode == kShadingVaryingColor || bits.test(Osd::MeshInterleaveVarying)) ? 4 : 0;
|
||||
|
||||
|
||||
if (kernel == kCPU) {
|
||||
@ -732,7 +726,8 @@ public:
|
||||
if (effectDesc.effect.patchCull) {
|
||||
ss << "#define OSD_ENABLE_PATCH_CULL\n";
|
||||
}
|
||||
if (effectDesc.effect.singleCreasePatch) {
|
||||
if (effectDesc.effect.singleCreasePatch &&
|
||||
type == Far::PatchDescriptor::REGULAR) {
|
||||
ss << "#define OSD_PATCH_ENABLE_SINGLE_CREASE\n";
|
||||
}
|
||||
// for legacy gregory
|
||||
@ -773,6 +768,9 @@ public:
|
||||
case kShadingPatchType:
|
||||
ss << "#define SHADING_PATCH_TYPE\n";
|
||||
break;
|
||||
case kShadingPatchDepth:
|
||||
ss << "#define SHADING_PATCH_DEPTH\n";
|
||||
break;
|
||||
case kShadingPatchCoord:
|
||||
ss << "#define SHADING_PATCH_COORD\n";
|
||||
break;
|
||||
@ -781,10 +779,13 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == Far::PatchDescriptor::TRIANGLES) {
|
||||
if (type == Far::PatchDescriptor::TRIANGLES ||
|
||||
type == Far::PatchDescriptor::LOOP ||
|
||||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define LOOP\n";
|
||||
} else if (type == Far::PatchDescriptor::QUADS) {
|
||||
} else {
|
||||
}
|
||||
if (type != Far::PatchDescriptor::TRIANGLES &&
|
||||
type != Far::PatchDescriptor::QUADS) {
|
||||
ss << "#define SMOOTH_NORMALS\n";
|
||||
}
|
||||
|
||||
@ -795,6 +796,10 @@ public:
|
||||
ss << "#define OSD_PATCH_GREGORY_BOUNDARY\n";
|
||||
} else if (type == Far::PatchDescriptor::GREGORY_BASIS) {
|
||||
ss << "#define OSD_PATCH_GREGORY_BASIS\n";
|
||||
} else if (type == Far::PatchDescriptor::LOOP) {
|
||||
ss << "#define OSD_PATCH_LOOP\n";
|
||||
} else if (type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n";
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
@ -1193,18 +1198,24 @@ display() {
|
||||
double fps = 1.0/elapsed;
|
||||
|
||||
if (g_displayPatchCounts) {
|
||||
int x = -280;
|
||||
int x = -420;
|
||||
int y = -180;
|
||||
g_hud.DrawString(x, y, "NonPatch : %d",
|
||||
g_hud.DrawString(x, y, "Quads : %d",
|
||||
patchCount[Descriptor::QUADS]); y += 20;
|
||||
g_hud.DrawString(x, y, "Triangles : %d",
|
||||
patchCount[Descriptor::TRIANGLES]); y += 20;
|
||||
g_hud.DrawString(x, y, "Regular : %d",
|
||||
patchCount[Descriptor::REGULAR]); y+= 20;
|
||||
g_hud.DrawString(x, y, "Loop : %d",
|
||||
patchCount[Descriptor::LOOP]); y+= 20;
|
||||
g_hud.DrawString(x, y, "Gregory : %d",
|
||||
patchCount[Descriptor::GREGORY]); y+= 20;
|
||||
g_hud.DrawString(x, y, "Boundary Gregory : %d",
|
||||
g_hud.DrawString(x, y, "Gregory Boundary : %d",
|
||||
patchCount[Descriptor::GREGORY_BOUNDARY]); y+= 20;
|
||||
g_hud.DrawString(x, y, "Gregory Basis : %d",
|
||||
patchCount[Descriptor::GREGORY_BASIS]); y+= 20;
|
||||
g_hud.DrawString(x, y, "Gregory Triangle : %d",
|
||||
patchCount[Descriptor::GREGORY_TRIANGLE]); y+= 20;
|
||||
}
|
||||
|
||||
int y = -220;
|
||||
@ -1515,6 +1526,9 @@ initHUD() {
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Patch Type",
|
||||
kShadingPatchType,
|
||||
g_shadingMode == kShadingPatchType);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Patch Depth",
|
||||
kShadingPatchDepth,
|
||||
g_shadingMode == kShadingPatchDepth);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Patch Coord",
|
||||
kShadingPatchCoord,
|
||||
g_shadingMode == kShadingPatchCoord);
|
||||
@ -1558,13 +1572,13 @@ initHUD() {
|
||||
|
||||
int endcap_pulldown = g_hud.AddPullDown(
|
||||
"End cap (E)", 10, 270, 200, callbackEndCap, 'e');
|
||||
g_hud.AddPullDownButton(endcap_pulldown,"None",
|
||||
kEndCapNone,
|
||||
g_endCap == kEndCapNone);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "BSpline",
|
||||
g_hud.AddPullDownButton(endcap_pulldown,"Linear",
|
||||
kEndCapBilinearBasis,
|
||||
g_endCap == kEndCapBilinearBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "Regular",
|
||||
kEndCapBSplineBasis,
|
||||
g_endCap == kEndCapBSplineBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "Gregory",
|
||||
kEndCapGregoryBasis,
|
||||
g_endCap == kEndCapGregoryBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "LegacyGregory",
|
||||
@ -1575,7 +1589,7 @@ initHUD() {
|
||||
for (int i = 1; i < 11; ++i) {
|
||||
char level[16];
|
||||
sprintf(level, "Lv. %d", i);
|
||||
g_hud.AddRadioButton(3, level, i==2, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
||||
g_hud.AddRadioButton(3, level, i == g_level, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
||||
}
|
||||
|
||||
int shapes_pulldown = g_hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n');
|
||||
@ -1583,7 +1597,7 @@ initHUD() {
|
||||
g_hud.AddPullDownButton(shapes_pulldown, g_defaultShapes[i].name.c_str(),i);
|
||||
}
|
||||
|
||||
g_hud.AddCheckBox("Show patch counts", g_displayPatchCounts!=0, -280, -20, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_COUNTS);
|
||||
g_hud.AddCheckBox("Show patch counts", g_displayPatchCounts!=0, -420, -20, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_COUNTS);
|
||||
|
||||
g_hud.Rebuild(windowWidth, windowHeight, frameBufferWidth, frameBufferHeight);
|
||||
}
|
||||
@ -1629,9 +1643,11 @@ callbackErrorGLFW(int error, const char* description) {
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
bool fullscreen = false;
|
||||
Scheme defaultScheme = kCatmark;
|
||||
std::string str;
|
||||
std::vector<char const *> animobjs;
|
||||
|
||||
@ -1642,15 +1658,27 @@ int main(int argc, char ** argv) {
|
||||
else if (!strcmp(argv[i], "-axis")) {
|
||||
g_axis = false;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-u")) {
|
||||
g_adaptive = false;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-d")) {
|
||||
g_level = atoi(argv[++i]);
|
||||
if (++i < argc) g_level = atoi(argv[i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-c")) {
|
||||
g_repeatCount = atoi(argv[++i]);
|
||||
if (++i < argc) g_repeatCount = atoi(argv[i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-f")) {
|
||||
fullscreen = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-bilinear")) {
|
||||
defaultScheme = kBilinear;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-catmark")) {
|
||||
defaultScheme = kCatmark;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-loop")) {
|
||||
defaultScheme = kLoop;
|
||||
}
|
||||
else {
|
||||
std::ifstream ifs(argv[1]);
|
||||
if (ifs) {
|
||||
@ -1658,16 +1686,16 @@ int main(int argc, char ** argv) {
|
||||
ss << ifs.rdbuf();
|
||||
ifs.close();
|
||||
str = ss.str();
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[1], str.c_str(), kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc(argv[1], str.c_str(), defaultScheme));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! animobjs.empty()) {
|
||||
|
||||
g_defaultShapes.push_back(ShapeDesc(animobjs[0], "", kCatmark));
|
||||
g_defaultShapes.push_back(ShapeDesc(animobjs[0], "", defaultScheme));
|
||||
|
||||
g_objAnim = ObjAnim::Create(animobjs, g_axis);
|
||||
g_objAnim = ObjAnim::Create(animobjs, g_axis, defaultScheme);
|
||||
}
|
||||
|
||||
initShapes();
|
||||
@ -1744,7 +1772,9 @@ int main(int argc, char ** argv) {
|
||||
#endif
|
||||
|
||||
// activate feature adaptive tessellation if OSD supports it
|
||||
g_adaptive = GLUtils::SupportsAdaptiveTessellation();
|
||||
if (g_adaptive) {
|
||||
g_adaptive = GLUtils::SupportsAdaptiveTessellation();
|
||||
}
|
||||
|
||||
initGL();
|
||||
|
||||
|
@ -44,12 +44,20 @@
|
||||
outpt.color = \
|
||||
mix(mix(inpt[a].color, inpt[b].color, UV.x), \
|
||||
mix(inpt[c].color, inpt[d].color, UV.x), UV.y)
|
||||
|
||||
#undef OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c) \
|
||||
outpt.color = \
|
||||
inpt[a].color * (1.0f - UV.x - UV.y) + \
|
||||
inpt[b].color * UV.x + \
|
||||
inpt[c].color * UV.y;
|
||||
#else
|
||||
#define OSD_USER_VARYING_DECLARE
|
||||
#define OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
#define OSD_USER_VARYING_PER_VERTEX()
|
||||
#define OSD_USER_VARYING_PER_CONTROL_POINT(ID_OUT, ID_IN)
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT(UV, a, b, c, d)
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------
|
||||
@ -171,6 +179,38 @@ out block {
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
vec2
|
||||
interpolateFaceVarying(vec2 uv, int fvarOffset)
|
||||
{
|
||||
int patchIndex = OsdGetPatchIndex(gl_PrimitiveID);
|
||||
|
||||
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
|
||||
#ifdef LOOP
|
||||
int patchType = OSD_PATCH_DESCRIPTOR_TRIANGLES;
|
||||
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
|
||||
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
|
||||
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
#else
|
||||
int patchType = OSD_PATCH_DESCRIPTOR_QUADS;
|
||||
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
|
||||
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
|
||||
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
|
||||
#endif
|
||||
int patchArrayStride = numPoints;
|
||||
|
||||
int primOffset = patchIndex * patchArrayStride;
|
||||
|
||||
vec2 result = vec2(0);
|
||||
for (int i=0; i<numPoints; ++i) {
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset;
|
||||
vec2 cv = vec2(texelFetch(OsdFVarDataBuffer, index).s,
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s);
|
||||
result += wP[i] * cv;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void emit(int index, vec3 normal)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
@ -191,8 +231,14 @@ void emit(int index, vec3 normal)
|
||||
|
||||
#ifdef SHADING_FACEVARYING_COLOR
|
||||
#ifdef LOOP // ----- scheme : LOOP
|
||||
vec2 uv;
|
||||
OSD_COMPUTE_FACE_VARYING_TRI_2(uv, /*fvarOffste=*/0, index);
|
||||
|
||||
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
|
||||
vec2 trist[3] = vec2[](vec2(0,0), vec2(1,0), vec2(0,1));
|
||||
vec2 st = trist[index];
|
||||
#else
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
|
||||
|
||||
#else // ----- scheme : CATMARK / BILINEAR
|
||||
|
||||
@ -202,8 +248,8 @@ void emit(int index, vec3 normal)
|
||||
#else
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv;
|
||||
OSD_COMPUTE_FACE_VARYING_2(uv, /*fvarOffset=*/0, st);
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
|
||||
|
||||
#endif // ------ scheme
|
||||
outpt.color = vec3(uv.s, uv.t, 0);
|
||||
#endif
|
||||
@ -452,11 +498,11 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
if (edgeCount == 1) {
|
||||
patchType = 2; // BOUNDARY
|
||||
}
|
||||
if (edgeCount == 2) {
|
||||
patchType = 3; // CORNER
|
||||
if (edgeCount > 1) {
|
||||
patchType = 3; // CORNER (not correct for patches that are not isolated)
|
||||
}
|
||||
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
|
||||
// check this after boundary/corner since single crease patch also has edgeCount.
|
||||
if (inpt.vSegments.y > 0) {
|
||||
patchType = 1;
|
||||
@ -467,6 +513,8 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
patchType = 5;
|
||||
#elif defined OSD_PATCH_GREGORY_BASIS
|
||||
patchType = 6;
|
||||
#elif defined OSD_PATCH_GREGORY_TRIANGLE
|
||||
patchType = 6;
|
||||
#endif
|
||||
|
||||
int pattern = bitCount(OsdGetPatchTransitionMask(patchParam));
|
||||
@ -474,6 +522,19 @@ getAdaptivePatchColor(ivec3 patchParam)
|
||||
return patchColors[6*patchType + pattern];
|
||||
}
|
||||
|
||||
vec4
|
||||
getAdaptiveDepthColor(ivec3 patchParam)
|
||||
{
|
||||
// Represent depth with repeating cycle of four colors:
|
||||
const vec4 depthColors[4] = vec4[4](
|
||||
vec4(0.0f, 0.5f, 0.5f, 1.0f),
|
||||
vec4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
vec4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
vec4(0.5f, 1.0f, 0.5f, 1.0f)
|
||||
);
|
||||
return depthColors[OsdGetPatchRefinementLevel(patchParam) & 3];
|
||||
}
|
||||
|
||||
#if defined(PRIM_QUAD) || defined(PRIM_TRI)
|
||||
void
|
||||
main()
|
||||
@ -488,6 +549,8 @@ main()
|
||||
int(floor(20*inpt.color.r)+floor(20*inpt.color.g))&1, 1);
|
||||
#elif defined(SHADING_PATCH_TYPE)
|
||||
vec4 color = getAdaptivePatchColor(OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID)));
|
||||
#elif defined(SHADING_PATCH_DEPTH)
|
||||
vec4 color = getAdaptiveDepthColor(OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID)));
|
||||
#elif defined(SHADING_PATCH_COORD)
|
||||
vec4 color = vec4(inpt.v.patchCoord.xy, 0, 1);
|
||||
#elif defined(SHADING_MATERIAL)
|
||||
|
@ -131,9 +131,13 @@ if( (NOT NO_OPENGL) AND (OPENGL_FOUND OR OPENGLES_FOUND) )
|
||||
if ( OPENGL_FOUND )
|
||||
list(APPEND KERNEL_FILES
|
||||
glslPatchCommon.glsl
|
||||
glslPatchCommonTess.glsl
|
||||
glslPatchBoxSplineTriangle.glsl
|
||||
glslPatchBSpline.glsl
|
||||
glslPatchGregory.glsl
|
||||
glslPatchGregoryBasis.glsl
|
||||
glslPatchGregoryTriangle.glsl
|
||||
glslPatchLegacy.glsl
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
172
opensubdiv/osd/glslPatchBoxSplineTriangle.glsl
Normal file
172
opensubdiv/osd/glslPatchBoxSplineTriangle.glsl
Normal file
@ -0,0 +1,172 @@
|
||||
//
|
||||
// Copyright 2018 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[12];
|
||||
|
||||
layout(vertices = 12) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv[12];
|
||||
for (int i=0; i<12; ++i) {
|
||||
cv[i] = inpt[i].v.position.xyz;
|
||||
}
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
OsdComputePerPatchVertexBoxSplineTriangle(
|
||||
patchParam, gl_InvocationID, cv, outpt[gl_InvocationID].v);
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Wait for all basis conversion to be finished
|
||||
barrier();
|
||||
#endif
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(12);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
for (int i=0; i<12; ++i) {
|
||||
cv[i] = outpt[i].v.P;
|
||||
}
|
||||
OsdGetTessLevelsAdaptiveLimitPointsTriangle(
|
||||
cv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalBoxSplineTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_BOX_SPLINE_TRIANGLE_SHADER
|
||||
|
||||
layout(triangles) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
OsdPerPatchVertexBezier cv[12];
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
cv[i] = inpt[i].v;
|
||||
}
|
||||
|
||||
vec2 UV = OsdGetTessParameterizationTriangle(gl_TessCoord.xy,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchBezierTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, 4, 5, 8);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
725
opensubdiv/osd/glslPatchCommonTess.glsl
Normal file
725
opensubdiv/osd/glslPatchCommonTess.glsl
Normal file
@ -0,0 +1,725 @@
|
||||
//
|
||||
// Copyright 2013-2018 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tessellation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For now, fractional spacing is supported only with screen space tessellation
|
||||
#ifndef OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
#undef OSD_FRACTIONAL_EVEN_SPACING
|
||||
#undef OSD_FRACTIONAL_ODD_SPACING
|
||||
#endif
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
#define OSD_SPACING fractional_even_spacing
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
#define OSD_SPACING fractional_odd_spacing
|
||||
#else
|
||||
#define OSD_SPACING equal_spacing
|
||||
#endif
|
||||
|
||||
//
|
||||
// Organization of B-spline and Bezier control points.
|
||||
//
|
||||
// Each patch is defined by 16 control points (labeled 0-15).
|
||||
//
|
||||
// The patch will be evaluated across the domain from (0,0) at
|
||||
// the lower-left to (1,1) at the upper-right. When computing
|
||||
// adaptive tessellation metrics, we consider refined vertex-vertex
|
||||
// and edge-vertex points along the transition edges of the patch
|
||||
// (labeled vv* and ev* respectively).
|
||||
//
|
||||
// The two segments of each transition edge are labeled Lo and Hi,
|
||||
// with the Lo segment occurring before the Hi segment along the
|
||||
// transition edge's domain parameterization. These Lo and Hi segment
|
||||
// tessellation levels determine how domain evaluation coordinates
|
||||
// are remapped along transition edges. The Hi segment value will
|
||||
// be zero for a non-transition edge.
|
||||
//
|
||||
// (0,1) (1,1)
|
||||
//
|
||||
// vv3 ev23 vv2
|
||||
// | Lo3 | Hi3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | 12 | 13 14 | 15 |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// Hi0 | | | | Hi2
|
||||
// | | | |
|
||||
// O-----------O-----------O-----------O
|
||||
// | 8 | 9 10 | 11 |
|
||||
// | | | |
|
||||
// ev03 --+ | | +-- ev12
|
||||
// | | | |
|
||||
// | 4 | 5 6 | 7 |
|
||||
// O-----------O-----------O-----------O
|
||||
// | | | |
|
||||
// Lo0 | | | | Lo2
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | 0 | 1 2 | 3 |
|
||||
// --O-----------O-----+-----O-----------O--
|
||||
// | Lo1 | Hi1 |
|
||||
// vv0 ev01 vv1
|
||||
//
|
||||
// (0,0) (1,0)
|
||||
//
|
||||
|
||||
#define OSD_MAX_TESS_LEVEL gl_MaxTessGenLevel
|
||||
|
||||
float OsdComputePostProjectionSphereExtent(vec3 center, float diameter)
|
||||
{
|
||||
vec4 p = OsdProjectionMatrix() * vec4(center, 1.0);
|
||||
return abs(diameter * OsdProjectionMatrix()[1][1] / p.w);
|
||||
}
|
||||
|
||||
float OsdComputeTessLevel(vec3 p0, vec3 p1)
|
||||
{
|
||||
// Adaptive factor can be any computation that depends only on arg values.
|
||||
// Project the diameter of the edge's bounding sphere instead of using the
|
||||
// length of the projected edge itself to avoid problems near silhouettes.
|
||||
p0 = (OsdModelViewMatrix() * vec4(p0, 1.0)).xyz;
|
||||
p1 = (OsdModelViewMatrix() * vec4(p1, 1.0)).xyz;
|
||||
vec3 center = (p0 + p1) / 2.0;
|
||||
float diameter = distance(p0, p1);
|
||||
float projLength = OsdComputePostProjectionSphereExtent(center, diameter);
|
||||
float tessLevel = max(1.0, OsdTessLevel() * projLength);
|
||||
|
||||
// We restrict adaptive tessellation levels to half of the device
|
||||
// supported maximum because transition edges are split into two
|
||||
// halves and the sum of the two corresponding levels must not exceed
|
||||
// the device maximum. We impose this limit even for non-transition
|
||||
// edges because a non-transition edge must be able to match up with
|
||||
// one half of the transition edge of an adjacent transition patch.
|
||||
return min(tessLevel, OSD_MAX_TESS_LEVEL / 2);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
vec4 tessLevelMin = vec4(1) + vec4(((transitionMask & 8) >> 3),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
((transitionMask & 4) >> 2));
|
||||
|
||||
tessOuterLo = max(vec4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = vec4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Uniform factors are simple powers of two for each level.
|
||||
// The maximum here can be increased if we know the maximum
|
||||
// refinement level of the mesh:
|
||||
// min(OSD_MAX_TESS_LEVEL, pow(2, MaximumRefinementLevel-1)
|
||||
int refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
||||
float tessLevel = min(OsdTessLevel(), OSD_MAX_TESS_LEVEL) /
|
||||
pow(2, refinementLevel-1);
|
||||
|
||||
// tessLevels of transition edge should be clamped to 2.
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
vec4 tessLevelMin = vec4(1) + vec4(((transitionMask & 4) >> 2),
|
||||
((transitionMask & 1) >> 0),
|
||||
((transitionMask & 2) >> 1),
|
||||
0);
|
||||
|
||||
tessOuterLo = max(vec4(tessLevel), tessLevelMin);
|
||||
tessOuterHi = vec4(0);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsRefinedPoints(vec3 cp[16], ivec3 patchParam,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. We compute the corresponding
|
||||
// vertex-vertex and edge-vertex refined points along the edges of the
|
||||
// patch using Catmull-Clark subdivision stencil weights.
|
||||
// For simplicity, we let the optimizer discard unused computation.
|
||||
|
||||
vec3 vv0 = (cp[0] + cp[2] + cp[8] + cp[10]) * 0.015625 +
|
||||
(cp[1] + cp[4] + cp[6] + cp[9]) * 0.09375 + cp[5] * 0.5625;
|
||||
vec3 ev01 = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[6]) * 0.375;
|
||||
|
||||
vec3 vv1 = (cp[1] + cp[3] + cp[9] + cp[11]) * 0.015625 +
|
||||
(cp[2] + cp[5] + cp[7] + cp[10]) * 0.09375 + cp[6] * 0.5625;
|
||||
vec3 ev12 = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 +
|
||||
(cp[6] + cp[10]) * 0.375;
|
||||
|
||||
vec3 vv2 = (cp[5] + cp[7] + cp[13] + cp[15]) * 0.015625 +
|
||||
(cp[6] + cp[9] + cp[11] + cp[14]) * 0.09375 + cp[10] * 0.5625;
|
||||
vec3 ev23 = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 +
|
||||
(cp[9] + cp[10]) * 0.375;
|
||||
|
||||
vec3 vv3 = (cp[4] + cp[6] + cp[12] + cp[14]) * 0.015625 +
|
||||
(cp[5] + cp[8] + cp[10] + cp[13]) * 0.09375 + cp[9] * 0.5625;
|
||||
vec3 ev03 = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 +
|
||||
(cp[5] + cp[9]) * 0.375;
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(vv0, ev03);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(vv3, ev03);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp[5], cp[9]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(vv0, ev01);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(vv1, ev01);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp[5], cp[6]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(vv1, ev12);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(vv2, ev12);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp[6], cp[10]);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(vv3, ev23);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(vv2, ev23);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp[9], cp[10]);
|
||||
}
|
||||
}
|
||||
|
||||
vec3
|
||||
Osd_EvalBezierCurveMidPoint(vec3 p0, vec3 p1, vec3 p2, vec3 p3)
|
||||
{
|
||||
float one8th = (1.0 / 8.0);
|
||||
return one8th * (p0 + 3.0f*(p1 + p2) + p3);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the four corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
// PERFORMANCE: we just need to pick the correct corner points from P,P1,P2
|
||||
vec3 p0 = OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 0.0));
|
||||
vec3 p3 = OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 0.0));
|
||||
vec3 p12 = OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 1.0));
|
||||
vec3 p15 = OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 1.0));
|
||||
if ((transitionMask & 8) != 0) {
|
||||
vec3 ev03 = OsdEvalBezier(cpBezier, patchParam, vec2(0.0, 0.5));
|
||||
tessOuterLo[0] = OsdComputeTessLevel(p0, ev03);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(p12, ev03);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(p0, p12);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
vec3 ev01 = OsdEvalBezier(cpBezier, patchParam, vec2(0.5, 0.0));
|
||||
tessOuterLo[1] = OsdComputeTessLevel(p0, ev01);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(p3, ev01);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(p0, p3);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
vec3 ev12 = OsdEvalBezier(cpBezier, patchParam, vec2(1.0, 0.5));
|
||||
tessOuterLo[2] = OsdComputeTessLevel(p3, ev12);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(p15, ev12);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(p3, p15);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
vec3 ev23 = OsdEvalBezier(cpBezier, patchParam, vec2(0.5, 1.0));
|
||||
tessOuterLo[3] = OsdComputeTessLevel(p12, ev23);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(p15, ev23);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(p12, p15);
|
||||
}
|
||||
#else
|
||||
|
||||
if ((transitionMask & 8) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[4].P, cpBezier[8].P, cpBezier[12].P);
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, P);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(cpBezier[12].P, P);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[12].P);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[0].P, cpBezier[1].P, cpBezier[2].P, cpBezier[3].P);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, P);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(cpBezier[3].P, P);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[3].P);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[3].P, cpBezier[7].P, cpBezier[11].P, cpBezier[15].P);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, P);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(cpBezier[15].P, P);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, cpBezier[15].P);
|
||||
}
|
||||
if ((transitionMask & 4) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(
|
||||
cpBezier[12].P, cpBezier[13].P, cpBezier[14].P, cpBezier[15].P);
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, P);
|
||||
tessOuterHi[3] = OsdComputeTessLevel(cpBezier[15].P, P);
|
||||
} else {
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, cpBezier[15].P);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsLimitPointsTriangle(vec3 cv[12],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 4) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[0], cv[4], cv[8], cv[11]);
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cv[0], P);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(cv[11], P);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cv[0], cv[11]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[0], cv[1], cv[2], cv[3]);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cv[0], P);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(cv[3], P);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cv[0], cv[3]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[3], cv[7], cv[10], cv[11]);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cv[11], P);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(cv[3], P);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cv[3], cv[11]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsLimitPointsGregoryTriangle(vec3 cv[15],
|
||||
ivec3 patchParam, out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// Each edge of a transition patch is adjacent to one or two patches
|
||||
// at the next refined level of subdivision. When the patch control
|
||||
// points have been converted to the Bezier basis, the control points
|
||||
// at the corners are on the limit surface (since a Bezier patch
|
||||
// interpolates its corner control points). We can compute an adaptive
|
||||
// tessellation level for transition edges on the limit surface by
|
||||
// evaluating a limit position at the mid point of each transition edge.
|
||||
|
||||
tessOuterLo = vec4(0);
|
||||
tessOuterHi = vec4(0);
|
||||
|
||||
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
||||
|
||||
if ((transitionMask & 4) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[0], cv[2], cv[11], cv[10]);
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cv[0], P);
|
||||
tessOuterHi[0] = OsdComputeTessLevel(cv[10], P);
|
||||
} else {
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cv[0], cv[10]);
|
||||
}
|
||||
if ((transitionMask & 1) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[0], cv[1], cv[7], cv[5]);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cv[0], P);
|
||||
tessOuterHi[1] = OsdComputeTessLevel(cv[5], P);
|
||||
} else {
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cv[0], cv[5]);
|
||||
}
|
||||
if ((transitionMask & 2) != 0) {
|
||||
vec3 P = Osd_EvalBezierCurveMidPoint(cv[5], cv[6], cv[12], cv[10]);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cv[10], P);
|
||||
tessOuterHi[2] = OsdComputeTessLevel(cv[5], P);
|
||||
} else {
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cv[5], cv[10]);
|
||||
}
|
||||
}
|
||||
|
||||
// Round up to the nearest even integer
|
||||
float OsdRoundUpEven(float x) {
|
||||
return 2*ceil(x/2);
|
||||
}
|
||||
|
||||
// Round up to the nearest odd integer
|
||||
float OsdRoundUpOdd(float x) {
|
||||
return 2*ceil((x+1)/2)-1;
|
||||
}
|
||||
|
||||
// Compute outer and inner tessellation levels taking into account the
|
||||
// current tessellation spacing mode.
|
||||
void
|
||||
OsdComputeTessLevels(inout vec4 tessOuterLo, inout vec4 tessOuterHi,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
||||
// segments will have lengths of zero for non-transition edges.
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpEven(tessOuterLo[0]) + OsdRoundUpEven(tessOuterHi[0]);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpEven(tessOuterLo[1]) + OsdRoundUpEven(tessOuterHi[1]);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpEven(tessOuterLo[2]) + OsdRoundUpEven(tessOuterHi[2]);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpEven(tessOuterLo[3]) + OsdRoundUpEven(tessOuterHi[3]);
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
// Combine fractional outer transition edge levels before rounding.
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
|
||||
// Round the segments of transition edges separately. We will recover the
|
||||
// fractional parameterization of transition edges after tessellation.
|
||||
//
|
||||
// The sum of the two outer odd segment lengths will be an even number
|
||||
// which the tessellator will increase by +1 so that there will be a
|
||||
// total odd number of segments. We clamp the combinedOuter tess levels
|
||||
// (used to compute the inner tess levels) so that the outer transition
|
||||
// edges will be sampled without degenerate triangles.
|
||||
|
||||
tessLevelOuter = combinedOuter;
|
||||
if (tessOuterHi[0] > 0) {
|
||||
tessLevelOuter[0] =
|
||||
OsdRoundUpOdd(tessOuterLo[0]) + OsdRoundUpOdd(tessOuterHi[0]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[1] > 0) {
|
||||
tessLevelOuter[1] =
|
||||
OsdRoundUpOdd(tessOuterLo[1]) + OsdRoundUpOdd(tessOuterHi[1]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[2] > 0) {
|
||||
tessLevelOuter[2] =
|
||||
OsdRoundUpOdd(tessOuterLo[2]) + OsdRoundUpOdd(tessOuterHi[2]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
if (tessOuterHi[3] > 0) {
|
||||
tessLevelOuter[3] =
|
||||
OsdRoundUpOdd(tessOuterLo[3]) + OsdRoundUpOdd(tessOuterHi[3]);
|
||||
combinedOuter = max(vec4(3), combinedOuter);
|
||||
}
|
||||
#else
|
||||
// Round equally spaced transition edge levels before combining.
|
||||
tessOuterLo = round(tessOuterLo);
|
||||
tessOuterHi = round(tessOuterHi);
|
||||
|
||||
vec4 combinedOuter = tessOuterLo + tessOuterHi;
|
||||
tessLevelOuter = combinedOuter;
|
||||
#endif
|
||||
|
||||
// Inner levels are the averages the corresponding outer levels.
|
||||
tessLevelInner[0] = (combinedOuter[1] + combinedOuter[3]) * 0.5;
|
||||
tessLevelInner[1] = (combinedOuter[0] + combinedOuter[2]) * 0.5;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputeTessLevelsTriangle(inout vec4 tessOuterLo, inout vec4 tessOuterHi,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
|
||||
// Inner level is the max of the three outer levels.
|
||||
tessLevelInner[0] = max(max(tessLevelOuter[0],
|
||||
tessLevelOuter[1]),
|
||||
tessLevelOuter[2]);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniform(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// uniform tessellation
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsUniformTriangle(ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
// uniform tessellation
|
||||
OsdGetTessLevelsUniformTriangle(patchParam, tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveRefinedPoints(vec3 cpRefined[16], ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsRefinedPoints(cpRefined, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPoints(cpBezier, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPointsTriangle(vec3 cv[12],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPointsTriangle(cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevelsAdaptiveLimitPointsGregoryTriangle(vec3 cv[15],
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner,
|
||||
out vec4 tessOuterLo, out vec4 tessOuterHi)
|
||||
{
|
||||
OsdGetTessLevelsLimitPointsGregoryTriangle(cv, patchParam,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
OsdComputeTessLevelsTriangle(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
void
|
||||
OsdGetTessLevels(vec3 cp0, vec3 cp1, vec3 cp2, vec3 cp3,
|
||||
ivec3 patchParam,
|
||||
out vec4 tessLevelOuter, out vec2 tessLevelInner)
|
||||
{
|
||||
vec4 tessOuterLo = vec4(0);
|
||||
vec4 tessOuterHi = vec4(0);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
tessOuterLo[0] = OsdComputeTessLevel(cp0, cp1);
|
||||
tessOuterLo[1] = OsdComputeTessLevel(cp0, cp3);
|
||||
tessOuterLo[2] = OsdComputeTessLevel(cp2, cp3);
|
||||
tessOuterLo[3] = OsdComputeTessLevel(cp1, cp2);
|
||||
tessOuterHi = vec4(0);
|
||||
#else
|
||||
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
||||
#endif
|
||||
|
||||
OsdComputeTessLevels(tessOuterLo, tessOuterHi,
|
||||
tessLevelOuter, tessLevelInner);
|
||||
}
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING || defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float
|
||||
OsdGetTessFractionalSplit(float t, float level, float levelUp)
|
||||
{
|
||||
// Fractional tessellation of an edge will produce n segments where n
|
||||
// is the tessellation level of the edge (level) rounded up to the
|
||||
// nearest even or odd integer (levelUp). There will be n-2 segments of
|
||||
// equal length (dx1) and two additional segments of equal length (dx0)
|
||||
// that are typically shorter than the other segments. The two additional
|
||||
// segments should be placed symmetrically on opposite sides of the
|
||||
// edge (offset).
|
||||
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
if (level <= 2) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(int(2*base-levelUp)/2 & int(base/2-1));
|
||||
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
if (level <= 1) return t;
|
||||
|
||||
float base = pow(2.0,floor(log2(levelUp)));
|
||||
float offset = 1.0/(((int(2*base-levelUp)/2+1) & int(base/2-1))+1);
|
||||
#endif
|
||||
|
||||
float dx0 = (1.0 - (levelUp-level)/2) / levelUp;
|
||||
float dx1 = (1.0 - 2.0*dx0) / (levelUp - 2.0*ceil(dx0));
|
||||
|
||||
if (t < 0.5) {
|
||||
float x = levelUp/2 - round(t*levelUp);
|
||||
return 0.5 - (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else if (t > 0.5) {
|
||||
float x = round(t*levelUp) - levelUp/2;
|
||||
return 0.5 + (x*dx1 + int(x*offset > 1) * (dx0 - dx1));
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float
|
||||
OsdGetTessTransitionSplit(float t, float lo, float hi)
|
||||
{
|
||||
#if defined OSD_FRACTIONAL_EVEN_SPACING
|
||||
float loRoundUp = OsdRoundUpEven(lo);
|
||||
float hiRoundUp = OsdRoundUpEven(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else {
|
||||
float t1 = (ti - loRoundUp) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
}
|
||||
#elif defined OSD_FRACTIONAL_ODD_SPACING
|
||||
float loRoundUp = OsdRoundUpOdd(lo);
|
||||
float hiRoundUp = OsdRoundUpOdd(hi);
|
||||
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
// The +1 below is to account for the extra segment produced by the
|
||||
// tessellator since the sum of two odd tess levels will be rounded
|
||||
// up by one to the next odd integer tess level.
|
||||
float ti = round(t * (loRoundUp + hiRoundUp + 1));
|
||||
|
||||
if (ti <= loRoundUp) {
|
||||
float t0 = ti / loRoundUp;
|
||||
return OsdGetTessFractionalSplit(t0, lo, loRoundUp) * 0.5;
|
||||
} else if (ti > (loRoundUp+1)) {
|
||||
float t1 = (ti - (loRoundUp+1)) / hiRoundUp;
|
||||
return OsdGetTessFractionalSplit(t1, hi, hiRoundUp) * 0.5 + 0.5;
|
||||
} else {
|
||||
return 0.5;
|
||||
}
|
||||
#else
|
||||
// Convert the parametric t into a segment index along the combined edge.
|
||||
float ti = round(t * (lo + hi));
|
||||
|
||||
if (ti <= lo) {
|
||||
return (ti / lo) * 0.5;
|
||||
} else {
|
||||
return ((ti - lo) / hi) * 0.5 + 0.5;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
vec2
|
||||
OsdGetTessParameterization(vec2 uv, vec4 tessOuterLo, vec4 tessOuterHi)
|
||||
{
|
||||
vec2 UV = uv;
|
||||
if (UV.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (UV.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (UV.x == 1 && tessOuterHi[2] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[2], tessOuterHi[2]);
|
||||
} else
|
||||
if (UV.y == 1 && tessOuterHi[3] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[3], tessOuterHi[3]);
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
|
||||
vec2
|
||||
OsdGetTessParameterizationTriangle(vec2 uv, vec4 tessOuterLo, vec4 tessOuterHi)
|
||||
{
|
||||
vec2 UV = uv;
|
||||
if (UV.x == 0 && tessOuterHi[0] > 0) {
|
||||
UV.y = OsdGetTessTransitionSplit(UV.y, tessOuterLo[0], tessOuterHi[0]);
|
||||
} else
|
||||
if (UV.y == 0 && tessOuterHi[1] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[1], tessOuterHi[1]);
|
||||
} else
|
||||
if (UV.x+UV.y == 1 && tessOuterHi[2] > 0) {
|
||||
UV.x = OsdGetTessTransitionSplit(UV.x, tessOuterLo[2], tessOuterHi[2]);
|
||||
UV.y = 1.0 - UV.x;
|
||||
}
|
||||
return UV;
|
||||
}
|
||||
|
175
opensubdiv/osd/glslPatchGregoryTriangle.glsl
Normal file
175
opensubdiv/osd/glslPatchGregoryTriangle.glsl
Normal file
@ -0,0 +1,175 @@
|
||||
//
|
||||
// Copyright 2018 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.VertexGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_VERTEX_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
layout(location = 0) in vec4 position;
|
||||
OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
|
||||
out block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
outpt.v.position = position;
|
||||
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(position);
|
||||
OSD_USER_VARYING_PER_VERTEX();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessControlGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_CONTROL_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
patch out vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
ControlVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt[15];
|
||||
|
||||
layout(vertices = 15) out;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 cv = inpt[gl_InvocationID].v.position.xyz;
|
||||
|
||||
ivec3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(gl_PrimitiveID));
|
||||
|
||||
outpt[gl_InvocationID].v.patchParam = patchParam;
|
||||
outpt[gl_InvocationID].v.P = cv;
|
||||
|
||||
OSD_USER_VARYING_PER_CONTROL_POINT(gl_InvocationID, gl_InvocationID);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Wait for all basis conversion to be finished
|
||||
barrier();
|
||||
#endif
|
||||
if (gl_InvocationID == 0) {
|
||||
vec4 tessLevelOuter = vec4(0);
|
||||
vec2 tessLevelInner = vec2(0);
|
||||
|
||||
OSD_PATCH_CULL(15);
|
||||
|
||||
OsdGetTessLevelsUniformTriangle(patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
#if defined OSD_ENABLE_SCREENSPACE_TESSELLATION
|
||||
// Gather bezier control points to compute limit surface tess levels
|
||||
vec3 cv[15];
|
||||
for (int i=0; i<15; ++i) {
|
||||
cv[i] = outpt[i].v.P;
|
||||
}
|
||||
OsdGetTessLevelsAdaptiveLimitPointsGregoryTriangle(
|
||||
cv, patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
#else
|
||||
OsdGetTessLevelsUniformTriangle(patchParam,
|
||||
tessLevelOuter, tessLevelInner,
|
||||
tessOuterLo, tessOuterHi);
|
||||
|
||||
#endif
|
||||
|
||||
gl_TessLevelOuter[0] = tessLevelOuter[0];
|
||||
gl_TessLevelOuter[1] = tessLevelOuter[1];
|
||||
gl_TessLevelOuter[2] = tessLevelOuter[2];
|
||||
|
||||
gl_TessLevelInner[0] = tessLevelInner[0];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.TessEvalGregoryTriangle
|
||||
//----------------------------------------------------------
|
||||
#ifdef OSD_PATCH_TESS_EVAL_GREGORY_TRIANGLE_SHADER
|
||||
|
||||
layout(triangles) in;
|
||||
layout(OSD_SPACING) in;
|
||||
|
||||
patch in vec4 tessOuterLo, tessOuterHi;
|
||||
|
||||
in block {
|
||||
OsdPerPatchVertexBezier v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} inpt[];
|
||||
|
||||
out block {
|
||||
OutputVertex v;
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 UV = OsdGetTessParameterizationTriangle(gl_TessCoord.xy,
|
||||
tessOuterLo,
|
||||
tessOuterHi);
|
||||
|
||||
vec3 P = vec3(0), dPu = vec3(0), dPv = vec3(0);
|
||||
vec3 N = vec3(0), dNu = vec3(0), dNv = vec3(0);
|
||||
|
||||
vec3 cv[15];
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
cv[i] = inpt[i].v.P;
|
||||
}
|
||||
|
||||
ivec3 patchParam = inpt[0].v.patchParam;
|
||||
OsdEvalPatchGregoryTriangle(patchParam, UV, cv, P, dPu, dPv, N, dNu, dNv);
|
||||
|
||||
// all code below here is client code
|
||||
outpt.v.position = OsdModelViewMatrix() * vec4(P, 1.0f);
|
||||
outpt.v.normal = (OsdModelViewMatrix() * vec4(N, 0.0f)).xyz;
|
||||
outpt.v.tangent = (OsdModelViewMatrix() * vec4(dPu, 0.0f)).xyz;
|
||||
outpt.v.bitangent = (OsdModelViewMatrix() * vec4(dPv, 0.0f)).xyz;
|
||||
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
outpt.v.Nu = dNu;
|
||||
outpt.v.Nv = dNv;
|
||||
#endif
|
||||
|
||||
outpt.v.tessCoord = UV;
|
||||
outpt.v.patchCoord = OsdInterpolatePatchCoordTriangle(UV, patchParam);
|
||||
|
||||
OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, 6, 7, 10);
|
||||
|
||||
OSD_DISPLACEMENT_CALLBACK;
|
||||
|
||||
gl_Position = OsdProjectionMatrix() * outpt.v.position;
|
||||
}
|
||||
|
||||
#endif
|
511
opensubdiv/osd/glslPatchLegacy.glsl
Normal file
511
opensubdiv/osd/glslPatchLegacy.glsl
Normal file
@ -0,0 +1,511 @@
|
||||
//
|
||||
// Copyright 2013-2018 Pixar
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
// with the following modification; you may not use this file except in
|
||||
// compliance with the Apache License and the following modification to it:
|
||||
// Section 6. Trademarks. is deleted and replaced with:
|
||||
//
|
||||
// 6. Trademarks. This License does not grant permission to use the trade
|
||||
// names, trademarks, service marks, or product names of the Licensor
|
||||
// and its affiliates, except as required to comply with Section 4(c) of
|
||||
// the License and to reproduce the content of the NOTICE file.
|
||||
//
|
||||
// You may obtain a copy of the Apache License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the Apache License with the above modification is
|
||||
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the Apache License for the specific
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
#if defined(OSD_PATCH_GREGORY) || defined(OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#define M_PI 3.14159265359f
|
||||
|
||||
// precomputed catmark coefficient table up to valence 29
|
||||
uniform float OsdCatmarkCoefficient[30] = float[](
|
||||
0, 0, 0, 0.812816, 0.500000, 0.363644, 0.287514,
|
||||
0.238688, 0.204544, 0.179229, 0.159657,
|
||||
0.144042, 0.131276, 0.120632, 0.111614,
|
||||
0.103872, 0.09715, 0.0912559, 0.0860444,
|
||||
0.0814022, 0.0772401, 0.0734867, 0.0700842,
|
||||
0.0669851, 0.0641504, 0.0615475, 0.0591488,
|
||||
0.0569311, 0.0548745, 0.0529621
|
||||
);
|
||||
|
||||
float
|
||||
OsdComputeCatmarkCoefficient(int valence)
|
||||
{
|
||||
#if OSD_MAX_VALENCE < 30
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
#else
|
||||
if (valence < 30) {
|
||||
return OsdCatmarkCoefficient[valence];
|
||||
} else {
|
||||
float t = 2.0f * float(M_PI) / float(valence);
|
||||
return 1.0f / (valence * (cos(t) + 5.0f +
|
||||
sqrt((cos(t) + 9) * (cos(t) + 1)))/16.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float cosfn(int n, int j) {
|
||||
return cos((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
float sinfn(int n, int j) {
|
||||
return sin((2.0f * M_PI * j)/float(n));
|
||||
}
|
||||
|
||||
#if !defined OSD_MAX_VALENCE || OSD_MAX_VALENCE < 1
|
||||
#undef OSD_MAX_VALENCE
|
||||
#define OSD_MAX_VALENCE 4
|
||||
#endif
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
vec3 P;
|
||||
ivec3 clipFlag;
|
||||
int valence;
|
||||
vec3 e0;
|
||||
vec3 e1;
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor;
|
||||
vec3 org;
|
||||
#endif
|
||||
vec3 r[OSD_MAX_VALENCE];
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
ivec3 patchParam;
|
||||
vec3 P;
|
||||
vec3 Ep;
|
||||
vec3 Em;
|
||||
vec3 Fp;
|
||||
vec3 Fm;
|
||||
};
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
uniform samplerBuffer OsdVertexBuffer;
|
||||
uniform isamplerBuffer OsdValenceBuffer;
|
||||
|
||||
vec3 OsdReadVertex(int vertexIndex)
|
||||
{
|
||||
int index = int(OSD_NUM_ELEMENTS * (vertexIndex + OsdBaseVertex()));
|
||||
return vec3(texelFetch(OsdVertexBuffer, index).x,
|
||||
texelFetch(OsdVertexBuffer, index+1).x,
|
||||
texelFetch(OsdVertexBuffer, index+2).x);
|
||||
}
|
||||
|
||||
int OsdReadVertexValence(int vertexID)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1));
|
||||
return texelFetch(OsdValenceBuffer, index).x;
|
||||
}
|
||||
|
||||
int OsdReadVertexIndex(int vertexID, int valenceVertex)
|
||||
{
|
||||
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
||||
return texelFetch(OsdValenceBuffer, index).x;
|
||||
}
|
||||
|
||||
uniform isamplerBuffer OsdQuadOffsetBuffer;
|
||||
|
||||
int OsdReadQuadOffset(int primitiveID, int offsetVertex)
|
||||
{
|
||||
int index = int(4*primitiveID+OsdGregoryQuadOffsetBase() + offsetVertex);
|
||||
return texelFetch(OsdQuadOffsetBuffer, index).x;
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerVertexGregory(int vID, vec3 P, out OsdPerVertexGregory v)
|
||||
{
|
||||
v.clipFlag = ivec3(0);
|
||||
|
||||
int ivalence = OsdReadVertexValence(vID);
|
||||
v.valence = ivalence;
|
||||
int valence = abs(ivalence);
|
||||
|
||||
vec3 f[OSD_MAX_VALENCE];
|
||||
vec3 pos = P;
|
||||
vec3 opos = vec3(0);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.org = pos;
|
||||
int boundaryEdgeNeighbors[2];
|
||||
int currNeighbor = 0;
|
||||
int ibefore = 0;
|
||||
int zerothNeighbor = 0;
|
||||
#endif
|
||||
|
||||
for (int i=0; i<valence; ++i) {
|
||||
int im = (i+valence-1)%valence;
|
||||
int ip = (i+1)%valence;
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*i);
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
bool isBoundaryNeighbor = false;
|
||||
int valenceNeighbor = OsdReadVertexValence(idx_neighbor);
|
||||
|
||||
if (valenceNeighbor < 0) {
|
||||
isBoundaryNeighbor = true;
|
||||
if (currNeighbor<2) {
|
||||
boundaryEdgeNeighbors[currNeighbor] = idx_neighbor;
|
||||
}
|
||||
currNeighbor++;
|
||||
if (currNeighbor == 1) {
|
||||
ibefore = i;
|
||||
zerothNeighbor = i;
|
||||
} else {
|
||||
if (i-ibefore == 1) {
|
||||
int tmp = boundaryEdgeNeighbors[0];
|
||||
boundaryEdgeNeighbors[0] = boundaryEdgeNeighbors[1];
|
||||
boundaryEdgeNeighbors[1] = tmp;
|
||||
zerothNeighbor = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vec3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*i + 1);
|
||||
vec3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
int idx_neighbor_p = OsdReadVertexIndex(vID, 2*ip);
|
||||
vec3 neighbor_p = OsdReadVertex(idx_neighbor_p);
|
||||
|
||||
int idx_neighbor_m = OsdReadVertexIndex(vID, 2*im);
|
||||
vec3 neighbor_m = OsdReadVertex(idx_neighbor_m);
|
||||
|
||||
int idx_diagonal_m = OsdReadVertexIndex(vID, 2*im + 1);
|
||||
vec3 diagonal_m = OsdReadVertex(idx_diagonal_m);
|
||||
|
||||
f[i] = (pos * float(valence) + (neighbor_p + neighbor)*2.0f + diagonal) / (float(valence)+5.0f);
|
||||
|
||||
opos += f[i];
|
||||
v.r[i] = (neighbor_p-neighbor_m)/3.0f + (diagonal - diagonal_m)/6.0f;
|
||||
}
|
||||
|
||||
opos /= valence;
|
||||
v.P = vec4(opos, 1.0f).xyz;
|
||||
|
||||
vec3 e;
|
||||
v.e0 = vec3(0);
|
||||
v.e1 = vec3(0);
|
||||
|
||||
for(int i=0; i<valence; ++i) {
|
||||
int im = (i + valence -1) % valence;
|
||||
e = 0.5f * (f[i] + f[im]);
|
||||
v.e0 += cosfn(valence, i)*e;
|
||||
v.e1 += sinfn(valence, i)*e;
|
||||
}
|
||||
float ef = OsdComputeCatmarkCoefficient(valence);
|
||||
v.e0 *= ef;
|
||||
v.e1 *= ef;
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
v.zerothNeighbor = zerothNeighbor;
|
||||
if (currNeighbor == 1) {
|
||||
boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0];
|
||||
}
|
||||
|
||||
if (ivalence < 0) {
|
||||
if (valence > 2) {
|
||||
v.P = (OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
4.0f * pos)/6.0f;
|
||||
} else {
|
||||
v.P = pos;
|
||||
}
|
||||
|
||||
v.e0 = (OsdReadVertex(boundaryEdgeNeighbors[0]) -
|
||||
OsdReadVertex(boundaryEdgeNeighbors[1]))/6.0;
|
||||
|
||||
float k = float(float(valence) - 1.0f); //k is the number of faces
|
||||
float c = cos(M_PI/k);
|
||||
float s = sin(M_PI/k);
|
||||
float gamma = -(4.0f*s)/(3.0f*k+c);
|
||||
float alpha_0k = -((1.0f+2.0f*c)*sqrt(1.0f+c))/((3.0f*k+c)*sqrt(1.0f-c));
|
||||
float beta_0 = s/(3.0f*k + c);
|
||||
|
||||
int idx_diagonal = OsdReadVertexIndex(vID, 2*zerothNeighbor + 1);
|
||||
vec3 diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 = gamma * pos +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
||||
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
||||
beta_0 * diagonal;
|
||||
|
||||
for (int x=1; x<valence - 1; ++x) {
|
||||
int curri = ((x + zerothNeighbor)%valence);
|
||||
float alpha = (4.0f*sin((M_PI * float(x))/k))/(3.0f*k+c);
|
||||
float beta = (sin((M_PI * float(x))/k) + sin((M_PI * float(x+1))/k))/(3.0f*k+c);
|
||||
|
||||
int idx_neighbor = OsdReadVertexIndex(vID, 2*curri);
|
||||
vec3 neighbor = OsdReadVertex(idx_neighbor);
|
||||
|
||||
idx_diagonal = OsdReadVertexIndex(vID, 2*curri + 1);
|
||||
diagonal = OsdReadVertex(idx_diagonal);
|
||||
|
||||
v.e1 += alpha * neighbor + beta * diagonal;
|
||||
}
|
||||
|
||||
v.e1 /= 3.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregory(ivec3 patchParam, int ID, int primitiveID,
|
||||
in OsdPerVertexGregory v[4],
|
||||
out OsdPerPatchVertexGregory result)
|
||||
{
|
||||
result.patchParam = patchParam;
|
||||
result.P = v[ID].P;
|
||||
|
||||
int i = ID;
|
||||
int ip = (i+1)%4;
|
||||
int im = (i+3)%4;
|
||||
int valence = abs(v[i].valence);
|
||||
int n = valence;
|
||||
|
||||
int start = OsdReadQuadOffset(primitiveID, i) & 0xff;
|
||||
int prev = (OsdReadQuadOffset(primitiveID, i) >> 8) & 0xff;
|
||||
|
||||
int start_m = OsdReadQuadOffset(primitiveID, im) & 0xff;
|
||||
int prev_p = (OsdReadQuadOffset(primitiveID, ip) >> 8) & 0xff;
|
||||
|
||||
int np = abs(v[ip].valence);
|
||||
int nm = abs(v[im].valence);
|
||||
|
||||
// Control Vertices based on :
|
||||
// "Approximating Subdivision Surfaces with Gregory Patches
|
||||
// for Hardware Tessellation"
|
||||
// Loop, Schaefer, Ni, Castano (ACM ToG Siggraph Asia 2009)
|
||||
//
|
||||
// P3 e3- e2+ P2
|
||||
// O--------O--------O--------O
|
||||
// | | | |
|
||||
// | | | |
|
||||
// | | f3- | f2+ |
|
||||
// | O O |
|
||||
// e3+ O------O O------O e2-
|
||||
// | f3+ f2- |
|
||||
// | |
|
||||
// | |
|
||||
// | f0- f1+ |
|
||||
// e0- O------O O------O e1+
|
||||
// | O O |
|
||||
// | | f0+ | f1- |
|
||||
// | | | |
|
||||
// | | | |
|
||||
// O--------O--------O--------O
|
||||
// P0 e0+ e1- P1
|
||||
//
|
||||
|
||||
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
||||
vec3 Em_ip;
|
||||
if (v[ip].valence < -2) {
|
||||
int j = (np + prev_p - v[ip].zerothNeighbor) % np;
|
||||
Em_ip = v[ip].P + cos((M_PI*j)/float(np-1))*v[ip].e0 + sin((M_PI*j)/float(np-1))*v[ip].e1;
|
||||
} else {
|
||||
Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p ) + v[ip].e1*sinfn(np, prev_p);
|
||||
}
|
||||
|
||||
vec3 Ep_im;
|
||||
if (v[im].valence < -2) {
|
||||
int j = (nm + start_m - v[im].zerothNeighbor) % nm;
|
||||
Ep_im = v[im].P + cos((M_PI*j)/float(nm-1))*v[im].e0 + sin((M_PI*j)/float(nm-1))*v[im].e1;
|
||||
} else {
|
||||
Ep_im = v[im].P + v[im].e0*cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
}
|
||||
|
||||
if (v[i].valence < 0) {
|
||||
n = (n-1)*2;
|
||||
}
|
||||
if (v[im].valence < 0) {
|
||||
nm = (nm-1)*2;
|
||||
}
|
||||
if (v[ip].valence < 0) {
|
||||
np = (np-1)*2;
|
||||
}
|
||||
|
||||
if (v[i].valence > 2) {
|
||||
result.Ep = v[i].P + v[i].e0*cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0*cosfn(n, prev ) + v[i].e1*sinfn(n, prev);
|
||||
|
||||
float s1=3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2=2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
} else if (v[i].valence < -2) {
|
||||
int j = (valence + start - v[i].zerothNeighbor) % valence;
|
||||
|
||||
result.Ep = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
j = (valence + prev - v[i].zerothNeighbor) % valence;
|
||||
result.Em = v[i].P + cos((M_PI*j)/float(valence-1))*v[i].e0 + sin((M_PI*j)/float(valence-1))*v[i].e1;
|
||||
|
||||
vec3 Rp = ((-2.0f * v[i].org - 1.0f * v[im].org) + (2.0f * v[ip].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
vec3 Rm = ((-2.0f * v[i].org - 1.0f * v[ip].org) + (2.0f * v[im].org + 1.0f * v[(i+2)%4].org))/3.0f;
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
|
||||
if (v[im].valence < 0) {
|
||||
s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
result.Fp = result.Fm = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
} else if (v[ip].valence < 0) {
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/n)-cos(2.0f*M_PI/nm);
|
||||
result.Fm = result.Fp = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
}
|
||||
|
||||
} else if (v[i].valence == -2) {
|
||||
result.Ep = (2.0f * v[i].org + v[ip].org)/3.0f;
|
||||
result.Em = (2.0f * v[i].org + v[im].org)/3.0f;
|
||||
result.Fp = result.Fm = (4.0f * v[i].org + v[(i+2)%n].org + 2.0f * v[ip].org + 2.0f * v[im].org)/9.0f;
|
||||
}
|
||||
|
||||
#else // not OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
result.Ep = v[i].P + v[i].e0 * cosfn(n, start) + v[i].e1*sinfn(n, start);
|
||||
result.Em = v[i].P + v[i].e0 * cosfn(n, prev ) + v[i].e1*sinfn(n, prev);
|
||||
|
||||
vec3 Em_ip = v[ip].P + v[ip].e0 * cosfn(np, prev_p ) + v[ip].e1*sinfn(np, prev_p);
|
||||
vec3 Ep_im = v[im].P + v[im].e0 * cosfn(nm, start_m) + v[im].e1*sinfn(nm, start_m);
|
||||
|
||||
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
||||
float s2 = 2*cosfn(n,1);
|
||||
|
||||
result.Fp = (cosfn(np,1)*v[i].P + s1*result.Ep + s2*Em_ip + v[i].r[start])/3.0f;
|
||||
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
||||
result.Fm = (cosfn(nm,1)*v[i].P + s1*result.Em + s2*Ep_im - v[i].r[prev])/3.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Face-varying
|
||||
// ----------------------------------------------------------------------------
|
||||
uniform samplerBuffer OsdFVarDataBuffer;
|
||||
|
||||
#ifndef OSD_FVAR_WIDTH
|
||||
#define OSD_FVAR_WIDTH 0
|
||||
#endif
|
||||
|
||||
// ------ extract from quads (catmark, bilinear) ---------
|
||||
// XXX: only linear interpolation is supported
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_1(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
float v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = texelFetch(OsdFVarDataBuffer, index).s \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_2(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec2 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec2(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_3(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec3 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec3(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_4(result, fvarOffset, tessCoord) \
|
||||
{ \
|
||||
vec4 v[4]; \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 4; \
|
||||
for (int i = 0; i < 4; ++i) { \
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
v[i] = vec4(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 3).s); \
|
||||
} \
|
||||
result = mix(mix(v[0], v[1], tessCoord.s), \
|
||||
mix(v[3], v[2], tessCoord.s), \
|
||||
tessCoord.t); \
|
||||
}
|
||||
|
||||
// ------ extract from triangles barycentric (loop) ---------
|
||||
// XXX: no interpolation supported
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_1(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = texelFetch(OsdFVarDataBuffer, index).s; \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_2(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec2(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_3(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec3(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s); \
|
||||
}
|
||||
|
||||
#define OSD_COMPUTE_FACE_VARYING_TRI_4(result, fvarOffset, triVert) \
|
||||
{ \
|
||||
int primOffset = OsdGetPatchIndex(gl_PrimitiveID) * 3; \
|
||||
int index = (primOffset+triVert)*OSD_FVAR_WIDTH + fvarOffset; \
|
||||
result = vec4(texelFetch(OsdFVarDataBuffer, index).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 2).s, \
|
||||
texelFetch(OsdFVarDataBuffer, index + 3).s); \
|
||||
}
|
||||
|
@ -34,6 +34,12 @@ namespace Osd {
|
||||
static const char *commonShaderSource =
|
||||
#include "glslPatchCommon.gen.h"
|
||||
;
|
||||
static const char *commonTessShaderSource =
|
||||
#include "glslPatchCommonTess.gen.h"
|
||||
;
|
||||
static const char *patchLegacyShaderSource =
|
||||
#include "glslPatchLegacy.gen.h"
|
||||
;
|
||||
static const char *patchBasisTypesShaderSource =
|
||||
#include "patchBasisCommonTypes.gen.h"
|
||||
;
|
||||
@ -43,6 +49,9 @@ static const char *patchBasisShaderSource =
|
||||
static const char *patchBasisEvalShaderSource =
|
||||
#include "patchBasisCommonEval.gen.h"
|
||||
;
|
||||
static const char *boxSplineTriangleShaderSource =
|
||||
#include "glslPatchBoxSplineTriangle.gen.h"
|
||||
;
|
||||
static const char *bsplineShaderSource =
|
||||
#include "glslPatchBSpline.gen.h"
|
||||
;
|
||||
@ -52,11 +61,18 @@ static const char *gregoryShaderSource =
|
||||
static const char *gregoryBasisShaderSource =
|
||||
#include "glslPatchGregoryBasis.gen.h"
|
||||
;
|
||||
static const char *gregoryTriangleShaderSource =
|
||||
#include "glslPatchGregoryTriangle.gen.h"
|
||||
;
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
return std::string(commonShaderSource);
|
||||
std::stringstream ss;
|
||||
ss << std::string(commonShaderSource);
|
||||
ss << std::string(commonTessShaderSource);
|
||||
ss << std::string(patchLegacyShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
@ -82,6 +98,11 @@ GLSLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
<< "#define OSD_PATCH_VERTEX_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_VERTEX_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_SHADER\n"
|
||||
@ -97,6 +118,11 @@ GLSLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_VERTEX_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
@ -114,6 +140,11 @@ GLSLPatchShaderSource::GetTessControlShaderSource(
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_SHADER\n"
|
||||
@ -129,6 +160,11 @@ GLSLPatchShaderSource::GetTessControlShaderSource(
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_CONTROL_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
@ -146,6 +182,11 @@ GLSLPatchShaderSource::GetTessEvalShaderSource(
|
||||
<< "#define OSD_PATCH_TESS_EVAL_BSPLINE_SHADER\n"
|
||||
<< bsplineShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::LOOP:
|
||||
ss << "#define OSD_PATCH_BOX_SPLINE_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_BOX_SPLINE_TRIANGLE_SHADER\n"
|
||||
<< boxSplineTriangleShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
ss << "#define OSD_PATCH_GREGORY\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_SHADER\n"
|
||||
@ -161,6 +202,11 @@ GLSLPatchShaderSource::GetTessEvalShaderSource(
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_BASIS_SHADER\n"
|
||||
<< gregoryBasisShaderSource;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_TRIANGLE:
|
||||
ss << "#define OSD_PATCH_GREGORY_TRIANGLE\n"
|
||||
<< "#define OSD_PATCH_TESS_EVAL_GREGORY_TRIANGLE_SHADER\n"
|
||||
<< gregoryTriangleShaderSource;
|
||||
break;
|
||||
default:
|
||||
break; // returns empty (points, lines, quads, ...)
|
||||
}
|
||||
|
@ -31,9 +31,9 @@
|
||||
#define OSD_DATA_STORAGE_CLASS
|
||||
#define OSD_REAL float
|
||||
#define OSD_REAL_CAST float
|
||||
#define OSD_ARG_ARRAY_BOUND_OPTIONAL false
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 0
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
elementType identifier[arraySize]
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
@ -61,9 +61,9 @@
|
||||
#define OSD_DATA_STORAGE_CLASS
|
||||
#define OSD_REAL float
|
||||
#define OSD_REAL_CAST float
|
||||
#define OSD_ARG_ARRAY_BOUND_OPTIONAL false
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 0
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
elementType identifier[arraySize]
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
@ -93,7 +93,7 @@
|
||||
#define OSD_REAL_CAST float
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 0
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
elementType identifier[arraySize]
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
@ -123,7 +123,7 @@
|
||||
#define OSD_REAL_CAST convert_float
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 0
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
elementType identifier[arraySize]
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
@ -153,7 +153,7 @@
|
||||
#define OSD_REAL_CAST float
|
||||
#define OSD_OPTIONAL(a) true
|
||||
#define OSD_OPTIONAL_INIT(a,b) b
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL false
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 0
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
thread elementType* identifier
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
@ -183,7 +183,7 @@
|
||||
#define OSD_REAL_CAST float
|
||||
#define OSD_OPTIONAL(a) (a)
|
||||
#define OSD_OPTIONAL_INIT(a,b) (a ? b : 0)
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL true
|
||||
#define OSD_ARRAY_ARG_BOUND_OPTIONAL 1
|
||||
#define OSD_IN_ARRAY(elementType, identifier, arraySize) \
|
||||
elementType identifier[arraySize]
|
||||
#define OSD_OUT_ARRAY(elementType, identifier, arraySize) \
|
||||
|
Loading…
Reference in New Issue
Block a user