91        Generate shader for a transform from a source color space to a destination color space 
   92        for a given config and shader language. 
   94        Returns the shader code and the number of texture resources required. 
   99            return shaderCode, textureCount
 
  104            processor = config.getProcessor(sourceColorSpace, destColorSpace)
 
  106            print(
'Failed to generated code for transform: %s -> %s' % (sourceColorSpace, destColorSpace))
 
  107            return shaderCode, textureCount
 
  110            gpuProcessor = processor.getDefaultGPUProcessor()
 
  112                shaderDesc = OCIO.GpuShaderDesc.CreateShaderDesc()
 
  115                        shaderDesc.setLanguage(language)
 
  116                        if shaderDesc.getLanguage() == language:
 
  118                            gpuProcessor.extractGpuShaderInfo(shaderDesc)                                                                 
 
  119                            shaderCode = shaderDesc.getShaderText()
 
  121                            for t 
in shaderDesc.getTextures():
 
  125                                shaderCode = shaderCode.replace(
 
  126                                    "// Declaration of the OCIO shader function\n", 
 
  127                                    "// " + sourceColorSpace + 
" to " + destColorSpace + 
" function. Texture count: %d\n" % textureCount)
 
  129                    except OCIO.Exception 
as err:
 
  132        return shaderCode, textureCount
 
 
  163        Scan through all the color spaces on the configs to check for texture resource usage. 
  164        Returns a set of color spaces that require texture resources. 
  166        testedSources = set()
 
  167        textureSources = set()
 
  169            config = OCIO.Config.CreateFromBuiltinConfig(c)
 
  170            colorSpaces = config.getColorSpaces()
 
  171            for colorSpace 
in colorSpaces:
 
  172                colorSpaceName = colorSpace.getName()
 
  174                if colorSpaceName 
in testedSources:
 
  176                testedSources.add(colorSpaceName)
 
  179                code, textureCount = self.
generateShaderCode(config, colorSpace.getName(), targetColorSpace, language)
 
  181                    print(
'- Transform "%s" to "%s" requires %d texture resources' % (colorSpace.getName(), targetColorSpace, textureCount))
 
  182                    textureSources.add(colorSpaceName)
 
  184        return textureSources
 
 
  208        Create a new definition in a document for a given color space transform. 
  209        Returns the definition. 
  213        nodeName = transformName.replace(
'mx_', 
'ND_')
 
  215        comment = doc.addChildOfCategory(
'comment')
 
  216        docString = 
' Color space %s to %s transform. Generated via OCIO. ' % (sourceColorSpace, targetColorSpace)
 
  217        comment.setDocString(docString)
 
  219        definition = doc.addNodeDef(nodeName, 
'color4')
 
  220        category = sourceColorSpace + 
'_to_' + targetColorSpace
 
  221        definition.setNodeString(category)
 
  222        definition.setNodeGroup(
'colortransform')
 
  223        definition.setDocString(docString)
 
  224        definition.setVersionString(
'1.0')
 
  226        defaultValueString = 
'0.0 0.0 0.0 1.0' 
  227        defaultValue = mx.createValueFromStrings(defaultValueString, 
'color4')
 
  228        input = definition.addInput(inputName, type)
 
  229        input.setValue(defaultValue)
 
  230        output = definition.getOutput(
'out')
 
  231        output.setAttribute(
'default', 
'in')
 
 
  248        Create a new implementation in a document for a given definition. 
  250        implName = transformName + 
'_' + target
 
  251        filename = transformName + 
'.' + extension
 
  252        implName = implName.replace(
'mx_', 
'IM_')
 
  255        impl = doc.getImplementation(implName)
 
  257            print(
'Implementation already exists: %s' % implName)
 
  260        comment = doc.addChildOfCategory(
'comment')
 
  261        comment.setDocString(
' Color space %s to %s transform. Generated via OCIO for target: %s'  
  262                            % (sourceColorSpace, targetColorSpace, target))
 
  263        impl = doc.addImplementation(implName)
 
  264        impl.setFile(filename)
 
  265        impl.setFunction(transformName)
 
  266        impl.setTarget(target)
 
  267        impl.setNodeDef(definition)
 
 
  271    def generateOCIO(self, config, definitionDoc, implDoc, sourceColorSpace = 'acescg', targetColorSpace = 'lin_rec709',
 
  272                    type='color4', IN_PIXEL_STRING = 'in'):
 
  274        Generate a MaterialX definition and implementation for a given color space transform.     
  275        Returns the definition, implementation, source code, extension and target. 
  280            [
'genglsl', 
'glsl', OCIO.GpuLanguage.GPU_LANGUAGE_GLSL_4_0]
 
  286        for gen 
