Exemple #1
0
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;
}