Merge pull request #864 from davidgyu/patch_fvar_examples

Updated glFVarViewer and glEvalLimit examples
This commit is contained in:
barfowl 2016-09-29 10:55:42 -07:00 committed by GitHub
commit 3e67332880
8 changed files with 294 additions and 51 deletions

View File

@ -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("");

View File

@ -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>
)

View File

@ -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();
}

View File

@ -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 ) );

View File

@ -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, '`');

View File

@ -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 ) );

View File

@ -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);

View File

@ -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("");