2012-12-11 01:15:13 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2012-12-11 01:15:13 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 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:
|
2012-12-11 01:15:13 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 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.
|
2012-12-11 01:15:13 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2012-12-11 01:15:13 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 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.
|
2012-12-11 01:15:13 +00:00
|
|
|
//
|
|
|
|
|
2013-10-08 02:02:41 +00:00
|
|
|
#if defined OSD_FRACTIONAL_ODD_SPACING
|
|
|
|
#define HS_PARTITION "fractional_odd"
|
|
|
|
#elif defined OSD_FRACTIONAL_EVEN_SPACING
|
|
|
|
#define HS_PARTITION "fractional_even"
|
|
|
|
#else
|
|
|
|
#define HS_PARTITION "integer"
|
|
|
|
#endif
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
//----------------------------------------------------------
|
|
|
|
// Patches.Coefficients
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
|
|
|
#if OSD_MAX_VALENCE<=10
|
|
|
|
static float ef[7] = {
|
|
|
|
0.813008, 0.500000, 0.363636, 0.287505,
|
|
|
|
0.238692, 0.204549, 0.179211
|
|
|
|
};
|
|
|
|
#else
|
|
|
|
static float ef[27] = {
|
|
|
|
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
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float cosfn(uint n, uint j) {
|
|
|
|
return cos((2.0f * M_PI * j)/float(n));
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float sinfn(uint n, uint j) {
|
|
|
|
return sin((2.0f * M_PI * j)/float(n));
|
|
|
|
}
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
//----------------------------------------------------------
|
|
|
|
// Patches.TessVertexGregory
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
Buffer<float> OsdVertexBuffer : register( t2 );
|
2015-05-20 21:36:57 +00:00
|
|
|
Buffer<int> OsdValenceBuffer : register( t3 );
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 OsdReadVertex(uint vertexIndex)
|
|
|
|
{
|
|
|
|
int index = int(OSD_NUM_ELEMENTS * (vertexIndex /*+ OsdBaseVertex()*/));
|
|
|
|
return float3(OsdVertexBuffer[index],
|
|
|
|
OsdVertexBuffer[index+1],
|
|
|
|
OsdVertexBuffer[index+2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
int OsdReadVertexValence(int vertexID)
|
|
|
|
{
|
|
|
|
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1));
|
|
|
|
return OsdValenceBuffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
int OsdReadVertexIndex(int vertexID, uint valenceVertex)
|
|
|
|
{
|
|
|
|
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
|
|
|
return OsdValenceBuffer[index];
|
|
|
|
}
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
void vs_main_patches( in InputVertex input,
|
|
|
|
uint vID : SV_VertexID,
|
|
|
|
out GregHullVertex output )
|
|
|
|
{
|
2013-07-02 05:53:47 +00:00
|
|
|
OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(input.position);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
int ivalence = OsdReadVertexValence(vID);
|
2013-07-02 05:53:47 +00:00
|
|
|
output.valence = ivalence;
|
|
|
|
uint valence = uint(abs(ivalence));
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2014-10-04 23:22:43 +00:00
|
|
|
float3 f[OSD_MAX_VALENCE];
|
2013-07-02 05:53:47 +00:00
|
|
|
float3 pos = input.position.xyz;
|
|
|
|
float3 opos = float3(0,0,0);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2013-07-02 07:26:09 +00:00
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
output.org = input.position.xyz;
|
|
|
|
int boundaryEdgeNeighbors[2];
|
|
|
|
uint currNeighbor = 0;
|
|
|
|
uint ibefore = 0;
|
|
|
|
uint zerothNeighbor = 0;
|
|
|
|
#endif
|
|
|
|
|
2013-07-02 05:53:47 +00:00
|
|
|
for (uint i=0; i<valence; ++i) {
|
2014-10-04 23:22:43 +00:00
|
|
|
uint im=(i+valence-1)%valence;
|
|
|
|
uint ip=(i+1)%valence;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint idx_neighbor = uint(OsdReadVertexIndex(vID, 2*i));
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2013-07-02 07:26:09 +00:00
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
bool isBoundaryNeighbor = false;
|
2015-05-21 14:25:04 +00:00
|
|
|
int valenceNeighbor = OsdReadVertexValence(int(idx_neighbor));
|
2013-07-02 07:26:09 +00:00
|
|
|
|
|
|
|
if (valenceNeighbor < 0) {
|
|
|
|
isBoundaryNeighbor = true;
|
2014-02-13 19:26:50 +00:00
|
|
|
if (currNeighbor<2) {
|
|
|
|
boundaryEdgeNeighbors[currNeighbor] = int(idx_neighbor);
|
|
|
|
}
|
|
|
|
currNeighbor++;
|
2015-05-21 14:25:04 +00:00
|
|
|
if (currNeighbor == 1) {
|
2013-07-02 07:26:09 +00:00
|
|
|
ibefore = i;
|
|
|
|
zerothNeighbor = i;
|
|
|
|
} else {
|
|
|
|
if (i-ibefore == 1) {
|
|
|
|
int tmp = boundaryEdgeNeighbors[0];
|
|
|
|
boundaryEdgeNeighbors[0] = boundaryEdgeNeighbors[1];
|
|
|
|
boundaryEdgeNeighbors[1] = tmp;
|
|
|
|
zerothNeighbor = i;
|
2014-10-04 23:22:43 +00:00
|
|
|
}
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 neighbor = OsdReadVertex(idx_neighbor);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint idx_diagonal = uint(OsdReadVertexIndex(vID, 2*i + 1));
|
|
|
|
float3 diagonal = OsdReadVertex(idx_diagonal);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint idx_neighbor_p = uint(OsdReadVertexIndex(vID, 2*ip));
|
|
|
|
float3 neighbor_p = OsdReadVertex(idx_neighbor_p);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint idx_neighbor_m = uint(OsdReadVertexIndex(vID, 2*im));
|
|
|
|
float3 neighbor_m = OsdReadVertex(idx_neighbor_m);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint idx_diagonal_m = uint(OsdReadVertexIndex(vID, 2*im + 1));
|
|
|
|
float3 diagonal_m = OsdReadVertex(idx_diagonal_m);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2013-07-02 05:53:47 +00:00
|
|
|
f[i] = (pos * float(valence) + (neighbor_p + neighbor)*2.0f + diagonal) / (float(valence)+5.0f);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
opos += f[i];
|
2013-07-02 05:53:47 +00:00
|
|
|
output.r[i] = (neighbor_p-neighbor_m)/3.0f + (diagonal - diagonal_m)/6.0f;
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
opos /= valence;
|
|
|
|
output.position = float4(opos, 1.0f).xyz;
|
|
|
|
|
|
|
|
float3 e;
|
|
|
|
output.e0 = float3(0,0,0);
|
|
|
|
output.e1 = float3(0,0,0);
|
2013-07-02 05:53:47 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
for(uint i=0; i<valence; ++i) {
|
|
|
|
uint im = (i + valence -1) % valence;
|
2013-07-02 05:53:47 +00:00
|
|
|
e = 0.5f * (f[i] + f[im]);
|
2015-01-10 20:28:54 +00:00
|
|
|
output.e0 += cosfn(valence, i)*e;
|
|
|
|
output.e1 += sinfn(valence, i)*e;
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
output.e0 *= ef[valence - 3];
|
|
|
|
output.e1 *= ef[valence - 3];
|
2013-07-02 07:26:09 +00:00
|
|
|
|
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
output.zerothNeighbor = zerothNeighbor;
|
|
|
|
if (currNeighbor == 1) {
|
|
|
|
boundaryEdgeNeighbors[1] = boundaryEdgeNeighbors[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ivalence < 0) {
|
|
|
|
if (valence > 2) {
|
2015-05-21 14:25:04 +00:00
|
|
|
output.position = (OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
|
|
|
OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
|
|
|
4.0f * pos)/6.0f;
|
2013-07-02 07:26:09 +00:00
|
|
|
} else {
|
2014-10-04 23:22:43 +00:00
|
|
|
output.position = pos;
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
output.e0 = (OsdReadVertex(boundaryEdgeNeighbors[0]) -
|
|
|
|
OsdReadVertex(boundaryEdgeNeighbors[1]))/6.0;
|
2013-07-02 07:26:09 +00:00
|
|
|
|
|
|
|
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));
|
2014-10-04 23:22:43 +00:00
|
|
|
float beta_0 = s/(3.0f*k + c);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
int idx_diagonal = OsdReadVertexIndex(vID, 2*zerothNeighbor + 1);
|
2013-07-02 07:26:09 +00:00
|
|
|
idx_diagonal = abs(idx_diagonal);
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 diagonal = OsdReadVertex(idx_diagonal);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2014-10-04 23:22:43 +00:00
|
|
|
output.e1 = gamma * pos +
|
2015-05-21 14:25:04 +00:00
|
|
|
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[0]) +
|
|
|
|
alpha_0k * OsdReadVertex(boundaryEdgeNeighbors[1]) +
|
2013-07-02 07:26:09 +00:00
|
|
|
beta_0 * diagonal;
|
|
|
|
|
|
|
|
for (uint x=1; x<valence - 1; ++x) {
|
|
|
|
uint 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);
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
int idx_neighbor = OsdReadVertexIndex(vID, 2*curri);
|
2013-07-02 07:26:09 +00:00
|
|
|
idx_neighbor = abs(idx_neighbor);
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 neighbor = OsdReadVertex(idx_neighbor);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
idx_diagonal = OsdReadVertexIndex(vID, 2*curri + 1);
|
|
|
|
diagonal = OsdReadVertex(idx_diagonal);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2014-10-04 23:22:43 +00:00
|
|
|
output.e1 += alpha * neighbor + beta * diagonal;
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
output.e1 /= 3.0f;
|
2014-10-04 23:22:43 +00:00
|
|
|
}
|
2013-07-02 07:26:09 +00:00
|
|
|
#endif
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------
|
|
|
|
// Patches.HullGregory
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
Buffer<int> OsdQuadOffsetBuffer : register( t4 );
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
int OsdReadQuadOffset(int primitiveID, uint offsetVertex)
|
2012-12-11 01:15:13 +00:00
|
|
|
{
|
2015-05-21 14:25:04 +00:00
|
|
|
int index = int(4*primitiveID+OsdGregoryQuadOffsetBase() + offsetVertex);
|
|
|
|
return OsdQuadOffsetBuffer[index];
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[domain("quad")]
|
2013-10-08 02:02:41 +00:00
|
|
|
[partitioning(HS_PARTITION)]
|
2015-05-20 21:12:48 +00:00
|
|
|
[outputtopology("triangle_cw")]
|
2012-12-11 01:15:13 +00:00
|
|
|
[outputcontrolpoints(4)]
|
|
|
|
[patchconstantfunc("HSConstFunc")]
|
|
|
|
GregDomainVertex hs_main_patches(
|
|
|
|
in InputPatch<GregHullVertex, 4> patch,
|
|
|
|
uint primitiveID : SV_PrimitiveID,
|
|
|
|
in uint ID : SV_OutputControlPointID )
|
|
|
|
{
|
|
|
|
uint i = ID;
|
|
|
|
uint ip = (i+1)%4;
|
|
|
|
uint im = (i+3)%4;
|
2013-07-02 07:26:09 +00:00
|
|
|
uint valence = abs(patch[i].valence);
|
2013-07-02 05:53:47 +00:00
|
|
|
uint n = valence;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
GregDomainVertex output;
|
|
|
|
output.position = patch[ID].position;
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint start = uint(OsdReadQuadOffset(primitiveID, i)) & 0x00ffu;
|
|
|
|
uint prev = uint(OsdReadQuadOffset(primitiveID, i)) & 0xff00u;
|
2013-07-02 05:53:47 +00:00
|
|
|
prev = uint(prev/256);
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
uint start_m = uint(OsdReadQuadOffset(primitiveID, im)) & 0x00ffu;
|
|
|
|
uint prev_p = uint(OsdReadQuadOffset(primitiveID, ip)) & 0xff00u;
|
2013-07-02 07:26:09 +00:00
|
|
|
prev_p = uint(prev_p/256);
|
|
|
|
|
2013-07-02 05:53:47 +00:00
|
|
|
uint np = abs(patch[ip].valence);
|
|
|
|
uint nm = abs(patch[im].valence);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2014-10-04 23:22:43 +00:00
|
|
|
// Control Vertices based on :
|
|
|
|
// "Approximating Subdivision Surfaces with Gregory Patches for Hardware Tessellation"
|
2015-05-21 00:39:06 +00:00
|
|
|
// Loop, Schaefer, Ni, Castano (ACM ToG Siggraph Asia 2009)
|
2012-12-11 22:26:06 +00:00
|
|
|
//
|
|
|
|
// P3 e3- e2+ E2
|
|
|
|
// 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- E1
|
|
|
|
//
|
|
|
|
|
2013-07-02 07:26:09 +00:00
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
float3 Ep = float3(0.0f,0.0f,0.0f);
|
|
|
|
float3 Em = float3(0.0f,0.0f,0.0f);
|
|
|
|
float3 Fp = float3(0.0f,0.0f,0.0f);
|
|
|
|
float3 Fm = float3(0.0f,0.0f,0.0f);
|
|
|
|
|
|
|
|
float3 Em_ip;
|
|
|
|
if (patch[ip].valence < -2) {
|
|
|
|
uint j = (np + prev_p - patch[ip].zerothNeighbor) % np;
|
|
|
|
Em_ip = patch[ip].position + cos((M_PI*j)/float(np-1))*patch[ip].e0 + sin((M_PI*j)/float(np-1))*patch[ip].e1;
|
|
|
|
} else {
|
2015-01-10 20:28:54 +00:00
|
|
|
Em_ip = patch[ip].position + patch[ip].e0*cosfn(np, prev_p) + patch[ip].e1*sinfn(np, prev_p);
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float3 Ep_im;
|
|
|
|
if (patch[im].valence < -2) {
|
|
|
|
uint j = (nm + start_m - patch[im].zerothNeighbor) % nm;
|
|
|
|
Ep_im = patch[im].position + cos((M_PI*j)/float(nm-1))*patch[im].e0 + sin((M_PI*j)/float(nm-1))*patch[im].e1;
|
|
|
|
} else {
|
2015-01-10 20:28:54 +00:00
|
|
|
Ep_im = patch[im].position + patch[im].e0*cosfn(nm, start_m) + patch[im].e1*sinfn(nm, start_m);
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (patch[i].valence < 0) {
|
|
|
|
n = (n-1)*2;
|
|
|
|
}
|
|
|
|
if (patch[im].valence < 0) {
|
|
|
|
nm = (nm-1)*2;
|
2014-10-04 23:22:43 +00:00
|
|
|
}
|
2013-07-02 07:26:09 +00:00
|
|
|
if (patch[ip].valence < 0) {
|
|
|
|
np = (np-1)*2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (patch[i].valence > 2) {
|
2015-01-10 20:28:54 +00:00
|
|
|
Ep = patch[i].position + (patch[i].e0*cosfn(n, start) + patch[i].e1*sinfn(n, start));
|
|
|
|
Em = patch[i].position + (patch[i].e0*cosfn(n, prev) + patch[i].e1*sinfn(n, prev));
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float s1=3-2*cosfn(n,1)-cosfn(np,1);
|
|
|
|
float s2=2*cosfn(n,1);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
Fp = (cosfn(np,1)*patch[i].position + s1*Ep + s2*Em_ip + patch[i].r[start])/3.0f;
|
2013-07-02 17:06:24 +00:00
|
|
|
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
2015-01-10 20:28:54 +00:00
|
|
|
Fm = (cosfn(nm,1)*patch[i].position + s1*Em + s2*Ep_im - patch[i].r[prev])/3.0f;
|
2013-07-02 07:26:09 +00:00
|
|
|
|
|
|
|
} else if (patch[i].valence < -2) {
|
|
|
|
uint j = (valence + start - patch[i].zerothNeighbor) % valence;
|
|
|
|
|
|
|
|
Ep = patch[i].position + cos((M_PI*j)/float(valence-1))*patch[i].e0 + sin((M_PI*j)/float(valence-1))*patch[i].e1;
|
|
|
|
j = (valence + prev - patch[i].zerothNeighbor) % valence;
|
|
|
|
Em = patch[i].position + cos((M_PI*j)/float(valence-1))*patch[i].e0 + sin((M_PI*j)/float(valence-1))*patch[i].e1;
|
|
|
|
|
|
|
|
float3 Rp = ((-2.0f * patch[i].org - 1.0f * patch[im].org) + (2.0f * patch[ip].org + 1.0f * patch[(i+2)%4].org))/3.0f;
|
|
|
|
float3 Rm = ((-2.0f * patch[i].org - 1.0f * patch[ip].org) + (2.0f * patch[im].org + 1.0f * patch[(i+2)%4].org))/3.0f;
|
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
|
|
|
float s2 = 2*cosfn(n,1);
|
2013-07-02 07:26:09 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
Fp = (cosfn(np,1)*patch[i].position + s1*Ep + s2*Em_ip + patch[i].r[start])/3.0f;
|
2013-07-02 17:06:24 +00:00
|
|
|
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
2015-01-10 20:28:54 +00:00
|
|
|
Fm = (cosfn(nm,1)*patch[i].position + s1*Em + s2*Ep_im - patch[i].r[prev])/3.0f;
|
2013-07-02 07:26:09 +00:00
|
|
|
|
|
|
|
if (patch[im].valence < 0) {
|
2015-01-10 20:28:54 +00:00
|
|
|
s1=3-2*cosfn(n,1)-cosfn(np,1);
|
|
|
|
Fp = Fm = (cosfn(np,1)*patch[i].position + s1*Ep + s2*Em_ip + patch[i].r[start])/3.0f;
|
2013-07-02 07:26:09 +00:00
|
|
|
} else if (patch[ip].valence < 0) {
|
|
|
|
s1 = 3.0f-2.0f*cos(2.0f*M_PI/n)-cos(2.0f*M_PI/nm);
|
2015-01-10 20:28:54 +00:00
|
|
|
Fm = Fp = (cosfn(nm,1)*patch[i].position + s1*Em + s2*Ep_im - patch[i].r[prev])/3.0f;
|
2013-07-02 07:26:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (patch[i].valence == -2) {
|
|
|
|
Ep = (2.0f * patch[i].org + patch[ip].org)/3.0f;
|
|
|
|
Em = (2.0f * patch[i].org + patch[im].org)/3.0f;
|
|
|
|
Fp = Fm = (4.0f * patch[i].org + patch[(i+2)%n].org + 2.0f * patch[ip].org + 2.0f * patch[im].org)/9.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else // not OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float3 Ep = patch[i].position + patch[i].e0 * cosfn(n, start) + patch[i].e1*sinfn(n, start);
|
|
|
|
float3 Em = patch[i].position + patch[i].e0 * cosfn(n, prev ) + patch[i].e1*sinfn(n, prev );
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float3 Em_ip = patch[ip].position + patch[ip].e0*cosfn(np, prev_p) + patch[ip].e1*sinfn(np, prev_p);
|
|
|
|
float3 Ep_im = patch[im].position + patch[im].e0*cosfn(nm, start_m) + patch[im].e1*sinfn(nm, start_m);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float s1 = 3-2*cosfn(n,1)-cosfn(np,1);
|
|
|
|
float s2 = 2*cosfn(n,1);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-01-10 20:28:54 +00:00
|
|
|
float3 Fp = (cosfn(np,1)*patch[i].position + s1*Ep + s2*Em_ip + patch[i].r[start])/3.0f;
|
2013-07-02 17:06:24 +00:00
|
|
|
s1 = 3.0f-2.0f*cos(2.0f*M_PI/float(n))-cos(2.0f*M_PI/float(nm));
|
2015-01-10 20:28:54 +00:00
|
|
|
float3 Fm = (cosfn(nm,1)*patch[i].position + s1*Em +s2*Ep_im - patch[i].r[prev])/3.0f;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2013-07-02 07:26:09 +00:00
|
|
|
#endif
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
output.Ep = Ep;
|
|
|
|
output.Em = Em;
|
|
|
|
output.Fp = Fp;
|
|
|
|
output.Fm = Fm;
|
|
|
|
|
Updated handling of patchParam and patchCoord
Each patch has a corresponding patchParam. This is a set of three values
specifying additional information about the patch:
faceId -- topological face identifier (e.g. Ptex FaceId)
bitfield -- refinement-level, non-quad, boundary, transition, uv-offset
sharpness -- crease sharpness for a single-crease patch
These are stored in OsdPatchParamBuffer indexed by the value returned
from OsdGetPatchIndex() which is a function of the current PrimitiveID
along with an optional client provided offset.
Accessors are provided to extract values from a patchParam. These are
all named OsdGetPatch*().
While drawing patches, the patchParam is condensed into a patchCoord which
has four values (u, v, faceLevel, faceId). These patchCoords are treated
as int values during per-prim processing but are converted to float values
during per-vertex processing where the values are interpolated.
Also, cleaned up more of the shader namespace by giving an Osd prefix
to public functions, and consolidated boundary and transition handling
code into the PatchCommon shader files. The functions determining
tessellation levels are now all named OsdGetTessLevel*().
2015-05-02 00:52:37 +00:00
|
|
|
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
2012-12-11 01:15:13 +00:00
|
|
|
|
Updated handling of patchParam and patchCoord
Each patch has a corresponding patchParam. This is a set of three values
specifying additional information about the patch:
faceId -- topological face identifier (e.g. Ptex FaceId)
bitfield -- refinement-level, non-quad, boundary, transition, uv-offset
sharpness -- crease sharpness for a single-crease patch
These are stored in OsdPatchParamBuffer indexed by the value returned
from OsdGetPatchIndex() which is a function of the current PrimitiveID
along with an optional client provided offset.
Accessors are provided to extract values from a patchParam. These are
all named OsdGetPatch*().
While drawing patches, the patchParam is condensed into a patchCoord which
has four values (u, v, faceLevel, faceId). These patchCoords are treated
as int values during per-prim processing but are converted to float values
during per-vertex processing where the values are interpolated.
Also, cleaned up more of the shader namespace by giving an Osd prefix
to public functions, and consolidated boundary and transition handling
code into the PatchCommon shader files. The functions determining
tessellation levels are now all named OsdGetTessLevel*().
2015-05-02 00:52:37 +00:00
|
|
|
output.patchCoord = OsdGetPatchCoord(patchParam);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
HS_CONSTANT_FUNC_OUT HSConstFunc(
|
|
|
|
InputPatch<GregHullVertex, 4> patch,
|
|
|
|
uint primitiveID : SV_PrimitiveID)
|
|
|
|
{
|
|
|
|
HS_CONSTANT_FUNC_OUT output;
|
|
|
|
|
|
|
|
int3 patchParam = OsdGetPatchParam(OsdGetPatchIndex(primitiveID));
|
|
|
|
|
|
|
|
OSD_PATCH_CULL(4);
|
|
|
|
|
|
|
|
float4 tessLevelOuter = float4(0,0,0,0);
|
|
|
|
float4 tessLevelInner = float4(0,0,0,0);
|
|
|
|
|
|
|
|
OsdGetTessLevels(patch[0].position.xyz, patch[3].position.xyz,
|
|
|
|
patch[2].position.xyz, patch[1].position.xyz,
|
|
|
|
patchParam, tessLevelOuter, tessLevelInner);
|
|
|
|
|
|
|
|
output.tessLevelOuter[0] = tessLevelOuter[0];
|
|
|
|
output.tessLevelOuter[1] = tessLevelOuter[1];
|
|
|
|
output.tessLevelOuter[2] = tessLevelOuter[2];
|
|
|
|
output.tessLevelOuter[3] = tessLevelOuter[3];
|
|
|
|
|
|
|
|
output.tessLevelInner[0] = tessLevelInner[0];
|
|
|
|
output.tessLevelInner[1] = tessLevelInner[1];
|
|
|
|
|
|
|
|
output.tessOuterLo = float4(0,0,0,0);
|
|
|
|
output.tessOuterHi = float4(0,0,0,0);
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
//----------------------------------------------------------
|
|
|
|
// Patches.DomainGregory
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
|
|
|
[domain("quad")]
|
|
|
|
void ds_main_patches(
|
|
|
|
in HS_CONSTANT_FUNC_OUT input,
|
|
|
|
in OutputPatch<GregDomainVertex, 4> patch,
|
2015-05-21 14:25:04 +00:00
|
|
|
in float2 UV : SV_DomainLocation,
|
2012-12-11 01:15:13 +00:00
|
|
|
out OutputVertex output )
|
|
|
|
{
|
|
|
|
float3 p[20];
|
|
|
|
|
|
|
|
p[0] = patch[0].position;
|
|
|
|
p[1] = patch[0].Ep;
|
|
|
|
p[2] = patch[0].Em;
|
|
|
|
p[3] = patch[0].Fp;
|
|
|
|
p[4] = patch[0].Fm;
|
|
|
|
|
|
|
|
p[5] = patch[1].position;
|
|
|
|
p[6] = patch[1].Ep;
|
|
|
|
p[7] = patch[1].Em;
|
|
|
|
p[8] = patch[1].Fp;
|
|
|
|
p[9] = patch[1].Fm;
|
|
|
|
|
|
|
|
p[10] = patch[2].position;
|
|
|
|
p[11] = patch[2].Ep;
|
|
|
|
p[12] = patch[2].Em;
|
|
|
|
p[13] = patch[2].Fp;
|
|
|
|
p[14] = patch[2].Fm;
|
|
|
|
|
|
|
|
p[15] = patch[3].position;
|
|
|
|
p[16] = patch[3].Ep;
|
|
|
|
p[17] = patch[3].Em;
|
|
|
|
p[18] = patch[3].Fp;
|
|
|
|
p[19] = patch[3].Fm;
|
|
|
|
|
|
|
|
float3 q[16];
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float u = UV.x, v=UV.y;
|
2012-12-11 01:15:13 +00:00
|
|
|
float U = 1-u, V=1-v;
|
|
|
|
|
|
|
|
float d11 = u+v; if(u+v==0.0f) d11 = 1.0f;
|
|
|
|
float d12 = U+v; if(U+v==0.0f) d12 = 1.0f;
|
|
|
|
float d21 = u+V; if(u+V==0.0f) d21 = 1.0f;
|
|
|
|
float d22 = U+V; if(U+V==0.0f) d22 = 1.0f;
|
|
|
|
|
|
|
|
q[ 5] = (u*p[3] + v*p[4])/d11;
|
|
|
|
q[ 6] = (U*p[9] + v*p[8])/d12;
|
|
|
|
q[ 9] = (u*p[19] + V*p[18])/d21;
|
|
|
|
q[10] = (U*p[13] + V*p[14])/d22;
|
|
|
|
|
|
|
|
q[ 0] = p[0];
|
|
|
|
q[ 1] = p[1];
|
|
|
|
q[ 2] = p[7];
|
|
|
|
q[ 3] = p[5];
|
|
|
|
q[ 4] = p[2];
|
|
|
|
q[ 7] = p[6];
|
|
|
|
q[ 8] = p[16];
|
|
|
|
q[11] = p[12];
|
|
|
|
q[12] = p[15];
|
|
|
|
q[13] = p[17];
|
|
|
|
q[14] = p[11];
|
|
|
|
q[15] = p[10];
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 position = float3(0, 0, 0);
|
|
|
|
float3 uTangent = float3(0, 0, 0);
|
|
|
|
float3 vTangent = float3(0, 0, 0);
|
2013-10-08 02:02:41 +00:00
|
|
|
|
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
|
|
|
float B[4], D[4], C[4];
|
2014-10-04 23:22:43 +00:00
|
|
|
float3 BUCP[4] = {float3(0,0,0), float3(0,0,0), float3(0,0,0), float3(0,0,0)},
|
|
|
|
DUCP[4] = {float3(0,0,0), float3(0,0,0), float3(0,0,0), float3(0,0,0)},
|
|
|
|
CUCP[4] = {float3(0,0,0), float3(0,0,0), float3(0,0,0), float3(0,0,0)};
|
2013-10-08 02:02:41 +00:00
|
|
|
float3 dUU = float3(0, 0, 0);
|
|
|
|
float3 dVV = float3(0, 0, 0);
|
|
|
|
float3 dUV = float3(0, 0, 0);
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
Univar4x4(UV.x, B, D, C);
|
2013-10-08 02:02:41 +00:00
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (uint j=0; j<4; ++j) {
|
2015-05-20 21:12:48 +00:00
|
|
|
float3 A = q[4*i + j];
|
2013-10-08 02:02:41 +00:00
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
|
|
|
CUCP[i] += A * C[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
Univar4x4(UV.y, B, D, C);
|
2013-10-08 02:02:41 +00:00
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
2015-05-21 14:25:04 +00:00
|
|
|
position += B[i] * BUCP[i];
|
|
|
|
uTangent += B[i] * DUCP[i];
|
|
|
|
vTangent += D[i] * BUCP[i];
|
2013-10-08 02:02:41 +00:00
|
|
|
dUU += B[i] * CUCP[i];
|
|
|
|
dVV += C[i] * BUCP[i];
|
|
|
|
dUV += D[i] * DUCP[i];
|
|
|
|
}
|
|
|
|
|
Updated handling of patchParam and patchCoord
Each patch has a corresponding patchParam. This is a set of three values
specifying additional information about the patch:
faceId -- topological face identifier (e.g. Ptex FaceId)
bitfield -- refinement-level, non-quad, boundary, transition, uv-offset
sharpness -- crease sharpness for a single-crease patch
These are stored in OsdPatchParamBuffer indexed by the value returned
from OsdGetPatchIndex() which is a function of the current PrimitiveID
along with an optional client provided offset.
Accessors are provided to extract values from a patchParam. These are
all named OsdGetPatch*().
While drawing patches, the patchParam is condensed into a patchCoord which
has four values (u, v, faceLevel, faceId). These patchCoords are treated
as int values during per-prim processing but are converted to float values
during per-vertex processing where the values are interpolated.
Also, cleaned up more of the shader namespace by giving an Osd prefix
to public functions, and consolidated boundary and transition handling
code into the PatchCommon shader files. The functions determining
tessellation levels are now all named OsdGetTessLevel*().
2015-05-02 00:52:37 +00:00
|
|
|
int level = patch[0].patchCoord.z;
|
2015-05-21 14:25:04 +00:00
|
|
|
uTangent *= 3 * level;
|
|
|
|
vTangent *= 3 * level;
|
2013-10-08 02:02:41 +00:00
|
|
|
dUU *= 6 * level;
|
|
|
|
dVV *= 6 * level;
|
|
|
|
dUV *= 9 * level;
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 n = cross(uTangent, vTangent);
|
2013-10-08 02:02:41 +00:00
|
|
|
float3 normal = normalize(n);
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float E = dot(uTangent, uTangent);
|
|
|
|
float F = dot(uTangent, vTangent);
|
|
|
|
float G = dot(vTangent, vTangent);
|
2013-10-08 02:02:41 +00:00
|
|
|
float e = dot(normal, dUU);
|
|
|
|
float f = dot(normal, dUV);
|
|
|
|
float g = dot(normal, dVV);
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 Nu = (f*F-e*G)/(E*G-F*F) * uTangent + (e*F-f*E)/(E*G-F*F) * vTangent;
|
|
|
|
float3 Nv = (g*F-f*G)/(E*G-F*F) * uTangent + (f*F-g*E)/(E*G-F*F) * vTangent;
|
2013-10-08 02:02:41 +00:00
|
|
|
|
|
|
|
Nu = Nu/length(n) - n * (dot(Nu,n)/pow(dot(n,n), 1.5));
|
|
|
|
Nv = Nv/length(n) - n * (dot(Nv,n)/pow(dot(n,n), 1.5));
|
|
|
|
|
|
|
|
output.Nu = Nu;
|
|
|
|
output.Nv = Nv;
|
|
|
|
#else
|
2012-12-11 01:15:13 +00:00
|
|
|
float B[4], D[4];
|
2014-10-04 23:22:43 +00:00
|
|
|
float3 BUCP[4] = {float3(0,0,0), float3(0,0,0), float3(0,0,0), float3(0,0,0)},
|
|
|
|
DUCP[4] = {float3(0,0,0), float3(0,0,0), float3(0,0,0), float3(0,0,0)};
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
Univar4x4(UV.x, B, D);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (uint j=0; j<4; ++j) {
|
2015-05-20 21:12:48 +00:00
|
|
|
float3 A = q[4*i + j];
|
2012-12-11 01:15:13 +00:00
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
Univar4x4(UV.y, B, D);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
for (uint i=0; i<4; ++i) {
|
2015-05-21 14:25:04 +00:00
|
|
|
position += B[i] * BUCP[i];
|
|
|
|
uTangent += B[i] * DUCP[i];
|
|
|
|
vTangent += D[i] * BUCP[i];
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|
Updated handling of patchParam and patchCoord
Each patch has a corresponding patchParam. This is a set of three values
specifying additional information about the patch:
faceId -- topological face identifier (e.g. Ptex FaceId)
bitfield -- refinement-level, non-quad, boundary, transition, uv-offset
sharpness -- crease sharpness for a single-crease patch
These are stored in OsdPatchParamBuffer indexed by the value returned
from OsdGetPatchIndex() which is a function of the current PrimitiveID
along with an optional client provided offset.
Accessors are provided to extract values from a patchParam. These are
all named OsdGetPatch*().
While drawing patches, the patchParam is condensed into a patchCoord which
has four values (u, v, faceLevel, faceId). These patchCoords are treated
as int values during per-prim processing but are converted to float values
during per-vertex processing where the values are interpolated.
Also, cleaned up more of the shader namespace by giving an Osd prefix
to public functions, and consolidated boundary and transition handling
code into the PatchCommon shader files. The functions determining
tessellation levels are now all named OsdGetTessLevel*().
2015-05-02 00:52:37 +00:00
|
|
|
int level = patch[0].patchCoord.z;
|
2015-05-21 14:25:04 +00:00
|
|
|
uTangent *= 3 * level;
|
|
|
|
vTangent *= 3 * level;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
float3 normal = normalize(cross(uTangent, vTangent));
|
2013-10-08 02:02:41 +00:00
|
|
|
#endif
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
output.position = mul(OsdModelViewMatrix(), float4(position, 1.0f));
|
|
|
|
output.normal = mul(OsdModelViewMatrix(), float4(normal, 0.0f)).xyz;
|
|
|
|
output.tangent = mul(OsdModelViewMatrix(), float4(uTangent, 0.0f)).xyz;
|
|
|
|
output.bitangent = mul(OsdModelViewMatrix(), float4(vTangent, 0.0f)).xyz;
|
2012-12-11 01:15:13 +00:00
|
|
|
|
Updated handling of patchParam and patchCoord
Each patch has a corresponding patchParam. This is a set of three values
specifying additional information about the patch:
faceId -- topological face identifier (e.g. Ptex FaceId)
bitfield -- refinement-level, non-quad, boundary, transition, uv-offset
sharpness -- crease sharpness for a single-crease patch
These are stored in OsdPatchParamBuffer indexed by the value returned
from OsdGetPatchIndex() which is a function of the current PrimitiveID
along with an optional client provided offset.
Accessors are provided to extract values from a patchParam. These are
all named OsdGetPatch*().
While drawing patches, the patchParam is condensed into a patchCoord which
has four values (u, v, faceLevel, faceId). These patchCoords are treated
as int values during per-prim processing but are converted to float values
during per-vertex processing where the values are interpolated.
Also, cleaned up more of the shader namespace by giving an Osd prefix
to public functions, and consolidated boundary and transition handling
code into the PatchCommon shader files. The functions determining
tessellation levels are now all named OsdGetTessLevel*().
2015-05-02 00:52:37 +00:00
|
|
|
output.patchCoord = OsdInterpolatePatchCoord(UV, patch[0].patchCoord);
|
2012-12-11 01:15:13 +00:00
|
|
|
|
|
|
|
OSD_DISPLACEMENT_CALLBACK;
|
|
|
|
|
2015-05-21 14:25:04 +00:00
|
|
|
output.positionOut = mul(OsdProjectionMatrix(), output.position);
|
|
|
|
output.edgeDistance = 0;
|
2012-12-11 01:15:13 +00:00
|
|
|
}
|