Fix fvardata interpolation on adaptive patches.

This commit is contained in:
Takahito Tejima 2013-06-04 11:02:27 -07:00
parent 71b51eb16d
commit a6bf169344
5 changed files with 69 additions and 68 deletions

View File

@ -131,13 +131,11 @@ static const char *defaultShaderSource =
// Draw styles for EffectDrawRegistry // Draw styles for EffectDrawRegistry
enum Effect enum Effect
{ {
kQuadFill = 0, kFill = 0,
kQuadLine = 1, kLine = 1,
kTriFill = 2, kPoint = 2,
kTriLine = 3,
kPoint = 4,
}; };
typedef std::pair<OpenSubdiv::OsdPatchDescriptor, Effect> EffectDesc; typedef std::pair<OpenSubdiv::OsdDrawContext::PatchDescriptor, Effect> EffectDesc;
// #### Override of OpenSubdiv::OsdGLDrawRegistry // #### Override of OpenSubdiv::OsdGLDrawRegistry
// //
@ -214,17 +212,20 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
SourceConfigType * sconfig = SourceConfigType * sconfig =
BaseRegistry::_CreateDrawSourceConfig(desc.first); BaseRegistry::_CreateDrawSourceConfig(desc.first);
if (desc.first.type != OpenSubdiv::kNonPatch) { bool quad = false;
// Per-vertex descriptors are use for uniform refinement if (desc.first.GetType() == OpenSubdiv::FarPatchTables::QUADS) {
if (effect == kQuadFill) effect = kTriFill;
if (effect == kQuadLine) effect = kTriLine;
sconfig->geometryShader.AddDefine("SMOOTH_NORMALS");
} else {
// Configuration for adaptive refinement // Configuration for adaptive refinement
sconfig->vertexShader.version = "#version 410\n"; sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.source = _shaderSource; sconfig->vertexShader.source = _shaderSource;
sconfig->vertexShader.AddDefine("VERTEX_SHADER"); sconfig->vertexShader.AddDefine("VERTEX_SHADER");
quad = true;
} else if (desc.first.GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) {
sconfig->vertexShader.version = "#version 410\n";
sconfig->vertexShader.source = _shaderSource;
sconfig->vertexShader.AddDefine("VERTEX_SHADER");
} else {
// adaptive patches
sconfig->geometryShader.AddDefine("SMOOTH_NORMALS");
} }
assert(sconfig); assert(sconfig);
@ -254,29 +255,20 @@ EffectDrawRegistry::_CreateDrawSourceConfig(DescType const & desc)
sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER"); sconfig->fragmentShader.AddDefine("FRAGMENT_SHADER");
// Set up directives according to draw style // Set up directives according to draw style
if (quad) {
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
} else {
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
}
switch (effect) { switch (effect) {
case kQuadFill: case kFill:
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL"); sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL"); sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL");
break; break;
case kQuadLine: case kLine:
sconfig->geometryShader.AddDefine("PRIM_QUAD");
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE"); sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE");
sconfig->fragmentShader.AddDefine("PRIM_QUAD");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE");
break;
case kTriFill:
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_FILL");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_FILL");
break;
case kTriLine:
sconfig->geometryShader.AddDefine("PRIM_TRI");
sconfig->geometryShader.AddDefine("GEOMETRY_OUT_LINE");
sconfig->fragmentShader.AddDefine("PRIM_TRI");
sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE"); sconfig->fragmentShader.AddDefine("GEOMETRY_OUT_LINE");
break; break;
case kPoint: case kPoint:
@ -344,7 +336,7 @@ EffectDrawRegistry::_CreateDrawConfig(
if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) { if ((loc = glGetUniformLocation(config->program, "g_QuadOffsetBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 2); // GL_TEXTURE2 glProgramUniform1i(config->program, loc, 2); // GL_TEXTURE2
} }
if ((loc = glGetUniformLocation(config->program, "g_patchLevelBuffer")) != -1) { if ((loc = glGetUniformLocation(config->program, "g_ptexIndicesBuffer")) != -1) {
glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3 glProgramUniform1i(config->program, loc, 3); // GL_TEXTURE3
} }
if ((loc = glGetUniformLocation(config->program, "g_uvFVarBuffer")) != -1) { if ((loc = glGetUniformLocation(config->program, "g_uvFVarBuffer")) != -1) {
@ -668,31 +660,36 @@ OpenSubdivShader::draw(const MHWRender::MDrawContext &mDrawContext,
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->patchIndexBuffer); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, osdDrawContext->GetPatchIndexBuffer());
// Get list of patches from OSD // Get list of patches from OSD
OpenSubdiv::OsdPatchArrayVector const & patches = OpenSubdiv::OsdDrawContext::PatchArrayVector const & patches =
osdDrawContext->patchArrays; osdDrawContext->patchArrays;
// Draw patches // Draw patches
for (size_t i = 0; i < patches.size(); ++i) { for (size_t i = 0; i < patches.size(); ++i) {
OpenSubdiv::OsdPatchArray const & patch = patches[i]; OpenSubdiv::OsdDrawContext::PatchArray const & patch = patches[i];
bindProgram(mDrawContext, osdDrawContext, patch); GLuint program = bindProgram(mDrawContext, osdDrawContext, patch);
if (patch.desc.type != OpenSubdiv::kNonPatch) { GLuint uniformGregoryQuadOffset = glGetUniformLocation(program, "GregoryQuadOffsetBase");
glPatchParameteri(GL_PATCH_VERTICES, patch.desc.GetPatchSize()); GLuint uniformLevelBase = glGetUniformLocation(program, "LevelBase");
glProgramUniform1i(program, uniformGregoryQuadOffset, patch.GetQuadOffsetIndex());
glProgramUniform1i(program, uniformLevelBase, patch.GetPatchIndex());
glDrawElements(GL_PATCHES, GLenum primType = GL_PATCHES;
patch.numIndices, GL_UNSIGNED_INT, if (patch.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::QUADS) {
reinterpret_cast<void *>(patch.firstIndex * primType = GL_LINES_ADJACENCY;
sizeof(unsigned int))); } else if (patch.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) {
} else { primType = GL_TRIANGLES;
glDrawElements(_scheme == OsdMeshData::kLoop ? GL_TRIANGLES : GL_LINES_ADJACENCY, } else if (patch.GetDescriptor().GetType() >= OpenSubdiv::FarPatchTables::REGULAR) {
patch.numIndices, GL_UNSIGNED_INT, glPatchParameteri(GL_PATCH_VERTICES, patch.GetDescriptor().GetNumControlVertices());
reinterpret_cast<void *>(patch.firstIndex *
sizeof(unsigned int)));
} }
glDrawElements(primType,
patch.GetNumIndices(), GL_UNSIGNED_INT,
reinterpret_cast<void *>(patch.GetVertIndex() *
sizeof(unsigned int)));
CHECK_GL_ERROR("post draw\n"); CHECK_GL_ERROR("post draw\n");
} }
@ -782,14 +779,14 @@ OpenSubdivShader::updateRegistry()
GLuint GLuint
OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext, OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext,
OpenSubdiv::OsdGLDrawContext *osdDrawContext, OpenSubdiv::OsdGLDrawContext *osdDrawContext,
const OpenSubdiv::OsdPatchArray & patch) const OpenSubdiv::OsdDrawContext::PatchArray & patch)
{ {
CHECK_GL_ERROR("bindProgram begin\n"); CHECK_GL_ERROR("bindProgram begin\n");
// Primitives are triangles for Loop subdivision, quads otherwise // Primitives are triangles for Loop subdivision, quads otherwise
Effect effect = (_scheme == OsdMeshData::kLoop) ? kTriFill : kQuadFill; Effect effect = kFill;
EffectDesc effectDesc( patch.desc, effect ); EffectDesc effectDesc( patch.GetDescriptor(), effect );
// Build shader // Build shader
EffectDrawRegistry::ConfigType * EffectDrawRegistry::ConfigType *
@ -828,13 +825,9 @@ OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext,
// Update and bind tessellation state // Update and bind tessellation state
struct Tessellation { struct Tessellation {
float TessLevel; float TessLevel;
int GregoryQuadOffsetBase;
int LevelBase;
} tessellationData; } tessellationData;
tessellationData.TessLevel = static_cast<float>(1 << _tessFactor); tessellationData.TessLevel = static_cast<float>(1 << _tessFactor);
tessellationData.GregoryQuadOffsetBase = patch.gregoryQuadOffsetBase;
tessellationData.LevelBase = patch.levelBase;
if (!g_tessellationUB) { if (!g_tessellationUB) {
glGenBuffers(1, &g_tessellationUB); glGenBuffers(1, &g_tessellationUB);
@ -932,30 +925,30 @@ OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext,
// GL texture buffers. These are managed by the DrawContext // GL texture buffers. These are managed by the DrawContext
// and must be bound for use by the program in addition to // and must be bound for use by the program in addition to
// any buffers used by the client/application shading code. // any buffers used by the client/application shading code.
if (osdDrawContext->vertexTextureBuffer) { if (osdDrawContext->GetVertexTextureBuffer()) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER, glBindTexture(GL_TEXTURE_BUFFER,
osdDrawContext->vertexTextureBuffer); osdDrawContext->GetVertexTextureBuffer());
} }
if (osdDrawContext->vertexValenceTextureBuffer) { if (osdDrawContext->GetVertexValenceTextureBuffer()) {
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER, glBindTexture(GL_TEXTURE_BUFFER,
osdDrawContext->vertexValenceTextureBuffer); osdDrawContext->GetVertexValenceTextureBuffer());
} }
if (osdDrawContext->quadOffsetTextureBuffer) { if (osdDrawContext->GetQuadOffsetsTextureBuffer()) {
glActiveTexture(GL_TEXTURE2); glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER, glBindTexture(GL_TEXTURE_BUFFER,
osdDrawContext->quadOffsetTextureBuffer); osdDrawContext->GetQuadOffsetsTextureBuffer());
} }
if (osdDrawContext->patchLevelTextureBuffer) { if (osdDrawContext->GetPatchParamTextureBuffer()) {
glActiveTexture(GL_TEXTURE3); glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER, glBindTexture(GL_TEXTURE_BUFFER,
osdDrawContext->patchLevelTextureBuffer); osdDrawContext->GetPatchParamTextureBuffer());
} }
if (osdDrawContext->fvarDataTextureBuffer) { if (osdDrawContext->GetFvarDataTextureBuffer()) {
glActiveTexture( GL_TEXTURE4 ); glActiveTexture(GL_TEXTURE4);
glBindTexture( GL_TEXTURE_BUFFER, glBindTexture(GL_TEXTURE_BUFFER,
osdDrawContext->fvarDataTextureBuffer ); osdDrawContext->GetFvarDataTextureBuffer() );
} }
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);

