def getShaderInfo(self, shader): """Read the shader parameters from a given shader. """ sloargs = self._sloargs # Split path and file name shaderPath, shaderFileName = os.path.split(shader) if shaderPath == "": shaderPath = "." # Remove the extension shader = os.path.splitext(shaderFileName)[0] sloargs.Slo_SetPath(shaderPath) # Try the shader name with extension first... if sloargs.Slo_SetShader(shaderFileName) != 0: # If the above failed, try the shader name without extension (prman)... if sloargs.Slo_SetShader(shader) != 0: raise IOError('Failed to open shader "%s"' % shader) shaderName = sloargs.Slo_GetName() shaderType = sloargs.Slo_TypetoStr(sloargs.Slo_GetType()) metaData = self._getMetaData() params = [] numParams = sloargs.Slo_GetNArgs() for i in range(1, numParams + 1): res = sloargs.Slo_GetArgById(i) symdef = res.contents if sloargs.Slo_StortoStr(symdef.storage).startswith("output"): output = "output" else: output = "" storage = sloargs.Slo_DetailtoStr(symdef.detail) paramType = sloargs.Slo_TypetoStr(symdef.type) arrLen = symdef.arraylen if arrLen == 0: arrLen = None name = symdef.name space = self._getSpace(symdef) if space == "": space = None defaultVal = self._getDefaultVal(symdef) params.append( _ShaderParam(output, storage, paramType, arrLen, name, space, defaultVal)) sloargs.Slo_EndShader() return [ _ShaderInfo(type=shaderType, name=shaderName, params=params, meta=metaData) ]
def getShaderInfo(self, shader): """Read the shader parameters from a given shader. """ sloargs = self._sloargs # Split path and file name shaderPath,shaderFileName = os.path.split(shader) if shaderPath=="": shaderPath = "." # Remove the extension shader = os.path.splitext(shaderFileName)[0] sloargs.Slo_SetPath(shaderPath) # Try the shader name with extension first... if sloargs.Slo_SetShader(shaderFileName)!=0: # If the above failed, try the shader name without extension (prman)... if sloargs.Slo_SetShader(shader)!=0: raise IOError('Failed to open shader "%s"'%shader) shaderName = sloargs.Slo_GetName() shaderType = sloargs.Slo_TypetoStr(sloargs.Slo_GetType()) metaData = self._getMetaData() params = [] numParams = sloargs.Slo_GetNArgs() for i in range(1, numParams+1): res = sloargs.Slo_GetArgById(i) symdef = res.contents if sloargs.Slo_StortoStr(symdef.storage).startswith("output"): output = "output" else: output = "" storage = sloargs.Slo_DetailtoStr(symdef.detail) paramType = sloargs.Slo_TypetoStr(symdef.type) arrLen = symdef.arraylen if arrLen==0: arrLen = None name = symdef.name space = self._getSpace(symdef) if space=="": space = None defaultVal = self._getDefaultVal(symdef) params.append(_ShaderParam(output,storage,paramType,arrLen,name,space,defaultVal)) sloargs.Slo_EndShader() return [_ShaderInfo(type=shaderType, name=shaderName, params=params, meta=metaData)]
def slparams(slfile=None, cpp=None, cpperrstream=sys.stderr, slname=None, includedirs=None, defines=None): """Extracts the shader parameters from a RenderMan Shader file. The argument *slfile* is either the name of a compiled shader, the name of the shader source file (``*.sl``) or a file-like object that provides the shader sources. *cpp* determines how the shader source is preprocessed. It can either be a string containing the name of an external preprocessor tool (such as ``cpp``) that must take the file name as parameter and dump the preprocessed output to stdout or it can be a callable that takes *slfile* and *cpperrstream* as input and returns the preprocessed sources as a string. If the external preprocessor does not produce any data a :exc:`PreprocessorNotFound` exception is thrown. The error stream of the preprocessor is written to the object specified by *cpperrstream* which must have a :meth:`write()` method. If *cpperrstream* is ``None``, the error stream is ignored. If *cpp* is ``None`` a simple internal preprocessor based on the :mod:`simplecpp` module is used. The *slname* argument is an alias for *slfile*, it is only available for backwards compatibility. *includedirs* is a list of strings that contain directories where to look for include files. *defines* is a list of tuples (*name*, *value*) that specify the predefined symbols to use. The function returns a list of shader info objects. These objects have four attributes: - ``type``: The type of the shader (surface, displacement, etc.) - ``name``: The name of the shader - ``params``: The shader parameters (see below) - ``meta``: The shader meta data. How exactly meta data is specified depends on the renderer you are using. The parameters are given as a list of shader parameter objects describing each parameter. A shader parameter object has the following attributes: - ``outputSpec``: The output specifier (either ``"output"`` or an empty string) - ``storage``: The storage class (``"uniform"`` or ``"varying"``) - ``type``: The parameter type - ``size``: The array length or ``None`` if the parameter is not an array - ``name``: The name of the parameter - ``space``: The space in which a point-like type was defined - ``default``: The "raw" default value. If the input was a shader source file, this will always be a string containing an expression. If the input was a compiled shader this will already be an appropriate Python value. You should never use this value directly, but always use :func:`convertdefault()` to obtain a value which can be further processed. This way, your code will work for both, compiled shaders and shader source files. For backwards compatibility, the shader info object behaves like a 3-tuple (*type*, *name*, *params*). The meta data can only be accessed via name though. The shader parameter objects can also be used like 7-tuples containing the above data (in the order given above). Example (output slightly reformatted for better readability):: >>> from cgkit import slparams >>> shaders = lparams.slparams("plastic.sl") >>> print shaders [('surface', 'plastic', [('', 'uniform', 'float', None, 'Ka', None, '1'), ('', 'uniform', 'float', None, 'Kd', None, '0.5'), ('', 'uniform', 'float', None, 'Ks', None, '0.5'), ('', 'uniform', 'float', None, 'roughness', None, '0.1'), ('', 'uniform', 'color', None, 'specularcolor', 'rgb', '1')])] >>> shaders[0].type 'surface' >>> shaders[0].name 'plastic' >>> for param in shaders[0].params: print param.name ... Ka Kd Ks roughness specularcolor >>> shaders[0].meta {} The parser used inside this function was generated using the parser generator `Yapps <http://theory.stanford.edu/~amitp/Yapps/>`_ by Amit Patel. """ if slname is not None: slfile = slname if slfile is None: return [] # Check if the input file is a string referring to a compiled shader # (suffix != .sl). If so, use the sloargs module to get the shader information if isinstance(slfile, basestring): if os.path.splitext(slfile)[1].lower() != ".sl": if (_has_sloargs): return sloargs.slparams(slfile) else: raise _sloargs_importerror # Run the preprocessor on the input file... slsrc = preprocess(cpp, slfile, cpperrstream=cpperrstream, defines=defines, includedirs=includedirs) f = StringIO.StringIO(slsrc) # ...and filter it, so that only the shader and function # definitions remain... filter = _SLfilter() sltokenize.tokenize(f.readline, filter.eater) f.close() # print filter.SLsource # Parse the filtered source code... scanner = _slparser._SLParserBaseScanner(filter.SLsource) parser = _SLParser(scanner) # return wrap_error_reporter(parser, "definitions") try: lst = getattr(parser, "definitions")() # Turn the 3-tuples into _ShaderInfo objects return map(lambda tup: _ShaderInfo(*tup), lst) except _slparser.NoMoreTokens, err: raise NoMoreTokens, "No more tokens"
def slparams(slfile=None, cpp=None, cpperrstream=sys.stderr, slname=None, includedirs=None, defines=None): """Extracts the shader parameters from a RenderMan Shader file. The argument *slfile* is either the name of a compiled shader, the name of the shader source file (``*.sl``) or a file-like object that provides the shader sources. *cpp* determines how the shader source is preprocessed. It can either be a string containing the name of an external preprocessor tool (such as ``cpp``) that must take the file name as parameter and dump the preprocessed output to stdout or it can be a callable that takes *slfile* and *cpperrstream* as input and returns the preprocessed sources as a string. If the external preprocessor does not produce any data a :exc:`PreprocessorNotFound` exception is thrown. The error stream of the preprocessor is written to the object specified by *cpperrstream* which must have a :meth:`write()` method. If *cpperrstream* is ``None``, the error stream is ignored. If *cpp* is ``None`` a simple internal preprocessor based on the :mod:`simplecpp` module is used. The *slname* argument is an alias for *slfile*, it is only available for backwards compatibility. *includedirs* is a list of strings that contain directories where to look for include files. *defines* is a list of tuples (*name*, *value*) that specify the predefined symbols to use. The function returns a list of shader info objects. These objects have four attributes: - ``type``: The type of the shader (surface, displacement, etc.) - ``name``: The name of the shader - ``params``: The shader parameters (see below) - ``meta``: The shader meta data. How exactly meta data is specified depends on the renderer you are using. The parameters are given as a list of shader parameter objects describing each parameter. A shader parameter object has the following attributes: - ``outputSpec``: The output specifier (either ``"output"`` or an empty string) - ``storage``: The storage class (``"uniform"`` or ``"varying"``) - ``type``: The parameter type - ``size``: The array length or ``None`` if the parameter is not an array - ``name``: The name of the parameter - ``space``: The space in which a point-like type was defined - ``default``: The "raw" default value. If the input was a shader source file, this will always be a string containing an expression. If the input was a compiled shader this will already be an appropriate Python value. You should never use this value directly, but always use :func:`convertdefault()` to obtain a value which can be further processed. This way, your code will work for both, compiled shaders and shader source files. For backwards compatibility, the shader info object behaves like a 3-tuple (*type*, *name*, *params*). The meta data can only be accessed via name though. The shader parameter objects can also be used like 7-tuples containing the above data (in the order given above). Example (output slightly reformatted for better readability):: >>> from cgkit import slparams >>> shaders = lparams.slparams("plastic.sl") >>> print shaders [('surface', 'plastic', [('', 'uniform', 'float', None, 'Ka', None, '1'), ('', 'uniform', 'float', None, 'Kd', None, '0.5'), ('', 'uniform', 'float', None, 'Ks', None, '0.5'), ('', 'uniform', 'float', None, 'roughness', None, '0.1'), ('', 'uniform', 'color', None, 'specularcolor', 'rgb', '1')])] >>> shaders[0].type 'surface' >>> shaders[0].name 'plastic' >>> for param in shaders[0].params: print param.name ... Ka Kd Ks roughness specularcolor >>> shaders[0].meta {} The parser used inside this function was generated using the parser generator `Yapps <http://theory.stanford.edu/~amitp/Yapps/>`_ by Amit Patel. """ if slname is not None: slfile = slname if slfile is None: return [] # Check if the input file is a string referring to a compiled shader # (suffix != .sl). If so, use the sloargs module to get the shader information if isinstance(slfile, basestring): if os.path.splitext(slfile)[1].lower() != ".sl": if _has_sloargs: return sloargs.slparams(slfile) else: raise _sloargs_importerror # Run the preprocessor on the input file... slsrc = preprocess(cpp, slfile, cpperrstream=cpperrstream, defines=defines, includedirs=includedirs) f = StringIO.StringIO(slsrc) # ...and filter it, so that only the shader and function # definitions remain... filter = _SLfilter() sltokenize.tokenize(f.readline, filter.eater) f.close() # print filter.SLsource # Parse the filtered source code... scanner = _slparser._SLParserBaseScanner(filter.SLsource) parser = _SLParser(scanner) # return wrap_error_reporter(parser, "definitions") try: lst = getattr(parser, "definitions")() # Turn the 3-tuples into _ShaderInfo objects return map(lambda tup: _ShaderInfo(*tup), lst) except _slparser.NoMoreTokens, err: raise NoMoreTokens, "No more tokens"