Пример #1
0
bool
UsdGeomPrimvarsAPI::HasPossiblyInheritedPrimvar(const TfToken &name) const
{
    TRACE_FUNCTION();

    UsdPrim prim = GetPrim();
    if (!prim) {
        TF_CODING_ERROR("HasPossiblyInheritedPrimvar called on invalid prim: %s", 
                        UsdDescribe(prim).c_str());
        return false;
    }
    UsdGeomPrimvar  pv = GetPrimvar(name);
    if (pv.HasAuthoredValue()){
        return true;
    }

    const TfToken attrName = UsdGeomPrimvar::_MakeNamespaced(name);
    if (attrName.IsEmpty()) {
        return false;
    }
    for (prim = prim.GetParent(); prim && !prim.IsPseudoRoot();
         prim = prim.GetParent()) {
        UsdAttribute attr = prim.GetAttribute(attrName);
        if (attr.HasAuthoredValue() && UsdGeomPrimvar::IsPrimvar(attr)) {
            // Only constant primvars can be inherited.
            // Non-constant interpolation blocks inheritance.
            return UsdGeomPrimvar(attr).GetInterpolation()
                == UsdGeomTokens->constant;
        }
    }
    return false;
}
Пример #2
0
static
void _DoAddNewPrimSpec(
    const SdfLayerHandle& destLayer, const _SpecDataEntry& specData)
{
    // Need to determine whether this property is considered inert when
    // being initially created based on fields being copied in. This mimics
    // what's done in the SdfPrimSpec constructor.
    TfToken type;
    SdfSpecifier specifier = SdfSpecifierOver;
    for (const _FieldValuePair& fieldValue : specData.dataToCopy) {
        if (fieldValue.second.IsEmpty()) {
            continue;
        }

        if (fieldValue.first == SdfFieldKeys->TypeName) {
            type = fieldValue.second.Get<TfToken>();
        }
        else if (fieldValue.first == SdfFieldKeys->Specifier) {
            specifier = fieldValue.second.Get<SdfSpecifier>();
        }
    }

    const bool inert = (specifier == SdfSpecifierOver && type.IsEmpty());
    Sdf_ChildrenUtils<Sdf_PrimChildPolicy>::CreateSpec(
        destLayer, specData.dstPath, SdfSpecTypePrim,
        /* inert = */ inert);
}
Пример #3
0
UsdGeomXformOp::UsdGeomXformOp(
    UsdPrim const& prim, 
    UsdGeomXformOp::Type const opType,
    UsdGeomXformOp::Precision const precision, 
    TfToken const &opSuffix,
    bool isInverseOp)
    : _opType(opType)
    , _isInverseOp(isInverseOp)
{
    // Determine the typeName of the xformOp attribute to be created.
    const SdfValueTypeName &typeName = GetValueTypeName(opType, precision);

    if (!typeName) { 
        TF_CODING_ERROR("Invalid xform-op: incompatible combination of "
            "opType (%s) and precision (%s).", 
            TfEnum::GetName(opType).c_str(),
            TfEnum::GetName(precision).c_str());
        return;
    } 

    TfToken attrName = UsdGeomXformOp::GetOpName(opType, opSuffix, 
        // isInverseOp is handled below
        /*isInverseOp*/ false);

    // attrName can never be empty.
    TF_VERIFY(!attrName.IsEmpty());

    // Create an  attribute in the xformOp: namespace with the
    // computed typeName.
    _attr = prim.CreateAttribute(attrName, typeName, /* custom */ false);

    // If a problem occurred, an error should already have been issued,
    // and _attr will be invalid, which is what we want
}
Пример #4
0
PXR_NAMESPACE_CLOSE_SCOPE

// ===================================================================== //
// Feel free to add custom code below this line. It will be preserved by
// the code generator.
//
// Just remember to wrap code in the appropriate delimiters:
// 'PXR_NAMESPACE_OPEN_SCOPE', 'PXR_NAMESPACE_CLOSE_SCOPE'.
// ===================================================================== //
// --(BEGIN CUSTOM CODE)--

PXR_NAMESPACE_OPEN_SCOPE