View File

@ -123,7 +123,7 @@ private:
GLuint bindTexture(const MString& filename, int textureUnit); GLuint bindTexture(const MString& filename, int textureUnit);
GLuint bindProgram(const MHWRender::MDrawContext & mDrawContext, GLuint bindProgram(const MHWRender::MDrawContext & mDrawContext,
OpenSubdiv::OsdGLDrawContext *osdDrawContext, OpenSubdiv::OsdGLDrawContext *osdDrawContext,
const OpenSubdiv::OsdPatchArray & patch); const OpenSubdiv::OsdDrawContext::PatchArray & patch);
// OSD attributes // OSD attributes
static MObject aLevel; static MObject aLevel;

View File

@ -170,7 +170,8 @@ void emitAdaptive(int index, vec3 normal, vec2 uvs[4])
#endif #endif
// Bi-linear interpolation within the patch // Bi-linear interpolation within the patch
vec2 st = input[index].v.patchCoord.st; output.v.patchCoord = input[index].v.patchCoord;
vec2 st = input[index].v.tessCoord;
output.v.patchCoord.st = output.v.patchCoord.st =
vec2( mix( mix(uvs[0].x, uvs[1].x, st.s ), mix(uvs[3].x, uvs[2].x, st.s ), st.t), vec2( mix( mix(uvs[0].x, uvs[1].x, st.s ), mix(uvs[3].x, uvs[2].x, st.s ), st.t),
mix( mix(uvs[0].y, uvs[1].y, st.s ), mix(uvs[3].y, uvs[2].y, st.s ), st.t) ); mix( mix(uvs[0].y, uvs[1].y, st.s ), mix(uvs[3].y, uvs[2].y, st.s ), st.t) );

