mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-11-09 13:50:05 +00:00
Merge pull request #1320 from davidgyu/dev_osd_patch_drawing_compatibilty
Improved osd patch drawing compatibility
This commit is contained in:
commit
3597371f84
@ -22,101 +22,11 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//
|
||||
// typical shader composition ordering (see glDrawRegistry:_CompileShader)
|
||||
//
|
||||
//
|
||||
// - glsl version string (#version 430)
|
||||
//
|
||||
// - common defines (#define OSD_ENABLE_PATCH_CULL, ...)
|
||||
// - source defines (#define VERTEX_SHADER, ...)
|
||||
//
|
||||
// - osd headers (glslPatchCommon: varying structs,
|
||||
// glslPtexCommon: ptex functions)
|
||||
// - client header (Osd*Matrix(), displacement callback, ...)
|
||||
//
|
||||
// - osd shader source (glslPatchBSpline, glslPatchGregory, ...)
|
||||
// or
|
||||
// client shader source (vertex/geometry/fragment shader)
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
// XXXdyu all handling of varying data can be managed by client code
|
||||
#ifndef OSD_USER_VARYING_DECLARE
|
||||
#define OSD_USER_VARYING_DECLARE
|
||||
// type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
#define OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
// layout(location = loc) in type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_VERTEX
|
||||
#define OSD_USER_VARYING_PER_VERTEX()
|
||||
// output.var = var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_CONTROL_POINT
|
||||
#define OSD_USER_VARYING_PER_CONTROL_POINT(ID_OUT, ID_IN)
|
||||
// output[ID_OUT].var = input[ID_IN].var
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT(UV, a, b, c, d)
|
||||
// output.var =
|
||||
// mix(mix(input[a].var, input[b].var, UV.x),
|
||||
// mix(input[c].var, input[d].var, UV.x), UV.y)
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c)
|
||||
// output.var =
|
||||
// input[a].var * (1.0f-UV.x-UV.y) +
|
||||
// input[b].var * UV.x +
|
||||
// input[c].var * UV.y;
|
||||
#endif
|
||||
|
||||
#if __VERSION__ < 420
|
||||
#define centroid
|
||||
#endif
|
||||
|
||||
struct ControlVertex {
|
||||
vec4 position;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
ivec3 clipFlag;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec3 tangent;
|
||||
vec3 bitangent;
|
||||
vec4 patchCoord; // u, v, faceLevel, faceId
|
||||
vec2 tessCoord; // tesscoord.st
|
||||
#if defined OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
vec3 Nu;
|
||||
vec3 Nv;
|
||||
#endif
|
||||
};
|
||||
|
||||
// osd shaders need following functions defined
|
||||
// The following callback functions are used when evaluating tessellation
|
||||
// rates and when using legacy patch drawing.
|
||||
mat4 OsdModelViewMatrix();
|
||||
mat4 OsdProjectionMatrix();
|
||||
mat4 OsdModelViewProjectionMatrix();
|
||||
float OsdTessLevel();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Patch Parameters
|
||||
@ -130,22 +40,6 @@ int OsdBaseVertex();
|
||||
// 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.
|
||||
//
|
||||
|
||||
uniform isamplerBuffer OsdPatchParamBuffer;
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
ivec3 OsdGetPatchParam(int patchIndex)
|
||||
{
|
||||
return texelFetch(OsdPatchParamBuffer, patchIndex).xyz;
|
||||
}
|
||||
|
||||
int OsdGetPatchFaceId(ivec3 patchParam)
|
||||
{
|
||||
@ -239,38 +133,6 @@ vec4 OsdInterpolatePatchCoordTriangle(vec2 localUV, ivec3 patchParam)
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
vec4 clipPos = OsdModelViewProjectionMatrix() * P; \
|
||||
bvec3 clip0 = lessThan(clipPos.xyz, vec3(clipPos.w)); \
|
||||
bvec3 clip1 = greaterThan(clipPos.xyz, -vec3(clipPos.w)); \
|
||||
outpt.v.clipFlag = ivec3(clip0) + 2*ivec3(clip1); \
|
||||
|
||||
#define OSD_PATCH_CULL(N) \
|
||||
ivec3 clipFlag = ivec3(0); \
|
||||
for(int i = 0; i < N; ++i) { \
|
||||
clipFlag |= inpt[i].v.clipFlag; \
|
||||
} \
|
||||
if (clipFlag != ivec3(3) ) { \
|
||||
gl_TessLevelInner[0] = 0; \
|
||||
gl_TessLevelInner[1] = 0; \
|
||||
gl_TessLevelOuter[0] = 0; \
|
||||
gl_TessLevelOuter[1] = 0; \
|
||||
gl_TessLevelOuter[2] = 0; \
|
||||
gl_TessLevelOuter[3] = 0; \
|
||||
return; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
@ -582,7 +444,7 @@ OsdFlipMatrix(mat4 m)
|
||||
}
|
||||
|
||||
// Regular BSpline to Bezier
|
||||
uniform mat4 Q = mat4(
|
||||
const mat4 Q = mat4(
|
||||
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,
|
||||
@ -590,7 +452,7 @@ uniform mat4 Q = mat4(
|
||||
);
|
||||
|
||||
// Infinitely Sharp (boundary)
|
||||
uniform mat4 Mi = mat4(
|
||||
const mat4 Mi = mat4(
|
||||
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,
|
||||
|
@ -22,6 +22,128 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
// XXXdyu all handling of varying data can be managed by client code
|
||||
#ifndef OSD_USER_VARYING_DECLARE
|
||||
#define OSD_USER_VARYING_DECLARE
|
||||
// type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
#define OSD_USER_VARYING_ATTRIBUTE_DECLARE
|
||||
// layout(location = loc) in type var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_VERTEX
|
||||
#define OSD_USER_VARYING_PER_VERTEX()
|
||||
// output.var = var;
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_CONTROL_POINT
|
||||
#define OSD_USER_VARYING_PER_CONTROL_POINT(ID_OUT, ID_IN)
|
||||
// output[ID_OUT].var = input[ID_IN].var
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT(UV, a, b, c, d)
|
||||
// output.var =
|
||||
// mix(mix(input[a].var, input[b].var, UV.x),
|
||||
// mix(input[c].var, input[d].var, UV.x), UV.y)
|
||||
#endif
|
||||
|
||||
#ifndef OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE
|
||||
#define OSD_USER_VARYING_PER_EVAL_POINT_TRIANGLE(UV, a, b, c)
|
||||
// output.var =
|
||||
// input[a].var * (1.0f-UV.x-UV.y) +
|
||||
// input[b].var * UV.x +
|
||||
// input[c].var * UV.y;
|
||||
#endif
|
||||
|
||||
#if __VERSION__ < 420
|
||||
#define centroid
|
||||
#endif
|
||||
|
||||
struct ControlVertex {
|
||||
vec4 position;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
ivec3 clipFlag;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
vec4 position;
|
||||
vec3 normal;
|
||||
vec3 tangent;
|
||||
vec3 bitangent;
|
||||
vec4 patchCoord; // u, v, faceLevel, faceId
|
||||
vec2 tessCoord; // tesscoord.st
|
||||
#if defined OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
vec3 Nu;
|
||||
vec3 Nv;
|
||||
#endif
|
||||
};
|
||||
|
||||
mat4 OsdModelViewProjectionMatrix();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// 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.
|
||||
|
||||
uniform isamplerBuffer OsdPatchParamBuffer;
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
ivec3 OsdGetPatchParam(int patchIndex)
|
||||
{
|
||||
return texelFetch(OsdPatchParamBuffer, patchIndex).xyz;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
vec4 clipPos = OsdModelViewProjectionMatrix() * P; \
|
||||
bvec3 clip0 = lessThan(clipPos.xyz, vec3(clipPos.w)); \
|
||||
bvec3 clip1 = greaterThan(clipPos.xyz, -vec3(clipPos.w)); \
|
||||
outpt.v.clipFlag = ivec3(clip0) + 2*ivec3(clip1); \
|
||||
|
||||
#define OSD_PATCH_CULL(N) \
|
||||
ivec3 clipFlag = ivec3(0); \
|
||||
for(int i = 0; i < N; ++i) { \
|
||||
clipFlag |= inpt[i].v.clipFlag; \
|
||||
} \
|
||||
if (clipFlag != ivec3(3) ) { \
|
||||
gl_TessLevelInner[0] = 0; \
|
||||
gl_TessLevelInner[1] = 0; \
|
||||
gl_TessLevelOuter[0] = 0; \
|
||||
gl_TessLevelOuter[1] = 0; \
|
||||
gl_TessLevelOuter[2] = 0; \
|
||||
gl_TessLevelOuter[3] = 0; \
|
||||
return; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -67,10 +67,18 @@ static const char *gregoryTriangleShaderSource =
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
GLSLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << std::string(commonShaderSource);
|
||||
ss << std::string(commonTessShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
GLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchDrawingShaderSource();
|
||||
ss << std::string(patchLegacyShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
@ -26,20 +26,39 @@
|
||||
#define OPENSUBDIV3_OSD_GLSL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <string>
|
||||
|
||||
#include "../far/patchDescriptor.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class GLSLPatchShaderSource {
|
||||
public:
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(
|
||||
Far::PatchDescriptor::Type type);
|
||||
|
||||
@ -48,6 +67,8 @@ public:
|
||||
|
||||
static std::string GetTessEvalShaderSource(
|
||||
Far::PatchDescriptor::Type type);
|
||||
|
||||
/// \}
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
@ -22,52 +22,11 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct InputVertex {
|
||||
float4 position : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
struct HullVertex {
|
||||
float4 position : POSITION;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
int3 clipFlag : CLIPFLAG;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
float4 positionOut : SV_Position;
|
||||
float4 position : POSITION1;
|
||||
float3 normal : NORMAL;
|
||||
float3 tangent : TANGENT;
|
||||
float3 bitangent : TANGENT1;
|
||||
float4 patchCoord : PATCHCOORD; // u, v, faceLevel, faceId
|
||||
noperspective float4 edgeDistance : EDGEDISTANCE;
|
||||
#if defined(OSD_COMPUTE_NORMAL_DERIVATIVES)
|
||||
float3 Nu : TANGENT2;
|
||||
float3 Nv : TANGENT3;
|
||||
#endif
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments : VSEGMENTS;
|
||||
#endif
|
||||
};
|
||||
|
||||
// osd shaders need following functions defined
|
||||
// The following callback functions are used when evaluating tessellation
|
||||
// rates and when using legacy patch drawing.
|
||||
float4x4 OsdModelViewMatrix();
|
||||
float4x4 OsdProjectionMatrix();
|
||||
float4x4 OsdModelViewProjectionMatrix();
|
||||
float OsdTessLevel();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Patch Parameters
|
||||
@ -81,31 +40,6 @@ int OsdBaseVertex();
|
||||
// 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
|
||||
Buffer<uint3> OsdPatchParamBuffer : register( t0 );
|
||||
#else
|
||||
Buffer<uint2> OsdPatchParamBuffer : register( t0 );
|
||||
#endif
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
int OsdGetPatchFaceId(int3 patchParam)
|
||||
{
|
||||
@ -199,60 +133,6 @@ float4 OsdInterpolatePatchCoordTriangle(float2 localUV, int3 patchParam)
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
float4 clipPos = mul(OsdModelViewProjectionMatrix(), P); \
|
||||
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; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#define OSD_PATCH_CULL_TRIANGLE(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.tessLevelOuter[0] = 0; \
|
||||
output.tessLevelOuter[1] = 0; \
|
||||
output.tessLevelOuter[2] = 0; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#define OSD_PATCH_CULL_TRIANGLE(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
@ -564,7 +444,7 @@ OsdFlipMatrix(float4x4 m)
|
||||
}
|
||||
|
||||
// Regular BSpline to Bezier
|
||||
static float4x4 Q = {
|
||||
static const 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,
|
||||
@ -572,7 +452,7 @@ static float4x4 Q = {
|
||||
};
|
||||
|
||||
// Infinitely Sharp (boundary)
|
||||
static float4x4 Mi = {
|
||||
static const 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,
|
||||
|
@ -22,6 +22,128 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct InputVertex {
|
||||
float4 position : POSITION;
|
||||
float3 normal : NORMAL;
|
||||
};
|
||||
|
||||
struct HullVertex {
|
||||
float4 position : POSITION;
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
int3 clipFlag : CLIPFLAG;
|
||||
#endif
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OutputVertex {
|
||||
float4 positionOut : SV_Position;
|
||||
float4 position : POSITION1;
|
||||
float3 normal : NORMAL;
|
||||
float3 tangent : TANGENT;
|
||||
float3 bitangent : TANGENT1;
|
||||
float4 patchCoord : PATCHCOORD; // u, v, faceLevel, faceId
|
||||
noperspective float4 edgeDistance : EDGEDISTANCE;
|
||||
#if defined(OSD_COMPUTE_NORMAL_DERIVATIVES)
|
||||
float3 Nu : TANGENT2;
|
||||
float3 Nv : TANGENT3;
|
||||
#endif
|
||||
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments : VSEGMENTS;
|
||||
#endif
|
||||
};
|
||||
|
||||
float4x4 OsdModelViewProjectionMatrix();
|
||||
int OsdGregoryQuadOffsetBase();
|
||||
int OsdPrimitiveIdBase();
|
||||
int OsdBaseVertex();
|
||||
|
||||
#ifndef OSD_DISPLACEMENT_CALLBACK
|
||||
#define OSD_DISPLACEMENT_CALLBACK
|
||||
#endif
|
||||
|
||||
// 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
|
||||
Buffer<uint3> OsdPatchParamBuffer : register( t0 );
|
||||
#else
|
||||
Buffer<uint2> OsdPatchParamBuffer : register( t0 );
|
||||
#endif
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return (primitiveId + OsdPrimitiveIdBase());
|
||||
}
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef OSD_ENABLE_PATCH_CULL
|
||||
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P) \
|
||||
float4 clipPos = mul(OsdModelViewProjectionMatrix(), P); \
|
||||
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; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#define OSD_PATCH_CULL_TRIANGLE(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.tessLevelOuter[0] = 0; \
|
||||
output.tessLevelOuter[1] = 0; \
|
||||
output.tessLevelOuter[2] = 0; \
|
||||
output.tessOuterLo = float4(0,0,0,0); \
|
||||
output.tessOuterHi = float4(0,0,0,0); \
|
||||
return output; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define OSD_PATCH_CULL_COMPUTE_CLIPFLAGS(P)
|
||||
#define OSD_PATCH_CULL(N)
|
||||
#define OSD_PATCH_CULL_TRIANGLE(N)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -69,10 +69,18 @@ static const char *gregoryTriangleShaderSource =
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
HLSLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << std::string(commonShaderSource);
|
||||
ss << std::string(commonTessShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
HLSLPatchShaderSource::GetCommonShaderSource() {
|
||||
std::stringstream ss;
|
||||
ss << GetPatchDrawingShaderSource();
|
||||
ss << std::string(patchLegacyShaderSource);
|
||||
return ss.str();
|
||||
}
|
||||
|
@ -26,25 +26,46 @@
|
||||
#define OPENSUBDIV3_OSD_HLSL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#include "../version.h"
|
||||
#include <string>
|
||||
|
||||
#include "../far/patchDescriptor.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class HLSLPatchShaderSource {
|
||||
public:
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetDomainShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
@ -24,173 +24,15 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
#include <metal_stdlib>
|
||||
|
||||
#define offsetof_(X, Y) &(((device X*)nullptr)->Y)
|
||||
|
||||
#define OSD_IS_ADAPTIVE (OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#ifndef OSD_MAX_TESS_LEVEL
|
||||
#define OSD_MAX_TESS_LEVEL 64
|
||||
#endif
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
using namespace metal;
|
||||
|
||||
using OsdPatchParamBufferType = packed_int3;
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
float3 P;
|
||||
short3 clipFlag;
|
||||
int valence;
|
||||
float3 e0;
|
||||
float3 e1;
|
||||
#if OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor;
|
||||
float3 org;
|
||||
#endif
|
||||
float3 r[OSD_MAX_VALENCE];
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
packed_float3 P;
|
||||
packed_float3 Ep;
|
||||
packed_float3 Em;
|
||||
packed_float3 Fp;
|
||||
packed_float3 Fm;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
// HLSL->Metal Compatibility
|
||||
//----------------------------------------------------------
|
||||
|
||||
float4 mul(float4x4 a, float4 b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
|
||||
float3 mul(float4x4 a, float3 b)
|
||||
{
|
||||
float3x3 m(a[0].xyz, a[1].xyz, a[2].xyz);
|
||||
return m * b;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
struct HullVertex {
|
||||
float4 position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag;
|
||||
#endif
|
||||
|
||||
float3 GetPosition() threadgroup
|
||||
{
|
||||
return position.xyz;
|
||||
}
|
||||
|
||||
void SetPosition(float3 v) threadgroup
|
||||
{
|
||||
position.xyz = v;
|
||||
}
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OsdPatchVertex {
|
||||
float3 position;
|
||||
float3 normal;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 patchCoord; //u, v, faceLevel, faceId
|
||||
float2 tessCoord; // tesscoord.st
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
float3 Nu;
|
||||
float3 Nv;
|
||||
#endif
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct OsdPerPatchTessFactors {
|
||||
float4 tessOuterLo;
|
||||
float4 tessOuterHi;
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexBezier {
|
||||
packed_float3 P;
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
packed_float3 P1;
|
||||
packed_float3 P2;
|
||||
#if !USE_PTVS_SHARPNESS
|
||||
float2 vSegments;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregoryBasis {
|
||||
packed_float3 P;
|
||||
};
|
||||
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexBezier;
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
using PatchVertexType = OsdPerVertexGregory;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregory;
|
||||
#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregoryBasis;
|
||||
#else
|
||||
using PatchVertexType = OsdInputVertexType;
|
||||
using PerPatchVertexType = OsdInputVertexType;
|
||||
#endif
|
||||
|
||||
//Shared buffers used by OSD that are common to all kernels
|
||||
struct OsdPatchParamBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
const device int* quadOffsetBuffer [[buffer(OSD_QUADOFFSET_BUFFER_INDEX)]];
|
||||
const device int* valenceBuffer [[buffer(OSD_VALENCE_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
const constant unsigned& kernelExecutionLimit [[buffer(OSD_KERNELLIMIT_BUFFER_INDEX)]];
|
||||
};
|
||||
|
||||
//Shared buffers used by OSD that are common to all PTVS implementations
|
||||
struct OsdVertexBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
};
|
||||
// The following callback functions are used when evaluating tessellation
|
||||
// rates and when using legacy patch drawing.
|
||||
float4x4 OsdModelViewMatrix();
|
||||
float4x4 OsdProjectionMatrix();
|
||||
float OsdTessLevel();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Patch Parameters
|
||||
@ -204,25 +46,6 @@ struct OsdVertexBufferSet
|
||||
// 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.
|
||||
//
|
||||
|
||||
int3 OsdGetPatchParam(int patchIndex, const device OsdPatchParamBufferType* osdPatchParamBuffer)
|
||||
{
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
return int3(osdPatchParamBuffer[patchIndex]);
|
||||
#else
|
||||
auto p = osdPatchParamBuffer[patchIndex];
|
||||
return int3(p[0], p[1], 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return primitiveId;
|
||||
}
|
||||
|
||||
int OsdGetPatchFaceId(int3 patchParam)
|
||||
{
|
||||
@ -316,40 +139,6 @@ float4 OsdInterpolatePatchCoordTriangle(float2 localUV, int3 patchParam)
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool OsdCullPerPatchVertex(
|
||||
threadgroup PatchVertexType* patch,
|
||||
float4x4 ModelViewMatrix
|
||||
)
|
||||
{
|
||||
#if OSD_ENABLE_BACKPATCH_CULL && OSD_PATCH_REGULAR
|
||||
auto v0 = float3(ModelViewMatrix * patch[5].position);
|
||||
auto v3 = float3(ModelViewMatrix * patch[6].position);
|
||||
auto v12 = float3(ModelViewMatrix * patch[9].position);
|
||||
|
||||
auto n = normalize(cross(v3 - v0, v12 - v0));
|
||||
v0 = normalize(v0 + v3 + v12);
|
||||
|
||||
if(dot(v0, n) > 0.6f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag = short3(0,0,0);
|
||||
for(int i = 0; i < CONTROL_POINTS_PER_PATCH; ++i) {
|
||||
clipFlag |= patch[i].clipFlag;
|
||||
}
|
||||
if (any(clipFlag != short3(3,3,3))) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
@ -421,6 +210,17 @@ OsdUnivar4x4(float u, thread float* B, thread float* D, thread float* C)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct OsdPerPatchVertexBezier {
|
||||
packed_float3 P;
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
packed_float3 P1;
|
||||
packed_float3 P2;
|
||||
#if !USE_PTVS_SHARPNESS
|
||||
float2 vSegments;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
float3
|
||||
OsdEvalBezier(float3 cp[16], float2 uv)
|
||||
{
|
||||
@ -1088,6 +888,10 @@ OsdEvalPatchBezier(int3 patchParam, float2 UV,
|
||||
// Gregory Basis
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct OsdPerPatchVertexGregoryBasis {
|
||||
packed_float3 P;
|
||||
};
|
||||
|
||||
void
|
||||
OsdComputePerPatchVertexGregoryBasis(int3 patchParam, int ID, float3 cv,
|
||||
device OsdPerPatchVertexGregoryBasis& result)
|
||||
@ -1444,3 +1248,4 @@ OsdEvalPatchGregoryTriangle(int3 patchParam, float2 UV, float3 cv[18],
|
||||
|
||||
OsdEvalPatchBezierTriangle(patchParam, UV, bezcv, P, dPu, dPv, N, dNu, dNv);
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,10 @@
|
||||
// (0,0) (1,0)
|
||||
//
|
||||
|
||||
#ifndef OSD_MAX_TESS_LEVEL
|
||||
#define OSD_MAX_TESS_LEVEL 64
|
||||
#endif
|
||||
|
||||
float OsdComputePostProjectionSphereExtent(
|
||||
const float4x4 OsdProjectionMatrix, float3 center, float diameter)
|
||||
{
|
||||
|
@ -24,6 +24,200 @@
|
||||
// language governing permissions and limitations under the Apache License.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------
|
||||
// Patches.Common
|
||||
//----------------------------------------------------------
|
||||
|
||||
#define offsetof_(X, Y) &(((device X*)nullptr)->Y)
|
||||
|
||||
#define OSD_IS_ADAPTIVE (OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE || OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE || OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY)
|
||||
|
||||
#ifndef OSD_NUM_ELEMENTS
|
||||
#define OSD_NUM_ELEMENTS 3
|
||||
#endif
|
||||
|
||||
struct OsdPerVertexGregory {
|
||||
float3 P;
|
||||
short3 clipFlag;
|
||||
int valence;
|
||||
float3 e0;
|
||||
float3 e1;
|
||||
#if OSD_PATCH_GREGORY_BOUNDARY
|
||||
int zerothNeighbor;
|
||||
float3 org;
|
||||
#endif
|
||||
float3 r[OSD_MAX_VALENCE];
|
||||
};
|
||||
|
||||
struct OsdPerPatchVertexGregory {
|
||||
packed_float3 P;
|
||||
packed_float3 Ep;
|
||||
packed_float3 Em;
|
||||
packed_float3 Fp;
|
||||
packed_float3 Fm;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------
|
||||
// HLSL->Metal Compatibility
|
||||
//----------------------------------------------------------
|
||||
|
||||
float4 mul(float4x4 a, float4 b)
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
|
||||
float3 mul(float4x4 a, float3 b)
|
||||
{
|
||||
float3x3 m(a[0].xyz, a[1].xyz, a[2].xyz);
|
||||
return m * b;
|
||||
|
||||
}
|
||||
|
||||
struct HullVertex {
|
||||
float4 position;
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag;
|
||||
#endif
|
||||
|
||||
float3 GetPosition() threadgroup
|
||||
{
|
||||
return position.xyz;
|
||||
}
|
||||
|
||||
void SetPosition(float3 v) threadgroup
|
||||
{
|
||||
position.xyz = v;
|
||||
}
|
||||
};
|
||||
|
||||
// XXXdyu all downstream data can be handled by client code
|
||||
struct OsdPatchVertex {
|
||||
float3 position;
|
||||
float3 normal;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 patchCoord; //u, v, faceLevel, faceId
|
||||
float2 tessCoord; // tesscoord.st
|
||||
#if OSD_COMPUTE_NORMAL_DERIVATIVES
|
||||
float3 Nu;
|
||||
float3 Nv;
|
||||
#endif
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
float2 vSegments;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct OsdPerPatchTessFactors {
|
||||
float4 tessOuterLo;
|
||||
float4 tessOuterHi;
|
||||
};
|
||||
|
||||
using OsdPatchParamBufferType = packed_int3;
|
||||
|
||||
#if OSD_PATCH_REGULAR || OSD_PATCH_BOX_SPLINE_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexBezier;
|
||||
#elif OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
using PatchVertexType = OsdPerVertexGregory;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregory;
|
||||
#elif OSD_PATCH_GREGORY_BASIS || OSD_PATCH_GREGORY_TRIANGLE
|
||||
using PatchVertexType = HullVertex;
|
||||
using PerPatchVertexType = OsdPerPatchVertexGregoryBasis;
|
||||
#else
|
||||
using PatchVertexType = OsdInputVertexType;
|
||||
using PerPatchVertexType = OsdInputVertexType;
|
||||
#endif
|
||||
|
||||
//Shared buffers used by OSD that are common to all kernels
|
||||
struct OsdPatchParamBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
#if OSD_PATCH_GREGORY || OSD_PATCH_GREGORY_BOUNDARY
|
||||
const device int* quadOffsetBuffer [[buffer(OSD_QUADOFFSET_BUFFER_INDEX)]];
|
||||
const device int* valenceBuffer [[buffer(OSD_VALENCE_BUFFER_INDEX)]];
|
||||
#endif
|
||||
|
||||
const constant unsigned& kernelExecutionLimit [[buffer(OSD_KERNELLIMIT_BUFFER_INDEX)]];
|
||||
};
|
||||
|
||||
//Shared buffers used by OSD that are common to all PTVS implementations
|
||||
struct OsdVertexBufferSet
|
||||
{
|
||||
const device OsdInputVertexType* vertexBuffer [[buffer(VERTEX_BUFFER_INDEX)]];
|
||||
const device unsigned* indexBuffer [[buffer(CONTROL_INDICES_BUFFER_INDEX)]];
|
||||
|
||||
const device OsdPatchParamBufferType* patchParamBuffer [[buffer(OSD_PATCHPARAM_BUFFER_INDEX)]];
|
||||
|
||||
device PerPatchVertexType* perPatchVertexBuffer [[buffer(OSD_PERPATCHVERTEX_BUFFER_INDEX)]];
|
||||
|
||||
#if !USE_PTVS_FACTORS
|
||||
device OsdPerPatchTessFactors* patchTessBuffer [[buffer(OSD_PERPATCHTESSFACTORS_BUFFER_INDEX)]];
|
||||
#endif
|
||||
};
|
||||
|
||||
// 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.
|
||||
|
||||
int3 OsdGetPatchParam(int patchIndex, const device OsdPatchParamBufferType* osdPatchParamBuffer)
|
||||
{
|
||||
#if OSD_PATCH_ENABLE_SINGLE_CREASE
|
||||
return int3(osdPatchParamBuffer[patchIndex]);
|
||||
#else
|
||||
auto p = osdPatchParamBuffer[patchIndex];
|
||||
return int3(p[0], p[1], 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int OsdGetPatchIndex(int primitiveId)
|
||||
{
|
||||
return primitiveId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// patch culling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool OsdCullPerPatchVertex(
|
||||
threadgroup PatchVertexType* patch,
|
||||
float4x4 ModelViewMatrix
|
||||
)
|
||||
{
|
||||
#if OSD_ENABLE_BACKPATCH_CULL && OSD_PATCH_REGULAR
|
||||
auto v0 = float3(ModelViewMatrix * patch[5].position);
|
||||
auto v3 = float3(ModelViewMatrix * patch[6].position);
|
||||
auto v12 = float3(ModelViewMatrix * patch[9].position);
|
||||
|
||||
auto n = normalize(cross(v3 - v0, v12 - v0));
|
||||
v0 = normalize(v0 + v3 + v12);
|
||||
|
||||
if(dot(v0, n) > 0.6f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#if OSD_ENABLE_PATCH_CULL
|
||||
short3 clipFlag = short3(0,0,0);
|
||||
for(int i = 0; i < CONTROL_POINTS_PER_PATCH; ++i) {
|
||||
clipFlag |= patch[i].clipFlag;
|
||||
}
|
||||
if (any(clipFlag != short3(3,3,3))) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Legacy Gregory
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -26,7 +26,9 @@
|
||||
#define OPENSUBDIV3_OSD_MTL_PATCH_SHADER_SOURCE_H
|
||||
|
||||
#import "../version.h"
|
||||
|
||||
#import "../far/patchDescriptor.h"
|
||||
|
||||
#import <string>
|
||||
|
||||
namespace OpenSubdiv {
|
||||
@ -34,12 +36,29 @@ namespace OPENSUBDIV_VERSION {
|
||||
|
||||
namespace Osd {
|
||||
|
||||
/// \brief Provides shader source which can be used by client code.
|
||||
class MTLPatchShaderSource {
|
||||
public:
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
public:
|
||||
/// \brief Returns shader source which can be used to evaluate
|
||||
/// position and first and second derivatives on piecewise parametric
|
||||
/// patches resulting from subdivision refinement.
|
||||
static std::string GetPatchBasisShaderSource();
|
||||
|
||||
/// \brief Returns shader source which can be used while drawing
|
||||
/// piecewise parametric patches resulting from subdivision refinement,
|
||||
/// e.g. while using GPU HW tessellation.
|
||||
static std::string GetPatchDrawingShaderSource();
|
||||
|
||||
/// \name Alternative methods
|
||||
/// \{
|
||||
/// These methods return shader source which can be used
|
||||
/// while drawing. Unlike the methods above, the source returned
|
||||
/// by these methods includes support for legacy patch types along
|
||||
/// with dependencies on specific resource bindings and interstage
|
||||
/// shader variable declarations.
|
||||
|
||||
static std::string GetCommonShaderSource();
|
||||
|
||||
static std::string GetVertexShaderSource(Far::PatchDescriptor::Type type);
|
||||
|
||||
static std::string GetHullShaderSource(Far::PatchDescriptor::Type type);
|
||||
@ -59,6 +78,9 @@ class MTLPatchShaderSource {
|
||||
static std::string GetDomainShaderSource(
|
||||
Far::PatchDescriptor::Type type,
|
||||
Far::PatchDescriptor::Type fvarType);
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace Osd
|
||||
|
@ -147,20 +147,25 @@ GetPatchTypeSource(Far::PatchDescriptor::Type type) {
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetCommonShaderSource() {
|
||||
MTLPatchShaderSource::GetPatchDrawingShaderSource() {
|
||||
#if TARGET_OS_IOS || TARGET_OS_TV
|
||||
return std::string("#define OSD_METAL_IOS 1\n")
|
||||
.append(commonShaderSource)
|
||||
.append(commonTessShaderSource)
|
||||
.append(patchLegacyShaderSource);
|
||||
.append(commonTessShaderSource);
|
||||
#elif TARGET_OS_OSX
|
||||
return std::string("#define OSD_METAL_OSX 1\n")
|
||||
.append(commonShaderSource)
|
||||
.append(commonTessShaderSource)
|
||||
.append(patchLegacyShaderSource);
|
||||
.append(commonTessShaderSource);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetCommonShaderSource() {
|
||||
return GetPatchDrawingShaderSource()
|
||||
.append(patchLegacyShaderSource);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
std::string
|
||||
MTLPatchShaderSource::GetPatchBasisShaderSource() {
|
||||
|
Loading…
Reference in New Issue
Block a user