in generationList:
 
  291            code, textureCount = self.
generateShaderCode(config, sourceColorSpace, targetColorSpace, language)
 
  295                print(
'- Skip generation for transform: "%s" to "%s" which requires %d texture resources' % (sourceColorSpace, targetColorSpace, textureCount))
 
  303                                                            IN_PIXEL_STRING, type)
 
  310        return definition, transformName, code, extension, target     
 
 
  312    def generateOCIOGraph(self, config, sourceColorSpace = 'acescg', targetColorSpace = 'lin_rec709',
 
  315        Generate a MaterialX nodegraph for a given color space transform. 
  316        @param config: The OCIO configuration. 
  317        @param sourceColorSpace: The source color space. 
  318        @param targetColorSpace: The destination color space. 
  319        @param type: The type of the transform. 
  320        Returns a MaterialX document containing a functional nodegraph and nodedef pair. 
  325        invalidTransforms = [ OCIO.TransformType.TRANSFORM_TYPE_LUT3D, OCIO.TransformType.TRANSFORM_TYPE_LUT1D, 
 
  326                              OCIO.TransformType.TRANSFORM_TYPE_GRADING_PRIMARY ]
 
  329        graphDoc = mx.createDocument()
 
  330        outputType = 
'color3' 
  331        xformName = sourceColorSpace + 
'_to_' + targetColorSpace + 
'_' + outputType
 
  333        nd = graphDoc.addNodeDef(
'ND_' + xformName )
 
  334        nd.setAttribute(
'node', xformName)
 
  335        ndInput = nd.addInput(
'in', 
'color3')
 
  336        ndInput.setValue([0.0, 0.0, 0.0], 
'color3')
 
  337        docString = f
'Generated color space {sourceColorSpace} to {targetColorSpace} transform.' 
  338        result = f
'{groupTransform}' 
  340        result = result.replace(
'<', 
'(')
 
  341        result = result.replace(
'>', 
')')
 
  342        result = re.sub(
r'[\r\n]+', 
'', result)
 
  345        docString = docString + 
'. OCIO Transforms: ' + result 
 
  346        nd.setDocString(docString)
 
  348        ng = graphDoc.addNodeGraph(
'NG_' + xformName)
 
  349        ng.setAttribute(
'nodedef', nd.getName())
 
  350        convertNode = ng.addNode(
'convert', 
'asVec', 
'vector3')
 
  351        converInput = convertNode.addInput(
'in', 
'color3')
 
  352        converInput.setInterfaceName(
'in')
 
  355        if not groupTransform:
 
  362        for i 
in range(groupTransform.__len__()):
 
  363            transform = groupTransform.__getitem__(i)
 
  365            transformType = transform.getTransformType()
 
  366            if transformType 
in invalidTransforms:
 
  367                print(f
'- Transform[{i}]: {transformType} contains an unsupported transform type')
 
  371            if transformType == OCIO.TransformType.TRANSFORM_TYPE_MATRIX:
 
  372                matrixNode = ng.addNode(
'transform', ng.createValidChildName(f
'matrixTransform'), 
'vector3')
 
  375                inInput = matrixNode.addInput(
'in', 
'vector3')
 
  377                    inInput.setAttribute(
'nodename', previousNode)
 
  380                        inInput.setAttribute(
'nodename', 
'asVec')
 
  385                matInput = matrixNode.addInput(
'mat', 
'matrix33')
 
  386                matrixValue = transform.getMatrix()
 
  388                matrixValue = matrixValue[0:3] + matrixValue[4:7] + matrixValue[8:11]
 
  389                matrixValue = 
', '.join([str(x) 
for x 
in matrixValue])
 
  391                matInput.setAttribute(
'value', matrixValue)        
 
  394                offsetValue = transform.getOffset()
 
  395                offsetValue = 
', '.join([str(x) 
for x 
in offsetValue])
 
  399                previousNode = matrixNode.getName()
 
  402            elif transformType == OCIO.TransformType.TRANSFORM_TYPE_EXPONENT 
or transformType == OCIO.TransformType.TRANSFORM_TYPE_EXPONENT_WITH_LINEAR:
 
  404                hasOffset = (transformType == OCIO.TransformType.TRANSFORM_TYPE_EXPONENT_WITH_LINEAR)
 
  407                exponentNode = ng.addNode(
'power', ng.createValidChildName(f
'exponent'), 
'vector3')
 
  408                exponentInput = exponentNode.addInput(
'in1', 
'vector3')
 
  410                    exponentInput.setAttribute(
'nodename', previousNode)
 
  413                        exponentInput.setAttribute(
'nodename', 
'asVec')
 
  415                        exponentInput.setValue([0.0, 0.0, 0.0], 
'vector3')
 
  417                exponentInput2 = exponentNode.addInput(
'in2', 
'vector3')
 
  418                exponentInput2Value = 
None 
  420                    exponentInput2Value = transform.getValue()
 
  422                    exponentInput2Value = transform.getGamma()
 
  424                exponentInput2Value = exponentInput2Value[0:3]
 
  425                exponentInput2.setValue(exponentInput2Value, 
'float')
 
  427                previousNode = exponentNode.getName()
 
  431                    offsetNode = ng.addNode(
'add', ng.createValidChildName(f
'offset'), 
'vector3')
 
  432                    offsetInput2 = offsetNode.addInput(
'in2', 
'vector3')
 
  433                    offsetInput2.setNodeName(exponentNode.getName())
 
  434                    offsetInput = offsetNode.addInput(
'in1', 
'vector3')
 
  435                    offsetValue = transform.getOffset()
 
  437                    offsetValue = offsetValue[0:3]
 
  438                    offsetInput.setValue(offsetValue, 
'vector3')
 
  440                    previousNode = offsetNode.getName()
 
  443                print(f
'- Transform[{i}]: {transformType} support has not been implemented yet')
 
  448        convertNode2 = ng.addNode(
'convert', 
'asColor', 
'color3')
 
  449        converInput2 = convertNode2.addInput(
'in', 
'vector3')
 
  451            converInput2.setAttribute(
'nodename', previousNode)
 
  455            converInput2.setAttribute(
'nodename', 
'asVec')
 
  457        out = ng.addOutput(ng.createValidChildName(
'out'), 
'color3')
 
  458        out.setAttribute(
'nodename', 
'asColor')
 
 
  464        Create a color3 variant of a color4 definition. 
  466        color4Name = definition.getName()
 
  467        color3Name = color4Name.replace(
'color4', 
'color3')
 
  468        color3Def = definitionDoc.addNodeDef(color3Name)
 
  469        color3Def.copyContentFrom(definition)
 
  470        c3input = color3Def.getInput(IN_PIXEL_STRING)
 
  471        c3input.setType(
'color3')
 
  472        c3input.setValue([0.0, 0.0, 0.0], 
'color3')
 
  474        ngName = color3Def.getName().replace(
'ND_', 
'NG_')
 
  475        ng = definitionDoc.addNodeGraph(ngName)
 
  476        c4instance = ng.addNodeInstance(definition)
 
  477        c4instance.addInputsFromNodeDef()
 
  478        c4instanceIn = c4instance.getInput(IN_PIXEL_STRING)
 
  479        c3to4 = ng.addNode(
'convert', 
'c3to4', 
'color4')
 
  480        c3to4Input = c3to4.addInput(
'in', 
'color3')
 
  481        c4to3 = ng.addNode(
'convert', 
'c4to3', 
'color3')
 
  482        c4to3Input = c4to3.addInput(
'in', 
'color4')
 
  483        ngout = ng.addOutput(
'out', 
'color3')
 
  485        ng.setNodeDef(color3Def)
 
  487        c4instanceIn.setNodeName(c3to4.getName())
 
  488        c4to3Input.setNodeName(c4instance.getName())
 
  489        ngout.setNodeName(c4to3.getName())
 
  490        c3to4Input.setInterfaceName(IN_PIXEL_STRING)