View File

@ -157,6 +157,11 @@ public:
return _quadOffsetsTextureBuffer; return _quadOffsetsTextureBuffer;
} }
/// Returns the GL texture buffer containing fvar data
GLuint GetFvarDataTextureBuffer() const {
return _fvarDataTextureBuffer;
}
protected: protected:
GLuint _patchIndexBuffer; GLuint _patchIndexBuffer;

View File

@ -82,6 +82,7 @@ struct OutputVertex {
vec3 normal; vec3 normal;
vec3 tangent; vec3 tangent;
centroid vec4 patchCoord; // u, v, level, faceID centroid vec4 patchCoord; // u, v, level, faceID
centroid vec2 tessCoord; // tesscoord.st
noperspective vec4 edgeDistance; noperspective vec4 edgeDistance;
#if OSD_NUM_VARYINGS > 0 #if OSD_NUM_VARYINGS > 0
float varyings[OSD_NUM_VARYINGS]; float varyings[OSD_NUM_VARYINGS];
@ -191,6 +192,7 @@ int GetPatchLevel()
ivec2 p = input[0].v.ptexInfo.xy; \ ivec2 p = input[0].v.ptexInfo.xy; \
int lv = input[0].v.ptexInfo.z; \ int lv = input[0].v.ptexInfo.z; \
int rot = input[0].v.ptexInfo.w; \ int rot = input[0].v.ptexInfo.w; \
output.v.tessCoord.xy = uv; \
uv.xy = float(rot==0)*uv.xy \ uv.xy = float(rot==0)*uv.xy \
+ float(rot==1)*vec2(1.0-uv.y, uv.x) \ + float(rot==1)*vec2(1.0-uv.y, uv.x) \
+ float(rot==2)*vec2(1.0-uv.x, 1.0-uv.y) \ + float(rot==2)*vec2(1.0-uv.x, 1.0-uv.y) \