improved glViewer shaders for Loop

Removed the use of the LOOP preprocessor symbol from
the glFVarViewer shaders code. The shader code is now
configured according to the types of the resulting patches
without depending on the subdivision scheme of the mesh
topology.

Improved the implementation of face-varying interpolation
similar to the glFVarViewer. Now the face-varying patch
type is obtained from the face-varying patch array
descriptor instead of being hard-coded by subdivison scheme.
This commit is contained in:
David G Yu 2019-06-17 17:17:20 -07:00
parent 5d33f7c28e
commit 9fe1284ae3
2 changed files with 92 additions and 38 deletions

View File

@ -233,7 +233,9 @@ GLuint g_transformUB = 0,
g_tessellationUB = 0,
g_tessellationBinding = 1,
g_lightingUB = 0,
g_lightingBinding = 2;
g_lightingBinding = 2,
g_fvarArrayDataUB = 0,
g_fvarArrayDataBinding = 3;
struct Transform {
float ModelViewMatrix[16];
@ -251,7 +253,7 @@ GLuint g_vao = 0;
struct FVarData
{
FVarData() :
textureBuffer(0) {
textureBuffer(0), textureParamBuffer(0) {
}
~FVarData() {
Release();
@ -260,11 +262,17 @@ 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();
// expand fvardata to per-patch array
std::vector<float> data;
@ -289,8 +297,22 @@ struct FVarData
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &buffer);
Far::ConstPatchParamArray fvarParam = patchTable->GetFVarPatchParams();
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);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &buffer);
}
GLuint textureBuffer;
GLuint textureBuffer, textureParamBuffer;
} g_fvarData;
//------------------------------------------------------------------------------
@ -780,11 +802,6 @@ public:
break;
}
if (type == Far::PatchDescriptor::TRIANGLES ||
type == Far::PatchDescriptor::LOOP ||
type == Far::PatchDescriptor::GREGORY_TRIANGLE) {
ss << "#define LOOP\n";
}
if (type != Far::PatchDescriptor::TRIANGLES &&
type != Far::PatchDescriptor::QUADS) {
ss << "#define SMOOTH_NORMALS\n";
@ -869,6 +886,10 @@ public:
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_lightingBinding);
uboIndex = glGetUniformBlockIndex(program, "OsdFVarArrayData");
if (uboIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, uboIndex, g_fvarArrayDataBinding);
// assign texture locations
GLint loc;
glUseProgram(program);
@ -878,16 +899,19 @@ public:
if ((loc = glGetUniformLocation(program, "OsdFVarDataBuffer")) != -1) {
glUniform1i(loc, 1); // GL_TEXTURE1
}
// for legacy gregory patches
if ((loc = glGetUniformLocation(program, "OsdVertexBuffer")) != -1) {
if ((loc = glGetUniformLocation(program, "OsdFVarParamBuffer")) != -1) {
glUniform1i(loc, 2); // GL_TEXTURE2
}
if ((loc = glGetUniformLocation(program, "OsdValenceBuffer")) != -1) {
// for legacy gregory patches
if ((loc = glGetUniformLocation(program, "OsdVertexBuffer")) != -1) {
glUniform1i(loc, 3); // GL_TEXTURE3
}
if ((loc = glGetUniformLocation(program, "OsdQuadOffsetBuffer")) != -1) {
if ((loc = glGetUniformLocation(program, "OsdValenceBuffer")) != -1) {
glUniform1i(loc, 4); // GL_TEXTURE4
}
if ((loc = glGetUniformLocation(program, "OsdQuadOffsetBuffer")) != -1) {
glUniform1i(loc, 5); // GL_TEXTURE5
}
glUseProgram(0);
return config;
@ -899,6 +923,9 @@ ShaderCache g_shaderCache;
//------------------------------------------------------------------------------
static void
updateUniformBlocks() {
using namespace OpenSubdiv;
if (! g_transformUB) {
glGenBuffers(1, &g_transformUB);
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
@ -932,6 +959,29 @@ updateUniformBlocks() {
glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB);
// Update and bind fvar patch array state
if (g_mesh->GetPatchTable()->GetNumFVarChannels() > 0) {
Osd::PatchArrayVector const &fvarPatchArrays =
g_mesh->GetPatchTable()->GetFVarPatchArrays();
// bind patch arrays UBO (std140 struct size padded to vec4 alignment)
int patchArraySize =
sizeof(GLint) * ((sizeof(Osd::PatchArray)/sizeof(GLint) + 3) & ~3);
if (!g_fvarArrayDataUB) {
glGenBuffers(1, &g_fvarArrayDataUB);
}
glBindBuffer(GL_UNIFORM_BUFFER, g_fvarArrayDataUB);
glBufferData(GL_UNIFORM_BUFFER,
fvarPatchArrays.size()*patchArraySize, NULL, GL_STATIC_DRAW);
for (int i=0; i<(int)fvarPatchArrays.size(); ++i) {
glBufferSubData(GL_UNIFORM_BUFFER,
i*patchArraySize, sizeof(Osd::PatchArray), &fvarPatchArrays[i]);
}
glBindBufferBase(GL_UNIFORM_BUFFER,
g_fvarArrayDataBinding, g_fvarArrayDataUB);
}
// Update and bind lighting state
struct Lighting {
struct Light {
@ -978,17 +1028,20 @@ bindTextures() {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_BUFFER,
g_fvarData.textureBuffer);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER,
g_fvarData.textureParamBuffer);
}
// legacy gregory
if (g_legacyGregoryPatchTable) {
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_BUFFER,
g_legacyGregoryPatchTable->GetVertexTextureBuffer());
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_BUFFER,
g_legacyGregoryPatchTable->GetVertexValenceTextureBuffer());
g_legacyGregoryPatchTable->GetVertexTextureBuffer());
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_BUFFER,
g_legacyGregoryPatchTable->GetVertexValenceTextureBuffer());
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_BUFFER,
g_legacyGregoryPatchTable->GetQuadOffsetsTextureBuffer());
}

