Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved osd patch drawing compatibility #1320

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 4 additions & 142 deletions opensubdiv/osd/glslPatchCommon.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -582,15 +444,15 @@ 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,
0.f, 1.f/6.f, 4.f/6.f, 1.f/6.f
);

// 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,
Expand Down
122 changes: 122 additions & 0 deletions opensubdiv/osd/glslPatchLegacy.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ----------------------------------------------------------------------------
Expand Down
10 changes: 9 additions & 1 deletion opensubdiv/osd/glslPatchShaderSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
27 changes: 24 additions & 3 deletions opensubdiv/osd/glslPatchShaderSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -48,6 +67,8 @@ class GLSLPatchShaderSource {

static std::string GetTessEvalShaderSource(
Far::PatchDescriptor::Type type);

/// \}
};

} // end namespace Osd
Expand Down
Loading