Add support for single-crease patches to D3D draw context & controller

- also updated the dxViewer code example

note: dxPtexViewer still needs to be updated
This commit is contained in:
manuelk 2015-02-08 17:31:55 -08:00
parent 60a0fd783a
commit 866b88b7c9
10 changed files with 318 additions and 62 deletions

View File

@ -122,7 +122,8 @@ enum HudCheckBox { kHUD_CB_DISPLAY_CAGE_EDGES,
kHUD_CB_VIEW_LOD,
kHUD_CB_FRACTIONAL_SPACING,
kHUD_CB_PATCH_CULL,
kHUD_CB_FREEZE };
kHUD_CB_FREEZE,
kHUD_CB_DISPLAY_PATCH_COUNTS };
int g_currentShape = 0;
@ -133,6 +134,7 @@ int g_frame = 0,
int g_freeze = 0,
g_wire = 2,
g_adaptive = 1,
g_singleCreasePatch = 1,
g_drawCageEdges = 1,
g_drawCageVertices = 0,
g_drawPatchCVs = 0,
@ -142,7 +144,8 @@ int g_freeze = 0,
int g_displayPatchColor = 1,
g_screenSpaceTess = 0,
g_fractionalSpacing = 0,
g_patchCull = 0;
g_patchCull = 0,
g_displayPatchCounts = 0;
float g_rotate[2] = {0, 0},
g_prev_x = 0,
@ -314,10 +317,12 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme=
g_scheme = scheme;
// Adaptive refinement currently supported only for catmull-clark scheme
bool doAdaptive = (g_adaptive!=0 and g_scheme==kCatmark);
bool doAdaptive = (g_adaptive!=0 and g_scheme==kCatmark),
doSingleCreasePatch = (g_singleCreasePatch!=0 and g_scheme==kCatmark);
OpenSubdiv::Osd::MeshBitset bits;
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
int numVertexElements = 6;
int numVaryingElements = 0;
@ -827,9 +832,24 @@ display() {
#endif
// patch drawing
int patchCount[12][6][4]; // [Type][Pattern][Rotation] (see far/patchTables.h)
int numTotalPatches = 0;
int numDrawCalls = 0;
for (int i=0; i<(int)patches.size(); ++i) {
OpenSubdiv::Osd::DrawContext::PatchArray const & patch = patches[i];
OpenSubdiv::Osd::DrawContext::PatchDescriptor desc = patch.GetDescriptor();
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
int patchPattern = desc.GetPattern();
int patchRotation = desc.GetRotation();
int subPatch = desc.GetSubPatch();
if (subPatch == 0) {
patchCount[patchType][patchPattern][patchRotation] += patch.GetNumPatches();
}
numTotalPatches += patch.GetNumPatches();
D3D11_PRIMITIVE_TOPOLOGY topology;
if (g_mesh->GetDrawContext()->IsAdaptive()) {
@ -869,10 +889,61 @@ display() {
g_pd3dDeviceContext->DrawIndexed(patch.GetNumIndices(), patch.GetVertIndex(), 0);
}
g_fpsTimer.Stop();
float elapsed = (float)g_fpsTimer.GetElapsed();
g_fpsTimer.Start();
if (g_hud->IsVisible()) {
g_fpsTimer.Stop();
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
double fps = 1.0/g_fpsTimer.GetElapsed();
g_fpsTimer.Start();
if (g_displayPatchCounts) {
int x = -280;
int y = -480;
g_hud->DrawString(x, y, "NonPatch : %d",
patchCount[Descriptor::QUADS][0][0]); y += 20;
g_hud->DrawString(x, y, "Regular : %d",
patchCount[Descriptor::REGULAR][0][0]); y+= 20;
g_hud->DrawString(x, y, "Boundary : %d",
patchCount[Descriptor::BOUNDARY][0][0]); y+= 20;
g_hud->DrawString(x, y, "Corner : %d",
patchCount[Descriptor::CORNER][0][0]); y+= 20;
g_hud->DrawString(x, y, "Single Crease : %d",
patchCount[Descriptor::SINGLE_CREASE][0][0]); y+= 20;
g_hud->DrawString(x, y, "Gregory : %d",
patchCount[Descriptor::GREGORY][0][0]); y+= 20;
g_hud->DrawString(x, y, "Boundary Gregory : %d",
patchCount[Descriptor::GREGORY_BOUNDARY][0][0]); 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;
}
}
g_hud->DrawString(10, -120, "Tess level : %d", g_tessLevel);
g_hud->DrawString(10, -100, "Control Vertices = %d", g_mesh->GetNumVertices());
@ -1063,6 +1134,12 @@ callbackAdaptive(bool checked, int a) {
createOsdMesh(g_defaultShapes[g_currentShape], g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme);
}
static void
callbackSingleCreasePatch(bool checked, int /* a */) {
g_singleCreasePatch = checked;
createOsdMesh(g_defaultShapes[g_currentShape], g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme);
}
static void
callbackCheckBox(bool checked, int button) {
switch (button) {
@ -1093,6 +1170,9 @@ callbackCheckBox(bool checked, int button) {
case kHUD_CB_FREEZE:
g_freeze = checked;
break;
case kHUD_CB_DISPLAY_PATCH_COUNTS:
g_displayPatchCounts = checked;
break;
}
}
@ -1140,6 +1220,7 @@ initHUD() {
g_hud->AddCheckBox("Frustum Patch Culling (B)", g_patchCull != 0, 10, 150, callbackCheckBox, kHUD_CB_PATCH_CULL, 'B');
g_hud->AddCheckBox("Adaptive (`)", true, 10, 190, callbackAdaptive, 0, '`');
g_hud->AddCheckBox("Single Crease Patch (S)", g_singleCreasePatch!=0, 10, 210, callbackSingleCreasePatch, 0, 's');
for (int i = 1; i < 11; ++i) {
char level[16];
@ -1152,6 +1233,8 @@ 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);
callbackModel(g_currentShape);
}

View File

@ -86,17 +86,11 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
pd3d11DeviceContext->GetDevice(&pd3d11Device);
assert(pd3d11Device);
DrawContext::ConvertPatchArrays(patchTables, _patchArrays,
patchTables.GetMaxValence(), numVertexElements);
// Process PTable
Far::PatchTables::PatchVertsTable const & ptables = patchTables.GetPatchControlVerticesTable();
Far::PatchParamTable const & ptexCoordTables = patchTables.GetPatchParamTable();
int totalPatchIndices = (int)ptables.size();
int totalPatches = (int)ptexCoordTables.size();
// Allocate and fill index buffer.
D3D11_BUFFER_DESC bd;
bd.ByteWidth = totalPatchIndices * sizeof(int);
bd.ByteWidth = (int)ptables.size() * sizeof(int);
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
@ -113,40 +107,66 @@ D3D11DrawContext::create(Far::PatchTables const &patchTables,
return false;
}
unsigned int * indexBuffer = (unsigned int *) mappedResource.pData;
memcpy(indexBuffer, &ptables[0], totalPatchIndices * sizeof(unsigned int));
memcpy(indexBuffer, &ptables[0], ptables.size() * sizeof(unsigned int));
pd3d11DeviceContext->Unmap(patchIndexBuffer, 0);
// create patch param buffer
bd.ByteWidth = totalPatches * sizeof(Far::PatchParam);
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = sizeof(unsigned int);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &ptexCoordinateBuffer);
if (FAILED(hr)) {
return false;
}
DrawContext::ConvertPatchArrays(patchTables, _patchArrays,
patchTables.GetMaxValence(), numVertexElements);
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
ZeroMemory(&srvd, sizeof(srvd));
srvd.Format = DXGI_FORMAT_R32G32_UINT;
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = totalPatches;
hr = pd3d11Device->CreateShaderResourceView(ptexCoordinateBuffer, &srvd, &ptexCoordinateBufferSRV);
if (FAILED(hr)) {
return false;
}
// allocate and initialize additional buffer data
hr = pd3d11DeviceContext->Map(ptexCoordinateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
return false;
// create ptex coordinate buffer
Far::PatchParamTable const & patchParamTables =
patchTables.GetPatchParamTable();
if (not patchParamTables.empty()) {
int numElements = (int)patchParamTables.size(),
elementSize = sizeof(Far::PatchParam);
unsigned int const * values =
reinterpret_cast<unsigned int const *>(&patchParamTables[0]);
std::vector<unsigned int> buffer;
bool useSingleCrease = not patchTables.GetSharpnessIndexTable().empty();
if (useSingleCrease) {
// if indexed sharpnesses exists, flatten them and interleave into 3-component buffer
packSharpnessValues(patchTables, buffer);
elementSize += sizeof(float);
values = &buffer[0];
}
bd.ByteWidth = numElements * elementSize;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
bd.StructureByteStride = sizeof(unsigned int);
hr = pd3d11Device->CreateBuffer(&bd, NULL, &ptexCoordinateBuffer);
if (FAILED(hr)) {
return false;
}
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
ZeroMemory(&srvd, sizeof(srvd));
srvd.Format = useSingleCrease ? DXGI_FORMAT_R32G32B32_UINT : DXGI_FORMAT_R32G32_UINT;
srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srvd.Buffer.FirstElement = 0;
srvd.Buffer.NumElements = numElements;
hr = pd3d11Device->CreateShaderResourceView(ptexCoordinateBuffer, &srvd, &ptexCoordinateBufferSRV);
if (FAILED(hr)) {
return false;
}
hr = pd3d11DeviceContext->Map(ptexCoordinateBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
return false;
}
unsigned int * ptexBuffer = (unsigned int *) mappedResource.pData;
memcpy(ptexBuffer, values, numElements * elementSize);
pd3d11DeviceContext->Unmap(ptexCoordinateBuffer, 0);
}
unsigned int * ptexBuffer = (unsigned int *) mappedResource.pData;
memcpy(ptexBuffer, &ptexCoordTables[0], totalPatches * sizeof(Far::PatchParam));
pd3d11DeviceContext->Unmap(ptexCoordinateBuffer, 0);
// create vertex valence buffer and vertex texture
Far::PatchTables::VertexValenceTable const &

View File

@ -97,6 +97,19 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig(
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";
@ -179,7 +192,10 @@ D3D11DrawRegistryBase::_CreateDrawSourceConfig(
sconfig->hullShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str());
sconfig->domainShader.AddDefine("OSD_TRANSITION_ROTATE", ss.str());
if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) {
if (desc.GetType() == Far::PatchDescriptor::SINGLE_CREASE) {
sconfig->hullShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
sconfig->domainShader.AddDefine("OSD_PATCH_SINGLE_CREASE");
} else if (desc.GetType() == Far::PatchDescriptor::BOUNDARY) {
sconfig->hullShader.AddDefine("OSD_PATCH_BOUNDARY");
} else if (desc.GetType() == Far::PatchDescriptor::CORNER) {
sconfig->hullShader.AddDefine("OSD_PATCH_CORNER");

View File

@ -199,6 +199,7 @@ private:
Far::PatchTablesFactory::Options options(level);
options.generateFVarTables = bits.test(MeshFVarData);
options.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
_patchTables = Far::PatchTablesFactory::Create(*_refiner, options);
@ -405,6 +406,7 @@ private:
Far::PatchTablesFactory::Options options(level);
options.generateFVarTables = bits.test(MeshFVarData);
options.useSingleCreasePatch = bits.test(MeshUseSingleCreasePatch);
_patchTables = Far::PatchTablesFactory::Create(*_refiner, options);

View File

@ -94,6 +94,33 @@ DrawContext::packPatchVerts(Far::PatchTables const & patchTables,
}
}
void
DrawContext::packSharpnessValues(Far::PatchTables const & patchTables,
std::vector<unsigned int> & dst) {
Far::PatchParamTable const & patchParamTables =
patchTables.GetPatchParamTable();
std::vector<int> const &sharpnessIndexTable =
patchTables.GetSharpnessIndexTable();
std::vector<float> const &sharpnessValues =
patchTables.GetSharpnessValues();
int npatches = (int)patchParamTables.size();
// PatchParam = sizeof(int)*2, 1 float for sharpness
dst.resize(npatches * (2 + 1));
for (size_t i = 0; i < npatches; ++i) {
float sharpness = sharpnessIndexTable[i] >= 0 ?
sharpnessValues[sharpnessIndexTable[i]] : 0.0f;
dst[i*3+0] = patchParamTables[i].faceIndex;
dst[i*3+1] = patchParamTables[i].bitField.field;
dst[i*3+2] = *((unsigned int *)&sharpness);
}
}
void
DrawContext::packFVarData(Far::PatchTables const & patchTables,
int fvarWidth, FVarData const & src, FVarData & dst) {

View File

@ -239,6 +239,9 @@ protected:
static void packPatchVerts(Far::PatchTables const & patchTables,
std::vector<Index> & dst);
static void packSharpnessValues(Far::PatchTables const & patchTables,
std::vector<unsigned int> & dst);
static void packFVarData(Far::PatchTables const & patchTables,
int fvarWidth, FVarData const & src, FVarData & dst);

View File

@ -164,27 +164,19 @@ GLDrawContext::create(Far::PatchTables const & patchTables, int numVertexElement
// create ptex coordinate buffer
Far::PatchParamTable const &
patchParamTables = patchTables.GetPatchParamTable();
Far::PatchParamTable const & patchParamTables =
patchTables.GetPatchParamTable();
if (not patchParamTables.empty()) {
std::vector<int> const &sharpnessIndexTable = patchTables.GetSharpnessIndexTable();
if (sharpnessIndexTable.empty()) {
if (patchTables.GetSharpnessIndexTable().empty()) {
_patchParamTextureBuffer = createTextureBuffer(patchParamTables, GL_RG32I);
} else {
// if indexed sharpnesses exists, flatten them and interleave into 3-component buffer
std::vector<float> const &sharpnessValues = patchTables.GetSharpnessValues();
size_t nPatches = patchParamTables.size();
// PatchParam = sizeof(int)*2, 1 float for sharpness
std::vector<unsigned int> buffer(nPatches * 3);
for (size_t i = 0; i < nPatches; ++i) {
float sharpness = sharpnessIndexTable[i] >=0 ?
sharpnessValues[sharpnessIndexTable[i]] : 0.0f;
buffer[i*3+0] = patchParamTables[i].faceIndex;
buffer[i*3+1] = patchParamTables[i].bitField.field;
buffer[i*3+2] = *((unsigned int *)&sharpness);
}
// if indexed sharpnesses exists, flatten them and interleave into 3-component buffer
std::vector<unsigned int> buffer;
packSharpnessValues(patchTables, buffer);
_patchParamTextureBuffer = createTextureBuffer(buffer, GL_RGB32I);
}

View File

@ -59,6 +59,14 @@ static float4x4 Q = {
0.f, 1.f/6.f, 4.f/6.f, 1.f/6.f
};
// Infinite sharp
static float4x4 Mi = {
1.f/6.f, 4.f/6.f, 1.f/6.f, 0.f,
0.f, 4.f/6.f, 2.f/6.f, 0.f,
0.f, 2.f/6.f, 4.f/6.f, 0.f,
0.f, 0.f, 1.f, 0.f
};
// Boundary / Corner
static float4x3 B = {
1.f, 0.f, 0.f,
@ -67,6 +75,27 @@ static float4x3 B = {
1.f/6.f, 4.f/6.f, 1.f/6.f
};
// compute single-crease patch matrix
float4x4
ComputeMatrixSimplified(float sharpness)
{
float s = pow(2.0f, sharpness);
float s2 = s*s;
float s3 = s2*s;
float4x4 m ={
0, s + 1 + 3*s2 - s3, 7*s - 2 - 6*s2 + 2*s3, (1-s)*(s-1)*(s-1),
0, (1+s)*(1+s), 6*s - 2 - 2*s2, (s-1)*(s-1),
0, 1+s, 6*s - 2, 1-s,
0, 1, 6*s - 2, 1 };
m /= (s*6.0);
m[0][0] = 1.0/6.0;
return m;
}
#ifdef OSD_PATCH_TRANSITION
HS_CONSTANT_TRANSITION_FUNC_OUT
#else
@ -92,7 +121,7 @@ HSConstFunc(
#ifdef OSD_PATCH_TRANSITION
float3 cp[OSD_PATCH_INPUT_SIZE];
for(int k = 0; k < OSD_PATCH_INPUT_SIZE; ++k) cp[k] = patch[k].position.xyz;
SetTransitionTessLevels(output, cp, patchLevel);
SetTransitionTessLevels(output, cp, patchLevel, primitiveID);
#else
#if defined OSD_PATCH_BOUNDARY
const int p[4] = { 1, 2, 5, 6 };
@ -172,15 +201,40 @@ HullVertex hs_main_patches(
}
}
#if defined OSD_PATCH_SINGLE_CREASE
float sharpness = GetSharpness(primitiveID);
float Sf = floor(sharpness);
float Sc = ceil(sharpness);
float Sr = frac(sharpness);
float4x4 Mf = ComputeMatrixSimplified(Sf);
float4x4 Mc = ComputeMatrixSimplified(Sc);
float4x4 Mj = (1-Sr) * Mf + Sr * Mi;
float4x4 Ms = (1-Sr) * Mf + Sr * Mc;
float3 pos = float3(0,0,0);
float3 P1 = float3(0,0,0);
float3 P2 = float3(0,0,0);
for (int k=0; k<4; ++k) {
pos += Mi[j][k]*H[k]; // 0 to 1-2^(-Sf)
P1 += Mj[j][k]*H[k]; // 1-2^(-Sf) to 1-2^(-Sc)
P2 += Ms[j][k]*H[k]; // 1-2^(-Sc) to 1
}
#else
float3 pos = float3(0,0,0);
for (int k=0; k<4; ++k){
pos += Q[j][k]*H[k];
}
#endif
#endif
HullVertex output;
output.position = float4(pos, 1.0);
#if defined OSD_PATCH_SINGLE_CREASE
output.P1 = float4(P1, 1.0);
output.P2 = float4(P2, 1.0);
output.sharpness = sharpness;
#endif
int patchLevel = GetPatchLevel(primitiveID);
@ -232,8 +286,35 @@ void ds_main_patches(
Univar4x4(UV.x, B, D);
#endif
#if defined OSD_PATCH_SINGLE_CREASE
float sharpness = patch[0].sharpness;
float s0 = 1.0 - pow(2.0f, -floor(sharpness));
float s1 = 1.0 - pow(2.0f, -ceil(sharpness));
#endif
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
#if defined OSD_PATCH_SINGLE_CREASE
#if OSD_TRANSITION_ROTATE == 1
int k = 4*(3-j) + i;
float s = 1-UV.x;
#elif OSD_TRANSITION_ROTATE == 2
int k = 4*(3-i) + (3-j);
float s = 1-UV.y;
#elif OSD_TRANSITION_ROTATE == 3
int k = 4*j + (3-i);
float s = UV.x;
#else // ROTATE=0 or non-transition
int k = 4*i + j;
float s = UV.y;
#endif
float3 A = (s < s0) ?
patch[k].position.xyz :
((s < s1) ?
patch[k].P1.xyz :
patch[k].P2.xyz);
#else // !SINGLE_CREASE
#if OSD_TRANSITION_ROTATE == 1
float3 A = patch[4*(3-j) + i].position.xyz;
#elif OSD_TRANSITION_ROTATE == 2
@ -242,6 +323,7 @@ void ds_main_patches(
float3 A = patch[4*j + (3-i)].position.xyz;
#else // OSD_TRANSITION_ROTATE == 0, or non-transition patch
float3 A = patch[4*i + j].position.xyz;
#endif
#endif
BUCP[i] += A * B[j];
DUCP[i] += A * D[j];

View File

@ -50,6 +50,11 @@ struct HullVertex {
float4 patchCoord : PATCHCOORD; // u, v, level, faceID
int4 ptexInfo : PTEXINFO; // u offset, v offset, 2^ptexlevel, rotation
int3 clipFlag : CLIPFLAG;
#if defined OSD_PATCH_SINGLE_CREASE
float4 P1 : POSITION1;
float4 P2 : POSITION2;
float sharpness : BLENDWEIGHT0;
#endif
};
struct OutputVertex {
@ -136,11 +141,18 @@ float TessAdaptive(float3 p0, float3 p1)
#define OSD_DISPLACEMENT_CALLBACK
#endif
Buffer<uint2> OsdPatchParamBuffer : register( t3 );
#if defined OSD_PATCH_SINGLE_CREASE
Buffer<uint3> OsdPatchParamBuffer : register( t3 );
#else
Buffer<uint2> OsdPatchParamBuffer : register( t3 );
#endif
#define GetPatchLevel(primitiveID) \
(OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].y & 0xf)
#define GetSharpness(primitiveID) \
(asfloat(OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].z))
#define OSD_COMPUTE_PTEX_COORD_HULL_SHADER \
{ \
int2 ptexIndex = OsdPatchParamBuffer[GetPrimitiveID(primitiveID)].xy; \

View File

@ -47,8 +47,8 @@ struct HS_CONSTANT_TRANSITION_FUNC_OUT {
//----------------------------------------------------------
void
SetTransitionTessLevels(inout HS_CONSTANT_TRANSITION_FUNC_OUT output, float3 cp[OSD_PATCH_INPUT_SIZE], int patchLevel)
{
SetTransitionTessLevels(inout HS_CONSTANT_TRANSITION_FUNC_OUT output, float3 cp[OSD_PATCH_INPUT_SIZE], int patchLevel, uint primitiveID) {
#ifdef OSD_ENABLE_SCREENSPACE_TESSELLATION
// These tables map the 9, 12, or 16 input control points onto the
// canonical 16 control points for a regular patch.
@ -146,6 +146,25 @@ SetTransitionTessLevels(inout HS_CONSTANT_TRANSITION_FUNC_OUT output, float3 cp[
vv0 = pv5;
vv1 = (pv5 + pv7) * 0.125 + pv6 * 0.75;
#endif
#elif defined OSD_PATCH_SINGLE_CREASE
// apply smooth, sharp or fractional-semisharp (linear interpolate) rules
float weight = min(1, GetSharpness(primitiveID));
// XXX: current rotation of single-crease patch is inconsistent
// to boundary patch. should be fixed.
#if OSD_TRANSITION_ROTATE == 2
vv0 = lerp(vv0, (pv4 + pv6) * 0.125 + pv5 * 0.75, weight);
vv1 = lerp(vv1, (pv5 + pv7) * 0.125 + pv6 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 3
vv1 = lerp(vv1, (pv2 + pv10) * 0.125 + pv6 * 0.75, weight);
vv2 = lerp(vv2, (pv6 + pv14) * 0.125 + pv10 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 0
vv2 = lerp(vv2, (pv9 + pv11) * 0.125 + pv10 * 0.75, weight);
vv3 = lerp(vv3, (pv8 + pv10) * 0.125 + pv9 * 0.75, weight);
#elif OSD_TRANSITION_ROTATE == 1
vv3 = lerp(vv3, (pv5 + pv13) * 0.125 + pv9 * 0.75, weight);
vv0 = lerp(vv0, (pv1 + pv9) * 0.125 + pv5 * 0.75, weight);
#endif
#endif
#ifdef OSD_TRANSITION_PATTERN00