UsdGeomPrimvar 
UsdGeomPrimvarsAPI::CreatePrimvar(const TfToken& attrName,
                                const SdfValueTypeName &typeName,
                                const TfToken& interpolation,
                                int elementSize) const
{
    const UsdPrim &prim = GetPrim();

    UsdGeomPrimvar primvar(prim, attrName, typeName);

    if (primvar){
        if (!interpolation.IsEmpty())
            primvar.SetInterpolation(interpolation);
        if (elementSize > 0)
            primvar.SetElementSize(elementSize);
    }
    // otherwise, errors have already been issued
    return primvar;
}
Пример #5
0
TfToken 
UsdGeomCollectionAPI::_GetCollectionPropertyName(
    const TfToken &baseName /* =TfToken() */) const
{
    return TfToken(UsdGeomTokens->collection.GetString() + ":" + 
                   _name.GetString() + 
                   (baseName.IsEmpty() ? "" : (":" + baseName.GetString())));
}
Пример #6
0
bool
UsdGeomPrimvarsAPI::HasPrimvar(const TfToken &name) const
{
    TfToken primvarName = UsdGeomPrimvar::_MakeNamespaced(name, /* quiet */true);
    const UsdPrim &prim = GetPrim();
    if (!prim) {
        TF_CODING_ERROR("HasPrimvar called on invalid prim: %s", 
                        UsdDescribe(prim).c_str());
        return false;
    }
    return primvarName.IsEmpty() ? false : 
        UsdGeomPrimvar::IsPrimvar(prim.GetAttribute(primvarName));
}
Пример #7
0
/* static */
UsdSkelInbetweenShape
UsdSkelInbetweenShape::_Create(const UsdPrim& prim, const TfToken& name)
{
    if(TF_VERIFY(prim)) {
        TfToken attrName = _MakeNamespaced(name);

        if(!attrName.IsEmpty()) {
            return UsdSkelInbetweenShape(
                prim.CreateAttribute(attrName, SdfValueTypeNames->Point3fArray,
                                     /*custom*/ false, SdfVariabilityUniform));
        }
    }
    return UsdSkelInbetweenShape();
}
Пример #8
0
/* static */
TfToken 
UsdGeomXformOp::GetOpName(
    const Type opType, 
    const TfToken &opSuffix,
    bool isInverseOp)
{
    TfToken opName = _MakeNamespaced(GetOpTypeToken(opType));

    if (!opSuffix.IsEmpty())
        opName = TfToken(opName.GetString() + ":" + opSuffix.GetString());

    if (isInverseOp)
        opName = TfToken(_tokens->invertPrefix.GetString() + opName.GetString());

    return opName;
}
Пример #9
0
UsdGeomPrimvar::UsdGeomPrimvar(const UsdPrim& prim, 
                               const TfToken& baseName,
                               const SdfValueTypeName &typeName,
                               bool custom)
{
    TF_VERIFY(prim);

    TfToken attrName = _MakeNamespaced(baseName);

    if (!attrName.IsEmpty()){
        _attr = prim.CreateAttribute(attrName, typeName, custom);
    }
    // If a problem occurred, an error should already have been issued,
    // and _attr will be invalid, which is what we want

    _SetIdTargetRelName();
}
Пример #10
0
/* static */
bool 
PxrUsdKatanaUsdInPluginRegistry::_DoFindKind(
        const TfToken& kind,
        std::string* opName,
        const _KindRegistry& reg)
{
    // can cache this if it becomes an issue.
    for (TfToken currKind = kind;
            not currKind.IsEmpty();
            currKind = KindRegistry::GetBaseKind(currKind)) {
        if (TfMapLookup(reg, currKind, opName)) {
            return true;
        }
    }

    return false;
}
Пример #11
0
/* static */
bool 
PxrUsdKatanaUsdInPluginRegistry::_DoFindKind(
        const TfToken& kind,
        std::string* opName,
        const _KindRegistry& reg)
{
    // can cache this if it becomes an issue.
    TfToken currKind = kind;
    while (!currKind.IsEmpty()) {
        if (TfMapLookup(reg, currKind, opName)) {
            return true;
        }
        if (KindRegistry::HasKind(currKind)) {
            currKind = KindRegistry::GetBaseKind(currKind);
        }
        else {
            FnLogWarn(TfStringPrintf("Unknown kind: '%s'", currKind.GetText()));
            return false;
        }
    }

    return false;
}
Пример #12
0
HdTextureResourceSharedPtr
UsdImagingGL_GetTextureResource(UsdPrim const& usdPrim,
                                SdfPath const& usdPath,
                                UsdTimeCode time)
{
    if (!TF_VERIFY(usdPrim))
        return HdTextureResourceSharedPtr();
    if (!TF_VERIFY(usdPath != SdfPath()))
        return HdTextureResourceSharedPtr();

    UsdAttribute attr = _GetTextureResourceAttr(usdPrim, usdPath);
    SdfAssetPath asset;
    if (!TF_VERIFY(attr) || !TF_VERIFY(attr.Get(&asset, time))) {
        return HdTextureResourceSharedPtr();
    }

    HdTextureType textureType = HdTextureType::Uv;

    TfToken filePath = TfToken(asset.GetResolvedPath());
    // If the path can't be resolved, it's either an UDIM texture
    // or the texture doesn't exists and we can to exit early.
    if (filePath.IsEmpty()) {
        filePath = TfToken(asset.GetAssetPath());
        if (GlfIsSupportedUdimTexture(filePath)) {
            textureType = HdTextureType::Udim;
        } else {
            TF_DEBUG(USDIMAGING_TEXTURES).Msg(
                "File does not exist, returning nullptr");
            TF_WARN("Unable to find Texture '%s' with path '%s'.",
                    filePath.GetText(), usdPath.GetText());
            return {};
        }
    } else {
        if (GlfIsSupportedPtexTexture(filePath)) {
            textureType = HdTextureType::Ptex;
        }
    }

    GlfImage::ImageOriginLocation origin =
            UsdImagingGL_ComputeTextureOrigin(usdPrim);

    HdWrap wrapS = _GetWrapS(usdPrim, textureType);
    HdWrap wrapT = _GetWrapT(usdPrim, textureType);
    HdMinFilter minFilter = _GetMinFilter(usdPrim);
    HdMagFilter magFilter = _GetMagFilter(usdPrim);
    float memoryLimit = _GetMemoryLimit(usdPrim);

    TF_DEBUG(USDIMAGING_TEXTURES).Msg(
            "Loading texture: id(%s), type(%s)\n",
            usdPath.GetText(),
            textureType == HdTextureType::Uv ? "Uv" :
            textureType == HdTextureType::Ptex ? "Ptex" : "Udim");
 
    HdTextureResourceSharedPtr texResource;
    TfStopwatch timer;
    timer.Start();
    // Udim's can't be loaded through like other textures, because
    // we can't select the right factory based on the file type.
    // We also need to pass the layer context to the factory,
    // so each file gets resolved properly.
    GlfTextureHandleRefPtr texture;
    if (textureType == HdTextureType::Udim) {
        UdimTextureFactory factory(_FindLayerHandle(attr, time));
        texture = GlfTextureRegistry::GetInstance().GetTextureHandle(
            filePath, origin, &factory);
    } else {
        texture = GlfTextureRegistry::GetInstance().GetTextureHandle(
            filePath, origin);
    }

    texResource = HdTextureResourceSharedPtr(
        new HdStSimpleTextureResource(texture, textureType, wrapS, wrapT,
                                      minFilter, magFilter, memoryLimit));
    timer.Stop();

    TF_DEBUG(USDIMAGING_TEXTURES).Msg("    Load time: %.3f s\n", 
                                     timer.GetSeconds());

    return texResource;
}
Пример #13
0
void
Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, 
                                    bool isMasterPrim)
{
    // Special-case the root (the only prim which has no parent) and
    // instancing masters.
    if (ARCH_UNLIKELY(not parent or isMasterPrim)) {
        _flags[Usd_PrimActiveFlag] = true;
        _flags[Usd_PrimLoadedFlag] = true;
        _flags[Usd_PrimModelFlag] = true;
        _flags[Usd_PrimGroupFlag] = true;
        _flags[Usd_PrimAbstractFlag] = false;
        _flags[Usd_PrimDefinedFlag] = true;
        _flags[Usd_PrimClipsFlag] = false;
        _flags[Usd_PrimInstanceFlag] = false;
        _flags[Usd_PrimMasterFlag] = isMasterPrim;
    } 
    else {
        // Compose and cache 'active'.
        UsdPrim self(Usd_PrimDataIPtr(this));
        bool active = true;
        self.GetMetadata(SdfFieldKeys->Active, &active);
        _flags[Usd_PrimActiveFlag] = active;

        // An active prim is loaded if it's loadable and in the load set, or
        // it's not loadable and its parent is loaded.
        _flags[Usd_PrimLoadedFlag] = active and
            (self.HasPayload() ?
             _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) :
             parent->IsLoaded());

        // According to Model hierarchy rules, only Model Groups may have Model
        // children (groups or otherwise).  So if our parent is not a Model
        // Group, then this prim cannot be a model (or a model group).
        // Otherwise we look up the kind metadata and consult the kind registry.
        _flags[Usd_PrimGroupFlag] = _flags[Usd_PrimModelFlag] = false;
        if (parent->IsGroup()) {
            static TfToken kindToken("kind");
            TfToken kind;
            self.GetMetadata(kindToken, &kind);

            // Use the kind registry to determine model/groupness.
            if (not kind.IsEmpty()) {
                _flags[Usd_PrimGroupFlag] = 
                    KindRegistry::IsA(kind, KindTokens->group);
                _flags[Usd_PrimModelFlag] = _flags[Usd_PrimGroupFlag] or
                    KindRegistry::IsA(kind, KindTokens->model);
            }
        }

        // Get specifier.
        SdfSpecifier specifier = GetSpecifier();

        // This prim is abstract if its parent is or if it's a class.
        _flags[Usd_PrimAbstractFlag] =
            parent->IsAbstract() or specifier == SdfSpecifierClass;

        // This prim is defined if its parent is defined and its specifier is
        // defining.
        const bool specifierIsDefining = SdfIsDefiningSpecifier(specifier);
        _flags[Usd_PrimDefinedFlag] =
            parent->IsDefined() and specifierIsDefining; 
        _flags[Usd_PrimHasDefiningSpecifierFlag] = specifierIsDefining;

        // The presence of clips that may affect attributes on this prim
        // is computed and set in UsdStage. Default to false.
        _flags[Usd_PrimClipsFlag] = false;

        // These flags indicate whether this prim is an instance or an
        // instance master.
        _flags[Usd_PrimInstanceFlag] = active and _primIndex->IsInstanceable();
        _flags[Usd_PrimMasterFlag] = parent->IsInMaster();
    }
}
Пример #14
0
// Walk the shader graph and emit nodes in topological order
// to avoid forward-references.
static
void _WalkGraph(UsdShadeShader const & shadeNode, 
               HdMaterialNetwork *materialNetwork,
               const TfTokenVector &shaderSourceTypes)
{
    // Store the path of the node
    HdMaterialNode node;
    node.path = shadeNode.GetPath();
    if (!TF_VERIFY(node.path != SdfPath::EmptyPath())) {
        return;
    }
    // If this node has already been found via another path, we do
    // not need to add it again.
    for (HdMaterialNode const& existingNode: materialNetwork->nodes) {
        if (existingNode.path == node.path) {
            return;
        }
    }

    // Visit the inputs of this node to ensure they are emitted first.
    const std::vector<UsdShadeInput> shadeNodeInputs = shadeNode.GetInputs();
    for (UsdShadeInput const& input: shadeNodeInputs) {
        // Check if this input is a connection and if so follow the path
        UsdShadeConnectableAPI source;
        TfToken sourceName;
        UsdShadeAttributeType sourceType;
        if (UsdShadeConnectableAPI::GetConnectedSource(input, 
                &source, &sourceName, &sourceType)) {
            // When we find a connection to a shading node output,
            // walk the upstream shading node.  Do not do this for
            // other sources (ex: a connection to a material
            // public interface parameter), since they are not
            // part of the shading node graph.
            if (sourceType == UsdShadeAttributeType::Output) {
                UsdShadeShader connectedNode(source);
                _WalkGraph(connectedNode, materialNetwork, shaderSourceTypes);
            }
        }
    }

    // Extract the identifier of the node
    TfToken id;
    if (!shadeNode.GetShaderId(&id)) {
        for (auto &sourceType : shaderSourceTypes) {
            if (SdrShaderNodeConstPtr n = 
                    shadeNode.GetShaderNodeForSourceType(sourceType)) {
                id = n->GetIdentifier();
                break;
            }
        }
    }

    if (!id.IsEmpty()) {
        node.identifier = id;

        // If a node is recognizable, we will try to extract the primvar 
        // names that is using since this can help render delegates 
        // optimize what what is needed from a prim when making data 
        // accessible for renderers.
        _ExtractPrimvarsFromNode(shadeNode, node, materialNetwork);
    } else {
        TF_WARN("UsdShade Shader without an id: %s.", node.path.GetText());
        node.identifier = TfToken("PbsNetworkMaterialStandIn_2");
    }

    // Add the parameters and the relationships of this node
    VtValue value;
    for (UsdShadeInput const& input: shadeNodeInputs) {
        // Check if this input is a connection and if so follow the path
        UsdShadeConnectableAPI source;
        TfToken sourceName;
        UsdShadeAttributeType sourceType;
        if (UsdShadeConnectableAPI::GetConnectedSource(input,
            &source, &sourceName, &sourceType)) {
            if (sourceType == UsdShadeAttributeType::Output) {
                // Store the relationship
                HdMaterialRelationship relationship;
                relationship.outputId = shadeNode.GetPath();
                relationship.outputName = input.GetBaseName();
                relationship.inputId = source.GetPath();
                relationship.inputName = sourceName;
                materialNetwork->relationships.push_back(relationship);
            } else if (sourceType == UsdShadeAttributeType::Input) {
                // Connected to an input on the public interface.
                // The source is not a node in the shader network, so
                // pull the value and pass it in as a parameter.
                if (UsdShadeInput connectedInput =
                    source.GetInput(sourceName)) {
                    if (connectedInput.Get(&value)) {
                        node.parameters[input.GetBaseName()] = value;
                    }
                }
            }
        } else {
            // Parameters detected, let's store it
            if (input.Get(&value)) {
                node.parameters[input.GetBaseName()] = value;
            }
        }
    }

    materialNetwork->nodes.push_back(node);
}
Пример #15
0
HdTextureResource::ID
UsdImagingGL_GetTextureResourceID(UsdPrim const& usdPrim,
                                  SdfPath const& usdPath,
                                  UsdTimeCode time,
                                  size_t salt)
{
    if (!TF_VERIFY(usdPrim)) {
        return HdTextureResource::ID(-1);
    }
    if (!TF_VERIFY(usdPath != SdfPath())) {
        return HdTextureResource::ID(-1);
    }

    // If the texture name attribute doesn't exist, it might be badly specified
    // in scene data.
    UsdAttribute attr = _GetTextureResourceAttr(usdPrim, usdPath);

    SdfAssetPath asset;
    if (!attr || !attr.Get(&asset, time)) {
        TF_WARN("Unable to find texture attribute <%s> in scene data",
                usdPath.GetText());
        return HdTextureResource::ID(-1);
    }

    HdTextureType textureType = HdTextureType::Uv;
    TfToken filePath = TfToken(asset.GetResolvedPath());

    if (!filePath.IsEmpty()) {
        // If the resolved path contains a correct path, then we are 
        // dealing with a ptex or uv textures.
        if (GlfIsSupportedPtexTexture(filePath)) {
            textureType = HdTextureType::Ptex;
        } else {
            textureType = HdTextureType::Uv;
        }
    } else {
        // If the path couldn't be resolved, then it might be a Udim as they 
        // contain special characters in the path to identify them <Udim>.
        // Another option is that the path is just wrong and it can not be
        // resolved.
        filePath = TfToken(asset.GetAssetPath());
        if (GlfIsSupportedUdimTexture(filePath)) {
            const GlfContextCaps& caps = GlfContextCaps::GetInstance();
            if (!UsdImaging_UdimTilesExist(filePath, caps.maxArrayTextureLayers,
                _FindLayerHandle(attr, time))) {
                TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback "
                        "textures are not supported for udim",
                        filePath.GetText(), usdPath.GetText());
                return HdTextureResource::ID(-1);
            }
            if (!caps.arrayTexturesEnabled) {
                TF_WARN("OpenGL context does not support array textures, "
                        "skipping UDIM Texture %s with path %s.",
                        filePath.GetText(), usdPath.GetText());
                return HdTextureResource::ID(-1);
            }
            textureType = HdTextureType::Udim;
        } else if (GlfIsSupportedPtexTexture(filePath)) {
            TF_WARN("Unable to find Texture '%s' with path '%s'. Fallback "
                    "textures are not supported for ptex",
                    filePath.GetText(), usdPath.GetText());
            return HdTextureResource::ID(-1);
        } else {
            TF_WARN("Unable to find Texture '%s' with path '%s'. A black "
                    "texture will be substituted in its place.",
                    filePath.GetText(), usdPath.GetText());
            return HdTextureResource::ID(-1);
        }
    }

    GlfImage::ImageOriginLocation origin =
            UsdImagingGL_ComputeTextureOrigin(usdPrim);

    // Hash on the texture filename.
    size_t hash = asset.GetHash();

    // Hash in wrapping and filtering metadata.
    HdWrap wrapS = _GetWrapS(usdPrim, textureType);
    HdWrap wrapT = _GetWrapT(usdPrim, textureType);
    HdMinFilter minFilter = _GetMinFilter(usdPrim);
    HdMagFilter magFilter = _GetMagFilter(usdPrim);
    float memoryLimit = _GetMemoryLimit(usdPrim);

    boost::hash_combine(hash, origin);
    boost::hash_combine(hash, wrapS);
    boost::hash_combine(hash, wrapT);
    boost::hash_combine(hash, minFilter);
    boost::hash_combine(hash, magFilter);
    boost::hash_combine(hash, memoryLimit);

    // Salt the result to prevent collisions in non-shared imaging.
    // Note that the salt is ignored for fallback texture hashes above.
    boost::hash_combine(hash, salt);

    return HdTextureResource::ID(hash);
}
Пример #16
0
HdSt_MeshShaderKey::HdSt_MeshShaderKey(
    Hd_GeometricShader::PrimitiveType primitiveType,
    TfToken shadingTerminal,
    bool hasCustomDisplacementTerminal,
    bool smoothNormals,
    bool doubleSided,
    bool faceVarying,
    bool blendWireframeColor,
    HdCullStyle cullStyle,
    HdMeshGeomStyle geomStyle)
    : primType(primitiveType)
    , cullStyle(cullStyle)
    , polygonMode(HdPolygonModeFill)
    , isFaceVarying(faceVarying)
    , glslfx(_tokens->baseGLSLFX)
{
    if (geomStyle == HdMeshGeomStyleEdgeOnly ||
        geomStyle == HdMeshGeomStyleHullEdgeOnly) {
        polygonMode = HdPolygonModeLine;
    }

    // vertex shader
    VS[0] = _tokens->instancing;
    VS[1] = (smoothNormals ? _tokens->smooth
                           : _tokens->flat);
    VS[2] = _tokens->mainVS;
    VS[3] = TfToken();

    // tessellation control shader
    const bool isPrimTypePatches = 
        Hd_GeometricShader::IsPrimTypePatches(primType);

    TCS[0] = isPrimTypePatches ? _tokens->instancing : TfToken();
    TCS[1] = isPrimTypePatches ? _tokens->mainBSplineTCS : TfToken();
    TCS[2] = TfToken();

    // tessellation evaluation shader
    TES[0] = isPrimTypePatches ? _tokens->instancing : TfToken();
    TES[1] = isPrimTypePatches ? _tokens->mainBezierTES : TfToken();
    TES[2] = TfToken();

    // geometry shader (note that PRIM_MESH_PATCHES uses triangles)
    GS[0] = _tokens->instancing;
    GS[1] = isPrimTypePatches ? _tokens->limit : 
                (smoothNormals ? _tokens->smooth : _tokens->flat);
    GS[2] = ((geomStyle == HdMeshGeomStyleEdgeOnly ||
              geomStyle == HdMeshGeomStyleHullEdgeOnly)   ? _tokens->edgeOnlyGS
           : (geomStyle == HdMeshGeomStyleEdgeOnSurf ||
              geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->edgeOnSurfGS
                                                          : _tokens->edgeNoneGS);

    GS[3] = Hd_GeometricShader::IsPrimTypeQuads(primType)? 
                _tokens->mainQuadGS : _tokens->mainTriangleGS;
    GS[4] = TfToken();

    // Optimization : If the mesh does not provide a custom displacement shader
    //                we have an opportunity to fully disable the geometry
    //                stage.
    if (!hasCustomDisplacementTerminal) {
        // Geometry shader (along with the displacement shader) 
        // can be fully disabled in the folowing condition.
        if (smoothNormals
            && (geomStyle == HdMeshGeomStyleSurf || geomStyle == HdMeshGeomStyleHull)
            && Hd_GeometricShader::IsPrimTypeTriangles(primType)
            && (!isFaceVarying)) {
            
            GS[0] = TfToken();
        } else {
            // If we were not able to disable the geometry stage
            // then we will add a very simple displacement shader.
            GS[4] = _tokens->displacementGS;
            GS[5] = TfToken();
        }
    }

    // Optimization : Points don't need any sort of geometry shader so
    //                we ignore it here.
    if (Hd_GeometricShader::IsPrimTypePoints(primType)) {
        GS[0] = TfToken();
    }

    // fragment shader
    FS[0] = _tokens->instancing;
    FS[1] = (smoothNormals ? _tokens->smooth
                           : _tokens->flat);
    FS[2] = (doubleSided   ? _tokens->doubleSidedFS
                           : _tokens->singleSidedFS);
    if (isPrimTypePatches) {
        FS[3] = ((geomStyle == HdMeshGeomStyleEdgeOnly ||
                  geomStyle == HdMeshGeomStyleHullEdgeOnly)   ? _tokens->patchEdgeOnlyFS
              : ((geomStyle == HdMeshGeomStyleEdgeOnSurf ||
                  geomStyle == HdMeshGeomStyleHullEdgeOnSurf) ? _tokens->patchEdgeOnSurfFS
                                                              : _tokens->edgeNoneFS));
    } else {
        if (geomStyle == HdMeshGeomStyleEdgeOnly ||
            geomStyle == HdMeshGeomStyleHullEdgeOnly) {
            FS[3] = blendWireframeColor ? _tokens->edgeOnlyBlendFS
                                        : _tokens->edgeOnlyNoBlendFS;
        } else if (geomStyle == HdMeshGeomStyleEdgeOnSurf ||
                   geomStyle == HdMeshGeomStyleHullEdgeOnSurf) {
            FS[3] = _tokens->edgeOnSurfFS;
        } else {
            FS[3] = _tokens->edgeNoneFS;
        }
    }

    TfToken terminalFS;
    if (shadingTerminal == HdMeshReprDescTokens->surfaceShader) {
        terminalFS = _tokens->surfaceFS;
    } else if (shadingTerminal == HdMeshReprDescTokens->surfaceShaderUnlit) {
        terminalFS = _tokens->surfaceUnlitFS;
    } else if (shadingTerminal == HdMeshReprDescTokens->constantColor) {
        terminalFS = _tokens->constantColorFS;
    } else if (!shadingTerminal.IsEmpty()) {
        terminalFS = shadingTerminal;
    } else {
        terminalFS = _tokens->surfaceFS;
    }

    FS[4] = terminalFS;
    FS[5] = _tokens->mainFS;
    FS[6] = TfToken();
}
Пример #17
0
void
Hd_SmoothNormalsComputationGPU::Execute(
    HdBufferArrayRangeSharedPtr const &range)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    if (!glDispatchCompute)
        return;


    TF_VERIFY(_adjacency);
    HdBufferArrayRangeSharedPtr const &adjacencyRange = _adjacency->GetAdjacencyRange();
    TF_VERIFY(adjacencyRange);

    // select shader by datatype
    TfToken shaderToken;
    if (_srcDataType == GL_FLOAT) {
        if (_dstDataType == GL_FLOAT) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToFloat;
        } else if (_dstDataType == GL_DOUBLE) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToDouble;
        } else if (_dstDataType == GL_INT_2_10_10_10_REV) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsFloatToPacked;
        }
    } else if (_srcDataType == GL_DOUBLE) {
        if (_dstDataType == GL_FLOAT) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToFloat;
        } else if (_dstDataType == GL_DOUBLE) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToDouble;
        } else if (_dstDataType == GL_INT_2_10_10_10_REV) {
            shaderToken = HdGLSLProgramTokens->smoothNormalsDoubleToPacked;
        }
    }
    if (!TF_VERIFY(!shaderToken.IsEmpty())) return;

    HdGLSLProgramSharedPtr computeProgram
        = HdGLSLProgram::GetComputeProgram(shaderToken);
    if (!computeProgram) return;

    GLuint program = computeProgram->GetProgram().GetId();

    // buffer resources for GPU computation
    HdBufferResourceSharedPtr points = range->GetResource(_srcName);
    HdBufferResourceSharedPtr normals = range->GetResource(_dstName);
    HdBufferResourceSharedPtr adjacency = adjacencyRange->GetResource();

    // prepare uniform buffer for GPU computation
    struct Uniform {
        int vertexOffset;
        int adjacencyOffset;
        int pointsOffset;
        int pointsStride;
        int normalsOffset;
        int normalsStride;
    } uniform;

    // coherent vertex offset in aggregated buffer array
    uniform.vertexOffset = range->GetOffset();
    // adjacency offset/stride in aggregated adjacency table
    uniform.adjacencyOffset = adjacencyRange->GetOffset();
    // interleaved offset/stride to points
    // note: this code (and the glsl smooth normal compute shader) assumes
    // components in interleaved vertex array are always same data type.
    // i.e. it can't handle an interleaved array which interleaves
    // float/double, float/int etc.
    uniform.pointsOffset = points->GetOffset() / points->GetComponentSize();
    uniform.pointsStride = points->GetStride() / points->GetComponentSize();
    // interleaved offset/stride to normals
    uniform.normalsOffset = normals->GetOffset() / normals->GetComponentSize();
    uniform.normalsStride = normals->GetStride() / normals->GetComponentSize();

    // The number of points is based off the size of the output,
    // However, the number of points in the adjacency table
    // is computed based off the largest vertex indexed from
    // to topology (aka topology->ComputeNumPoints).
    //
    // Therefore, we need to clamp the number of points
    // to the number of entries in the adjancency table.
    int numDestPoints = range->GetNumElements();
    int numSrcPoints = _adjacency->GetNumPoints();

    int numPoints = std::min(numSrcPoints, numDestPoints);

    // transfer uniform buffer
    GLuint ubo = computeProgram->GetGlobalUniformBuffer().GetId();
    HdRenderContextCaps const &caps = HdRenderContextCaps::GetInstance();
    // XXX: workaround for 319.xx driver bug of glNamedBufferDataEXT on UBO
    // XXX: move this workaround to renderContextCaps
    if (false && caps.directStateAccessEnabled) {
        glNamedBufferDataEXT(ubo, sizeof(uniform), &uniform, GL_STATIC_DRAW);
    } else {
        glBindBuffer(GL_UNIFORM_BUFFER, ubo);
        glBufferData(GL_UNIFORM_BUFFER, sizeof(uniform), &uniform, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    }

    glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, points->GetId());
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, normals->GetId());
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, adjacency->GetId());

    // dispatch compute kernel
    glUseProgram(program);

    glDispatchCompute(numPoints, 1, 1);

    glUseProgram(0);
    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

    glBindBufferBase(GL_UNIFORM_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, 0);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, 0);
}
Пример #18
0
void 
UsdImagingGprimAdapter::TrackVariability(UsdPrim const& prim,
                                         SdfPath const& cachePath,
                                         int requestedBits,
                                         int* dirtyBits,
                                         UsdImagingInstancerContext const* 
                                             instancerContext)
{
    // WARNING: This method is executed from multiple threads, the value cache
    // has been carefully pre-populated to avoid mutating the underlying
    // container during update.
    
    // Why is this OK? 
    // Either the value is unvarying, in which case the time ordinate doesn't
    // matter; or the value is varying, in which case we will update it upon
    // first call to Delegate::SetTime(). 
    UsdTimeCode time(1.0);

    UsdImagingValueCache* valueCache = _GetValueCache();

    if (requestedBits & HdChangeTracker::DirtyPrimVar) {
        if (not _IsVarying(prim, 
                   UsdGeomTokens->primvarsDisplayColor, 
                   HdChangeTracker::DirtyPrimVar,
                   UsdImagingTokens->usdVaryingPrimVar,
                   dirtyBits,
                   false)) {
            // Only do this second check if the displayColor isn't already known
            // to be varying.
            _IsVarying(prim, 
                   UsdGeomTokens->primvarsDisplayOpacity, 
                   HdChangeTracker::DirtyPrimVar,
                   UsdImagingTokens->usdVaryingPrimVar,
                   dirtyBits,
                   false);
        }
    }

    if (requestedBits & HdChangeTracker::DirtyExtent) {
        // Discover time-varying extent.
        _IsVarying(prim, 
                   UsdGeomTokens->extent, 
                   HdChangeTracker::DirtyExtent,
                   UsdImagingTokens->usdVaryingExtent,
                   dirtyBits,
                   false);
    }

    if (requestedBits & HdChangeTracker::DirtyTransform) {
        // Discover time-varying transforms.
        _IsTransformVarying(prim, 
                   HdChangeTracker::DirtyTransform,
                   UsdImagingTokens->usdVaryingXform,
                   dirtyBits);
    } 

    if (requestedBits & HdChangeTracker::DirtyVisibility) {
        valueCache->GetVisible(cachePath) = GetVisible(prim, time);
        // Discover time-varying visibility.
        _IsVarying(prim, 
                   UsdGeomTokens->visibility, 
                   HdChangeTracker::DirtyVisibility,
                   UsdImagingTokens->usdVaryingVisibility,
                   dirtyBits,
                   true);

        TfToken purpose = _GetPurpose(prim, time);
        // Empty purpose means there is no opinion, fall back to geom.
        if (purpose.IsEmpty())
            purpose = UsdGeomTokens->default_;
        valueCache->GetPurpose(cachePath) = purpose;
    }
}
Пример #19
0
void
Usd_PrimData::_ComposeAndCacheFlags(Usd_PrimDataConstPtr parent, 
                                    bool isMasterPrim)
{
    // We do not have to clear _flags here since in the pseudo root or instance
    // master case the values never change, and in the ordinary prim case we set
    // every flag.

    // Special-case the root (the only prim which has no parent) and
    // instancing masters.
    if (ARCH_UNLIKELY(!parent || isMasterPrim)) {
        _flags[Usd_PrimActiveFlag] = true;
        _flags[Usd_PrimLoadedFlag] = true;
        _flags[Usd_PrimModelFlag] = true;
        _flags[Usd_PrimGroupFlag] = true;
        _flags[Usd_PrimDefinedFlag] = true;
        _flags[Usd_PrimMasterFlag] = isMasterPrim;
    } 
    else {
        // Compose and cache 'active'.
        UsdPrim self(Usd_PrimDataIPtr(this), SdfPath());
        bool active = true;
        self.GetMetadata(SdfFieldKeys->Active, &active);
        _flags[Usd_PrimActiveFlag] = active;

        // Cache whether or not this prim has a payload.
        bool hasPayload = _primIndex->HasPayload();
        _flags[Usd_PrimHasPayloadFlag] = hasPayload;

        // An active prim is loaded if it's loadable and in the load set, or
        // it's not loadable and its parent is loaded.
        _flags[Usd_PrimLoadedFlag] = active &&
            (hasPayload ?
             _stage->_GetPcpCache()->IsPayloadIncluded(_primIndex->GetPath()) :
             parent->IsLoaded());

        // According to Model hierarchy rules, only Model Groups may have Model
        // children (groups or otherwise).  So if our parent is not a Model
        // Group, then this prim cannot be a model (or a model group).
        // Otherwise we look up the kind metadata and consult the kind registry.
        bool isGroup = false, isModel = false;
        if (parent->IsGroup()) {
            static TfToken kindToken("kind");
            TfToken kind;
            self.GetMetadata(kindToken, &kind);
            // Use the kind registry to determine model/groupness.
            if (!kind.IsEmpty()) {
                isGroup = KindRegistry::IsA(kind, KindTokens->group);
                isModel = isGroup || KindRegistry::IsA(kind, KindTokens->model);
            }
        }
        _flags[Usd_PrimGroupFlag] = isGroup;
        _flags[Usd_PrimModelFlag] = isModel;

        // Get specifier.
        SdfSpecifier specifier = GetSpecifier();

        // This prim is abstract if its parent is or if it's a class.
        _flags[Usd_PrimAbstractFlag] =
            parent->IsAbstract() || specifier == SdfSpecifierClass;

        // Cache whether or not this prim has an authored defining specifier.
        const bool isDefiningSpec = SdfIsDefiningSpecifier(specifier);
        _flags[Usd_PrimHasDefiningSpecifierFlag] = isDefiningSpec;

        // This prim is defined if its parent is and its specifier is defining.
        _flags[Usd_PrimDefinedFlag] = isDefiningSpec && parent->IsDefined();

        // The presence of clips that may affect attributes on this prim
        // is computed and set in UsdStage. Default to false.
        _flags[Usd_PrimClipsFlag] = false;

        // These flags indicate whether this prim is an instance or an
        // instance master.
        _flags[Usd_PrimInstanceFlag] = active && _primIndex->IsInstanceable();
        _flags[Usd_PrimMasterFlag] = parent->IsInMaster();
    }
}