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