static bool _IsMatrixIdentity(const GfMatrix4d& matrix) { const GfMatrix4d IDENTITY(1.0); const double TOLERANCE = 1e-6; if (GfIsClose(matrix.GetRow(0), IDENTITY.GetRow(0), TOLERANCE) && GfIsClose(matrix.GetRow(1), IDENTITY.GetRow(1), TOLERANCE) && GfIsClose(matrix.GetRow(2), IDENTITY.GetRow(2), TOLERANCE) && GfIsClose(matrix.GetRow(3), IDENTITY.GetRow(3), TOLERANCE)) { return true; } return false; }
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); }