Python API 2.0 Reference
python/api2/py2DepthShader.py
1 from __future__ import division
2 #-
3 # ===========================================================================
4 # Copyright 2020 Autodesk, Inc. All rights reserved.
5 #
6 # Use of this software is subject to the terms of the Autodesk license
7 # agreement provided at the time of installation or download, or which
8 # otherwise accompanies this software in either electronic or hard copy form.
9 # ===========================================================================
10 #+
11 
12 import sys
13 from string import *
14 import maya.api.OpenMaya as om
15 import maya.api.OpenMayaRender as omr
16 import textwrap
17 
18 # Produces dependency graph node DepthShader
19 # This node is an example of a surface shader that colors objects based on the distance from the camera.
20 # The inputs for this node are can be found in the Maya UI on the Attribute Editor for the node.
21 # The output attribute of the node is called "outColor". It is a 3 float value that represents the resulting color produced by the node.
22 # To use this shader, create a DepthShader with Shading Group or connect its output to a Shading Group's "SurfaceShader" attribute.
23 
24 
25 def maya_useNewAPI():
26  """
27  The presence of this function tells Maya that the plugin produces, and
28  expects to be passed, objects created using the Maya Python API 2.0.
29  """
30  pass
31 
32 ##################################################################
33 ## Plugin Depth Shader Class Declaration
34 ##################################################################
35 class depthShader(om.MPxNode):
36  # Id tag for use with binary file format
37  id = om.MTypeId( 0x81164 )
38 
39  # Input attributes
40  aColorNear = None
41  aColorFar = None
42  aNear = None
43  aFar = None
44  aPointCamera = None
45 
46  # Output attributes
47  aOutColor = None
48 
49  @staticmethod
50  def creator():
51  return depthShader()
52 
53  @staticmethod
54  def initialize():
55  nAttr = om.MFnNumericAttribute()
56 
57  # Create input attributes
58 
59  depthShader.aColorNear = nAttr.createColor("color", "c")
60  nAttr.keyable = True
61  nAttr.storable = True
62  nAttr.readable = True
63  nAttr.writable = True
64  nAttr.default = (0.0, 1.0, 0.0) # Green
65 
66 
67  depthShader.aColorFar = nAttr.createColor("colorFar", "cf")
68  nAttr.keyable = True
69  nAttr.storable = True
70  nAttr.readable = True
71  nAttr.writable = True
72  nAttr.default = (0.0, 0.0, 1.0) # Blue
73 
74  depthShader.aNear = nAttr.create("near", "n", om.MFnNumericData.kFloat)
75  nAttr.keyable = True
76  nAttr.storable = True
77  nAttr.readable = True
78  nAttr.writable = True
79  nAttr.setMin(0.0)
80  nAttr.setSoftMax(1000.0)
81 
82  depthShader.aFar = nAttr.create("far", "f", om.MFnNumericData.kFloat)
83  nAttr.keyable = True
84  nAttr.storable = True
85  nAttr.readable = True
86  nAttr.writable = True
87  nAttr.setMin(0.0)
88  nAttr.setSoftMax(1000.0)
89  nAttr.default = 2.0
90 
91  depthShader.aPointCamera = nAttr.createPoint("pointCamera", "p")
92  nAttr.keyable = True
93  nAttr.storable = True
94  nAttr.readable = True
95  nAttr.writable = True
96  nAttr.hidden = True
97 
98  # Create output attributes
99  depthShader.aOutColor = nAttr.createColor("outColor", "oc")
100  nAttr.keyable = False
101  nAttr.storable = False
102  nAttr.readable = True
103  nAttr.writable = False
104 
105  om.MPxNode.addAttribute(depthShader.aColorNear)
106  om.MPxNode.addAttribute(depthShader.aColorFar)
107  om.MPxNode.addAttribute(depthShader.aNear)
108  om.MPxNode.addAttribute(depthShader.aFar)
109  om.MPxNode.addAttribute(depthShader.aPointCamera)
110  om.MPxNode.addAttribute(depthShader.aOutColor)
111 
112  om.MPxNode.attributeAffects(depthShader.aColorNear, depthShader.aOutColor)
113  om.MPxNode.attributeAffects(depthShader.aColorFar, depthShader.aOutColor)
114  om.MPxNode.attributeAffects(depthShader.aNear, depthShader.aOutColor)
115  om.MPxNode.attributeAffects(depthShader.aFar, depthShader.aOutColor)
116  om.MPxNode.attributeAffects(depthShader.aPointCamera, depthShader.aOutColor)
117 
118  def __init__(self):
119  om.MPxNode.__init__(self)
120 
121  def compute(self, plug, block):
122  # outColor or individial R, G, B channel
123  if (plug != depthShader.aOutColor) and (plug.parent() != depthShader.aOutColor):
124  return None # Let the Maya parent class compute the plug
125 
126  # get sample surface shading parameters
127  pCamera = block.inputValue(depthShader.aPointCamera).asFloatVector()
128  cNear = block.inputValue(depthShader.aColorNear).asFloatVector()
129  cFar = block.inputValue(depthShader.aColorFar).asFloatVector()
130  nearClip = block.inputValue(depthShader.aNear).asFloat()
131  farClip = block.inputValue(depthShader.aFar).asFloat()
132 
133  # pCamera.z is negative
134  ratio = 1.0
135  dist = farClip - nearClip
136  if dist != 0:
137  ratio = (farClip + pCamera.z) / dist
138  resultColor = cNear * ratio + cFar*(1.0 - ratio)
139 
140  # set ouput color attribute
141  outColorHandle = block.outputValue( depthShader.aOutColor )
142  outColorHandle.setMFloatVector( resultColor )
143  outColorHandle.setClean()
144 
145  # The plug has been computed successfully
146  return self
147 
148  def postConstructor(self):
149  pass
150 
151 ##################################################################
152 ## Plugin Depth Shader Override Class Declaration
153 ##################################################################
154 class depthShaderOverride(omr.MPxSurfaceShadingNodeOverride):
155  @staticmethod
156  def creator(obj):
157  return depthShaderOverride(obj)
158 
159  def __init__(self, obj):
160  omr.MPxSurfaceShadingNodeOverride.__init__(self, obj)
161 
162  # Register fragments with the manager if needed
163  fragmentMgr = omr.MRenderer.getFragmentManager()
164  if fragmentMgr != None:
165  if not fragmentMgr.hasFragment("depthShaderPluginFragment"):
166  fragmentBody = textwrap.dedent("""
167  <fragment uiName=\"depthShaderPluginFragment\" name=\"depthShaderPluginFragment\" type=\"plumbing\" class=\"ShadeFragment\" version=\"1.0\">
168  <description><![CDATA[Depth shader fragment]]></description>
169  <properties>
170  <float name=\"depthValue\" />
171  <float3 name=\"color\" />
172  <float3 name=\"colorFar\" />
173  <float name=\"near\" />
174  <float name=\"far\" />
175  </properties>
176  <values>
177  <float name=\"depthValue\" value=\"0.0\" />
178  <float3 name=\"color\" value=\"0.0,1.0,0.0\" />
179  <float3 name=\"colorFar\" value=\"0.0,0.0,1.0\" />
180  <float name=\"near\" value=\"0.0\" />
181  <float name=\"far\" value=\"2.0\" />
182  </values>
183  <outputs>
184  <float3 name=\"outColor\" />
185  </outputs>
186  <implementation>
187  <implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">
188  <function_name val=\"depthShaderPluginFragment\" />
189  <source><![CDATA[
190  float3 depthShaderPluginFragment(float depthValue, float3 cNear, float3 cFar, float nearClip, float farClip) \n
191  { \n
192  float ratio = (farClip + depthValue)/(farClip - nearClip); \n
193  return cNear*ratio + cFar*(1.0f - ratio); \n
194  } \n]]>
195  </source>
196  </implementation>
197  <implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">
198  <function_name val=\"depthShaderPluginFragment\" />
199  <source><![CDATA[
200  float3 depthShaderPluginFragment(float depthValue, float3 cNear, float3 cFar, float nearClip, float farClip) \n
201  { \n
202  float ratio = (farClip + depthValue)/(farClip - nearClip); \n
203  return cNear*ratio + cFar*(1.0f - ratio); \n
204  } \n]]>
205  </source>
206  </implementation>
207  <implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">
208  <function_name val=\"depthShaderPluginFragment\" />
209  <source><![CDATA[
210  vec3 depthShaderPluginFragment(float depthValue, vec3 cNear, vec3 cFar, float nearClip, float farClip) \n
211  { \n
212  float ratio = (farClip + depthValue)/(farClip - nearClip); \n
213  return cNear*ratio + cFar*(1.0f - ratio); \n
214  } \n]]>
215  </source>
216  </implementation>
217  </implementation>
218  </fragment>""")
219 
220  fragmentMgr.addShadeFragmentFromBuffer(fragmentBody.encode('utf-8'), False)
221 
222  if not fragmentMgr.hasFragment("depthShaderPluginInterpolantFragment"):
223  vertexFragmentBody = textwrap.dedent("""
224  <fragment uiName=\"depthShaderPluginInterpolantFragment\" name=\"depthShaderPluginInterpolantFragment\" type=\"interpolant\" class=\"ShadeFragment\" version=\"1.0\">
225  <description><![CDATA[Depth shader vertex fragment]]></description>
226  <properties>
227  <float3 name=\"Pm\" semantic=\"Pm\" flags=\"varyingInputParam\" />
228  <float4x4 name=\"worldViewProj\" semantic=\"worldviewprojection\" />
229  </properties>
230  <values>
231  </values>
232  <outputs>
233  <float name=\"outDepthValue\" ^1s/>
234  </outputs>
235  <implementation>
236  <implementation render=\"OGSRenderer\" language=\"Cg\" lang_version=\"2.1\">
237  <function_name val=\"depthShaderPluginInterpolantFragment\" />
238  <source><![CDATA[
239  float depthShaderPluginInterpolantFragment(float depthValue) \n
240  { \n
241  return depthValue; \n
242  } \n]]>
243  </source>
244  <vertex_source><![CDATA[
245  float idepthShaderPluginInterpolantFragment(float3 Pm, float4x4 worldViewProj) \n
246  { \n
247  float4 pCamera = mul(worldViewProj, float4(Pm, 1.0f)); \n
248  return (pCamera.z - pCamera.w*2.0f); \n
249  } \n]]>
250  </vertex_source>
251  </implementation>
252  <implementation render=\"OGSRenderer\" language=\"HLSL\" lang_version=\"11.0\">
253  <function_name val=\"depthShaderPluginInterpolantFragment\" />
254  <source><![CDATA[
255  float depthShaderPluginInterpolantFragment(float depthValue) \n
256  { \n
257  return depthValue; \n
258  } \n]]>
259  </source>
260  <vertex_source><![CDATA[
261  float idepthShaderPluginInterpolantFragment(float3 Pm, float4x4 worldViewProj) \n
262  { \n
263  float4 pCamera = mul(float4(Pm, 1.0f), worldViewProj); \n
264  return (pCamera.z - pCamera.w*2.0f); \n
265  } \n]]>
266  </vertex_source>
267  </implementation>
268  <implementation render=\"OGSRenderer\" language=\"GLSL\" lang_version=\"3.0\">
269  <function_name val=\"depthShaderPluginInterpolantFragment\" />
270  <source><![CDATA[
271  float depthShaderPluginInterpolantFragment(float depthValue) \n
272  { \n
273  return depthValue; \n
274  } \n]]>
275  </source>
276  <vertex_source><![CDATA[
277  float idepthShaderPluginInterpolantFragment(vec3 Pm, mat4 worldViewProj) \n
278  { \n
279  vec4 pCamera = worldViewProj * vec4(Pm, 1.0f); \n
280  return (pCamera.z - pCamera.w*2.0f); \n
281  } \n]]>
282  </vertex_source>
283  </implementation>
284  </implementation>
285  </fragment>""")
286 
287  # In DirectX, need to specify a semantic for the output of the vertex shader
288  if omr.MRenderer.drawAPI() == omr.MRenderer.kDirectX11:
289  vertexFragmentBody = vertexFragmentBody.replace("^1s", "semantic=\"extraDepth\" ")
290  else:
291  vertexFragmentBody = vertexFragmentBody.replace("^1s", " ")
292 
293  fragmentMgr.addShadeFragmentFromBuffer(vertexFragmentBody.encode('utf-8'), False)
294 
295  if not fragmentMgr.hasFragment("depthShaderPluginGraph"):
296  fragmentGraphBody = textwrap.dedent("""
297  <fragment_graph name=\"depthShaderPluginGraph\" ref=\"depthShaderPluginGraph\" class=\"FragmentGraph\" version=\"1.0\">
298  <fragments>
299  <fragment_ref name=\"depthShaderPluginFragment\" ref=\"depthShaderPluginFragment\" />
300  <fragment_ref name=\"depthShaderPluginInterpolantFragment\" ref=\"depthShaderPluginInterpolantFragment\" />
301  </fragments>
302  <connections>
303  <connect from=\"depthShaderPluginInterpolantFragment.outDepthValue\" to=\"depthShaderPluginFragment.depthValue\" />
304  </connections>
305  <properties>
306  <float3 name=\"Pm\" ref=\"depthShaderPluginInterpolantFragment.Pm\" semantic=\"Pm\" flags=\"varyingInputParam\" />
307  <float4x4 name=\"worldViewProj\" ref=\"depthShaderPluginInterpolantFragment.worldViewProj\" semantic=\"worldviewprojection\" />
308  <float3 name=\"color\" ref=\"depthShaderPluginFragment.color\" />
309  <float3 name=\"colorFar\" ref=\"depthShaderPluginFragment.colorFar\" />
310  <float name=\"near\" ref=\"depthShaderPluginFragment.near\" />
311  <float name=\"far\" ref=\"depthShaderPluginFragment.far\" />
312  </properties>
313  <values>
314  <float3 name=\"color\" value=\"0.0,1.0,0.0\" />
315  <float3 name=\"colorFar\" value=\"0.0,0.0,1.0\" />
316  <float name=\"near\" value=\"0.0\" />
317  <float name=\"far\" value=\"2.0\" />
318  </values>
319  <outputs>
320  <float3 name=\"outColor\" ref=\"depthShaderPluginFragment.outColor\" />
321  </outputs>
322  </fragment_graph>""")
323 
324  fragmentMgr.addFragmentGraphFromBuffer(fragmentGraphBody.encode('utf-8'))
325 
326  def supportedDrawAPIs(self):
327  return omr.MRenderer.kOpenGL | omr.MRenderer.kOpenGLCoreProfile | omr.MRenderer.kDirectX11
328 
329  def fragmentName(self):
330  return "depthShaderPluginGraph"
331 
332 ##
333 ## Plugin setup
334 #######################################################
335 sRegistrantId = "depthShaderPlugin_py"
336 
337 def initializePlugin(obj):
338  plugin = om.MFnPlugin(obj, "Autodesk", "4.5", "Any")
339  try:
340  userClassify = "shader/surface:drawdb/shader/surface/depthShader_py"
341  plugin.registerNode("depthShader_py", depthShader.id, depthShader.creator, depthShader.initialize, om.MPxNode.kDependNode, userClassify)
342  except:
343  sys.stderr.write("Failed to register node\n")
344  raise
345 
346  try:
347  global sRegistrantId
348  omr.MDrawRegistry.registerSurfaceShadingNodeOverrideCreator("drawdb/shader/surface/depthShader_py", sRegistrantId, depthShaderOverride.creator)
349  except:
350  sys.stderr.write("Failed to register override\n")
351  raise
352 
353 def uninitializePlugin(obj):
354  plugin = om.MFnPlugin(obj)
355  try:
356  plugin.deregisterNode(depthShader.id)
357  except:
358  sys.stderr.write("Failed to deregister node\n")
359  raise
360 
361  try:
362  global sRegistrantId
363  omr.MDrawRegistry.deregisterSurfaceShadingNodeOverrideCreator("drawdb/shader/surface/depthShader_py", sRegistrantId)
364  except:
365  sys.stderr.write("Failed to deregister override\n")
366  raise
367