scripted/pyViewRenderOverride.py

scripted/pyViewRenderOverride.py
1 #-
2 # Copyright 2015 Autodesk, Inc. All rights reserved.
3 #
4 # Use of this software is subject to the terms of the Autodesk license agreement
5 # provided at the time of installation or download, or which otherwise
6 # accompanies this software in either electronic or hard copy form.
7 #+
8 
9 import sys
10 from OpenGL.GL import *
11 import maya.api.OpenMayaRender as omr
12 import maya.api.OpenMayaUI as omui
13 import maya.api.OpenMaya as om
14 
15 def maya_useNewAPI():
16  """
17  The presence of this function tells Maya that the plugin produces, and
18  expects to be passed, objects created using the Maya Python API 2.0.
19  """
20  pass
21 
22 # Enumerations to identify an operation within a list of operations.
23 kBackgroundBlit = 0
24 kMaya3dSceneRender = 1 # 3d scene render to target 1
25 kMaya3dSceneRenderOpaque = 2 # 3d opaque scene render to target 1
26 kMaya3dSceneRenderTransparent = 3 # 3d transparent scene render to target 1
27 kThresholdOp = 4 # Brightness threshold
28 kHorizBlurOp = 5 # Down sample to target 2
29 kVertBlurOp = 6
30 kBlendOp = 7 # Blend target 1 and 2 back to target 1
31 kPostOperation1 = 8 # Post ops on target 1
32 kPostOperation2 = 9
33 kMaya3dSceneRenderUI = 10 # Post ui draw to target 1
34 kUserOpNumber = 11 # User op draw to target 1
35 kHUDBlit = 12 # Draw HUD on top
36 kPresentOp = 13 # Present
37 kNumberOfOps = 14
38 
39 # Helper to enumerate the target indexing
40 kMyColorTarget = 0
41 kMyDepthTarget = 1
42 kMyBlurTarget = 2
43 kTargetCount = 3
44 
45 #
46 # Utilty to print out lighting information from a draw context
47 #
48 def printDrawContextLightInfo(drawContext):
49  # Get all the lighting information in the scene
50  considerAllSceneLights = omr.MDrawContext.kFilteredIgnoreLightLimit
51  omr.MRenderer.needEvaluateAllLights()
52  lightCount = drawContext.numberOfActiveLights(considerAllSceneLights)
53  if lightCount == 0:
54  return
55 
56  positions = om.MFloatPointArray()
57  position = om.MFloatPoint(0, 0, 0)
58  direction = om.MFloatVector()
59  color = om.MColor()
60  positionCount = 0
61 
62  for i in range(lightCount):
63  lightParam = drawContext.getLightParameterInformation( i, considerAllSceneLights )
64  if not lightParam is None:
65  print "\tLight " + str(i) +"\n\t{"
66 
67  for pname in lightParam.parameterList():
68  ptype = lightParam.parameterType(pname)
69  if ptype == omr.MLightParameterInformation.kBoolean:
70  print "\t\tLight parameter " + pname + ". Bool " + str(lightParam.getParameter(pname))
71  elif ptype == omr.MLightParameterInformation.kInteger:
72  print "\t\tLight parameter " + pname + ". Integer " + str(lightParam.getParameter(pname))
73  elif ptype == omr.MLightParameterInformation.kFloat:
74  print "\t\tLight parameter " + pname + ". Float " + str(lightParam.getParameter(pname))
75  elif ptype == omr.MLightParameterInformation.kFloat2:
76  print "\t\tLight parameter " + pname + ". Float " + str(lightParam.getParameter(pname))
77  elif ptype == omr.MLightParameterInformation.kFloat3:
78  print "\t\tLight parameter " + pname + ". Float3 " + str(lightParam.getParameter(pname))
79  elif ptype == omr.MLightParameterInformation.kFloat4:
80  print "\t\tLight parameter " + pname + ". Float4 " + str(lightParam.getParameter(pname))
81  elif ptype == omr.MLightParameterInformation.kFloat4x4Row:
82  print "\t\tLight parameter " + pname + ". Float4x4Row " + str(lightParam.getParameter(pname))
83  elif ptype == omr.MLightParameterInformation.kFloat4x4Col:
84  print "\t\tLight parameter " + pname + ". kFloat4x4Col " + str(lightParam.getParameter(pname))
85  elif ptype == omr.MLightParameterInformation.kTexture2:
86  # Get shadow map as a resource handle directly in OpenGL
87  print "\t\tLight texture parameter " + pname + ". OpenGL texture id = " + str(lightParam.getParameterTextureHandle(pname))
88  # Similar access for DX would look something like this:
89  # (ID3D11ShaderResourceView *) lightParam.getParameterTextureHandle(pname)
90  elif ptype == omr.MLightParameterInformation.kSampler:
91  print "\t\tLight sampler parameter " + pname + ". filter = " + str(lightParam.getParameter(pname).filter)
92 
93  # Do some discovery to map stock parameters to usable values
94  # based on the semantic
95  #
96  semantic = lightParam.parameterSemantic(pname)
97  if semantic == omr.MLightParameterInformation.kLightEnabled:
98  print "\t\t- Parameter semantic : light enabled"
99  elif semantic == omr.MLightParameterInformation.kWorldPosition:
100  print "\t\t- Parameter semantic : world position"
101  floatVals = lightParam.getParameter(pname)
102  position += om.MFloatPoint( floatVals[0], floatVals[1], floatVals[2] )
103  positionCount = positionCount + 1
104  elif semantic == omr.MLightParameterInformation.kWorldDirection:
105  print "\t\t- Parameter semantic : world direction"
106  direction = lightParam.getParameter(pname)
107  elif semantic == omr.MLightParameterInformation.kIntensity:
108  print "\t\t- Parameter semantic : intensity"
109  elif semantic == omr.MLightParameterInformation.kColor:
110  print "\t\t- Parameter semantic : color"
111  color = om.MColor( lightParam.getParameter(pname) )
112  elif semantic == omr.MLightParameterInformation.kEmitsDiffuse:
113  print "\t\t- Parameter semantic : emits-diffuse"
114  elif semantic == omr.MLightParameterInformation.kEmitsSpecular:
115  print "\t\t- Parameter semantic : emits-specular"
116  elif semantic == omr.MLightParameterInformation.kDecayRate:
117  print "\t\t- Parameter semantic : decay rate"
118  elif semantic == omr.MLightParameterInformation.kDropoff:
119  print "\t\t- Parameter semantic : drop-off"
120  elif semantic == omr.MLightParameterInformation.kCosConeAngle:
121  print "\t\t- Parameter semantic : cosine cone angle"
122  elif semantic == omr.MLightParameterInformation.kShadowMap:
123  print "\t\t- Parameter semantic : shadow map"
124  elif semantic == omr.MLightParameterInformation.kShadowSamp:
125  print "\t\t- Parameter semantic : shadow map sampler"
126  elif semantic == omr.MLightParameterInformation.kShadowBias:
127  print "\t\t- Parameter semantic : shadow map bias"
128  elif semantic == omr.MLightParameterInformation.kShadowMapSize:
129  print "\t\t- Parameter semantic : shadow map size"
130  elif semantic == omr.MLightParameterInformation.kShadowViewProj:
131  print "\t\t- Parameter semantic : shadow map view projection matrix"
132  elif semantic == omr.MLightParameterInformation.kShadowColor:
133  print "\t\t- Parameter semantic : shadow color"
134  elif semantic == omr.MLightParameterInformation.kGlobalShadowOn:
135  print "\t\t- Parameter semantic : global shadows on"
136  elif semantic == omr.MLightParameterInformation.kShadowOn:
137  print "\t\t- Parameter semantic : local shadows on"
138 
139  # Compute an average position
140  if positionCount > 1:
141  position /= positionCount
142  print "\t\tCompute average position " + str(position)
143 
144  # Print by semantic
145  print "\t\tSemantic -> Parameter Name Lookups"
146  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kLightEnabled)
147  floatVals = ""
148  try:
149  floatVals = lightParam.getParameter(omr.MLightParameterInformation.kLightEnabled)
150  except RuntimeError:
151  pass
152  print "\t\t\tkLightEnabled -> " + str(paramNames) + " -- " + str(floatVals)
153  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kWorldPosition)
154  print "\t\t\tkWorldPosition -> " + str(paramNames)
155  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kWorldDirection)
156  print "\t\t\tkWorldDirection -> " + str(paramNames)
157  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kIntensity)
158  print "\t\t\tkIntensity -> " + str(paramNames)
159  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kColor)
160  print "\t\t\tkColor -> " + str(paramNames)
161  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kEmitsDiffuse)
162  print "\t\t\tkEmitsDiffuse -> " + str(paramNames)
163  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kEmitsSpecular)
164  print "\t\t\tkEmitsSpecular -> " + str(paramNames)
165  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kDecayRate)
166  print "\t\t\tkDecayRate -> " + str(paramNames)
167  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kDropoff)
168  print "\t\t\tkDropoff -> " + str(paramNames)
169  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kCosConeAngle)
170  print "\t\t\tkCosConeAngle -> " + str(paramNames)
171  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kIrradianceIn)
172  print "\t\t\tkIrradianceIn -> " + str(paramNames)
173  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowMap)
174  print "\t\t\tkShadowMap -> " + str(paramNames)
175  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowSamp)
176  print "\t\t\tkShadowSamp -> " + str(paramNames)
177  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowBias)
178  print "\t\t\tkShadowBias -> " + str(paramNames)
179  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowMapSize)
180  print "\t\t\tkShadowMapSize -> " + str(paramNames)
181  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowColor)
182  print "\t\t\tkShadowColor -> " + str(paramNames)
183  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kGlobalShadowOn)
184  print "\t\t\tkGlobalShadowOn -> " + str(paramNames)
185  paramNames = lightParam.parameterNames(omr.MLightParameterInformation.kShadowOn)
186  print "\t\t\tkShadowOn -> " + str(paramNames)
187 
188  print "\t}"
189 
190 
191 # Shader override helpers:
192 # As part of a shader override it is possible to attach callbacks which
193 # are invoked when the shader is to be used. The following are some examples
194 # of what could be performed.
195 #
196 # Example utility used by a callback to:
197 #
198 # 1. Print out the shader parameters for a give MShaderInsrtance
199 # 2. Examine the list of render items which will be rendered with this MShaderInstance
200 # 3. Examine the pass context and print out information in the context.
201 #
202 def callbackDataPrint(context, renderItemList, shaderInstance):
203  if not shaderInstance is None:
204  paramNames = shaderInstance.parameterList()
205  paramCount = len(paramNames)
206  print "\tSHADER: # of parameters = " + str(paramCount)
207  for i in range(paramCount):
208  print "\t\tPARAM[" + paramNames[i] + "]"
209 
210  numItems = len(renderItemList)
211  for i in range(numItems):
212  item = renderItemList[i]
213  if not item is None:
214  path = item.sourceDagPath()
215  print "\tRENDER ITEM: '" + item.name() + "' -- SOURCE: '" + path.fullPathName() + "'"
216 
217  passCtx = context.getPassContext()
218  passId = passCtx.passIdentifier()
219  passSem = passCtx.passSemantics()
220  print "PASS ID[" + passId + "], PASS SEMANTICS[" + str(passSem) + "]"
221 
222 #
223 # Example utility used by callback to bind lighting information to a shader instance.
224 #
225 # This callback works specific with the MayaBlinnDirectionLightShadow shader example.
226 # It will explicitly binding lighting and shadowing information to the shader instance.
227 #
228 def shaderOverrideCallbackBindLightingInfo(drawContext, renderItemList, shaderInstance):
229  if shaderInstance is None:
230  return
231 
232  # Defaults in case there are no lights
233  #
234  globalShadowsOn = False
235  localShadowsOn = False
236  direction = om.MFloatVector(0.0, 0.0, 1.0)
237  lightIntensity = 0.0 # If no lights then black out the light
238  lightColor = [ 0.0, 0.0, 0.0 ]
239 
240  # Scan to find the first light that has a direction component in it
241  # It's possible we find no lights.
242  #
243  considerAllSceneLights = omr.MDrawContext.kFilteredIgnoreLightLimit
244  omr.MRenderer.needEvaluateAllLights()
245  lightCount = drawContext.numberOfActiveLights(considerAllSceneLights)
246  if lightCount > 0:
247  shadowViewProj = om.MMatrix()
248  shadowResourceTexture = None
249  samplerDesc = omr.MSamplerStateDesc()
250  shadowColor = [ 0.0, 0.0, 0.0 ]
251 
252  foundDirectional = False
253  for i in range(lightCount):
254  if foundDirectional:
255  break
256  globalShadowsOn = False
257  localShadowsOn = False
258  direction = om.MFloatVector(0.0, 0.0, 1.0)
259  lightIntensity = 0.0
260  lightColor = [ 0.0, 0.0, 0.0 ]
261 
262  lightParam = drawContext.getLightParameterInformation( i, considerAllSceneLights )
263  if not lightParam is None:
264  for pname in lightParam.parameterList():
265  semantic = lightParam.parameterSemantic( pname )
266  # Pick a few light parameters to pick up as an example
267  if semantic == omr.MLightParameterInformation.kWorldDirection:
268  floatVals = lightParam.getParameter( pname )
269  direction = om.MFloatVector( floatVals[0], floatVals[1], floatVals[2] )
270  foundDirectional = True
271  elif semantic == omr.MLightParameterInformation.kIntensity:
272  floatVals = lightParam.getParameter( pname )
273  lightIntensity = floatVals[0]
274  elif semantic == omr.MLightParameterInformation.kColor:
275  lightColor = lightParam.getParameter( pname )
276 
277  # Pick up shadowing parameters
278  elif semantic == omr.MLightParameterInformation.kGlobalShadowOn:
279  intVals = lightParam.getParameter( pname )
280  if len(intVals) > 0:
281  globalShadowsOn = (intVals[0] != 0)
282  elif semantic == omr.MLightParameterInformation.kShadowOn:
283  intVals = lightParam.getParameter( pname )
284  if len(intVals) > 0:
285  localShadowsOn = (intVals[0] != 0)
286  elif semantic == omr.MLightParameterInformation.kShadowViewProj:
287  shadowViewProj = lightParam.getParameter( pname )
288  elif semantic == omr.MLightParameterInformation.kShadowMap:
289  shadowResourceTexture = lightParam.getParameter( pname )
290  elif semantic == omr.MLightParameterInformation.kShadowSamp:
291  samplerDesc = lightParam.getParameter( pname )
292  elif semantic == omr.MLightParameterInformation.kShadowColor:
293  shadowColor = lightParam.getParameter( pname )
294 
295  # Set shadow map and projection if shadows are turned on.
296  #
297  if foundDirectional and globalShadowsOn and localShadowsOn and not shadowResourceTexture is None:
298  resourceHandle = shadowResourceTexture.resourceHandle()
299  if resourceHandle > 0:
300  debugShadowBindings = False
301  try:
302  shaderInstance.setParameter("mayaShadowPCF1_shadowMap", shadowResource )
303  if debugShadowBindings:
304  print "Bound shadow map to shader param mayaShadowPCF1_shadowMap"
305  except:
306  pass
307  try:
308  shaderInstance.setParameter("mayaShadowPCF1_shadowViewProj", shadowViewProj )
309  if debugShadowBindings:
310  print "Bound shadow map transform to shader param mayaShadowPCF1_shadowViewProj"
311  except:
312  pass
313  try:
314  shaderInstance.setParameter("mayaShadowPCF1_shadowColor", shadowColor )
315  if debugShadowBindings:
316  print "Bound shadow map color to shader param mayaShadowPCF1_shadowColor"
317  except:
318  pass
319 
320  textureManager = omr.MRenderer.getTextureManager()
321  if not textureManager is None:
322  textureManager.releaseTexture(shadowResourceTexture)
323  shadowResourceTexture = None
324 
325  # Set up parameters which should be set regardless of light existence.
326  shaderInstance.setParameter("mayaDirectionalLight_direction", direction)
327  shaderInstance.setParameter("mayaDirectionalLight_intensity", lightIntensity)
328  shaderInstance.setParameter("mayaDirectionalLight_color", lightColor)
329  shaderInstance.setParameter("mayaShadowPCF1_mayaGlobalShadowOn", globalShadowsOn)
330  shaderInstance.setParameter("mayaShadowPCF1_mayaShadowOn", localShadowsOn)
331 
332 #
333 # Example pre-render callback attached to a shader instance
334 #
335 def shaderOverridePreDrawCallback(context, renderItemList, shaderInstance):
336  print "PRE-draw callback triggered for render item list with data:"
337  callbackDataPrint(context, renderItemList, shaderInstance)
338  print ""
339 
340  print "\tLIGHTS"
341  printDrawContextLightInfo( context )
342  print ""
343 
344 #
345 # Example post-render callback attached to a shader instance
346 #
347 def shaderOverridePostDrawCallback(context, renderItemList, shaderInstance):
348  print "POST-draw callback triggered for render item list with data:"
349  callbackDataPrint(context, renderItemList, shaderInstance)
350  print ""
351 
352 ###################################################################
353 # Custom HUD operation
354 #
355 #
356 class viewRenderHUDOperation(omr.MHUDRender):
357  def __init__(self):
358  omr.MHUDRender.__init__(self)
359 
360  self.mTargets = None
361 
362  # Target override
363  def targetOverrideList(self):
364  if not self.mTargets is None:
365  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
366  return None
367 
368  def hasUIDrawables(self):
369  return True
370 
371  def addUIDrawables(self, drawManager2D, frameContext):
372  # Start draw UI
373  drawManager2D.beginDrawable()
374  # Set font color
375  drawManager2D.setColor( om.MColor( (0.455, 0.212, 0.596) ) )
376  # Set font size
377  drawManager2D.setFontSize( omr.MUIDrawManager.kSmallFontSize )
378 
379  # Draw renderer name
380  dim = frameContext.getViewportDimensions()
381  x=dim[0]
382  y=dim[1]
383  w=dim[2]
384  h=dim[3]
385  drawManager2D.text( om.MPoint(w*0.5, h*0.91), "Sample VP2 Renderer Override", omr.MUIDrawManager.kCenter )
386 
387  # Draw viewport information
388  viewportInfoText = "Viewport information: x= "
389  viewportInfoText += str(x)
390  viewportInfoText += ", y= "
391  viewportInfoText += str(y)
392  viewportInfoText += ", w= "
393  viewportInfoText += str(w)
394  viewportInfoText += ", h= "
395  viewportInfoText += str(h)
396  drawManager2D.text( om.MPoint(w*0.5, h*0.885), viewportInfoText, omr.MUIDrawManager.kCenter )
397 
398  # End draw UI
399  drawManager2D.endDrawable()
400 
401  def setRenderTargets(self, targets):
402  self.mTargets = targets
403 
404 
405 ###################################################################
406 #
407 # Custom present target operation
408 #
409 # Only overrides the targets to present
410 #
411 class viewRenderPresentTarget(omr.MPresentTarget):
412  def __init__(self, name):
413  omr.MPresentTarget.__init__(self, name)
414 
415  # Targets used as input parameters to mShaderInstance
416  self.mTargets = None
417 
418  def targetOverrideList(self):
419  if not self.mTargets is None:
420  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
421  return None
422 
423  def setRenderTargets(self, targets):
424  self.mTargets = targets
425 
426 
427 ###################################################################
428 # Custom quad operation
429 #
430 # General quad operation which can be instantiated with a few
431 # different shaders.
432 #
433 
434 class viewRenderQuadRender(omr.MQuadRender):
435  # Shader list
436  kEffectNone = 0
437  kPost_EffectMonochrome = 1 # Mono color shader
438  kPost_EffectEdgeDetect = 2 # Edge detect shader
439  kPost_EffectInvert = 3 # Invert color shader
440  kScene_Threshold = 4 # Color threshold shader
441  kScene_BlurHoriz = 5 # Horizontal blur shader
442  kScene_BlurVert = 6 # Vertical blur shader
443  kSceneBlur_Blend = 7 # Blend shader
444  kPre_MandelBrot = 8 # Mandelbrot shader
445 
446  def __init__(self, name):
447  omr.MQuadRender.__init__(self, name)
448 
449  # Shader to use for the quad render
450  self.mShaderInstance = None
451  # Targets used as input parameters to mShaderInstance
452  self.mTargets = None
453  # View rectangle
454  self.mViewRectangle = om.MFloatPoint()
455  # Shader to use for quad rendering
456  self.mShader = self.kEffectNone
457 
458  def __del__(self):
459  if not self.mShaderInstance is None:
460  shaderMgr = omr.MRenderer.getShaderManager()
461  if not shaderMgr is None:
462  shaderMgr.releaseShader(self.mShaderInstance)
463  self.mShaderInstance = None
464 
465  # Return the appropriate shader instance based on the what
466  # we want the quad operation to perform
467  def shader(self):
468  # Create a new shader instance for this quad render instance
469  #
470  if self.mShaderInstance is None:
471  shaderMgr = omr.MRenderer.getShaderManager()
472  if not shaderMgr is None:
473  # Note in the following code that we are not specifying the
474  # full file name, but relying on the getEffectFileShader() logic
475  # to determine the correct file name extension based on the shading language
476  # which is appropriate for the drawing API (DirectX or OpenGL).
477  #
478  # Refer to the documentation for this method to review how the
479  # final name on disk is derived.
480  #
481  # The second argument here is the technique. If desired
482  # and effect on disk can hold different techniques. For each unique
483  # effect + technique a different shader instance is created.
484  #
485  if self.mShader == self.kPre_MandelBrot:
486  self.mShaderInstance = shaderMgr.getEffectsFileShader( "MandelBrot", "" )
487  elif self.mShader == self.kPost_EffectMonochrome:
488  self.mShaderInstance = shaderMgr.getEffectsFileShader( "FilterMonochrome", "" )
489  elif self.mShader == self.kPost_EffectEdgeDetect:
490  self.mShaderInstance = shaderMgr.getEffectsFileShader( "FilterEdgeDetect", "" )
491  elif self.mShader == self.kPost_EffectInvert:
492  self.mShaderInstance = shaderMgr.getEffectsFileShader( "Invert", "" )
493  elif self.mShader == self.kScene_Threshold:
494  self.mShaderInstance = shaderMgr.getEffectsFileShader( "Threshold", "" )
495  elif self.mShader == self.kScene_BlurHoriz:
496  self.mShaderInstance = shaderMgr.getEffectsFileShader( "Blur", "BlurHoriz" )
497  elif self.mShader == self.kScene_BlurVert:
498  self.mShaderInstance = shaderMgr.getEffectsFileShader( "Blur", "BlurVert" )
499  elif self.mShader == self.kSceneBlur_Blend:
500  self.mShaderInstance = shaderMgr.getEffectsFileShader( "Blend", "Add" )
501 
502  # Set parameters on the shader instance.
503  #
504  # This is where the input render targets can be specified by binding
505  # a render target to the appropriate parameter on the shader instance.
506  #
507  if not self.mShaderInstance is None:
508  if self.mShader == self.kPre_MandelBrot:
509  # Example of a simple float parameter setting.
510  try:
511  self.mShaderInstance.setParameter("gIterate", 50)
512  except:
513  print "Could not change mandelbrot parameter"
514  return None
515 
516  elif self.mShader == self.kPost_EffectInvert:
517  # Set the input texture parameter 'gInputTex' to use
518  # a given color target
519  try:
520  self.mShaderInstance.setParameter("gInputTex", self.mTargets[kMyColorTarget])
521  except:
522  print "Could not set input render target / texture parameter on invert shader"
523  return None
524 
525  elif self.mShader == self.kScene_Threshold:
526  # Set the input texture parameter 'gSourceTex' to use
527  # a given color target
528  try:
529  self.mShaderInstance.setParameter("gSourceTex", self.mTargets[kMyColorTarget])
530  except:
531  print "Could not set input render target / texture parameter on threshold shader"
532  return None
533  self.mShaderInstance.setParameter("gBrightThreshold", 0.7 )
534 
535  elif self.mShader == self.kScene_BlurHoriz:
536  # Set the input texture parameter 'gSourceTex' to use
537  # a given color target
538  try:
539  self.mShaderInstance.setParameter("gSourceTex", self.mTargets[kMyBlurTarget])
540  except:
541  print "Could not set input render target / texture parameter on hblur shader"
542  return None
543 
544  elif self.mShader == self.kScene_BlurVert:
545  # Set the input texture parameter 'gSourceTex' to use
546  # a given color target
547  try:
548  self.mShaderInstance.setParameter("gSourceTex", self.mTargets[kMyBlurTarget])
549  except:
550  print "Could not set input render target / texture parameter on vblur shader"
551  return None
552 
553  elif self.mShader == self.kSceneBlur_Blend:
554  # Set the first input texture parameter 'gSourceTex' to use
555  # one color target.
556  try:
557  self.mShaderInstance.setParameter("gSourceTex", self.mTargets[kMyColorTarget])
558  except:
559  return None
560  # Set the second input texture parameter 'gSourceTex2' to use
561  # a second color target.
562  try:
563  self.mShaderInstance.setParameter("gSourceTex2", self.mTargets[kMyBlurTarget])
564  except:
565  return None
566  self.mShaderInstance.setParameter("gBlendSrc", 0.3 )
567 
568  elif self.mShader == self.kPost_EffectMonochrome:
569  # Set the input texture parameter 'gInputTex' to use
570  # a given color target
571  try:
572  self.mShaderInstance.setParameter("gInputTex", self.mTargets[kMyColorTarget])
573  except:
574  print "Could not set input render target / texture parameter on monochrome shader"
575  return None
576 
577  elif self.mShader == self.kPost_EffectEdgeDetect:
578  # Set the input texture parameter 'gInputTex' to use
579  # a given color target
580  try:
581  self.mShaderInstance.setParameter("gInputTex", self.mTargets[kMyColorTarget])
582  except:
583  print "Could not set input render target / texture parameter on edge detect shader"
584  return None
585  self.mShaderInstance.setParameter("gThickness", 1.0 )
586  self.mShaderInstance.setParameter("gThreshold", 0.1 )
587 
588  return self.mShaderInstance
589 
590  # Based on which shader is being used for the quad render
591  # we want to render to different targets. For the
592  # threshold and two blur shaders the temporary 'blur'
593  # target is used. Otherwise rendering should be directed
594  # to the custom color and depth target.
595  def targetOverrideList(self):
596  if not self.mTargets is None:
597  # Render to blur target for blur operations
598  if self.mShader == self.kScene_Threshold or self.mShader == self.kScene_BlurHoriz or self.mShader == self.kScene_BlurVert:
599  return [ self.mTargets[kMyBlurTarget] ]
600  else:
601  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
602  return None
603 
604  # Set the clear override to use.
605  def clearOperation(self):
606  clearOp = self.mClearOperation
607  # Want to clear everything since the quad render is the first operation.
608  if self.mShader == self.kPre_MandelBrot:
609  clearOp.setClearGradient( False )
610  clearOp.setMask( omr.MClearOperation.kClearAll )
611  # This is a post processing operation, so we don't want to clear anything
612  else:
613  clearOp.setClearGradient( False )
614  clearOp.setMask( omr.MClearOperation.kClearNone )
615  return clearOp
616 
617  def setRenderTargets(self, targets):
618  self.mTargets = targets
619 
620  def setShader(self, shader):
621  self.mShader = shader
622 
623  def viewRectangle(self):
624  return self.mViewRectangle
625 
626  def setViewRectangle(self, rect):
627  self.mViewRectangle = rect
628 
629 
630 ###################################################################
631 # Simple scene operation
632 #
633 # Example of just overriding a few options on the scene render.
634 #
635 class simpleViewRenderSceneRender(omr.MSceneRender):
636  def __init__(self, name):
637  omr.MSceneRender.__init__(self, name)
638 
639  self.mViewRectangle = om.MFloatPoint(0.0, 0.0, 1.0, 1.0) # 100 % of target size
640 
641  def viewportRectangleOverride(self):
642  # Enable this flag to use viewport sizing
643  testRectangleSize = False
644  if testRectangleSize:
645  # 1/3 to the right and 10 % up. 1/2 the target size.
646  self.mViewRectangle = om.MFloatPoint(0.33, 0.10, 0.50, 0.50)
647  return self.mViewRectangle
648 
649  def clearOperation(self):
650  # Override to clear to these gradient colors
651  val1 = [ 0.0, 0.2, 0.8, 1.0 ]
652  val2 = [ 0.5, 0.4, 0.1, 1.0 ]
653  clearOp = self.mClearOperation
654  clearOp.setClearColor( val1 )
655  clearOp.setClearColor2( val2 )
656  clearOp.setClearGradient( True )
657  return clearOp
658 
659 
660 ###################################################################
661 # Custom scene operation
662 #
663 # A scene render which is reused as necessary with different
664 # override parameters
665 #
666 class viewRenderSceneRender(omr.MSceneRender):
667  def __init__(self, name, sceneFilter, clearMask):
668  omr.MSceneRender.__init__(self, name)
669 
670  self.mSelectionList = om.MSelectionList()
671 
672  # 3D viewport panel name, if available
673  self.mPanelName = ""
674  # Camera override
675  self.mCameraOverride = omr.MCameraOverride()
676  # Viewport rectangle override
677  self.mViewRectangle = om.MFloatPoint(0.0, 0.0, 1.0, 1.0) # 100 % of target size
678  # Available render targets
679  self.mTargets = None
680  # Shader override for surfaces
681  self.mShaderOverride = None
682  # Scene draw filter override
683  self.mSceneFilter = sceneFilter
684  # Mask for clear override
685  self.mClearMask = clearMask
686 
687  # Some sample override flags
688  self.mUseShaderOverride = False
689  self.mUseStockShaderOverride = False
690  self.mAttachPrePostShaderCallback = False
691  self.mUseShadowShader = False
692  self.mOverrideDisplayMode = True
693  self.mOverrideLightingMode = False
694  self.mOverrideCullingMode = False
695  self.mDebugTargetResourceHandle = False
696  self.mOverrrideM3dViewDisplayMode = False
697  self.mPrevDisplayStyle = omui.M3dView.kGouraudShaded # Track previous display style of override set
698  self.mFilterDrawNothing = False
699  self.mFilterDrawSelected = False
700  self.mEnableSRGBWrite = False
701 
702 
703  def __del__(self):
704  if not self.mShaderOverride is None:
705  shaderMgr = omr.MRenderer.getShaderManager()
706  if not shaderMgr is None:
707  shaderMgr.releaseShader(self.mShaderOverride)
708  self.mShaderOverride = None
709 
710  def setRenderTargets(self, targets):
711  self.mTargets = targets
712 
713  def targetOverrideList(self):
714  if not self.mTargets is None:
715  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
716  return None
717 
718  # Indicate whether to enable SRGB write
719  def enableSRGBWrite(self):
720  return self.mEnableSRGBWrite
721 
722  # Sample of accessing the view to get a camera path and using that as
723  # the camera override. Other camera paths or direct matrix setting
724  def cameraOverride(self):
725  if len(self.mPanelName) > 0:
726  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
727  self.mCameraOverride.mCameraPath = view.getCamera()
728  return self.mCameraOverride
729 
730  print "\t" + self.mName + ": Query custom scene camera override -- no override set"
731  return None
732 
733  # Depending on what is required either the scene filter will return whether
734  # to draw the opaque, transparent of non-shaded (UI) items.
735  def renderFilterOverride(self):
736  return self.mSceneFilter
737 
738  # Example display mode override. In this example we override so that
739  # the scene will always be drawn in shaded mode and in bounding box
740  # mode (bounding boxes will also be drawn). This is fact not a
741  # 'regular' viewport display mode available from the viewport menus.
742  def displayModeOverride(self):
743  if self.mOverrideDisplayMode:
744  return ( omr.MSceneRender.kBoundingBox | omr.MSceneRender.kShaded )
745  return omr.MSceneRender.kNoDisplayModeOverride
746 
747  # Example Lighting mode override. In this example
748  # the override would set to draw with only selected lights.
749  def lightModeOverride(self):
750  if self.mOverrideLightingMode:
751  return omr.MSceneRender.kSelectedLights
752  return omr.MSceneRender.kNoLightingModeOverride
753 
754  # Return shadow override. For the UI pass we don't want to compute shadows.
755  def shadowEnableOverride(self):
756  if (self.mSceneFilter & omr.MSceneRender.kRenderShadedItems) == 0:
757  return False # UI doesn't need shadows
758  # For all other cases, just use whatever is currently set
759  return None
760 
761  # Example culling mode override. When enable
762  # this example would force to cull backfacing
763  # polygons.
764  def cullingOverride(self):
765  if self.mOverrideCullingMode:
766  return omr.MSceneRender.kCullBackFaces
767  return omr.MSceneRender.kNoCullingOverride
768 
769  # Per scene operation pre-render.
770  # In this example the display style for the given panel / view
771  # M3dView is set to be consistent with the draw override
772  # for the scene operation.
773  def preRender(self):
774  if self.mOverrrideM3dViewDisplayMode:
775  if len(self.mPanelName) > 0:
776  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
777  self.mPrevDisplayStyle = view.displayStyle();
778  view.setDisplayStyle( omui.M3dView.kGouraudShaded )
779 
780  # Post-render example.
781  # In this example we can debug the resource handle of the active render target
782  # after this operation. The matching for for the pre-render M3dView override
783  # also resides here to restore the M3dView state.
784  def postRender(self):
785  if self.mDebugTargetResourceHandle:
786  # Get the id's for the textures which are used as the color and
787  # depth render targets. These id's could arbitrarily change
788  # so they should not be held on to.
789  if not self.mTargets[kMyColorTarget] is None:
790  colorResourceHandle = self.mTargets[kMyColorTarget].resourceHandle()
791  print "\t - Color target resource handle = " + str(colorResourceHandle)
792 
793  if not self.mTargets[kMyDepthTarget] is None:
794  depthStencilResourceHandle = self.mTargets[kMyDepthTarget].resourceHandle()
795  print "\t - Depth target resource handle = " + str(depthStencilResourceHandle)
796 
797  if self.mOverrrideM3dViewDisplayMode:
798  if len(self.mPanelName) > 0:
799  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
800  view.setDisplayStyle( self.mPrevDisplayStyle )
801 
802  # Object type exclusions example.
803  # In this example we want to hide cameras
804  def getObjectTypeExclusions(self):
805  # Example of hiding by type.
806  return omr.MFrameContext.kExcludeCameras
807 
808  # Example scene override logic.
809  # In this example, the scene to draw can be filtered by a returned
810  # selection list. If an empty selection list is returned then we can
811  # essentially disable scene drawing. The other option coded here
812  # is to look at the current active selection list and return that.
813  # This results in only rendering what has been selected by the user
814  # If this filtering is required across more than one operation it
815  # is better to precompute these values in the setup phase of
816  # override and cache the information per operation as required.
817  def objectSetOverride(self):
818  self.mSelectionList.clear()
819 
820  # If you set this to True you can make the
821  # scene draw draw no part of the scene, only the
822  # additional UI elements
823  #
824  if self.mFilterDrawNothing:
825  return self.mSelectionList
826 
827  # Turn this on to query the active list and only
828  # use that for drawing
829  #
830  if self.mFilterDrawSelected:
831  selList = om.MGlobal.getActiveSelectionList()
832  if selList.length() > 0:
833  iter = om.MItSelectionList(selList)
834  while not iter.isDone():
835  comp = iter.getComponent()
836  self.mSelectionList.add( comp[0], comp[1] )
837  iter.next()
838 
839  if self.mSelectionList.length() > 0:
840  print "\t" + self.name() + " : Filtering render with active object list"
841  return self.mSelectionList
842 
843  return None
844 
845  # Custom clear override.
846  # Depending on whether we are drawing the "UI" or "non-UI"
847  # parts of the scene we will clear different channels.
848  # Color is never cleared since there is a separate operation
849  # to clear the background.
850  def clearOperation(self):
851  clearOp = self.mClearOperation
852  if (self.mSceneFilter & (omr.MSceneRender.kRenderOpaqueShadedItems | omr.MSceneRender.kRenderTransparentShadedItems | omr.MSceneRender.kRenderUIItems)) != 0:
853  clearOp.setClearGradient(False)
854  else:
855  # Force a gradient clear with some sample colors.
856  #
857  val1 = [ 0.0, 0.2, 0.8, 1.0 ]
858  val2 = [ 0.5, 0.4, 0.1, 1.0 ]
859  clearOp.setClearColor(val1)
860  clearOp.setClearColor2(val2)
861  clearOp.setClearGradient(True)
862 
863  clearOp.setMask(self.mClearMask)
864  return clearOp
865 
866  # Example of setting a shader override.
867  # Some variations are presented based on some member flags:
868  # - Use a stock shader or not
869  # - Attach pre and post shader instance callbacks
870  # - Use a shadow shader
871  def shaderOverride(self):
872  if self.mUseShaderOverride:
873  if self.mShaderOverride is None:
874  shaderManager = omr.MRenderer.getShaderManager()
875  if not shaderManager is None:
876  preCallBack = None
877  postCallBack = None
878  if not self.mUseStockShaderOverride:
879  if self.mUseShadowShader:
880  # This shader has parameters which can be updated
881  # by the attached pre-callback.
882  preCallBack = shaderOverrideCallbackBindLightingInfo
883  self.mShaderOverride = shaderManager.getEffectsFileShader("MayaBlinnDirectionalLightShadow", "", None, True, preCallBack, postCallBack)
884  else:
885  # Use a sample Gooch shader
886  if self.mAttachPrePostShaderCallback:
887  preCallBack = shaderOverridePreDrawCallback
888  if self.mAttachPrePostShaderCallback:
889  postCallBack = shaderOverridePostDrawCallback
890  self.mShaderOverride = shaderManager.getEffectsFileShader("Gooch", "", None, True, preCallBack, postCallBack)
891  else:
892  # Use a stock shader available from the shader manager
893  # In this case the stock Blinn shader.
894  if self.mAttachPrePostShaderCallback:
895  preCallBack = shaderOverridePreDrawCallback
896  if self.mAttachPrePostShaderCallback:
897  postCallBack = shaderOverridePostDrawCallback
898  self.mShaderOverride = shaderManager.getStockShader( omr.MShaderManager.k3dBlinnShader, preCallBack, postCallBack)
899 
900  if not self.mShaderOverride is None:
901  print "\t" + self.name() + " : Set stock shader override " + str(omr.MShaderManager.k3dBlinnShader)
902  diffColor = [0.0, 0.4, 1.0, 1.0]
903  try:
904  self.mShaderOverride.setParameter("diffuseColor", diffColor)
905  except:
906  print "Could not set diffuseColor on shader"
907 
908  return self.mShaderOverride
909 
910  # No override so return None
911  return None
912 
913  def hasUIDrawables(self):
914  return True
915 
916  # Pre UI draw
917  def addPreUIDrawables(self, drawManager, frameContext):
918  drawManager.beginDrawable()
919  drawManager.setColor( om.MColor( (0.1, 0.5, 0.95) ) )
920  drawManager.setFontSize( omr.MUIDrawManager.kSmallFontSize )
921  drawManager.text( om.MPoint( -2, 2, -2 ), "Pre UI draw test in Scene operation", omr.MUIDrawManager.kRight )
922  drawManager.line( om.MPoint( -2, 0, -2 ), om.MPoint( -2, 2, -2 ) )
923  drawManager.setColor( om.MColor( (1.0, 1.0, 1.0) ) )
924  drawManager.sphere( om.MPoint( -2, 2, -2 ), 0.8, False )
925  drawManager.setColor( om.MColor( (0.1, 0.5, 0.95, 0.4) ) )
926  drawManager.sphere( om.MPoint( -2, 2, -2 ), 0.8, True )
927  drawManager.endDrawable()
928 
929  # Post UI draw
930  def addPostUIDrawables(self, drawManager, frameContext):
931  drawManager.beginDrawable()
932  drawManager.setColor( om.MColor( (0.05, 0.95, 0.34) ) )
933  drawManager.setFontSize( omr.MUIDrawManager.kSmallFontSize )
934  drawManager.text( om.MPoint( 2, 2, 2 ), "Post UI draw test in Scene operation", omr.MUIDrawManager.kLeft )
935  drawManager.line( om.MPoint( 2, 0, 2), om.MPoint( 2, 2, 2 ) )
936  drawManager.setColor( om.MColor( (1.0, 1.0, 1.0) ) )
937  drawManager.sphere( om.MPoint( 2, 2, 2 ), 0.8, False )
938  drawManager.setColor( om.MColor( (0.05, 0.95, 0.34, 0.4) ) )
939  drawManager.sphere( om.MPoint( 2, 2, 2 ), 0.8, True )
940  drawManager.endDrawable()
941 
942  def panelName(self):
943  return self.mPanelName
944 
945  def setPanelName(self, name):
946  self.mPanelName = name
947 
948  def viewRectangle(self):
949  return self.mViewRectangle
950 
951  def setViewRectangle(self, rect):
952  self.mViewRectangle = rect
953 
954  def colorTarget(self):
955  if not self.mTargets is None:
956  return self.mTargets[kMyColorTarget]
957  return None
958 
959  def depthTarget(self):
960  if not self.mTargets is None:
961  return self.mTargets[kMyDepthTarget]
962  return None
963 
964  def setEnableSRGBWriteFlag(self, val):
965  self.mEnableSRGBWrite = val
966 
967  def enableSRGBWriteFlag(self):
968  return self.mEnableSRGBWrite
969 
970 ###################################################################
971 ##
972 ## A very simplistic custom scene draw example which just draws
973 ## coloured bounding boxes for surface types.
974 ##
975 ## Used by the custom user operation (viewRenderUserOperation)
976 ##
977 ###################################################################
978 class MCustomSceneDraw:
979 
980  def matrixAsArray(self, matrix):
981  array = []
982  for i in range(16):
983  array.append(matrix[i])
984  return array
985 
986  ## Some simple code to draw a wireframe bounding box in OpenGL
987  def drawBounds(self, dagPath, box):
988  matrix = dagPath.inclusiveMatrix()
989  minPt = box.min
990  maxPt = box.max
991 
992  bottomLeftFront = [ minPt.x, minPt.y, minPt.z ]
993  topLeftFront = [ minPt.x, maxPt.y, minPt.z ]
994  bottomRightFront = [ maxPt.x, minPt.y, minPt.z ]
995  topRightFront = [ maxPt.x, maxPt.y, minPt.z ]
996  bottomLeftBack = [ minPt.x, minPt.y, maxPt.z ]
997  topLeftBack = [ minPt.x, maxPt.y, maxPt.z ]
998  bottomRightBack = [ maxPt.x, minPt.y, maxPt.z ]
999  topRightBack = [ maxPt.x, maxPt.y, maxPt.z ]
1000 
1001  glMatrixMode( GL_MODELVIEW )
1002  glPushMatrix()
1003  glMultMatrixd( self.matrixAsArray(matrix) )
1004 
1005  glBegin( GL_LINE_STRIP )
1006  glVertex3dv( bottomLeftFront )
1007  glVertex3dv( bottomLeftBack )
1008  glVertex3dv( topLeftBack )
1009  glVertex3dv( topLeftFront )
1010  glVertex3dv( bottomLeftFront )
1011  glVertex3dv( bottomRightFront )
1012  glVertex3dv( bottomRightBack)
1013  glVertex3dv( topRightBack )
1014  glVertex3dv( topRightFront )
1015  glVertex3dv( bottomRightFront )
1016  glEnd()
1017 
1018  glBegin( GL_LINES )
1019  glVertex3dv(bottomLeftBack)
1020  glVertex3dv(bottomRightBack)
1021 
1022  glVertex3dv(topLeftBack)
1023  glVertex3dv(topRightBack)
1024 
1025  glVertex3dv(topLeftFront)
1026  glVertex3dv(topRightFront)
1027  glEnd()
1028 
1029  glPopMatrix()
1030 
1031  ## Draw a scene full of bounding boxes
1032  def draw(self, cameraPath, size):
1033  if not cameraPath.isValid:
1034  return False
1035 
1036  """
1037  MDrawTraversal *trav = NULL;
1038  trav = new MSurfaceDrawTraversal;
1039 
1040  if (!trav)
1041  return false;
1042 
1043  trav->enableFiltering( true );
1044  trav->setFrustum( cameraPath, width, height );
1045  if (!trav->frustumValid())
1046  {
1047  delete trav; trav = NULL;
1048  return false;
1049  }
1050  trav->traverse();
1051 
1052  unsigned int numItems = trav->numberOfItems();
1053  unsigned int i;
1054  for (i=0; i<numItems; i++)
1055  {
1056  MDagPath path;
1057  trav->itemPath(i, path);
1058 
1059  if (path.isValid())
1060  {
1061  bool drawIt = false;
1062 
1063  //
1064  // Draw surfaces (polys, nurbs, subdivs)
1065  //
1066  if ( path.hasFn( MFn::kMesh) ||
1067  path.hasFn( MFn::kNurbsSurface) ||
1068  path.hasFn( MFn::kSubdiv) )
1069  {
1070  drawIt = true;
1071  if (trav->itemHasStatus( i, MDrawTraversal::kActiveItem ))
1072  {
1073  gGLFT->glColor3f( 1.0f, 1.0f, 1.0f );
1074  }
1075  else if (trav->itemHasStatus( i, MDrawTraversal::kTemplateItem ))
1076  {
1077  gGLFT->glColor3f( 0.2f, 0.2f, 0.2f );
1078  }
1079  else
1080  {
1081  if (path.hasFn( MFn::kMesh ))
1082  gGLFT->glColor3f( 0.286f, 0.706f, 1.0f );
1083  else if (path.hasFn( MFn::kNurbsSurface))
1084  gGLFT->glColor3f( 0.486f, 0.306f, 1.0f );
1085  else
1086  gGLFT->glColor3f( 0.886f, 0.206f, 1.0f );
1087  }
1088  }
1089 
1090  if (drawIt)
1091  {
1092  MFnDagNode dagNode(path);
1093  MBoundingBox box = dagNode.boundingBox();
1094  drawBounds( path, box );
1095  }
1096  }
1097  }
1098 
1099  if (trav)
1100  {
1101  delete trav;
1102  trav = NULL;
1103  }
1104  """
1105  return True
1106 
1107 ###################################################################
1108 #
1109 # Custom user operation. One approach to adding a pre and
1110 # post scene operations. In this approach only 1 operation
1111 # is reused twice with local state as to when it is being
1112 # used. Another approach which may be more suitable for when
1113 # global state is changed is to create 2 instances of this
1114 # operation and keep global state on the override instead of
1115 # locally here.
1116 #
1117 # The cost of an override is very small so creating more instances
1118 # can provide a clearer and cleaner render loop logic.
1119 #
1120 class viewRenderUserOperation(omr.MUserRenderOperation):
1121  def __init__(self, name):
1122  omr.MUserRenderOperation.__init__(self, name)
1123 
1124  # 3D viewport panel name, if any
1125  self.mPanelName = ""
1126  # Camera override
1127  self.mCameraOverride = omr.MCameraOverride()
1128  # Viewport rectangle override
1129  self.mViewRectangle = om.MFloatPoint(0.0, 0.0, 1.0, 1.0) # 100 % of target size
1130  # Available targets
1131  self.mTargets = None
1132  # sRGB write flag
1133  self.fEnableSRGBWriteFlag = False
1134  # Draw an extra label
1135  self.fDrawLabel = False
1136  # Use camera override
1137  self.fUserCameraOverride = False
1138  # Draw colored bounding boxes
1139  self.fDrawBoundingBoxes = False
1140  # Debugging flags
1141  self.fDebugDrawContext = False
1142  self.fDebugLightingInfo = False
1143 
1144  def execute(self, drawContext):
1145  # Sample code to debug pass information
1146  debugPassInformation = False
1147  if debugPassInformation:
1148  passCtx = drawContext.getPassContext()
1149  passId = passCtx.passIdentifier()
1150  passSem = passCtx.passSemantics()
1151  print "viewRenderUserOperation: drawing in pass[" + str(passId) + "], semantic[" + str(passSem) + "]"
1152 
1153  # Example code to find the active override.
1154  # This is not necessary if the operations just keep a reference
1155  # to the override, but this demonstrates how this
1156  # contextual information can be extracted.
1157  #
1158  overrideName = omr.MRenderer.activeRenderOverride()
1159  overrideFunc = omr.MRenderer.findRenderOverride( overrideName )
1160 
1161  # Some sample code to debug lighting information in the MDrawContext
1162  #
1163  if self.fDebugLightingInfo:
1164  printDrawContextLightInfo( drawContext )
1165 
1166  # Some sample code to debug other MDrawContext information
1167  #
1168  if self.fDebugDrawContext:
1169  matrix = drawContext.getMatrix(omr.MFrameContext.kWorldMtx)
1170  print "World matrix is: " + str(matrix)
1171 
1172  viewDirection = drawContext.getTuple(omr.MFrameContext.kViewDirection)
1173  print "Viewdirection is: " + str(viewDirection)
1174 
1175  box = drawContext.getSceneBox()
1176  print "Screen box is: " + str(box)
1177  print "\tcenter=" + str(box.center)
1178 
1179  vpdim = drawContext.getViewportDimensions()
1180  print "Viewport dimension: " + str(vpdim)
1181 
1182  # Draw some addition things for scene draw
1183  #
1184  if len(self.mPanelName) > 0:
1185  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
1186  ## Get the current viewport and scale it relative to that
1187  ##
1188  targetSize = drawContext.getRenderTargetSize()
1189 
1190  if self.fDrawLabel:
1191  testString = "Drawing with override: "
1192  testString += overrideFunc.name()
1193  pos = om.MPoint(0.0, 0.0, 0.0)
1194  glColor3f( 1.0, 1.0, 1.0 )
1195  view.drawText( testString, pos )
1196 
1197  ## Some user drawing of scene bounding boxes
1198  ##
1199  if self.fDrawBoundingBoxes:
1200  cameraPath = view.getCamera()
1201  userDraw = MCustomSceneDraw()
1202  userDraw.draw( cameraPath, targetSize )
1203 
1204  def cameraOverride(self):
1205  if self.fUserCameraOverride:
1206  if len(self.mPanelName) > 0:
1207  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
1208  self.mCameraOverride.mCameraPath = view.getCamera()
1209  return self.mCameraOverride
1210 
1211  return None
1212 
1213  def targetOverrideList(self):
1214  if not self.mTargets is None:
1215  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
1216  return None
1217 
1218  def enableSRGBWrite(self):
1219  return self.fEnableSRGBWriteFlag
1220 
1221  def hasUIDrawables(self):
1222  return True
1223 
1224  def addUIDrawables(self, drawManager, frameContext):
1225  drawManager.beginDrawable()
1226  drawManager.setColor( om.MColor( (0.95, 0.5, 0.1) ) )
1227  drawManager.text( om.MPoint( 0, 2, 0 ), "UI draw test in user operation" )
1228  drawManager.line( om.MPoint( 0, 0, 0), om.MPoint( 0, 2, 0 ) )
1229  drawManager.setColor( om.MColor( (1.0, 1.0, 1.0) ) )
1230  drawManager.sphere( om.MPoint( 0, 2, 0 ), 0.8, False )
1231  drawManager.setColor( om.MColor( (0.95, 0.5, 0.1, 0.4) ) )
1232  drawManager.sphere( om.MPoint( 0, 2, 0 ), 0.8, True )
1233  drawManager.endDrawable()
1234 
1235  def setRenderTargets(self, targets):
1236  self.mTargets = targets
1237 
1238  def setEnableSRGBWriteFlag(self, val):
1239  self.fEnableSRGBWriteFlag = val
1240 
1241  def panelName(self):
1242  return self.mPanelName
1243 
1244  def setPanelName(self, name):
1245  self.mPanelName = name
1246 
1247  def viewRectangle(self):
1248  return self.mViewRectangle
1249 
1250  def setViewRectangle(self, rect):
1251  self.mViewRectangle = rect
1252 
1253 
1254 ###################################################################
1255 # Sample custom render override class.
1256 #
1257 # Is responsible for setting up the render loop operations and
1258 # updating resources for each frame render as well as any
1259 # rendering options.
1260 #
1261 # By default the plugin will perform a number of operations
1262 # in order to:
1263 #
1264 # 1) Draw a procedurally generated background
1265 # 2) Draw the non-UI parts of the scene using internal logic.
1266 # 3) Threshold the scene
1267 # 4) Blur the thresholded output
1268 # 5) Combine the thresholded output with the original scene (resulting
1269 # in a "glow")
1270 # 6a) Draw the UI parts of the scene using internal logic.
1271 # 6b) Perform an option custom user operation for additional UI.
1272 # 7) Draw the 2D HUD
1273 # 8) 'Present' the final output
1274 #
1275 # A number of intermediate render targets are created to hold contents
1276 # which are passed from operation to operation.
1277 #
1278 class viewRenderOverride(omr.MRenderOverride):
1279  def __init__(self, name):
1280  omr.MRenderOverride.__init__(self, name)
1281 
1282  # UI name which will show up in places
1283  # like the viewport 'Renderer' menu
1284  self.mUIName = "Sample VP2 Renderer Override"
1285 
1286  # Operation lists
1287  self.mRenderOperations = []
1288  self.mRenderOperationNames = []
1289 
1290  for i in range(kNumberOfOps):
1291  self.mRenderOperations.append(None)
1292  self.mRenderOperationNames.append("")
1293  self.mCurrentOperation = -1
1294 
1295  # Shared render target list
1296  self.mTargetOverrideNames = []
1297  self.mTargetDescriptions = []
1298  self.mTargets = []
1299  self.mTargetSupportsSRGBWrite = []
1300 
1301  for i in range(kTargetCount):
1302  self.mTargetOverrideNames.append("")
1303  self.mTargetDescriptions.append(None)
1304  self.mTargets.append(None)
1305  self.mTargetSupportsSRGBWrite.append(False)
1306 
1307  # Init target information for the override
1308  sampleCount = 1 # no multi-sampling
1309  colorFormat = omr.MRenderer.kR8G8B8A8_UNORM
1310  depthFormat = omr.MRenderer.kD24S8
1311 
1312  # There are 3 render targets used for the entire override:
1313  # 1. Color
1314  # 2. Depth
1315  # 3. Intermediate target to perform target blurs
1316  #
1317  self.mTargetOverrideNames [kMyColorTarget] = "__viewRenderOverrideCustomColorTarget__"
1318  self.mTargetDescriptions [kMyColorTarget] = omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyColorTarget], 256, 256, sampleCount, colorFormat, 0, False)
1319  self.mTargets [kMyColorTarget] = None
1320  self.mTargetSupportsSRGBWrite[kMyColorTarget] = False
1321 
1322  self.mTargetOverrideNames [kMyDepthTarget] = "__viewRenderOverrideCustomDepthTarget__"
1323  self.mTargetDescriptions [kMyDepthTarget] = omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyDepthTarget], 256, 256, sampleCount, depthFormat, 0, False)
1324  self.mTargets [kMyDepthTarget] = None
1325  self.mTargetSupportsSRGBWrite[kMyDepthTarget] = False
1326 
1327  self.mTargetOverrideNames [kMyBlurTarget] = "__viewRenderOverrideBlurTarget__"
1328  self.mTargetDescriptions [kMyBlurTarget]= omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyBlurTarget], 256, 256, sampleCount, colorFormat, 0, False)
1329  self.mTargets [kMyBlurTarget] = None
1330  self.mTargetSupportsSRGBWrite[kMyBlurTarget] = False
1331 
1332  # Set to True to split UI and non-UI draw
1333  self.mSplitUIDraw = False
1334 
1335  # For debugging
1336  self.mDebugOverride = False
1337 
1338  # Default do full effects
1339  self.mSimpleRendering = False
1340 
1341  # Override is for this panel
1342  self.mPanelName = ""
1343 
1344  def __del__(self):
1345  targetMgr = omr.MRenderer.getRenderTargetManager()
1346 
1347  # Delete any targets created
1348  for i in range(kTargetCount):
1349  self.mTargetDescriptions[i] = None
1350 
1351  if not self.mTargets[i] is None:
1352  if not targetMgr is None:
1353  targetMgr.releaseRenderTarget(self.mTargets[i])
1354  self.mTargets[i] = None
1355 
1356  self.cleanup()
1357 
1358  # Delete all the operations. This will release any
1359  # references to other resources used per operation
1360  #
1361  for i in range(kNumberOfOps):
1362  self.mRenderOperations[i] = None
1363 
1364  # Clean up callbacks
1365  #
1366  # PYAPI_TODO if (mRendererChangeCB)
1367  # PYAPI_TODO MMessage::removeCallback(mRendererChangeCB)
1368  # PYAPI_TODO if (mRenderOverrideChangeCB)
1369  # PYAPI_TODO MMessage::removeCallback(mRenderOverrideChangeCB)
1370 
1371  # Return that this plugin supports both GL and DX draw APIs
1372  def supportedDrawAPIs(self):
1373  return ( omr.MRenderer.kOpenGL | omr.MRenderer.kDirectX11 | omr.MRenderer.kOpenGLCoreProfile )
1374 
1375  # Initialize "iterator". We keep a list of operations indexed
1376  # by mCurrentOperation. Set to 0 to point to the first operation.
1377  def startOperationIterator(self):
1378  self.mCurrentOperation = 0
1379  return True
1380 
1381  # Return an operation indicated by mCurrentOperation
1382  def renderOperation(self):
1383  if self.mCurrentOperation >= 0 and self.mCurrentOperation < kNumberOfOps:
1384  while self.mRenderOperations[self.mCurrentOperation] is None:
1385  self.mCurrentOperation = self.mCurrentOperation+1
1386  if self.mCurrentOperation >= kNumberOfOps:
1387  return None
1388 
1389  if not self.mRenderOperations[self.mCurrentOperation] is None:
1390  if self.mDebugOverride:
1391  print "\t" + self.name() + "Queue render operation[" + str(self.mCurrentOperation) + "] = (" + self.mRenderOperations[self.mCurrentOperation].name() + ")"
1392  return self.mRenderOperations[self.mCurrentOperation]
1393  return None
1394 
1395  # Advance "iterator" to next operation
1396  def nextRenderOperation(self):
1397  self.mCurrentOperation = self.mCurrentOperation + 1
1398  if self.mCurrentOperation < kNumberOfOps:
1399  return True
1400  return False
1401 
1402  # Update the render targets that are required for the entire override.
1403  # References to these targets are set on the individual operations as
1404  # required so that they will send their output to the appropriate location.
1405  def updateRenderTargets(self):
1406  if self.mDebugOverride:
1407  print "\t" + self.name() + ": Set output render target overrides: color=" + self.mTargetDescriptions[kMyColorTarget].name() + ", depth=" + self.mTargetDescriptions[kMyDepthTarget].name()
1408 
1409  # Get the current output target size as specified by the
1410  # renderer. If it has changed then the targets need to be
1411  # resized to match.
1412  targetSize = omr.MRenderer.outputTargetSize()
1413  targetWidth = targetSize[0]
1414  targetHeight = targetSize[1]
1415 
1416  #if self.mTargetDescriptions[kMyColorTarget].width() != targetWidth or self.mTargetDescriptions[kMyColorTarget].height() != targetHeight:
1417  # A resize occured
1418 
1419  # Note that the render target sizes could be set to be
1420  # smaller than the size used by the renderer. In this case
1421  # a final present will generally stretch the output.
1422 
1423  # Update size value for all target descriptions kept
1424  for targetId in range(kTargetCount):
1425  self.mTargetDescriptions[targetId].setWidth( targetWidth )
1426  self.mTargetDescriptions[targetId].setHeight( targetHeight )
1427 
1428  # Keep track of whether the main color target can support sRGB write
1429  colorTargetSupportsSGRBWrite = False
1430  # Uncomment this to debug if targets support sRGB write.
1431  sDebugSRGBWrite = False
1432  # Enable to testing unordered write access
1433  testUnorderedWriteAccess = False
1434 
1435  # Either acquire a new target if it didn't exist before, resize
1436  # the current target.
1437  targetManager = omr.MRenderer.getRenderTargetManager()
1438  if not targetManager is None:
1439  if sDebugSRGBWrite:
1440  if omr.MRenderer.drawAPI() != omr.MRenderer.kOpenGL:
1441  # Sample code to scan all available targetgs for sRGB write support
1442  for i in range(omr.MRenderer.kNumberOfRasterFormats):
1443  if targetManager.formatSupportsSRGBWrite(i):
1444  print "Format " + str(i) + " supports SRGBwrite"
1445 
1446  for targetId in range(kTargetCount):
1447  # Check to see if the format supports sRGB write.
1448  # Set unordered write access flag if test enabled.
1449  supportsSRGBWrite = False
1450  if omr.MRenderer.drawAPI() != omr.MRenderer.kOpenGL:
1451  supportsSRGBWrite = targetManager.formatSupportsSRGBWrite( self.mTargetDescriptions[targetId].rasterFormat() )
1452  self.mTargetSupportsSRGBWrite[targetId] = supportsSRGBWrite
1453  self.mTargetDescriptions[targetId].setAllowsUnorderedAccess( testUnorderedWriteAccess )
1454 
1455  # Keep track of whether the main color target can support sRGB write
1456  if targetId == kMyColorTarget:
1457  colorTargetSupportsSGRBWrite = supportsSRGBWrite
1458 
1459  if sDebugSRGBWrite:
1460  if targetId == kMyColorTarget or targetId == kMyBlurTarget:
1461  print "Color target " + str(targetId) + " supports sRGB write = " + str(supportsSRGBWrite)
1462  # This would be expected to fail.
1463  if targetId == kMyDepthTarget:
1464  print "Depth target supports sRGB write = " + str(supportsSRGBWrite)
1465 
1466  # Create a new target
1467  if self.mTargets[targetId] is None:
1468  self.mTargets[targetId] = targetManager.acquireRenderTarget( self.mTargetDescriptions[targetId] )
1469 
1470  # "Update" using a description will resize as necessary
1471  else:
1472  self.mTargets[targetId].updateDescription( self.mTargetDescriptions[targetId] )
1473 
1474  if testUnorderedWriteAccess and not self.mTargets[targetId] is None:
1475  returnDesc = self.mTargets[targetId].targetDescription()
1476  self.mTargetDescriptions[targetId].setAllowsUnorderedAccess( returnDesc.allowsUnorderedAccess() )
1477  print "Acquire target[" + returnDesc.name() + "] with unordered access = " + str(returnDesc.allowsUnorderedAccess()) + ". Should fail if attempting with depth target = " + str(targetId == kMyDepthTarget)
1478 
1479  # Update the render targets on the individual operations
1480  #
1481  # Set the targets on the operations. For simplicity just
1482  # passing over the set of all targets used for the frame
1483  # to each operation.
1484  #
1485  quadOp = self.mRenderOperations[kBackgroundBlit]
1486  if not quadOp is None:
1487  quadOp.setRenderTargets(self.mTargets)
1488 
1489  sceneOp = self.mRenderOperations[kMaya3dSceneRender]
1490  if not sceneOp is None:
1491  sceneOp.setRenderTargets(self.mTargets)
1492  sceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1493 
1494  opaqueSceneOp = self.mRenderOperations[kMaya3dSceneRenderOpaque]
1495  if not opaqueSceneOp is None:
1496  opaqueSceneOp.setRenderTargets(self.mTargets)
1497  opaqueSceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1498 
1499  transparentSceneOp = self.mRenderOperations[kMaya3dSceneRenderTransparent]
1500  if not transparentSceneOp is None:
1501  transparentSceneOp.setRenderTargets(self.mTargets)
1502  transparentSceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1503 
1504  uiSceneOp = self.mRenderOperations[kMaya3dSceneRenderUI]
1505  if not uiSceneOp is None:
1506  uiSceneOp.setRenderTargets(self.mTargets)
1507  uiSceneOp.setEnableSRGBWriteFlag( False ) # Don't enable sRGB write for UI
1508 
1509  quadOp2 = self.mRenderOperations[kPostOperation1]
1510  if not quadOp2 is None:
1511  quadOp2.setRenderTargets(self.mTargets)
1512 
1513  quadOp3 = self.mRenderOperations[kPostOperation2]
1514  if not quadOp3 is None:
1515  quadOp3.setRenderTargets(self.mTargets)
1516 
1517  userOp = self.mRenderOperations[kUserOpNumber]
1518  if not userOp is None:
1519  userOp.setRenderTargets(self.mTargets)
1520  userOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite ) # Enable sRGB write for user ops
1521 
1522  presentOp = self.mRenderOperations[kPresentOp]
1523  if not presentOp is None:
1524  presentOp.setRenderTargets(self.mTargets)
1525 
1526  thresholdOp = self.mRenderOperations[kThresholdOp]
1527  if not thresholdOp is None:
1528  thresholdOp.setRenderTargets(self.mTargets)
1529 
1530  horizBlur = self.mRenderOperations[kHorizBlurOp]
1531  if not horizBlur is None:
1532  horizBlur.setRenderTargets(self.mTargets)
1533 
1534  vertBlur = self.mRenderOperations[kVertBlurOp]
1535  if not vertBlur is None:
1536  vertBlur.setRenderTargets(self.mTargets)
1537 
1538  blendOp = self.mRenderOperations[kBlendOp]
1539  if not blendOp is None:
1540  blendOp.setRenderTargets(self.mTargets)
1541 
1542  hudOp = self.mRenderOperations[kHUDBlit]
1543  if not hudOp is None:
1544  hudOp.setRenderTargets(self.mTargets)
1545 
1546  return (not self.mTargets[kMyColorTarget] is None and not self.mTargets[kMyDepthTarget] is None and not self.mTargets[kMyBlurTarget] is None)
1547 
1548  # "setup" will be called for each frame update.
1549  # Here we set up the render loop logic and allocate any necessary resources.
1550  # The render loop logic setup is done by setting up a list of
1551  # render operations which will be returned by the "iterator" calls.
1552  def setup(self, destination ):
1553  if self.mDebugOverride:
1554  print self.name() + " : Perform setup with panel [" + destination + "]"
1555 
1556  # As an example, we keep track of the active 3d viewport panel
1557  # if any exists. This information is passed to the operations
1558  # in case they require accessing the current 3d view (M3dView).
1559  self.mPanelName = destination
1560 
1561  # Track changes to the renderer and override for this viewport (nothing
1562  # will be printed unless mDebugOverride is True)
1563  # PYAPI_TODO if (!mRendererChangeCB)
1564  # PYAPI_TODO mRendererChangeCB = MUiMessage::add3dViewRendererChangedCallback(destination, sRendererChangeFunc, (void*)mDebugOverride)
1565  # PYAPI_TODO if (!mRenderOverrideChangeCB)
1566  # PYAPI_TODO mRenderOverrideChangeCB = MUiMessage::add3dViewRenderOverrideChangedCallback(destination, sRenderOverrideChangeFunc, (void*)mDebugOverride)
1567 
1568  if self.mRenderOperations[kPresentOp] is None:
1569  # Sample of a "simple" render loop.
1570  # "Simple" means a scene draw + HUD + present to viewport
1571  if self.mSimpleRendering:
1572  self.mSplitUIDraw = False
1573 
1574  self.mRenderOperations[kBackgroundBlit] = None
1575 
1576  self.mRenderOperationNames[kMaya3dSceneRender] = "__MySimpleSceneRender"
1577  sceneOp = simpleViewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRender] )
1578  self.mRenderOperations[kMaya3dSceneRender] = sceneOp
1579 
1580  # NULL out any additional opertions used for the "complex" render loop
1581  self.mRenderOperations[kMaya3dSceneRenderOpaque] = None
1582  self.mRenderOperations[kMaya3dSceneRenderTransparent] = None
1583  self.mRenderOperations[kThresholdOp] = None
1584  self.mRenderOperations[kHorizBlurOp] = None
1585  self.mRenderOperations[kVertBlurOp] = None
1586  self.mRenderOperations[kPostOperation1] = None
1587  self.mRenderOperations[kPostOperation2] = None
1588  self.mRenderOperations[kMaya3dSceneRenderUI] = None
1589  self.mRenderOperations[kUserOpNumber] = None
1590 
1591  self.mRenderOperations[kHUDBlit] = viewRenderHUDOperation()
1592  self.mRenderOperationNames[kHUDBlit] = self.mRenderOperations[kHUDBlit].name()
1593 
1594  self.mRenderOperationNames[kPresentOp] = "__MyPresentTarget"
1595  self.mRenderOperations[kPresentOp] = viewRenderPresentTarget( self.mRenderOperationNames[kPresentOp] )
1596  self.mRenderOperationNames[kPresentOp] = self.mRenderOperations[kPresentOp].name()
1597 
1598  # Sample which performs the full "complex" render loop
1599  #
1600  else:
1601  rect = om.MFloatPoint(0.0, 0.0, 1.0, 1.0)
1602 
1603  # Pre scene quad render to render a procedurally drawn background
1604  #
1605  self.mRenderOperationNames[kBackgroundBlit] = "__MyPreQuadRender"
1606  quadOp = viewRenderQuadRender( self.mRenderOperationNames[kBackgroundBlit] )
1607  quadOp.setShader( viewRenderQuadRender.kPre_MandelBrot ) # We use a shader override to render the background
1608  quadOp.setViewRectangle(rect)
1609  self.mRenderOperations[kBackgroundBlit] = quadOp
1610 
1611  # Set up scene draw operations
1612  #
1613  # This flag indicates that we wish to split up the scene draw into
1614  # opaque, transparent, and UI passes.
1615  #
1616  # If we don't split up the UI from the opaque and transparent,
1617  # the UI will have the "glow" effect applied to it. Instead
1618  # splitting up will allow the UI to draw after the "glow" effect
1619  # has been applied.
1620  #
1621  self.mSplitUIDraw = True
1622  self.mRenderOperations[kMaya3dSceneRender] = None
1623  self.mRenderOperations[kMaya3dSceneRenderOpaque] = None
1624  self.mRenderOperations[kMaya3dSceneRenderTransparent] = None
1625  self.mRenderOperations[kMaya3dSceneRenderUI] = None
1626  if self.mSplitUIDraw:
1627  # opaque
1628  sceneOp = None
1629  sDrawOpaque = True # can disable if desired
1630  if sDrawOpaque:
1631  self.mRenderOperationNames[kMaya3dSceneRenderOpaque] = "__MyStdSceneRenderOpaque"
1632  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1633  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderOpaque], omr.MSceneRender.kRenderOpaqueShadedItems, clearMask )
1634  sceneOp.setViewRectangle(rect)
1635  self.mRenderOperations[kMaya3dSceneRenderOpaque] = sceneOp
1636 
1637  # transparent, clear nothing since needs to draw on top of opaque
1638  sDrawTransparent = True # can disable if desired
1639  if sDrawTransparent:
1640  self.mRenderOperationNames[kMaya3dSceneRenderTransparent] = "__MyStdSceneRenderTransparent"
1641  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1642  if sDrawOpaque:
1643  clearMask = omr.MClearOperation.kClearNone
1644  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderTransparent], omr.MSceneRender.kRenderTransparentShadedItems, clearMask )
1645  sceneOp.setViewRectangle(rect)
1646  self.mRenderOperations[kMaya3dSceneRenderTransparent] = sceneOp
1647 
1648  # ui, don't clear depth since we need it for drawing ui correctly
1649  self.mRenderOperationNames[kMaya3dSceneRenderUI] = "__MyStdSceneRenderUI"
1650  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1651  if sDrawOpaque or sDrawTransparent:
1652  clearMask = omr.MClearOperation.kClearStencil
1653  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderUI], omr.MSceneRender.kRenderUIItems, clearMask )
1654  sceneOp.setViewRectangle(rect)
1655  self.mRenderOperations[kMaya3dSceneRenderUI] = sceneOp
1656  else:
1657  # will draw all of opaque, transparent and ui at once
1658  self.mRenderOperationNames[kMaya3dSceneRender] = "__MyStdSceneRender"
1659  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1660  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRender], omr.MSceneRender.kNoSceneFilterOverride, clearMask )
1661  sceneOp.setViewRectangle(rect)
1662  self.mRenderOperations[kMaya3dSceneRender] = sceneOp
1663 
1664  # Set up operations which will perform a threshold and a blur on the thresholded
1665  # render target. Also included is an operation to blend the non-UI scene
1666  # render target with the output of this set of operations (thresholded blurred scene)
1667  #
1668  self.mRenderOperationNames[kThresholdOp] = "__ThresholdColor"
1669  quadThreshold = viewRenderQuadRender( self.mRenderOperationNames[kThresholdOp] )
1670  quadThreshold.setShader( viewRenderQuadRender.kScene_Threshold ) # Use threshold shader
1671  quadThreshold.setViewRectangle(rect)
1672  self.mRenderOperations[kThresholdOp] = quadThreshold
1673 
1674  self.mRenderOperationNames[kHorizBlurOp] = "__HorizontalBlur"
1675  quadHBlur = viewRenderQuadRender( self.mRenderOperationNames[kHorizBlurOp] )
1676  quadHBlur.setShader( viewRenderQuadRender.kScene_BlurHoriz ) # Use horizontal blur shader
1677  quadHBlur.setViewRectangle(rect)
1678  self.mRenderOperations[kHorizBlurOp] = quadHBlur
1679 
1680  self.mRenderOperationNames[kVertBlurOp] = "__VerticalBlur"
1681  quadVBlur = viewRenderQuadRender( self.mRenderOperationNames[kVertBlurOp] )
1682  quadVBlur.setShader( viewRenderQuadRender.kScene_BlurVert ) # Use vertical blur shader
1683  quadVBlur.setViewRectangle(rect)
1684  self.mRenderOperations[kVertBlurOp] = quadVBlur
1685 
1686  self.mRenderOperationNames[kBlendOp] = "__SceneBlurBlend"
1687  quadBlend = viewRenderQuadRender( self.mRenderOperationNames[kBlendOp] )
1688  quadBlend.setShader( viewRenderQuadRender.kSceneBlur_Blend ) # Use color blend shader
1689  quadBlend.setViewRectangle(rect)
1690  self.mRenderOperations[kBlendOp] = quadBlend
1691 
1692  # Sample custom operation which will peform a custom "scene render"
1693  #
1694  self.mRenderOperationNames[kUserOpNumber] = "__MyCustomSceneRender"
1695  userOp = viewRenderUserOperation( self.mRenderOperationNames[kUserOpNumber] )
1696  userOp.setViewRectangle(rect)
1697  self.mRenderOperations[kUserOpNumber] = userOp
1698 
1699  wantPostQuadOps = False
1700 
1701  # Some sample post scene quad render operations
1702  # a. Monochrome quad render with custom shader
1703  self.mRenderOperationNames[kPostOperation1] = "__PostOperation1"
1704  quadOp2 = viewRenderQuadRender( self.mRenderOperationNames[kPostOperation1] )
1705  quadOp2.setShader( viewRenderQuadRender.kPost_EffectMonochrome )
1706  quadOp2.setViewRectangle(rect)
1707  if wantPostQuadOps:
1708  self.mRenderOperations[kPostOperation1] = quadOp2
1709  else:
1710  self.mRenderOperations[kPostOperation1] = None
1711 
1712  # b. Invert quad render with custom shader
1713  self.mRenderOperationNames[kPostOperation2] = "__PostOperation2"
1714  quadOp3 = viewRenderQuadRender( self.mRenderOperationNames[kPostOperation2] )
1715  quadOp3.setShader( viewRenderQuadRender.kPost_EffectInvert )
1716  quadOp3.setViewRectangle(rect)
1717  if wantPostQuadOps:
1718  self.mRenderOperations[kPostOperation2] = quadOp3
1719  else:
1720  self.mRenderOperations[kPostOperation2] = None
1721 
1722  # "Present" opertion which will display the target for viewports.
1723  # Operation is a no-op for batch rendering as there is no on-screen
1724  # buffer to send the result to.
1725  self.mRenderOperationNames[kPresentOp] = "__MyPresentTarget"
1726  self.mRenderOperations[kPresentOp] = viewRenderPresentTarget( self.mRenderOperationNames[kPresentOp] )
1727  self.mRenderOperationNames[kPresentOp] = self.mRenderOperations[kPresentOp].name()
1728 
1729  # A preset 2D HUD render operation
1730  self.mRenderOperations[kHUDBlit] = viewRenderHUDOperation()
1731  self.mRenderOperationNames[kHUDBlit] = self.mRenderOperations[kHUDBlit].name()
1732 
1733  gotTargets = True
1734  if not self.mSimpleRendering:
1735  # Update any of the render targets which will be required
1736  gotTargets = self.updateRenderTargets()
1737 
1738  # Set the name of the panel on operations which may use the panel
1739  # name to find out the associated M3dView.
1740  if not self.mRenderOperations[kMaya3dSceneRender] is None:
1741  self.mRenderOperations[kMaya3dSceneRender].setPanelName( self.mPanelName )
1742  if not self.mRenderOperations[kMaya3dSceneRenderOpaque] is None:
1743  self.mRenderOperations[kMaya3dSceneRenderOpaque].setPanelName( self.mPanelName )
1744  if not self.mRenderOperations[kMaya3dSceneRenderTransparent] is None:
1745  self.mRenderOperations[kMaya3dSceneRenderTransparent].setPanelName( self.mPanelName )
1746  if not self.mRenderOperations[kMaya3dSceneRenderUI] is None:
1747  self.mRenderOperations[kMaya3dSceneRenderUI].setPanelName( self.mPanelName )
1748  if not self.mRenderOperations[kUserOpNumber] is None:
1749  self.mRenderOperations[kUserOpNumber].setPanelName( self.mPanelName )
1750 
1751  self.mCurrentOperation = -1
1752 
1753  if not gotTargets:
1754  raise ValueError
1755 
1756  # End of frame cleanup. For now just clears out any data on operations which may
1757  # change from frame to frame (render target, output panel name etc)
1758  def cleanup(self):
1759  if self.mDebugOverride:
1760  print self.name() + " : Perform cleanup. panelname=" + self.mPanelName
1761 
1762  quadOp = self.mRenderOperations[kPostOperation1]
1763  if not quadOp is None:
1764  quadOp.setRenderTargets(None)
1765 
1766  quadOp = self.mRenderOperations[kPostOperation2]
1767  if not quadOp is None:
1768  quadOp.setRenderTargets(None)
1769 
1770  # Reset the active view
1771  self.mPanelName = ""
1772  # Reset current operation
1773  self.mCurrentOperation = -1
1774 
1775  def panelName(self):
1776  return self.mPanelName
1777 
1778  def setSimpleRendering(self, flag):
1779  self.mSimpleRendering = flag
1780 
1781  def uiName(self):
1782  return self.mUIName
1783 
1784 
1785 viewRenderOverrideInstance = None
1786 
1787 #
1788 # Register an override and associated command
1789 #
1790 def initializePlugin(obj):
1791  plugin = om.MFnPlugin(obj)
1792  try:
1793  global viewRenderOverrideInstance
1794  viewRenderOverrideInstance = viewRenderOverride( "my_viewRenderOverride" )
1795  omr.MRenderer.registerOverride(viewRenderOverrideInstance)
1796  except:
1797  sys.stderr.write("registerOverride\n")
1798  raise
1799 
1800 #
1801 # When uninitializing the plugin, make sure to deregister the
1802 # override and then delete the instance which is being kept here.
1803 #
1804 # Also remove the command used to set options on the override
1805 #
1806 def uninitializePlugin(obj):
1807  plugin = om.MFnPlugin(obj)
1808  try:
1809  global viewRenderOverrideInstance
1810  if not viewRenderOverrideInstance is None:
1811  omr.MRenderer.deregisterOverride(viewRenderOverrideInstance)
1812  viewRenderOverrideInstance = None
1813  except:
1814  sys.stderr.write("deregisterOverride\n")
1815  raise
1816