void GlfSimpleLightingContext::SetStateFromOpenGL() { // import classic GL light's parameters into shaded lights SetUseLighting(glIsEnabled(GL_LIGHTING)); GfMatrix4d worldToViewMatrix; glGetDoublev(GL_MODELVIEW_MATRIX, worldToViewMatrix.GetArray()); GfMatrix4d viewToWorldMatrix = worldToViewMatrix.GetInverse(); GLint nLights = 0; glGetIntegerv(GL_MAX_LIGHTS, &nLights); GlfSimpleLightVector lights; lights.reserve(nLights); GlfSimpleLight light; for(int i = 0; i < nLights; ++i) { int lightName = GL_LIGHT0 + i; if (glIsEnabled(lightName)) { GLfloat position[4], color[4]; glGetLightfv(lightName, GL_POSITION, position); light.SetPosition(GfVec4f(position)*viewToWorldMatrix); glGetLightfv(lightName, GL_AMBIENT, color); light.SetAmbient(GfVec4f(color)); glGetLightfv(lightName, GL_DIFFUSE, color); light.SetDiffuse(GfVec4f(color)); glGetLightfv(lightName, GL_SPECULAR, color); light.SetSpecular(GfVec4f(color)); lights.push_back(light); } } SetLights(lights); GlfSimpleMaterial material; GLfloat color[4], shininess; glGetMaterialfv(GL_FRONT, GL_AMBIENT, color); material.SetAmbient(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color); material.SetDiffuse(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_SPECULAR, color); material.SetSpecular(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_EMISSION, color); material.SetEmission(GfVec4f(color)); glGetMaterialfv(GL_FRONT, GL_SHININESS, &shininess); // clamp to 0.0001, since pow(0,0) is undefined in GLSL. shininess = std::max(0.0001f, shininess); material.SetShininess(shininess); SetMaterial(material); GfVec4f sceneAmbient; glGetFloatv(GL_LIGHT_MODEL_AMBIENT, &sceneAmbient[0]); SetSceneAmbient(sceneAmbient); }
void HdRprim::_PopulateConstantPrimVars(HdSceneDelegate* delegate, HdDrawItem *drawItem, HdDirtyBits *dirtyBits) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); SdfPath const& id = GetId(); HdRenderIndex &renderIndex = delegate->GetRenderIndex(); HdResourceRegistry *resourceRegistry = &HdResourceRegistry::GetInstance(); // XXX: this should be in a different method // XXX: This should be in HdSt getting the HdSt Shader const HdShader *shader = static_cast<const HdShader *>( renderIndex.GetSprim(HdPrimTypeTokens->shader, _surfaceShaderID)); if (shader == nullptr) { shader = static_cast<const HdShader *>( renderIndex.GetFallbackSprim(HdPrimTypeTokens->shader)); } _sharedData.surfaceShader = shader->GetShaderCode(); // update uniforms HdBufferSourceVector sources; if (HdChangeTracker::IsTransformDirty(*dirtyBits, id)) { GfMatrix4d transform = delegate->GetTransform(id); _sharedData.bounds.SetMatrix(transform); // for CPU frustum culling HdBufferSourceSharedPtr source(new HdVtBufferSource( HdTokens->transform, transform)); sources.push_back(source); source.reset(new HdVtBufferSource(HdTokens->transformInverse, transform.GetInverse())); sources.push_back(source); // if this is a prototype (has instancer), // also push the instancer transform separately. if (!_instancerID.IsEmpty()) { // gather all instancer transforms in the instancing hierarchy VtMatrix4dArray rootTransforms = _GetInstancerTransforms(delegate); VtMatrix4dArray rootInverseTransforms(rootTransforms.size()); bool leftHanded = transform.IsLeftHanded(); for (size_t i = 0; i < rootTransforms.size(); ++i) { rootInverseTransforms[i] = rootTransforms[i].GetInverse(); // flip the handedness if necessary leftHanded ^= rootTransforms[i].IsLeftHanded(); } source.reset(new HdVtBufferSource( HdTokens->instancerTransform, rootTransforms, /*staticArray=*/true)); sources.push_back(source); source.reset(new HdVtBufferSource( HdTokens->instancerTransformInverse, rootInverseTransforms, /*staticArray=*/true)); sources.push_back(source); // XXX: It might be worth to consider to have isFlipped // for non-instanced prims as well. It can improve // the drawing performance on older-GPUs by reducing // fragment shader cost, although it needs more GPU memory. // set as int (GLSL needs 32-bit align for bool) source.reset(new HdVtBufferSource( HdTokens->isFlipped, VtValue(int(leftHanded)))); sources.push_back(source); } } if (HdChangeTracker::IsExtentDirty(*dirtyBits, id)) { _sharedData.bounds.SetRange(GetExtent(delegate)); GfVec3d const & localMin = drawItem->GetBounds().GetBox().GetMin(); HdBufferSourceSharedPtr sourceMin(new HdVtBufferSource( HdTokens->bboxLocalMin, VtValue(GfVec4f( localMin[0], localMin[1], localMin[2], 0)))); sources.push_back(sourceMin); GfVec3d const & localMax = drawItem->GetBounds().GetBox().GetMax(); HdBufferSourceSharedPtr sourceMax(new HdVtBufferSource( HdTokens->bboxLocalMax, VtValue(GfVec4f( localMax[0], localMax[1], localMax[2], 0)))); sources.push_back(sourceMax); } if (HdChangeTracker::IsPrimIdDirty(*dirtyBits, id)) { GfVec4f primIdColor; int32_t primId = GetPrimId(); HdBufferSourceSharedPtr source(new HdVtBufferSource( HdTokens->primID, VtValue(primId))); sources.push_back(source); } if (HdChangeTracker::IsAnyPrimVarDirty(*dirtyBits, id)) { TfTokenVector primVarNames = delegate->GetPrimVarConstantNames(id); sources.reserve(sources.size()+primVarNames.size()); TF_FOR_ALL(nameIt, primVarNames) { if (HdChangeTracker::IsPrimVarDirty(*dirtyBits, id, *nameIt)) { VtValue value = delegate->Get(id, *nameIt); // XXX Hydra doesn't support string primvar yet if (value.IsHolding<std::string>()) continue; if (!value.IsEmpty()) { HdBufferSourceSharedPtr source( new HdVtBufferSource(*nameIt, value)); // if it's an unacceptable type, skip it (e.g. std::string) if (source->GetNumComponents() > 0) { sources.push_back(source); } } } } }
void GlfSimpleLightingContext::BindUniformBlocks(GlfBindingMapPtr const &bindingMap) { if (not _lightingUniformBlock) _lightingUniformBlock = GlfUniformBlock::New(); if (not _shadowUniformBlock) _shadowUniformBlock = GlfUniformBlock::New(); if (not _materialUniformBlock) _materialUniformBlock = GlfUniformBlock::New(); bool shadowExists = false; if ((not _lightingUniformBlockValid or not _shadowUniformBlockValid) and _lights.size() > 0) { int numLights = GetNumLightsUsed(); // 16byte aligned struct LightSource { float position[4]; float ambient[4]; float diffuse[4]; float specular[4]; float spotDirection[4]; float spotCutoff; float spotFalloff; float padding[2]; float attenuation[4]; bool hasShadow; int32_t shadowIndex; int32_t padding2[2]; }; struct Lighting { int32_t useLighting; int32_t useColorMaterialDiffuse; int32_t padding[2]; LightSource lightSource[0]; }; // 16byte aligned struct ShadowMatrix { float viewToShadowMatrix[16]; float basis0[4]; float basis1[4]; float basis2[4]; float bias; float padding[3]; }; struct Shadow { ShadowMatrix shadow[0]; }; size_t lightingSize = sizeof(Lighting) + sizeof(LightSource) * numLights; size_t shadowSize = sizeof(ShadowMatrix) * numLights; Lighting *lightingData = (Lighting *)alloca(lightingSize); Shadow *shadowData = (Shadow *)alloca(shadowSize); memset(shadowData, 0, shadowSize); memset(lightingData, 0, lightingSize); GfMatrix4d viewToWorldMatrix = _worldToViewMatrix.GetInverse(); lightingData->useLighting = _useLighting; lightingData->useColorMaterialDiffuse = _useColorMaterialDiffuse; for (int i = 0; _useLighting and i < numLights; ++i) { GlfSimpleLight const &light = _lights[i]; setVec4(lightingData->lightSource[i].position, light.GetPosition() * _worldToViewMatrix); setVec4(lightingData->lightSource[i].diffuse, light.GetDiffuse()); setVec4(lightingData->lightSource[i].ambient, light.GetAmbient()); setVec4(lightingData->lightSource[i].specular, light.GetSpecular()); setVec3(lightingData->lightSource[i].spotDirection, _worldToViewMatrix.TransformDir(light.GetSpotDirection())); setVec3(lightingData->lightSource[i].attenuation, light.GetAttenuation()); lightingData->lightSource[i].spotCutoff = light.GetSpotCutoff(); lightingData->lightSource[i].spotFalloff = light.GetSpotFalloff(); lightingData->lightSource[i].hasShadow = light.HasShadow(); if (lightingData->lightSource[i].hasShadow) { int shadowIndex = light.GetShadowIndex(); lightingData->lightSource[i].shadowIndex = shadowIndex; GfMatrix4d viewToShadowMatrix = viewToWorldMatrix * _shadows->GetWorldToShadowMatrix(shadowIndex); double invBlur = 1.0/(std::max(0.0001F, light.GetShadowBlur())); GfMatrix4d mat = viewToShadowMatrix.GetInverse(); GfVec4f xVec = GfVec4f(mat.GetRow(0) * invBlur); GfVec4f yVec = GfVec4f(mat.GetRow(1) * invBlur); GfVec4f zVec = GfVec4f(mat.GetRow(2)); shadowData->shadow[shadowIndex].bias = light.GetShadowBias(); setMatrix(shadowData->shadow[shadowIndex].viewToShadowMatrix, viewToShadowMatrix); setVec4(shadowData->shadow[shadowIndex].basis0, xVec); setVec4(shadowData->shadow[shadowIndex].basis1, yVec); setVec4(shadowData->shadow[shadowIndex].basis2, zVec); shadowExists = true; } } _lightingUniformBlock->Update(lightingData, lightingSize); _lightingUniformBlockValid = true; if (shadowExists) { _shadowUniformBlock->Update(shadowData, shadowSize); _shadowUniformBlockValid = true; } } _lightingUniformBlock->Bind(bindingMap, _tokens->lightingUB); if (shadowExists) { _shadowUniformBlock->Bind(bindingMap, _tokens->shadowUB); } if (not _materialUniformBlockValid) { // has to be matched with the definition of simpleLightingShader.glslfx struct Material { float ambient[4]; float diffuse[4]; float specular[4]; float emission[4]; float sceneColor[4]; // XXX: should be separated? float shininess; float padding[3]; } materialData; memset(&materialData, 0, sizeof(materialData)); setVec4(materialData.ambient, _material.GetAmbient()); setVec4(materialData.diffuse, _material.GetDiffuse()); setVec4(materialData.specular, _material.GetSpecular()); setVec4(materialData.emission, _material.GetEmission()); materialData.shininess = _material.GetShininess(); setVec4(materialData.sceneColor, _sceneAmbient); _materialUniformBlock->Update(&materialData, sizeof(materialData)); _materialUniformBlockValid = true; } _materialUniformBlock->Bind(bindingMap, _tokens->materialUB); }