Esempio n. 1
0
// #### updateRegistry
//
//      Evaluates dirty flags and updates the effect registry if any
//      attributes have changed that require the shader to be rebuilt
//
void
OpenSubdivShader::updateRegistry()
{
    /* If adaptive flag has changed, update the effectRegistry accordingly */
    if (_adaptiveDirty) {
        g_effectRegistry.setIsAdaptive(_adaptive);
        _adaptiveDirty = false;
    }

    MHWRender::MRenderer *theRenderer = MHWRender::MRenderer::theRenderer();
    _theTextureManager = theRenderer->getTextureManager();

    /* If diffuse texture has changed, update the effectRegistry accordingly */
    if (_diffuseMapDirty) {
        GLuint diffMapId = bindTexture( _diffuseMapFile, DIFF_TEXTURE_UNIT );
        g_effectRegistry.setDiffuseId(diffMapId);
        _diffuseMapDirty = false;
    }

    /* If shader source has changed, update the effectRegistry accordingly */
    if (_shaderSourceDirty) {
        if ( _shaderSource.empty() ) {
            if ( g_effectRegistry.getShaderSource() != defaultShaderSource ) {
                g_effectRegistry.setShaderSource(defaultShaderSource);
            }
        } else {
            if ( g_effectRegistry.getShaderSource() != _shaderSource ) {
                g_effectRegistry.setShaderSource(_shaderSource);
            }
        }
        _shaderSourceDirty = false;
    }
}
GLuint
OpenSubdivPtexShader::bindProgram(const MHWRender::MDrawContext &     mDrawContext,
                                  OpenSubdiv::OsdGLDrawContext *osdDrawContext,
                                  const OpenSubdiv::OsdPatchArray &   patch)
{

    CHECK_GL_ERROR("bindProgram begin\n");

    // Build shader
    Effect effect;
    effect.color = _enableColor;
    effect.occlusion = _enableOcclusion;
    effect.displacement = _enableDisplacement;
    effect.normal = _enableNormal;
    EffectDesc effectDesc( patch.desc, effect );
    EffectDrawRegistry::ConfigType *
    config = 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;
        int GregoryQuadOffsetBase;
        int PrimitiveIdBase;
    } tessellationData;

    tessellationData.TessLevel = static_cast<float>(1 << _tessFactor);
    tessellationData.GregoryQuadOffsetBase = patch.GetQuadOffsetBase;
    tessellationData.PrimitiveIdBase = patch.GetPatchIndex();;

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


#ifdef USE_NON_IMAGE_BASED_LIGHTING
    // 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 < 1; ++i) {
        MFloatPointArray positions;
        MFloatVector direction;
        float intensity;
        MColor color;
        bool hasDirection, hasPosition;
        mDrawContext.getLightInformation(i, positions, direction, intensity,
                                         color, hasDirection, hasPosition);

        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);
