scripted/pyViewRenderOverride.py

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