Autodesk / maya-usd

A common USD (Universal Scene Description) plugin for Autodesk Maya
765 stars 201 forks source link

Color Shift on srgb textures in the viewport #2949

Open jossh-h opened 1 year ago

jossh-h commented 1 year ago

Describe the bug Hi there, 

We (AL) have encountered an bug where we see a color shift which seems to be due to an issue with the _localTextureMap and the texture manager becoming out of sync.  We have a workflow where the stage contains a geom and material in one variant and we need to switch to another variant where the geom and material do not exist, during the switching there are two important things happen: 

 If we then switch back to previous variant, we can observe a color shift    This seems to be due to the fact that Maya's MTextureManager still holds a reference to the texture (and will return early), but the HdVP2TextureInfoSharedPtr object which holds the HdVP2TextureInfo _isColorSpaceSRGB info has been destroyed during the de-construction of HdVP2Material, in our case, _LoadTexture returns the texture but leaving the isSRGB  and uvScaleOffset being default value which is the discrepancy we found    I have attached a code snippet, layer and jpg texture to repro this      Could you advise on the best option to fix this?

Steps to reproduce Steps to reproduce the behavior:

  1. Download/save the attached srgbColorChart.jpg texture and simplePlaneMaterial.usda layer
  2. Update the rootLayer and srgbTexture path variables in the attached srgb_texture_scene_setup.py file and execute
  3. You should observe the following color shift USD Geom on the left, Maya poly mesh on the right image

Expected behavior We would expect no color shift to take place during variant switching / activation toggling

Attachments srgbColorChart

simplePlaneMaterial.usda

#usda 1.0
(
)

def Xform "plane01" (
    kind = "component"
)
{
    def Mesh "planeMesh" (
        apiSchemas = ["MaterialBindingAPI"]
    )
    {
        float3[] extent = [(-145, -145, 0), (145, 145, 0)]
        int[] faceVertexCounts = [4]
        int[] faceVertexIndices = [0, 1, 2, 3]
        rel material:binding = </plane01/planeMaterial>
        point3f[] points = [(-145, -145, 0), (145, -145, 0), (145, 145, 0), (-145, 145, 0)]
        texCoord2f[] primvars:st = [(0, 0), (1, 0), (1, 1), (0, 1)] (
            interpolation = "varying"
        )
    }

    def Material "planeMaterial"
    {
        token inputs:frame:stPrimvarName = "st"
        token outputs:surface.connect = </plane01/planeMaterial/PBRShader.outputs:surface>

        def Shader "PBRShader"
        {
            uniform token info:id = "UsdPreviewSurface"
            color3f inputs:diffuseColor.connect = </plane01/planeMaterial/diffuseTexture.outputs:rgb>
            float inputs:metallic = 0
            float inputs:roughness = 0.4
            token outputs:surface
        }

        def Shader "stReader"
        {
            uniform token info:id = "UsdPrimvarReader_float2"
            token inputs:varname.connect = </plane01/planeMaterial.inputs:frame:stPrimvarName>
            float2 outputs:result
        }

        def Shader "diffuseTexture"
        {
            uniform token info:id = "UsdUVTexture"
            asset inputs:file = @./srgbColorChart.jpg@
            float2 inputs:st.connect = </plane01/planeMaterial/stReader.outputs:result>
            float3 outputs:rgb
        }
    }
}

srgb_texture_scene_setup.py

from functools import partial

import mayaUsd

from maya import cmds

def main():
    # NOTE: ################### UPDATE PATHS ###########################
    # layer contains a relative reference to the srgbColorChart.jpg file.
    rootLayer = "/path/to/simplePlaneMaterial.usda"
    srgbTexture = "/path/to/srgbColorChart.jpg"

    cmds.file(force=True, new=True)

    # Make sure the sync mode is ON (disable async loading)
    cmds.optionVar(intValue=("mayaUsd_DisableAsyncTextureLoading", 1))

    # setup camera
    cmds.xform("persp", translation=(145, 2, 568), rotation=(0, 0, 0), worldSpace=True)
    panel = activeModelPanel()
    cmds.modelEditor(
        panel,
        edit=True,
        lights=False,
        displayLights="default",
        displayTextures=True,
        grid=False,
    )

    # load usd stage
    shapeNode, _ = createProxyFromFile(rootLayer)

    #### setup plane with srgb texture assigned ####
    polyPlaneName, _nodeName = cmds.polyPlane()
    cmds.xform(
        polyPlaneName,
        translation=(290, 0, 0),
        scale=(290, 290, 290),
        rotation=(90, 0, 0),
    )

    # create usdPreviewSufraceShader
    lambertShader = cmds.shadingNode("usdPreviewSurface", asShader=True)
    shaderGroup = cmds.sets(renderable=True, noSurfaceShader=True, empty=True)
    cmds.connectAttr(
        f"{lambertShader}.outColor", f"{shaderGroup}.surfaceShader", force=True
    )

    # create fileTexture node
    fileTexture = cmds.shadingNode("file", asShader=True, isColorManaged=True)
    cmds.setAttr(f"{fileTexture}.fileTextureName", srgbTexture, type="string")
    cmds.connectAttr(
        f"{fileTexture}.outColor", f"{lambertShader}.diffuseColor", force=True
    )

    # assign shader to the polyPlane
    cmds.sets(polyPlaneName, forceElement=shaderGroup)

    cmds.select(cl=True)
    stage = mayaUsd.ufe.getStage(shapeNode)
    prim = stage.GetPrimAtPath("/plane01")
    assert prim.IsValid()

    def toggleState(prim):
        prim.SetActive(False)
        prim.SetActive(True)

    cmds.evalDeferred(partial(toggleState, prim))

def createProxyFromFile(filePath):
    cmds.createNode("mayaUsdProxyShape", name="stageShape")

    shapeNode = cmds.ls(sl=True, l=True)[0]
    cmds.setAttr("{}.filePath".format(shapeNode), filePath, type="string")

    shapeStage = mayaUsd.lib.GetPrim(shapeNode).GetStage()

    cmds.select(clear=True)
    cmds.connectAttr("time1.outTime", "{}.time".format(shapeNode))

    return shapeNode, shapeStage

def activeModelPanel():
    for panel in cmds.getPanel(type="modelPanel"):
        if cmds.modelEditor(panel, q=1, av=1):
            return panel

if __name__ == "__main__":
    main()

Specs (if applicable):

Additional context Add any other context about the problem here.

maya-usd-git-sync[bot] commented 11 months ago

Issue synced internally to EMSUSD-759