#endif

    GLint eye = glGetUniformLocation(program, "eyePositionInWorld");
    MPoint e = MPoint(0, 0, 0) *
               mDrawContext.getMatrix(MHWRender::MDrawContext::kWorldViewInverseMtx);
    glProgramUniform3f(program, eye,
                       static_cast<float>(e.x),
                       static_cast<float>(e.y),
                       static_cast<float>(e.z));

    // 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, "fresnelBias"),
                       _fresnelBias);
    glProgramUniform1f(program,
                       glGetUniformLocation(program, "fresnelScale"),
                       _fresnelScale);
    glProgramUniform1f(program,
                       glGetUniformLocation(program, "fresnelPower"),
                       _fresnelPower);


    // Ptex bindings
    // color ptex
    if (effectRegistry.getPtexColorValid()) {
        GLint texData = glGetUniformLocation(program, "textureImage_Data");
        glProgramUniform1i(program, texData, CLR_TEXTURE_UNIT + 0);
        GLint texPacking = glGetUniformLocation(program, "textureImage_Packing");
        glProgramUniform1i(program, texPacking, CLR_TEXTURE_UNIT + 1);
        GLint texPages = glGetUniformLocation(program, "textureImage_Pages");
        glProgramUniform1i(program, texPages, CLR_TEXTURE_UNIT + 2);
    }

    // displacement ptex
    if (effectRegistry.getPtexDisplacementValid()) {
        GLint texData = glGetUniformLocation(program, "textureDisplace_Data");
        glProgramUniform1i(program, texData, DISP_TEXTURE_UNIT + 0);
        GLint texPacking = glGetUniformLocation(program, "textureDisplace_Packing");
        glProgramUniform1i(program, texPacking, DISP_TEXTURE_UNIT + 1);
        GLint texPages = glGetUniformLocation(program, "textureDisplace_Pages");
        glProgramUniform1i(program, texPages, DISP_TEXTURE_UNIT + 2);
    }

    // occlusion ptex
    if (effectRegistry.getPtexOcclusionValid()) {
        GLint texData = glGetUniformLocation(program, "textureOcclusion_Data");
        glProgramUniform1i(program, texData, OCC_TEXTURE_UNIT + 0);
        GLint texPacking = glGetUniformLocation(program, "textureOcclusion_Packing");
        glProgramUniform1i(program, texPacking, OCC_TEXTURE_UNIT + 1);
        GLint texPages = glGetUniformLocation(program, "textureOcclusion_Pages");
        glProgramUniform1i(program, texPages, OCC_TEXTURE_UNIT + 2);
    }

    // diffuse environment map
    if (effectRegistry.getDiffuseEnvironmentId() != 0) {
        GLint difmap = glGetUniformLocation(program, "diffuseEnvironmentMap");
        glProgramUniform1i(program, difmap, DIFF_TEXTURE_UNIT);
    }

    // specular environment map
    if (effectRegistry.getSpecularEnvironmentId() != 0) {
        GLint envmap = glGetUniformLocation(program, "specularEnvironmentMap");
        glProgramUniform1i(program, envmap, ENV_TEXTURE_UNIT);
    }

    glActiveTexture(GL_TEXTURE0);

    CHECK_GL_ERROR("bindProgram leave\n");

    return program;
}
//
//      updateRegistry
//
//      When attributes change which affect the shader compilation the
//      effectRegistry needs to be updated with the new values
//
void
OpenSubdivPtexShader::updateRegistry()
{
    // adaptive toggle
    if (_adaptiveDirty) {
        effectRegistry.setIsAdaptive(_adaptive);
        _adaptiveDirty = false;
    }

    // ptex color file
    if (_ptexColorDirty) {
        bool ptexColorValid = bindPtexTexture(_colorFile, &_ptexColor, CLR_TEXTURE_UNIT);
        effectRegistry.setPtexColorValid(ptexColorValid);
        _ptexColorDirty = false;
    }

    // ptex displacement file
    if (_ptexDisplacementDirty) {
        bool ptexDisplacementValid = bindPtexTexture(_displacementFile, &_ptexDisplacement, DISP_TEXTURE_UNIT);
        effectRegistry.setPtexDisplacementValid(ptexDisplacementValid);
        _ptexDisplacementDirty = false;
    }

    // ptex occlusion file
    if (_ptexOcclusionDirty) {
        bool ptexOcclusionValid = bindPtexTexture(_occlusionFile, &_ptexOcclusion, OCC_TEXTURE_UNIT);
        effectRegistry.setPtexOcclusionValid(ptexOcclusionValid);
        _ptexOcclusionDirty = false;
    }


    MHWRender::MRenderer *theRenderer = MHWRender::MRenderer::theRenderer();
    _theTextureManager = theRenderer->getTextureManager();

    // diffuse environment map file
    if (_diffEnvMapDirty) {
        GLuint diffEnvMapId = bindTexture( _diffEnvMapFile, DIFF_TEXTURE_UNIT );
        effectRegistry.setDiffuseEnvironmentId(diffEnvMapId);
        _diffEnvMapDirty = false;
    }

    // specular environment map file
    if (_specEnvMapDirty) {
        GLuint specEnvMapId = bindTexture( _specEnvMapFile, ENV_TEXTURE_UNIT );
        effectRegistry.setSpecularEnvironmentId(specEnvMapId);
        _specEnvMapDirty = false;
    }

    // shader source
    if (_shaderSourceDirty) {
        if ( _shaderSource.empty() ) {
            if ( effectRegistry.getShaderSource() != defaultShaderSource ) {
                effectRegistry.setShaderSource(defaultShaderSource);
            }
        } else {
            if ( effectRegistry.getShaderSource() != _shaderSource ) {
                effectRegistry.setShaderSource(_shaderSource);
            }
        }
        _shaderSourceDirty = false;
    }
}
Esempio n. 4
0
// #### 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;
}