View File

@ -179,23 +179,29 @@ out block {
OSD_USER_VARYING_DECLARE
} outpt;
uniform isamplerBuffer OsdFVarParamBuffer;
layout(std140) uniform OsdFVarArrayData {
OsdPatchArray fvarPatchArray[2];
};
vec2
interpolateFaceVarying(vec2 uv, int fvarOffset)
{
int patchIndex = OsdGetPatchIndex(gl_PrimitiveID);
OsdPatchArray array = fvarPatchArray[0];
ivec3 fvarPatchParam = texelFetch(OsdFVarParamBuffer, patchIndex).xyz;
OsdPatchParam param = OsdPatchParamInit(fvarPatchParam.x,
fvarPatchParam.y,
fvarPatchParam.z);
int patchType = OsdPatchParamIsRegular(param) ? array.regDesc : array.desc;
float wP[20], wDu[20], wDv[20], wDuu[20], wDuv[20], wDvv[20];
#ifdef LOOP
int patchType = OSD_PATCH_DESCRIPTOR_TRIANGLES;
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
#else
int patchType = OSD_PATCH_DESCRIPTOR_QUADS;
OsdPatchParam param = OsdPatchParamInit(0, 0, 0);
int numPoints = OsdEvaluatePatchBasisNormalized(patchType, param,
uv.s, uv.t, wP, wDu, wDv, wDuu, wDuv, wDvv);
#endif
int patchArrayStride = numPoints;
int primOffset = patchIndex * patchArrayStride;
@ -230,27 +236,22 @@ void emit(int index, vec3 normal)
#endif
#ifdef SHADING_FACEVARYING_COLOR
#ifdef LOOP // ----- scheme : LOOP
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
// interpolate fvar data at refined tri or quad vertex locations
#ifdef PRIM_TRI
vec2 trist[3] = vec2[](vec2(0,0), vec2(1,0), vec2(0,1));
vec2 st = trist[index];
#else
vec2 st = inpt[index].v.tessCoord;
#endif
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
#else // ----- scheme : CATMARK / BILINEAR
#ifdef SHADING_FACEVARYING_UNIFORM_SUBDIVISION
#ifdef PRIM_QUAD
vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
vec2 st = quadst[index];
#endif
#else
// interpolate fvar data at tessellated vertex locations
vec2 st = inpt[index].v.tessCoord;
#endif
vec2 uv = interpolateFaceVarying(st, /*fvarOffset=*/0);
#endif // ------ scheme
vec2 uv = interpolateFaceVarying(st, /*fvarOffset*/0);
outpt.color = vec3(uv.s, uv.t, 0);
#endif
@ -502,7 +503,7 @@ getAdaptivePatchColor(ivec3 patchParam)
patchType = 3; // CORNER (not correct for patches that are not isolated)
}
#if defined(OSD_PATCH_ENABLE_SINGLE_CREASE) && !defined(LOOP)
#if defined OSD_PATCH_ENABLE_SINGLE_CREASE
// check this after boundary/corner since single crease patch also has edgeCount.
if (inpt.vSegments.y > 0) {
patchType = 1;