void MyDrawDelegate::DrawElements(OpenSubdiv::OsdDrawContext::PatchArray const &patchArray) { // bind patchType-wise effect state // can be skipped (if config is not changed) MyDrawConfig *config = GetDrawConfig(_currentEffect, patchArray.GetDescriptor()); GLuint program = config->program; if (true /* if config is different from previous call */) { glUseProgram(program); #if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0) glPatchParameteri(GL_PATCH_VERTICES, patchArray.GetDescriptor().GetNumControlVertices()); #endif // bind patchArray state and draw } // apply patch color _currentEffect->BindDrawConfig(config, patchArray.GetDescriptor()); glUniform1i(config->primitiveIdBaseUniform, patchArray.GetPatchIndex()); if (patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::GREGORY || patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::GREGORY_BOUNDARY){ glUniform1i(config->gregoryQuadOffsetBaseUniform, patchArray.GetQuadOffsetIndex()); } if (patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::QUADS) { glDrawElements(GL_LINES_ADJACENCY, patchArray.GetNumIndices(), GL_UNSIGNED_INT, (void*)(patchArray.GetVertIndex()*sizeof(GLuint))); } else if (patchArray.GetDescriptor().GetType() == OpenSubdiv::FarPatchTables::TRIANGLES) { glDrawElements(GL_TRIANGLES, patchArray.GetNumIndices(), GL_UNSIGNED_INT, (void*)(patchArray.GetVertIndex()*sizeof(GLuint))); } else { #if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0) glDrawElements(GL_PATCHES, patchArray.GetNumIndices(), GL_UNSIGNED_INT, (void*)(patchArray.GetVertIndex()*sizeof(GLuint))); #endif } _numDrawCalls++; }
// #### bindProgram // // Do all the work to build and install shader including // set up buffer blocks for uniform variables, set up // default lighting parameters, pass material uniforms // and bind texture buffers used by texture maps and by // OpenSubdiv's built-in shading code. // GLuint OpenSubdivShader::bindProgram(const MHWRender::MDrawContext & mDrawContext, OpenSubdiv::OsdGLDrawContext *osdDrawContext, const OpenSubdiv::OsdDrawContext::PatchArray & patch) { CHECK_GL_ERROR("bindProgram begin\n"); // Primitives are triangles for Loop subdivision, quads otherwise Effect effect = kFill; EffectDesc effectDesc( patch.GetDescriptor(), effect ); // Build shader EffectDrawRegistry::ConfigType * config = g_effectRegistry.GetDrawConfig(effectDesc); // Install shader GLuint program = config->program; glUseProgram(program); // Update and bind transform state struct Transform { float ModelViewMatrix[16]; float ProjectionMatrix[16]; float ModelViewProjectionMatrix[16]; } transformData; setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx), transformData.ModelViewMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kProjectionMtx), transformData.ProjectionMatrix); setMatrix(mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewProjMtx), transformData.ModelViewProjectionMatrix); if (!g_transformUB) { glGenBuffers(1, &g_transformUB); glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(transformData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(transformData), &transformData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_transformBinding, g_transformUB); // Update and bind tessellation state struct Tessellation { float TessLevel; } tessellationData; tessellationData.TessLevel = static_cast<float>(1 << _tessFactor); if (!g_tessellationUB) { glGenBuffers(1, &g_tessellationUB); glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(tessellationData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(tessellationData), &tessellationData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB); // Update and bind lighting state int numLights = mDrawContext.numberOfActiveLights(); struct Lighting { struct Light { float position[4]; float diffuse[4]; float ambient[4]; float specular[4]; } lightSource[2]; } lightingData; memset(&lightingData, 0, sizeof(lightingData)); for (int i = 0; i < numLights && i < 2; ++i) { MFloatPointArray positions; MFloatVector direction; float intensity; MColor color; bool hasDirection, hasPosition; mDrawContext.getLightInformation(i, positions, direction, intensity, color, hasDirection, hasPosition); MMatrix modelView = mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewMtx); direction = MVector(direction) * modelView; Lighting::Light &light = lightingData.lightSource[i]; if (hasDirection) { light.position[0] = -direction[0]; light.position[1] = -direction[1]; light.position[2] = -direction[2]; for (int j = 0; j < 4; ++j) { light.diffuse[j] = color[j] * intensity; light.ambient[j] = color[j] * intensity; light.specular[j] = color[j] * intensity; } } } if (!g_lightingUB) { glGenBuffers(1, &g_lightingUB); glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferData(GL_UNIFORM_BUFFER, sizeof(lightingData), NULL, GL_STATIC_DRAW); }; glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightingData), &lightingData); glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBufferBase(GL_UNIFORM_BUFFER, g_lightingBinding, g_lightingUB); // Update other uniforms float color[4] = { 0, 0, 0, 1 }; _diffuse.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "diffuseColor"), 1, color); _ambient.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "ambientColor"), 1, color); _specular.get(color); glProgramUniform4fv(program, glGetUniformLocation(program, "specularColor"), 1, color); glProgramUniform1f(program, glGetUniformLocation(program, "shininess"), _shininess); // Bind diffuse map if (g_effectRegistry.getDiffuseId()!=0) { GLint difmap = glGetUniformLocation(program, "diffuseMap"); glProgramUniform1i(program, difmap, DIFF_TEXTURE_UNIT); } // Bind all texture buffers // OpenSubdiv's geometric shading code depends on additional // GL texture buffers. These are managed by the DrawContext // and must be bound for use by the program in addition to // any buffers used by the client/application shading code. if (osdDrawContext->GetVertexTextureBuffer()) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetVertexTextureBuffer()); } if (osdDrawContext->GetVertexValenceTextureBuffer()) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetVertexValenceTextureBuffer()); } if (osdDrawContext->GetQuadOffsetsTextureBuffer()) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetQuadOffsetsTextureBuffer()); } if (osdDrawContext->GetPatchParamTextureBuffer()) { glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetPatchParamTextureBuffer()); } if (osdDrawContext->GetFvarDataTextureBuffer()) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_BUFFER, osdDrawContext->GetFvarDataTextureBuffer() ); } glActiveTexture(GL_TEXTURE0); CHECK_GL_ERROR("bindProgram leave\n"); return program; }