mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-23 12:10:08 +00:00
Merge pull request #936 from NickBMarine/metalFvarExample
Added fvar support for metal as well as a ui for fvar.
This commit is contained in:
commit
fde91b4a42
@ -213,6 +213,18 @@ enum {
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackBoundary = [=](int boundaryType) {
|
||||
switch((FVarBoundary)boundaryType) {
|
||||
case kFVarLinearNone:
|
||||
case kFVarLinearCornersOnly:
|
||||
case kFVarLinearCornersPlus1:
|
||||
case kFVarLinearCornersPlus2:
|
||||
case kFVarLinearBoundaries:
|
||||
case kFVarLinearAll:
|
||||
self.osdRenderer.fVarBoundary = (FVarBoundary)boundaryType;
|
||||
}
|
||||
};
|
||||
|
||||
auto callbackDisplayStyle = [=](int displayStyle) {
|
||||
switch((DisplayStyle)displayStyle) {
|
||||
case kDisplayStyleWire:
|
||||
@ -224,13 +236,14 @@ enum {
|
||||
assert("Unknown displayStyle" && 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
auto callbackShadingMode = [=](int shadingMode) {
|
||||
switch((ShadingMode)shadingMode) {
|
||||
case kShadingNormal:
|
||||
case kShadingMaterial:
|
||||
case kShadingPatchType:
|
||||
case kShadingPatchCoord:
|
||||
case kShadingFaceVarying:
|
||||
self.osdRenderer.shadingMode = (ShadingMode)shadingMode;
|
||||
break;
|
||||
default:
|
||||
@ -282,8 +295,8 @@ enum {
|
||||
hud.AddCheckBox("Fractional spacing (T)", _osdRenderer.useFractionalTessellation,
|
||||
10, y, callbackCheckbox, kHUD_CB_FRACTIONAL_SPACING, 't');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Frustum Patch Culling (B)", _osdRenderer.usePatchClipCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'b');
|
||||
hud.AddCheckBox("Frustum Patch Culling (F)", _osdRenderer.usePatchClipCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_PATCH_CULL, 'f');
|
||||
y += 20;
|
||||
hud.AddCheckBox("Backface Culling (L)", _osdRenderer.usePatchBackfaceCulling,
|
||||
10, y, callbackCheckbox, kHUD_CB_BACK_CULL, 'l');
|
||||
@ -321,10 +334,34 @@ enum {
|
||||
hud.AddPullDownButton(shading_pulldown, "Normal",
|
||||
kShadingNormal,
|
||||
_osdRenderer.shadingMode == kShadingNormal);
|
||||
|
||||
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
|
||||
hud.AddPullDownButton(shading_pulldown, "Face Varying",
|
||||
kShadingFaceVarying,
|
||||
_osdRenderer.shadingMode == kShadingFaceVarying);
|
||||
|
||||
int compute_pulldown = hud.AddPullDown("Compute (K)", 475, 10, 175, callbackKernel, 'k');
|
||||
hud.AddPullDownButton(compute_pulldown, "CPU", kCPU, _osdRenderer.kernelType == kCPU);
|
||||
hud.AddPullDownButton(compute_pulldown, "Metal", kMetal, _osdRenderer.kernelType == kMetal);
|
||||
|
||||
int boundary_pulldown = hud.AddPullDown("Boundary (B)", 650, 10, 300, callbackBoundary, 'b');
|
||||
hud.AddPullDownButton(boundary_pulldown, "None (edge only)",
|
||||
kFVarLinearNone,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearNone);
|
||||
hud.AddPullDownButton(boundary_pulldown, "Corners Only",
|
||||
kFVarLinearCornersOnly,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearCornersOnly);
|
||||
hud.AddPullDownButton(boundary_pulldown, "Corners 1 (edge corner)",
|
||||
kFVarLinearCornersPlus1,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearCornersPlus1);
|
||||
hud.AddPullDownButton(boundary_pulldown, "Corners 2 (edge corner prop)",
|
||||
kFVarLinearCornersPlus2,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearCornersPlus2);
|
||||
hud.AddPullDownButton(boundary_pulldown, "Boundaries (always sharp)",
|
||||
kFVarLinearBoundaries,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearBoundaries);
|
||||
hud.AddPullDownButton(boundary_pulldown, "All (bilinear)",
|
||||
kFVarLinearAll,
|
||||
_osdRenderer.fVarBoundary == kFVarLinearAll);
|
||||
|
||||
{
|
||||
hud.AddCheckBox("Adaptive (`)", _osdRenderer.useAdaptive,
|
||||
10, 190, callbackCheckbox, kHUD_CB_ADAPTIVE, '`');
|
||||
|
@ -34,6 +34,15 @@ typedef enum {
|
||||
kEndCapGregoryBasis,
|
||||
} EndCap;
|
||||
|
||||
typedef enum {
|
||||
kFVarLinearNone = 0,
|
||||
kFVarLinearCornersOnly,
|
||||
kFVarLinearCornersPlus1,
|
||||
kFVarLinearCornersPlus2,
|
||||
kFVarLinearBoundaries,
|
||||
kFVarLinearAll
|
||||
} FVarBoundary;
|
||||
|
||||
typedef enum {
|
||||
kCPU = 0,
|
||||
kMetal,
|
||||
@ -49,7 +58,8 @@ typedef enum {
|
||||
kShadingMaterial = 0,
|
||||
kShadingPatchType,
|
||||
kShadingNormal,
|
||||
kShadingPatchCoord
|
||||
kShadingPatchCoord,
|
||||
kShadingFaceVarying,
|
||||
} ShadingMode;
|
||||
|
||||
|
||||
@ -105,6 +115,7 @@ typedef struct {
|
||||
@property (nonatomic) DisplayStyle displayStyle;
|
||||
@property (nonatomic) ShadingMode shadingMode;
|
||||
@property (nonatomic) EndCap endCapMode;
|
||||
@property (nonatomic) FVarBoundary fVarBoundary;
|
||||
@property (nonatomic) KernelType kernelType;
|
||||
|
||||
@end
|
||||
|
@ -31,7 +31,7 @@ using namespace metal;
|
||||
#define SHADING_TYPE_PATCH 1
|
||||
#define SHADING_TYPE_NORMAL 2
|
||||
#define SHADING_TYPE_PATCH_COORD 3
|
||||
|
||||
#define SHADING_TYPE_FACE_VARYING 4
|
||||
|
||||
struct PerFrameConstants {
|
||||
float4x4 ModelViewMatrix;
|
||||
@ -46,7 +46,7 @@ struct OutputVertex {
|
||||
float3 position;
|
||||
float3 normal;
|
||||
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE_FACE_VARYING
|
||||
float3 patchColor;
|
||||
#endif
|
||||
};
|
||||
@ -65,6 +65,7 @@ struct SolidColorVertex {
|
||||
private:
|
||||
uint _color [[flat, user(color)]];
|
||||
};
|
||||
|
||||
struct PackedInputVertex {
|
||||
packed_float3 position;
|
||||
};
|
||||
@ -190,7 +191,6 @@ getAdaptivePatchColor(int3 patchParam
|
||||
#if OSD_PATCH_REGULAR
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float3 P1 [[attribute(1)]];
|
||||
@ -213,7 +213,6 @@ struct PatchInput
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
struct ControlPoint
|
||||
{
|
||||
|
||||
float3 P [[attribute(0)]];
|
||||
float3 Ep [[attribute(1)]];
|
||||
float3 Em [[attribute(2)]];
|
||||
@ -399,6 +398,9 @@ vertex OutputVertex vertex_main(
|
||||
#else
|
||||
const OsdVertexBufferSet patchInput,
|
||||
#endif
|
||||
const device float* osdFaceVaryingData [[buffer(OSD_FVAR_DATA_BUFFER_INDEX)]],
|
||||
const device int* osdFaceVaryingIndices [[buffer(OSD_FVAR_INDICES_BUFFER_INDEX)]],
|
||||
const device packed_int3* osdFaceVaryingPatchParams [[buffer(OSD_FVAR_PATCHPARAM_BUFFER_INDEX)]],
|
||||
float2 position_in_patch [[position_in_patch]],
|
||||
uint patch_id [[patch_id]]
|
||||
)
|
||||
@ -430,6 +432,52 @@ vertex OutputVertex vertex_main(
|
||||
#elif SHADING_TYPE == SHADING_TYPE_NORMAL
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
out.patchColor = patchVertex.patchCoord.xyz;
|
||||
#elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING
|
||||
int patchIndex = OsdGetPatchIndex(patch_id);
|
||||
float2 uv = position_in_patch;
|
||||
#if OSD_FACEVARYING_PATCH_REGULAR
|
||||
float wP[16], wDs[16], wDt[16], wDss[16], wDst[16], wDtt[16];
|
||||
int patchCVs = 16;
|
||||
int patchStride = patchCVs;
|
||||
|
||||
int3 fvarPatchParam = osdFaceVaryingPatchParams[patchIndex];
|
||||
int boundaryMask = OsdGetPatchBoundaryMask(fvarPatchParam);
|
||||
OsdGetBSplinePatchWeights(uv.x, uv.y, 1.0f, boundaryMask, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
#elif OSD_FACEVARYING_PATCH_GREGORY_BASIS
|
||||
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
|
||||
int patchCVs = 20;
|
||||
int patchStride = patchCVs;
|
||||
int3 fvarPatchParam = osdFaceVaryingPatchParams[patchIndex];
|
||||
if (OsdGetPatchIsRegular(fvarPatchParam)) {
|
||||
float wP16[16], wDs16[16], wDt16[16], wDss16[16], wDst16[16], wDtt16[16];
|
||||
patchCVs = 16;
|
||||
int boundaryMask = OsdGetPatchBoundaryMask(fvarPatchParam);
|
||||
OsdGetBSplinePatchWeights(uv.x, uv.y, 1.0f, boundaryMask, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
|
||||
for (int i=0; i<patchCVs; ++i) {
|
||||
wP[i] = wP16[i];
|
||||
}
|
||||
} else {
|
||||
OsdGetGregoryPatchWeights(uv.x, uv.y, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
}
|
||||
#elif OSD_FACEVARYING_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
TODO
|
||||
#else
|
||||
float wP[4], wDs[4], wDt[4], wDss[4], wDst[4], wDtt[4];
|
||||
int patchCVs = 4;
|
||||
int patchStride = patchCVs;
|
||||
OsdGetBilinearPatchWeights(uv.x, uv.y, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
#endif
|
||||
|
||||
int primOffset = patchIndex * patchStride;
|
||||
|
||||
float2 fvarUV = float2(0.);
|
||||
for (int i = 0; i < patchCVs; ++i) {
|
||||
int index = osdFaceVaryingIndices[primOffset + i] * 2 /* OSD_FVAR_WIDTH */ + 0 /* fvarOffset */;
|
||||
float2 cv = float2(osdFaceVaryingData[index + 0], osdFaceVaryingData[index + 1]);
|
||||
fvarUV += wP[i] * cv;
|
||||
}
|
||||
|
||||
out.patchColor.rg = fvarUV;
|
||||
#endif
|
||||
|
||||
return out;
|
||||
@ -488,6 +536,7 @@ vertex SolidColorVertex vertex_lines(
|
||||
const auto in = osdPerPatchVertexBezier[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + BSplineControlLineIndices[idx]];
|
||||
|
||||
SolidColorVertex out;
|
||||
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0);
|
||||
out.positionOut.z -= 0.001;
|
||||
|
||||
@ -590,6 +639,8 @@ vertex OutputVertex vertex_main(
|
||||
device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]],
|
||||
device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]],
|
||||
const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]],
|
||||
const device float2* osdFaceVaryingData[[buffer(OSD_FVAR_DATA_BUFFER_INDEX)]],
|
||||
const device int* osdFaceVaryingIndices[[buffer(OSD_FVAR_INDICES_BUFFER_INDEX)]],
|
||||
uint vertex_id [[vertex_id]]
|
||||
)
|
||||
{
|
||||
@ -604,11 +655,13 @@ vertex OutputVertex vertex_main(
|
||||
float3 p1 = vertexBuffer[indicesBuffer[quadId * 4 + 1]].position;
|
||||
float3 p2 = vertexBuffer[indicesBuffer[quadId * 4 + 2]].position;
|
||||
float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position;
|
||||
float2 uv = osdFaceVaryingData[osdFaceVaryingIndices[quadId * 4 + triangleIdx[vertex_id % 6]]].xy;
|
||||
#else
|
||||
float3 p0 = vertexBuffer[indicesBuffer[primID * 3 + 0]].position;
|
||||
float3 p1 = vertexBuffer[indicesBuffer[primID * 3 + 1]].position;
|
||||
float3 p2 = vertexBuffer[indicesBuffer[primID * 3 + 2]].position;
|
||||
float3 position = vertexBuffer[indicesBuffer[vertex_id]].position;
|
||||
float2 uv = osdFacevaryingData[osdFaceVaryingIndices[vertex_id]].xy;
|
||||
#endif
|
||||
|
||||
float3 normal = normalize(cross(p2 - p1, p0 - p1));
|
||||
@ -617,12 +670,14 @@ vertex OutputVertex vertex_main(
|
||||
OutputVertex out;
|
||||
out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz;
|
||||
out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0);
|
||||
out.normal = (frameConsts.ModelViewMatrix * float4(normal,0.0)).xyz;
|
||||
out.normal = (frameConsts.ModelViewMatrix * float4(normal, 0.0)).xyz;
|
||||
|
||||
#if SHADING_TYPE == SHADING_TYPE_PATCH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
out.patchColor = out.normal;
|
||||
#elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING
|
||||
out.patchColor.rg = uv;
|
||||
#endif
|
||||
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -669,17 +724,17 @@ fragment float4 fragment_main(OutputVertex in [[stage_in]],
|
||||
const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f);
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH
|
||||
const float3 diffuseColor = in.patchColor;
|
||||
#else
|
||||
#endif
|
||||
#if SHADING_TYPE == SHADING_TYPE_NORMAL
|
||||
color.xyz = normalize(in.normal) * 0.5 + 0.5;
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD
|
||||
color.xy = in.patchColor.xy;
|
||||
color.z = 0;
|
||||
#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE == SHADING_TYPE_FACE_VARYING
|
||||
color.xyz = lighting(1.0, lightData, in.position, normalize(in.normal));
|
||||
int checker = int(floor(20*in.patchColor.r)+floor(20*in.patchColor.g))&1;
|
||||
color.xyz *= float3(in.patchColor.rg*checker, 1-checker);
|
||||
color.xyz = pow(color.xyz, 1/2.2);
|
||||
#else
|
||||
color.xyz = lighting(diffuseColor, lightData, in.position, normalize(in.normal));
|
||||
#endif
|
||||
// color.xyz = pow(color.xyz, 2.2);
|
||||
color.w = 1;
|
||||
return max(color,shade);
|
||||
}
|
||||
|
@ -67,9 +67,17 @@
|
||||
#define OSD_DRAWINDIRECT_BUFFER_INDEX 14
|
||||
#define OSD_KERNELLIMIT_BUFFER_INDEX 15
|
||||
|
||||
#define OSD_FVAR_DATA_BUFFER_INDEX 16
|
||||
#define OSD_FVAR_INDICES_BUFFER_INDEX 17
|
||||
#define OSD_FVAR_PATCHPARAM_BUFFER_INDEX 18
|
||||
|
||||
#define FRAME_CONST_BUFFER_INDEX 11
|
||||
#define INDICES_BUFFER_INDEX 2
|
||||
|
||||
#define USE_FACE_VARYING 1
|
||||
|
||||
#define FVAR_SINGLE_BUFFER 1
|
||||
|
||||
using namespace OpenSubdiv::OPENSUBDIV_VERSION;
|
||||
|
||||
template <> Far::StencilTable const * Osd::convertToCompatibleStencilTable<OpenSubdiv::Far::StencilTable, OpenSubdiv::Far::StencilTable, OpenSubdiv::Osd::MTLContext>(
|
||||
@ -145,12 +153,18 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
id<MTLDepthStencilState> _readWriteDepthStencilState;
|
||||
id<MTLDepthStencilState> _readOnlyDepthStencilState;
|
||||
|
||||
id<MTLBuffer> _faceVaryingDataBuffer;
|
||||
id<MTLBuffer> _faceVaryingIndicesBuffer;
|
||||
id<MTLBuffer> _faceVaryingPatchParamBuffer;
|
||||
|
||||
|
||||
Camera _cameraData;
|
||||
Osd::MTLContext _context;
|
||||
|
||||
|
||||
int _numVertexElements;
|
||||
int _numVaryingElements;
|
||||
int _numFaceVaryingElements;
|
||||
int _numVertices;
|
||||
int _frameCount;
|
||||
int _animationFrames;
|
||||
@ -199,7 +213,6 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
_context.device = [delegate deviceFor:self];
|
||||
_context.commandQueue = [delegate commandQueueFor:self];
|
||||
|
||||
|
||||
_osdShaderSource = @(shaderSource);
|
||||
|
||||
_needsRebuild = true;
|
||||
@ -216,13 +229,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
if(_needsRebuild) {
|
||||
[self _rebuildState];
|
||||
}
|
||||
|
||||
|
||||
if(!_freeze) {
|
||||
if(_animateVertices) {
|
||||
_animatedVertices.resize(_vertexData.size());
|
||||
auto p = _vertexData.data();
|
||||
auto n = _animatedVertices.data();
|
||||
|
||||
int numElements = _numVertexElements + _numVaryingElements;
|
||||
|
||||
float r = sin(_animationFrames*0.01f) * _animateVertices;
|
||||
for (int i = 0; i < _numVertices; ++i) {
|
||||
float move = 0.05f*cosf(p[0]*20+_animationFrames*0.01f);
|
||||
@ -232,8 +247,12 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
n[1] = -p[0]*st + p[1]*ct;
|
||||
n[2] = p[2];
|
||||
|
||||
p += _numVertexElements;
|
||||
n += _numVertexElements;
|
||||
for (int j = 0; j < _numVaryingElements; ++j) {
|
||||
n[3 + j] = p[3 + j];
|
||||
}
|
||||
|
||||
p += numElements;
|
||||
n += numElements;
|
||||
}
|
||||
|
||||
_mesh->UpdateVertexBuffer(_animatedVertices.data(), 0, _numVertices);
|
||||
@ -283,10 +302,18 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
|
||||
auto pav = _mesh->GetPatchTable()->GetPatchArrays();
|
||||
auto pib = _mesh->GetPatchTable()->GetPatchIndexBuffer();
|
||||
auto pfvarav = _mesh->GetPatchTable()->GetFVarPatchArrays();
|
||||
|
||||
[renderCommandEncoder setVertexBuffer:buffer offset:0 atIndex:VERTEX_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer: pib offset:0 atIndex:INDICES_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer:pib offset:0 atIndex:INDICES_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer:_frameConstantsBuffer offset:0 atIndex:FRAME_CONST_BUFFER_INDEX];
|
||||
#if FVAR_SINGLE_BUFFER
|
||||
int faceVaryingDataBufferOffset = _doAdaptive ? 0 : _shape->uvs.size() * sizeof(float);
|
||||
[renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:faceVaryingDataBufferOffset atIndex:OSD_FVAR_DATA_BUFFER_INDEX];
|
||||
#else
|
||||
[renderCommandEncoder setVertexBuffer:_faceVaryingDataBuffer offset:0 atIndex:OSD_FVAR_DATA_BUFFER_INDEX];
|
||||
#endif
|
||||
[renderCommandEncoder setVertexBuffer:_faceVaryingIndicesBuffer offset:0 atIndex:OSD_FVAR_INDICES_BUFFER_INDEX];
|
||||
|
||||
if(_doAdaptive)
|
||||
{
|
||||
@ -294,6 +321,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
[renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer:_mesh->GetPatchTable()->GetPatchParamBuffer() offset:0 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer:_perPatchDataBuffer offset:0 atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBuffer:_faceVaryingPatchParamBuffer offset:0 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX];
|
||||
}
|
||||
|
||||
if(_endCapMode == kEndCapLegacyGregory)
|
||||
@ -323,6 +351,12 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
if(_doAdaptive)
|
||||
{
|
||||
[renderCommandEncoder setVertexBufferOffset:patch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_PATCHPARAM_BUFFER_INDEX];
|
||||
|
||||
auto& fvarPatch = pfvarav[i];
|
||||
assert(sizeof(Osd::PatchParam) == sizeof(int) * 3);
|
||||
|
||||
[renderCommandEncoder setVertexBufferOffset:fvarPatch.primitiveIdBase * sizeof(int) * 3 atIndex:OSD_FVAR_PATCHPARAM_BUFFER_INDEX];
|
||||
[renderCommandEncoder setVertexBufferOffset:fvarPatch.indexBase * sizeof(unsigned) atIndex:OSD_FVAR_INDICES_BUFFER_INDEX];
|
||||
}
|
||||
|
||||
[renderCommandEncoder setVertexBufferOffset:patch.indexBase * sizeof(unsigned) atIndex:INDICES_BUFFER_INDEX];
|
||||
@ -367,7 +401,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
|
||||
if(_displayStyle == kDisplayStyleWireOnShaded)
|
||||
{
|
||||
simd::float4 shade = {1, 1,1,1};
|
||||
simd::float4 shade = {1,1,1,1};
|
||||
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
|
||||
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
|
||||
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
|
||||
@ -440,7 +474,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * 6];
|
||||
if(_displayStyle == kDisplayStyleWireOnShaded)
|
||||
{
|
||||
simd::float4 shade = {1, 1,1,1};
|
||||
simd::float4 shade = {1,1,1,1};
|
||||
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
|
||||
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
|
||||
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
|
||||
@ -453,7 +487,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
[renderCommandEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:patch.GetNumPatches() * d.GetNumControlVertices()];
|
||||
if(_displayStyle == kDisplayStyleWireOnShaded)
|
||||
{
|
||||
simd::float4 shade = {1, 1,1,1};
|
||||
simd::float4 shade = {1,1,1,1};
|
||||
[renderCommandEncoder setFragmentBytes:&shade length:sizeof(shade) atIndex:2];
|
||||
[renderCommandEncoder setTriangleFillMode:MTLTriangleFillModeLines];
|
||||
[renderCommandEncoder setDepthBias:-5 slopeScale:-1.0 clamp:-100.0];
|
||||
@ -569,6 +603,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
kernelExecutionLimit = patch.GetNumPatches() * 4;
|
||||
[computeCommandEncoder setBufferOffset:_perPatchDataOffsets[3] atIndex:OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX];
|
||||
[computeCommandEncoder setBufferOffset:_tessFactorOffsets[3] atIndex:QUAD_TESSFACTORS_INDEX];
|
||||
break;
|
||||
default: assert("Unsupported patch type" && 0); break;
|
||||
@ -593,7 +628,6 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
using namespace Sdc;
|
||||
using namespace Osd;
|
||||
using namespace Far;
|
||||
|
||||
auto shapeDesc = &g_defaultShapes[[_loadedModels indexOfObject:_currentModel]];
|
||||
_shape.reset(Shape::parseObj(shapeDesc->data.c_str(), shapeDesc->scheme));
|
||||
const auto scheme = shapeDesc->scheme;
|
||||
@ -601,10 +635,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
// create Far mesh (topology)
|
||||
Sdc::SchemeType sdctype = GetSdcType(*_shape);
|
||||
Sdc::Options sdcoptions = GetSdcOptions(*_shape);
|
||||
|
||||
|
||||
sdcoptions.SetFVarLinearInterpolation((OpenSubdiv::Sdc::Options::FVarLinearInterpolation)_fVarBoundary);
|
||||
|
||||
std::unique_ptr<OpenSubdiv::Far::TopologyRefiner> refiner;
|
||||
refiner.reset(
|
||||
Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)));
|
||||
refiner.reset(Far::TopologyRefinerFactory<Shape>::Create(*_shape, Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions)));
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0);
|
||||
@ -626,22 +661,33 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
|
||||
int level = _refinementLevel;
|
||||
_numVertexElements = 3;
|
||||
int numVaryingElements = 0;
|
||||
|
||||
#if USE_FACE_VARYING
|
||||
_numFaceVaryingElements = _shape->HasUV() ? 2 : 0;
|
||||
#else
|
||||
_numFaceVaryingElements = 0;
|
||||
#endif
|
||||
|
||||
_numVaryingElements = 0;
|
||||
|
||||
bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, _numVaryingElements > 0);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarData, _numFaceVaryingElements > 0);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarAdaptive, _doAdaptive);
|
||||
|
||||
int numElements = _numVertexElements + _numVaryingElements;
|
||||
|
||||
if(_kernelType == kCPU)
|
||||
{
|
||||
_mesh.reset(new CPUMeshType(
|
||||
refiner.release(),
|
||||
_mesh.reset(new CPUMeshType(refiner.get(),
|
||||
_numVertexElements,
|
||||
numVaryingElements,
|
||||
_numVaryingElements,
|
||||
level, bits, nullptr, &_context));
|
||||
}
|
||||
else
|
||||
{
|
||||
_mesh.reset(new mtlMeshType(
|
||||
refiner.release(),
|
||||
_mesh.reset(new mtlMeshType(refiner.get(),
|
||||
_numVertexElements,
|
||||
numVaryingElements,
|
||||
_numVaryingElements,
|
||||
level, bits, nullptr, &_context));
|
||||
}
|
||||
|
||||
@ -650,7 +696,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
[_delegate setupRenderPipelineState:desc for:self];
|
||||
|
||||
const auto vertexDescriptor = desc.vertexDescriptor;
|
||||
vertexDescriptor.layouts[0].stride = sizeof(float) * _numVertexElements;
|
||||
vertexDescriptor.layouts[0].stride = sizeof(float) * numElements;
|
||||
vertexDescriptor.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
|
||||
vertexDescriptor.layouts[0].stepRate = 1;
|
||||
vertexDescriptor.attributes[0].format = MTLVertexFormatFloat3;
|
||||
@ -669,51 +715,111 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
&_context));
|
||||
}
|
||||
|
||||
_vertexData.resize(refBaseLevel.GetNumVertices() * _numVertexElements);
|
||||
_vertexData.resize(refBaseLevel.GetNumVertices() * numElements);
|
||||
_meshCenter = simd::float3{0,0,0};
|
||||
|
||||
if(_shape->normals.size())
|
||||
for(int i = 0; i < refBaseLevel.GetNumVertices(); i++)
|
||||
{
|
||||
for(int i = 0; i < refBaseLevel.GetNumVertices(); i++)
|
||||
{
|
||||
_vertexData[i * _numVertexElements + 0] = _shape->verts[i * 3 + 0];
|
||||
_vertexData[i * _numVertexElements + 1] = _shape->verts[i * 3 + 1];
|
||||
_vertexData[i * _numVertexElements + 2] = _shape->verts[i * 3 + 2];
|
||||
}
|
||||
_vertexData[i * numElements + 0] = _shape->verts[i * 3 + 0];
|
||||
_vertexData[i * numElements + 1] = _shape->verts[i * 3 + 1];
|
||||
_vertexData[i * numElements + 2] = _shape->verts[i * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++)
|
||||
{
|
||||
_vertexData[vertexIdx * _numVertexElements + 0] = _shape->verts[vertexIdx * 3 + 0];
|
||||
_vertexData[vertexIdx * _numVertexElements + 1] = _shape->verts[vertexIdx * 3 + 1];
|
||||
_vertexData[vertexIdx * _numVertexElements + 2] = _shape->verts[vertexIdx * 3 + 2];
|
||||
}
|
||||
|
||||
for(auto faceIdx = 0; faceIdx < refBaseLevel.GetNumFaces(); faceIdx++)
|
||||
{
|
||||
auto faceIndices = refBaseLevel.GetFaceVertices(faceIdx);
|
||||
simd::float3 v[4];
|
||||
for(int faceVert = 0; faceVert < faceIndices.size(); faceVert++)
|
||||
{
|
||||
memcpy(v + faceVert, _shape->verts.data() + faceIndices[faceVert] * 3, sizeof(float) * 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(auto vertexIdx = 0; vertexIdx < refBaseLevel.GetNumVertices(); vertexIdx++)
|
||||
{
|
||||
_meshCenter[0] += _vertexData[vertexIdx * _numVertexElements + 0];
|
||||
_meshCenter[1] += _vertexData[vertexIdx * _numVertexElements + 1];
|
||||
_meshCenter[2] += _vertexData[vertexIdx * _numVertexElements + 2];
|
||||
_meshCenter[0] += _vertexData[vertexIdx * numElements + 0];
|
||||
_meshCenter[1] += _vertexData[vertexIdx * numElements + 1];
|
||||
_meshCenter[2] += _vertexData[vertexIdx * numElements + 2];
|
||||
}
|
||||
|
||||
|
||||
_meshCenter /= (_shape->verts.size() / 3);
|
||||
_mesh->UpdateVertexBuffer(_vertexData.data(), 0, refBaseLevel.GetNumVertices());
|
||||
_mesh->Refine();
|
||||
_mesh->Synchronize();
|
||||
|
||||
if(_numFaceVaryingElements > 0)
|
||||
{
|
||||
Far::StencilTableFactory::Options stencilTableFactoryOptions;
|
||||
stencilTableFactoryOptions.interpolationMode = Far::StencilTableFactory::INTERPOLATE_FACE_VARYING;
|
||||
stencilTableFactoryOptions.generateOffsets = true;
|
||||
stencilTableFactoryOptions.generateControlVerts = false;
|
||||
stencilTableFactoryOptions.generateIntermediateLevels = _doAdaptive;
|
||||
stencilTableFactoryOptions.factorizeIntermediateLevels = true;
|
||||
stencilTableFactoryOptions.maxLevel = level;
|
||||
stencilTableFactoryOptions.fvarChannel = 0;
|
||||
|
||||
Far::PatchTable const *farPatchTable = _mesh->GetFarPatchTable();
|
||||
Far::StencilTable const *stencilTable = Far::StencilTableFactory::Create(*refiner, stencilTableFactoryOptions);
|
||||
Far::StencilTable const *stencilTableWithLocalPoints = Far::StencilTableFactory::AppendLocalPointStencilTableFaceVarying(*refiner,
|
||||
stencilTable,
|
||||
farPatchTable->GetLocalPointFaceVaryingStencilTable(),
|
||||
0);
|
||||
|
||||
if(stencilTableWithLocalPoints) {
|
||||
delete stencilTable;
|
||||
stencilTable = stencilTableWithLocalPoints;
|
||||
}
|
||||
|
||||
Osd::MTLStencilTable mtlStencilTable = Osd::MTLStencilTable(stencilTable, &_context);
|
||||
|
||||
uint32_t fvarWidth = _numFaceVaryingElements;
|
||||
uint32_t coarseFVarValuesCount = _shape->uvs.size() / fvarWidth;
|
||||
uint32_t finalFVarValuesCount = stencilTable->GetNumStencils();
|
||||
|
||||
#if FVAR_SINGLE_BUFFER
|
||||
Osd::CPUMTLVertexBuffer *fvarDataBuffer = Osd::CPUMTLVertexBuffer::Create(fvarWidth, coarseFVarValuesCount + finalFVarValuesCount, &_context);
|
||||
fvarDataBuffer->UpdateData(_shape->uvs.data(), 0, coarseFVarValuesCount, &_context);
|
||||
|
||||
_faceVaryingDataBuffer = fvarDataBuffer->BindMTLBuffer(&_context);
|
||||
_faceVaryingDataBuffer.label = @"OSD FVar data";
|
||||
|
||||
Osd::BufferDescriptor srcDesc(0, fvarWidth, fvarWidth);
|
||||
Osd::BufferDescriptor dstDesc(coarseFVarValuesCount * fvarWidth, fvarWidth, fvarWidth);
|
||||
|
||||
Osd::MTLComputeEvaluator::EvalStencils(fvarDataBuffer, srcDesc,
|
||||
fvarDataBuffer, dstDesc,
|
||||
&mtlStencilTable,
|
||||
nullptr,
|
||||
&_context);
|
||||
#else
|
||||
Osd::CPUMTLVertexBuffer *coarseFVarDataBuffer = Osd::CPUMTLVertexBuffer::Create(fvarWidth, coarseFVarValuesCount, &_context);
|
||||
coarseFVarDataBuffer->UpdateData(_shape->uvs.data(), 0, coarseFVarValuesCount, &_context);
|
||||
|
||||
id<MTLBuffer> mtlCoarseFVarDataBuffer = coarseFVarDataBuffer->BindMTLBuffer(&_context);
|
||||
mtlCoarseFVarDataBuffer.label = @"OSD FVar coarse data";
|
||||
|
||||
Osd::CPUMTLVertexBuffer *refinedFVarDataBuffer = Osd::CPUMTLVertexBuffer::Create(fvarWidth, finalFVarValuesCount, &_context);
|
||||
_faceVaryingDataBuffer = refinedFVarDataBuffer->BindMTLBuffer(&_context);
|
||||
_faceVaryingDataBuffer.label = @"OSD FVar data";
|
||||
|
||||
Osd::BufferDescriptor coarseBufferDescriptor(0, fvarWidth, fvarWidth);
|
||||
Osd::BufferDescriptor refinedBufferDescriptor(0, fvarWidth, fvarWidth);
|
||||
|
||||
Osd::MTLComputeEvaluator::EvalStencils(coarseFVarDataBuffer, coarseBufferDescriptor,
|
||||
refinedFVarDataBuffer, refinedBufferDescriptor,
|
||||
&mtlStencilTable,
|
||||
nullptr,
|
||||
&_context);
|
||||
#endif
|
||||
|
||||
Osd::MTLPatchTable const *patchTable = _mesh->GetPatchTable();
|
||||
|
||||
_faceVaryingIndicesBuffer = patchTable->GetFVarPatchIndexBuffer(0);
|
||||
_faceVaryingIndicesBuffer.label = @"OSD FVar indices";
|
||||
|
||||
_faceVaryingPatchParamBuffer = patchTable->GetFVarPatchParamBuffer(0);
|
||||
_faceVaryingPatchParamBuffer.label = @"OSD FVar patch params";
|
||||
|
||||
#if FVAR_SINGLE_BUFFER
|
||||
delete fvarDataBuffer;
|
||||
#else
|
||||
delete refinedFVarDataBuffer;
|
||||
delete coarseFVarDataBuffer;
|
||||
#endif
|
||||
delete stencilTable;
|
||||
}
|
||||
|
||||
refiner.release();
|
||||
}
|
||||
|
||||
-(void)_updateState {
|
||||
@ -771,11 +877,13 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
}
|
||||
_tessFactorOffsets[0] = totalPatches * sizeof(MTLQuadTessellationFactorsHalf);
|
||||
_perPatchDataOffsets[0] = totalPatchDataSize;
|
||||
|
||||
float elementFloats = 3;
|
||||
if(_useSingleCrease)
|
||||
elementFloats += 6;
|
||||
|
||||
totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
|
||||
totalPatchDataSize += elementFloats * sizeof(float) * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); // OsdPerPatchVertexBezier
|
||||
|
||||
}
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY:
|
||||
@ -785,8 +893,10 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
}
|
||||
_tessFactorOffsets[1] = totalPatches * sizeof(MTLQuadTessellationFactorsHalf);
|
||||
_perPatchDataOffsets[1] = totalPatchDataSize;
|
||||
totalPatchDataSize += sizeof(float) * 4 * 8 * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
|
||||
totalPatchDataSize += sizeof(float) * 3 * 5 * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
|
||||
|
||||
break;
|
||||
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY:
|
||||
if(_usePatchIndexBuffer)
|
||||
{
|
||||
@ -794,7 +904,8 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
}
|
||||
_tessFactorOffsets[2] = totalPatches * sizeof(MTLQuadTessellationFactorsHalf);
|
||||
_perPatchDataOffsets[2] = totalPatchDataSize;
|
||||
totalPatchDataSize += sizeof(float) * 4 * 8 * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
|
||||
totalPatchDataSize += sizeof(float) * 3 * 5 * patch.GetNumPatches() * patch.desc.GetNumControlVertices();
|
||||
|
||||
break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS:
|
||||
if(_usePatchIndexBuffer)
|
||||
@ -803,7 +914,8 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
}
|
||||
_tessFactorOffsets[3] = totalPatches * sizeof(MTLQuadTessellationFactorsHalf);
|
||||
_perPatchDataOffsets[3] = totalPatchDataSize;
|
||||
//Improved basis doesn't have per-patch-per-vertex data.
|
||||
totalPatchDataSize += sizeof(float) * 3 * patch.GetNumPatches() * patch.desc.GetNumControlVertices(); // OsdPerPatchVertexGregory
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -826,13 +938,15 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
}
|
||||
|
||||
Osd::MTLPatchShaderSource shaderSource;
|
||||
auto& patchArrays = _mesh->GetPatchTable()->GetPatchArrays();
|
||||
for(auto& patch : patchArrays)
|
||||
auto patchArrays = _mesh->GetPatchTable()->GetPatchArrays();
|
||||
auto pFVarArray = _mesh->GetPatchTable()->GetFVarPatchArrays();
|
||||
for(int i = 0; i < patchArrays.size(); ++i)
|
||||
{
|
||||
auto type = patch.GetDescriptor().GetType();
|
||||
auto type = patchArrays[i].GetDescriptor().GetType();
|
||||
auto fvarType = pFVarArray[i].GetDescriptor().GetType();
|
||||
auto& threadsPerThreadgroup = _threadgroupSizes[type];
|
||||
threadsPerThreadgroup = 32; //Initial guess of 32
|
||||
int usefulControlPoints = patch.GetDescriptor().GetNumControlVertices();
|
||||
int usefulControlPoints = patchArrays[i].GetDescriptor().GetNumControlVertices();
|
||||
|
||||
auto compileOptions = [[MTLCompileOptions alloc] init];
|
||||
auto preprocessor = [[NSMutableDictionary alloc] init];
|
||||
@ -873,20 +987,27 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
#endif
|
||||
|
||||
//Need to define the input vertex struct so that it's available everywhere.
|
||||
shaderBuilder << R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
{
|
||||
shaderBuilder << R"(
|
||||
#include <metal_stdlib>
|
||||
using namespace metal;
|
||||
|
||||
struct OsdInputVertexType {
|
||||
metal::packed_float3 position;
|
||||
};
|
||||
)";
|
||||
}
|
||||
|
||||
struct OsdInputVertexType {
|
||||
metal::packed_float3 position;
|
||||
};
|
||||
)";
|
||||
|
||||
shaderBuilder << shaderSource.GetHullShaderSource(type);
|
||||
shaderBuilder << shaderSource.GetHullShaderSource(type, fvarType);
|
||||
if(_numFaceVaryingElements > 0)
|
||||
shaderBuilder << shaderSource.GetPatchBasisShaderSource();
|
||||
shaderBuilder << _osdShaderSource.UTF8String;
|
||||
|
||||
const auto str = shaderBuilder.str();
|
||||
|
||||
int numElements = _numVertexElements + _numVaryingElements;
|
||||
|
||||
DEFINE(VERTEX_BUFFER_INDEX,VERTEX_BUFFER_INDEX);
|
||||
DEFINE(PATCH_INDICES_BUFFER_INDEX,PATCH_INDICES_BUFFER_INDEX);
|
||||
DEFINE(CONTROL_INDICES_BUFFER_INDEX,CONTROL_INDICES_BUFFER_INDEX);
|
||||
@ -916,15 +1037,18 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
DEFINE(USE_PTVS_SHARPNESS, 1);
|
||||
DEFINE(THREADS_PER_THREADGROUP, threadsPerThreadgroup);
|
||||
DEFINE(CONTROL_POINTS_PER_THREAD, std::max<int>(1, usefulControlPoints / threadsPerThreadgroup));
|
||||
DEFINE(VERTEX_CONTROL_POINTS_PER_PATCH, patch.desc.GetNumControlVertices());
|
||||
DEFINE(VERTEX_CONTROL_POINTS_PER_PATCH, patchArrays[i].desc.GetNumControlVertices());
|
||||
DEFINE(OSD_MAX_VALENCE, _mesh->GetMaxValence());
|
||||
DEFINE(OSD_NUM_ELEMENTS, _numVertexElements);
|
||||
DEFINE(OSD_NUM_ELEMENTS, numElements);
|
||||
DEFINE(OSD_ENABLE_BACKPATCH_CULL, _usePatchBackfaceCulling);
|
||||
DEFINE(SHADING_TYPE, _shadingMode);
|
||||
DEFINE(OSD_USE_PATCH_INDEX_BUFFER, _usePatchIndexBuffer);
|
||||
DEFINE(OSD_ENABLE_SCREENSPACE_TESSELLATION, _useScreenspaceTessellation && _useFractionalTessellation);
|
||||
DEFINE(OSD_ENABLE_PATCH_CULL, _usePatchClipCulling && _doAdaptive);
|
||||
|
||||
DEFINE(OSD_FVAR_DATA_BUFFER_INDEX, OSD_FVAR_DATA_BUFFER_INDEX);
|
||||
DEFINE(OSD_FVAR_INDICES_BUFFER_INDEX, OSD_FVAR_INDICES_BUFFER_INDEX);
|
||||
DEFINE(OSD_FVAR_PATCHPARAM_BUFFER_INDEX, OSD_FVAR_PATCHPARAM_BUFFER_INDEX);
|
||||
|
||||
compileOptions.preprocessorMacros = preprocessor;
|
||||
|
||||
NSError* err = nil;
|
||||
@ -974,7 +1098,7 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[OSD_PATCHPARAM_BUFFER_INDEX].stride = sizeof(int) * 3;
|
||||
|
||||
|
||||
// PatchInput :: int3 patchParam [[attribute(10)]];
|
||||
vertexDesc.attributes[10].bufferIndex = OSD_PATCHPARAM_BUFFER_INDEX;
|
||||
vertexDesc.attributes[10].format = MTLVertexFormatInt3;
|
||||
vertexDesc.attributes[10].offset = 0;
|
||||
@ -987,33 +1111,45 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride = sizeof(float) * 3;
|
||||
|
||||
// ControlPoint :: float3 P [[attribute(0)]];
|
||||
// OsdPerPatchVertexBezier :: packed_float3 P
|
||||
vertexDesc.attributes[0].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
|
||||
vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
|
||||
vertexDesc.attributes[0].offset = 0;
|
||||
|
||||
if(_useSingleCrease)
|
||||
{
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 6;
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX].stride += sizeof(float) * 3 * 2;
|
||||
|
||||
// ControlPoint :: float3 P1 [[attribute(1)]];
|
||||
// OsdPerPatchVertexBezier :: packed_float3 P1
|
||||
vertexDesc.attributes[1].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
|
||||
vertexDesc.attributes[1].format = MTLVertexFormatFloat3;
|
||||
vertexDesc.attributes[1].offset = sizeof(float) * 3;
|
||||
|
||||
// ControlPoint :: float3 P2 [[attribute(2)]];
|
||||
// OsdPerPatchVertexBezier :: packed_float3 P2
|
||||
vertexDesc.attributes[2].bufferIndex = OSD_PERPATCHVERTEXBEZIER_BUFFER_INDEX;
|
||||
vertexDesc.attributes[2].format = MTLVertexFormatFloat3;
|
||||
vertexDesc.attributes[2].offset = sizeof(float) * 6;
|
||||
|
||||
// USE_PTVS_SHARPNESS is true and so OsdPerPatchVertexBezier :: float2 vSegments is not used
|
||||
}
|
||||
|
||||
if(_useScreenspaceTessellation)
|
||||
{
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepFunction = MTLVertexStepFunctionPerPatch;
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 8;
|
||||
vertexDesc.layouts[OSD_PERPATCHTESSFACTORS_BUFFER_INDEX].stride = sizeof(float) * 4 * 2;
|
||||
|
||||
// PatchInput :: float4 tessOuterLo [[attribute(5)]];
|
||||
// OsdPerPatchTessFactors :: float4 tessOuterLo;
|
||||
vertexDesc.attributes[5].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
|
||||
vertexDesc.attributes[5].format = MTLVertexFormatFloat4;
|
||||
vertexDesc.attributes[5].offset = 0;
|
||||
|
||||
// PatchInput :: float4 tessOuterHi [[attribute(6)]];
|
||||
// OsdPerPatchTessFactors :: float4 tessOuterHi;
|
||||
vertexDesc.attributes[6].bufferIndex = OSD_PERPATCHTESSFACTORS_BUFFER_INDEX;
|
||||
vertexDesc.attributes[6].format = MTLVertexFormatFloat4;
|
||||
vertexDesc.attributes[6].offset = sizeof(float) * 4;
|
||||
@ -1026,6 +1162,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX].stride = sizeof(float) * 3 * 5;
|
||||
|
||||
// ControlPoint :: float3 P [[attribute(0)]];
|
||||
// ControlPoint :: float3 Ep [[attribute(1)]];
|
||||
// ControlPoint :: float3 Em [[attribute(2)]];
|
||||
// ControlPoint :: float3 Fp [[attribute(3)]];
|
||||
// ControlPoint :: float3 Fm [[attribute(4)]];
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
vertexDesc.attributes[i].bufferIndex = OSD_PERPATCHVERTEXGREGORY_BUFFER_INDEX;
|
||||
@ -1038,9 +1179,11 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stepRate = 1;
|
||||
vertexDesc.layouts[VERTEX_BUFFER_INDEX].stride = sizeof(float) * 3;
|
||||
|
||||
// ControlPoint :: float3 position [[attribute(0)]];
|
||||
vertexDesc.attributes[0].bufferIndex = VERTEX_BUFFER_INDEX;
|
||||
vertexDesc.attributes[0].format = MTLVertexFormatFloat3;
|
||||
vertexDesc.attributes[0].offset = 0;
|
||||
|
||||
break;
|
||||
case Far::PatchDescriptor::QUADS:
|
||||
//Quads cannot use stage in, due to the need for re-indexing.
|
||||
@ -1212,6 +1355,12 @@ using PerFrameBuffer = MTLRingBuffer<DataType, FRAME_LAG>;
|
||||
_kernelType = kernelType;
|
||||
}
|
||||
|
||||
|
||||
-(void)setFVarBoundary:(FVarBoundary)fVarBoundary {
|
||||
_needsRebuild |= (fVarBoundary != _fVarBoundary);
|
||||
_fVarBoundary = fVarBoundary;
|
||||
}
|
||||
|
||||
-(void)setCurrentModel:(NSString *)currentModel {
|
||||
_needsRebuild |= ![currentModel isEqualToString:_currentModel];
|
||||
_currentModel = currentModel;
|
||||
|
@ -39,11 +39,14 @@ namespace OpenSubdiv {
|
||||
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
@ -50,19 +50,28 @@ namespace OpenSubdiv {
|
||||
#include "mtlPatchGregoryBasis.gen.h"
|
||||
);
|
||||
|
||||
static std::string GetPatchTypeDefine(Far::PatchDescriptor::Type type) {
|
||||
static std::string GetPatchTypeDefine(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
switch(type) {
|
||||
case Far::PatchDescriptor::LINES: return "#define OSD_PATCH_LINES 1\n";
|
||||
case Far::PatchDescriptor::TRIANGLES: return "#define OSD_PATCH_TRIANGLES 1\n";
|
||||
case Far::PatchDescriptor::QUADS: return "#define OSD_PATCH_QUADS 1\n";
|
||||
case Far::PatchDescriptor::REGULAR: return "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n";
|
||||
case Far::PatchDescriptor::GREGORY: return "#define OSD_PATCH_GREGORY 1\n";
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY: return "#define OSD_PATCH_GREGORY_BOUNDRY 1\n";
|
||||
case Far::PatchDescriptor::GREGORY_BASIS: return "#define OSD_PATCH_GREGORY_BASIS 1\n";
|
||||
case Far::PatchDescriptor::LINES: ss << "#define OSD_PATCH_LINES 1\n"; break;
|
||||
case Far::PatchDescriptor::TRIANGLES: ss << "#define OSD_PATCH_TRIANGLES 1\n"; break;
|
||||
case Far::PatchDescriptor::QUADS: ss << "#define OSD_PATCH_QUADS 1\n"; break;
|
||||
case Far::PatchDescriptor::REGULAR: ss << "#define OSD_PATCH_BSPLINE 1\n#define OSD_PATCH_REGULAR 1\n"; break;
|
||||
case Far::PatchDescriptor::GREGORY: ss << "#define OSD_PATCH_GREGORY 1\n"; break;
|
||||
case Far::PatchDescriptor::GREGORY_BOUNDARY: ss << "#define OSD_PATCH_GREGORY_BOUNDRY 1\n"; break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_PATCH_GREGORY_BASIS 1\n"; break;
|
||||
default:
|
||||
assert("Unknown Far::PatchDescriptor::Type" && 0);
|
||||
return "";
|
||||
}
|
||||
switch(fvarType) {
|
||||
case Far::PatchDescriptor::REGULAR: ss << "#define OSD_FACEVARYING_PATCH_REGULAR 1\n"; break;
|
||||
case Far::PatchDescriptor::GREGORY_BASIS: ss << "#define OSD_FACEVARYING_PATCH_GREGORY_BASIS 1\n"; break;
|
||||
default:
|
||||
return ss.str();
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string GetPatchTypeSource(Far::PatchDescriptor::Type type) {
|
||||
@ -102,9 +111,10 @@ namespace OpenSubdiv {
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type) {
|
||||
MTLPatchShaderSource::GetVertexShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
@ -112,9 +122,10 @@ namespace OpenSubdiv {
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type) {
|
||||
MTLPatchShaderSource::GetHullShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
@ -122,9 +133,10 @@ namespace OpenSubdiv {
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type) {
|
||||
MTLPatchShaderSource::GetDomainShaderSource(Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType) {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchTypeDefine(type);
|
||||
ss << GetPatchTypeDefine(type, fvarType);
|
||||
ss << GetCommonShaderSource();
|
||||
ss << GetPatchTypeSource(type);
|
||||
return ss.str();
|
||||
|
Loading…
Reference in New Issue
Block a user