bool UsdSkelTopology::Validate(std::string* reason) const { TRACE_FUNCTION(); if(!TF_VERIFY(GetNumJoints() == 0 || _parentIndicesData)) return false; for(size_t i = 0; i < GetNumJoints(); ++i) { int parent = _parentIndicesData[i]; if(parent >= 0) { if(ARCH_UNLIKELY(static_cast<size_t>(parent) >= i)) { if(static_cast<size_t>(parent) == i) { if(reason) { *reason = TfStringPrintf( "Joint %zu has itself as its parent.", i); } return false; } if(reason) { *reason = TfStringPrintf( "Joint %zu has mis-ordered parent %d. Joints are " "expected to be ordered with parent joints always " "coming before children.", i, parent); // XXX: Note that this ordering restriction is a schema // requirement primarily because it simplifies hierarchy // evaluation (see UsdSkelConcatJointTransforms) // But a nice side effect for validation purposes is that // it also ensures that topology is non-cyclic. } return false; } } } return true; }
UsdMayaGLBatchRenderer::TaskDelegate::TaskDelegate( HdRenderIndex *renderIndex, SdfPath const& delegateID) : HdSceneDelegate(renderIndex, delegateID) { _lightingContext = GlfSimpleLightingContext::New(); // populate tasks in renderindex // create an unique namespace _rootId = delegateID.AppendChild( TfToken(TfStringPrintf("_UsdImaging_%p", this))); _simpleLightTaskId = _rootId.AppendChild(_tokens->simpleLightTask); _cameraId = _rootId.AppendChild(_tokens->camera); // camera { // Since we're hardcoded to use HdStRenderDelegate, we expect to // have camera Sprims. TF_VERIFY(renderIndex->IsSprimTypeSupported(HdPrimTypeTokens->camera)); renderIndex->InsertSprim(HdPrimTypeTokens->camera, this, _cameraId); _ValueCache &cache = _valueCacheMap[_cameraId]; cache[HdStCameraTokens->worldToViewMatrix] = VtValue(GfMatrix4d(1.0)); cache[HdStCameraTokens->projectionMatrix] = VtValue(GfMatrix4d(1.0)); cache[HdStCameraTokens->windowPolicy] = VtValue(); // no window policy. } // simple lighting task (for Hydra native) { renderIndex->InsertTask<HdxSimpleLightTask>(this, _simpleLightTaskId); _ValueCache &cache = _valueCacheMap[_simpleLightTaskId]; HdxSimpleLightTaskParams taskParams; taskParams.cameraPath = _cameraId; cache[HdTokens->params] = VtValue(taskParams); cache[HdTokens->children] = VtValue(SdfPathVector()); } }
bool UsdMtlxFileFormat::ReadFromString( const SdfLayerBasePtr& layerBase, const std::string& str) const { TRACE_FUNCTION(); SdfLayerHandle layer = TfDynamic_cast<SdfLayerHandle>(layerBase); if (!TF_VERIFY(layer)) { return false; } auto stage = UsdStage::CreateInMemory(); if (!_Read(stage, [&str](mx::DocumentPtr d) { mx::readFromXmlString(d, str); })) { return false; } layer->TransferContent(stage->GetRootLayer()); return true; }
void Sdf_SubLayerListEditor::_OnEdit( SdfListOpType op, const std::vector<std::string>& oldValues, const std::vector<std::string>& newValues) const { // When sublayer paths are added or removed, we need to keep the // sublayer offsets vector (stored in a separate field) in sync. const SdfLayerOffsetVector oldLayerOffsets = _GetOwner()-> GetFieldAs<SdfLayerOffsetVector>(SdfFieldKeys->SubLayerOffsets); // If this is ever the case, bad things will probably happen as code // in SdfLayer assumes the two vectors are in sync. if (not TF_VERIFY(oldValues.size() == oldLayerOffsets.size(), "Sublayer offsets do not match sublayer paths")) { return; } // Rebuild the layer offsets vector, retaining offsets. SdfLayerOffsetVector newLayerOffsets(newValues.size()); for (size_t i = 0; i < newValues.size(); ++i) { const std::string& newLayer = newValues[i]; std::vector<std::string>::const_iterator oldValuesIt = std::find(oldValues.begin(), oldValues.end(), newLayer); if (oldValuesIt == oldValues.end()) { continue; } const size_t oldLayerOffsetIndex = std::distance(oldValues.begin(), oldValuesIt); newLayerOffsets[i] = oldLayerOffsets[oldLayerOffsetIndex]; } _GetOwner()->SetField(SdfFieldKeys->SubLayerOffsets, newLayerOffsets); }
void Hd_TestDriver::_Init(HdReprSelector const &reprSelector) { _renderIndex = HdRenderIndex::New(&_renderDelegate); TF_VERIFY(_renderIndex != nullptr); _sceneDelegate = new HdUnitTestDelegate(_renderIndex, SdfPath::AbsoluteRootPath()); _reprSelector = reprSelector; GfMatrix4d viewMatrix = GfMatrix4d().SetIdentity(); viewMatrix *= GfMatrix4d().SetTranslate(GfVec3d(0.0, 1000.0, 0.0)); viewMatrix *= GfMatrix4d().SetRotate(GfRotation(GfVec3d(1.0, 0.0, 0.0), -90.0)); GfFrustum frustum; frustum.SetPerspective(45, true, 1, 1.0, 10000.0); GfMatrix4d projMatrix = frustum.ComputeProjectionMatrix(); SetCamera(viewMatrix, projMatrix, GfVec4d(0, 0, 512, 512)); // set depthfunc to default _renderPassState->SetDepthFunc(HdCmpFuncLess); }
size_t PcpPrimIndex_Graph::_CreateNodesForSubgraph( const PcpPrimIndex_Graph& subgraph, const PcpArc& arc) { // The subgraph's root should never have a parent or origin node; we // rely on this invariant below. TF_VERIFY(!subgraph.GetRootNode().GetParentNode() && !subgraph.GetRootNode().GetOriginNode()); // Insert a copy of all of the node data in the given subgraph into our // node pool. const size_t oldNumNodes = _GetNumNodes(); _data->finalized = false; _data->nodes.insert( _data->nodes.end(), subgraph._data->nodes.begin(), subgraph._data->nodes.end()); _nodeSitePaths.insert( _nodeSitePaths.end(), subgraph._nodeSitePaths.begin(), subgraph._nodeSitePaths.end()); _nodeHasSpecs.insert( _nodeHasSpecs.end(), subgraph._nodeHasSpecs.begin(), subgraph._nodeHasSpecs.end()); const size_t newNumNodes = _GetNumNodes(); const size_t subgraphRootNodeIndex = oldNumNodes; // Set the arc connecting the root of the subgraph to the rest of the // graph. _Node& subgraphRoot = _data->nodes[subgraphRootNodeIndex]; subgraphRoot.SetArc(arc); // XXX: This is very similar to code in _ApplyNodeIndexMapping that // adjust node references. There must be a good way to factor // all of that out... // Iterate over all of the newly-copied nodes and adjust references to // other nodes in the node pool. struct _ConvertOldToNewIndex { _ConvertOldToNewIndex(size_t base, size_t numNewNodes) : _base(base), _numNewNodes(numNewNodes) { } size_t operator()(size_t oldIndex) const { if (oldIndex != _Node::_invalidNodeIndex) { TF_VERIFY(oldIndex + _base < _numNewNodes); return oldIndex + _base; } else { return oldIndex; } } size_t _base; size_t _numNewNodes; }; const _ConvertOldToNewIndex convertToNewIndex(subgraphRootNodeIndex, newNumNodes); for (size_t i = oldNumNodes; i < newNumNodes; ++i) { _Node& newNode = _data->nodes[i]; // Update the node's mapToRoot since it is now part of a new graph. if (i != subgraphRootNodeIndex) { newNode.mapToRoot = subgraphRoot.mapToRoot.Compose(newNode.mapToRoot); } // The parent and origin of the root of the newly-inserted subgraph // don't need to be fixed up because it doesn't point to a node // within the subgraph. if (i != subgraphRootNodeIndex) { PARENT(newNode) = convertToNewIndex(PARENT(newNode)); ORIGIN(newNode) = convertToNewIndex(ORIGIN(newNode)); } FIRST_CHILD(newNode) = convertToNewIndex(FIRST_CHILD(newNode)); LAST_CHILD(newNode) = convertToNewIndex(LAST_CHILD(newNode)); PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode)); NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode)); } return subgraphRootNodeIndex; }
bool HdxIntersector::Query(HdxIntersector::Params const& params, HdRprimCollection const& col, HdEngine* engine, HdxIntersector::Result* result) { TRACE_FUNCTION(); // Make sure we're in a sane GL state before attempting anything. if (GlfHasLegacyGraphics()) { TF_RUNTIME_ERROR("framebuffer object not supported"); return false; } GlfGLContextSharedPtr context = GlfGLContext::GetCurrentGLContext(); if (!TF_VERIFY(context)) { TF_RUNTIME_ERROR("Invalid GL context"); return false; } if (!_drawTarget) { // Initialize the shared draw target late to ensure there is a valid GL // context, which may not be the case at constructon time. _Init(GfVec2i(128,128)); } GfVec2i size(_drawTarget->GetSize()); GfVec4i viewport(0, 0, size[0], size[1]); if (!TF_VERIFY(_renderPass)) { return false; } _renderPass->SetRprimCollection(col); // Setup state based on incoming params. _renderPassState->SetAlphaThreshold(params.alphaThreshold); _renderPassState->SetClipPlanes(params.clipPlanes); _renderPassState->SetCullStyle(params.cullStyle); _renderPassState->SetCamera(params.viewMatrix, params.projectionMatrix, viewport); _renderPassState->SetLightingEnabled(false); // Use a separate drawTarget (framebuffer object) for each GL context // that uses this renderer, but the drawTargets share attachments/textures. GlfDrawTargetRefPtr drawTarget = GlfDrawTarget::New(size); // Clone attachments into this context. Note that this will do a // light-weight copy of the textures, it does not produce a full copy of the // underlying images. drawTarget->Bind(); drawTarget->CloneAttachments(_drawTarget); // // Setup GL raster state // GLenum drawBuffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, drawBuffers); glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glDepthFunc(GL_LEQUAL); glClearColor(0,0,0,0); glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); GLF_POST_PENDING_GL_ERRORS(); // // Execute the picking pass // { GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Setup stencil state and prevent writes to color buffer. glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_KEEP, // stencil failed GL_KEEP, // stencil passed, depth failed GL_REPLACE); // stencil passed, depth passed // // Condition the stencil buffer. // params.depthMaskCallback(); // we expect any GL state changes are restored. // Disable stencil updates and setup the stencil test. glStencilFunc(GL_LESS, 0, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // Clear depth incase the depthMaskCallback pollutes the depth buffer. glClear(GL_DEPTH_BUFFER_BIT); // Restore color outputs & setup state for rendering glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glFrontFace(GL_CCW); // // Enable conservative rasterization, if available. // // XXX: This wont work until it's in the Glew build. bool convRstr = glewIsSupported("GL_NV_conservative_raster"); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glEnable(GL_CONSERVATIVE_RASTERIZATION_NV); } // // Execute // // XXX: make intersector a Task HdTaskSharedPtrVector tasks; tasks.push_back(boost::make_shared<HdxIntersector_DrawTask>(_renderPass, _renderPassState, params.renderTags)); engine->Execute(*_index, tasks); glDisable(GL_STENCIL_TEST); if (convRstr) { // XXX: this should come from Glew #define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 glDisable(GL_CONSERVATIVE_RASTERIZATION_NV); } // Restore glBindVertexArray(0); glDeleteVertexArrays(1, &vao); } GLF_POST_PENDING_GL_ERRORS(); // // Capture the result buffers to be resolved later. // size_t len = size[0] * size[1]; std::unique_ptr<unsigned char[]> primId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> instanceId(new unsigned char[len*4]); std::unique_ptr<unsigned char[]> elementId(new unsigned char[len*4]); std::unique_ptr<float[]> depths(new float[len]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("primId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &primId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("instanceId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &instanceId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("elementId")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &elementId[0]); glBindTexture(GL_TEXTURE_2D, drawTarget->GetAttachments().at("depth")->GetGlTextureName()); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &depths[0]); glBindTexture(GL_TEXTURE_2D, 0); GLF_POST_PENDING_GL_ERRORS(); if (result) { *result = HdxIntersector::Result( std::move(primId), std::move(instanceId), std::move(elementId), std::move(depths), _index, params, viewport); } drawTarget->Unbind(); GLF_POST_PENDING_GL_ERRORS(); return true; }
HdSt_DrawBatch::_DrawingProgram & HdSt_DrawBatch::_GetDrawingProgram(HdStRenderPassStateSharedPtr const &state, bool indirect, HdStResourceRegistrySharedPtr const &resourceRegistry) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); HdStDrawItem const *firstDrawItem = _drawItemInstances[0]->GetDrawItem(); // Calculate unique hash to detect if the shader (composed) has changed // recently and we need to recompile it. size_t shaderHash = state->GetShaderHash(); boost::hash_combine(shaderHash, firstDrawItem->GetGeometricShader()->ComputeHash()); HdStShaderCodeSharedPtr overrideShader = state->GetOverrideShader(); HdStShaderCodeSharedPtr surfaceShader = overrideShader ? overrideShader : firstDrawItem->GetMaterialShader(); boost::hash_combine(shaderHash, surfaceShader->ComputeHash()); bool shaderChanged = (_shaderHash != shaderHash); // Set shaders (lighting and renderpass) to the program. // We need to do this before checking if the shaderChanged because // it is possible that the shader does not need to // be recompiled but some of the parameters have changed. HdStShaderCodeSharedPtrVector shaders = state->GetShaders(); _program.SetShaders(shaders); _program.SetGeometricShader(firstDrawItem->GetGeometricShader()); // XXX: if this function appears to be expensive, we might consider caching // programs by shaderHash. if (!_program.GetGLSLProgram() || shaderChanged) { _program.SetSurfaceShader(surfaceShader); // Try to compile the shader and if it fails to compile we go back // to use the specified fallback surface shader. if (!_program.CompileShader(firstDrawItem, indirect, resourceRegistry)){ // While the code should gracefully handle shader compilation // failures, it is also undesirable for shaders to silently fail. TF_CODING_ERROR("Failed to compile shader for prim %s.", firstDrawItem->GetRprimID().GetText()); // If we failed to compile the surface shader, replace it with the // fallback surface shader and try again. // XXX: Note that we only say "surface shader" here because it is // currently the only one that we allow customization for. We // expect all the other shaders to compile or else the shipping // code is broken and needs to be fixed. When we open up more // shaders for customization, we will need to check them as well. typedef boost::shared_ptr<class HioGlslfx> HioGlslfxSharedPtr; HioGlslfxSharedPtr glslSurfaceFallback = HioGlslfxSharedPtr( new HioGlslfx(HdStPackageFallbackSurfaceShader())); HdStShaderCodeSharedPtr fallbackSurface = HdStShaderCodeSharedPtr( new HdStGLSLFXShader(glslSurfaceFallback)); _program.SetSurfaceShader(fallbackSurface); bool res = _program.CompileShader(firstDrawItem, indirect, resourceRegistry); // We expect the fallback shader to always compile. TF_VERIFY(res); } _shaderHash = shaderHash; } return _program; }
void PcpPrimIndex_Graph::_ApplyNodeIndexMapping( const std::vector<size_t>& nodeIndexMap) { _NodePool& oldNodes = _data->nodes; SdfPathVector& oldSitePaths = _nodeSitePaths; std::vector<bool>& oldHasSpecs = _nodeHasSpecs; TF_VERIFY(oldNodes.size() == oldSitePaths.size() && oldNodes.size() == oldHasSpecs.size()); TF_VERIFY(nodeIndexMap.size() == oldNodes.size()); const size_t numNodesToErase = std::count(nodeIndexMap.begin(), nodeIndexMap.end(), _Node::_invalidNodeIndex); const size_t oldNumNodes = oldNodes.size(); const size_t newNumNodes = oldNumNodes - numNodesToErase; TF_VERIFY(newNumNodes <= oldNumNodes); struct _ConvertOldToNewIndex { _ConvertOldToNewIndex(const std::vector<size_t>& table, size_t numNewNodes) : _table(table) { for (size_t i = 0, n = _table.size(); i != n; ++i) { TF_VERIFY(_table[i] < numNewNodes || _table[i] == _Node::_invalidNodeIndex); } } size_t operator()(size_t oldIndex) const { if (oldIndex != _Node::_invalidNodeIndex) { return _table[oldIndex]; } else { return oldIndex; } } const std::vector<size_t>& _table; }; const _ConvertOldToNewIndex convertToNewIndex(nodeIndexMap, newNumNodes); // If this mapping causes nodes to be erased, it's much more convenient // to fix up node indices to accommodate those erasures in the old node // pool before moving nodes to their new position. if (numNodesToErase > 0) { for (size_t i = 0; i < oldNumNodes; ++i) { const size_t oldNodeIndex = i; const size_t newNodeIndex = convertToNewIndex(oldNodeIndex); _Node& node = _data->nodes[oldNodeIndex]; // Sanity-check: If this node isn't going to be erased, its parent // can't be erased either. const bool nodeWillBeErased = (newNodeIndex == _Node::_invalidNodeIndex); if (!nodeWillBeErased) { const bool parentWillBeErased = PARENT(node) != _Node::_invalidNodeIndex && convertToNewIndex(PARENT(node)) == _Node::_invalidNodeIndex; TF_VERIFY(!parentWillBeErased); continue; } if (PREV_SIBLING(node) != _Node::_invalidNodeIndex) { _Node& prevNode = _data->nodes[PREV_SIBLING(node)]; NEXT_SIBLING(prevNode) = NEXT_SIBLING(node); } if (NEXT_SIBLING(node) != _Node::_invalidNodeIndex) { _Node& nextNode = _data->nodes[NEXT_SIBLING(node)]; PREV_SIBLING(nextNode) = PREV_SIBLING(node); } _Node& parentNode = _data->nodes[PARENT(node)]; if (FIRST_CHILD(parentNode) == oldNodeIndex) { FIRST_CHILD(parentNode) = NEXT_SIBLING(node); } if (LAST_CHILD(parentNode) == oldNodeIndex) { LAST_CHILD(parentNode) = PREV_SIBLING(node); } } } // Swap nodes into their new position. _NodePool nodesAfterMapping(newNumNodes); SdfPathVector nodeSitePathsAfterMapping(newNumNodes); std::vector<bool> nodeHasSpecsAfterMapping(newNumNodes); for (size_t i = 0; i < oldNumNodes; ++i) { const size_t oldNodeIndex = i; const size_t newNodeIndex = convertToNewIndex(oldNodeIndex); if (newNodeIndex == _Node::_invalidNodeIndex) { continue; } // Swap the node from the old node pool into the new node pool at // the desired location. _Node& oldNode = oldNodes[oldNodeIndex]; _Node& newNode = nodesAfterMapping[newNodeIndex]; newNode.Swap(oldNode); PARENT(newNode) = convertToNewIndex(PARENT(newNode)); ORIGIN(newNode) = convertToNewIndex(ORIGIN(newNode)); FIRST_CHILD(newNode) = convertToNewIndex(FIRST_CHILD(newNode)); LAST_CHILD(newNode) = convertToNewIndex(LAST_CHILD(newNode)); PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode)); NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode)); // Copy the corresponding node site path. nodeSitePathsAfterMapping[newNodeIndex] = oldSitePaths[oldNodeIndex]; nodeHasSpecsAfterMapping[newNodeIndex] = oldHasSpecs[oldNodeIndex]; } _data->nodes.swap(nodesAfterMapping); _nodeSitePaths.swap(nodeSitePathsAfterMapping); _nodeHasSpecs.swap(nodeHasSpecsAfterMapping); }
SdfAttributeSpecHandle SdfAttributeSpec::_New( const SdfRelationshipSpecHandle& owner, const SdfPath& path, const std::string& name, const SdfValueTypeName& typeName, SdfVariability variability, bool custom) { if (not owner) { TF_CODING_ERROR("NULL owner"); return TfNullPtr; } if (not typeName) { TF_CODING_ERROR("Cannot create attribute spec <%s> with invalid type", owner->GetPath().AppendTarget(path). AppendProperty(TfToken(name)).GetText()); return TfNullPtr; } SdfChangeBlock block; // Determine the path of the relationship target SdfPath absPath = path.MakeAbsolutePath(owner->GetPath().GetPrimPath()); SdfPath targetPath = owner->GetPath().AppendTarget(absPath); // Check to make sure that the name is valid if (not Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::IsValidName(name)) { TF_CODING_ERROR( "Cannot create attribute on %s with invalid name: %s", targetPath.GetText(), name.c_str()); return TfNullPtr; } // Create the relationship target if it doesn't already exist. Note // that this does not automatically get added to the relationship's // target path list. SdfSpecHandle targetSpec = owner->_FindOrCreateTargetSpec(path); // AttributeSpecs are considered initially to have only required fields // only if they are not custom. bool hasOnlyRequiredFields = (not custom); // Create the relational attribute spec SdfPath attrPath = targetPath.AppendRelationalAttribute(TfToken(name)); if (not Sdf_ChildrenUtils<Sdf_AttributeChildPolicy>::CreateSpec( owner->GetLayer(), attrPath, SdfSpecTypeAttribute, hasOnlyRequiredFields)) { return TfNullPtr; } SdfAttributeSpecHandle spec = owner->GetLayer()->GetAttributeAtPath(attrPath); // Avoid expensive dormancy checks in the case of binary-backed data. SdfAttributeSpec *specPtr = get_pointer(spec); if (TF_VERIFY(specPtr)) { specPtr->SetField(SdfFieldKeys->Custom, custom); specPtr->SetField(SdfFieldKeys->TypeName, typeName.GetAsToken()); specPtr->SetField(SdfFieldKeys->Variability, variability); } return spec; }
void UsdImagingGprimAdapter::_DiscoverPrimvarsDeprecated(UsdGeomGprim const& gprim, SdfPath const& cachePath, UsdPrim const& shaderPrim, UsdTimeCode time, UsdImagingValueCache* valueCache) { UsdImagingValueCache::PrimvarInfo primvar; std::vector<UsdProperty> const& props = shaderPrim.GetProperties(); TF_FOR_ALL(propIt, props) { UsdAttribute attr = propIt->As<UsdAttribute>(); if (not attr) { continue; } if (attr.GetPath().IsNamespacedPropertyPath()) { continue; } // Ok this is a parameter, check source input. if (UsdAttribute texAttr = shaderPrim.GetAttribute( TfToken(attr.GetPath().GetName() + ":texture"))) { TfToken t; SdfAssetPath ap; VtValue v; UsdGeomPrimvar primvarAttr; texAttr.Get(&ap, UsdTimeCode::Default()); bool isPtex = GlfPtexTexture::IsPtexTexture(TfToken(ap.GetAssetPath())); if (isPtex) { t = UsdImagingTokens->ptexFaceIndex; // Allow the client to override this name texAttr.GetMetadata(UsdImagingTokens->faceIndexPrimvar, &t); primvarAttr = gprim.GetPrimvar(t); if (primvarAttr) { if (primvarAttr.ComputeFlattened(&v, time)) { primvar.name = t; primvar.interpolation = primvarAttr.GetInterpolation(); valueCache->GetPrimvar(cachePath, t) = v; _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath)); } } t = UsdImagingTokens->ptexFaceOffset; // Allow the client to override this name texAttr.GetMetadata(UsdImagingTokens->faceOffsetPrimvar, &t); primvarAttr = gprim.GetPrimvar(t); if (primvarAttr) { primvar.name = t; primvar.interpolation = primvarAttr.GetInterpolation(); if (primvarAttr.ComputeFlattened(&v, time)) { valueCache->GetPrimvar(cachePath, t) = v; _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath)); } } } else { texAttr.GetMetadata(UsdImagingTokens->uvPrimvar, &t); primvarAttr = gprim.GetPrimvar(t); if (TF_VERIFY(primvarAttr, "%s\n", t.GetText())) { if (TF_VERIFY(primvarAttr.ComputeFlattened(&v, time))) { primvar.name = t; // does not include primvars: primvar.interpolation = primvarAttr.GetInterpolation(); // Convert double to float, we don't need double precision. if (v.IsHolding<VtVec2dArray>()) { v = VtValue::Cast<VtVec2fArray>(v); } valueCache->GetPrimvar(cachePath, t) = v; _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath)); } } } } else if (UsdAttribute pvAttr = shaderPrim.GetAttribute( TfToken(attr.GetPath().GetName() + ":primvar"))) { TfToken t; VtValue v; UsdGeomPrimvar primvarAttr; if (TF_VERIFY(pvAttr.Get(&t, UsdTimeCode::Default()))) { primvarAttr = gprim.GetPrimvar(t); if (TF_VERIFY(primvarAttr.ComputeFlattened(&v, time))) { primvar.name = t; // does not include primvars: primvar.interpolation = primvarAttr.GetInterpolation(); valueCache->GetPrimvar(cachePath, t) = v; _MergePrimvar(primvar, &valueCache->GetPrimvars(cachePath)); } } } }
bool Hd_SmoothNormalsComputation::Resolve() { // dependency check first if (_adjacencyBuilder) { if (!_adjacencyBuilder->IsResolved()) return false; } if (!_points->IsResolved()) return false; if (!_TryLock()) return false; HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); if (!TF_VERIFY(_adjacency)) return true; size_t numPoints = _points->GetNumElements(); HdBufferSourceSharedPtr normals; switch (_points->GetTupleType().type) { case HdTypeFloatVec3: if (_packed) { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormalsPacked( _adjacency, numPoints, static_cast<const GfVec3f*>(_points->GetData()))))); } else { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormals( _adjacency, numPoints, static_cast<const GfVec3f*>(_points->GetData()))))); } break; case HdTypeDoubleVec3: if (_packed) { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormalsPacked( _adjacency, numPoints, static_cast<const GfVec3d*>(_points->GetData()))))); } else { normals = HdBufferSourceSharedPtr( new HdVtBufferSource( _dstName, VtValue( Hd_SmoothNormals::ComputeSmoothNormals( _adjacency, numPoints, static_cast<const GfVec3d*>(_points->GetData()))))); } break; default: TF_CODING_ERROR("Unsupported points type for computing smooth normals"); break; } _SetResult(normals); // call base class to mark as resolved. _SetResolved(); return true; }
const std::string& SdfFileFormat::GetPrimaryFileExtension() const { static std::string emptyString; return TF_VERIFY(!_extensions.empty()) ? _extensions[0] : emptyString; }
void HdStRenderContextCaps::_LoadCaps() { // XXX: consider to move this class into glf // note that this function is called without GL context, in some unit tests. shaderStorageBufferEnabled = false; bindlessTextureEnabled = false; bindlessBufferEnabled = false; multiDrawIndirectEnabled = false; directStateAccessEnabled = false; bufferStorageEnabled = false; shadingLanguage420pack = false; explicitUniformLocation = false; maxUniformBlockSize = 16*1024; // GL spec minimum maxShaderStorageBlockSize = 16*1024*1024; // GL spec minimum maxTextureBufferSize = 64*1024; // GL spec minimum uniformBufferOffsetAlignment = 0; const char *glVersionStr = (const char*)glGetString(GL_VERSION); // GL hasn't been initialized yet. if (glVersionStr == NULL) return; const char *dot = strchr(glVersionStr, '.'); if (TF_VERIFY((dot && dot != glVersionStr), "Can't parse GL_VERSION %s", glVersionStr)) { // GL_VERSION = "4.5.0 <vendor> <version>" // "4.1 <vendor-os-ver> <version>" // "4.1 <vendor-os-ver>" int major = std::max(0, std::min(9, *(dot-1) - '0')); int minor = std::max(0, std::min(9, *(dot+1) - '0')); glVersion = major * 100 + minor * 10; } if (glVersion >= 200) { const char *glslVersionStr = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); dot = strchr(glslVersionStr, '.'); if (TF_VERIFY((dot && dot != glslVersionStr), "Can't parse GL_SHADING_LANGUAGE_VERSION %s", glslVersionStr)) { // GL_SHADING_LANGUAGE_VERSION = "4.10" // "4.50 <vendor>" int major = std::max(0, std::min(9, *(dot-1) - '0')); int minor = std::max(0, std::min(9, *(dot+1) - '0')); glslVersion = major * 100 + minor * 10; } } else { glslVersion = 0; } // initialize by Core versions if (glVersion >= 310) { glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &maxUniformBlockSize); glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxTextureBufferSize); glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformBufferOffsetAlignment); } if (glVersion >= 420) { shadingLanguage420pack = true; } if (glVersion >= 430) { shaderStorageBufferEnabled = true; explicitUniformLocation = true; glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxShaderStorageBlockSize); } if (glVersion >= 440) { bufferStorageEnabled = true; } if (glVersion >= 450) { multiDrawIndirectEnabled = true; directStateAccessEnabled = true; } // initialize by individual extension. if (GLEW_ARB_bindless_texture && glMakeTextureHandleResidentNV) { bindlessTextureEnabled = true; } if (GLEW_NV_shader_buffer_load && glMakeNamedBufferResidentNV) { bindlessBufferEnabled = true; } if (GLEW_ARB_explicit_uniform_location) { explicitUniformLocation = true; } if (GLEW_ARB_shading_language_420pack) { shadingLanguage420pack = true; } if (GLEW_ARB_multi_draw_indirect) { multiDrawIndirectEnabled = true; } #if defined(GLEW_VERSION_4_5) // glew 1.11 or newer (usd requirement is 1.10) if (GLEW_ARB_direct_state_access) { directStateAccessEnabled = true; } #endif if (GLEW_EXT_direct_state_access) { directStateAccessEnabled = true; } // Environment variable overrides (only downgrading is possible) if (!TfGetEnvSetting(HD_ENABLE_SHADER_STORAGE_BUFFER)) { shaderStorageBufferEnabled = false; } if (!TfGetEnvSetting(HD_ENABLE_BINDLESS_TEXTURE)) { bindlessTextureEnabled = false; } if (!TfGetEnvSetting(HD_ENABLE_BINDLESS_BUFFER)) { bindlessBufferEnabled = false; } if (!TfGetEnvSetting(HD_ENABLE_MULTI_DRAW_INDIRECT)) { multiDrawIndirectEnabled = false; } if (!TfGetEnvSetting(HD_ENABLE_DIRECT_STATE_ACCESS)) { directStateAccessEnabled = false; } // For debugging and unit testing if (TfGetEnvSetting(HD_GLSL_VERSION) > 0) { // GLSL version override glslVersion = std::min(glslVersion, TfGetEnvSetting(HD_GLSL_VERSION)); // downgrade to the overriden GLSL version explicitUniformLocation &= (glslVersion >= 430); bindlessTextureEnabled &= (glslVersion >= 430); bindlessBufferEnabled &= (glslVersion >= 430); shaderStorageBufferEnabled &= (glslVersion >= 430); shadingLanguage420pack &= (glslVersion >= 420); } // For driver issues workaround if (!TfGetEnvSetting(HD_ENABLE_COPY_BUFFER)) { copyBufferEnabled = false; } // GPU Compute if (TfGetEnvSetting(HD_ENABLE_GPU_COMPUTE)) { #if OPENSUBDIV_HAS_GLSL_COMPUTE if (glslVersion >= 430 && shaderStorageBufferEnabled) { gpuComputeEnabled = true; } else { TF_WARN("HD_ENABLE_GPU_COMPUTE can't be enabled " "(OpenGL 4.3 required).\n"); } #else TF_WARN("HD_ENABLE_GPU_COMPUTE can't be enabled " "(OpenSubdiv hasn't been configured with GLSL compute).\n"); #endif } if (TfDebug::IsEnabled(HD_RENDER_CONTEXT_CAPS)) { std::cout << "HdStRenderContextCaps: \n" << " GL version = " << glVersion << "\n" << " GLSL version = " << glslVersion << "\n" << " GL_MAX_UNIFORM_BLOCK_SIZE = " << maxUniformBlockSize << "\n" << " GL_MAX_SHADER_STORAGE_BLOCK_SIZE = " << maxShaderStorageBlockSize << "\n" << " GL_MAX_TEXTURE_BUFFER_SIZE = " << maxTextureBufferSize << "\n" << " GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = " << uniformBufferOffsetAlignment << "\n" << " ARB_bindless_texture = " << bindlessTextureEnabled << "\n" << " ARB_explicit_uniform_location = " << explicitUniformLocation << "\n" << " ARB_multi_draw_indirect = " << multiDrawIndirectEnabled << "\n" << " ARB_direct_state_access = " << directStateAccessEnabled << "\n" << " ARB_shader_storage_buffer_object = " << shaderStorageBufferEnabled << "\n" << " ARB_shading_language_420pack = " << shadingLanguage420pack << "\n" << " NV_shader_buffer_load = " << bindlessBufferEnabled << "\n" << " GPU Compute = " << gpuComputeEnabled << "\n" ; if (!copyBufferEnabled) { std::cout << " CopyBuffer : disabled\n"; } } }
static VtVec3fArray _GenerateCapsuleMeshPoints(float radius, float height, TfToken const & axis) { // choose basis vectors aligned with the spine axis GfVec3f u, v, spine; if (axis == UsdGeomTokens->x) { u = GfVec3f::YAxis(); v = GfVec3f::ZAxis(); spine = GfVec3f::XAxis(); } else if (axis == UsdGeomTokens->y) { u = GfVec3f::ZAxis(); v = GfVec3f::XAxis(); spine = GfVec3f::YAxis(); } else { // (axis == UsdGeomTokens->z) u = GfVec3f::XAxis(); v = GfVec3f::YAxis(); spine = GfVec3f::ZAxis(); } // compute a ring of points with unit radius in the uv plane std::vector<GfVec3f> ring(_slices); for (int i=0; i<_slices; ++i) { float a = float(2 * M_PI * i) / _slices; ring[i] = u * cosf(a) + v * sinf(a); } int numPoints = _slices * (_stacks + 1) // cylinder + 2 * _slices * (_hemisphereStacks-1) // hemispheres + 2; // end points // populate points VtVec3fArray pointsArray(numPoints); GfVec3f * p = pointsArray.data(); // base hemisphere *p++ = spine * (-height/2-radius); for (int i=0; i<_hemisphereStacks-1; ++i) { float a = float(M_PI / 2) * (1.0f - float(i+1) / _hemisphereStacks); float r = radius * cosf(a); float w = radius * sinf(a); for (int j=0; j<_slices; ++j) { *p++ = r * ring[j] + spine * (-height/2-w); } } // middle for (int i=0; i<=_stacks; ++i) { float t = float(i) / _stacks; float w = height * (t - 0.5f); for (int j=0; j<_slices; ++j) { *p++ = radius * ring[j] + spine * w; } } // top hemisphere for (int i=0; i<_hemisphereStacks-1; ++i) { float a = float(M_PI / 2) * (float(i+1) / _hemisphereStacks); float r = radius * cosf(a); float w = radius * sinf(a); for (int j=0; j<_slices; ++j) { *p++ = r * ring[j] + spine * (height/2+w); } } *p++ = spine * (height/2.0f+radius); TF_VERIFY(p - pointsArray.data() == numPoints); return pointsArray; }
const SdfPath& PcpNodeRef::GetPath() const { TF_VERIFY(_nodeIdx < _graph->_nodeSitePaths.size()); return _graph->_nodeSitePaths[_nodeIdx]; }
void PcpNodeRef::SetHasSpecs(bool hasSpecs) { TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size()); _graph->_nodeHasSpecs[_nodeIdx] = hasSpecs; }
bool PcpNodeRef::HasSpecs() const { TF_VERIFY(_nodeIdx < _graph->_nodeHasSpecs.size()); return _graph->_nodeHasSpecs[_nodeIdx]; }
void GlfBaseTexture::_CreateTexture(GlfBaseTextureDataConstPtr texData, bool const generateMipmap, int const unpackCropTop, int const unpackCropBottom, int const unpackCropLeft, int const unpackCropRight) { TRACE_FUNCTION(); if (texData and texData->HasRawBuffer()) { glBindTexture( GL_TEXTURE_2D, _textureName); glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, generateMipmap ? GL_TRUE : GL_FALSE); if (not texData->IsCompressed()) { if (GlfGetNumElements(texData->GLFormat()) == 1) { GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; glTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } int texDataWidth = texData->ResizedWidth(); int texDataHeight = texData->ResizedHeight(); int unpackRowLength = texDataWidth; int unpackSkipPixels = 0; int unpackSkipRows = 0; if (unpackCropTop < 0 or unpackCropTop > texDataHeight) { return; } else if (unpackCropTop > 0) { unpackSkipRows = unpackCropTop; texDataHeight -= unpackCropTop; } if (unpackCropBottom < 0 or unpackCropBottom > texDataHeight) { return; } else if (unpackCropBottom) { texDataHeight -= unpackCropBottom; } if (unpackCropLeft < 0 or unpackCropLeft > texDataWidth) { return; } else { unpackSkipPixels = unpackCropLeft; texDataWidth -= unpackCropLeft; } if (unpackCropRight < 0 or unpackCropRight > texDataWidth) { return; } else if (unpackCropRight > 0) { texDataWidth -= unpackCropRight; } glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackRowLength); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackSkipPixels); glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackSkipRows); glTexImage2D( GL_TEXTURE_2D, 0, texData->GLInternalFormat(), texDataWidth, texDataHeight, 0, texData->GLFormat(), texData->GLType(), texData->GetRawBuffer()); glPopClientAttrib(); } else { // There should be no cropping when using compressed textures TF_VERIFY(unpackCropTop == 0 && unpackCropBottom == 0 && unpackCropLeft == 0 && unpackCropRight == 0); glCompressedTexImage2D( GL_TEXTURE_2D, 0, texData->GLInternalFormat(), texData->ResizedWidth(), texData->ResizedHeight(), 0, texData->ComputeBytesUsed(), texData->GetRawBuffer()); } glBindTexture( GL_TEXTURE_2D, 0); _SetMemoryUsed(texData->ComputeBytesUsed()); } }
HdSt_BasisCurvesShaderKey::HdSt_BasisCurvesShaderKey( TfToken const &type, TfToken const &basis, DrawStyle drawStyle, NormalStyle normalStyle, bool basisWidthInterpolation, bool basisNormalInterpolation) : glslfx(_tokens->baseGLSLFX) { bool drawThick = (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE) || (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON); bool cubic = (type == HdTokens->cubic); bool linear = (type == HdTokens->linear); TF_VERIFY(cubic || linear); // The order of the clauses below matters! if (drawStyle == HdSt_BasisCurvesShaderKey::POINTS) { primType = HdSt_GeometricShader::PrimitiveType::PRIM_POINTS; } else if (cubic) { // cubic curves get drawn via isolines in a tessellation shader // even in wire mode. primType = HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_CUBIC_PATCHES; } else if (drawThick){ primType = HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_LINEAR_PATCHES; } else { primType = HdSt_GeometricShader::PrimitiveType::PRIM_BASIS_CURVES_LINES; } bool isPrimTypePoints = HdSt_GeometricShader::IsPrimTypePoints(primType); bool oriented = normalStyle == HdSt_BasisCurvesShaderKey::ORIENTED; uint8_t vsIndex = 0; VS[vsIndex++] = _tokens->instancing; VS[vsIndex++] = drawThick ? _tokens->curvesVertexPatch : _tokens->curvesVertexWire; VS[vsIndex++] = oriented ? _tokens->curvesVertexNormalOriented : _tokens->curvesVertexNormalImplicit; if (isPrimTypePoints) { // Add mixins that allow for picking and sel highlighting of points. // Even though these are more "render pass-ish", we do this here to // reduce the shader code generated when the points repr isn't used. VS[vsIndex++] = _tokens->pointIdVS; VS[vsIndex++] = _tokens->pointIdSelDecodeUtilsVS; VS[vsIndex++] = _tokens->pointIdSelPointSelVS; } else { VS[vsIndex++] = _tokens->pointIdNoneVS; } VS[vsIndex] = TfToken(); // Setup Tessellation if (linear) { switch(drawStyle) { case HdSt_BasisCurvesShaderKey::POINTS: case HdSt_BasisCurvesShaderKey::WIRE: { TCS[0] = TfToken(); TES[0] = TfToken(); break; } case HdSt_BasisCurvesShaderKey::RIBBON: { TCS[0] = _tokens->curvesTessControlShared; TCS[1] = _tokens->curvesTessControlLinearPatch; TCS[2] = _tokens->curvesTessControlLinearRibbon; TCS[3] = TfToken(); TES[0] = _tokens->instancing; TES[1] = _tokens->curvesTessEvalPatch; TES[2] = _tokens->curvesFallback; TES[3] = _tokens->curvesTessEvalLinearPatch; TES[4] = oriented ? _tokens->curvesTessEvalRibbonOriented : _tokens->curvesTessEvalRibbonImplicit; TES[5] = TfToken(); break; } case HdSt_BasisCurvesShaderKey::HALFTUBE: { TCS[0] = _tokens->curvesTessControlShared; TCS[1] = _tokens->curvesTessControlLinearPatch; TCS[2] = _tokens->curvesTessControlLinearHalfTube; TCS[3] = TfToken(); TES[0] = _tokens->instancing; TES[1] = _tokens->curvesTessEvalPatch; TES[2] = _tokens->curvesFallback; TES[3] = _tokens->curvesTessEvalLinearPatch; TES[4] = _tokens->curvesTessEvalHalfTube; TES[5] = TfToken(); break; } default: TF_CODING_ERROR("Unhandled drawstyle for basis curves"); } } else { // cubic switch(drawStyle) { case HdSt_BasisCurvesShaderKey::POINTS: { TCS[0] = TfToken(); TES[0] = TfToken(); break; } case HdSt_BasisCurvesShaderKey::WIRE: { TCS[0] = _tokens->curvesTessControlShared; TCS[1] = _tokens->curvesTessControlCubicWire; TCS[2] = TfToken(); TES[0] = _tokens->instancing; TES[1] = _tokens->curvesTessEvalCubicWire; TES[2] = HdSt_BasisToShaderKey(basis); TES[3] = TfToken(); break; } case HdSt_BasisCurvesShaderKey::RIBBON: { TCS[0] = _tokens->curvesTessControlShared; TCS[1] = _tokens->curvesTessControlCubicPatch; TCS[2] = _tokens->curvesTessControlCubicRibbon; TCS[3] = TfToken(); TES[0] = _tokens->instancing; TES[1] = _tokens->curvesTessEvalPatch; TES[2] = _tokens->curvesTessEvalCubicPatch; TES[3] = HdSt_BasisToShaderKey(basis); TES[4] = oriented ? _tokens->curvesTessEvalRibbonOriented : _tokens->curvesTessEvalRibbonImplicit; TES[5] = basisWidthInterpolation ? _tokens->curveCubicWidthsBasis : _tokens->curveCubicWidthsLinear; TES[6] = basisNormalInterpolation ? _tokens->curveCubicNormalsBasis : _tokens->curveCubicNormalsLinear; TES[7] = TfToken(); break; } case HdSt_BasisCurvesShaderKey::HALFTUBE: { TCS[0] = _tokens->curvesTessControlShared; TCS[1] = _tokens->curvesTessControlCubicPatch; TCS[2] = _tokens->curvesTessControlCubicHalfTube; TCS[3] = TfToken(); TES[0] = _tokens->instancing; TES[1] = _tokens->curvesTessEvalPatch; TES[2] = _tokens->curvesTessEvalCubicPatch; TES[3] = HdSt_BasisToShaderKey(basis); TES[4] = _tokens->curvesTessEvalHalfTube; TES[5] = basisWidthInterpolation ? _tokens->curveCubicWidthsBasis : _tokens->curveCubicWidthsLinear; TES[6] = basisNormalInterpolation ? _tokens->curveCubicNormalsBasis : _tokens->curveCubicNormalsLinear; TES[7] = TfToken(); break; } default: TF_CODING_ERROR("Unhandled drawstyle for basis curves"); } } // setup fragment shaders // Common must be first as it defines terminal interfaces uint8_t fsIndex = 0; FS[fsIndex++] = _tokens->commonFS; FS[fsIndex++] = _tokens->surfaceFS; FS[fsIndex++] = _tokens->scalarOverrideFS; // we don't currently ever set primType to PRIM_POINTS for curves, but // if we ever want to view them as just points, this allows point picking to // work. FS[fsIndex++] = isPrimTypePoints? _tokens->pointIdFS : _tokens->pointIdFallbackFS; if (drawStyle == HdSt_BasisCurvesShaderKey::WIRE || drawStyle == HdSt_BasisCurvesShaderKey::POINTS) { FS[fsIndex++] = _tokens->curvesFragmentWire; FS[fsIndex++] = TfToken(); } else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON && normalStyle == HdSt_BasisCurvesShaderKey::ORIENTED){ FS[fsIndex++] = _tokens->curvesFragmentPatch; FS[fsIndex++] = _tokens->curvesFragmentRibbonOriented; FS[fsIndex++] = TfToken(); } else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON && normalStyle == HdSt_BasisCurvesShaderKey::ROUND){ FS[fsIndex++] = _tokens->curvesFragmentPatch; FS[fsIndex++] = _tokens->curvesFragmentRibbonRound; FS[fsIndex++] = TfToken(); } else if (drawStyle == HdSt_BasisCurvesShaderKey::RIBBON && normalStyle == HdSt_BasisCurvesShaderKey::HAIR){ FS[fsIndex++] = _tokens->curvesFragmentPatch; FS[fsIndex++] = _tokens->curvesFragmentHair; FS[fsIndex++] = TfToken(); } else if (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE && normalStyle == HdSt_BasisCurvesShaderKey::ROUND){ FS[fsIndex++] = _tokens->curvesFragmentPatch; FS[fsIndex++] = _tokens->curvesFragmentHalfTube; FS[fsIndex++] = TfToken(); } else if (drawStyle == HdSt_BasisCurvesShaderKey::HALFTUBE && normalStyle == HdSt_BasisCurvesShaderKey::HAIR){ FS[fsIndex++] = _tokens->curvesFragmentPatch; FS[fsIndex++] = _tokens->curvesFragmentHair; FS[fsIndex++] = TfToken(); } else{ TF_WARN("Cannot setup fragment shaders for invalid combination of \ basis curves shader key settings."); FS[fsIndex++] = _tokens->curvesFragmentHair; FS[fsIndex++] = TfToken(); } }
static void _AddClipsFromNode(const PcpPrimIndex& primIndex, Usd_ClipCache::Clips* clips) { Usd_ResolvedClipInfo clipInfo; auto node = Usd_ResolveClipInfo(primIndex, &clipInfo); // If we haven't found all of the required clip metadata we can just // bail out. Note that clipTimes and clipManifestAssetPath are *not* // required. if (!clipInfo.clipAssetPaths || !clipInfo.clipPrimPath || !clipInfo.clipActive) { return; } // The clip manifest is currently optional but can greatly improve // performance if specified. For debugging performance problems, // issue a message indicating if one hasn't been specified. if (!clipInfo.clipManifestAssetPath) { TF_DEBUG(USD_CLIPS).Msg( "No clip manifest specified for prim <%s>. " "Performance may be improved if a manifest is specified.", primIndex.GetPath().GetString().c_str()); } // XXX: Possibly want a better way to inform consumers of the error // message.. std::string error; if (!_ValidateClipFields( *clipInfo.clipAssetPaths, *clipInfo.clipPrimPath, *clipInfo.clipActive, &error)) { TF_WARN( "Invalid clips specified for prim <%s> in LayerStack %s: %s", node.GetPath().GetString().c_str(), TfStringify(node.GetLayerStack()).c_str(), error.c_str()); return; } // If a clip manifest has been specified, create a clip for it. if (clipInfo.clipManifestAssetPath) { const Usd_ClipRefPtr clip(new Usd_Clip( /* clipSourceNode = */ node, /* clipSourceLayerIndex = */ clipInfo.indexOfLayerWhereAssetPathsFound, /* clipAssetPath = */ *clipInfo.clipManifestAssetPath, /* clipPrimPath = */ SdfPath(*clipInfo.clipPrimPath), /* clipStartTime = */ Usd_ClipTimesEarliest, /* clipEndTime = */ Usd_ClipTimesLatest, /* clipTimes = */ Usd_Clip::TimeMappings())); clips->manifestClip = clip; } // Generate a mapping of startTime -> clip entry. This allows us to // quickly determine the (startTime, endTime) for a given clip. typedef std::map<double, Usd_ClipEntry> _TimeToClipMap; _TimeToClipMap startTimeToClip; for (const auto& startFrameAndClipIndex : *clipInfo.clipActive) { const double startFrame = startFrameAndClipIndex[0]; const int clipIndex = (int)(startFrameAndClipIndex[1]); const SdfAssetPath& assetPath = (*clipInfo.clipAssetPaths)[clipIndex]; Usd_ClipEntry entry; entry.startTime = startFrame; entry.clipAssetPath = assetPath; entry.clipPrimPath = SdfPath(*clipInfo.clipPrimPath); // Validation should have caused us to bail out if there were any // conflicting clip activations set. TF_VERIFY(startTimeToClip.insert( std::make_pair(entry.startTime, entry)).second); } // Build up the final vector of clips. const _TimeToClipMap::const_iterator itBegin = startTimeToClip.begin(); const _TimeToClipMap::const_iterator itEnd = startTimeToClip.end(); _TimeToClipMap::const_iterator it = startTimeToClip.begin(); while (it != itEnd) { const Usd_ClipEntry clipEntry = it->second; const Usd_Clip::ExternalTime clipStartTime = (it == itBegin ? Usd_ClipTimesEarliest : it->first); ++it; const Usd_Clip::ExternalTime clipEndTime = (it == itEnd ? Usd_ClipTimesLatest : it->first); // Generate the clip time mapping that applies to this clip. Usd_Clip::TimeMappings timeMapping; if (clipInfo.clipTimes) { for (const auto& clipTime : *clipInfo.clipTimes) { const Usd_Clip::ExternalTime extTime = clipTime[0]; const Usd_Clip::InternalTime intTime = clipTime[1]; if (clipStartTime <= extTime && extTime < clipEndTime) { timeMapping.push_back( Usd_Clip::TimeMapping(extTime, intTime)); } } } const Usd_ClipRefPtr clip(new Usd_Clip( /* clipSourceNode = */ node, /* clipSourceLayerIndex = */ clipInfo.indexOfLayerWhereAssetPathsFound, /* clipAssetPath = */ clipEntry.clipAssetPath, /* clipPrimPath = */ clipEntry.clipPrimPath, /* clipStartTime = */ clipStartTime, /* clipEndTime = */ clipEndTime, /* clipTimes = */ timeMapping)); clips->valueClips.push_back(clip); } clips->sourceNode = node; clips->sourceLayerIndex = clipInfo.indexOfLayerWhereAssetPathsFound; }
// 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); }
bool HdxColorCorrectionTask::_CreateFramebufferResources(GLuint *texture) { // If framebufferSize is not provided we use the viewport size. // This can be incorrect if the client/app has changed the viewport to // be different then the render window size. (E.g. UsdView CameraMask mode) GfVec2i fboSize = _framebufferSize; if (fboSize[0] <= 0 || fboSize[1] <= 0) { GLint res[4] = {0}; glGetIntegerv(GL_VIEWPORT, res); fboSize = GfVec2i(res[2], res[3]); } bool createTexture = (_texture == 0 || fboSize != _textureSize); if (createTexture) { if (_texture != 0) { glDeleteTextures(1, &_texture); _texture = 0; } _textureSize = fboSize; GLint restoreTexture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &restoreTexture); glGenTextures(1, texture); glBindTexture(GL_TEXTURE_2D, *texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // XXX For step 1 we copy the client FBO texture, apply gamma to the // copy and write it back to the client texture. // A future step will likely create a 16F texture at the start of // hydra rendering and use color-correction to render the results back // into the client FBO texture. // XXX For now we assume we always want R16F. We could perhaps expose // this as client-API in HdxColorCorrectionTaskParams. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, _textureSize[0], _textureSize[1], 0, GL_RGBA, GL_FLOAT, 0); glBindTexture(GL_TEXTURE_2D, restoreTexture); } bool switchedGLContext = !_owningContext || !_owningContext->IsCurrent(); if (switchedGLContext) { // If we're rendering with a different context than the render pass // was created with, recreate the FBO because FB is not shared. // XXX we need this since we use a FBO in _CopyTexture(). Ideally we // use HdxCompositor to do the copy, but for that we need to know the // textureId currently bound to the default framebuffer. However // glGetFramebufferAttachmentParameteriv will return and error when // trying to query the texture name bound to GL_BACK_LEFT. if (_owningContext && _owningContext->IsValid()) { GlfGLContextScopeHolder contextHolder(_owningContext); glDeleteFramebuffers(1, &_framebuffer); } _owningContext = GlfGLContext::GetCurrentGLContext(); if (!TF_VERIFY(_owningContext, "No valid GL context")) { return false; } if (_framebuffer == 0) { glGenFramebuffers(1, &_framebuffer); } } if (createTexture || switchedGLContext) { GLint restoreReadFB, restoreDrawFB; glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &restoreReadFB); glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &restoreDrawFB); glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, restoreReadFB); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, restoreDrawFB); } GLF_POST_PENDING_GL_ERRORS(); return true; }
/* virtual */ void HdxLight::Sync(HdSceneDelegate *sceneDelegate, HdRenderParam *renderParam, HdDirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); TF_UNUSED(renderParam); SdfPath const &id = GetID(); if (!TF_VERIFY(sceneDelegate != nullptr)) { return; } // HdxLight communicates to the scene graph and caches all interesting // values within this class. // later on Get() is called from TaskState (RenderPass) to perform // aggregation/pre-computation, in order to make the shader execution // efficient. HdDirtyBits bits = *dirtyBits; // Change tracking // Transform if (bits & DirtyTransform) { VtValue transform = sceneDelegate->Get(id, HdxLightTokens->transform); if (transform.IsHolding<GfMatrix4d>()) { _params[HdxLightTokens->transform] = transform; } else { _params[HdxLightTokens->transform] = GfMatrix4d(1); } } // Lighting Params if (bits & DirtyParams) { _params[HdxLightTokens->params] = sceneDelegate->Get(id, HdxLightTokens->params); } // Shadow Params if (bits & DirtyShadowParams) { _params[HdxLightTokens->shadowParams] = sceneDelegate->Get(id, HdxLightTokens->shadowParams); } // Shadow Collection if (bits & DirtyCollection) { VtValue vtShadowCollection = sceneDelegate->Get(id, HdxLightTokens->shadowCollection); // Optional if (vtShadowCollection.IsHolding<HdRprimCollection>()) { HdRprimCollection newCollection = vtShadowCollection.UncheckedGet<HdRprimCollection>(); if (_params[HdxLightTokens->shadowCollection] != newCollection) { _params[HdxLightTokens->shadowCollection] = newCollection; HdChangeTracker& changeTracker = sceneDelegate->GetRenderIndex().GetChangeTracker(); changeTracker.MarkCollectionDirty(newCollection.GetName()); } } else { _params[HdxLightTokens->shadowCollection] = HdRprimCollection(); } } *dirtyBits = Clean; }
UsdEditContext::~UsdEditContext() { // Stage should never allow an invalid EditTarget to be set... if (_stage and TF_VERIFY(_originalEditTarget.IsValid())) _stage->SetEditTarget(_originalEditTarget); }
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); }
/* virtual */ void HdStLight::Sync(HdSceneDelegate *sceneDelegate, HdRenderParam *renderParam, HdDirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); TF_UNUSED(renderParam); SdfPath const &id = GetId(); if (!TF_VERIFY(sceneDelegate != nullptr)) { return; } // HdStLight communicates to the scene graph and caches all interesting // values within this class. Later on Get() is called from // TaskState (RenderPass) to perform aggregation/pre-computation, // in order to make the shader execution efficient. // Change tracking HdDirtyBits bits = *dirtyBits; // Transform if (bits & DirtyTransform) { VtValue transform = sceneDelegate->Get(id, HdLightTokens->transform); if (transform.IsHolding<GfMatrix4d>()) { _params[HdLightTokens->transform] = transform; } else { _params[HdLightTokens->transform] = GfMatrix4d(1); } } // Lighting Params if (bits & DirtyParams) { // If it is an area light we will extract the parameters and convert // them to a gl friendly representation. if (_lightType == HdPrimTypeTokens->simpleLight) { _params[HdLightTokens->params] = sceneDelegate->Get(id, HdLightTokens->params); } else { _params[HdLightTokens->params] = _ApproximateAreaLight(id, sceneDelegate); } } // Shadow Params if (bits & DirtyShadowParams) { _params[HdLightTokens->shadowParams] = sceneDelegate->Get(id, HdLightTokens->shadowParams); } // Shadow Collection if (bits & DirtyCollection) { VtValue vtShadowCollection = sceneDelegate->Get(id, HdLightTokens->shadowCollection); // Optional if (vtShadowCollection.IsHolding<HdRprimCollection>()) { HdRprimCollection newCollection = vtShadowCollection.UncheckedGet<HdRprimCollection>(); if (_params[HdLightTokens->shadowCollection] != newCollection) { _params[HdLightTokens->shadowCollection] = newCollection; HdChangeTracker& changeTracker = sceneDelegate->GetRenderIndex().GetChangeTracker(); changeTracker.MarkCollectionDirty(newCollection.GetName()); } } else { _params[HdLightTokens->shadowCollection] = HdRprimCollection(); } } *dirtyBits = Clean; }
PXR_NAMESPACE_USING_DIRECTIVE void TestTemplates() { // --------------------------------------------------------------------- // // This test operates on /RootPrim.foo // and /RootPrim.foo:hidden // --------------------------------------------------------------------- // SdfPath primPath("/RootPrim"); TfToken prop("foo"); TfToken metaField("hidden"); std::string propPath(primPath.GetString() + "." + prop.GetString()); // --------------------------------------------------------------------- // // Author scene and compose the Stage // --------------------------------------------------------------------- // SdfLayerRefPtr layer = SdfLayer::CreateAnonymous(); UsdStageRefPtr stage = UsdStage::Open(layer->GetIdentifier()); TF_VERIFY(stage->OverridePrim(primPath), "Failed to create prim at %s", primPath.GetText()); UsdPrim prim(stage->GetPrimAtPath(primPath)); TF_VERIFY(prim, "Failed to get Prim from %s", primPath.GetText()); // Grab the attribute we will be testing with. UsdAttribute attr = prim.CreateAttribute(prop, SdfValueTypeNames->Double3Array); TF_VERIFY(attr, "Failed to create property at %s", propPath.c_str()); // --------------------------------------------------------------------- // // Setup some test data // --------------------------------------------------------------------- // VtVec3dArray vtVecOut(1); VtVec3dArray vtVecIn; std::string tmp; VtValue value; // ===================================================================== // // TEST READING METADATA // ===================================================================== // // --------------------------------------------------------------------- // // GetMetadata & SetMetadata the value as a VtValue // --------------------------------------------------------------------- // TF_VERIFY(attr.SetMetadata(metaField, VtValue(true)), "VtValue: Failed to set hidden metadata at %s", propPath.c_str()); // Print the layer for debugging. layer->ExportToString(&tmp); std::cout << "-----------------------------------------" << std::endl; std::cout << "Metadata -- VtValue:" << std::endl; std::cout << tmp << std::endl; // Verify the result. TF_VERIFY(attr.GetMetadata(metaField, &value), "Metadata -- VtValue: Failed to get property value at %s", propPath.c_str()); TF_VERIFY(value.IsHolding<bool>(), "Metadata -- VtValue: not holding bool%s", propPath.c_str()); TF_VERIFY(value.Get<bool>(), "Metadata -- VtValue: value was not true %s", propPath.c_str()); // --------------------------------------------------------------------- // // GetMetadata & SetMetadata the value as bool // --------------------------------------------------------------------- // bool valueIn = false; TF_VERIFY(attr.SetMetadata(metaField, true), "Metadata -- bool: Failed to set property at %s", propPath.c_str()); // Print the layer for debugging. tmp = ""; layer->ExportToString(&tmp); std::cout << "-----------------------------------------" << std::endl; std::cout << "Metadata -- bool:" << std::endl; std::cout << tmp << std::endl; // Verify Result. TF_VERIFY(attr.GetMetadata(metaField, &valueIn), "Metadata -- bool: Failed to get property value at %s", propPath.c_str()); TF_VERIFY(valueIn, "Metadata -- bool: value was not true %s", propPath.c_str()); // ===================================================================== // // TEST READING VALUES // ===================================================================== // // --------------------------------------------------------------------- // // Get & Set the value as a VtValue // --------------------------------------------------------------------- // vtVecOut[0] = GfVec3d(9,8,7); TF_VERIFY(attr.Set(VtValue(vtVecOut)), "VtValue: Failed to set property at %s", propPath.c_str()); // Print the layer for debugging. layer->ExportToString(&tmp); std::cout << "-----------------------------------------" << std::endl; std::cout << "VtValue:" << std::endl; std::cout << tmp << std::endl; // Verify the result. TF_VERIFY(attr.Get(&value), "VtValue: Failed to get property value at %s", propPath.c_str()); TF_VERIFY(value.IsHolding<VtVec3dArray>(), "VtValue: not holding VtVec3dArray %s", propPath.c_str()); TF_VERIFY(value.Get<VtVec3dArray>()[0] == vtVecOut[0], "VtValue: VtVec3d[0] does not match %s", propPath.c_str()); // --------------------------------------------------------------------- // // Get & Set the value as a VtArray // --------------------------------------------------------------------- // vtVecOut[0] = GfVec3d(6,5,4); TF_VERIFY(attr.Set(vtVecOut), "Failed to set property at %s", propPath.c_str()); // Print the layer for debugging. tmp = ""; layer->ExportToString(&tmp); std::cout << "-----------------------------------------" << std::endl; std::cout << "VtArray:" << std::endl; std::cout << tmp << std::endl; // Verify Result. TF_VERIFY(attr.Get(&vtVecIn), "VtArray: Failed to get property value at %s", propPath.c_str()); TF_VERIFY(vtVecIn[0] == vtVecOut[0], "VtArray: VtVec3d[0] does not match %s", propPath.c_str()); // --------------------------------------------------------------------- // // Get & Set the value as a VtDictionary (Dictionary composition semantics // are exercised in testUsdMetadata). // --------------------------------------------------------------------- // VtDictionary inDict; inDict["$Side"] = "R"; TF_VERIFY(!prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions)); TF_VERIFY(prim.SetMetadata(SdfFieldKeys->PrefixSubstitutions, inDict)); VtDictionary outDict; TF_VERIFY(prim.HasAuthoredMetadata(SdfFieldKeys->PrefixSubstitutions)); // Verify bug 97783 - GetMetadata should return true if Usd was able to // retrieve/compose a VtDictionary. TF_VERIFY(prim.GetMetadata(SdfFieldKeys->PrefixSubstitutions,&outDict)); TF_VERIFY(inDict == outDict); std::cout << "-----------------------------------------" << std::endl; std::cout << "VtDictionary:" << std::endl; tmp = ""; layer->ExportToString(&tmp); std::cout << tmp << std::endl; }
void UsdMayaGLBatchRenderer::TaskDelegate::_SetLightingStateFromLightingContext() { const GlfSimpleLightVector& lights = _lightingContext->GetLights(); bool hasNumLightsChanged = false; // Insert light Ids into the render index for those that do not yet exist. while (_lightIds.size() < lights.size()) { SdfPath lightId( TfStringPrintf("%s/light%d", _rootId.GetText(), (int)_lightIds.size())); _lightIds.push_back(lightId); // Since we're hardcoded to use HdStRenderDelegate, we expect to have // light Sprims. TF_VERIFY(GetRenderIndex().IsSprimTypeSupported(HdPrimTypeTokens->light)); GetRenderIndex().InsertSprim(HdPrimTypeTokens->light, this, lightId); hasNumLightsChanged = true; } // Remove unused light Ids from HdRenderIndex while (_lightIds.size() > lights.size()) { GetRenderIndex().RemoveSprim(HdPrimTypeTokens->light, _lightIds.back()); _lightIds.pop_back(); hasNumLightsChanged = true; } // invalidate HdLights for (size_t i = 0; i < lights.size(); ++i) { _ValueCache &cache = _valueCacheMap[_lightIds[i]]; // store GlfSimpleLight directly. cache[HdStLightTokens->params] = VtValue(lights[i]); cache[HdStLightTokens->transform] = VtValue(); cache[HdStLightTokens->shadowParams] = VtValue(HdxShadowParams()); cache[HdStLightTokens->shadowCollection] = VtValue(); // Only mark as dirty the parameters to avoid unnecessary invalidation // specially marking as dirty lightShadowCollection will trigger // a collection dirty on geometry and we don't want that to happen // always GetRenderIndex().GetChangeTracker().MarkSprimDirty( _lightIds[i], HdStLight::AllDirty); } // sadly the material also comes from lighting context right now... HdxSimpleLightTaskParams taskParams = _GetValue<HdxSimpleLightTaskParams>(_simpleLightTaskId, HdTokens->params); taskParams.sceneAmbient = _lightingContext->GetSceneAmbient(); taskParams.material = _lightingContext->GetMaterial(); // invalidate HdxSimpleLightTask too if (hasNumLightsChanged) { _SetValue(_simpleLightTaskId, HdTokens->params, taskParams); GetRenderIndex().GetChangeTracker().MarkTaskDirty( _simpleLightTaskId, HdChangeTracker::DirtyParams); } }
static void CameraAndLightTest() { HdStRenderDelegate renderDelegate; std::unique_ptr<HdRenderIndex> index(HdRenderIndex::New(&renderDelegate)); TF_VERIFY(index); std::unique_ptr<Hdx_UnitTestDelegate> delegate( new Hdx_UnitTestDelegate(index.get())); HdChangeTracker& tracker = index->GetChangeTracker(); HdPerfLog& perfLog = HdPerfLog::GetInstance(); perfLog.Enable(); HdRprimCollection collection(HdTokens->geometry, HdTokens->hull); HdRenderPassStateSharedPtr renderPassState(new HdRenderPassState()); HdRenderPassSharedPtr renderPass( new HdSt_RenderPass(index.get(), collection)); HdEngine engine; HdTaskSharedPtr drawTask = boost::make_shared<Hd_TestTask>(renderPass, renderPassState); HdTaskSharedPtrVector tasks = { drawTask }; GfMatrix4d tx(1.0f); tx.SetRow(3, GfVec4f(5, 0, 5, 1.0)); SdfPath cube("geometry"); delegate->AddCube(cube, tx); SdfPath camera("camera"); SdfPath light("light"); delegate->AddCamera(camera); delegate->AddLight(light, GlfSimpleLight()); delegate->SetLight(light, HdStLightTokens->shadowCollection, VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->hull))); engine.Execute(*index, tasks); VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1); // Update camera matrix delegate->SetCamera(camera, GfMatrix4d(2), GfMatrix4d(2)); tracker.MarkSprimDirty(camera, HdStCamera::DirtyViewMatrix); tracker.MarkSprimDirty(camera, HdStCamera::DirtyProjMatrix); engine.Execute(*index, tasks); // batch should not be rebuilt VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 1); // Update shadow collection delegate->SetLight(light, HdStLightTokens->shadowCollection, VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->refined))); tracker.MarkSprimDirty(light, HdStLight::DirtyCollection); engine.Execute(*index, tasks); // batch rebuilt VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2); // Update shadow collection again with the same data delegate->SetLight(light, HdStLightTokens->shadowCollection, VtValue(HdRprimCollection(HdTokens->geometry, HdTokens->refined))); tracker.MarkSprimDirty(light, HdStLight::DirtyCollection); engine.Execute(*index, tasks); // batch should not be rebuilt VERIFY_PERF_COUNT(HdPerfTokens->rebuildBatches, 2); }