Python API 2.0 Reference: 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 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 ## A very simplistic custom scene draw example which just draws
984 ## coloured bounding boxes for surface types.
985 ##
986 ## Used by the custom user operation (viewRenderUserOperation)
987 ##
988 ###################################################################
989 class MCustomSceneDraw(object):
990 
991  def matrixAsArray(self, matrix):
992  array = []
993  for i in range(16):
994  array.append(matrix[i])
995  return array
996 
997  ## Some simple code to draw a wireframe bounding box in OpenGL
998  def drawBounds(self, dagPath, box):
999  matrix = dagPath.inclusiveMatrix()
1000  minPt = box.min
1001  maxPt = box.max
1002 
1003  bottomLeftFront = [ minPt.x, minPt.y, minPt.z ]
1004  topLeftFront = [ minPt.x, maxPt.y, minPt.z ]
1005  bottomRightFront = [ maxPt.x, minPt.y, minPt.z ]
1006  topRightFront = [ maxPt.x, maxPt.y, minPt.z ]
1007  bottomLeftBack = [ minPt.x, minPt.y, maxPt.z ]
1008  topLeftBack = [ minPt.x, maxPt.y, maxPt.z ]
1009  bottomRightBack = [ maxPt.x, minPt.y, maxPt.z ]
1010  topRightBack = [ maxPt.x, maxPt.y, maxPt.z ]
1011 
1012  glMatrixMode( GL_MODELVIEW )
1013  glPushMatrix()
1014  glMultMatrixd( self.matrixAsArray(matrix) )
1015 
1016  glBegin( GL_LINE_STRIP )
1017  glVertex3dv( bottomLeftFront )
1018  glVertex3dv( bottomLeftBack )
1019  glVertex3dv( topLeftBack )
1020  glVertex3dv( topLeftFront )
1021  glVertex3dv( bottomLeftFront )
1022  glVertex3dv( bottomRightFront )
1023  glVertex3dv( bottomRightBack)
1024  glVertex3dv( topRightBack )
1025  glVertex3dv( topRightFront )
1026  glVertex3dv( bottomRightFront )
1027  glEnd()
1028 
1029  glBegin( GL_LINES )
1030  glVertex3dv(bottomLeftBack)
1031  glVertex3dv(bottomRightBack)
1032 
1033  glVertex3dv(topLeftBack)
1034  glVertex3dv(topRightBack)
1035 
1036  glVertex3dv(topLeftFront)
1037  glVertex3dv(topRightFront)
1038  glEnd()
1039 
1040  glPopMatrix()
1041 
1042  ## Draw a scene full of bounding boxes
1043  def draw(self, cameraPath, size):
1044  if not cameraPath.isValid:
1045  return False
1046 
1047  """
1048  MDrawTraversal *trav = NULL;
1049  trav = new MSurfaceDrawTraversal;
1050 
1051  if (!trav)
1052  return false;
1053 
1054  trav->enableFiltering( true );
1055  trav->setFrustum( cameraPath, width, height );
1056  if (!trav->frustumValid())
1057  {
1058  delete trav; trav = NULL;
1059  return false;
1060  }
1061  trav->traverse();
1062 
1063  unsigned int numItems = trav->numberOfItems();
1064  unsigned int i;
1065  for (i=0; i<numItems; i++)
1066  {
1067  MDagPath path;
1068  trav->itemPath(i, path);
1069 
1070  if (path.isValid())
1071  {
1072  bool drawIt = false;
1073 
1074  //
1075  // Draw surfaces (polys, nurbs, subdivs)
1076  //
1077  if ( path.hasFn( MFn::kMesh) ||
1078  path.hasFn( MFn::kNurbsSurface) ||
1079  path.hasFn( MFn::kSubdiv) )
1080  {
1081  drawIt = true;
1082  if (trav->itemHasStatus( i, MDrawTraversal::kActiveItem ))
1083  {
1084  gGLFT->glColor3f( 1.0f, 1.0f, 1.0f );
1085  }
1086  else if (trav->itemHasStatus( i, MDrawTraversal::kTemplateItem ))
1087  {
1088  gGLFT->glColor3f( 0.2f, 0.2f, 0.2f );
1089  }
1090  else
1091  {
1092  if (path.hasFn( MFn::kMesh ))
1093  gGLFT->glColor3f( 0.286f, 0.706f, 1.0f );
1094  else if (path.hasFn( MFn::kNurbsSurface))
1095  gGLFT->glColor3f( 0.486f, 0.306f, 1.0f );
1096  else
1097  gGLFT->glColor3f( 0.886f, 0.206f, 1.0f );
1098  }
1099  }
1100 
1101  if (drawIt)
1102  {
1103  MFnDagNode dagNode(path);
1104  MBoundingBox box = dagNode.boundingBox();
1105  drawBounds( path, box );
1106  }
1107  }
1108  }
1109 
1110  if (trav)
1111  {
1112  delete trav;
1113  trav = NULL;
1114  }
1115  """
1116  return True
1117 
1118 ###################################################################
1119 #
1120 # Custom user operation. One approach to adding a pre and
1121 # post scene operations. In this approach only 1 operation
1122 # is reused twice with local state as to when it is being
1123 # used. Another approach which may be more suitable for when
1124 # global state is changed is to create 2 instances of this
1125 # operation and keep global state on the override instead of
1126 # locally here.
1127 #
1128 # The cost of an override is very small so creating more instances
1129 # can provide a clearer and cleaner render loop logic.
1130 #
1131 class viewRenderUserOperation(omr.MUserRenderOperation):
1132  def __init__(self, name):
1133  omr.MUserRenderOperation.__init__(self, name)
1134 
1135  # 3D viewport panel name, if any
1136  self.mPanelName = ""
1137  # Camera override
1138  self.mCameraOverride = omr.MCameraOverride()
1139  # Viewport rectangle override
1140  self.mViewRectangle = om.MFloatPoint(0.0, 0.0, 1.0, 1.0) # 100 % of target size
1141  # Available targets
1142  self.mTargets = None
1143  # sRGB write flag
1144  self.fEnableSRGBWriteFlag = False
1145  # Draw an extra label
1146  self.fDrawLabel = False
1147  # Use camera override
1148  self.fUserCameraOverride = False
1149  # Draw colored bounding boxes
1150  self.fDrawBoundingBoxes = False
1151  # Debugging flags
1152  self.fDebugDrawContext = False
1153  self.fDebugLightingInfo = False
1154 
1155  def execute(self, drawContext):
1156  # Sample code to debug pass information
1157  debugPassInformation = False
1158  if debugPassInformation:
1159  passCtx = drawContext.getPassContext()
1160  passId = passCtx.passIdentifier()
1161  passSem = passCtx.passSemantics()
1162  print("viewRenderUserOperation: drawing in pass[" + str(passId) + "], semantic[" + str(passSem) + "]")
1163 
1164  # Example code to find the active override.
1165  # This is not necessary if the operations just keep a reference
1166  # to the override, but this demonstrates how this
1167  # contextual information can be extracted.
1168  #
1169  overrideName = omr.MRenderer.activeRenderOverride()
1170  overrideFunc = omr.MRenderer.findRenderOverride( overrideName )
1171 
1172  # Some sample code to debug lighting information in the MDrawContext
1173  #
1174  if self.fDebugLightingInfo:
1175  printDrawContextLightInfo( drawContext )
1176 
1177  # Some sample code to debug other MDrawContext information
1178  #
1179  if self.fDebugDrawContext:
1180  matrix = drawContext.getMatrix(omr.MFrameContext.kWorldMtx)
1181  print("World matrix is: " + str(matrix))
1182 
1183  viewDirection = drawContext.getTuple(omr.MFrameContext.kViewDirection)
1184  print("Viewdirection is: " + str(viewDirection))
1185 
1186  box = drawContext.getSceneBox()
1187  print("Screen box is: " + str(box))
1188  print("\tcenter=" + str(box.center))
1189 
1190  vpdim = drawContext.getViewportDimensions()
1191  print("Viewport dimension: " + str(vpdim))
1192 
1193  # Draw some addition things for scene draw
1194  #
1195  if len(self.mPanelName) > 0:
1196  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
1197  ## Get the current viewport and scale it relative to that
1198  ##
1199  targetSize = drawContext.getRenderTargetSize()
1200 
1201  if self.fDrawLabel:
1202  testString = "Drawing with override: "
1203  testString += overrideFunc.name()
1204  pos = om.MPoint(0.0, 0.0, 0.0)
1205  glColor3f( 1.0, 1.0, 1.0 )
1206  view.drawText( testString, pos )
1207 
1208  ## Some user drawing of scene bounding boxes
1209  ##
1210  if self.fDrawBoundingBoxes:
1211  cameraPath = view.getCamera()
1212  userDraw = MCustomSceneDraw()
1213  userDraw.draw( cameraPath, targetSize )
1214 
1215  def cameraOverride(self):
1216  if self.fUserCameraOverride:
1217  if len(self.mPanelName) > 0:
1218  view = omui.M3dView.getM3dViewFromModelPanel(self.mPanelName)
1219  self.mCameraOverride.mCameraPath = view.getCamera()
1220  return self.mCameraOverride
1221 
1222  return None
1223 
1224  def targetOverrideList(self):
1225  if not self.mTargets is None:
1226  return [ self.mTargets[kMyColorTarget], self.mTargets[kMyDepthTarget] ]
1227  return None
1228 
1229  def enableSRGBWrite(self):
1230  return self.fEnableSRGBWriteFlag
1231 
1232  def hasUIDrawables(self):
1233  return True
1234 
1235  def addUIDrawables(self, drawManager, frameContext):
1236  drawManager.beginDrawable()
1237  drawManager.setColor( om.MColor( (0.95, 0.5, 0.1) ) )
1238  drawManager.text( om.MPoint( 0, 2, 0 ), "UI draw test in user operation" )
1239  drawManager.line( om.MPoint( 0, 0, 0), om.MPoint( 0, 2, 0 ) )
1240  drawManager.setColor( om.MColor( (1.0, 1.0, 1.0) ) )
1241  drawManager.sphere( om.MPoint( 0, 2, 0 ), 0.8, False )
1242  drawManager.setColor( om.MColor( (0.95, 0.5, 0.1, 0.4) ) )
1243  drawManager.sphere( om.MPoint( 0, 2, 0 ), 0.8, True )
1244  drawManager.endDrawable()
1245 
1246  def setRenderTargets(self, targets):
1247  self.mTargets = targets
1248 
1249  def setEnableSRGBWriteFlag(self, val):
1250  self.fEnableSRGBWriteFlag = val
1251 
1252  def panelName(self):
1253  return self.mPanelName
1254 
1255  def setPanelName(self, name):
1256  self.mPanelName = name
1257 
1258  def viewRectangle(self):
1259  return self.mViewRectangle
1260 
1261  def setViewRectangle(self, rect):
1262  self.mViewRectangle = rect
1263 
1264 
1265 ###################################################################
1266 # Sample custom render override class.
1267 #
1268 # Is responsible for setting up the render loop operations and
1269 # updating resources for each frame render as well as any
1270 # rendering options.
1271 #
1272 # By default the plugin will perform a number of operations
1273 # in order to:
1274 #
1275 # 1) Draw a procedurally generated background
1276 # 2) Draw the non-UI parts of the scene using internal logic.
1277 # 3) Threshold the scene
1278 # 4) Blur the thresholded output
1279 # 5) Combine the thresholded output with the original scene (resulting
1280 # in a "glow")
1281 # 6a) Draw the UI parts of the scene using internal logic.
1282 # 6b) Perform an option custom user operation for additional UI.
1283 # 7) Draw the 2D HUD
1284 # 8) 'Present' the final output
1285 #
1286 # A number of intermediate render targets are created to hold contents
1287 # which are passed from operation to operation.
1288 #
1289 class viewRenderOverride(omr.MRenderOverride):
1290  def __init__(self, name):
1291  omr.MRenderOverride.__init__(self, name)
1292 
1293  # UI name which will show up in places
1294  # like the viewport 'Renderer' menu
1295  self.mUIName = "Sample VP2 Renderer Override"
1296 
1297  # Operation lists
1298  self.mRenderOperations = []
1299  self.mRenderOperationNames = []
1300 
1301  for i in range(kNumberOfOps):
1302  self.mRenderOperations.append(None)
1303  self.mRenderOperationNames.append("")
1304  self.mCurrentOperation = -1
1305 
1306  # Shared render target list
1307  self.mTargetOverrideNames = []
1308  self.mTargetDescriptions = []
1309  self.mTargets = []
1310  self.mTargetSupportsSRGBWrite = []
1311 
1312  for i in range(kTargetCount):
1313  self.mTargetOverrideNames.append("")
1314  self.mTargetDescriptions.append(None)
1315  self.mTargets.append(None)
1316  self.mTargetSupportsSRGBWrite.append(False)
1317 
1318  # Init target information for the override
1319  sampleCount = 1 # no multi-sampling
1320  colorFormat = omr.MRenderer.kR8G8B8A8_UNORM
1321  depthFormat = omr.MRenderer.kD24S8
1322 
1323  # There are 3 render targets used for the entire override:
1324  # 1. Color
1325  # 2. Depth
1326  # 3. Intermediate target to perform target blurs
1327  #
1328  self.mTargetOverrideNames [kMyColorTarget] = "__viewRenderOverrideCustomColorTarget__"
1329  self.mTargetDescriptions [kMyColorTarget] = omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyColorTarget], 256, 256, sampleCount, colorFormat, 0, False)
1330  self.mTargets [kMyColorTarget] = None
1331  self.mTargetSupportsSRGBWrite[kMyColorTarget] = False
1332 
1333  self.mTargetOverrideNames [kMyDepthTarget] = "__viewRenderOverrideCustomDepthTarget__"
1334  self.mTargetDescriptions [kMyDepthTarget] = omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyDepthTarget], 256, 256, sampleCount, depthFormat, 0, False)
1335  self.mTargets [kMyDepthTarget] = None
1336  self.mTargetSupportsSRGBWrite[kMyDepthTarget] = False
1337 
1338  self.mTargetOverrideNames [kMyBlurTarget] = "__viewRenderOverrideBlurTarget__"
1339  self.mTargetDescriptions [kMyBlurTarget]= omr.MRenderTargetDescription(self.mTargetOverrideNames[kMyBlurTarget], 256, 256, sampleCount, colorFormat, 0, False)
1340  self.mTargets [kMyBlurTarget] = None
1341  self.mTargetSupportsSRGBWrite[kMyBlurTarget] = False
1342 
1343  # Set to True to split UI and non-UI draw
1344  self.mSplitUIDraw = False
1345 
1346  # For debugging
1347  self.mDebugOverride = False
1348 
1349  # Default do full effects
1350  self.mSimpleRendering = False
1351 
1352  # Override is for this panel
1353  self.mPanelName = ""
1354 
1355  def __del__(self):
1356  targetMgr = omr.MRenderer.getRenderTargetManager()
1357 
1358  # Delete any targets created
1359  for i in range(kTargetCount):
1360  self.mTargetDescriptions[i] = None
1361 
1362  if not self.mTargets[i] is None:
1363  if not targetMgr is None:
1364  targetMgr.releaseRenderTarget(self.mTargets[i])
1365  self.mTargets[i] = None
1366 
1367  self.cleanup()
1368 
1369  # Delete all the operations. This will release any
1370  # references to other resources used per operation
1371  #
1372  for i in range(kNumberOfOps):
1373  self.mRenderOperations[i] = None
1374 
1375  # Clean up callbacks
1376  #
1377  # PYAPI_TODO if (mRendererChangeCB)
1378  # PYAPI_TODO MMessage::removeCallback(mRendererChangeCB)
1379  # PYAPI_TODO if (mRenderOverrideChangeCB)
1380  # PYAPI_TODO MMessage::removeCallback(mRenderOverrideChangeCB)
1381 
1382  # Return that this plugin supports both GL and DX draw APIs
1383  def supportedDrawAPIs(self):
1384  return ( omr.MRenderer.kOpenGL | omr.MRenderer.kDirectX11 | omr.MRenderer.kOpenGLCoreProfile )
1385 
1386  # Initialize "iterator". We keep a list of operations indexed
1387  # by mCurrentOperation. Set to 0 to point to the first operation.
1388  def startOperationIterator(self):
1389  self.mCurrentOperation = 0
1390  return True
1391 
1392  # Return an operation indicated by mCurrentOperation
1393  def renderOperation(self):
1394  if self.mCurrentOperation >= 0 and self.mCurrentOperation < kNumberOfOps:
1395  while self.mRenderOperations[self.mCurrentOperation] is None:
1396  self.mCurrentOperation = self.mCurrentOperation+1
1397  if self.mCurrentOperation >= kNumberOfOps:
1398  return None
1399 
1400  if not self.mRenderOperations[self.mCurrentOperation] is None:
1401  if self.mDebugOverride:
1402  print("\t" + self.name() + "Queue render operation[" + str(self.mCurrentOperation) + "] = (" + self.mRenderOperations[self.mCurrentOperation].name() + ")")
1403  return self.mRenderOperations[self.mCurrentOperation]
1404  return None
1405 
1406  # Advance "iterator" to next operation
1407  def nextRenderOperation(self):
1408  self.mCurrentOperation = self.mCurrentOperation + 1
1409  if self.mCurrentOperation < kNumberOfOps:
1410  return True
1411  return False
1412 
1413  # Update the render targets that are required for the entire override.
1414  # References to these targets are set on the individual operations as
1415  # required so that they will send their output to the appropriate location.
1416  def updateRenderTargets(self):
1417  if self.mDebugOverride:
1418  print("\t" + self.name() + ": Set output render target overrides: color=" + self.mTargetDescriptions[kMyColorTarget].name() + ", depth=" + self.mTargetDescriptions[kMyDepthTarget].name())
1419 
1420  # Get the current output target size as specified by the
1421  # renderer. If it has changed then the targets need to be
1422  # resized to match.
1423  targetSize = omr.MRenderer.outputTargetSize()
1424  targetWidth = targetSize[0]
1425  targetHeight = targetSize[1]
1426 
1427  #if self.mTargetDescriptions[kMyColorTarget].width() != targetWidth or self.mTargetDescriptions[kMyColorTarget].height() != targetHeight:
1428  # A resize occured
1429 
1430  # Note that the render target sizes could be set to be
1431  # smaller than the size used by the renderer. In this case
1432  # a final present will generally stretch the output.
1433 
1434  # Update size value for all target descriptions kept
1435  for targetId in range(kTargetCount):
1436  self.mTargetDescriptions[targetId].setWidth( targetWidth )
1437  self.mTargetDescriptions[targetId].setHeight( targetHeight )
1438 
1439  # Keep track of whether the main color target can support sRGB write
1440  colorTargetSupportsSGRBWrite = False
1441  # Uncomment this to debug if targets support sRGB write.
1442  sDebugSRGBWrite = False
1443  # Enable to testing unordered write access
1444  testUnorderedWriteAccess = False
1445 
1446  # Either acquire a new target if it didn't exist before, resize
1447  # the current target.
1448  targetManager = omr.MRenderer.getRenderTargetManager()
1449  if not targetManager is None:
1450  if sDebugSRGBWrite:
1451  if omr.MRenderer.drawAPI() != omr.MRenderer.kOpenGL:
1452  # Sample code to scan all available targetgs for sRGB write support
1453  for i in range(omr.MRenderer.kNumberOfRasterFormats):
1454  if targetManager.formatSupportsSRGBWrite(i):
1455  print("Format " + str(i) + " supports SRGBwrite")
1456 
1457  for targetId in range(kTargetCount):
1458  # Check to see if the format supports sRGB write.
1459  # Set unordered write access flag if test enabled.
1460  supportsSRGBWrite = False
1461  if omr.MRenderer.drawAPI() != omr.MRenderer.kOpenGL:
1462  supportsSRGBWrite = targetManager.formatSupportsSRGBWrite( self.mTargetDescriptions[targetId].rasterFormat() )
1463  self.mTargetSupportsSRGBWrite[targetId] = supportsSRGBWrite
1464  self.mTargetDescriptions[targetId].setAllowsUnorderedAccess( testUnorderedWriteAccess )
1465 
1466  # Keep track of whether the main color target can support sRGB write
1467  if targetId == kMyColorTarget:
1468  colorTargetSupportsSGRBWrite = supportsSRGBWrite
1469 
1470  if sDebugSRGBWrite:
1471  if targetId == kMyColorTarget or targetId == kMyBlurTarget:
1472  print("Color target " + str(targetId) + " supports sRGB write = " + str(supportsSRGBWrite))
1473  # This would be expected to fail.
1474  if targetId == kMyDepthTarget:
1475  print("Depth target supports sRGB write = " + str(supportsSRGBWrite))
1476 
1477  # Create a new target
1478  if self.mTargets[targetId] is None:
1479  self.mTargets[targetId] = targetManager.acquireRenderTarget( self.mTargetDescriptions[targetId] )
1480 
1481  # "Update" using a description will resize as necessary
1482  else:
1483  self.mTargets[targetId].updateDescription( self.mTargetDescriptions[targetId] )
1484 
1485  if testUnorderedWriteAccess and not self.mTargets[targetId] is None:
1486  returnDesc = self.mTargets[targetId].targetDescription()
1487  self.mTargetDescriptions[targetId].setAllowsUnorderedAccess( returnDesc.allowsUnorderedAccess() )
1488  print("Acquire target[" + returnDesc.name() + "] with unordered access = " + str(returnDesc.allowsUnorderedAccess()) + ". Should fail if attempting with depth target = " + str(targetId == kMyDepthTarget))
1489 
1490  # Update the render targets on the individual operations
1491  #
1492  # Set the targets on the operations. For simplicity just
1493  # passing over the set of all targets used for the frame
1494  # to each operation.
1495  #
1496  quadOp = self.mRenderOperations[kBackgroundBlit]
1497  if not quadOp is None:
1498  quadOp.setRenderTargets(self.mTargets)
1499 
1500  sceneOp = self.mRenderOperations[kMaya3dSceneRender]
1501  if not sceneOp is None:
1502  sceneOp.setRenderTargets(self.mTargets)
1503  sceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1504 
1505  opaqueSceneOp = self.mRenderOperations[kMaya3dSceneRenderOpaque]
1506  if not opaqueSceneOp is None:
1507  opaqueSceneOp.setRenderTargets(self.mTargets)
1508  opaqueSceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1509 
1510  transparentSceneOp = self.mRenderOperations[kMaya3dSceneRenderTransparent]
1511  if not transparentSceneOp is None:
1512  transparentSceneOp.setRenderTargets(self.mTargets)
1513  transparentSceneOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite )
1514 
1515  uiSceneOp = self.mRenderOperations[kMaya3dSceneRenderUI]
1516  if not uiSceneOp is None:
1517  uiSceneOp.setRenderTargets(self.mTargets)
1518  uiSceneOp.setEnableSRGBWriteFlag( False ) # Don't enable sRGB write for UI
1519 
1520  quadOp2 = self.mRenderOperations[kPostOperation1]
1521  if not quadOp2 is None:
1522  quadOp2.setRenderTargets(self.mTargets)
1523 
1524  quadOp3 = self.mRenderOperations[kPostOperation2]
1525  if not quadOp3 is None:
1526  quadOp3.setRenderTargets(self.mTargets)
1527 
1528  userOp = self.mRenderOperations[kUserOpNumber]
1529  if not userOp is None:
1530  userOp.setRenderTargets(self.mTargets)
1531  userOp.setEnableSRGBWriteFlag( colorTargetSupportsSGRBWrite ) # Enable sRGB write for user ops
1532 
1533  presentOp = self.mRenderOperations[kPresentOp]
1534  if not presentOp is None:
1535  presentOp.setRenderTargets(self.mTargets)
1536 
1537  thresholdOp = self.mRenderOperations[kThresholdOp]
1538  if not thresholdOp is None:
1539  thresholdOp.setRenderTargets(self.mTargets)
1540 
1541  horizBlur = self.mRenderOperations[kHorizBlurOp]
1542  if not horizBlur is None:
1543  horizBlur.setRenderTargets(self.mTargets)
1544 
1545  vertBlur = self.mRenderOperations[kVertBlurOp]
1546  if not vertBlur is None:
1547  vertBlur.setRenderTargets(self.mTargets)
1548 
1549  blendOp = self.mRenderOperations[kBlendOp]
1550  if not blendOp is None:
1551  blendOp.setRenderTargets(self.mTargets)
1552 
1553  hudOp = self.mRenderOperations[kHUDBlit]
1554  if not hudOp is None:
1555  hudOp.setRenderTargets(self.mTargets)
1556 
1557  return (not self.mTargets[kMyColorTarget] is None and not self.mTargets[kMyDepthTarget] is None and not self.mTargets[kMyBlurTarget] is None)
1558 
1559  # "setup" will be called for each frame update.
1560  # Here we set up the render loop logic and allocate any necessary resources.
1561  # The render loop logic setup is done by setting up a list of
1562  # render operations which will be returned by the "iterator" calls.
1563  def setup(self, destination ):
1564  if self.mDebugOverride:
1565  print(self.name() + " : Perform setup with panel [" + destination + "]")
1566 
1567  # As an example, we keep track of the active 3d viewport panel
1568  # if any exists. This information is passed to the operations
1569  # in case they require accessing the current 3d view (M3dView).
1570  self.mPanelName = destination
1571 
1572  # Track changes to the renderer and override for this viewport (nothing
1573  # will be printed unless mDebugOverride is True)
1574  # PYAPI_TODO if (!mRendererChangeCB)
1575  # PYAPI_TODO mRendererChangeCB = MUiMessage::add3dViewRendererChangedCallback(destination, sRendererChangeFunc, (void*)mDebugOverride)
1576  # PYAPI_TODO if (!mRenderOverrideChangeCB)
1577  # PYAPI_TODO mRenderOverrideChangeCB = MUiMessage::add3dViewRenderOverrideChangedCallback(destination, sRenderOverrideChangeFunc, (void*)mDebugOverride)
1578 
1579  if self.mRenderOperations[kPresentOp] is None:
1580  # Sample of a "simple" render loop.
1581  # "Simple" means a scene draw + HUD + present to viewport
1582  if self.mSimpleRendering:
1583  self.mSplitUIDraw = False
1584 
1585  self.mRenderOperations[kBackgroundBlit] = None
1586 
1587  self.mRenderOperationNames[kMaya3dSceneRender] = "__MySimpleSceneRender"
1588  sceneOp = simpleViewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRender] )
1589  self.mRenderOperations[kMaya3dSceneRender] = sceneOp
1590 
1591  # NULL out any additional opertions used for the "complex" render loop
1592  self.mRenderOperations[kMaya3dSceneRenderOpaque] = None
1593  self.mRenderOperations[kMaya3dSceneRenderTransparent] = None
1594  self.mRenderOperations[kThresholdOp] = None
1595  self.mRenderOperations[kHorizBlurOp] = None
1596  self.mRenderOperations[kVertBlurOp] = None
1597  self.mRenderOperations[kPostOperation1] = None
1598  self.mRenderOperations[kPostOperation2] = None
1599  self.mRenderOperations[kMaya3dSceneRenderUI] = None
1600  self.mRenderOperations[kUserOpNumber] = None
1601 
1602  self.mRenderOperations[kHUDBlit] = viewRenderHUDOperation()
1603  self.mRenderOperationNames[kHUDBlit] = self.mRenderOperations[kHUDBlit].name()
1604 
1605  self.mRenderOperationNames[kPresentOp] = "__MyPresentTarget"
1606  self.mRenderOperations[kPresentOp] = viewRenderPresentTarget( self.mRenderOperationNames[kPresentOp] )
1607  self.mRenderOperationNames[kPresentOp] = self.mRenderOperations[kPresentOp].name()
1608 
1609  # Sample which performs the full "complex" render loop
1610  #
1611  else:
1612  rect = om.MFloatPoint(0.0, 0.0, 1.0, 1.0)
1613 
1614  # Pre scene quad render to render a procedurally drawn background
1615  #
1616  self.mRenderOperationNames[kBackgroundBlit] = "__MyPreQuadRender"
1617  quadOp = viewRenderQuadRender( self.mRenderOperationNames[kBackgroundBlit] )
1618  quadOp.setShader( viewRenderQuadRender.kPre_MandelBrot ) # We use a shader override to render the background
1619  quadOp.setViewRectangle(rect)
1620  self.mRenderOperations[kBackgroundBlit] = quadOp
1621 
1622  # Set up scene draw operations
1623  #
1624  # This flag indicates that we wish to split up the scene draw into
1625  # opaque, transparent, and UI passes.
1626  #
1627  # If we don't split up the UI from the opaque and transparent,
1628  # the UI will have the "glow" effect applied to it. Instead
1629  # splitting up will allow the UI to draw after the "glow" effect
1630  # has been applied.
1631  #
1632  self.mSplitUIDraw = True
1633  self.mRenderOperations[kMaya3dSceneRender] = None
1634  self.mRenderOperations[kMaya3dSceneRenderOpaque] = None
1635  self.mRenderOperations[kMaya3dSceneRenderTransparent] = None
1636  self.mRenderOperations[kMaya3dSceneRenderUI] = None
1637  if self.mSplitUIDraw:
1638  # opaque
1639  sceneOp = None
1640  sDrawOpaque = True # can disable if desired
1641  if sDrawOpaque:
1642  self.mRenderOperationNames[kMaya3dSceneRenderOpaque] = "__MyStdSceneRenderOpaque"
1643  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1644  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderOpaque], omr.MSceneRender.kRenderOpaqueShadedItems, clearMask )
1645  sceneOp.setViewRectangle(rect)
1646  self.mRenderOperations[kMaya3dSceneRenderOpaque] = sceneOp
1647 
1648  # transparent, clear nothing since needs to draw on top of opaque
1649  sDrawTransparent = True # can disable if desired
1650  if sDrawTransparent:
1651  self.mRenderOperationNames[kMaya3dSceneRenderTransparent] = "__MyStdSceneRenderTransparent"
1652  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1653  if sDrawOpaque:
1654  clearMask = omr.MClearOperation.kClearNone
1655  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderTransparent], omr.MSceneRender.kRenderTransparentShadedItems, clearMask )
1656  sceneOp.setViewRectangle(rect)
1657  self.mRenderOperations[kMaya3dSceneRenderTransparent] = sceneOp
1658 
1659  # ui, don't clear depth since we need it for drawing ui correctly
1660  self.mRenderOperationNames[kMaya3dSceneRenderUI] = "__MyStdSceneRenderUI"
1661  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1662  if sDrawOpaque or sDrawTransparent:
1663  clearMask = omr.MClearOperation.kClearStencil
1664  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRenderUI], omr.MSceneRender.kRenderUIItems, clearMask )
1665  sceneOp.setViewRectangle(rect)
1666  self.mRenderOperations[kMaya3dSceneRenderUI] = sceneOp
1667  else:
1668  # will draw all of opaque, transparent and ui at once
1669  self.mRenderOperationNames[kMaya3dSceneRender] = "__MyStdSceneRender"
1670  clearMask = omr.MClearOperation.kClearDepth | omr.MClearOperation.kClearStencil
1671  sceneOp = viewRenderSceneRender( self.mRenderOperationNames[kMaya3dSceneRender], omr.MSceneRender.kNoSceneFilterOverride, clearMask )
1672  sceneOp.setViewRectangle(rect)
1673  self.mRenderOperations[kMaya3dSceneRender] = sceneOp
1674 
1675  # Set up operations which will perform a threshold and a blur on the thresholded
1676  # render target. Also included is an operation to blend the non-UI scene
1677  # render target with the output of this set of operations (thresholded blurred scene)
1678  #
1679  self.mRenderOperationNames[kThresholdOp] = "__ThresholdColor"
1680  quadThreshold = viewRenderQuadRender( self.mRenderOperationNames[kThresholdOp] )
1681  quadThreshold.setShader( viewRenderQuadRender.kScene_Threshold ) # Use threshold shader
1682  quadThreshold.setViewRectangle(rect)
1683  self.mRenderOperations[kThresholdOp] = quadThreshold
1684 
1685  self.mRenderOperationNames[kHorizBlurOp] = "__HorizontalBlur"
1686  quadHBlur = viewRenderQuadRender( self.mRenderOperationNames[kHorizBlurOp] )
1687  quadHBlur.setShader( viewRenderQuadRender.kScene_BlurHoriz ) # Use horizontal blur shader
1688  quadHBlur.setViewRectangle(rect)
1689  self.mRenderOperations[kHorizBlurOp] = quadHBlur
1690 
1691  self.mRenderOperationNames[kVertBlurOp] = "__VerticalBlur"
1692  quadVBlur = viewRenderQuadRender( self.mRenderOperationNames[kVertBlurOp] )
1693  quadVBlur.setShader( viewRenderQuadRender.kScene_BlurVert ) # Use vertical blur shader
1694  quadVBlur.setViewRectangle(rect)
1695  self.mRenderOperations[kVertBlurOp] = quadVBlur
1696 
1697  self.mRenderOperationNames[kBlendOp] = "__SceneBlurBlend"
1698  quadBlend = viewRenderQuadRender( self.mRenderOperationNames[kBlendOp] )
1699  quadBlend.setShader( viewRenderQuadRender.kSceneBlur_Blend ) # Use color blend shader
1700  quadBlend.setViewRectangle(rect)
1701  self.mRenderOperations[kBlendOp] = quadBlend
1702 
1703  # Sample custom operation which will peform a custom "scene render"
1704  #
1705  self.mRenderOperationNames[kUserOpNumber] = "__MyCustomSceneRender"
1706  userOp = viewRenderUserOperation( self.mRenderOperationNames[kUserOpNumber] )
1707  userOp.setViewRectangle(rect)
1708  self.mRenderOperations[kUserOpNumber] = userOp
1709 
1710  wantPostQuadOps = False
1711 
1712  # Some sample post scene quad render operations
1713  # a. Monochrome quad render with custom shader
1714  self.mRenderOperationNames[kPostOperation1] = "__PostOperation1"
1715  quadOp2 = viewRenderQuadRender( self.mRenderOperationNames[kPostOperation1] )
1716  quadOp2.setShader( viewRenderQuadRender.kPost_EffectMonochrome )
1717  quadOp2.setViewRectangle(rect)
1718  if wantPostQuadOps:
1719  self.mRenderOperations[kPostOperation1] = quadOp2
1720  else:
1721  self.mRenderOperations[kPostOperation1] = None
1722 
1723  # b. Invert quad render with custom shader
1724  self.mRenderOperationNames[kPostOperation2] = "__PostOperation2"
1725  quadOp3 = viewRenderQuadRender( self.mRenderOperationNames[kPostOperation2] )
1726  quadOp3.setShader( viewRenderQuadRender.kPost_EffectInvert )
1727  quadOp3.setViewRectangle(rect)
1728  if wantPostQuadOps:
1729  self.mRenderOperations[kPostOperation2] = quadOp3
1730  else:
1731  self.mRenderOperations[kPostOperation2] = None
1732 
1733  # "Present" opertion which will display the target for viewports.
1734  # Operation is a no-op for batch rendering as there is no on-screen
1735  # buffer to send the result to.
1736  self.mRenderOperationNames[kPresentOp] = "__MyPresentTarget"
1737  self.mRenderOperations[kPresentOp] = viewRenderPresentTarget( self.mRenderOperationNames[kPresentOp] )
1738  self.mRenderOperationNames[kPresentOp] = self.mRenderOperations[kPresentOp].name()
1739 
1740  # A preset 2D HUD render operation
1741  self.mRenderOperations[kHUDBlit] = viewRenderHUDOperation()
1742  self.mRenderOperationNames[kHUDBlit] = self.mRenderOperations[kHUDBlit].name()
1743 
1744  gotTargets = True
1745  if not self.mSimpleRendering:
1746  # Update any of the render targets which will be required
1747  gotTargets = self.updateRenderTargets()
1748 
1749  # Set the name of the panel on operations which may use the panel
1750  # name to find out the associated M3dView.
1751  if not self.mRenderOperations[kMaya3dSceneRender] is None:
1752  self.mRenderOperations[kMaya3dSceneRender].setPanelName( self.mPanelName )
1753  if not self.mRenderOperations[kMaya3dSceneRenderOpaque] is None:
1754  self.mRenderOperations[kMaya3dSceneRenderOpaque].setPanelName( self.mPanelName )
1755  if not self.mRenderOperations[kMaya3dSceneRenderTransparent] is None:
1756  self.mRenderOperations[kMaya3dSceneRenderTransparent].setPanelName( self.mPanelName )
1757  if not self.mRenderOperations[kMaya3dSceneRenderUI] is None:
1758  self.mRenderOperations[kMaya3dSceneRenderUI].setPanelName( self.mPanelName )
1759  if not self.mRenderOperations[kUserOpNumber] is None:
1760  self.mRenderOperations[kUserOpNumber].setPanelName( self.mPanelName )
1761 
1762  self.mCurrentOperation = -1
1763 
1764  if not gotTargets:
1765  raise ValueError
1766 
1767  # End of frame cleanup. For now just clears out any data on operations which may
1768  # change from frame to frame (render target, output panel name etc)
1769  def cleanup(self):
1770  if self.mDebugOverride:
1771  print(self.name() + " : Perform cleanup. panelname=" + self.mPanelName)
1772 
1773  quadOp = self.mRenderOperations[kPostOperation1]
1774  if not quadOp is None:
1775  quadOp.setRenderTargets(None)
1776 
1777  quadOp = self.mRenderOperations[kPostOperation2]
1778  if not quadOp is None:
1779  quadOp.setRenderTargets(None)
1780 
1781  # Reset the active view
1782  self.mPanelName = ""
1783  # Reset current operation
1784  self.mCurrentOperation = -1
1785 
1786  def panelName(self):
1787  return self.mPanelName
1788 
1789  def setSimpleRendering(self, flag):
1790  self.mSimpleRendering = flag
1791 
1792  def uiName(self):
1793  return self.mUIName
1794 
1795 
1796 viewRenderOverrideInstance = None
1797 
1798 #
1799 # Register an override and associated command
1800 #
1801 def initializePlugin(obj):
1802  plugin = om.MFnPlugin(obj)
1803  try:
1804  global viewRenderOverrideInstance
1805  viewRenderOverrideInstance = viewRenderOverride( "my_viewRenderOverride" )
1806  omr.MRenderer.registerOverride(viewRenderOverrideInstance)
1807  except:
1808  sys.stderr.write("registerOverride\n")
1809  raise
1810 
1811 #
1812 # When uninitializing the plugin, make sure to deregister the
1813 # override and then delete the instance which is being kept here.
1814 #
1815 # Also remove the command used to set options on the override
1816 #
1817 def uninitializePlugin(obj):
1818  plugin = om.MFnPlugin(obj)
1819  try:
1820  global viewRenderOverrideInstance
1821  if not viewRenderOverrideInstance is None:
1822  omr.MRenderer.deregisterOverride(viewRenderOverrideInstance)
1823  viewRenderOverrideInstance = None
1824  except:
1825  sys.stderr.write("deregisterOverride\n")
1826  raise
1827