Skip to content

Dev/dmotor/fix light linking #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions FireRender.Maya.Src/Context/FireRenderContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,29 @@ void FireRenderContext::cleanScene()
}
}

// detach lights before the rest of the objects to unlink lights correctly
it = m_sceneObjects.begin();
while (it != m_sceneObjects.end())
{
FireRenderLight* fireRenderLight = dynamic_cast<FireRenderLight*> (it->second.get());
FireRenderEnvLight* envLight = dynamic_cast<FireRenderEnvLight*>(it->second.get());

if (fireRenderLight != nullptr)
{
fireRenderLight->detachFromScene();
it = m_sceneObjects.erase(it);
}
else if (envLight != nullptr)
{
envLight->detachFromScene();
it = m_sceneObjects.erase(it);
}
else
{
it++;
}
}

m_sceneObjects.clear();

m_camera.clear();
Expand Down Expand Up @@ -3648,7 +3671,7 @@ void FireRenderContext::ReadDenoiserFrameBuffersIntoRAM(ReadFrameBufferRequestPa
});
}

frw::Light FireRenderContext::GetRprLightFromNode(const MObject& node)
frw::Light FireRenderContext::LinkLightSceneObjectWithCurrentlyParsedMesh(const MObject& node)
{
MUuid uuidPointer = MFnDependencyNode(node).uuid();
MString uuidString = uuidPointer.asString();
Expand Down Expand Up @@ -3682,7 +3705,7 @@ frw::Light FireRenderContext::GetRprLightFromNode(const MObject& node)
return envLight->getLight();
}

MGlobal::displayWarning("light with uuid " + MString(lightObjectPointer->uuid().c_str()) + " is not support linking");
MGlobal::displayWarning("light with uuid " + MString(lightObjectPointer->uuid().c_str()) + " does not support linking");
return frw::Light();

}
2 changes: 1 addition & 1 deletion FireRender.Maya.Src/Context/FireRenderContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ class FireRenderContext : public IFireRenderContextInfo
bool setupDenoiserForViewport();

// used for toon shader light linking
frw::Light GetRprLightFromNode(const MObject& node) override;
frw::Light LinkLightSceneObjectWithCurrentlyParsedMesh(const MObject& node);

protected:
static int INCORRECT_PLUGIN_ID;
Expand Down
3 changes: 0 additions & 3 deletions FireRender.Maya.Src/Context/FireRenderContextIFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,4 @@ class IFireRenderContextInfo
virtual bool IsUberScaleSupported() const = 0;

virtual bool IsGLTFExport() const = 0;

// used for toon shader light linking
virtual frw::Light GetRprLightFromNode(const MObject& node) = 0;
};
28 changes: 28 additions & 0 deletions FireRender.Maya.Src/FireMaya.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1884,6 +1884,21 @@ void FireMaya::Scope::SetCachedShader(const NodeId& id, frw::Shader shader)
m->shaderMap[id] = shader;
}

std::pair<FireMaya::Scope::MMapNodeIdIterator, FireMaya::Scope::MMapNodeIdIterator> FireMaya::Scope::GetCachedShaderIds(const NodeId& lightId)
{
return m->lightShaderMap.equal_range(lightId);
}

void FireMaya::Scope::SetCachedShaderId(const NodeId& lightId, NodeId& shaderId)
{
m->lightShaderMap.insert(std::pair<NodeId, NodeId>(lightId, shaderId));
}

void FireMaya::Scope::ClearCachedShaderIds(const NodeId& lightId)
{
m->lightShaderMap.erase(lightId);
}

