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-06-24 19:03:57 +00:00
|
|
|
// Patches.Common
|
2012-12-11 01:15:13 +00:00
|
|
|
//----------------------------------------------------------
|
|
|
|
|
2015-04-18 21:00:23 +00:00
|
|
|
// XXXdyu-patch-drawing support for fractional spacing
|
|
|
|
#undef OSD_FRACTIONAL_ODD_SPACING
|
|
|
|
#undef OSD_FRACTIONAL_EVEN_SPACING
|
2013-06-24 19:03:57 +00:00
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
#if defined OSD_FRACTIONAL_ODD_SPACING
|
|
|
|
#define OSD_PARTITIONING "fractional_odd"
|
|
|
|
#elif defined OSD_FRACTIONAL_EVEN_SPACING
|
|
|
|
#define OSD_PARTITIONING "fractional_even"
|
|
|
|
#else
|
|
|
|
#define OSD_PARTITIONING "integer"
|
|
|
|
#endif
|
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
#define M_PI 3.14159265359f
|
|
|
|
|
|
|
|
struct InputVertex {
|
|
|
|
float4 position : POSITION;
|
|
|
|
float3 normal : NORMAL;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct HullVertex {
|
|
|
|
float4 position : POSITION;
|
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
|
|
|
#ifdef OSD_ENABLE_PATCH_CULL
|
2012-12-11 01:15:13 +00:00
|
|
|
int3 clipFlag : CLIPFLAG;
|
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
|
|
|
#endif
|
2012-12-11 01:15:13 +00:00
|
|
|
};
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
// XXXdyu all downstream data can be handled by client code
|
2012-12-11 01:15:13 +00:00
|
|
|
struct OutputVertex {
|
|
|
|
float4 positionOut : SV_Position;
|
|
|
|
float4 position : POSITION1;
|
|
|
|
float3 normal : NORMAL;
|
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
|
|
|
float3 tangent : TANGENT;
|
2013-10-08 02:02:41 +00:00
|
|
|
float3 bitangent : TANGENT1;
|
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
|
|
|
float4 patchCoord : PATCHCOORD; // u, v, faceLevel, faceId
|
2012-12-11 01:15:13 +00:00
|
|
|
noperspective float4 edgeDistance : EDGEDISTANCE;
|
2013-10-08 02:02:41 +00:00
|
|
|
#if defined(OSD_COMPUTE_NORMAL_DERIVATIVES)
|
|
|
|
float3 Nu : TANGENT2;
|
|
|
|
float3 Nv : TANGENT3;
|
|
|
|
#endif
|
2015-04-18 21:00:23 +00:00
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
2015-05-31 14:31:21 +00:00
|
|
|
float2 vSegments : VSEGMENTS;
|
2015-04-18 21:00:23 +00:00
|
|
|
#endif
|
2012-12-11 01:15:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct HS_CONSTANT_FUNC_OUT {
|
|
|
|
float tessLevelInner[2] : SV_InsideTessFactor;
|
|
|
|
float tessLevelOuter[4] : SV_TessFactor;
|
2015-04-18 21:00:23 +00:00
|
|
|
float4 tessOuterLo : TRANSITIONLO;
|
|
|
|
float4 tessOuterHi : TRANSITIONHI;
|
2012-12-11 01:15:13 +00:00
|
|
|
};
|
|
|
|
|
2013-12-03 23:59:38 +00:00
|
|
|
// osd shaders need following functions defined
|
|
|
|
float4x4 OsdModelViewMatrix();
|
|
|
|
float4x4 OsdProjectionMatrix();
|
|
|
|
float4x4 OsdModelViewProjectionMatrix();
|
|
|
|
float OsdTessLevel();
|
|
|
|
int OsdGregoryQuadOffsetBase();
|
|
|
|
int OsdPrimitiveIdBase();
|
2015-05-26 23:35:06 +00:00
|
|
|
int OsdBaseVertex();
|
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
|
|
|
#ifndef OSD_DISPLACEMENT_CALLBACK
|
|
|
|
#define OSD_DISPLACEMENT_CALLBACK
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Patch Parameters
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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 single-crease patches
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
2015-05-20 21:36:57 +00:00
|
|
|
Buffer<uint3> OsdPatchParamBuffer : register( t0 );
|
2012-12-11 01:15:13 +00:00
|
|
|
#else
|
2015-05-20 21:36:57 +00:00
|
|
|
Buffer<uint2> OsdPatchParamBuffer : register( t0 );
|
2012-12-11 01:15:13 +00:00
|
|
|
#endif
|
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 OsdGetPatchIndex(int primitiveId)
|
|
|
|
{
|
|
|
|
return (primitiveId + OsdPrimitiveIdBase());
|
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
|
|
|
int3 OsdGetPatchParam(int patchIndex)
|
|
|
|
{
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
|
|
|
return OsdPatchParamBuffer[patchIndex].xyz;
|
|
|
|
#else
|
|
|
|
uint2 p = OsdPatchParamBuffer[patchIndex].xy;
|
|
|
|
return int3(p.x, p.y, 0);
|
2013-12-03 23:59:38 +00:00
|
|
|
#endif
|
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
|
|
|
}
|
2013-12-03 23:59:38 +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 OsdGetPatchFaceId(int3 patchParam)
|
2013-01-05 03:15:24 +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
|
|
|
return patchParam.x;
|
2013-01-05 03:15:24 +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 OsdGetPatchFaceLevel(int3 patchParam)
|
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
|
|
|
return (1 << ((patchParam.y & 0x7) - ((patchParam.y >> 3) & 1)));
|
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 OsdGetPatchRefinementLevel(int3 patchParam)
|
|
|
|
{
|
|
|
|
return (patchParam.y & 0x7);
|
|
|
|
}
|
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 OsdGetPatchBoundaryMask(int3 patchParam)
|
|
|
|
{
|
|
|
|
return ((patchParam.y >> 4) & 0xf);
|
|
|
|
}
|
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 OsdGetPatchTransitionMask(int3 patchParam)
|
|
|
|
{
|
|
|
|
return ((patchParam.y >> 8) & 0xf);
|
|
|
|
}
|
2015-04-18 21:00:23 +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
|
|
|
int2 OsdGetPatchFaceUV(int3 patchParam)
|
|
|
|
{
|
|
|
|
int u = (patchParam.y >> 22) & 0x3ff;
|
|
|
|
int v = (patchParam.y >> 12) & 0x3ff;
|
|
|
|
return int2(u,v);
|
|
|
|
}
|
2013-12-03 23:59:38 +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
|
|
|
float OsdGetPatchSharpness(int3 patchParam)
|
|
|
|
{
|
|
|
|
return asfloat(patchParam.z);
|
|
|
|
}
|
2015-02-09 01:31:55 +00:00
|
|
|
|
2015-06-02 19:02:52 +00:00
|
|
|
float OsdGetPatchSingleCreaseSegmentParameter(int3 patchParam, float2 uv)
|
|
|
|
{
|
|
|
|
int boundaryMask = OsdGetPatchBoundaryMask(patchParam);
|
|
|
|
float s = 0;
|
|
|
|
if ((boundaryMask & 1) != 0) {
|
|
|
|
s = 1 - uv.y;
|
|
|
|
} else if ((boundaryMask & 2) != 0) {
|
|
|
|
s = uv.x;
|
|
|
|
} else if ((boundaryMask & 4) != 0) {
|
|
|
|
s = uv.y;
|
|
|
|
} else if ((boundaryMask & 8) != 0) {
|
|
|
|
s = 1 - uv.x;
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
int4 OsdGetPatchCoord(int3 patchParam)
|
|
|
|
{
|
|
|
|
int faceId = OsdGetPatchFaceId(patchParam);
|
|
|
|
int faceLevel = OsdGetPatchFaceLevel(patchParam);
|
|
|
|
int2 faceUV = OsdGetPatchFaceUV(patchParam);
|
|
|
|
return int4(faceUV.x, faceUV.y, faceLevel, faceId);
|
|
|
|
}
|
2012-12-11 01:15:13 +00:00
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
float4 OsdInterpolatePatchCoord(float2 localUV, int3 patchParam)
|
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
|
|
|
{
|
2015-05-26 23:35:06 +00:00
|
|
|
int4 perPrimPatchCoord = OsdGetPatchCoord(patchParam);
|
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 faceId = perPrimPatchCoord.w;
|
|
|
|
int faceLevel = perPrimPatchCoord.z;
|
|
|
|
float2 faceUV = float2(perPrimPatchCoord.x, perPrimPatchCoord.y);
|
|
|
|
float2 uv = localUV/faceLevel + faceUV/faceLevel;
|
2015-05-26 23:35:06 +00:00
|
|
|
// add 0.5 to integer values for more robust interpolation
|
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
|
|
|
return float4(uv.x, uv.y, faceLevel+0.5, faceId+0.5);
|
|
|
|
}
|
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
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// patch culling
|
|
|
|
// ----------------------------------------------------------------------------
|
2013-10-08 02:02:41 +00:00
|
|
|
|
2012-12-11 01:15:13 +00:00
|
|
|
#ifdef OSD_ENABLE_PATCH_CULL
|
|
|
|
|
|
|
|
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
2013-12-03 23:59:38 +00:00
|
|
|
float4 clipPos = mul(OsdModelViewProjectionMatrix(), P); \
|
2012-12-11 01:15:13 +00:00
|
|
|
int3 clip0 = int3(clipPos.x < clipPos.w, \
|
|
|
|
clipPos.y < clipPos.w, \
|
|
|
|
clipPos.z < clipPos.w); \
|
|
|
|
int3 clip1 = int3(clipPos.x > -clipPos.w, \
|
|
|
|
clipPos.y > -clipPos.w, \
|
|
|
|
clipPos.z > -clipPos.w); \
|
|
|
|
output.clipFlag = int3(clip0) + 2*int3(clip1); \
|
|
|
|
|
|
|
|
#define OSD_PATCH_CULL(N) \
|
|
|
|
int3 clipFlag = int3(0,0,0); \
|
|
|
|
for(int i = 0; i < N; ++i) { \
|
|
|
|
clipFlag |= patch[i].clipFlag; \
|
|
|
|
} \
|
|
|
|
if (any(clipFlag != int3(3,3,3))) { \
|
|
|
|
output.tessLevelInner[0] = 0; \
|
|
|
|
output.tessLevelInner[1] = 0; \
|
|
|
|
output.tessLevelOuter[0] = 0; \
|
|
|
|
output.tessLevelOuter[1] = 0; \
|
|
|
|
output.tessLevelOuter[2] = 0; \
|
|
|
|
output.tessLevelOuter[3] = 0; \
|
2015-05-31 14:31:21 +00:00
|
|
|
output.tessOuterLo = float4(0,0,0,0); \
|
|
|
|
output.tessOuterHi = float4(0,0,0,0); \
|
2012-12-11 01:15:13 +00:00
|
|
|
return output; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
|
|
|
#define OSD_PATCH_CULL(N)
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void
|
2015-05-26 23:35:06 +00:00
|
|
|
OsdUnivar4x4(in float u, out float B[4], out float D[4])
|
2013-10-08 02:02:41 +00:00
|
|
|
{
|
|
|
|
float t = u;
|
|
|
|
float s = 1.0f - u;
|
|
|
|
|
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
|
|
|
float A0 = s * s;
|
2013-10-08 02:02:41 +00:00
|
|
|
float A1 = 2 * s * t;
|
|
|
|
float A2 = t * t;
|
|
|
|
|
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
|
|
|
B[0] = s * A0;
|
2013-10-08 02:02:41 +00:00
|
|
|
B[1] = t * A0 + s * A1;
|
|
|
|
B[2] = t * A1 + s * A2;
|
|
|
|
B[3] = t * A2;
|
|
|
|
|
|
|
|
D[0] = - A0;
|
|
|
|
D[1] = A0 - A1;
|
|
|
|
D[2] = A1 - A2;
|
|
|
|
D[3] = A2;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-05-26 23:35:06 +00:00
|
|
|
OsdUnivar4x4(in float u, out float B[4], out float D[4], out float C[4])
|
2013-10-08 02:02:41 +00:00
|
|
|
{
|
|
|
|
float t = u;
|
|
|
|
float s = 1.0f - u;
|
|
|
|
|
|
|
|
float A0 = s * s;
|
|
|
|
float A1 = 2 * s * t;
|
|
|
|
float A2 = t * t;
|
|
|
|
|
|
|
|
B[0] = s * A0;
|
|
|
|
B[1] = t * A0 + s * A1;
|
|
|
|
B[2] = t * A1 + s * A2;
|
|
|
|
B[3] = t * A2;
|
|
|
|
|
|
|
|
D[0] = - A0;
|
|
|
|
D[1] = A0 - A1;
|
|
|
|
D[2] = A1 - A2;
|
|
|
|
D[3] = A2;
|
|
|
|
|
|
|
|
A0 = - s;
|
|
|
|
A1 = s - t;
|
|
|
|
A2 = t;
|
|
|
|
|
|
|
|
C[0] = - A0;
|
|
|
|
C[1] = A0 - A1;
|
|
|
|
C[2] = A1 - A2;
|
|
|
|
C[3] = A2;
|
|
|
|
}
|
2015-04-21 16:50:34 +00:00
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
struct OsdPerPatchVertexBezier {
|
|
|
|
int3 patchParam : PATCHPARAM;
|
|
|
|
float3 P : POSITION;
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
|
|
|
float3 P1 : POSITION1;
|
|
|
|
float3 P2 : POSITION2;
|
|
|
|
float2 vSegments : VSEGMENTS;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2015-04-21 16:50:34 +00:00
|
|
|
float3
|
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
|
|
|
OsdEvalBezier(float3 cp[16], float2 uv)
|
2015-04-21 16:50:34 +00:00
|
|
|
{
|
2015-05-26 23:35:06 +00:00
|
|
|
float3 BUCP[4] = {float3(0,0,0),float3(0,0,0),float3(0,0,0),float3(0,0,0)};
|
2015-04-21 16:50:34 +00:00
|
|
|
|
|
|
|
float B[4], D[4];
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
OsdUnivar4x4(uv.x, B, D);
|
2015-04-21 16:50:34 +00:00
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cp[4*i + j];
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
float3 P = float3(0,0,0);
|
2015-04-21 16:50:34 +00:00
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
OsdUnivar4x4(uv.y, B, D);
|
2015-04-21 16:50:34 +00:00
|
|
|
for (int k=0; k<4; ++k) {
|
2015-05-26 23:35:06 +00:00
|
|
|
P += B[k] * BUCP[k];
|
2015-04-21 16:50:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
return P;
|
2015-04-21 16:50:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
// When OSD_PATCH_ENABLE_SINGLE_CREASE is defined,
|
|
|
|
// this function evaluates single-crease patch, which is segmented into
|
|
|
|
// 3 parts in the v-direction.
|
|
|
|
//
|
|
|
|
// v=0 vSegment.x vSegment.y v=1
|
|
|
|
// +------------------+-------------------+------------------+
|
|
|
|
// | cp 0 | cp 1 | cp 2 |
|
|
|
|
// | (infinite sharp) | (floor sharpness) | (ceil sharpness) |
|
|
|
|
// +------------------+-------------------+------------------+
|
|
|
|
//
|
|
|
|
float3
|
2015-06-02 19:02:52 +00:00
|
|
|
OsdEvalBezier(OsdPerPatchVertexBezier cp[16], int3 patchParam, float2 uv)
|
2015-05-31 14:31:21 +00:00
|
|
|
{
|
|
|
|
float3 BUCP[4] = {float3(0,0,0),float3(0,0,0),float3(0,0,0),float3(0,0,0)};
|
|
|
|
|
|
|
|
float B[4], D[4];
|
2015-06-02 19:02:52 +00:00
|
|
|
float s = OsdGetPatchSingleCreaseSegmentParameter(patchParam, uv);
|
2015-05-31 14:31:21 +00:00
|
|
|
|
|
|
|
OsdUnivar4x4(uv.x, B, D);
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
|
|
|
float2 vSegments = cp[0].vSegments;
|
2015-06-02 19:02:52 +00:00
|
|
|
if (s <= vSegments.x) {
|
2015-05-31 14:31:21 +00:00
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cp[4*i + j].P;
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
}
|
|
|
|
}
|
2015-06-02 19:02:52 +00:00
|
|
|
} else if (s <= vSegments.y) {
|
2015-05-31 14:31:21 +00:00
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cp[4*i + j].P1;
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cp[4*i + j].P2;
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cp[4*i + j].P;
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
float3 P = float3(0,0,0);
|
|
|
|
|
|
|
|
OsdUnivar4x4(uv.y, B, D);
|
|
|
|
for (int k=0; k<4; ++k) {
|
|
|
|
P += B[k] * BUCP[k];
|
|
|
|
}
|
|
|
|
|
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
2015-04-21 16:50:34 +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
|
|
|
// Boundary Interpolation
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdComputeBSplineBoundaryPoints(inout float3 cpt[16], int3 patchParam)
|
|
|
|
{
|
|
|
|
int boundaryMask = OsdGetPatchBoundaryMask(patchParam);
|
|
|
|
|
|
|
|
if ((boundaryMask & 1) != 0) {
|
|
|
|
cpt[0] = 2*cpt[4] - cpt[8];
|
|
|
|
cpt[1] = 2*cpt[5] - cpt[9];
|
|
|
|
cpt[2] = 2*cpt[6] - cpt[10];
|
|
|
|
cpt[3] = 2*cpt[7] - cpt[11];
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 2) != 0) {
|
|
|
|
cpt[3] = 2*cpt[2] - cpt[1];
|
|
|
|
cpt[7] = 2*cpt[6] - cpt[5];
|
|
|
|
cpt[11] = 2*cpt[10] - cpt[9];
|
|
|
|
cpt[15] = 2*cpt[14] - cpt[13];
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 4) != 0) {
|
|
|
|
cpt[12] = 2*cpt[8] - cpt[4];
|
|
|
|
cpt[13] = 2*cpt[9] - cpt[5];
|
|
|
|
cpt[14] = 2*cpt[10] - cpt[6];
|
|
|
|
cpt[15] = 2*cpt[11] - cpt[7];
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 8) != 0) {
|
|
|
|
cpt[0] = 2*cpt[1] - cpt[2];
|
|
|
|
cpt[4] = 2*cpt[5] - cpt[6];
|
|
|
|
cpt[8] = 2*cpt[9] - cpt[10];
|
|
|
|
cpt[12] = 2*cpt[13] - cpt[14];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Tessellation
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// 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 occuring 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)
|
|
|
|
//
|
|
|
|
|
|
|
|
float OsdComputePostProjectionSphereExtent(float3 center, float diameter)
|
|
|
|
{
|
2015-05-26 23:35:06 +00:00
|
|
|
float4 p = mul(OsdProjectionMatrix(), float4(center, 1.0));
|
|
|
|
return abs(diameter * OsdProjectionMatrix()[1][1] / p.w);
|
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
|
|
|
}
|
|
|
|
|
|
|
|
float OsdComputeTessLevel(float3 p0, float3 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.
|
2015-05-26 23:35:06 +00:00
|
|
|
p0 = mul(OsdModelViewMatrix(), float4(p0, 1.0)).xyz;
|
|
|
|
p1 = mul(OsdModelViewMatrix(), float4(p1, 1.0)).xyz;
|
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
|
|
|
float3 center = (p0 + p1) / 2.0;
|
|
|
|
float diameter = distance(p0, p1);
|
|
|
|
float projLength = OsdComputePostProjectionSphereExtent(center, diameter);
|
|
|
|
return round(max(1.0, OsdTessLevel() * projLength));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdGetTessLevelsUniform(int3 patchParam,
|
2015-05-26 23:35:06 +00:00
|
|
|
out float4 tessOuterLo, out float4 tessOuterHi)
|
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 refinementLevel = OsdGetPatchRefinementLevel(patchParam);
|
|
|
|
float tessLevel = OsdTessLevel() / pow(2, refinementLevel-1);
|
|
|
|
|
|
|
|
tessOuterLo = float4(tessLevel,tessLevel,tessLevel,tessLevel);
|
|
|
|
tessOuterHi = float4(0,0,0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdGetTessLevelsRefinedPoints(float3 cp[16], int3 patchParam,
|
2015-05-26 23:35:06 +00:00
|
|
|
out float4 tessOuterLo, out float4 tessOuterHi)
|
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
|
|
|
{
|
|
|
|
// 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.
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
float3 ev01 = (cp[1] + cp[2] + cp[9] + cp[10]) * 0.0625 +
|
|
|
|
(cp[5] + cp[6]) * 0.375;
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
float3 ev12 = (cp[5] + cp[7] + cp[9] + cp[11]) * 0.0625 +
|
|
|
|
(cp[6] + cp[10]) * 0.375;
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
float3 ev23 = (cp[5] + cp[6] + cp[13] + cp[14]) * 0.0625 +
|
|
|
|
(cp[9] + cp[10]) * 0.375;
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
float3 ev03 = (cp[4] + cp[6] + cp[8] + cp[10]) * 0.0625 +
|
|
|
|
(cp[5] + cp[9]) * 0.375;
|
|
|
|
|
|
|
|
tessOuterLo = float4(0,0,0,0);
|
|
|
|
tessOuterHi = float4(0,0,0,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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-05-31 14:31:21 +00:00
|
|
|
OsdGetTessLevelsLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
|
|
|
int3 patchParam, out float4 tessOuterLo, out float4 tessOuterHi)
|
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
|
|
|
{
|
|
|
|
// 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 = float4(0,0,0,0);
|
|
|
|
tessOuterHi = float4(0,0,0,0);
|
|
|
|
|
|
|
|
int transitionMask = OsdGetPatchTransitionMask(patchParam);
|
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
2015-06-02 19:02:52 +00:00
|
|
|
// PERFOMANCE: we just need to pick the correct corner points from P, P1, P2
|
|
|
|
float3 p0 = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.0));
|
|
|
|
float3 p3 = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.0));
|
|
|
|
float3 p12 = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 1.0));
|
|
|
|
float3 p15 = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 1.0));
|
2015-05-31 14:31:21 +00:00
|
|
|
if ((transitionMask & 8) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev03 = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.5));
|
|
|
|
tessOuterLo[0] = OsdComputeTessLevel(p0, ev03);
|
|
|
|
tessOuterHi[0] = OsdComputeTessLevel(p12, ev03);
|
2015-05-31 14:31:21 +00:00
|
|
|
} else {
|
2015-06-02 19:02:52 +00:00
|
|
|
tessOuterLo[0] = OsdComputeTessLevel(p0, p12);
|
2015-05-31 14:31:21 +00:00
|
|
|
}
|
|
|
|
if ((transitionMask & 1) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev01 = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0));
|
|
|
|
tessOuterLo[1] = OsdComputeTessLevel(p0, ev01);
|
|
|
|
tessOuterHi[1] = OsdComputeTessLevel(p3, ev01);
|
2015-05-31 14:31:21 +00:00
|
|
|
} else {
|
2015-06-02 19:02:52 +00:00
|
|
|
tessOuterLo[1] = OsdComputeTessLevel(p0, p3);
|
2015-05-31 14:31:21 +00:00
|
|
|
}
|
|
|
|
if ((transitionMask & 2) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev12 = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5));
|
|
|
|
tessOuterLo[2] = OsdComputeTessLevel(p3, ev12);
|
|
|
|
tessOuterHi[2] = OsdComputeTessLevel(p15, ev12);
|
2015-05-31 14:31:21 +00:00
|
|
|
} else {
|
2015-06-02 19:02:52 +00:00
|
|
|
tessOuterLo[2] = OsdComputeTessLevel(p3, p15);
|
2015-05-31 14:31:21 +00:00
|
|
|
}
|
|
|
|
if ((transitionMask & 4) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev23 = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0));
|
|
|
|
tessOuterLo[3] = OsdComputeTessLevel(p12, ev23);
|
|
|
|
tessOuterHi[3] = OsdComputeTessLevel(p15, ev23);
|
2015-05-31 14:31:21 +00:00
|
|
|
} else {
|
2015-06-02 19:02:52 +00:00
|
|
|
tessOuterLo[3] = OsdComputeTessLevel(p12, p15);
|
2015-05-31 14:31:21 +00:00
|
|
|
}
|
|
|
|
#else
|
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
|
|
|
if ((transitionMask & 8) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev03 = OsdEvalBezier(cpBezier, patchParam, float2(0.0, 0.5));
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, ev03);
|
|
|
|
tessOuterHi[0] = OsdComputeTessLevel(cpBezier[12].P, ev03);
|
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
|
|
|
} else {
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[0] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[12].P);
|
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
|
|
|
}
|
|
|
|
if ((transitionMask & 1) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev01 = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 0.0));
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, ev01);
|
|
|
|
tessOuterHi[1] = OsdComputeTessLevel(cpBezier[3].P, ev01);
|
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
|
|
|
} else {
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[1] = OsdComputeTessLevel(cpBezier[0].P, cpBezier[3].P);
|
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
|
|
|
}
|
|
|
|
if ((transitionMask & 2) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev12 = OsdEvalBezier(cpBezier, patchParam, float2(1.0, 0.5));
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, ev12);
|
|
|
|
tessOuterHi[2] = OsdComputeTessLevel(cpBezier[15].P, ev12);
|
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
|
|
|
} else {
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[2] = OsdComputeTessLevel(cpBezier[3].P, cpBezier[15].P);
|
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
|
|
|
}
|
|
|
|
if ((transitionMask & 4) != 0) {
|
2015-06-02 19:02:52 +00:00
|
|
|
float3 ev23 = OsdEvalBezier(cpBezier, patchParam, float2(0.5, 1.0));
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, ev23);
|
|
|
|
tessOuterHi[3] = OsdComputeTessLevel(cpBezier[15].P, ev23);
|
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
|
|
|
} else {
|
2015-05-31 14:31:21 +00:00
|
|
|
tessOuterLo[3] = OsdComputeTessLevel(cpBezier[12].P, cpBezier[15].P);
|
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
|
|
|
}
|
2015-05-31 14:31:21 +00:00
|
|
|
#endif
|
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
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-05-31 14:31:21 +00:00
|
|
|
OsdGetTessLevelsUniform(int3 patchParam,
|
2015-05-26 23:35:06 +00:00
|
|
|
out float4 tessLevelOuter, out float2 tessLevelInner,
|
|
|
|
out float4 tessOuterLo, out float4 tessOuterHi)
|
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
|
|
|
{
|
|
|
|
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
2015-05-31 14:31:21 +00:00
|
|
|
|
|
|
|
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
|
|
|
// segments will have a length of zero for non-transition edges.
|
|
|
|
tessLevelOuter = tessOuterLo + tessOuterHi;
|
|
|
|
|
|
|
|
// Inner levels are the average the corresponding outer levels.
|
|
|
|
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
|
|
|
|
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdGetTessLevelsAdaptiveRefinedPoints(float3 cpRefined[16], int3 patchParam,
|
|
|
|
out float4 tessLevelOuter, out float2 tessLevelInner,
|
|
|
|
out float4 tessOuterLo, out float4 tessOuterHi)
|
|
|
|
{
|
|
|
|
OsdGetTessLevelsRefinedPoints(cpRefined, patchParam, tessOuterLo, tessOuterHi);
|
|
|
|
|
|
|
|
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
|
|
|
// segments will have a length of zero for non-transition edges.
|
|
|
|
tessLevelOuter = tessOuterLo + tessOuterHi;
|
|
|
|
|
|
|
|
// Inner levels are the average the corresponding outer levels.
|
|
|
|
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
|
|
|
|
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdGetTessLevelsAdaptiveLimitPoints(OsdPerPatchVertexBezier cpBezier[16],
|
|
|
|
int3 patchParam,
|
|
|
|
out float4 tessLevelOuter, out float2 tessLevelInner,
|
|
|
|
out float4 tessOuterLo, out float4 tessOuterHi)
|
|
|
|
{
|
|
|
|
OsdGetTessLevelsLimitPoints(cpBezier, patchParam, tessOuterLo, tessOuterHi);
|
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
|
|
|
|
|
|
|
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
|
|
|
// segments will have a length of zero for non-transition edges.
|
|
|
|
tessLevelOuter = tessOuterLo + tessOuterHi;
|
|
|
|
|
|
|
|
// Inner levels are the average the corresponding outer levels.
|
|
|
|
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
|
|
|
|
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdGetTessLevels(float3 cp0, float3 cp1, float3 cp2, float3 cp3,
|
|
|
|
int3 patchParam,
|
2015-05-26 23:35:06 +00:00
|
|
|
out float4 tessLevelOuter, out float2 tessLevelInner)
|
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
|
|
|
{
|
|
|
|
float4 tessOuterLo = float4(0,0,0,0);
|
|
|
|
float4 tessOuterHi = float4(0,0,0,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 = float4(0,0,0,0);
|
|
|
|
#else
|
|
|
|
OsdGetTessLevelsUniform(patchParam, tessOuterLo, tessOuterHi);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Outer levels are the sum of the Lo and Hi segments where the Hi
|
|
|
|
// segments will have a length of zero for non-transition edges.
|
|
|
|
tessLevelOuter = tessOuterLo + tessOuterHi;
|
|
|
|
|
|
|
|
// Inner levels are the average the corresponding outer levels.
|
|
|
|
tessLevelInner[0] = (tessLevelOuter[1] + tessLevelOuter[3]) * 0.5;
|
|
|
|
tessLevelInner[1] = (tessLevelOuter[0] + tessLevelOuter[2]) * 0.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
float
|
|
|
|
OsdGetTessTransitionSplit(float t, float n0, float n1)
|
|
|
|
{
|
|
|
|
float ti = round(t * (n0 + n1));
|
|
|
|
|
|
|
|
if (ti <= n0) {
|
|
|
|
return 0.5 * (ti / n0);
|
|
|
|
} else {
|
|
|
|
return 0.5 * ((ti - n0) / n1) + 0.5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float2
|
|
|
|
OsdGetTessParameterization(float2 uv, float4 tessOuterLo, float4 tessOuterHi)
|
|
|
|
{
|
|
|
|
float2 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;
|
|
|
|
}
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// BSpline
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// compute single-crease patch matrix
|
|
|
|
float4x4
|
|
|
|
OsdComputeMs(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;
|
|
|
|
}
|
|
|
|
|
2015-06-02 19:02:52 +00:00
|
|
|
// flip matrix orientation
|
|
|
|
float4x4
|
|
|
|
OsdFlipMatrix(float4x4 m)
|
|
|
|
{
|
|
|
|
return float4x4(m[3][3], m[3][2], m[3][1], m[3][0],
|
|
|
|
m[2][3], m[2][2], m[2][1], m[2][0],
|
|
|
|
m[1][3], m[1][2], m[1][1], m[1][0],
|
|
|
|
m[0][3], m[0][2], m[0][1], m[0][0]);
|
|
|
|
}
|
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
// convert BSpline cv to Bezier cv
|
2015-05-26 23:35:06 +00:00
|
|
|
void
|
|
|
|
OsdComputePerPatchVertexBSpline(int3 patchParam, int ID, float3 cv[16],
|
2015-05-31 14:31:21 +00:00
|
|
|
out OsdPerPatchVertexBezier result)
|
2015-05-26 23:35:06 +00:00
|
|
|
{
|
|
|
|
// Regular BSpline to Bezier
|
|
|
|
float4x4 Q = {
|
|
|
|
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, 1.f/6.f, 4.f/6.f, 1.f/6.f
|
|
|
|
};
|
|
|
|
|
|
|
|
result.patchParam = patchParam;
|
|
|
|
|
|
|
|
int i = ID%4;
|
|
|
|
int j = ID/4;
|
|
|
|
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
2015-06-02 19:02:52 +00:00
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
// Infinitely Sharp (boundary)
|
2015-05-26 23:35:06 +00:00
|
|
|
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
|
|
|
|
};
|
|
|
|
|
2015-06-02 19:02:52 +00:00
|
|
|
float4x4 Mj, Ms;
|
2015-05-31 14:31:21 +00:00
|
|
|
float sharpness = OsdGetPatchSharpness(patchParam);
|
|
|
|
if (sharpness > 0) {
|
|
|
|
float Sf = floor(sharpness);
|
|
|
|
float Sc = ceil(sharpness);
|
|
|
|
float Sr = frac(sharpness);
|
2015-05-26 23:35:06 +00:00
|
|
|
float4x4 Mf = OsdComputeMs(Sf);
|
|
|
|
float4x4 Mc = OsdComputeMs(Sc);
|
2015-06-02 19:02:52 +00:00
|
|
|
Mj = (1-Sr) * Mf + Sr * Mi;
|
|
|
|
Ms = (1-Sr) * Mf + Sr * Mc;
|
2015-05-31 14:31:21 +00:00
|
|
|
float s0 = 1 - pow(2, -floor(sharpness));
|
|
|
|
float s1 = 1 - pow(2, -ceil(sharpness));
|
|
|
|
result.vSegments = float2(s0, s1);
|
2015-06-02 19:02:52 +00:00
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
} else {
|
2015-06-02 19:02:52 +00:00
|
|
|
Mj = Ms = Mi;
|
|
|
|
result.vSegments = float2(0, 0);
|
|
|
|
}
|
|
|
|
result.P = float3(0,0,0); // 0 to 1-2^(-Sf)
|
|
|
|
result.P1 = float3(0,0,0); // 1-2^(-Sf) to 1-2^(-Sc)
|
|
|
|
result.P2 = float3(0,0,0); // 1-2^(-Sc) to 1
|
|
|
|
|
|
|
|
float4x4 MUi, MUj, MUs;
|
|
|
|
float4x4 MVi, MVj, MVs;
|
|
|
|
MUi = MUj = MUs = Q;
|
|
|
|
MVi = MVj = MVs = Q;
|
|
|
|
|
|
|
|
int boundaryMask = OsdGetPatchBoundaryMask(patchParam);
|
|
|
|
if ((boundaryMask & 1) != 0) {
|
|
|
|
MVi = OsdFlipMatrix(Mi);
|
|
|
|
MVj = OsdFlipMatrix(Mj);
|
|
|
|
MVs = OsdFlipMatrix(Ms);
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 2) != 0) {
|
|
|
|
MUi = Mi;
|
|
|
|
MUj = Mj;
|
|
|
|
MUs = Ms;
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 4) != 0) {
|
|
|
|
MVi = Mi;
|
|
|
|
MVj = Mj;
|
|
|
|
MVs = Ms;
|
|
|
|
}
|
|
|
|
if ((boundaryMask & 8) != 0) {
|
|
|
|
MUi = OsdFlipMatrix(Mi);
|
|
|
|
MUj = OsdFlipMatrix(Mj);
|
|
|
|
MUs = OsdFlipMatrix(Ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
float3 Hi[4], Hj[4], Hs[4];
|
|
|
|
for (int l=0; l<4; ++l) {
|
|
|
|
Hi[l] = Hj[l] = Hs[l] = float3(0,0,0);
|
|
|
|
for (int k=0; k<4; ++k) {
|
|
|
|
Hi[l] += MUi[i][k] * cv[l*4 + k];
|
|
|
|
Hj[l] += MUj[i][k] * cv[l*4 + k];
|
|
|
|
Hs[l] += MUs[i][k] * cv[l*4 + k];
|
2015-05-26 23:35:06 +00:00
|
|
|
}
|
2015-06-02 19:02:52 +00:00
|
|
|
}
|
|
|
|
for (int k=0; k<4; ++k) {
|
|
|
|
result.P += MVi[j][k]*Hi[k];
|
|
|
|
result.P1 += MVj[j][k]*Hj[k];
|
|
|
|
result.P2 += MVs[j][k]*Hs[k];
|
2015-05-26 23:35:06 +00:00
|
|
|
}
|
|
|
|
#else
|
2015-06-02 19:02:52 +00:00
|
|
|
OsdComputeBSplineBoundaryPoints(cv, patchParam);
|
|
|
|
|
|
|
|
float3 H[4];
|
|
|
|
for (int l=0; l<4; ++l) {
|
|
|
|
H[l] = float3(0,0,0);
|
|
|
|
for(int k=0; k<4; ++k) {
|
|
|
|
H[l] += Q[i][k] * cv[l*4 + k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-26 23:35:06 +00:00
|
|
|
{
|
|
|
|
result.P = float3(0,0,0);
|
|
|
|
for (int k=0; k<4; ++k){
|
|
|
|
result.P += Q[j][k]*H[k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-05-31 14:31:21 +00:00
|
|
|
OsdEvalPatchBezier(int3 patchParam, float2 UV,
|
|
|
|
OsdPerPatchVertexBezier cv[16],
|
|
|
|
out float3 P, out float3 dPu, out float3 dPv,
|
|
|
|
out float3 N, out float3 dNu, out float3 dNv)
|
2015-05-26 23:35:06 +00:00
|
|
|
{
|
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
|
|
|
float B[4], D[4], C[4];
|
|
|
|
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)};
|
|
|
|
OsdUnivar4x4(UV.x, B, D, C);
|
|
|
|
#else
|
|
|
|
float B[4], D[4];
|
|
|
|
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)};
|
|
|
|
OsdUnivar4x4(UV.x, B, D);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
2015-05-31 14:31:21 +00:00
|
|
|
float2 vSegments = cv[0].vSegments;
|
2015-06-02 19:02:52 +00:00
|
|
|
float s = OsdGetPatchSingleCreaseSegmentParameter(patchParam, UV);
|
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
int k = 4*i + j;
|
2015-05-26 23:35:06 +00:00
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
float3 A = (s <= vSegments.x) ? cv[k].P
|
|
|
|
: ((s <= vSegments.y) ? cv[k].P1
|
|
|
|
: cv[k].P2);
|
2015-05-26 23:35:06 +00:00
|
|
|
|
2015-05-31 14:31:21 +00:00
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
2015-05-26 23:35:06 +00:00
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
2015-05-31 14:31:21 +00:00
|
|
|
CUCP[i] += A * C[j];
|
2015-05-26 23:35:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// ----------------------------------------------------------------
|
2015-05-31 14:31:21 +00:00
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = cv[4*i + j].P;
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
2015-05-26 23:35:06 +00:00
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
2015-05-31 14:31:21 +00:00
|
|
|
CUCP[i] += A * C[j];
|
2015-05-26 23:35:06 +00:00
|
|
|
#endif
|
|
|
|
}
|
2015-05-31 14:31:21 +00:00
|
|
|
}
|
2015-05-26 23:35:06 +00:00
|
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
|
|
|
|
P = float3(0,0,0);
|
|
|
|
dPu = float3(0,0,0);
|
|
|
|
dPv = float3(0,0,0);
|
|
|
|
|
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
|
|
|
// used for weingarten term
|
|
|
|
OsdUnivar4x4(UV.y, B, D, C);
|
|
|
|
|
|
|
|
float3 dUU = float3(0,0,0);
|
|
|
|
float3 dVV = float3(0,0,0);
|
|
|
|
float3 dUV = float3(0,0,0);
|
|
|
|
|
|
|
|
for (int k=0; k<4; ++k) {
|
|
|
|
P += B[k] * BUCP[k];
|
|
|
|
dPu += B[k] * DUCP[k];
|
|
|
|
dPv += D[k] * BUCP[k];
|
|
|
|
|
|
|
|
dUU += B[k] * CUCP[k];
|
|
|
|
dVV += C[k] * BUCP[k];
|
|
|
|
dUV += D[k] * DUCP[k];
|
|
|
|
}
|
|
|
|
|
|
|
|
int level = OsdGetPatchFaceLevel(patchParam);
|
|
|
|
dPu *= 3 * level;
|
|
|
|
dPv *= 3 * level;
|
|
|
|
dUU *= 6 * level;
|
|
|
|
dVV *= 6 * level;
|
|
|
|
dUV *= 9 * level;
|
|
|
|
|
|
|
|
float3 n = cross(dPu, dPv);
|
|
|
|
N = normalize(n);
|
|
|
|
|
|
|
|
float E = dot(dPu, dPu);
|
|
|
|
float F = dot(dPu, dPv);
|
|
|
|
float G = dot(dPv, dPv);
|
|
|
|
float e = dot(N, dUU);
|
|
|
|
float f = dot(N, dUV);
|
|
|
|
float g = dot(N, dVV);
|
|
|
|
|
|
|
|
dNu = (f*F-e*G)/(E*G-F*F) * dPu + (e*F-f*E)/(E*G-F*F) * dPv;
|
|
|
|
dNv = (g*F-f*G)/(E*G-F*F) * dPu + (f*F-g*E)/(E*G-F*F) * dPv;
|
|
|
|
|
|
|
|
dNu = dNu/length(n) - n * (dot(dNu,n)/pow(dot(n,n), 1.5));
|
|
|
|
dNv = dNv/length(n) - n * (dot(dNv,n)/pow(dot(n,n), 1.5));
|
|
|
|
#else
|
|
|
|
OsdUnivar4x4(UV.y, B, D);
|
|
|
|
|
|
|
|
for (int k=0; k<4; ++k) {
|
|
|
|
P += B[k] * BUCP[k];
|
|
|
|
dPu += B[k] * DUCP[k];
|
|
|
|
dPv += D[k] * BUCP[k];
|
|
|
|
}
|
|
|
|
int level = OsdGetPatchFaceLevel(patchParam);
|
|
|
|
dPu *= 3 * level;
|
|
|
|
dPv *= 3 * level;
|
|
|
|
|
|
|
|
N = normalize(cross(dPu, dPv));
|
|
|
|
dNu = float3(0,0,0);
|
|
|
|
dNv = float3(0,0,0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// GregoryBasis
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct OsdPerPatchVertexGregoryBasis {
|
|
|
|
int3 patchParam : PATCHPARAM;
|
|
|
|
float3 P : POSITION0;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdComputePerPatchVertexGregoryBasis(int3 patchParam, int ID, float3 cv,
|
|
|
|
out OsdPerPatchVertexGregoryBasis result)
|
|
|
|
{
|
|
|
|
result.patchParam = patchParam;
|
|
|
|
result.P = cv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdEvalPatchGregory(int3 patchParam, float2 UV, float3 cv[20],
|
|
|
|
out float3 P, out float3 dPu, out float3 dPv,
|
|
|
|
out float3 N, out float3 dNu, out float3 dNv)
|
|
|
|
{
|
|
|
|
float u = UV.x, v = UV.y;
|
|
|
|
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;
|
|
|
|
|
|
|
|
float3 q[16];
|
|
|
|
|
|
|
|
q[ 5] = (u*cv[3] + v*cv[4])/d11;
|
|
|
|
q[ 6] = (U*cv[9] + v*cv[8])/d12;
|
|
|
|
q[ 9] = (u*cv[19] + V*cv[18])/d21;
|
|
|
|
q[10] = (U*cv[13] + V*cv[14])/d22;
|
|
|
|
|
|
|
|
q[ 0] = cv[0];
|
|
|
|
q[ 1] = cv[1];
|
|
|
|
q[ 2] = cv[7];
|
|
|
|
q[ 3] = cv[5];
|
|
|
|
q[ 4] = cv[2];
|
|
|
|
q[ 7] = cv[6];
|
|
|
|
q[ 8] = cv[16];
|
|
|
|
q[11] = cv[12];
|
|
|
|
q[12] = cv[15];
|
|
|
|
q[13] = cv[17];
|
|
|
|
q[14] = cv[11];
|
|
|
|
q[15] = cv[10];
|
|
|
|
|
|
|
|
P = float3(0,0,0);
|
|
|
|
dPu = float3(0,0,0);
|
|
|
|
dPv = float3(0,0,0);
|
|
|
|
|
|
|
|
#ifdef OSD_COMPUTE_NORMAL_DERIVATIVES
|
|
|
|
float B[4], D[4], C[4];
|
|
|
|
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)};
|
|
|
|
float3 dUU = float3(0,0,0);
|
|
|
|
float3 dVV = float3(0,0,0);
|
|
|
|
float3 dUV = float3(0,0,0);
|
|
|
|
|
|
|
|
OsdUnivar4x4(UV.x, B, D, C);
|
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = q[4*i + j];
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
|
|
|
CUCP[i] += A * C[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OsdUnivar4x4(UV.y, B, D, C);
|
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
P += B[i] * BUCP[i];
|
|
|
|
dPu += B[i] * DUCP[i];
|
|
|
|
dPv += D[i] * BUCP[i];
|
|
|
|
dUU += B[i] * CUCP[i];
|
|
|
|
dVV += C[i] * BUCP[i];
|
|
|
|
dUV += D[i] * DUCP[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
int level = OsdGetPatchFaceLevel(patchParam);
|
|
|
|
dPu *= 3 * level;
|
|
|
|
dPv *= 3 * level;
|
|
|
|
dUU *= 6 * level;
|
|
|
|
dVV *= 6 * level;
|
|
|
|
dUV *= 9 * level;
|
|
|
|
|
|
|
|
float3 n = cross(dPu, dPv);
|
2015-06-02 19:02:52 +00:00
|
|
|
N = normalize(n);
|
2015-05-26 23:35:06 +00:00
|
|
|
|
|
|
|
float E = dot(dPu, dPu);
|
|
|
|
float F = dot(dPu, dPv);
|
|
|
|
float G = dot(dPv, dPv);
|
|
|
|
float e = dot(N, dUU);
|
|
|
|
float f = dot(N, dUV);
|
|
|
|
float g = dot(N, dVV);
|
|
|
|
|
|
|
|
dNu = (f*F-e*G)/(E*G-F*F) * dPu + (e*F-f*E)/(E*G-F*F) * dPv;
|
|
|
|
dNv = (g*F-f*G)/(E*G-F*F) * dPu + (f*F-g*E)/(E*G-F*F) * dPv;
|
|
|
|
|
|
|
|
dNu = dNu/length(n) - n * (dot(dNu,n)/pow(dot(n,n), 1.5));
|
|
|
|
dNv = dNv/length(n) - n * (dot(dNv,n)/pow(dot(n,n), 1.5));
|
|
|
|
#else
|
|
|
|
float B[4], D[4];
|
|
|
|
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)};
|
|
|
|
|
|
|
|
OsdUnivar4x4(UV.x, B, D);
|
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
for (int j=0; j<4; ++j) {
|
|
|
|
float3 A = q[4*i + j];
|
|
|
|
BUCP[i] += A * B[j];
|
|
|
|
DUCP[i] += A * D[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OsdUnivar4x4(UV.y, B, D);
|
|
|
|
|
|
|
|
for (int i=0; i<4; ++i) {
|
|
|
|
P += B[i] * BUCP[i];
|
|
|
|
dPu += B[i] * DUCP[i];
|
|
|
|
dPv += D[i] * BUCP[i];
|
|
|
|
}
|
|
|
|
int level = OsdGetPatchFaceLevel(patchParam);
|
|
|
|
dPu *= 3 * level;
|
|
|
|
dPv *= 3 * level;
|
|
|
|
|
|
|
|
N = normalize(cross(dPu, dPv));
|
|
|
|
dNu = float3(0,0,0);
|
|
|
|
dNv = float3(0,0,0);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Legacy Gregory
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if defined(OSD_PATCH_GREGORY) || defined(OSD_PATCH_GREGORY_BOUNDARY)
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
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 {
|
|
|
|
float3 P : POSITION0;
|
|
|
|
int3 clipFlag : CLIPFLAG;
|
|
|
|
int valence : BLENDINDICE0;
|
|
|
|
float3 e0 : POSITION1;
|
|
|
|
float3 e1 : POSITION2;
|
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
int zerothNeighbor : BLENDINDICE1;
|
|
|
|
float3 org : POSITION3;
|
|
|
|
#endif
|
|
|
|
float3 r[OSD_MAX_VALENCE] : POSITION4;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct OsdPerPatchVertexGregory {
|
|
|
|
int3 patchParam: PATCHPARAM;
|
|
|
|
float3 P : POSITION0;
|
|
|
|
float3 Ep : POSITION1;
|
|
|
|
float3 Em : POSITION2;
|
|
|
|
float3 Fp : POSITION3;
|
|
|
|
float3 Fm : POSITION4;
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef OSD_NUM_ELEMENTS
|
|
|
|
#define OSD_NUM_ELEMENTS 3
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Buffer<float> OsdVertexBuffer : register( t2 );
|
|
|
|
Buffer<int> OsdValenceBuffer : register( t3 );
|
|
|
|
|
|
|
|
float3 OsdReadVertex(int 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, int valenceVertex)
|
|
|
|
{
|
|
|
|
int index = int(vertexID * (2 * OSD_MAX_VALENCE + 1) + 1 + valenceVertex);
|
|
|
|
return OsdValenceBuffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
Buffer<int> OsdQuadOffsetBuffer : register( t4 );
|
|
|
|
|
|
|
|
int OsdReadQuadOffset(int primitiveID, int offsetVertex)
|
|
|
|
{
|
|
|
|
int index = int(4*primitiveID+OsdGregoryQuadOffsetBase() + offsetVertex);
|
|
|
|
return OsdQuadOffsetBuffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
OsdComputePerVertexGregory(int vID, float3 P, out OsdPerVertexGregory v)
|
|
|
|
{
|
|
|
|
v.clipFlag = int3(0,0,0);
|
|
|
|
|
|
|
|
int ivalence = OsdReadVertexValence(vID);
|
|
|
|
v.valence = ivalence;
|
|
|
|
int valence = abs(ivalence);
|
|
|
|
|
|
|
|
float3 f[OSD_MAX_VALENCE];
|
|
|
|
float3 pos = P;
|
|
|
|
float3 opos = float3(0,0,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
|
|
|
|
|
|
|
|
float3 neighbor = OsdReadVertex(idx_neighbor);
|
|
|
|
|
|
|
|
int idx_diagonal = OsdReadVertexIndex(vID, 2*i + 1);
|
|
|
|
float3 diagonal = OsdReadVertex(idx_diagonal);
|
|
|
|
|
|
|
|
int idx_neighbor_p = OsdReadVertexIndex(vID, 2*ip);
|
|
|
|
float3 neighbor_p = OsdReadVertex(idx_neighbor_p);
|
|
|
|
|
|
|
|
int idx_neighbor_m = OsdReadVertexIndex(vID, 2*im);
|
|
|
|
float3 neighbor_m = OsdReadVertex(idx_neighbor_m);
|
|
|
|
|
|
|
|
int idx_diagonal_m = OsdReadVertexIndex(vID, 2*im + 1);
|
|
|
|
float3 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 = float4(opos, 1.0f).xyz;
|
|
|
|
|
|
|
|
float3 e;
|
|
|
|
v.e0 = float3(0,0,0);
|
|
|
|
v.e1 = float3(0,0,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;
|
|
|
|
}
|
|
|
|
v.e0 *= ef[valence - 3];
|
|
|
|
v.e1 *= ef[valence - 3];
|
|
|
|
|
|
|
|
#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);
|
|
|
|
float3 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);
|
|
|
|
float3 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(int3 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+ 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
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifdef OSD_PATCH_GREGORY_BOUNDARY
|
|
|
|
float3 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
|
|
|
|
float3 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;
|
|
|
|
float3 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 );
|
|
|
|
|
|
|
|
float3 Em_ip = v[ip].P + v[ip].e0*cosfn(np, prev_p) + v[ip].e1*sinfn(np, prev_p);
|
|
|
|
float3 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
|