mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-29 03:01:24 +00:00
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:
parent
60a0fd783a
commit
866b88b7c9
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 &
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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; \
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user