void FireMaya::Scope::SetCachedVolumeShader(const NodeId& id, frw::Shader shader)
{
if (!shader)
Expand Down Expand Up @@ -1965,13 +1980,26 @@ frw::Shader FireMaya::Scope::GetShader(MObject node, const FireRenderMeshCommon*

DebugPrint("Parsing shader: %s (forceUpdate=%d, shader.IsDirty()=%d)", shaderId.c_str(), forceUpdate, shader.IsDirty());
m->m_pCurrentlyParsedMesh = pMesh;
m->m_pLastLinkedLight = MObject::kNullObj;

// create now
shader = ParseShader(node);
if (shader.IsValid())
{
SetCachedShader(shaderId, shader);
shader.SetDirty(false);

if (m->m_pLastLinkedLight != MObject::kNullObj)
{
std::string lightId = getNodeUUid(m->m_pLastLinkedLight);

MFnDependencyNode fnNode(m->m_pLastLinkedLight);
std::string fnName = fnNode.name().asChar();

SetCachedShaderId(lightId, shaderId);

m->m_pLastLinkedLight = MObject::kNullObj;
}
}

m->m_pCurrentlyParsedMesh = nullptr;
Expand Down
8 changes: 8 additions & 0 deletions FireRender.Maya.Src/FireMaya.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,14 @@ namespace FireMaya

std::map<NodeId, frw::Shader> volumeShaderMap;
std::map<NodeId, frw::Shader> shaderMap;
std::multimap<NodeId, NodeId> lightShaderMap; // shaderId = lightShaderMap[lightNodeId]
std::map<NodeId, frw::Value> valueMap;
std::map<NodeId, MCallbackId> m_nodeDirtyCallbacks;
std::map<NodeId, MCallbackId> m_AttributeChangedCallbacks;
std::map<std::string, frw::Image> imageCache;

FireRenderMeshCommon const* m_pCurrentlyParsedMesh; // is not supposed to keep any data outside of during mesh parsing
MObject m_pLastLinkedLight; // is not supposed to keep any data outside of during mesh parsing

Data();
~Data();
Expand All @@ -232,6 +234,7 @@ namespace FireMaya
void NodeDirtyCallback(MObject& node);

FireRenderMeshCommon const* GetCurrentlyParsedMesh() const { return m->m_pCurrentlyParsedMesh; }
void SetLastLinkedLight(const MObject& lightObj) const { m->m_pLastLinkedLight = lightObj; }
void SetIsLastPassTextureMissing(bool value) const { m_IsLastPassTextureMissing = value; }

frw::Value createImageFromShaderNode(MObject node, MString plugName = "outColor", int width = 256, int height = 256) const;
Expand Down Expand Up @@ -329,6 +332,11 @@ namespace FireMaya
frw::Shader GetCachedShader(const NodeId& str) const;
void SetCachedShader(const NodeId& str, frw::Shader shader);

typedef std::multimap<NodeId, NodeId>::iterator MMapNodeIdIterator;
std::pair<MMapNodeIdIterator, MMapNodeIdIterator> GetCachedShaderIds(const NodeId& lightId);
void SetCachedShaderId(const NodeId& lightId, NodeId& shaderId);// shaderId = lightShaderMap[lightNodeId]
void ClearCachedShaderIds(const NodeId& lightId);

void Reset();
void Init(rpr_context handle, bool destroyMaterialSystemOnDelete = true, bool createScene = true);
void CreateScene(void);
Expand Down
30 changes: 30 additions & 0 deletions FireRender.Maya.Src/FireRenderObjects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,6 +2028,23 @@ void FireRenderLight::detachFromScene()
if (!m_isVisible)
return;

FireMaya::Scope& scope = context()->GetScope();

MFnDependencyNode fnNode(Object());
std::string fnName = fnNode.name().asChar();

std::string lightId = getNodeUUid(Object());
auto shaderIds = scope.GetCachedShaderIds(lightId);
for (auto it = shaderIds.first; it != shaderIds.second; ++it)
{
frw::Shader linkedShader = scope.GetCachedShader(it->second);
linkedShader.ClearLinkedLight(GetFrLight().light);
}
if (std::distance(shaderIds.first, shaderIds.second) != 0)
{
scope.ClearCachedShaderIds(lightId);
}

if (auto scene = Scene())
{
if (m_light.isAreaLight && m_light.areaLight)
Expand Down Expand Up @@ -2244,6 +2261,19 @@ void FireRenderEnvLight::detachFromScene()
if (!m_isVisible)
return;

FireMaya::Scope& scope = context()->GetScope();
std::string lightId = getNodeUUid(Object());
auto shaderIds = scope.GetCachedShaderIds(lightId);
for (auto it = shaderIds.first; it != shaderIds.second; ++it)
{
frw::Shader linkedShader = scope.GetCachedShader(it->second);
linkedShader.ClearLinkedLight(getLight());
}
if (std::distance(shaderIds.first, shaderIds.second) != 0)
{
scope.ClearCachedShaderIds(lightId);
}

if (auto scene = Scene())
{
detachFromSceneInternal();
Expand Down
12 changes: 10 additions & 2 deletions FireRender.Maya.Src/FireRenderToonMaterial.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "FireRenderToonMaterial.h"
#include "FireMaya.h"
#include "FireRenderUtils.h"
#include "Context/FireRenderContext.h"
#include <maya/MSelectionList.h>
#include <maya/MUuid.h>
#include <maya/MDGMessage.h>
Expand Down Expand Up @@ -339,14 +340,21 @@ void FireMaya::ToonMaterial::linkLight(Scope& scope, frw::Shader& shader)
return;
}

frw::Light rprLight = scope.GetIContextInfo()->GetRprLightFromNode(light);
FireRenderContext* pContext = dynamic_cast<FireRenderContext*>(scope.GetIContextInfo());
if (!pContext)
{
return;
}

frw::Light rprLight = pContext->LinkLightSceneObjectWithCurrentlyParsedMesh(light);

if (!rprLight.IsValid())
{
return;
}

shader.xSetParameterLight(RPR_MATERIAL_INPUT_LIGHT, rprLight);
pContext->GetScope().SetLastLinkedLight(light);
shader.LinkLight(rprLight);
}

bool checkIsLight(MObject& node)
Expand Down
23 changes: 20 additions & 3 deletions FireRender.Maya.Src/frWrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -3712,10 +3712,27 @@ namespace frw
return false;
}

void xSetParameterLight(rpr_material_node_input parameter, Light light)
void LinkLight(const Light& light)
{
const Data& d = data();
rpr_int res = rprMaterialNodeSetInputLightDataByKey(Handle(), parameter, light.Handle());
AddReference(light);

rpr_int res = rprMaterialNodeSetInputLightDataByKey(Handle(), RPR_MATERIAL_INPUT_LIGHT, light.Handle());
if (res == RPR_ERROR_UNSUPPORTED ||
res == RPR_ERROR_INVALID_PARAMETER)
{
// print error/warning if needed
}
else
{
checkStatus(res);
}
}

void ClearLinkedLight(const Light& light)
{
RemoveReference(light);

rpr_int res = rprMaterialNodeSetInputLightDataByKey(Handle(), RPR_MATERIAL_INPUT_LIGHT, nullptr);
if (res == RPR_ERROR_UNSUPPORTED ||
res == RPR_ERROR_INVALID_PARAMETER)
{
Expand Down