mirror of
https://github.com/PixarAnimationStudios/OpenSubdiv
synced 2024-12-18 06:31:02 +00:00
Merge pull request #864 from davidgyu/patch_fvar_examples
Updated glFVarViewer and glEvalLimit examples
This commit is contained in:
commit
3e67332880
@ -564,6 +564,8 @@ public:
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
ss << "#define OSD_PATCH_BASIS_HLSL\n";
|
||||
ss << Osd::HLSLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
ss << Osd::HLSLPatchShaderSource::GetCommonShaderSource();
|
||||
std::string common = ss.str();
|
||||
ss.str("");
|
||||
|
@ -56,6 +56,7 @@ _add_glfw_executable(glEvalLimit "examples"
|
||||
particles.h
|
||||
"${INC_FILES}"
|
||||
$<TARGET_OBJECTS:regression_common_obj>
|
||||
$<TARGET_OBJECTS:regression_far_utils_obj>
|
||||
$<TARGET_OBJECTS:examples_common_obj>
|
||||
)
|
||||
|
||||
|
@ -160,6 +160,9 @@ struct Transform {
|
||||
float ModelViewProjectionMatrix[16];
|
||||
} g_transformData;
|
||||
|
||||
OpenSubdiv::Sdc::Options::FVarLinearInterpolation g_fvarBoundary =
|
||||
//OpenSubdiv::Sdc::Options::FVAR_LINEAR_ALL;
|
||||
OpenSubdiv::Sdc::Options::FVAR_LINEAR_CORNERS_ONLY;
|
||||
|
||||
// performance
|
||||
float g_evalTime = 0;
|
||||
@ -190,6 +193,7 @@ struct Program {
|
||||
GLuint attrTangentU;
|
||||
GLuint attrTangentV;
|
||||
GLuint attrPatchCoord;
|
||||
GLuint attrFVarData;
|
||||
} g_defaultProgram;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -216,13 +220,16 @@ public:
|
||||
virtual GLuint BindSourceData() const = 0;
|
||||
virtual GLuint BindVertexData() const = 0;
|
||||
virtual GLuint BindDerivatives() const = 0;
|
||||
virtual GLuint BindFaceVaryingData() const = 0;
|
||||
virtual GLuint BindPatchCoords() const = 0;
|
||||
virtual void UpdateData(const float *src, int startVertex, int numVertices) = 0;
|
||||
virtual void UpdateVaryingData(const float *src, int startVertex, int numVertices) = 0;
|
||||
virtual void UpdateFaceVaryingData(const float *src, int startVertex, int numVertices) = 0;
|
||||
virtual void Refine() = 0;
|
||||
virtual void EvalPatches() = 0;
|
||||
virtual void EvalPatchesWithDerivatives() = 0;
|
||||
virtual void EvalPatchesVarying() = 0;
|
||||
virtual void EvalPatchesFaceVarying() = 0;
|
||||
virtual void UpdatePatchCoords(
|
||||
std::vector<Osd::PatchCoord> const &patchCoords) = 0;
|
||||
};
|
||||
@ -241,39 +248,52 @@ public:
|
||||
|
||||
EvalOutput(Far::StencilTable const *vertexStencils,
|
||||
Far::StencilTable const *varyingStencils,
|
||||
int numCoarseVerts, int numTotalVerts, int numParticles,
|
||||
Far::PatchTable const *patchTable,
|
||||
Far::StencilTable const *faceVaryingStencils,
|
||||
int numCoarseVerts, int numTotalVerts,
|
||||
int numCoarseFVarVerts, int numTotalFVarVerts,
|
||||
int numParticles, Far::PatchTable const *patchTable,
|
||||
EvaluatorCache *evaluatorCache = NULL,
|
||||
DEVICE_CONTEXT *deviceContext = NULL)
|
||||
: _srcDesc( /*offset*/ 0, /*length*/ 3, /*stride*/ 3),
|
||||
_srcVaryingDesc(/*offset*/ 0, /*length*/ 3, /*stride*/ 3),
|
||||
_srcFVarDesc( /*offset*/ 0, /*length*/ 2, /*stride*/ 2),
|
||||
_vertexDesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
|
||||
_varyingDesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6),
|
||||
_fvarDesc( /*offset*/ 0, /*legnth*/ 2, /*stride*/ 2),
|
||||
_duDesc( /*offset*/ 0, /*legnth*/ 3, /*stride*/ 6),
|
||||
_dvDesc( /*offset*/ 3, /*legnth*/ 3, /*stride*/ 6),
|
||||
_deviceContext(deviceContext) {
|
||||
_srcData = SRC_VERTEX_BUFFER::Create(3, numTotalVerts, _deviceContext);
|
||||
_srcVaryingData = SRC_VERTEX_BUFFER::Create(3, numTotalVerts, _deviceContext);
|
||||
_srcFVarData = EVAL_VERTEX_BUFFER::Create(2, numTotalFVarVerts, _deviceContext);
|
||||
_vertexData = EVAL_VERTEX_BUFFER::Create(6, numParticles, _deviceContext);
|
||||
_derivatives = EVAL_VERTEX_BUFFER::Create(6, numParticles, _deviceContext);
|
||||
_fvarData = EVAL_VERTEX_BUFFER::Create(2, numParticles, _deviceContext);
|
||||
_patchTable = PATCH_TABLE::Create(patchTable, _deviceContext);
|
||||
_patchCoords = NULL;
|
||||
_numCoarseVerts = numCoarseVerts;
|
||||
_numCoarseFVarVerts = numCoarseFVarVerts;
|
||||
_vertexStencils =
|
||||
Osd::convertToCompatibleStencilTable<STENCIL_TABLE>(vertexStencils, _deviceContext);
|
||||
_varyingStencils =
|
||||
Osd::convertToCompatibleStencilTable<STENCIL_TABLE>(varyingStencils, _deviceContext);
|
||||
_faceVaryingStencils = (faceVaryingStencils)
|
||||
? Osd::convertToCompatibleStencilTable<STENCIL_TABLE>(faceVaryingStencils, _deviceContext)
|
||||
: NULL;
|
||||
_evaluatorCache = evaluatorCache;
|
||||
}
|
||||
~EvalOutput() {
|
||||
delete _srcData;
|
||||
delete _srcVaryingData;
|
||||
delete _srcFVarData;
|
||||
delete _vertexData;
|
||||
delete _derivatives;
|
||||
delete _fvarData;
|
||||
delete _patchTable;
|
||||
delete _patchCoords;
|
||||
delete _vertexStencils;
|
||||
delete _varyingStencils;
|
||||
delete _faceVaryingStencils;
|
||||
}
|
||||
virtual GLuint BindSourceData() const {
|
||||
return _srcData->BindVBO();
|
||||
@ -284,6 +304,9 @@ public:
|
||||
virtual GLuint BindDerivatives() const {
|
||||
return _derivatives->BindVBO();
|
||||
}
|
||||
virtual GLuint BindFaceVaryingData() const {
|
||||
return _fvarData->BindVBO();
|
||||
}
|
||||
virtual GLuint BindPatchCoords() const {
|
||||
return _patchCoords->BindVBO();
|
||||
}
|
||||
@ -293,6 +316,9 @@ public:
|
||||
virtual void UpdateVaryingData(const float *src, int startVertex, int numVertices) {
|
||||
_srcVaryingData->UpdateData(src, startVertex, numVertices, _deviceContext);
|
||||
}
|
||||
virtual void UpdateFaceVaryingData(const float *src, int startVertex, int numVertices) {
|
||||
_srcFVarData->UpdateData(src, startVertex, numVertices, _deviceContext);
|
||||
}
|
||||
virtual void Refine() {
|
||||
Osd::BufferDescriptor dstDesc = _srcDesc;
|
||||
dstDesc.offset += _numCoarseVerts * _srcDesc.stride;
|
||||
@ -316,6 +342,21 @@ public:
|
||||
_varyingStencils,
|
||||
evalInstance,
|
||||
_deviceContext);
|
||||
|
||||
if (_faceVaryingStencils) {
|
||||
int const fvarWidth = 2;
|
||||
Osd::BufferDescriptor dstFVarDesc(_numCoarseFVarVerts*fvarWidth,
|
||||
fvarWidth, fvarWidth);
|
||||
evalInstance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
_evaluatorCache, _srcFVarDesc, dstFVarDesc, _deviceContext);
|
||||
|
||||
EVALUATOR::EvalStencils(_srcFVarData, _srcFVarDesc,
|
||||
_srcFVarData, dstFVarDesc,
|
||||
_faceVaryingStencils,
|
||||
evalInstance,
|
||||
_deviceContext);
|
||||
}
|
||||
|
||||
}
|
||||
virtual void EvalPatches() {
|
||||
EVALUATOR const *evalInstance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
@ -344,7 +385,7 @@ public:
|
||||
EVALUATOR const *evalInstance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
_evaluatorCache, _srcVaryingDesc, _varyingDesc, _deviceContext);
|
||||
|
||||
EVALUATOR::EvalPatches(
|
||||
EVALUATOR::EvalPatchesVarying(
|
||||
_srcVaryingData, _srcVaryingDesc,
|
||||
// varyingdata is interleved in vertexData.
|
||||
_vertexData, _varyingDesc,
|
||||
@ -352,6 +393,17 @@ public:
|
||||
_patchCoords,
|
||||
_patchTable, evalInstance, _deviceContext);
|
||||
}
|
||||
virtual void EvalPatchesFaceVarying() {
|
||||
EVALUATOR const *evalInstance = OpenSubdiv::Osd::GetEvaluator<EVALUATOR>(
|
||||
_evaluatorCache, _srcFVarDesc, _fvarDesc, _deviceContext);
|
||||
|
||||
EVALUATOR::EvalPatchesFaceVarying(
|
||||
_srcFVarData, _srcFVarDesc,
|
||||
_fvarData, _fvarDesc,
|
||||
_patchCoords->GetNumVertices(),
|
||||
_patchCoords,
|
||||
_patchTable, /*fvarChannel=*/0, evalInstance, _deviceContext);
|
||||
}
|
||||
virtual void UpdatePatchCoords(
|
||||
std::vector<Osd::PatchCoord> const &patchCoords) {
|
||||
if (_patchCoords &&
|
||||
@ -369,21 +421,26 @@ public:
|
||||
private:
|
||||
SRC_VERTEX_BUFFER *_srcData;
|
||||
SRC_VERTEX_BUFFER *_srcVaryingData;
|
||||
EVAL_VERTEX_BUFFER *_srcFVarData;
|
||||
EVAL_VERTEX_BUFFER *_vertexData;
|
||||
EVAL_VERTEX_BUFFER *_derivatives;
|
||||
EVAL_VERTEX_BUFFER *_varyingData;
|
||||
EVAL_VERTEX_BUFFER *_fvarData;
|
||||
EVAL_VERTEX_BUFFER *_patchCoords;
|
||||
PATCH_TABLE *_patchTable;
|
||||
Osd::BufferDescriptor _srcDesc;
|
||||
Osd::BufferDescriptor _srcVaryingDesc;
|
||||
Osd::BufferDescriptor _srcFVarDesc;
|
||||
Osd::BufferDescriptor _vertexDesc;
|
||||
Osd::BufferDescriptor _varyingDesc;
|
||||
Osd::BufferDescriptor _fvarDesc;
|
||||
Osd::BufferDescriptor _duDesc;
|
||||
Osd::BufferDescriptor _dvDesc;
|
||||
int _numCoarseVerts;
|
||||
int _numCoarseFVarVerts;
|
||||
|
||||
STENCIL_TABLE const *_vertexStencils;
|
||||
STENCIL_TABLE const *_varyingStencils;
|
||||
STENCIL_TABLE const *_faceVaryingStencils;
|
||||
|
||||
EvaluatorCache *_evaluatorCache;
|
||||
DEVICE_CONTEXT *_deviceContext;
|
||||
@ -459,8 +516,9 @@ updateGeom() {
|
||||
|
||||
// color
|
||||
if (g_drawMode == kVARYING) {
|
||||
// XXX: is this really varying?
|
||||
g_evalOutput->EvalPatchesVarying();
|
||||
} else if (g_drawMode == kFACEVARYING) {
|
||||
g_evalOutput->EvalPatchesFaceVarying();
|
||||
}
|
||||
|
||||
s.Stop();
|
||||
@ -478,6 +536,8 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
OpenSubdiv::Sdc::SchemeType sdctype = GetSdcType(*shape);
|
||||
OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
||||
|
||||
sdcoptions.SetFVarLinearInterpolation(g_fvarBoundary);
|
||||
|
||||
Far::TopologyRefiner *topologyRefiner =
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
||||
OpenSubdiv::Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
||||
@ -485,8 +545,6 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
g_orgPositions=shape->verts;
|
||||
g_positions.resize(g_orgPositions.size(), 0.0f);
|
||||
|
||||
delete shape;
|
||||
|
||||
float speed = g_particles ? g_particles->GetSpeed() : 0.2f;
|
||||
|
||||
// save coarse topology (used for coarse mesh drawing)
|
||||
@ -501,7 +559,9 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
|
||||
Far::StencilTable const * vertexStencils = NULL;
|
||||
Far::StencilTable const * varyingStencils = NULL;
|
||||
int nverts=0;
|
||||
Far::StencilTable const * faceVaryingStencils = NULL;
|
||||
std::vector<float> fvarData;
|
||||
int nverts=0, nTotalfvarVerts=0;
|
||||
|
||||
{
|
||||
bool adaptive = (sdctype == OpenSubdiv::Sdc::SCHEME_CATMARK);
|
||||
@ -509,6 +569,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
// Apply feature adaptive refinement to the mesh so that we can use the
|
||||
// limit evaluation API features.
|
||||
Far::TopologyRefiner::AdaptiveOptions options(level);
|
||||
options.considerFVarChannels = true;
|
||||
topologyRefiner->RefineAdaptive(options);
|
||||
} else {
|
||||
Far::TopologyRefiner::UniformOptions options(level);
|
||||
@ -531,7 +592,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Far::StencilTableFactory::Create(*topologyRefiner, soptions);
|
||||
|
||||
// Generate bi-cubic patch table for the limit surface
|
||||
Far::PatchTableFactory::Options poptions;
|
||||
Far::PatchTableFactory::Options poptions(level);
|
||||
if (g_endCap == kEndCapBSplineBasis) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_BSPLINE_BASIS);
|
||||
@ -539,6 +600,8 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
poptions.SetEndCapType(
|
||||
Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS);
|
||||
}
|
||||
poptions.generateFVarTables = true;
|
||||
poptions.generateFVarLegacyLinearPatches = false;
|
||||
|
||||
Far::PatchTable const * patchTable =
|
||||
Far::PatchTableFactory::Create(*topologyRefiner, poptions);
|
||||
@ -561,17 +624,29 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
delete varyingStencils;
|
||||
varyingStencils = table;
|
||||
}
|
||||
if (Far::StencilTable const *localPointFaceVaryingStencilTable =
|
||||
patchTable->GetLocalPointFaceVaryingStencilTable()) {
|
||||
faceVaryingStencils = localPointFaceVaryingStencilTable;
|
||||
}
|
||||
|
||||
// total number of vertices = coarse verts + refined verts + gregory basis verts
|
||||
nverts = vertexStencils->GetNumControlVertices() +
|
||||
vertexStencils->GetNumStencils();
|
||||
|
||||
nTotalfvarVerts = topologyRefiner->GetNumFVarValuesTotal(0) +
|
||||
patchTable->GetNumLocalPointsFaceVarying(0);
|
||||
|
||||
InterpolateFVarData(*topologyRefiner, *shape, fvarData);
|
||||
|
||||
if (g_patchTable) delete g_patchTable;
|
||||
g_patchTable = patchTable;
|
||||
}
|
||||
|
||||
delete shape;
|
||||
|
||||
// note that for patch eval we need coarse+refined combined buffer.
|
||||
int nCoarseVertices = topologyRefiner->GetLevel(0).GetNumVertices();
|
||||
int nCoarseFVarVertices = (int)fvarData.size()/2;
|
||||
|
||||
// In following template instantiations, same type of vertex buffers are
|
||||
// used for both source and destination (first and second template
|
||||
@ -587,8 +662,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Far::StencilTable,
|
||||
Osd::CpuPatchTable,
|
||||
Osd::CpuEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable);
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable);
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
} else if (g_kernel == kOPENMP) {
|
||||
g_evalOutput = new EvalOutput<Osd::CpuGLVertexBuffer,
|
||||
@ -596,8 +673,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Far::StencilTable,
|
||||
Osd::CpuPatchTable,
|
||||
Osd::OmpEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable);
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_TBB
|
||||
} else if (g_kernel == kTBB) {
|
||||
@ -606,8 +685,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Far::StencilTable,
|
||||
Osd::CpuPatchTable,
|
||||
Osd::TbbEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable);
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
} else if (g_kernel == kCUDA) {
|
||||
@ -616,8 +697,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Osd::CudaStencilTable,
|
||||
Osd::CudaPatchTable,
|
||||
Osd::CudaEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable);
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
} else if (g_kernel == kCL) {
|
||||
@ -628,8 +711,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Osd::CLPatchTable,
|
||||
Osd::CLEvaluator,
|
||||
CLDeviceContext>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable,
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable,
|
||||
&clEvaluatorCache, &g_clDeviceContext);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
@ -640,8 +725,10 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Osd::GLStencilTableTBO,
|
||||
Osd::GLPatchTable,
|
||||
Osd::GLXFBEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable,
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable,
|
||||
&glXFBEvaluatorCache);
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
@ -652,12 +739,16 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) {
|
||||
Osd::GLStencilTableSSBO,
|
||||
Osd::GLPatchTable,
|
||||
Osd::GLComputeEvaluator>
|
||||
(vertexStencils, varyingStencils,
|
||||
nCoarseVertices, nverts, g_nParticles, g_patchTable,
|
||||
(vertexStencils, varyingStencils, faceVaryingStencils,
|
||||
nCoarseVertices, nverts,
|
||||
nCoarseFVarVertices, nTotalfvarVerts,
|
||||
g_nParticles, g_patchTable,
|
||||
&glComputeEvaluatorCache);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_evalOutput->UpdateFaceVaryingData(&fvarData[0], 0, (int)fvarData.size()/2);
|
||||
|
||||
// Create the 'uv particles' manager - this class manages the limit
|
||||
// location samples (ptex face index, (s,t) and updates them between frames.
|
||||
// Note: the number of limit locations can be entirely arbitrary
|
||||
@ -692,6 +783,7 @@ linkDefaultProgram() {
|
||||
"in vec3 tangentU;\n"
|
||||
"in vec3 tangentV;\n"
|
||||
"in vec2 patchCoord;\n"
|
||||
"in vec2 fvarData;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"uniform mat4 ModelViewMatrix;\n"
|
||||
"uniform mat4 ProjectionMatrix;\n"
|
||||
@ -708,7 +800,9 @@ linkDefaultProgram() {
|
||||
" } else if (DrawMode == 3) {\n"
|
||||
" fragColor = vec4(vec3(1)*dot(normal, vec3(0,0,1)), 1);\n"
|
||||
" } else if (DrawMode == 4) {\n" // face varying
|
||||
" fragColor = vec4(1);\n"
|
||||
" // generating a checkerboard pattern\n"
|
||||
" int checker = int(floor(20*fvarData.r)+floor(20*fvarData.g))&1;\n"
|
||||
" fragColor = vec4(fvarData.rg*checker, 1-checker, 1);\n"
|
||||
" } else {\n" // varying
|
||||
" fragColor = vec4(color, 1);\n"
|
||||
" }\n"
|
||||
@ -734,6 +828,7 @@ linkDefaultProgram() {
|
||||
glBindAttribLocation(program, 2, "tangentU");
|
||||
glBindAttribLocation(program, 3, "tangentV");
|
||||
glBindAttribLocation(program, 4, "patchCoord");
|
||||
glBindAttribLocation(program, 5, "fvarData");
|
||||
glBindFragDataLocation(program, 0, "color");
|
||||
|
||||
glLinkProgram(program);
|
||||
@ -762,6 +857,7 @@ linkDefaultProgram() {
|
||||
g_defaultProgram.attrTangentU = glGetAttribLocation(program, "tangentU");
|
||||
g_defaultProgram.attrTangentV = glGetAttribLocation(program, "tangentV");
|
||||
g_defaultProgram.attrPatchCoord = glGetAttribLocation(program, "patchCoord");
|
||||
g_defaultProgram.attrFVarData = glGetAttribLocation(program, "fvarData");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -783,6 +879,8 @@ drawSamples() {
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPatchCoord);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrFVarData);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_evalOutput->BindVertexData());
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0);
|
||||
@ -795,11 +893,15 @@ drawSamples() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_evalOutput->BindPatchCoords());
|
||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 5, (float*)12);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, g_evalOutput->BindFaceVaryingData());
|
||||
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 2, 0);
|
||||
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPosition);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrColor);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrPatchCoord);
|
||||
glEnableVertexAttribArray(g_defaultProgram.attrFVarData);
|
||||
|
||||
glPointSize(2.0f);
|
||||
int nPatchCoords = (int)g_particles->GetPatchCoords().size();
|
||||
@ -811,6 +913,7 @@ drawSamples() {
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentU);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrTangentV);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrPatchCoord);
|
||||
glDisableVertexAttribArray(g_defaultProgram.attrFVarData);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
@ -875,20 +978,6 @@ display() {
|
||||
g_hud.DrawString(10, -40, "CPU Draw : %.3f ms", drawCpuTime);
|
||||
g_hud.DrawString(10, -20, "FPS : %3.1f", fps);
|
||||
|
||||
if (g_drawMode==kFACEVARYING) {
|
||||
static char msg[] =
|
||||
"ERROR: Face-varying interpolation hasn't been supported yet.";
|
||||
g_hud.DrawString(g_width/4, g_height/4, 1, 0, 0, msg);
|
||||
}
|
||||
|
||||
if (g_endCap != kEndCapBSplineBasis &&
|
||||
(g_kernel != kCPU && g_kernel != kOPENMP && g_kernel != kTBB)) {
|
||||
static char msg[] =
|
||||
"ERROR: This kernel only supports BSpline basis patches.";
|
||||
g_hud.DrawString(g_width/4, g_height/4+20, 1, 0, 0, msg);
|
||||
}
|
||||
|
||||
|
||||
g_hud.Flush();
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,9 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
|
@ -30,6 +30,7 @@ GLFWmonitor* g_primary = 0;
|
||||
|
||||
#include <far/error.h>
|
||||
#include <osd/cpuEvaluator.h>
|
||||
#include <osd/cpuVertexBuffer.h>
|
||||
#include <osd/cpuGLVertexBuffer.h>
|
||||
#include <osd/glMesh.h>
|
||||
OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL;
|
||||
@ -62,6 +63,9 @@ enum DisplayStyle { kWire = 0,
|
||||
kShaded,
|
||||
kWireShaded };
|
||||
|
||||
enum EndCap { kEndCapBSplineBasis,
|
||||
kEndCapGregoryBasis };
|
||||
|
||||
int g_currentShape = 0;
|
||||
|
||||
int g_frame = 0,
|
||||
@ -105,6 +109,7 @@ std::vector<float> g_orgPositions,
|
||||
|
||||
Scheme g_scheme;
|
||||
|
||||
int g_endCap = kEndCapBSplineBasis;
|
||||
int g_level = 2;
|
||||
int g_tessLevel = 1;
|
||||
int g_tessLevelMin = 1;
|
||||
@ -138,7 +143,7 @@ struct Program {
|
||||
struct FVarData
|
||||
{
|
||||
FVarData() :
|
||||
textureBuffer(0) {
|
||||
textureBuffer(0), textureParamBuffer(0) {
|
||||
}
|
||||
~FVarData() {
|
||||
Release();
|
||||
@ -147,11 +152,38 @@ struct FVarData
|
||||
if (textureBuffer)
|
||||
glDeleteTextures(1, &textureBuffer);
|
||||
textureBuffer = 0;
|
||||
if (textureParamBuffer)
|
||||
glDeleteTextures(1, &textureParamBuffer);
|
||||
textureParamBuffer = 0;
|
||||
}
|
||||
void Create(OpenSubdiv::Far::PatchTable const *patchTable,
|
||||
int fvarWidth, std::vector<float> const & fvarSrcData) {
|
||||
|
||||
using namespace OpenSubdiv;
|
||||
|
||||
Release();
|
||||
OpenSubdiv::Far::ConstIndexArray indices = patchTable->GetFVarValues();
|
||||
Far::ConstIndexArray indices = patchTable->GetFVarValues();
|
||||
|
||||
const float * fvarSrcDataPtr = &fvarSrcData[0];
|
||||
Osd::CpuVertexBuffer *fvarBuffer = NULL;
|
||||
|
||||
int numLocalFVarPoints = patchTable->GetNumLocalPointsFaceVarying();
|
||||
if (numLocalFVarPoints > 0) {
|
||||
int numSrcFVarPoints = (int)fvarSrcData.size() / fvarWidth;
|
||||
fvarBuffer = Osd::CpuVertexBuffer::Create(
|
||||
fvarWidth, numSrcFVarPoints + numLocalFVarPoints);
|
||||
fvarBuffer->UpdateData(&fvarSrcData[0], 0, numSrcFVarPoints);
|
||||
|
||||
Osd::BufferDescriptor srcDesc(0, fvarWidth, fvarWidth);
|
||||
Osd::BufferDescriptor dstDesc(numSrcFVarPoints*fvarWidth,
|
||||
fvarWidth, fvarWidth);
|
||||
|
||||
Osd::CpuEvaluator::EvalStencils(fvarBuffer, srcDesc,
|
||||
fvarBuffer, dstDesc,
|
||||
patchTable->GetLocalPointFaceVaryingStencilTable());
|
||||
|
||||
fvarSrcDataPtr = fvarBuffer->BindCpuBuffer();
|
||||
}
|
||||
|
||||
// expand fvardata to per-patch array
|
||||
std::vector<float> data;
|
||||
@ -160,7 +192,7 @@ struct FVarData
|
||||
for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
|
||||
int index = indices[fvert] * fvarWidth;
|
||||
for (int i = 0; i < fvarWidth; ++i) {
|
||||
data.push_back(fvarSrcData[index++]);
|
||||
data.push_back(fvarSrcDataPtr[index++]);
|
||||
}
|
||||
}
|
||||
GLuint buffer;
|
||||
@ -169,6 +201,10 @@ struct FVarData
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
|
||||
&data[0], GL_STATIC_DRAW);
|
||||
|
||||
if (fvarBuffer) {
|
||||
delete fvarBuffer;
|
||||
}
|
||||
|
||||
glGenTextures(1, &textureBuffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, textureBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
|
||||
@ -176,8 +212,23 @@ struct FVarData
|
||||
glBindTexture(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
Far::ConstPatchParamArray fvarParam = patchTable->GetFVarPatchParam();
|
||||
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, fvarParam.size()*sizeof(Far::PatchParam),
|
||||
&fvarParam[0], GL_STATIC_DRAW);
|
||||
|
||||
glGenTextures(1, &textureParamBuffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, textureParamBuffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindTexture(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
GLuint textureBuffer;
|
||||
GLuint textureBuffer, textureParamBuffer;
|
||||
} g_fvarData;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -366,6 +417,10 @@ rebuildMesh() {
|
||||
OpenSubdiv::Osd::MeshBitset bits;
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, doAdaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarAdaptive, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
||||
|
||||
|
||||
int numVertexElements = 3;
|
||||
int numVaryingElements = 0;
|
||||
@ -461,10 +516,13 @@ GetEffect(bool uvDraw = false) {
|
||||
|
||||
struct EffectDesc {
|
||||
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
|
||||
Effect effect) : desc(desc), effect(effect),
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc,
|
||||
Effect effect) : desc(desc), fvarDesc(fvarDesc),
|
||||
effect(effect),
|
||||
maxValence(0), numElements(0) { }
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor desc;
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc;
|
||||
Effect effect;
|
||||
int maxValence;
|
||||
int numElements;
|
||||
@ -472,9 +530,10 @@ struct EffectDesc {
|
||||
bool operator < (const EffectDesc &e) const {
|
||||
return
|
||||
(desc < e.desc || ((desc == e.desc &&
|
||||
(fvarDesc < e.fvarDesc || ((fvarDesc == e.fvarDesc &&
|
||||
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
|
||||
(numElements < e.numElements || ((numElements == e.numElements) &&
|
||||
(effect < e.effect))))))));
|
||||
(effect < e.effect)))))))))));
|
||||
}
|
||||
};
|
||||
|
||||
@ -536,7 +595,17 @@ public:
|
||||
ss << "#define SHADING_FACEVARYING_UNIFORM_SUBDIVISION\n";
|
||||
}
|
||||
|
||||
if (effectDesc.desc.IsAdaptive()) {
|
||||
if (effectDesc.fvarDesc.GetType() == Far::PatchDescriptor::REGULAR) {
|
||||
ss << "#define SHADING_FACEVARYING_SMOOTH_BSPLINE_BASIS\n";
|
||||
} else if (effectDesc.fvarDesc.GetType() == Far::PatchDescriptor::GREGORY_BASIS) {
|
||||
ss << "#define SHADING_FACEVARYING_SMOOTH_GREGORY_BASIS\n";
|
||||
}
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
ss << "#define OSD_PATCH_BASIS_GLSL\n";
|
||||
ss << Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
ss << Osd::GLSLPatchShaderSource::GetCommonShaderSource();
|
||||
std::string common = ss.str();
|
||||
ss.str("");
|
||||
@ -607,6 +676,9 @@ public:
|
||||
if ((loc = glGetUniformLocation(program, "OsdFVarDataBuffer")) != -1) {
|
||||
glUniform1i(loc, 1); // GL_TEXTURE1
|
||||
}
|
||||
if ((loc = glGetUniformLocation(program, "OsdFVarParamBuffer")) != -1) {
|
||||
glUniform1i(loc, 2); // GL_TEXTURE2
|
||||
}
|
||||
|
||||
|
||||
return config;
|
||||
@ -661,14 +733,18 @@ bindTextures() {
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, g_fvarData.textureBuffer);
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, g_fvarData.textureParamBuffer);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
static GLenum
|
||||
bindProgram(Effect effect, OpenSubdiv::Osd::PatchArray const & patch) {
|
||||
bindProgram(Effect effect,
|
||||
OpenSubdiv::Osd::PatchArray const & patch,
|
||||
OpenSubdiv::Far::PatchDescriptor const & fvarDesc) {
|
||||
|
||||
EffectDesc effectDesc(patch.GetDescriptor(), effect);
|
||||
EffectDesc effectDesc(patch.GetDescriptor(), fvarDesc, effect);
|
||||
|
||||
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
|
||||
|
||||
@ -745,6 +821,9 @@ display() {
|
||||
|
||||
glBindVertexArray(g_vao);
|
||||
|
||||
OpenSubdiv::Far::PatchDescriptor fvarDesc =
|
||||
g_mesh->GetFarPatchTable()->GetFVarChannelPatchDescriptor(0);
|
||||
|
||||
OpenSubdiv::Osd::PatchArrayVector const & patches =
|
||||
g_mesh->GetPatchTable()->GetPatchArrays();
|
||||
|
||||
@ -758,7 +837,7 @@ display() {
|
||||
for (int i = 0; i < (int)patches.size(); ++i) {
|
||||
OpenSubdiv::Osd::PatchArray const & patch = patches[i];
|
||||
|
||||
GLenum primType = bindProgram(GetEffect(), patch);
|
||||
GLenum primType = bindProgram(GetEffect(), patch, fvarDesc);
|
||||
|
||||
glDrawElements(
|
||||
primType,
|
||||
@ -789,7 +868,7 @@ display() {
|
||||
for (int i = 0; i < (int)patches.size(); ++i) {
|
||||
OpenSubdiv::Osd::PatchArray const & patch = patches[i];
|
||||
|
||||
GLenum primType = bindProgram(GetEffect(/*uvDraw=*/ true), patch);
|
||||
GLenum primType = bindProgram(GetEffect(/*uvDraw=*/ true), patch, fvarDesc);
|
||||
|
||||
glDrawElements(
|
||||
primType,
|
||||
@ -927,6 +1006,12 @@ callbackDisplayStyle(int b) {
|
||||
g_displayStyle = b;
|
||||
}
|
||||
|
||||
static void
|
||||
callbackEndCap(int endCap) {
|
||||
g_endCap = endCap;
|
||||
rebuildMesh();
|
||||
}
|
||||
|
||||
static void
|
||||
callbackLevel(int l) {
|
||||
|
||||
@ -996,6 +1081,15 @@ initHUD() {
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Shaded", kShaded, g_displayStyle==kShaded);
|
||||
g_hud.AddPullDownButton(shading_pulldown, "Wire+Shaded", kWireShaded, g_displayStyle==kWireShaded);
|
||||
|
||||
int endcap_pulldown = g_hud.AddPullDown("End cap (E)", 10, 140, 200,
|
||||
callbackEndCap, 'e');
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "BSpline",
|
||||
kEndCapBSplineBasis,
|
||||
g_endCap == kEndCapBSplineBasis);
|
||||
g_hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
|
||||
kEndCapGregoryBasis,
|
||||
g_endCap == kEndCapGregoryBasis);
|
||||
|
||||
if (GLUtils::SupportsAdaptiveTessellation())
|
||||
g_hud.AddCheckBox("Adaptive (`)", g_adaptive != 0, 10, 250, callbackAdaptive, 0, '`');
|
||||
|
||||
|
@ -64,6 +64,9 @@ static void initShapes() {
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) );
|
||||
g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) );
|
||||
|
@ -166,6 +166,57 @@ out block {
|
||||
OSD_USER_VARYING_DECLARE
|
||||
} outpt;
|
||||
|
||||
uniform isamplerBuffer OsdFVarParamBuffer;
|
||||
|
||||
vec2
|
||||
interpolateFaceVarying(vec2 uv, int fvarOffset)
|
||||
{
|
||||
int patchIndex = OsdGetPatchIndex(gl_PrimitiveID);
|
||||
|
||||
#if defined(SHADING_FACEVARYING_SMOOTH_BSPLINE_BASIS)
|
||||
float wP[16], wDs[16], wDt[16], wDss[16], wDst[16], wDtt[16];
|
||||
int patchCVs = 16;
|
||||
int patchStride = patchCVs;
|
||||
int boundaryMask = (int(texelFetch(OsdFVarParamBuffer, patchIndex).y) >> 8) & 0xf;
|
||||
OsdGetBSplinePatchWeights(uv.s, uv.t, 1.0f, boundaryMask, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
|
||||
#elif defined(SHADING_FACEVARYING_SMOOTH_GREGORY_BASIS)
|
||||
float wP[20], wDs[20], wDt[20], wDss[20], wDst[20], wDtt[20];
|
||||
int patchCVs = 20;
|
||||
int patchStride = patchCVs;
|
||||
bool isRegular = ((int(texelFetch(OsdFVarParamBuffer, patchIndex).y) >> 5) & 0x1) != 0;
|
||||
if (isRegular) {
|
||||
float wP16[16], wDs16[16], wDt16[16], wDss16[16], wDst16[16], wDtt16[16];
|
||||
patchCVs = 16;
|
||||
int boundaryMask = (int(texelFetch(OsdFVarParamBuffer, patchIndex).y) >> 8) & 0xf;
|
||||
OsdGetBSplinePatchWeights(uv.s, uv.t, 1.0f, boundaryMask, wP16, wDs16, wDt16, wDss16, wDst16, wDtt16);
|
||||
for (int i=0; i<patchCVs; ++i) {
|
||||
wP[i] = wP16[i];
|
||||
}
|
||||
} else {
|
||||
OsdGetGregoryPatchWeights(uv.s, uv.t, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
}
|
||||
|
||||
#else
|
||||
float wP[4], wDs[4], wDt[4], wDss[4], wDst[4], wDtt[4];
|
||||
int patchCVs = 4;
|
||||
int patchStride = patchCVs;
|
||||
OsdGetBilinearPatchWeights(uv.s, uv.t, 1.0f, wP, wDs, wDt, wDss, wDst, wDtt);
|
||||
#endif
|
||||
|
||||
int primOffset = patchIndex * patchStride;
|
||||
|
||||
vec2 result = vec2(0);
|
||||
for (int i=0; i<patchCVs; ++i) {
|
||||
int index = (primOffset+i)*OSD_FVAR_WIDTH + fvarOffset;
|
||||
vec2 cv = vec2(texelFetch(OsdFVarDataBuffer, index).s,
|
||||
texelFetch(OsdFVarDataBuffer, index + 1).s);
|
||||
result += wP[i] * cv;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void emit(int index, vec3 normal)
|
||||
{
|
||||
outpt.v.position = inpt[index].v.position;
|
||||
@ -187,8 +238,7 @@ void emit(int index, vec3 normal)
|
||||
#else
|
||||
vec2 st = inpt[index].v.tessCoord;
|
||||
#endif
|
||||
vec2 uv;
|
||||
OSD_COMPUTE_FACE_VARYING_2(uv, /*fvarOffset=*/0, st);
|
||||
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
|
||||
#endif // ------ scheme
|
||||
|
||||
outpt.color = vec3(uv.s, uv.t, 0);
|
||||
|
@ -790,6 +790,8 @@ public:
|
||||
}
|
||||
|
||||
// include osd PatchCommon
|
||||
ss << "#define OSD_PATCH_BASIS_GLSL\n";
|
||||
ss << Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
|
||||
ss << Osd::GLSLPatchShaderSource::GetCommonShaderSource();
|
||||
std::string common = ss.str();
|
||||
ss.str("");
|
||||
|
Loading…
Reference in New Issue
Block a user