1#line 0 "examples/mtlViewer/mtlViewer.metal" 2 3// 4// Copyright 2013 Pixar 5// 6// Licensed under the Apache License, Version 2.0 (the "Apache License") 7// with the following modification; you may not use this file except in 8// compliance with the Apache License and the following modification to it: 9// Section 6. Trademarks. is deleted and replaced with: 10// 11// 6. Trademarks. This License does not grant permission to use the trade 12// names, trademarks, service marks, or product names of the Licensor 13// and its affiliates, except as required to comply with Section 4(c) of 14// the License and to reproduce the content of the NOTICE file. 15// 16// You may obtain a copy of the Apache License at 17// 18// http://www.apache.org/licenses/LICENSE-2.0 19// 20// Unless required by applicable law or agreed to in writing, software 21// distributed under the Apache License with the above modification is 22// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 23// KIND, either express or implied. See the Apache License for the specific 24// language governing permissions and limitations under the Apache License. 25// 26 27#include <metal_stdlib> 28using namespace metal; 29 30#if OSD_IS_ADAPTIVE 31static_assert(!OSD_ENABLE_SCREENSPACE_TESSELLATION || !USE_PTVS_FACTORS, "USE_PTVS_FACTORS cannot be enabled if OSD_ENABLE_SCREENSPACE_TESSELLATION is enabled"); 32#endif 33 34#define SHADING_TYPE_MATERIAL 0 35#define SHADING_TYPE_FACE_VARYING_COLOR 1 36#define SHADING_TYPE_PATCH_TYPE 2 37#define SHADING_TYPE_PATCH_DEPTH 3 38#define SHADING_TYPE_PATCH_COORD 4 39#define SHADING_TYPE_NORMAL 5 40 41struct PerFrameConstants { 42 float4x4 ModelViewMatrix; 43 float4x4 ProjectionMatrix; 44 float4x4 ModelViewProjectionMatrix; 45 float4x4 ModelViewInverseMatrix; 46 float TessLevel; 47}; 48 49struct OutputVertex { 50 float4 positionOut [[position]]; 51 float3 position; 52 float3 normal; 53#if SHADING_TYPE == SHADING_TYPE_PATCH_TYPE || SHADING_TYPE == SHADING_TYPE_PATCH_DEPTH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE_FACE_VARYING_COLOR 54 float3 patchColor; 55#endif 56}; 57 58struct SolidColorVertex { 59 float4 positionOut [[position]]; 60 61 half4 getColor() const { 62 return unpack_unorm4x8_to_half(_color); 63 } 64 65 void setColor(half4 color) { 66 _color = pack_half_to_unorm4x8(color); 67 } 68 69private: 70 uint _color [[flat, user(color)]]; 71}; 72 73struct PackedInputVertex { 74 packed_float3 position; 75}; 76 77struct Light { 78 float3 Position; 79 float3 ambient; 80 float3 diffuse; 81 float3 specular; 82}; 83 84float3 lighting(float3 diffuseColor, const constant Light* lightData, float3 eyePos, float3 eyeN) 85{ 86 87 float3 color(0); 88 for(int i = 0; i < 2; i++) 89 { 90 const auto l = lightData[i].Position; 91 const auto h = normalize(l + float3(0,0,1)); 92 const auto d = max(0.0, dot(eyeN, l)); 93 const auto s = powr(max(0.0, dot(eyeN, h)), 500.0f); 94 95 color += lightData[i].ambient 96 + d * lightData[i].diffuse * diffuseColor 97 + s * lightData[i].specular; 98 } 99 100 return color; 101} 102 103 104const constant float4 patchColors[] = { 105 float4(1.0f, 1.0f, 1.0f, 1.0f), // regular 106 float4(0.0f, 1.0f, 1.0f, 1.0f), // regular pattern 0 107 float4(0.0f, 0.5f, 1.0f, 1.0f), // regular pattern 1 108 float4(0.0f, 0.5f, 0.5f, 1.0f), // regular pattern 2 109 float4(0.5f, 0.0f, 1.0f, 1.0f), // regular pattern 3 110 float4(1.0f, 0.5f, 1.0f, 1.0f), // regular pattern 4 111 112 float4(1.0f, 0.5f, 0.5f, 1.0f), // single crease 113 float4(1.0f, 0.70f, 0.6f, 1.0f), // single crease pattern 0 114 float4(1.0f, 0.65f, 0.6f, 1.0f), // single crease pattern 1 115 float4(1.0f, 0.60f, 0.6f, 1.0f), // single crease pattern 2 116 float4(1.0f, 0.55f, 0.6f, 1.0f), // single crease pattern 3 117 float4(1.0f, 0.50f, 0.6f, 1.0f), // single crease pattern 4 118 119 float4(0.8f, 0.0f, 0.0f, 1.0f), // boundary 120 float4(0.0f, 0.0f, 0.75f, 1.0f), // boundary pattern 0 121 float4(0.0f, 0.2f, 0.75f, 1.0f), // boundary pattern 1 122 float4(0.0f, 0.4f, 0.75f, 1.0f), // boundary pattern 2 123 float4(0.0f, 0.6f, 0.75f, 1.0f), // boundary pattern 3 124 float4(0.0f, 0.8f, 0.75f, 1.0f), // boundary pattern 4 125 126 float4(0.0f, 1.0f, 0.0f, 1.0f), // corner 127 float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 0 128 float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 1 129 float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 2 130 float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 3 131 float4(0.5f, 1.0f, 0.5f, 1.0f), // corner pattern 4 132 133 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 134 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 135 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 136 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 137 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 138 float4(1.0f, 1.0f, 0.0f, 1.0f), // gregory 139 140 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 141 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 142 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 143 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 144 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 145 float4(1.0f, 0.5f, 0.0f, 1.0f), // gregory boundary 146 147 float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis 148 float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis 149 float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis 150 float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis 151 float4(1.0f, 0.7f, 0.3f, 1.0f), // gregory basis 152 float4(1.0f, 0.7f, 0.3f, 1.0f) // gregory basis 153}; 154 155float4 156getAdaptivePatchColor(int3 patchParam 157#if OSD_PATCH_ENABLE_SINGLE_CREASE 158 , float2 vSegments 159#else 160#endif 161 ) 162{ 163 164 165 int patchType = 0; 166 167 int edgeCount = popcount(OsdGetPatchBoundaryMask(patchParam)); 168 if (edgeCount == 1) { 169 patchType = 2; // BOUNDARY 170 } 171 if (edgeCount > 1) { 172 patchType = 3; // CORNER 173 } 174 175#if OSD_PATCH_ENABLE_SINGLE_CREASE 176 // check this after boundary/corner since single crease patch also has edgeCount. 177 if (vSegments.y > 0) { 178 patchType = 1; 179 } 180#elif OSD_PATCH_GREGORY 181 patchType = 4; 182#elif OSD_PATCH_GREGORY_BOUNDARY 183 patchType = 5; 184#elif OSD_PATCH_GREGORY_BASIS 185 patchType = 6; 186#elif OSD_PATCH_GREGORY_TRIANGLE 187 patchType = 6; 188#endif 189 190 int pattern = popcount(OsdGetPatchTransitionMask(patchParam)); 191 192 return patchColors[6*patchType + pattern]; 193} 194 195float4 196getAdaptiveDepthColor(int3 patchParam) 197{ 198 // Represent depth with repeating cycle of four colors: 199 const float4 depthColors[4] = { 200 float4(0.0f, 0.5f, 0.5f, 1.0f), 201 float4(1.0f, 1.0f, 1.0f, 1.0f), 202 float4(0.0f, 1.0f, 1.0f, 1.0f), 203 float4(0.5f, 1.0f, 0.5f, 1.0f) 204 }; 205 return depthColors[OsdGetPatchRefinementLevel(patchParam) & 3]; 206} 207 208#if OSD_IS_ADAPTIVE 209#if USE_STAGE_IN 210#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE 211struct ControlPoint 212{ 213 float3 P [[attribute(0)]]; 214#if OSD_PATCH_ENABLE_SINGLE_CREASE 215 float3 P1 [[attribute(1)]]; 216 float3 P2 [[attribute(2)]]; 217#if !USE_PTVS_SHARPNESS 218 float2 vSegments [[attribute(3)]]; 219#endif 220#endif 221}; 222#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 223struct ControlPoint 224{ 225 float3 P [[attribute(0)]]; 226 float3 Ep [[attribute(1)]]; 227 float3 Em [[attribute(2)]]; 228 float3 Fp [[attribute(3)]]; 229 float3 Fm [[attribute(4)]]; 230}; 231#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE 232struct ControlPoint 233{ 234 float3 position [[attribute(0)]]; 235}; 236#endif 237 238struct PatchInput 239{ 240 patch_control_point<ControlPoint> cv; 241#if !USE_PTVS_FACTORS 242 float4 tessOuterLo [[attribute(5)]]; 243 float4 tessOuterHi [[attribute(6)]]; 244#endif 245 int3 patchParam [[attribute(10)]]; 246}; 247#endif 248 249#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 250typedef MTLQuadTessellationFactorsHalf PatchTessFactors; 251#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE 252typedef MTLTriangleTessellationFactorsHalf PatchTessFactors; 253#endif 254 255 256//---------------------------------------------------------- 257// OSD Kernel 258//---------------------------------------------------------- 259//The user of OSD should define this kernel which serves as the landing point for all patch computation 260//This compute function should just be copied and pasted, modifying the section under "User Vertex Transform" 261//Or the entire function may be moddified as needed (for example to add a patch index buffer) 262kernel void compute_main( 263 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 264 unsigned thread_position_in_grid [[thread_position_in_grid]], 265 unsigned thread_position_in_threadgroup [[thread_position_in_threadgroup]], 266 unsigned threadgroup_position_in_grid [[threadgroup_position_in_grid]], 267 OsdPatchParamBufferSet osdBuffers, //This struct contains all of the buffers needed by OSD 268 device PatchTessFactors* patchTessellationFactors [[buffer(PATCH_TESSFACTORS_INDEX)]] 269#if OSD_USE_PATCH_INDEX_BUFFER 270 ,device unsigned* patchIndex [[buffer(OSD_PATCH_INDEX_BUFFER_INDEX)]] 271 ,device MTLDrawPatchIndirectArguments* drawIndirectCommands [[buffer(OSD_DRAWINDIRECT_BUFFER_INDEX)]] 272#endif 273) 274{ 275 276 //---------------------------------------------------------- 277 // OSD Kernel Setup 278 //---------------------------------------------------------- 279 280 #define PATCHES_PER_THREADGROUP (THREADS_PER_THREADGROUP / THREADS_PER_PATCH) 281 int const primitiveID = thread_position_in_grid / THREADS_PER_PATCH; 282 int const primitiveIDInTG = thread_position_in_threadgroup / THREADS_PER_PATCH; 283 int const vertexIndex = threadgroup_position_in_grid * PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH + 284 thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD; 285 int const vertexIndexInTG = thread_position_in_threadgroup * CONTROL_POINTS_PER_THREAD; 286 int const invocationID = (thread_position_in_threadgroup * VERTEX_CONTROL_POINTS_PER_THREAD) % (THREADS_PER_PATCH*VERTEX_CONTROL_POINTS_PER_THREAD); 287 288 //Contains the shared patchParam value used by all threads that act upon a single patch 289 //the .z (sharpness) field is set to -1 (NAN) if that patch should be culled to signal other threads to return. 290 threadgroup int3 patchParam[PATCHES_PER_THREADGROUP]; 291 threadgroup PatchVertexType patchVertices[PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH]; 292 293 //---------------------------------------------------------- 294 // OSD Vertex Transform 295 //---------------------------------------------------------- 296 { 297 patchParam[primitiveIDInTG] = OsdGetPatchParam(primitiveID, osdBuffers.patchParamBuffer); 298 299 for (unsigned threadOffset = 0; threadOffset < CONTROL_POINTS_PER_THREAD; ++threadOffset) 300 { 301 if (vertexIndexInTG + threadOffset < PATCHES_PER_THREADGROUP * CONTROL_POINTS_PER_PATCH) 302 { 303 const auto vertexId = osdBuffers.indexBuffer[(vertexIndex + threadOffset)]; 304 const auto v = osdBuffers.vertexBuffer[vertexId]; 305 306 threadgroup auto& patchVertex = patchVertices[vertexIndexInTG + threadOffset]; 307 308 //---------------------------------------------------------- 309 // User Vertex Transform 310 //---------------------------------------------------------- 311 312 OsdComputePerVertex(float4(v.position,1), patchVertex, vertexId, frameConsts.ModelViewProjectionMatrix, osdBuffers); 313 } 314 } 315 } 316 317#if NEEDS_BARRIER 318 threadgroup_barrier(mem_flags::mem_threadgroup); 319#endif 320 321 //---------------------------------------------------------- 322 // OSD Patch Cull 323 //---------------------------------------------------------- 324 { 325 auto patch = patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH; 326 327 if (!OsdCullPerPatchVertex(patch, frameConsts.ModelViewMatrix)) 328 { 329#if !OSD_USE_PATCH_INDEX_BUFFER 330#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 331 patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h; 332 patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h; 333 patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h; 334 patchTessellationFactors[primitiveID].edgeTessellationFactor[3] = 0.0h; 335 patchTessellationFactors[primitiveID].insideTessellationFactor[0] = 0.0h; 336 patchTessellationFactors[primitiveID].insideTessellationFactor[1] = 0.0h; 337#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE 338 patchTessellationFactors[primitiveID].edgeTessellationFactor[0] = 0.0h; 339 patchTessellationFactors[primitiveID].edgeTessellationFactor[1] = 0.0h; 340 patchTessellationFactors[primitiveID].edgeTessellationFactor[2] = 0.0h; 341 patchTessellationFactors[primitiveID].insideTessellationFactor = 0.0h; 342#endif 343#endif 344 345 patchParam[primitiveIDInTG].z = -1; 346#if !NEEDS_BARRIER 347 return; 348#endif 349 } 350 } 351 352#if NEEDS_BARRIER 353 threadgroup_barrier(mem_flags::mem_threadgroup); 354#endif 355 356 //---------------------------------------------------------- 357 // OSD Patch Compute 358 //---------------------------------------------------------- 359 if (patchParam[primitiveIDInTG].z != -1) 360 { 361 for (unsigned threadOffset = 0; threadOffset < VERTEX_CONTROL_POINTS_PER_THREAD; ++threadOffset) 362 { 363 if (invocationID + threadOffset < VERTEX_CONTROL_POINTS_PER_PATCH) 364 { 365 OsdComputePerPatchVertex( 366 patchParam[primitiveIDInTG], 367 invocationID + threadOffset, 368 primitiveID, 369 invocationID + threadOffset + primitiveID * VERTEX_CONTROL_POINTS_PER_PATCH, 370 patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH, 371 osdBuffers 372 ); 373 } 374 } 375 } 376 377#if NEEDS_BARRIER 378 threadgroup_barrier(mem_flags::mem_device_and_threadgroup); 379#endif 380 381 //---------------------------------------------------------- 382 // OSD Tessellation Factors 383 //---------------------------------------------------------- 384 if (invocationID == 0) 385 { 386 387#if OSD_USE_PATCH_INDEX_BUFFER 388 const auto patchId = atomic_fetch_add_explicit((device atomic_uint*)&drawIndirectCommands->patchCount, 1, memory_order_relaxed); 389 patchIndex[patchId] = primitiveID; 390#else 391 const auto patchId = primitiveID; 392#endif 393 394 OsdComputePerPatchFactors( 395 patchParam[primitiveIDInTG], 396 frameConsts.TessLevel, 397 primitiveID, 398 frameConsts.ProjectionMatrix, 399 frameConsts.ModelViewMatrix, 400 osdBuffers, 401 patchVertices + primitiveIDInTG * CONTROL_POINTS_PER_PATCH, 402 patchTessellationFactors[patchId] 403 ); 404 } 405} 406 407#if SHADING_TYPE == SHADING_TYPE_FACE_VARYING_COLOR 408float3 409interpolateFaceVaryingColor( 410 int patch_id, 411 float2 uv, 412 const device float* fvarData, 413 const device int* fvarIndices, 414 const device packed_int3* fvarPatchParams, 415 const constant int* fvarPatchArrays) 416{ 417 OsdPatchArray fvarPatchArray = OsdPatchArrayInit( 418 fvarPatchArrays[0], 419 fvarPatchArrays[1], 420 fvarPatchArrays[2], 421 fvarPatchArrays[3], 422 fvarPatchArrays[4], 423 fvarPatchArrays[5]); 424 OsdPatchParam fvarParam = OsdPatchParamInit( 425 fvarPatchParams[patch_id][0], 426 fvarPatchParams[patch_id][1], 427 fvarPatchParams[patch_id][2]); 428 429 int fvarPatchType = OsdPatchParamIsRegular(fvarParam) 430 ? fvarPatchArray.regDesc 431 : fvarPatchArray.desc; 432 433 float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20]; 434 int numPoints = OsdEvaluatePatchBasisNormalized(fvarPatchType, fvarParam, 435 uv.x, uv.y, wP, wDu, wDv, wDuu, wDuv, wDvv); 436 437 int primOffset = patch_id * fvarPatchArray.stride; 438 439 float2 interpUV = float2(0); 440 for (int i = 0; i < numPoints; ++i) { 441 int index = fvarIndices[primOffset + i] * 2 /* OSD_FVAR_WIDTH */ + 0 /* fvarOffset */; 442 float2 cv = float2(fvarData[index + 0], fvarData[index + 1]); 443 interpUV += wP[i] * cv; 444 } 445 446 return float3(interpUV, 0); 447} 448#endif 449 450#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 451[[patch(quad, VERTEX_CONTROL_POINTS_PER_PATCH)]] 452#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE 453[[patch(triangle, VERTEX_CONTROL_POINTS_PER_PATCH)]] 454#endif 455vertex OutputVertex vertex_main( 456 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 457#if USE_STAGE_IN 458 const PatchInput patchInput [[stage_in]], 459#else 460 const OsdVertexBufferSet patchInput, 461#endif 462 const device float* osdFaceVaryingData [[buffer(OSD_FVAR_DATA_BUFFER_INDEX)]], 463 const device int* osdFaceVaryingIndices [[buffer(OSD_FVAR_INDICES_BUFFER_INDEX)]], 464 const device packed_int3* osdFaceVaryingPatchParams [[buffer(OSD_FVAR_PATCHPARAM_BUFFER_INDEX)]], 465 const constant int* osdFaceVaryingPatchArrays [[buffer(OSD_FVAR_PATCH_ARRAYS_BUFFER_INDEX)]], 466#if OSD_PATCH_REGULAR || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 467 float2 position_in_patch [[position_in_patch]], 468#elif OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_TRIANGLE 469 float3 position_in_patch [[position_in_patch]], 470#endif 471 uint patch_id [[patch_id]] 472 ) 473{ 474 OutputVertex out; 475 476#if USE_STAGE_IN 477 int3 patchParam = patchInput.patchParam; 478#else 479 int3 patchParam = patchInput.patchParamBuffer[patch_id]; 480#endif 481 482 int refinementLevel = OsdGetPatchRefinementLevel(patchParam); 483 float tessLevel = min(frameConsts.TessLevel, (float)OSD_MAX_TESS_LEVEL) / 484 exp2((float)refinementLevel - 1); 485 486 auto patchVertex = OsdComputePatch(tessLevel, position_in_patch, patch_id, patchInput); 487 488 out.position = (frameConsts.ModelViewMatrix * float4(patchVertex.position, 1.0f)).xyz; 489 out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(patchVertex.position, 1.0f); 490 491 out.normal = mul(frameConsts.ModelViewMatrix, patchVertex.normal); 492#if SHADING_TYPE == SHADING_TYPE_PATCH_TYPE 493#if OSD_PATCH_ENABLE_SINGLE_CREASE 494 out.patchColor = getAdaptivePatchColor(patchParam, patchVertex.vSegments).xyz; 495#else 496 out.patchColor = getAdaptivePatchColor(patchParam).xyz; 497#endif 498#elif SHADING_TYPE == SHADING_TYPE_PATCH_DEPTH 499 out.patchColor = getAdaptiveDepthColor(patchParam).xyz; 500#elif SHADING_TYPE == SHADING_TYPE_NORMAL 501#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD 502 out.patchColor = patchVertex.patchCoord.xyz; 503#elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING_COLOR 504 out.patchColor = interpolateFaceVaryingColor( 505 patch_id, 506 patchVertex.tessCoord.xy, 507 osdFaceVaryingData, 508 osdFaceVaryingIndices, 509 osdFaceVaryingPatchParams, 510 osdFaceVaryingPatchArrays); 511#endif 512 513 return out; 514} 515#endif 516 517#if OSD_PATCH_REGULAR 518const constant unsigned BSplineControlLineIndices[] = { 519 0, 1, //Outer lines 520 1, 2, 521 2, 3, 522 3, 7, 523 7, 11, 524 11, 15, 525 15, 14, 526 14, 13, 527 13, 12, 528 12, 8, 529 8, 4, 530 4, 0, 531 532 //Inner lines 533 5, 6, 534 6, 10, 535 10, 9, 536 9, 5, 537 538 //TL edge lines 539 1, 5, 540 4, 5, 541 542 //TR edge lines 543 2, 6, 544 6, 7, 545 546 //BL edge lines 547 8, 9, 548 9, 13, 549 550 //BR edge lines 551 10, 14, 552 10, 11 553}; 554 555vertex SolidColorVertex vertex_lines( 556 const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]], 557 const device OsdPerPatchVertexBezier* osdPerPatchVertexBezier [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]], 558 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 559 uint vertex_id [[vertex_id]] 560 ) 561{ 562 const auto idx_size = sizeof(BSplineControlLineIndices) / sizeof(BSplineControlLineIndices[0]); 563 const auto idx = vertex_id % idx_size; 564 const auto patch_id = vertex_id / idx_size; 565 566 const auto in = osdPerPatchVertexBezier[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + BSplineControlLineIndices[idx]]; 567 568 SolidColorVertex out; 569 570 out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.P, 1.0); 571 out.positionOut.z -= 0.001; 572 573 if(idx > 22) { 574 out.setColor(half4(0,1,0,1)); 575 } 576 else 577 { 578 out.setColor(half4(1,0,0,1)); 579 } 580 581 return out; 582} 583#endif 584 585#if OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY 586const constant uint GregoryBasisControlLineIndices[] = { 587 //Outer Edge 588 0, 2, 589 2, 16, 590 16, 15, 591 15, 17, 592 17, 11, 593 11, 10, 594 10, 12, 595 12, 6, 596 6, 5, 597 5, 7, 598 7, 1, 599 1, 0, 600 601 //Outside-Inside Edges 602 1, 3, 603 2, 4, 604 16, 18, 605 17, 19, 606 11, 13, 607 12, 14, 608 6, 8, 609 7, 9, 610 611 //Inner Edge 612 3, 4, 613 4, 18, 614 18, 19, 615 19, 13, 616 13, 14, 617 14, 8, 618 8, 9, 619 9, 3, 620}; 621 622 623vertex SolidColorVertex vertex_lines( 624#ifdef OSD_PATCH_GREGORY_BASIS 625 const device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]], 626 const device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]], 627#else 628 const device PackedInputVertex* vertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]], 629#endif 630 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 631 uint vertex_id [[vertex_id]] 632 ) 633{ 634 const auto idx_size = sizeof(GregoryBasisControlLineIndices) / sizeof(GregoryBasisControlLineIndices[0]); 635 const auto idx = vertex_id % idx_size; 636 const auto patch_id = vertex_id / idx_size; 637 638#ifdef OSD_PATCH_GREGORY_BASIS 639 const auto in = vertexBuffer[indicesBuffer[patch_id * VERTEX_CONTROL_POINTS_PER_PATCH + GregoryBasisControlLineIndices[idx]]]; 640#else 641 const auto in = vertexBuffer[patch_id * 20 + GregoryBasisControlLineIndices[idx]]; 642#endif 643 SolidColorVertex out; 644 645 out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(in.position, 1.0); 646 out.positionOut.z -= 0.001; 647 648 if(idx > 22) { 649 out.setColor(half4(0,1,0,1)); 650 } 651 else 652 { 653 out.setColor(half4(1,0,0,1)); 654 } 655 656 return out; 657} 658#endif 659 660#if OSD_PATCH_QUADS || OSD_PATCH_TRIANGLES 661 662#if OSD_PATCH_QUADS 663const constant uint triangleIdx[6] = { 664 0, 2, 1, 3, 2, 0 665}; 666#endif 667 668vertex OutputVertex vertex_main( 669 device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]], 670 device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]], 671 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 672 const device float2* osdFaceVaryingData[[buffer(OSD_FVAR_DATA_BUFFER_INDEX)]], 673 const device int* osdFaceVaryingIndices[[buffer(OSD_FVAR_INDICES_BUFFER_INDEX)]], 674 uint vertex_id [[vertex_id]] 675 ) 676{ 677#if OSD_PATCH_QUADS 678 const auto quadId = vertex_id / 6; 679#else 680 const auto primID = vertex_id / 3; 681#endif 682 683#if OSD_PATCH_QUADS 684 float3 p0 = vertexBuffer[indicesBuffer[quadId * 4 + 0]].position; 685 float3 p1 = vertexBuffer[indicesBuffer[quadId * 4 + 1]].position; 686 float3 p2 = vertexBuffer[indicesBuffer[quadId * 4 + 2]].position; 687 float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position; 688 float2 uv = osdFaceVaryingData[osdFaceVaryingIndices[quadId * 4 + triangleIdx[vertex_id % 6]]].xy; 689#else 690 float3 p0 = vertexBuffer[indicesBuffer[primID * 3 + 0]].position; 691 float3 p1 = vertexBuffer[indicesBuffer[primID * 3 + 1]].position; 692 float3 p2 = vertexBuffer[indicesBuffer[primID * 3 + 2]].position; 693 float3 position = vertexBuffer[indicesBuffer[vertex_id]].position; 694 float2 uv = osdFaceVaryingData[osdFaceVaryingIndices[vertex_id]].xy; 695#endif 696 697 float3 normal = normalize(cross(p2 - p1, p0 - p1)); 698 699 700 OutputVertex out; 701 out.position = (frameConsts.ModelViewMatrix * float4(position, 1.0)).xyz; 702 out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0); 703 out.normal = (frameConsts.ModelViewMatrix * float4(normal, 0.0)).xyz; 704 705#if SHADING_TYPE == SHADING_TYPE_PATCH_TYPE || SHADING_TYPE == SHADING_TYPE_PATCH_DEPTH || SHADING_TYPE == SHADING_TYPE_PATCH_COORD 706 out.patchColor = out.normal; 707#elif SHADING_TYPE == SHADING_TYPE_FACE_VARYING_COLOR 708 out.patchColor.rg = uv; 709#endif 710 711 return out; 712} 713 714vertex SolidColorVertex vertex_lines( 715 device unsigned* indicesBuffer [[buffer(INDICES_BUFFER_INDEX)]], 716 device PackedInputVertex* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]], 717 const constant PerFrameConstants& frameConsts [[buffer(FRAME_CONST_BUFFER_INDEX)]], 718 uint vertex_id [[vertex_id]] 719 ) 720{ 721#if OSD_PATCH_QUADS 722 const auto quadId = vertex_id / 6; 723#else 724 const auto primID = vertex_id / 3; 725#endif 726 727#if OSD_PATCH_QUADS 728 float3 position = vertexBuffer[indicesBuffer[quadId * 4 + triangleIdx[vertex_id % 6]]].position; 729#else 730 float3 position = vertexBuffer[indicesBuffer[vertex_id]].position; 731#endif 732 733 SolidColorVertex out; 734 out.positionOut = frameConsts.ModelViewProjectionMatrix * float4(position, 1.0); 735 736 return out; 737} 738#endif 739 740fragment half4 fragment_solidcolor(SolidColorVertex in [[stage_in]]) 741{ 742 return in.getColor(); 743} 744 745 746fragment float4 fragment_main(OutputVertex in [[stage_in]], 747 const constant Light* lightData [[buffer(0)]], 748 const constant PerFrameConstants& frameConsts [[buffer(1)]], 749 const constant float4& shade [[buffer(2)]]) 750{ 751 float4 color; 752 753#if SHADING_TYPE == SHADING_TYPE_MATERIAL 754 const float3 diffuseColor = float3(0.4f, 0.4f, 0.8f); 755#elif SHADING_TYPE == SHADING_TYPE_PATCH_TYPE || SHADING_TYPE == SHADING_TYPE_PATCH_DEPTH 756 const float3 diffuseColor = in.patchColor; 757#endif 758#if SHADING_TYPE == SHADING_TYPE_NORMAL 759 color.xyz = normalize(in.normal) * 0.5 + 0.5; 760#elif SHADING_TYPE == SHADING_TYPE_PATCH_COORD || SHADING_TYPE == SHADING_TYPE_FACE_VARYING_COLOR 761 color.xyz = lighting(1.0, lightData, in.position, normalize(in.normal)); 762 int checker = int(floor(20*in.patchColor.r)+floor(20*in.patchColor.g))&1; 763 color.xyz *= float3(in.patchColor.rg*checker, 1-checker); 764 color.xyz = pow(color.xyz, 1/2.2); 765#else 766 color.xyz = lighting(diffuseColor, lightData, in.position, normalize(in.normal)); 767#endif 768 color.w = 1; 769 return max(color,shade); 770} 771